Jekyll2023-05-26T05:26:25+00:00https://everythingshouldbevirtual.com/feed.xmlEverythingShouldBeVirtualWorld of Virtual Things, Cloudy Things, Automation and some DevOPS.Larry Smith Jr.NFD24 - DriveNets2021-03-02T09:00:00+00:002021-03-02T09:00:00+00:00https://everythingshouldbevirtual.com/NFD24-DriveNets<p>Recently I had the privilege to attend <a href="https://techfieldday.com/event/nfd24/">NFD 24</a>
in which <a href="https://drivenets.com">DriveNets</a> presented. I had never heard of them
until this event. Which I am shaming myself for because they are doing some
amazing things around transforming the network market.</p>
<p>One of the primary things that caught my attention was around what they are
doing by disaggregating network functions. This is something that I have experienced
in some capacity or another over the past few years. And when I understood what
they were doing, I was immediately interested.</p>
<p>They have two products in which I will touch on in this post. One being <a href="https://drivenets.com/products/dnos/">DNOS</a> and the other is <a href="https://drivenets.com/products/dnor/">DNOR</a>.</p>
<h2 id="dnos---drivenets-network-operating-system">DNOS - DriveNets Network Operating System</h2>
<p><a href="https://drivenets.com/products/dnos/">DNOS</a> is a fully featured networking
stack that runs on servers and white boxes. DNOS leverages many
cloud and virtualization technologies to make this a fully distributed OS running
as Docker containers in your network. DNOS separates the data plane on a cluster
of white boxes and the control plane on any environment supporting containers.
Therefore, disaggregating the data and control plane for massive scale.</p>
<h2 id="dnor---drivenets-network-orchestrator">DNOR - DriveNets Network Orchestrator</h2>
<p><a href="https://drivenets.com/products/dnor/">DNOR</a> is an orchestrator in which automates
the deployment, scaling and management of the DriveNets Cloud solution. Therefore
accelerating the deployment of cloud-native networks.</p>
<p>Because of these automated operations provided by DNOR, life-cycle management of
things such as: Zero-touch provisioning, modular software orchestration, and
scale-up and scale-down are operationalized. Providing benefits such as: shorter
maintenance windows, simplified operations, and improved reliability.</p>
<p>Another benefit of DNOR is complete visibility of your network. This means that
such things as: cluster views, availability, and performance within hardware and
software is visible. In turn, this assists in troubleshooting issues faster
and ensuring that network performance and availability are proactively monitored.</p>
<h2 id="target-audience">Target Audience</h2>
<p>From what I gathered at this point, it appears that service providers are the
target audience for DriveNets. With that being said, <a href="https://about.att.com/story/2020/open_disaggregated_core_router.html">AT&T</a> became the first in
the industry to implement DriveNets disaggregated core routing platform. This is
obviously a huge win for DriveNets, and they definitely did a great job highlighting
this during their presentation. Huge props to the DriveNets team on this for sure.</p>
<h2 id="conclusion">Conclusion</h2>
<p>Although I have only highlighted two of DriveNets products here, I plan on digging
more into their products more in depth as time permits. As I mentioned at the
start of this post, I’ve been exposed to a few implementations over the past
several years where DriveNets would have been a game changer. So, I’ll definitely
be keeping an eye on what they are doing over time.</p>
<blockquote>
<p>DISCLAIMER: I have been invited to Network Field Day Exclusive by Gestalt IT
who paid for travel, hotel, meals and transportation. I did not receive any
compensation to attend NFD and I am under no obligation whatsoever to write any
content related to NFD. The contents of these blog posts represent my personal
opinions about the products and solutions presented during NFD.</p>
</blockquote>Larry Smith Jr.Recently I had the privilege to attend NFD 24 in which DriveNets presented. I had never heard of them until this event. Which I am shaming myself for because they are doing some amazing things around transforming the network market.Ubuntu 20.04 - cloud-init Gotchas2020-08-25T22:41:00+00:002020-08-25T22:41:00+00:00https://everythingshouldbevirtual.com/Ubuntu-20.04-cloud-init-gotchas<p>Recently while working on my latest <a href="https://github.com/mrlesmithjr/packer-templates-revisited">Packer Templates</a>
I ran into an issue with Ubuntu 20.04. The issue was related to <a href="https://cloud-init.io/">cloud-init</a>
not being able to grow the root partition nor change the hostname. I was testing
this on <a href="https://www.proxmox.com/en/">Proxmox</a> using Terraform.</p>
<blockquote>
<p>NOTE: <a href="https://github.com/Telmate/terraform-provider-proxmox">terraform-provider-proxmox</a></p>
</blockquote>
<p>Obviously these are two very important capabilities when provisioning cloud
instances. So, why was this not working? Well I started Googling and of course
nothing was coming up that would give me a clue. So, I started digging into logs, etc.
And sure enough, I found in the log that these two capabilities were not working
because of the file <code class="language-plaintext highlighter-rouge">/etc/cloud/cloud.cfg.d/99-installer.cfg</code>.</p>
<p>An example of the contents of <code class="language-plaintext highlighter-rouge">/etc/cloud/cloud.cfg.d/99-installer.cfg</code>:</p>
<div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code>datasource:
None:
metadata: <span class="o">{</span>instance-id: 872e2bc0-9805-4623-bdda-5e8bcca540dc<span class="o">}</span>
userdata_raw: <span class="s2">"#cloud-config</span><span class="se">\n</span><span class="s2">growpart: {mode: 'off'}</span><span class="se">\n</span><span class="s2">locale: en_US.UTF-8</span><span class="se">\n</span><span class="s2">preserve_hostname:</span><span class="se">\</span><span class="s2">
</span><span class="se">\ </span><span class="s2">true</span><span class="se">\n</span><span class="s2">resize_rootfs: false</span><span class="se">\n</span><span class="s2">users:</span><span class="se">\n</span><span class="s2">- gecos: packer</span><span class="se">\n</span><span class="s2"> groups: [adm, cdrom,</span><span class="se">\</span><span class="s2">
</span><span class="se">\ </span><span class="s2">dip, plugdev, lxd, sudo]</span><span class="se">\n</span><span class="s2"> lock_passwd: false</span><span class="se">\n</span><span class="s2"> name: packer</span><span class="se">\n</span><span class="s2"> passwd:</span><span class="se">\</span><span class="s2">
</span><span class="se">\ </span><span class="nv">$6$AA</span><span class="s2">.Jw829.bXpJ4w</span><span class="nv">$bf2mI99OoUo2F4</span><span class="s2">/rSfnAD9vNg2vjOiJaynMSeOgZcE3PB/OMCRgYuon74mIyzgUiXBEA8/VluqEQuZBGcQq5B.</span><span class="se">\n\</span><span class="s2">
</span><span class="se">\ </span><span class="s2"> shell: /bin/bash</span><span class="se">\n</span><span class="s2">"</span>
datasource_list: <span class="o">[</span>None]
</code></pre></div></div>
<p>From the above example you can see that <code class="language-plaintext highlighter-rouge">growpart: {mode: 'off}</code> and
<code class="language-plaintext highlighter-rouge">preserve_hostname: true</code> are set. This right here was the cause of my issues.
So, to resolve this issue. Simply delete the file and you are good to go!</p>
<p>Just sharing this with folks in case you ever run into this as well.</p>
<p>Enjoy!</p>Larry Smith Jr.Recently while working on my latest Packer Templates I ran into an issue with Ubuntu 20.04. The issue was related to cloud-init not being able to grow the root partition nor change the hostname. I was testing this on Proxmox using Terraform.CFD7 - VMware TKG2020-05-05T01:00:00+00:002020-05-05T01:00:00+00:00https://everythingshouldbevirtual.com/CFD7-VMware-TKG<p>Recently I had the pleasure to attend <a href="https://techfieldday.com/event/cfd7/">#CFD7</a>
in which VMware presented <a href="https://tanzu.vmware.com/kubernetes-grid">VMware Tanzu Kubernetes Grid</a>. Our friend, <a href="https://twitter.com/kendrickcoleman">Kendrick Coleman</a> did a great job presenting TKG to us. Even squashed a few
questions/concerns along the way. Of course, not all of them were squashed but..</p>
<!-- Courtesy of embedresponsively.com //-->
<div class="responsive-video-container">
<iframe src="https://player.vimeo.com/video/411486627?dnt=true" frameborder="0" webkitallowfullscreen="" mozallowfullscreen="" allowfullscreen=""></iframe>
</div>
<blockquote>
<p>NOTE: Current version of Kubernetes supported as of #CFD7 - 1.17.3</p>
</blockquote>
<h2 id="what-is-tkg">What Is TKG</h2>
<p>Directly from the VMware TKG docs, TKG can be summed up as:</p>
<p><code class="language-plaintext highlighter-rouge">VMware Tanzu™ Kubernetes Grid™ provides organizations with a consistent, upstream-compatible, regional Kubernetes substrate across software-defined datacenters (SDDC) and public cloud environments, that is ready for end-user workloads and ecosystem integrations. Tanzu Kubernetes Grid builds on trusted upstream and community projects and delivers a Kubernetes platform that is engineered and supported by VMware, so that you do not have to build your Kubernetes environment by yourself.</code></p>
<p>TKG is the core component of Kubernetes deployments. This component applies to
all implementations. TKG uses Kubernetes to deploy Kubernetes. Ummm What? Yep,
you heard that! WOW! I can hear the comments of how complex this sounds. However,
it does sound like it. But it actually makes sense to ensure a consistent deployment
across all implementations. But, it is very complex and not for the faint at
heart. The reality is, if they never showed TKG CLI and the underlying constructs,
no one would likely question the complexity. But here we are!</p>
<p>TKG extends core Kubernetes by using a Custom Resource Definition(CRD). This CRD defines specific resources that native Kubernetes does not know about by using <a href="https://github.com/kubernetes-sigs/cluster-api">Cluster API</a>.</p>
<p><code class="language-plaintext highlighter-rouge">The Cluster API is a Kubernetes project to bring declarative, Kubernetes-style APIs to cluster creation, configuration, and management. It provides optional, additive functionality on top of core Kubernetes.</code></p>
<p><img src="../../images/2020/05/2020-05-10-16-44-12.png" alt="VMware CRD - Cluster API" /></p>
<h2 id="architecture">Architecture</h2>
<p>When it comes to the architecture of TKG, we can see that there is a lot of
bingo going on here. But hey, it takes a lot to make this work!</p>
<p><img src="../../images/2020/05/2020-05-10-16-58-44.png" alt="TKG-Architecture" /></p>
<p>Core Components:</p>
<ul>
<li>idP Auth - <a href="https://github.com/dexidp/dex">dex</a></li>
<li>Monitoring</li>
<li>Logging/Monitoring - <a href="https://fluentbit.io/">Fluentbit</a></li>
<li>Cluster Lifecycle - <a href="https://kubernetes.io/docs/reference/setup-tools/kubeadm/kubeadm/">kubeadm</a></li>
<li>Container Registry - <a href="https://goharbor.io/">Harbor</a></li>
<li>Ingress - <a href="https://projectcontour.io/">Contour</a></li>
<li>Lifecycle Management - <a href="https://github.com/kubernetes-sigs/cluster-api">Cluster API</a></li>
</ul>
<p>Additional Components:</p>
<ul>
<li>Runtime - <a href="https://containerd.io/">Containerd</a></li>
<li>Networking CNI - <a href="https://docs.projectcalico.org/getting-started/kubernetes/">Calico</a></li>
<li>Crash Diagnostics</li>
<li>Provided OVA and AMI Images</li>
</ul>
<p><img src="../../images/2020/05/2020-05-10-17-04-11.png" alt="TKG - Component Internals" /></p>
<h2 id="implementations">Implementations</h2>
<p>VMware TKG comes in three different flavors (personas):</p>
<ul>
<li><a href="https://docs.vmware.com/en/VMware-Tanzu-Kubernetes-Grid/1.0/vmware-tanzu-kubernetes-grid-10/GUID-index.html">Standalone Tanzu Kubernetes Grid</a></li>
<li><a href="https://docs.vmware.com/en/VMware-vSphere/7.0/vmware-vsphere-with-kubernetes/GUID-7E00E7C2-D1A1-4F7D-9110-620F30C02547.html">VMware Tanzu™ Kubernetes Grid™ service for vSphere</a></li>
<li><a href="https://docs.vmware.com/en/VMware-Tanzu-Mission-Control/index.html">VMware Tanzu™ Mission Control™</a></li>
</ul>
<h2 id="standalone-tanzu-kubernetes-grid">Standalone Tanzu Kubernetes Grid</h2>
<p>At the core of TKG, we get TKG CLI.</p>
<blockquote>
<p>NOTE: You can download TKG CLI from <a href="https://www.vmware.com/go/get-tkg">here</a>.</p>
</blockquote>
<p>Creating new TKG clusters is as simple (Not tested) as executing:</p>
<div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code>tkg create cluster <span class="o">[</span>name] <span class="nt">--plan</span><span class="o">=</span>production
</code></pre></div></div>
<p><img src="../../images/2020/05/2020-05-10-22-41-15.png" alt="TKG - Standalone" /></p>
<p>The following platforms are supported to deploy to:</p>
<ul>
<li>vSphere 6.7u3</li>
<li>vSphere 7.0 (see below)</li>
<li>Amazon EC2</li>
</ul>
<h3 id="vsphere-70">vSphere 7.0</h3>
<p>With vSphere 7.0, you do not need to deploy TKG management clusters if you
enabled the vSphere with Kubernetes feature. This is because you can use the TKG
CLI to connect directly to the Supervisor Cluster available when this feature
is enabled.</p>
<p>However, if the Kubernetes feature is not enabled. You can use TKG CLI to deploy
a management cluster, but it is not supported. The process to do so will be
identical to vSphere 6.7u3.</p>
<h2 id="vmware-tanzu-kubernetes-grid-service-for-vsphere">VMware Tanzu™ Kubernetes Grid™ service for vSphere</h2>
<p>TKG for vSphere was originally called Project Pacific when announced at VMworld 2019. A Tanzu Kubernetes Grid cluster, runs as virtual machines at the Supervisor
layer of vSphere. This service is enabled as a feature on vSphere 7.0 (see above).</p>
<p>TKG for vSphere makes a lot of sense for the standard vSphere admin. As it brings
the Kubernetes constructs into vCenter in traditional-ish ways. I personally
feel this will likely be where we see a lot of deployments occuring. But, we
shall see over time of course.</p>
<h2 id="vmware-tanzu-mission-control">VMware Tanzu™ Mission Control™</h2>
<p>What is Tanzu Mission Control? Well the following pretty much sums that up:</p>
<p><code class="language-plaintext highlighter-rouge">Tanzu Mission Control helps organizations to overcome the challenge of managing a fleet of Kubernetes clusters on-premises, in the cloud and from multiple vendors.</code></p>
<p><img src="../../images/2020/05/2020-05-10-22-45-15.png" alt="TKG - Mission Control" /></p>
<p>Tanzu Mission Control was under development by Heptio prior to their aquisition
by VMware.</p>
<h2 id="conclusion">Conclusion</h2>
<p>So, in conclusion here. I wanted to just quickly note some of the elements that
were touched on during the short 30 minute session we had. I’ll likely very soon
be exploring more in depth, the various TKG concepts. But until then, I’ll continue
to handle my own automated Kubernetes deployments as I’ve done for a few years now.</p>
<h2 id="follow-up">Follow UP</h2>
<p>One question I asked during the session was, how does TKG CLI function in a
CI/CD pipeline. After watching back the session, I don’t think where I was
going was very clear. So, I’ll attempt to add a bit more context here.</p>
<p>My question came from the perspective of understanding that TKG CLI can perform
a one time provisioning of a management cluster with no issues. However, if
I am managing my complete infrastructure as code. And leveraging pipelines that
continously run. I need to ensure that when a management cluster is required. I
do not attempt this on each iteration of pipeline executions. My question was
asked from an idempotent context, which made absolutely no sense :( Because after
listening back and digging into TKG more, the process follows the declarative
manner of Kubernetes already.</p>
<p>So, if I were to answer my question on where I was headed. I’d answer with,
You need to first check whether the management cluster is already available and
functional. If it is not, then provision. However, if it is already available,
skip. I know this sounds ridiculous, but for whatever reason when I listen to
things like this. I automatically jump to, how does this look from a holistic
view when doing full datacenter automation.</p>
<h2 id="additional-cfd7-resources">Additional CFD7 Resources</h2>
<ul>
<li><a href="https://www.eigenmagic.com/2020/05/11/vmware-makes-kubernetes-even-more-so-with-tanzu/">https://www.eigenmagic.com/2020/05/11/vmware-makes-kubernetes-even-more-so-with-tanzu/</a></li>
</ul>
<blockquote>
<p>DISCLAIMER: I have been invited to Cloud Field Day Exclusive by Gestalt IT who
paid for travel, hotel, meals and transportation. I did not receive any
compensation to attend CFD and I am under no obligation whatsoever to write any
content related to CFD. The contents of these blog posts represent my personal
opinions about the products and solutions presented during CFD.</p>
</blockquote>Larry Smith Jr.Recently I had the pleasure to attend #CFD7 in which VMware presented VMware Tanzu Kubernetes Grid. Our friend, Kendrick Coleman did a great job presenting TKG to us. Even squashed a few questions/concerns along the way. Of course, not all of them were squashed but..Updating Git Project Structure2020-02-20T18:00:00+00:002020-02-20T18:00:00+00:00https://everythingshouldbevirtual.com/Updating-Git-Project-Structure<p>As of late, I have been working on putting together a <a href="https://cookiecutter.readthedocs.io/">Cookiecutter</a> template to use as part of creating new <a href="https://ansible.com">Ansible</a> roles.</p>
<p>Some things I have included in <a href="https://github.com/mrlesmithjr/cookiecutter-ansible-role">cookiecutter-ansible-role</a> template include:</p>
<ul>
<li>Ansible role structure</li>
<li>CI
<ul>
<li>GitHub Actions</li>
<li>GitLab CI/CD</li>
<li>Travis</li>
</ul>
</li>
<li>Molecule Testing</li>
<li>Documentation
<ul>
<li>Code of Conduct</li>
<li>Contributing</li>
<li>License</li>
<li>Readme</li>
</ul>
</li>
</ul>
<p>I have spent a good bit of time implementing some of my best practices, etc.
which I feel are at least important to me. The ultimate goal is to leverage
Cookiecutter to easily generate a consistent structure as I create new Ansible
roles.</p>
<p>Now this sounds great for creating new Ansible roles, but what about all of the
hundreds of existing roles I have already? How will I get all of my existing
roles into this same new structure? Well that is what I will be showing here.
Exactly how I am <strong>CURRENTLY</strong> tackling this.</p>
<h2 id="example">Example</h2>
<p>In this example I will be working with my <a href="https://github.com/mrlesmithjr/ansible-control-machine.git">ansible-control-machine</a> Ansible role.</p>
<p>First thing I will do is clone the project, but I will be cloning to the <code class="language-plaintext highlighter-rouge">ansible-control-machine.orig</code> directory:</p>
<div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code>git clone git@github.com:mrlesmithjr/ansible-control-machine.git ansible-control-machine.orig
...
Cloning into <span class="s1">'ansible-control-machine.orig'</span>...
remote: Enumerating objects: 20, <span class="k">done</span><span class="nb">.</span>
remote: Counting objects: 100% <span class="o">(</span>20/20<span class="o">)</span>, <span class="k">done</span><span class="nb">.</span>
remote: Compressing objects: 100% <span class="o">(</span>15/15<span class="o">)</span>, <span class="k">done</span><span class="nb">.</span>
remote: Total 141 <span class="o">(</span>delta 8<span class="o">)</span>, reused 13 <span class="o">(</span>delta 5<span class="o">)</span>, pack-reused 121
Receiving objects: 100% <span class="o">(</span>141/141<span class="o">)</span>, 35.10 KiB | 1.67 MiB/s, <span class="k">done</span><span class="nb">.</span>
Resolving deltas: 100% <span class="o">(</span>50/50<span class="o">)</span>, <span class="k">done</span><span class="nb">.</span>
</code></pre></div></div>
<p>Let’s check real quick to see what our original structure looked like:</p>
<div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nb">ls</span> <span class="nt">-la</span> ansible-control-machine.orig
...
total 32
drwxr-xr-x 14 larrysmithjr staff 448 Feb 20 21:25 <span class="nb">.</span>
drwxr-xr-x 31 larrysmithjr staff 992 Feb 20 21:31 ..
drwxr-xr-x 12 larrysmithjr staff 384 Feb 20 21:25 .git
<span class="nt">-rw-r--r--</span> 1 larrysmithjr staff 2427 Feb 20 21:25 .travis.yml
<span class="nt">-rw-r--r--</span> 1 larrysmithjr staff 1486 Feb 20 21:25 .yamllint.yml
<span class="nt">-rw-r--r--</span> 1 larrysmithjr staff 2050 Feb 20 21:25 README.md
drwxr-xr-x 15 larrysmithjr staff 480 Feb 20 21:25 Vagrant
drwxr-xr-x 3 larrysmithjr staff 96 Feb 20 21:25 defaults
drwxr-xr-x 3 larrysmithjr staff 96 Feb 20 21:25 handlers
drwxr-xr-x 3 larrysmithjr staff 96 Feb 20 21:25 meta
<span class="nt">-rwxr-xr-x</span> 1 larrysmithjr staff 419 Feb 20 21:25 setup_travis_tests.sh
drwxr-xr-x 6 larrysmithjr staff 192 Feb 20 21:25 tasks
drwxr-xr-x 17 larrysmithjr staff 544 Feb 20 21:25 tests
drwxr-xr-x 3 larrysmithjr staff 96 Feb 20 21:25 vars
</code></pre></div></div>
<p>Next I will launch <code class="language-plaintext highlighter-rouge">cookiecutter</code> to use my <a href="https://github.com/mrlesmithjr/cookiecutter-ansible-role">cookiecutter-ansible-role</a> template to create a brand
new project called <code class="language-plaintext highlighter-rouge">ansible-control-machine</code>.</p>
<div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code>cookiecutter https://github.com/mrlesmithjr/cookiecutter-ansible-role.git
</code></pre></div></div>
<p>Following the prompts, I will fill in the details.</p>
<div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code>role_name <span class="o">[</span>Enter Ansible role name]: ansible-control-machine
description <span class="o">[</span>Enter description of Ansible role]: Ansible role to build an Ansible control machine
author <span class="o">[</span>Your Name]: Larry Smith Jr.
company <span class="o">[</span>Enter company name]:
email <span class="o">[</span>me@example.com]: mrlesmithjr@gmail.com
website <span class="o">[</span>http://example.com]: http://everythingshouldbevirtual.com
twitter <span class="o">[</span>example]: mrlesmithjr
Select license:
1 - MIT
2 - BSD-3
3 - Apache Software License 2.0
Choose from 1, 2, 3 <span class="o">[</span>1]:
min_ansible_version <span class="o">[</span>2.8]:
year <span class="o">[</span>2020]:
github_username <span class="o">[</span>Enter your GitHub username]: mrlesmithjr
travis_username <span class="o">[</span>Enter your Travis CI username]: mrlesmithjr
Select default_ci_badges:
1 - Y
2 - N
Choose from 1, 2 <span class="o">[</span>1]:
</code></pre></div></div>
<p>Now I should have a new directory called <code class="language-plaintext highlighter-rouge">ansible-control-machine</code>. So, let’s
see what the new structure looks like:</p>
<div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nb">ls</span> <span class="nt">-la</span> ansible-control-machine
...
total 96
drwxr-xr-x 24 larrysmithjr staff 768 Feb 20 21:31 <span class="nb">.</span>
drwxr-xr-x 31 larrysmithjr staff 992 Feb 20 21:31 ..
drwxr-xr-x 3 larrysmithjr staff 96 Feb 20 21:31 .github
<span class="nt">-rw-r--r--</span> 1 larrysmithjr staff 6 Feb 20 21:31 .gitignore
<span class="nt">-rw-r--r--</span> 1 larrysmithjr staff 417 Feb 20 21:31 .gitlab-ci.yml
<span class="nt">-rw-r--r--</span> 1 larrysmithjr staff 271 Feb 20 21:31 .travis.yml
<span class="nt">-rw-r--r--</span> 1 larrysmithjr staff 617 Feb 20 21:31 .yamllint
<span class="nt">-rw-r--r--</span> 1 larrysmithjr staff 3356 Feb 20 21:31 CODE_OF_CONDUCT.md
<span class="nt">-rw-r--r--</span> 1 larrysmithjr staff 400 Feb 20 21:31 CONTRIBUTING.md
<span class="nt">-rw-r--r--</span> 1 larrysmithjr staff 40 Feb 20 21:31 CONTRIBUTORS.md
<span class="nt">-rw-r--r--</span> 1 larrysmithjr staff 1072 Feb 20 21:31 LICENSE.md
<span class="nt">-rw-r--r--</span> 1 larrysmithjr staff 1037 Feb 20 21:31 README.md
drwxr-xr-x 3 larrysmithjr staff 96 Feb 20 21:31 defaults
drwxr-xr-x 3 larrysmithjr staff 96 Feb 20 21:31 files
drwxr-xr-x 3 larrysmithjr staff 96 Feb 20 21:31 handlers
drwxr-xr-x 3 larrysmithjr staff 96 Feb 20 21:31 meta
drwxr-xr-x 5 larrysmithjr staff 160 Feb 20 21:31 molecule
<span class="nt">-rw-r--r--</span> 1 larrysmithjr staff 87 Feb 20 21:31 playbook.yml
<span class="nt">-rw-r--r--</span> 1 larrysmithjr staff 37 Feb 20 21:31 requirements-dev.txt
<span class="nt">-rw-r--r--</span> 1 larrysmithjr staff 89 Feb 20 21:31 requirements.txt
<span class="nt">-rw-r--r--</span> 1 larrysmithjr staff 0 Feb 20 21:31 requirements.yml
drwxr-xr-x 3 larrysmithjr staff 96 Feb 20 21:31 tasks
drwxr-xr-x 3 larrysmithjr staff 96 Feb 20 21:31 templates
drwxr-xr-x 3 larrysmithjr staff 96 Feb 20 21:31 vars
</code></pre></div></div>
<p>As you can see, there is quite a lot more in the new structure compared to the
original.</p>
<p>Now is where the fun really begins :)</p>
<p>Let’s change into the <code class="language-plaintext highlighter-rouge">ansible-control-machine</code> directory:</p>
<div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nb">cd </span>ansible-control-machine
</code></pre></div></div>
<p>Now let’s do a quick <code class="language-plaintext highlighter-rouge">git status</code>:</p>
<div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code>git status
...
fatal: not a git repository <span class="o">(</span>or any of the parent directories<span class="o">)</span>: .git
</code></pre></div></div>
<p>Oh no! Where is my repo info? Answer is there isn’t any yet in the new structure.
Now let’s see how we can get that back into our new structure.</p>
<p>And we will do that by simply copying the <code class="language-plaintext highlighter-rouge">.git</code> directory from our original
project which will bring all of that into our new directory.</p>
<div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nb">cp</span> <span class="nt">-Rv</span> ../ansible-control-machine.orig/.git <span class="nb">.</span>
...
../ansible-control-machine.orig/.git -> ./.git
../ansible-control-machine.orig/.git/config -> ./.git/config
../ansible-control-machine.orig/.git/objects -> ./.git/objects
../ansible-control-machine.orig/.git/objects/pack -> ./.git/objects/pack
../ansible-control-machine.orig/.git/objects/pack/pack-35613ed67c65538902f0322dc253bcc6b19acd31.pack -> ./.git/objects/pack/pack-35613ed67c65538902f0322dc253bcc6b19acd31.pack
../ansible-control-machine.orig/.git/objects/pack/pack-35613ed67c65538902f0322dc253bcc6b19acd31.idx -> ./.git/objects/pack/pack-35613ed67c65538902f0322dc253bcc6b19acd31.idx
../ansible-control-machine.orig/.git/objects/info -> ./.git/objects/info
../ansible-control-machine.orig/.git/HEAD -> ./.git/HEAD
../ansible-control-machine.orig/.git/info -> ./.git/info
../ansible-control-machine.orig/.git/info/exclude -> ./.git/info/exclude
../ansible-control-machine.orig/.git/logs -> ./.git/logs
../ansible-control-machine.orig/.git/logs/HEAD -> ./.git/logs/HEAD
../ansible-control-machine.orig/.git/logs/refs -> ./.git/logs/refs
../ansible-control-machine.orig/.git/logs/refs/heads -> ./.git/logs/refs/heads
../ansible-control-machine.orig/.git/logs/refs/heads/master -> ./.git/logs/refs/heads/master
../ansible-control-machine.orig/.git/logs/refs/remotes -> ./.git/logs/refs/remotes
../ansible-control-machine.orig/.git/logs/refs/remotes/origin -> ./.git/logs/refs/remotes/origin
../ansible-control-machine.orig/.git/logs/refs/remotes/origin/HEAD -> ./.git/logs/refs/remotes/origin/HEAD
../ansible-control-machine.orig/.git/description -> ./.git/description
../ansible-control-machine.orig/.git/hooks -> ./.git/hooks
../ansible-control-machine.orig/.git/hooks/commit-msg.sample -> ./.git/hooks/commit-msg.sample
../ansible-control-machine.orig/.git/hooks/pre-rebase.sample -> ./.git/hooks/pre-rebase.sample
../ansible-control-machine.orig/.git/hooks/pre-commit.sample -> ./.git/hooks/pre-commit.sample
../ansible-control-machine.orig/.git/hooks/applypatch-msg.sample -> ./.git/hooks/applypatch-msg.sample
../ansible-control-machine.orig/.git/hooks/fsmonitor-watchman.sample -> ./.git/hooks/fsmonitor-watchman.sample
../ansible-control-machine.orig/.git/hooks/pre-receive.sample -> ./.git/hooks/pre-receive.sample
../ansible-control-machine.orig/.git/hooks/prepare-commit-msg.sample -> ./.git/hooks/prepare-commit-msg.sample
../ansible-control-machine.orig/.git/hooks/post-update.sample -> ./.git/hooks/post-update.sample
../ansible-control-machine.orig/.git/hooks/pre-merge-commit.sample -> ./.git/hooks/pre-merge-commit.sample
../ansible-control-machine.orig/.git/hooks/pre-applypatch.sample -> ./.git/hooks/pre-applypatch.sample
../ansible-control-machine.orig/.git/hooks/pre-push.sample -> ./.git/hooks/pre-push.sample
../ansible-control-machine.orig/.git/hooks/update.sample -> ./.git/hooks/update.sample
../ansible-control-machine.orig/.git/refs -> ./.git/refs
../ansible-control-machine.orig/.git/refs/heads -> ./.git/refs/heads
../ansible-control-machine.orig/.git/refs/heads/master -> ./.git/refs/heads/master
../ansible-control-machine.orig/.git/refs/tags -> ./.git/refs/tags
../ansible-control-machine.orig/.git/refs/remotes -> ./.git/refs/remotes
../ansible-control-machine.orig/.git/refs/remotes/origin -> ./.git/refs/remotes/origin
../ansible-control-machine.orig/.git/refs/remotes/origin/HEAD -> ./.git/refs/remotes/origin/HEAD
../ansible-control-machine.orig/.git/index -> ./.git/index
../ansible-control-machine.orig/.git/packed-refs -> ./.git/packed-refs
</code></pre></div></div>
<p>Once the copy is complete we can do another <code class="language-plaintext highlighter-rouge">git status</code> to see how things look
now:</p>
<div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code>git status
...
On branch master
Your branch is up to <span class="nb">date </span>with <span class="s1">'origin/master'</span><span class="nb">.</span>
Changes not staged <span class="k">for </span>commit:
<span class="o">(</span>use <span class="s2">"git add/rm <file>..."</span> to update what will be committed<span class="o">)</span>
<span class="o">(</span>use <span class="s2">"git restore <file>..."</span> to discard changes <span class="k">in </span>working directory<span class="o">)</span>
modified: .travis.yml
deleted: .yamllint.yml
modified: README.md
deleted: Vagrant/.gitignore
deleted: Vagrant/Vagrantfile
deleted: Vagrant/ansible.cfg
deleted: Vagrant/bootstrap.sh
deleted: Vagrant/bootstrap.yml
deleted: Vagrant/cleanup.bat
deleted: Vagrant/cleanup.sh
deleted: Vagrant/hosts
deleted: Vagrant/nodes.yml
deleted: Vagrant/playbook.yml
deleted: Vagrant/prep.sh
deleted: Vagrant/requirements.yml
deleted: Vagrant/roles/ansible-control-machine
modified: defaults/main.yml
modified: meta/main.yml
deleted: setup_travis_tests.sh
deleted: tasks/debian.yml
modified: tasks/main.yml
deleted: tasks/redhat.yml
deleted: tasks/setup.yml
deleted: tests/.ansible-lint
deleted: tests/Dockerfile.centos-7
deleted: tests/Dockerfile.debian-jessie
deleted: tests/Dockerfile.debian-stretch
deleted: tests/Dockerfile.fedora-24
deleted: tests/Dockerfile.fedora-25
deleted: tests/Dockerfile.fedora-26
deleted: tests/Dockerfile.fedora-27
deleted: tests/Dockerfile.fedora-28
deleted: tests/Dockerfile.fedora-29
deleted: tests/Dockerfile.ubuntu-bionic
deleted: tests/Dockerfile.ubuntu-trusty
deleted: tests/Dockerfile.ubuntu-xenial
deleted: tests/inventory
deleted: tests/test.yml
Untracked files:
<span class="o">(</span>use <span class="s2">"git add <file>..."</span> to include <span class="k">in </span>what will be committed<span class="o">)</span>
.github/workflows/default.yml
.gitignore
.gitlab-ci.yml
.yamllint
CODE_OF_CONDUCT.md
CONTRIBUTING.md
CONTRIBUTORS.md
LICENSE.md
files/.gitkeep
molecule/default/Dockerfile.j2
molecule/default/INSTALL.rst
molecule/default/molecule.yml
molecule/shared/converge.yml
molecule/shared/tests/test_default.py
molecule/vagrant/INSTALL.rst
molecule/vagrant/molecule.yml
molecule/vagrant/prepare.yml
playbook.yml
requirements-dev.txt
requirements.txt
requirements.yml
templates/.gitkeep
no changes added to commit <span class="o">(</span>use <span class="s2">"git add"</span> and/or <span class="s2">"git commit -a"</span><span class="o">)</span>
</code></pre></div></div>
<p>Well that looks better but a little bit scary right? Of course not! Now all we
need to do is decide what we want to keep and what we want to get rid of. But
before we do that, let’s create a new branch so we are not messing with <code class="language-plaintext highlighter-rouge">master</code>.
By doing this we are ensuring that we don’t mess anything up in <code class="language-plaintext highlighter-rouge">master</code> in case
we do something wrong.</p>
<p>So, let’s create a new branch called <code class="language-plaintext highlighter-rouge">updating-structure</code>:</p>
<div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code>git checkout <span class="nt">-b</span> updating-structure
...
Switched to a new branch <span class="s1">'updating-structure'</span>
</code></pre></div></div>
<p>Now that we are in our <code class="language-plaintext highlighter-rouge">updating-structure</code> branch we can start by checking out
anything marked as deleted in which we would like to keep.</p>
<div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code>git status | <span class="nb">grep </span>deleted
...
deleted: .yamllint.yml
deleted: Vagrant/.gitignore
deleted: Vagrant/Vagrantfile
deleted: Vagrant/ansible.cfg
deleted: Vagrant/bootstrap.sh
deleted: Vagrant/bootstrap.yml
deleted: Vagrant/cleanup.bat
deleted: Vagrant/cleanup.sh
deleted: Vagrant/hosts
deleted: Vagrant/nodes.yml
deleted: Vagrant/playbook.yml
deleted: Vagrant/prep.sh
deleted: Vagrant/requirements.yml
deleted: Vagrant/roles/ansible-control-machine
deleted: setup_travis_tests.sh
deleted: tasks/debian.yml
deleted: tasks/redhat.yml
deleted: tasks/setup.yml
deleted: tests/.ansible-lint
deleted: tests/Dockerfile.centos-7
deleted: tests/Dockerfile.debian-jessie
deleted: tests/Dockerfile.debian-stretch
deleted: tests/Dockerfile.fedora-24
deleted: tests/Dockerfile.fedora-25
deleted: tests/Dockerfile.fedora-26
deleted: tests/Dockerfile.fedora-27
deleted: tests/Dockerfile.fedora-28
deleted: tests/Dockerfile.fedora-29
deleted: tests/Dockerfile.ubuntu-bionic
deleted: tests/Dockerfile.ubuntu-trusty
deleted: tests/Dockerfile.ubuntu-xenial
deleted: tests/inventory
deleted: tests/test.yml
</code></pre></div></div>
<p>Because this is for an Ansible role I know that I want to keep anything in
<code class="language-plaintext highlighter-rouge">tasks</code> from the above. So I’ll checkout those to keep them.</p>
<div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code>git checkout tasks
...
Updated 4 paths from the index
</code></pre></div></div>
<p>Let’s check our <code class="language-plaintext highlighter-rouge">deleted</code> files once more to make sure we are good:</p>
<div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code>git status | <span class="nb">grep </span>deleted
...
deleted: .yamllint.yml
deleted: Vagrant/.gitignore
deleted: Vagrant/Vagrantfile
deleted: Vagrant/ansible.cfg
deleted: Vagrant/bootstrap.sh
deleted: Vagrant/bootstrap.yml
deleted: Vagrant/cleanup.bat
deleted: Vagrant/cleanup.sh
deleted: Vagrant/hosts
deleted: Vagrant/nodes.yml
deleted: Vagrant/playbook.yml
deleted: Vagrant/prep.sh
deleted: Vagrant/requirements.yml
deleted: Vagrant/roles/ansible-control-machine
deleted: setup_travis_tests.sh
deleted: tests/.ansible-lint
deleted: tests/Dockerfile.centos-7
deleted: tests/Dockerfile.debian-jessie
deleted: tests/Dockerfile.debian-stretch
deleted: tests/Dockerfile.fedora-24
deleted: tests/Dockerfile.fedora-25
deleted: tests/Dockerfile.fedora-26
deleted: tests/Dockerfile.fedora-27
deleted: tests/Dockerfile.fedora-28
deleted: tests/Dockerfile.fedora-29
deleted: tests/Dockerfile.ubuntu-bionic
deleted: tests/Dockerfile.ubuntu-trusty
deleted: tests/Dockerfile.ubuntu-xenial
deleted: tests/inventory
deleted: tests/test.yml
</code></pre></div></div>
<p>Looks good. So, now I will get rid of the <code class="language-plaintext highlighter-rouge">Vagrant</code> and <code class="language-plaintext highlighter-rouge">tests</code> directories
because I know these are for testing and I’ll be replacing these with the new
Molecule tests.</p>
<div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code>git add Vagrant/ tests/
</code></pre></div></div>
<p>And another quick <code class="language-plaintext highlighter-rouge">git status</code> shows:</p>
<div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code>On branch updating-structure
Changes to be committed:
<span class="o">(</span>use <span class="s2">"git restore --staged <file>..."</span> to unstage<span class="o">)</span>
deleted: Vagrant/.gitignore
deleted: Vagrant/Vagrantfile
deleted: Vagrant/ansible.cfg
deleted: Vagrant/bootstrap.sh
deleted: Vagrant/bootstrap.yml
deleted: Vagrant/cleanup.bat
deleted: Vagrant/cleanup.sh
deleted: Vagrant/hosts
deleted: Vagrant/nodes.yml
deleted: Vagrant/playbook.yml
deleted: Vagrant/prep.sh
deleted: Vagrant/requirements.yml
deleted: Vagrant/roles/ansible-control-machine
deleted: tests/.ansible-lint
deleted: tests/Dockerfile.centos-7
deleted: tests/Dockerfile.debian-jessie
deleted: tests/Dockerfile.debian-stretch
deleted: tests/Dockerfile.fedora-24
deleted: tests/Dockerfile.fedora-25
deleted: tests/Dockerfile.fedora-26
deleted: tests/Dockerfile.fedora-27
deleted: tests/Dockerfile.fedora-28
deleted: tests/Dockerfile.fedora-29
deleted: tests/Dockerfile.ubuntu-bionic
deleted: tests/Dockerfile.ubuntu-trusty
deleted: tests/Dockerfile.ubuntu-xenial
deleted: tests/inventory
deleted: tests/test.yml
Changes not staged <span class="k">for </span>commit:
<span class="o">(</span>use <span class="s2">"git add/rm <file>..."</span> to update what will be committed<span class="o">)</span>
<span class="o">(</span>use <span class="s2">"git restore <file>..."</span> to discard changes <span class="k">in </span>working directory<span class="o">)</span>
modified: .travis.yml
deleted: .yamllint.yml
modified: README.md
modified: defaults/main.yml
modified: meta/main.yml
deleted: setup_travis_tests.sh
Untracked files:
<span class="o">(</span>use <span class="s2">"git add <file>..."</span> to include <span class="k">in </span>what will be committed<span class="o">)</span>
.github/workflows/default.yml
.gitignore
.gitlab-ci.yml
.yamllint
CODE_OF_CONDUCT.md
CONTRIBUTING.md
CONTRIBUTORS.md
LICENSE.md
files/.gitkeep
molecule/default/Dockerfile.j2
molecule/default/INSTALL.rst
molecule/default/molecule.yml
molecule/shared/converge.yml
molecule/shared/tests/test_default.py
molecule/vagrant/INSTALL.rst
molecule/vagrant/molecule.yml
molecule/vagrant/prepare.yml
playbook.yml
requirements-dev.txt
requirements.txt
requirements.yml
templates/.gitkeep
</code></pre></div></div>
<p>I’m happy with this so I’ll now commit those changes:</p>
<div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code>git commit <span class="nt">-m</span> <span class="s2">"Deleted old tests, etc. not needed"</span>
...
<span class="o">[</span>updating-structure a117fcf] Deleted old tests, etc. not needed
28 files changed, 1202 deletions<span class="o">(</span>-<span class="o">)</span>
delete mode 100644 Vagrant/.gitignore
delete mode 100644 Vagrant/Vagrantfile
delete mode 100644 Vagrant/ansible.cfg
delete mode 100755 Vagrant/bootstrap.sh
delete mode 100644 Vagrant/bootstrap.yml
delete mode 100644 Vagrant/cleanup.bat
delete mode 100755 Vagrant/cleanup.sh
delete mode 120000 Vagrant/hosts
delete mode 100644 Vagrant/nodes.yml
delete mode 100644 Vagrant/playbook.yml
delete mode 100755 Vagrant/prep.sh
delete mode 100644 Vagrant/requirements.yml
delete mode 120000 Vagrant/roles/ansible-control-machine
delete mode 100644 tests/.ansible-lint
delete mode 100644 tests/Dockerfile.centos-7
delete mode 100644 tests/Dockerfile.debian-jessie
delete mode 100644 tests/Dockerfile.debian-stretch
delete mode 100644 tests/Dockerfile.fedora-24
delete mode 100644 tests/Dockerfile.fedora-25
delete mode 100644 tests/Dockerfile.fedora-26
delete mode 100644 tests/Dockerfile.fedora-27
delete mode 100644 tests/Dockerfile.fedora-28
delete mode 100644 tests/Dockerfile.fedora-29
delete mode 100644 tests/Dockerfile.ubuntu-bionic
delete mode 100644 tests/Dockerfile.ubuntu-trusty
delete mode 100644 tests/Dockerfile.ubuntu-xenial
delete mode 100644 tests/inventory
delete mode 100644 tests/test.yml
</code></pre></div></div>
<p>Now I can start reviewing the changes that were made to the files that are marked as <code class="language-plaintext highlighter-rouge">modified</code>. So, I’ll first check to see which files were modified:</p>
<div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code>git status | <span class="nb">grep </span>modified
...
modified: .travis.yml
modified: README.md
modified: defaults/main.yml
modified: meta/main.yml
</code></pre></div></div>
<p>As we can see there are only four files which have been modified. So, I’ll take
my time and go through each of those files with whatever editor of my choosing
to see what to keep and what to discard. I personally use VSCode for this as it
makes it really easy to discard or keep any modifications.</p>
<p>Once I am done with the modified files I’ll go ahead and add/commit those as well.</p>
<div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code>git status
...
On branch updating-structure
Changes to be committed:
<span class="o">(</span>use <span class="s2">"git restore --staged <file>..."</span> to unstage<span class="o">)</span>
modified: .travis.yml
modified: README.md
modified: meta/main.yml
Untracked files:
<span class="o">(</span>use <span class="s2">"git add <file>..."</span> to include <span class="k">in </span>what will be committed<span class="o">)</span>
.github/workflows/default.yml
.gitignore
.gitlab-ci.yml
.yamllint
CODE_OF_CONDUCT.md
CONTRIBUTING.md
CONTRIBUTORS.md
LICENSE.md
files/.gitkeep
molecule/default/Dockerfile.j2
molecule/default/INSTALL.rst
molecule/default/molecule.yml
molecule/shared/converge.yml
molecule/shared/tests/test_default.py
molecule/vagrant/INSTALL.rst
molecule/vagrant/molecule.yml
molecule/vagrant/prepare.yml
playbook.yml
requirements-dev.txt
requirements.txt
requirements.yml
templates/.gitkeep
</code></pre></div></div>
<div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code>git commit <span class="nt">-m</span> <span class="s2">"Updated files, etc. after new structure"</span>
...
3 files changed, 58 insertions<span class="o">(</span>+<span class="o">)</span>, 173 deletions<span class="o">(</span>-<span class="o">)</span>
rewrite .travis.yml <span class="o">(</span>93%<span class="o">)</span>
rewrite README.md <span class="o">(</span>87%<span class="o">)</span>
</code></pre></div></div>
<p>Then the final step is to go ahead and add the remaining <code class="language-plaintext highlighter-rouge">untracked files</code>. As
these would be new files which are part of my new desired structure and I’ll
want those to be committed as well.</p>
<p>We can add all <code class="language-plaintext highlighter-rouge">untracked files</code> by:</p>
<div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code>git add <span class="nb">.</span>
</code></pre></div></div>
<div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code>git status
...
On branch updating-structure
Changes to be committed:
<span class="o">(</span>use <span class="s2">"git restore --staged <file>..."</span> to unstage<span class="o">)</span>
new file: .github/workflows/default.yml
new file: .gitignore
new file: .gitlab-ci.yml
new file: .yamllint
new file: CODE_OF_CONDUCT.md
new file: CONTRIBUTING.md
new file: CONTRIBUTORS.md
new file: LICENSE.md
new file: files/.gitkeep
new file: molecule/default/Dockerfile.j2
new file: molecule/default/INSTALL.rst
new file: molecule/default/molecule.yml
new file: molecule/shared/converge.yml
new file: molecule/shared/tests/test_default.py
new file: molecule/vagrant/INSTALL.rst
new file: molecule/vagrant/molecule.yml
new file: molecule/vagrant/prepare.yml
new file: playbook.yml
new file: requirements-dev.txt
new file: requirements.txt
new file: requirements.yml
new file: templates/.gitkeep
</code></pre></div></div>
<p>Now we can commit these as well:</p>
<div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code>git commit <span class="nt">-m</span> <span class="s2">"New files, etc. from new structure"</span>
...
<span class="o">[</span>updating-structure 9b5a5f2] New files, etc. from new structure
22 files changed, 431 insertions<span class="o">(</span>+<span class="o">)</span>
create mode 100644 .github/workflows/default.yml
create mode 100644 .gitignore
create mode 100644 .gitlab-ci.yml
create mode 100644 .yamllint
create mode 100644 CODE_OF_CONDUCT.md
create mode 100644 CONTRIBUTING.md
create mode 100644 CONTRIBUTORS.md
create mode 100644 LICENSE.md
create mode 100644 files/.gitkeep
create mode 100644 molecule/default/Dockerfile.j2
create mode 100644 molecule/default/INSTALL.rst
create mode 100644 molecule/default/molecule.yml
create mode 100644 molecule/shared/converge.yml
create mode 100644 molecule/shared/tests/test_default.py
create mode 100644 molecule/vagrant/INSTALL.rst
create mode 100644 molecule/vagrant/molecule.yml
create mode 100644 molecule/vagrant/prepare.yml
create mode 100644 playbook.yml
create mode 100644 requirements-dev.txt
create mode 100644 requirements.txt
create mode 100644 requirements.yml
create mode 100644 templates/.gitkeep
</code></pre></div></div>
<p>Now I am all done with updating my project with a new desired structure in place
without losing anything other than what I hopefully intended. So, you can now
push those changes up to the <code class="language-plaintext highlighter-rouge">updating-structure</code> branch.</p>
<p>Let’s ensure our <code class="language-plaintext highlighter-rouge">git remote</code> is still in place before doing so:</p>
<div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code>git remote <span class="nt">-v</span>
...
origin git@github.com:mrlesmithjr/ansible-control-machine.git <span class="o">(</span>fetch<span class="o">)</span>
origin git@github.com:mrlesmithjr/ansible-control-machine.git <span class="o">(</span>push<span class="o">)</span>
</code></pre></div></div>
<p>Awesome! So we are good to go and can now push them up.</p>
<div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code>git push
...
Enumerating objects: 43, <span class="k">done</span><span class="nb">.</span>
Counting objects: 100% <span class="o">(</span>43/43<span class="o">)</span>, <span class="k">done</span><span class="nb">.</span>
Delta compression using up to 8 threads
Compressing objects: 100% <span class="o">(</span>29/29<span class="o">)</span>, <span class="k">done</span><span class="nb">.</span>
Writing objects: 100% <span class="o">(</span>38/38<span class="o">)</span>, 8.15 KiB | 2.72 MiB/s, <span class="k">done</span><span class="nb">.</span>
Total 38 <span class="o">(</span>delta 4<span class="o">)</span>, reused 0 <span class="o">(</span>delta 0<span class="o">)</span>
remote: Resolving deltas: 100% <span class="o">(</span>4/4<span class="o">)</span>, completed with 2 <span class="nb">local </span>objects.
remote:
remote: Create a pull request <span class="k">for</span> <span class="s1">'updating-structure'</span> on GitHub by visiting:
remote: https://github.com/mrlesmithjr/ansible-control-machine/pull/new/updating-structure
remote:
To github.com:mrlesmithjr/ansible-control-machine.git
<span class="k">*</span> <span class="o">[</span>new branch] updating-structure -> updating-structure
</code></pre></div></div>
<p>Once that is completed you can then start testing and resolving any issues that
you may find from any CI tests if enabled. In my case I have pushed to GitHub
and I have a GitHub Actions workflow that should kick off. Remember, this is
something I included in the Cookiecutter template.</p>
<p>And finally, once you are happy with where your new <code class="language-plaintext highlighter-rouge">updating-structure</code> branch
is. You can then create a Pull Request to get the changes merged into your
<code class="language-plaintext highlighter-rouge">master</code> branch. I want to stress once again that we have not touched our
<code class="language-plaintext highlighter-rouge">master</code> branch at all so it still has the original structure until the Pull
Request is merged.</p>
<h2 id="conclusion">Conclusion</h2>
<p>Overall, this is not too bad of an excercise to get the new structure in place.
But initially it can be quite daunting as you may be worried about causing
issues. But if you follow these steps, you should be just fine! So, there you
have it. I’d love to hear from others on how they go about these types of
scenarios and your experiences. So feel free to leave feedback.</p>
<p>Enjoy!</p>Larry Smith Jr.As of late, I have been working on putting together a Cookiecutter template to use as part of creating new Ansible roles.Manager or Leader2019-11-19T12:45:00+00:002019-11-19T12:45:00+00:00https://everythingshouldbevirtual.com/Manager-or-Leader<p>Are you a manager or leader?</p>
<p>Say what?</p>
<p>This is a subject that has been on my mind for many, many years. Some may argue
that these are the same. They are not. However, you cannot have one without the other, but they should not be viewed as the same. Some information I am about to share is purely from my perspective and likely not received well by some. This is not my intent; it is all about sparking conversation and making people think.</p>
<p>What inspired me to write this, you may ask yourself. Well, there are many different things over the past few years that have, but most recently, this Twitter post inspired me to put this into words.</p>
<blockquote class="twitter-tweet" data-partner="tweetdeck"><p lang="en" dir="ltr">IMHO, a true leader should only be visible within the team you are leading. Outside of your team however, the leader should not easily be recognized as your team should be empowered and on the same page. If the leader were to leave, that team should pick right up!</p>— Larry Smith Jr. (@mrlesmithjr) <a href="https://twitter.com/mrlesmithjr/status/1196822184783732736?ref_src=twsrc%5Etfw">November 19, 2019</a></blockquote>
<script async="" src="https://platform.twitter.com/widgets.js" charset="utf-8"></script>
<h2 id="background">Background</h2>
<p>I was raised in a military family, as many of us are. Things that my father taught me regarding this were paramount to shaping me somewhat differently than most (I believe). My father taught me to be a leader by example (as most fathers/mothers do). However, he also taught me you do not need to be in the spotlight to be a true leader. Treat all people equally, and never put yourself above others. I remember a story he once told me where he was promoted to foreman (General Motors). He initially thought it would be great but soon discovered it was not because of his peers trying to embed into him that he was now one of them and should not treat his former peers the same as he did. After about a week of this, he said he refused to do that and wanted to be the foreman no longer and would rather be with his people. My father was a leader to the utmost degree until he passed away almost five years ago. In my eyes, he is still a leader.
Another thing he taught me was to respect titles but to take them with a grain of salt. Titles should never dictate a conversation or persuade you in your decision(s). This has stuck with me throughout my life.</p>
<h2 id="my-career">My Career</h2>
<p>Throughout my career, I have been approached many times over the past ten years or so about taking on a management role. Anyone who knows me where this has been discussed, you already know what my answer was.</p>
<p>“No way in hell, not for me.”</p>
<p>So, in most cases, it was agreed that I would function in a mentor/advisory role. I have spent many years mentoring others to be empowered and have a voice. I have worked equally in this capacity with my immediate team(s) and management team(s). I am notorious for having chat sessions with others while in meetings, guiding them in what they might want to say or do based on the context of the discussion. I had somewhat of an answer if I was providing others with guidance. So, why would I not be the one to speak up and give the answer and be the leader? The answer is simple: empower those around you to make their voices heard. This builds confidence in others and empowers them. It also means that I am learning from others because they may interpret something differently in their message delivery. I feel successful by seeing others feel and be successful.</p>
<p>So, you might think this could be interpreted as the role of a manager. I disagree here, and now I will digress (maybe).</p>
<h2 id="manager-roles">Manager Roles</h2>
<p>What does a manager role mean to me?</p>
<p>Work with me here, and please do not take offense, as none is intended.</p>
<p>A manager should be the go-to person and the face of the team they represent. They do not need to be technical, and honestly, I’d prefer they not to be. They need to have their team’s back in their time of need and be the one who is put into the spotlight. I view a manager as a dictator (not in the bad sense). They are the one who dictates what is being asked to be done and ultimately should be accountable for things getting done.
In most cases, they may or may not know what needs to be done to deliver. They should also be open to the fact that their team may disagree with them and let the team decide the right course of action. I learned many years ago that your job is to make the manager look good! This translates to the fact that the guidance given to your manager should be in the best interest of everyone.</p>
<p>Remember the part where I mentioned that titles should not dictate your conversations or decisions? Yeah, this is where it is essential. It is not a means to disrespect your manager but to put them on the same level playing ground. A good manager will respect this and be willing to allow this. But they must understand it is about having their best interest and making them look good! Remember the part about feeling successful by seeing others being successful? Yeah, this is part of that.</p>
<h2 id="leader-roles">Leader Roles</h2>
<p>What does a leadership role mean to me?</p>
<p>In my opinion, a leader leads by example and does not feel the need to stand out from their peers. A leader is not the go-to person on the direction of how things are moving or the face of their team. They are, however, the ones to inspire and empower others to do great things. A leader may only be recognized by their immediate peers but outside of them, they should only be viewed as part of the team. Remember the Twitter post I linked to above? I think the leader should not stand out externally to their team. A true leader will bring those up around them, and the whole team should deliver the same message. Now, their manager may recognize who the leader is, but outside of that, no one should know. A true leaders should never be felt they belong in the spotlight. True leaders should have their whole team in the spotlight. Often true leaders may or may not even recognize that they are. If you realize it, be humble and never use it to take the upper hand. Use it in a way to empower those around you.</p>
<h2 id="conclusion">Conclusion</h2>
<p>As you can probably tell, this topic is very passionate for me. Am I right in my opinions here? Probably not, as they are just that, my opinions. However, I do believe these are great topics for discussion.</p>
<p>I also put this tweet out a week or so ago. And I truly meant it! And I also received numerous amazing messages from folks! And for anyone reading this post, feel free to reach out!</p>
<blockquote class="twitter-tweet" data-partner="tweetdeck"><p lang="en" dir="ltr">I'm at that point that my day to day work I do is no longer enjoyable without being more of a mentor. Problem is I need more willing mentees available. If you or someone you know is interested, reach out to me.</p>— Larry Smith Jr. (@mrlesmithjr) <a href="https://twitter.com/mrlesmithjr/status/1194025732017704967?ref_src=twsrc%5Etfw">November 11, 2019</a></blockquote>
<script async="" src="https://platform.twitter.com/widgets.js" charset="utf-8"></script>
<p>Enjoy!</p>Larry Smith Jr.Are you a manager or leader?CFD6 - Hashicorp2019-10-13T20:28:00+00:002019-10-13T20:28:00+00:00https://everythingshouldbevirtual.com/CFD6-Hashicorp<p>Recently while attending Cloud Field Day 6, one of the companies presenting just so happened to be Hashicorp. Now Hashicorp is one of my
personal favorite companies in the open-source world. So, to say that I
was extremely excited to hear them would be an understatement. Luckily
for us, Mitchell Hashimoto was the one who presented to all of us delegates as
I am sure everyone was excited about this.</p>
<p>Hashicorp spent a bit of time highlighting some of their products but their main focus for the presentation was around Consul. Why Consul? Because as Mitchell mentioned, networking has a huge bullseye on it’s back and cloud is coming for
you! :) Which is where Consul comes into play.</p>
<!-- Courtesy of embedresponsively.com //-->
<div class="responsive-video-container">
<iframe src="https://www.youtube-nocookie.com/embed/VML6w2Vj9Ws" frameborder="0" webkitallowfullscreen="" mozallowfullscreen="" allowfullscreen=""></iframe>
</div>
<h2 id="consul-for-service-networking">Consul For Service Networking</h2>
<!-- Courtesy of embedresponsively.com //-->
<div class="responsive-video-container">
<iframe src="https://www.youtube-nocookie.com/embed/TWthJXrDiis" frameborder="0" webkitallowfullscreen="" mozallowfullscreen="" allowfullscreen=""></iframe>
</div>
<h3 id="multi-cloud-multiple-technologies---call-me-when-you-have-a-good-idea">Multi-Cloud (Multiple Technologies) - Call Me When You Have a Good Idea</h3>
<p>In the beginning of this segment Mitchell talks about a multi-cloud conversation
he had with an analyst a few years ago and they said for him to call them back
when he had a good idea. Ummmm…Someone <strong>SHOULD</strong> have listened to him!</p>
<p>As Mitchell explains in regards to the diagram below, the technologies defined
are reality and with TCP, they can all co-exist. Makes sense obviously.
<img src="../../images/2019/10/Consul-Mixed-Technologies.png" alt="Mixed Technologies" /></p>
<p>And through organic growth in a datacenter, things begin to get complex as seen
in the diagram below.</p>
<p><img src="../../images/2019/10/Consul-Modern-Datacenter-Challenges.png" alt="Modern Datacenter Challenges" /></p>
<h3 id="what-is-consul">What Is Consul</h3>
<p><img src="../../images/2019/10/Consul-What-Is-It.png" alt="What Is Consul?" /></p>
<p>Hashicorp follows the crawl, walk, run strategy with Consul as with all of their
other products. For example, a service mesh seems like a big bang effort but
not needed initially. Service mesh functionality in Consul was added last year whereas the top two bullets have been in place four to five years. I have
leveraged Consul for the top two bullets across large-scale data centers. From an architecture perspective, the diagram below outlines a multi-data center Consul architecture. The open-source version requires full network connectivity
between data centers, whereas, the paid for version can function in
hub-spoke model.</p>
<p><img src="../../images/2019/10/Consul-Multi-DC-Architecture.png" alt="Multi-Datacenter Architecture" /></p>
<p>Consul does require an agent on hosts to handle membership, etc. But in instances where the agent may not be an option, services for hosts can be registered via
the Consul API as an external resource. When running in a container platform (Kubernetes, Docker Swarm, etc.) the agent runs on the container host not
within the container images. The real benefit for service resiliency does require
an agent to ensure the health of all nodes and services. The agent is very light
weight and is a single binary written in Go. This binary is the same for Consul
servers and Consul clients, however the argument passed determines the mode in
which the agent executes. You can find more on the Consul agent <a href="https://www.consul.io/docs/agent/basics.html">here</a>.</p>
<h2 id="consul-connect">Consul Connect</h2>
<!-- Courtesy of embedresponsively.com //-->
<div class="responsive-video-container">
<iframe src="https://www.youtube-nocookie.com/embed/JQqtoWF-0pg" frameborder="0" webkitallowfullscreen="" mozallowfullscreen="" allowfullscreen=""></iframe>
</div>
<p>Now what they really wanted to cover around Consul was what they are now calling
Consul connect. Consul connect provides secure communications between services
with TLS encryption and identity-based authorization that works anywhere (VMs,
containers, edge switches, etc.).</p>
<h3 id="consul-connect---instead-of-traditional-firewall-access-methods">Consul Connect - Instead of Traditional Firewall Access Methods</h3>
<p>One concept that Consul connect addresses is how traditional firewalls work
based on a static IP address being the identity in which access is allowed. With
Consul Connect, you can use a service identity within Consul to control access
to services.</p>
<p><img src="../../images/2019/10/Consul-Firewall-Reference.png" alt="Consul Firewall Reference" /></p>
<h3 id="consul-connect---service-access-graph">Consul Connect - Service Access Graph</h3>
<p>Because all services are known within Consul, service access graphs can be
created to allow service level access to services rather than IP based access.
Service access graphs can be created in advance prior to any services being
deployed which makes the approval process much simpler and can be in place by
the time services are deployed.</p>
<p><img src="../../images/2019/10/Consul-Service-Graph-Intentions.png" alt="Consul Service Graph Intentions" /></p>
<p>Mitchell also mentioned that Hashicorp made an announcement around <a href="https://www.hashicorp.com/blog/hashicorp-consul-enterprise-supports-vmware-nsx-service-mesh-federation">VMware NSX Service Mesh Federation</a>. I’d
definitely recommend reading about this functionality.</p>
<h3 id="consul-connect---certificate-authority">Consul Connect - Certificate Authority</h3>
<p>Consul connect implements it’s own certificate authority which leverages Hashicorp
Vault. As Mitchell explains, this makes it easy to get going but realistically
no one will use this. Most will leverage an external CA for certs. This means
that the CA system within Consul connect is pluggable.</p>
<h3 id="consul-connect---pluggable-data-plane">Consul Connect - Pluggable Data Plane</h3>
<p>Consul connect is a control plane solution (pluggable API) that integrates with
<a href="https://www.envoyproxy.io/">Envoy</a> and <a href="https://www.haproxy.com/products/haproxy-kubernetes-ingress-controller/">HAProxy</a> currently. More vendor support is underway.</p>
<h3 id="consul-connect---mesh-gateways">Consul Connect - Mesh Gateways</h3>
<p>Based on a question from the group in regard to controlling access to services
from cloud to on-prem. Mitchell discussed Consul connect mesh gateways. This
was definitely one topic that I didn’t grasp immediately and I will definitely
need to do some deeper review of. However, if you are interested, check
out more about this <a href="https://www.consul.io/docs/connect/mesh_gateway.html">here</a>.</p>
<p><img src="../../images/2019/10/Consul-Mesh-Gateways.png" alt="Consul Mesh Gateways" /></p>
<h2 id="conclusion">Conclusion</h2>
<p>As I mentioned earlier, I worked on a large project across data centers
a few years ago in which we used Consul in each data center which also included
WAN replication. We had a tremendous amount of success with Consul. However, I
would say that with the recent amount of new functionality, there is so much
that you can do and the features seem to shine massively.</p>
<p>With this all being said, I guess it is time for me to freshen up <a href="https://github.com/mrlesmithjr/vagrant-vault-consul-docker-monitoring">this</a> project I was
working on quite some time ago!</p>
<p>As always, enjoy!</p>
<blockquote>
<p>DISCLAIMER: I have been invited to Cloud Field Day Exclusive by Gestalt IT who paid for travel, hotel, meals and transportation. I did not receive any compensation to attend CFD and I am under no obligation whatsoever to write any content related to CFD. The contents of these blog posts represent my personal opinions about the products and solutions presented during CFD.</p>
</blockquote>Larry Smith Jr.Recently while attending Cloud Field Day 6, one of the companies presenting just so happened to be Hashicorp. Now Hashicorp is one of my personal favorite companies in the open-source world. So, to say that I was extremely excited to hear them would be an understatement. Luckily for us, Mitchell Hashimoto was the one who presented to all of us delegates as I am sure everyone was excited about this.CFD6 VMware API Questions2019-10-02T20:28:00+00:002019-10-02T20:28:00+00:00https://everythingshouldbevirtual.com/automation/CFD6-VMware-API-Questions<h2 id="cfd6-vmware-api-questions">CFD6 VMware API Questions</h2>
<p>While, attending <a href="https://techfieldday.com/event/cfd6/">Cloud Field Day 6</a> in
Silicon Valley as a delegate for Tech Field Day, Dell and VMware gave us their
pitch on <a href="https://www.vmware.com/products/cloud-foundation.html">VMware Cloud Foundation</a>.</p>
<p>To be clear, I had zero understanding of <code class="language-plaintext highlighter-rouge">VCF</code> prior to this. When I attend
these events I want to ask legitimately <strong>DUMB</strong> questions as I would as a
customer hearing about a product for the first time. Now to be fair, I
absolutely love some things that VMware does, but as most other companies out
there, there are some things that do not make sense. One of the things that I
find extremely annoying from VMware is their API functionality in most cases.
And generally the annoying part for me is the documentation around API usage.</p>
<p><strong>IT IS GETTING BETTER</strong></p>
<p>With this all being said, I’d like to walk through what was in my head while
hearing these presentations. In the previous session to the one below, we heard
all about VXRail, etc. Very cool stuff for sure. However, as the session for
<code class="language-plaintext highlighter-rouge">VCF</code> was progressing, my head went to a place of absolute disorganization based
on what I was hearing. Typical for me in most cases because to be fair, I do
not generally look at solutions in the same manner that a normal consumer would.
So, as I was listening to the <code class="language-plaintext highlighter-rouge">VCF</code> presentation, I thought that they had done
something really cool here and brought a layer of abstraction up in the stack
that a consumer could tap into from an automation perspective. Meaning that one
could simply automate a <strong>FULL</strong> VMware stack from a single API endpoint and not
have to worry about all of the additional layers (APIs) of everything else in
the lower levels (vCenter, vRA, vRO, NSX, etc.). So I started with my questions
to hopefully get an answer on what the real story was. Did I ask the questions
as clear as I could have? Probably not. But as usual (IMO), the lack of a clear
strategy from VMware across all products was rampant in my brain. In one instance
the reference of if you are only concerned about vCenter, then this probably is
not for you (my interpretation). In reality, I want to be concerned about the
whole stack. Full stack automation is definitely in my favor here, but I digress.
Now did I misinterpret the story being told? Possibly and I hope that is the case.
But my real point is this, every vendor needs to absolutely convey a clear story
on their strategy so that every level of consumer understands. But to be fair,
VMware is a huge company and covers a massive amount of ground. So, this is
somewhat expected but I personally think they should do a better job on telling
their complete story without all of the added layers of complexity. If I want to
do this, go over here, if I want to do that, go over there, etc., etc.</p>
<h2 id="conclusion">Conclusion</h2>
<p>As I mentioned above. I truly hope that I completely misinterpreted the story
being told. If I did, I would absolutely love some additional dialog for clarity
on my part.</p>
<p>In the video segment below, <a href="https://twitter.com/Ned1313">Ned Bellevance</a> tees
up my questions very well. And no, we did not plan this!</p>
<!-- Courtesy of embedresponsively.com //-->
<div class="responsive-video-container">
<iframe src="https://www.youtube-nocookie.com/embed/Qc1fGYJilQI?start=1752" frameborder="0" webkitallowfullscreen="" mozallowfullscreen="" allowfullscreen=""></iframe>
</div>
<p>In addition to all of this, <a href="https://twitter.com/CTOAdvisor">Keith Townsend</a>
just published a very good article around the <a href="https://www.thectoadvisor.com/blog/2019/10/2/vmwares-cloud-in-300-words">VMware’s Cloud in 300-words</a> that you
should definitely check out as well.</p>
<p>As always, enjoy!</p>Larry Smith Jr.CFD6 VMware API QuestionsAnsible Blocks With Conditionals2019-09-12T13:18:00+00:002019-09-12T13:18:00+00:00https://everythingshouldbevirtual.com/automation/Ansible-Blocks-With-Conditionals<h2 id="ansible-blocks-with-conditionals">Ansible Blocks With Conditionals</h2>
<h3 id="background">Background</h3>
<p>Recently I had an interesting issue when using Ansible <a href="https://docs.ansible.com/ansible/latest/user_guide/playbooks_blocks.html">Blocks</a> in a playbook
which was skipping tasks within the block itself. I had no idea
that this was to be expected so I am sharing this here in case others stumble
upon this.</p>
<p>The playbook that I had created was importing another playbook using a loop
(Because Ansible does not support loops of tasks any other way that I know of)
a defined number of times. As part of the <code class="language-plaintext highlighter-rouge">Block</code>, I had a conditional which
evaluated whether or not something was true or false. And based on this
condition, additional tasks within the block were to be executed. Well I was
definitely caught by surprise once I understood what was occurring. And actually,
it is actually quite interesting to know.</p>
<h3 id="example">Example</h3>
<p>For the context of this example I will not be using a looping playbook, but
instead a simplistic playbook to demonstrate what I saw.</p>
<h4 id="example-1">Example 1</h4>
<p>This example will demonstrate how I had originally put the playbook together and
we can see the results.</p>
<p>Playbook:</p>
<div class="language-yaml highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nn">---</span>
<span class="pi">-</span> <span class="na">hosts</span><span class="pi">:</span> <span class="s">localhost</span>
<span class="na">gather_facts</span><span class="pi">:</span> <span class="no">false</span>
<span class="na">connection</span><span class="pi">:</span> <span class="s">local</span>
<span class="na">vars</span><span class="pi">:</span>
<span class="na">debugging</span><span class="pi">:</span> <span class="no">true</span>
<span class="na">tasks</span><span class="pi">:</span>
<span class="pi">-</span> <span class="na">block</span><span class="pi">:</span>
<span class="pi">-</span> <span class="na">name</span><span class="pi">:</span> <span class="s">First Task</span>
<span class="na">debug</span><span class="pi">:</span>
<span class="na">msg</span><span class="pi">:</span> <span class="s">First Task</span>
<span class="pi">-</span> <span class="na">name</span><span class="pi">:</span> <span class="s">Set debugging To False</span>
<span class="na">set_fact</span><span class="pi">:</span>
<span class="na">debugging</span><span class="pi">:</span> <span class="no">false</span>
<span class="pi">-</span> <span class="na">name</span><span class="pi">:</span> <span class="s">Second Task</span>
<span class="na">debug</span><span class="pi">:</span>
<span class="na">msg</span><span class="pi">:</span> <span class="s">Second Task</span>
<span class="na">when</span><span class="pi">:</span> <span class="s">debugging|bool</span>
</code></pre></div></div>
<p>Based on the above playbook, I had expected both <code class="language-plaintext highlighter-rouge">First Task</code> and <code class="language-plaintext highlighter-rouge">Second Task</code>
to execute. But what we will see is, that this is not true at all.</p>
<p>Execution:</p>
<div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code>PLAY <span class="o">[</span>localhost] <span class="k">*********************************************************************************************************************************************</span>
TASK <span class="o">[</span>First Task] <span class="k">********************************************************************************************************************************************</span>
ok: <span class="o">[</span>localhost] <span class="o">=></span> <span class="o">{</span>
<span class="s2">"msg"</span>: <span class="s2">"First Task"</span>
<span class="o">}</span>
TASK <span class="o">[</span>Set debugging To False] <span class="k">********************************************************************************************************************************</span>
ok: <span class="o">[</span>localhost]
TASK <span class="o">[</span>Second Task] <span class="k">*******************************************************************************************************************************************</span>
skipping: <span class="o">[</span>localhost]
PLAY RECAP <span class="k">***************************************************************************************************************************************************</span>
localhost : <span class="nv">ok</span><span class="o">=</span>2 <span class="nv">changed</span><span class="o">=</span>0 <span class="nv">unreachable</span><span class="o">=</span>0 <span class="nv">failed</span><span class="o">=</span>0 <span class="nv">skipped</span><span class="o">=</span>1 <span class="nv">rescued</span><span class="o">=</span>0 <span class="nv">ignored</span><span class="o">=</span>0
</code></pre></div></div>
<p>Now if you review the results from above, you notice that the <code class="language-plaintext highlighter-rouge">Second Task</code>
was skipped. My initial thought was <code class="language-plaintext highlighter-rouge">WTF</code>, why did the <code class="language-plaintext highlighter-rouge">Second Task</code>
not execute because when I entered the block, <code class="language-plaintext highlighter-rouge">debugging</code> was set to <code class="language-plaintext highlighter-rouge">true</code>. So,
I would have assumed that even though I set <code class="language-plaintext highlighter-rouge">debugging: false</code> in the <code class="language-plaintext highlighter-rouge">set_fact</code>
task, that it would have still executed that <code class="language-plaintext highlighter-rouge">Second Task</code>. Not at all true.</p>
<h4 id="example-2">Example 2</h4>
<p>For this example, I will simply switch the tasks around to show that it works.
I know this is poor example because there really is not any reason that it <strong>SHOULDN’T</strong>
work. But again, for a simplistic demonstration it serves just fine because
our real concern is what we learned from <a href="#example-1">Example 1</a>.</p>
<p>Playbook:</p>
<div class="language-yaml highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nn">---</span>
<span class="pi">-</span> <span class="na">hosts</span><span class="pi">:</span> <span class="s">localhost</span>
<span class="na">gather_facts</span><span class="pi">:</span> <span class="no">false</span>
<span class="na">connection</span><span class="pi">:</span> <span class="s">local</span>
<span class="na">vars</span><span class="pi">:</span>
<span class="na">debugging</span><span class="pi">:</span> <span class="no">true</span>
<span class="na">tasks</span><span class="pi">:</span>
<span class="pi">-</span> <span class="na">block</span><span class="pi">:</span>
<span class="pi">-</span> <span class="na">name</span><span class="pi">:</span> <span class="s">First Task</span>
<span class="na">debug</span><span class="pi">:</span>
<span class="na">msg</span><span class="pi">:</span> <span class="s">First Task</span>
<span class="pi">-</span> <span class="na">name</span><span class="pi">:</span> <span class="s">Second Task</span>
<span class="na">debug</span><span class="pi">:</span>
<span class="na">msg</span><span class="pi">:</span> <span class="s">Second Task</span>
<span class="pi">-</span> <span class="na">name</span><span class="pi">:</span> <span class="s">Set debugging To False</span>
<span class="na">set_fact</span><span class="pi">:</span>
<span class="na">debugging</span><span class="pi">:</span> <span class="no">false</span>
<span class="na">when</span><span class="pi">:</span> <span class="s">debugging|bool</span>
</code></pre></div></div>
<p>Execution:</p>
<div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code>PLAY <span class="o">[</span>localhost] <span class="k">*********************************************************************************************************************************************</span>
TASK <span class="o">[</span>First Task] <span class="k">********************************************************************************************************************************************</span>
ok: <span class="o">[</span>localhost] <span class="o">=></span> <span class="o">{</span>
<span class="s2">"msg"</span>: <span class="s2">"First Task"</span>
<span class="o">}</span>
TASK <span class="o">[</span>Second Task] <span class="k">*******************************************************************************************************************************************</span>
ok: <span class="o">[</span>localhost] <span class="o">=></span> <span class="o">{</span>
<span class="s2">"msg"</span>: <span class="s2">"Second Task"</span>
<span class="o">}</span>
TASK <span class="o">[</span>Set debugging To False] <span class="k">********************************************************************************************************************************</span>
ok: <span class="o">[</span>localhost]
PLAY RECAP <span class="k">***************************************************************************************************************************************************</span>
localhost : <span class="nv">ok</span><span class="o">=</span>3 <span class="nv">changed</span><span class="o">=</span>0 <span class="nv">unreachable</span><span class="o">=</span>0 <span class="nv">failed</span><span class="o">=</span>0 <span class="nv">skipped</span><span class="o">=</span>0 <span class="nv">rescued</span><span class="o">=</span>0 <span class="nv">ignored</span><span class="o">=</span>0
</code></pre></div></div>
<p>As you can see, this worked as expected. Again, the real focus is on the <a href="#example-1">Example 1</a> results.</p>
<h3 id="learnings">Learnings</h3>
<p>Based on what I saw in my real use case in addition to these examples is the
following:</p>
<ul>
<li>If you are using a conditional as part of your <code class="language-plaintext highlighter-rouge">block</code>, ensure that you do
not set the variable which defines whether the condition is met or not prior to
any additional tasks within the block. <strong>ALWAYS</strong> set the condition as the last
task inside the <code class="language-plaintext highlighter-rouge">block</code>.</li>
<li>Ansible actually evaluates the conditional which is defined as part of the
<code class="language-plaintext highlighter-rouge">block</code> for each and every task inside the <code class="language-plaintext highlighter-rouge">block</code> itself.</li>
</ul>
<h3 id="updated-example">Updated Example</h3>
<p>I wanted to share this with others after I had someone reach out and ask about
using blocks and conditionals with roles. I felt this was a great question and
wanted to share the playbook we came up with.</p>
<script src="https://gist.github.com/mrlesmithjr/0bc55ad12743bbdead4cfc89d834a27e.js"> </script>
<h3 id="conclusion">Conclusion</h3>
<p>Hope this is of some use to others in case you ever run into this unexpected
scenario.</p>
<p>And as always, <strong>ENJOY!!</strong></p>Larry Smith Jr.Ansible Blocks With ConditionalsNested ESXi Templates2019-03-18T21:34:00+00:002019-03-18T21:34:00+00:00https://everythingshouldbevirtual.com/virtualization/Nested-ESXi-Templates<p>Over the past week I have been working on a streamlined process to deploy
nested ESXi 6.7 via automation tooling. Going through this I came across
an issue with all nested ESXi hosts obtaining the same IP address. I had already
followed the normal processes that are well documented in regard to prepping
the image before bundling up for use as a template.</p>
<p>The following were the commands that I found as a typical scenario:</p>
<div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code>esxcli system settings advanced <span class="nb">set</span> <span class="nt">-o</span> /Net/FollowHardwareMac <span class="nt">-i</span> 1
<span class="nb">sed</span> <span class="nt">-i</span> <span class="s1">'/\\/system\\/uuid/d'</span> /etc/vmware/esx.conf
/sbin/auto-backup.sh
</code></pre></div></div>
<p>These seemed to be working as desired until I decided to spin up quite a few of
them, and boom, there it was, all nested ESXi hosts had the same IP address.
Now for clarity, I am using Packer to build the base nested ESXi image (more on
this in a later post). But that was not the cause of the issue.</p>
<p>The following is what I was finally able to get to work as desired (in addition
to the above commands):</p>
<div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nb">sed</span> <span class="nt">-i</span> <span class="s1">'/\\/net\\/pnic\\/child\\[0000\\]\\/mac/d'</span> /etc/vmware/esx.conf
<span class="nb">sed</span> <span class="nt">-i</span> <span class="s1">'/\\/net\\/vmkernelnic\\/child\\[0000\\]\\/mac/d'</span> /etc/vmware/esx.conf
</code></pre></div></div>
<p>So the whole command set in one would look like:</p>
<div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code>esxcli system settings advanced <span class="nb">set</span> <span class="nt">-o</span> /Net/FollowHardwareMac <span class="nt">-i</span> 1
<span class="nb">sed</span> <span class="nt">-i</span> <span class="s1">'/\\/system\\/uuid/d'</span> /etc/vmware/esx.conf
<span class="nb">sed</span> <span class="nt">-i</span> <span class="s1">'/\\/net\\/pnic\\/child\\[0000\\]\\/mac/d'</span> /etc/vmware/esx.conf
<span class="nb">sed</span> <span class="nt">-i</span> <span class="s1">'/\\/net\\/vmkernelnic\\/child\\[0000\\]\\/mac/d'</span> /etc/vmware/esx.conf
/sbin/auto-backup.sh
</code></pre></div></div>
<p>The issue was that all the hosts were still coming up with the same MAC
address. So, not sure what was going on here in my scenario, but possibly this
may save someone else the headache I went through on this.</p>
<blockquote>
<p>UPDATE: 05/13/2019 - Ran into the infamous <code class="language-plaintext highlighter-rouge">datastore1</code> issue when attempting
to join nested ESXi hosts to vCenter. You will experience the issue because
all of the templates have the same UUID for <code class="language-plaintext highlighter-rouge">datastore1</code>. Resolve this by
adding <code class="language-plaintext highlighter-rouge">--novmfsondisk</code> in your <code class="language-plaintext highlighter-rouge">ks.cfg</code>. Ex. <code class="language-plaintext highlighter-rouge">install --firstdisk --overwritevmfs --novmfsondisk</code>.</p>
</blockquote>
<p>Enjoy!</p>Larry Smith Jr.Over the past week I have been working on a streamlined process to deploy nested ESXi 6.7 via automation tooling. Going through this I came across an issue with all nested ESXi hosts obtaining the same IP address. I had already followed the normal processes that are well documented in regard to prepping the image before bundling up for use as a template.VMware Workstation - Enter Serial Number From Linux CLI2019-02-21T19:05:00+00:002019-02-21T19:05:00+00:00https://everythingshouldbevirtual.com/virtualization/VMware-Workstation-Enter-Serial-Number-Linux-CLI<p>Well, this was a fun exercise. While building out some VMs to execute Packer
image builds for vSphere, I installed VMware Workstation via Ansible and forgot
to add the serial number as part of the installation. Yes, you read that correct,
running Packer builds inside a vSphere VM, within VMware Workstation. All kicked
off via GitLab CI pipelines. So, anyways, back to the issue at hand. I needed
to enter a functional license key to make Packer happy with VMware Workstation.
Well, something that one would think would be relatively easy, was not so much.
At least for me. Because there was not a GUI, I had to figure out the CLI command
to execute. Google did not provide me with anything very useful, but finally
pieced some stuff together which ended up working. So, here it is, the overly
complex command:</p>
<div class="language-bash highlighter-rouge"><div class="highlight"><pre class="highlight"><code><span class="nb">sudo</span> /usr/lib/vmware/bin/licenseTool enter XXXXX-XXXXX-XXXXX-XXXXX-XXXXX <span class="s2">""</span> <span class="s2">""</span> 15.0+ <span class="s2">"VMware Workstation"</span> /usr/lib/vmware
</code></pre></div></div>
<p>There is a command <code class="language-plaintext highlighter-rouge">vmware-license-enter.sh</code> which did not work at all, but
looking at the contents of the script, allowed me to figure out the correct
command to run.</p>
<p>So, there you have it! Hopefully this will be of some use to others, but more of
a bookmark for me!</p>
<p>Enjoy!</p>Larry Smith Jr.Well, this was a fun exercise. While building out some VMs to execute Packer image builds for vSphere, I installed VMware Workstation via Ansible and forgot to add the serial number as part of the installation. Yes, you read that correct, running Packer builds inside a vSphere VM, within VMware Workstation. All kicked off via GitLab CI pipelines. So, anyways, back to the issue at hand. I needed to enter a functional license key to make Packer happy with VMware Workstation. Well, something that one would think would be relatively easy, was not so much. At least for me. Because there was not a GUI, I had to figure out the CLI command to execute. Google did not provide me with anything very useful, but finally pieced some stuff together which ended up working. So, here it is, the overly complex command: