<?xml version="1.0" encoding="UTF-8"?>
<?xml-stylesheet type="text/xsl" href="http://todd.wells.ws/assets/xslt/rss.xslt" ?>
<?xml-stylesheet type="text/css" href="http://todd.wells.ws/assets/css/rss.css" ?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
	<channel>
		<title>Todd Wells</title>
		<description>Blog about DevOps in the Cloud.  Special focus on ChatOps and SaltStack.</description>
		<link>http://todd.wells.ws/</link>
		<atom:link href="http://todd.wells.ws/feed.xml" rel="self" type="application/rss+xml" />
		
			<item>
				<title>If Corona Were the Flu</title>
				<link>http://todd.wells.ws/blog/if-corona-were-the-flu/</link>
				<pubDate>Sat, 04 Apr 2020 00:00:00 +0000</pubDate>
				<description>&lt;p&gt;Trying to understand the Corona virus and how it is affecting society is an exercise in frustration. Sifting through all of the news, blogs, tweets, gossip to get to accurate and useful data is hard. We are getting told “Social Distance”, “Stay at Home”, “Flatten The Curve”.  But they are not presenting clear data to back up these statements.  So I dig in and try to understand the data for myself.  This is my attempt to present the data in a picture that will help people realize why we need to take all these extreme measures.&lt;/p&gt;

&lt;h3 id=&quot;flu-hospitalization-and-mortality&quot;&gt;Flu Hospitalization and Mortality&lt;/h3&gt;
&lt;p&gt;So the first picture is “What if Corona were the flu”.&lt;/p&gt;

&lt;p&gt;Lets start with &lt;a href=&quot;https://www.cdc.gov/flu/about/burden/preliminary-in-season-estimates.htm&quot;&gt;flu data from CDC&lt;/a&gt;.  I have picked a number within the ranges specified, assuming the number is towards the top of the range.&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;50,000,000 infections (15% of US population)&lt;/li&gt;
  &lt;li&gt;600,000 hospitalizations (1.2% of infections)&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;60,000&lt;/strong&gt; deaths (.12% of infections)&lt;/li&gt;
&lt;/ul&gt;

&lt;h3 id=&quot;covid-19-same-infection-rate-as-flu-low-mortality&quot;&gt;COVID-19 Same Infection Rate as Flu, Low Mortality&lt;/h3&gt;
&lt;p&gt;And now imagine we leave the infection rate the same but change the hospitalization and death rates to those of COVID-19.  Based on the &lt;a href=&quot;https://www.cdc.gov/mmwr/volumes/69/wr/mm6912e2.htm?s_cid=mm6912e2_w#T1_down&quot;&gt;COVID-19 data from CDC&lt;/a&gt; the hospitalization and death percentages are (using the lowest percentage in the range) 21% and 1.8% respectively.  I’m actually going to further lower the death rate to only 1% for now.   With that here is what COVID-19 would look like&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;50,000,000 infections (15% of US population)&lt;/li&gt;
  &lt;li&gt;10,500,000 hospitalizations (21% of infections)&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;500,000&lt;/strong&gt; deaths (1% of infections)&lt;/li&gt;
&lt;/ul&gt;

&lt;h3 id=&quot;covid-19-conservative-infection-rate-low-mortality&quot;&gt;COVID-19 Conservative Infection Rate, Low Mortality&lt;/h3&gt;
&lt;p&gt;Based on the assumption that COVID-19 had the same infection rate as the flu, and that our medical system could handle the increased hospitalization rate, the US would lose half a million people. But those are not valid assumptions.&lt;/p&gt;

&lt;p&gt;COVID-19 is much more contagious than flu.  After watching &lt;a href=&quot;https://www.youtube.com/watch?v=PWzbArPgo-o&quot;&gt;Ninja Nerd Science&lt;/a&gt; I am going with a conservative estimate of twice as contagious, doubling our infections.&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;100,000,000 infections (30% of US population)&lt;/li&gt;
  &lt;li&gt;21,000,000 hospitalizations (21% of infections)&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;1,000,000&lt;/strong&gt; deaths (1% of infections)&lt;/li&gt;
&lt;/ul&gt;

&lt;h3 id=&quot;covid-19-conservative-infection-rate-conservative-mortality-for-overloaded-hospitals&quot;&gt;COVID-19 Conservative Infection Rate, Conservative Mortality for Overloaded Hospitals&lt;/h3&gt;
&lt;p&gt;And our medical system can also not handle the patient load. And so the death rate will go up as people can not get the medical treatment they require. Lets also make a conservative change and put the death rate back to the 1.8% of the CDC data.&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;100,000,000 infections (30% of US population)&lt;/li&gt;
  &lt;li&gt;21,000,000 hospitalizations (21% of infections)&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;1,800,000&lt;/strong&gt; deaths (1.8% of infections)&lt;/li&gt;
&lt;/ul&gt;

&lt;h3 id=&quot;comments&quot;&gt;Comments&lt;/h3&gt;
&lt;p&gt;Even the conservative picture of COVID-19 without any “extreme measures” is pretty grim. The actual picture if we did not try to reduce the infection rate and prevent hospitals from being completely overloaded would likely be much worse.&lt;/p&gt;

&lt;p&gt;I am feeling a little stir crazy after only two weeks of “Stay at Home”. And practicing “Social Distance” when I do have to go out for food is awkward, physically difficult in the typical grocery store, and emotionally draining.  But is the cost of staying home worth saving over a million lives?&lt;/p&gt;

&lt;p&gt;And how many lives we save is dependent on how well we do “Stay at Home” and “Social Distance”.  To achieve what the CDC is projecting ( 100,000 to 200,000) we have to reduce the infection rate well below that of the flu. Which means potentially months of even more strict “Stay at Home” and “Social Distance”.  Do I want to do this? No.  Do I think it necessary? Yes.&lt;/p&gt;
</description>
				<guid isPermaLink="true">http://todd.wells.ws/blog/if-corona-were-the-flu/</guid>
			</item>
		
			<item>
				<title>AWS MySQL Choices:  MySQL, RDS, Aurora oh my</title>
				<link>http://todd.wells.ws/blog/aws-mysql-choices/</link>
				<pubDate>Sat, 04 Feb 2017 00:00:00 +0000</pubDate>
				<description>&lt;p&gt;My migration to AWS is to the point where I have to decide on what database to use.  Or should I say what version of a database to use.  Our current DB is MySQL, so I want to stick with compatible options.   And there are three:  self-managed MySQL, RDS MySQL, RDS Aurora.   Which to choose?&lt;/p&gt;

&lt;p&gt;My Ubuntu servers running self-managed MySQL perform their job just fine.  Our only significant outage in the last year that was DB related was running out of space (oops, my bad).  So from a basic reliability standpoint there is no problem with self-managed MySQL.  The issues come in when you add in backups &amp;amp; replication, which is a given for most organizations.  Developing the processes and procedures for performing backups and for creating slaves took work.   And it takes ongoing work.  Replication issues have caused me to rebuild two MySQL Slaves this year alone and many more last year.  So I have that process down. But I would rather not have to deal with it at all. The story is similar with Backups.   Time fixing backup issues and replication failures account for over 50% of production maintenance.   I want to outsource all of this backup &amp;amp; replication maintenance.   And both RDS MySQL and RDS Aurora do that.  Backups … check the box.  Creating a slave in another AZ … check the box.  Oh and lets add in Encryption … check the box.&lt;/p&gt;

&lt;p&gt;So RDS MySQL or Aurora?&lt;/p&gt;

&lt;p&gt;RDS is MySQL with all of the automation/maintenance I am looking for in place.  The 20-30% cost increase of an EC2 instance of the same size is well worth the cost for not having to do all that maintenance.   But in the end it is just MySQL servers that have a lot of automation build around them.  Aurora on the other hand is built differently: 6X data replication, dedicated storage subsystem, rapid replica creation.  Maybe call this Oracle RAC Lite.  Which to me is a good thing.  I managed Oracle RAC for many years and the maintenance efforts required was way higher than a similar number of MySQL servers and slaves. RAC was cumbersome and required specialized DBAs to keep it running and of course cost many arms and legs.&lt;/p&gt;

&lt;p&gt;Technically Aurora looks to be a better solution than RDS MySQL. So the decision gets down to price.   Can I afford Aurora.   When I first looked at Aurora, the answer was no, but that was primarily because there were no smaller instance sizes.   r3.large for about $210/month was small enough for my production instances, but too much ( and too costly ) for development/test instances and special purpose slaves.  And I would rather not manage PROD in Aurora and Dev/Test in RDS MySQL.  Looking more recently I see that t2.medium was now an option with a $60/month price point.  So I need to re-evaluate.&lt;/p&gt;

&lt;p&gt;And that re-evaluation lead me to go over the Aurora documentation much more thoroughly. And when I did I found way down at the bottom of the pricing page&lt;/p&gt;

&lt;div class=&quot;language-text highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;I/O Rate	$0.200 per 1 million requests
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Wow good catch.  No longer is a DB server a fixed cost ( add up instance and storage cost ).  Looking online I see many people have been surprised by a large and unexpected I/O cost on their first bill.  Not going to make that mistake.  An AWS support chat asking for help with estimating Aurora IO based on my current MySQL servers did not give me much information on how they might be different. So I am going to assume MySQL IOPs and Aurora IOPs will be about the same.  A quick calculation show me that an average of 100 IOPs/sec over a month adds about $50 in I/O costs.   Looking at my monitoring ( NewRelic ) shows me only % utilization, so guess I have to go old school:  install and enable sysstat.   I’ll let you know how it turns out.&lt;/p&gt;
</description>
				<guid isPermaLink="true">http://todd.wells.ws/blog/aws-mysql-choices/</guid>
			</item>
		
			<item>
				<title>Can SaltStack do AWS, what's in a name</title>
				<link>http://todd.wells.ws/blog/aws-whats-in-a-name/</link>
				<pubDate>Fri, 27 Jan 2017 00:00:00 +0000</pubDate>
				<description>&lt;p&gt;Two days of &lt;a href=&quot;https://github.com/saltstack-formulas/aws-formula&quot;&gt;aws-formula&lt;/a&gt; being live and I found it was broken. Because of names. More precisely the collision of of names in different VPCs.  Aren’t VPCs completely independent?  Well yes, except for names it appears.&lt;/p&gt;

&lt;p&gt;The normal methodology for a salt state is to check if something needs to be updated and then update it if it does.  It appears that this methodology is breaking down in the AWS state/module.  I think this is partly due to how AWS is structured and part to difficulties with the boto module.&lt;/p&gt;

&lt;p&gt;The aws-formula uses object names to create all objects.  One reason for this is the lack of a mechanism for capturing the results of one state ( create Internet Gateway ) and using a part of that captured value ( Internet Gateway ID) as an input for another state ( create Route Table ).   Ansible’s &lt;code class=&quot;language-text highlighter-rouge&quot;&gt;Registered Variable&lt;/code&gt; can accomplish this, but it is somewhat messy as the registered variable has to be manipulated in a command in order to parse out the part of the output desired, then that parsed out value captured in another variable before being used in subsequent commands.  Using Names instead of IDs for all AWS objects is a much cleaner methodology for creating a VPC and all its required components.  It removes all the complexity of parsing IDs based on state results.&lt;/p&gt;

&lt;p&gt;AWS uses a tag to capture the name for objects.  In VPCs, this includes: Subnets, Route Tables, Internet Gateways, Network ACLs, Security Groups.   Multiple objects of these types can have the same name. Here is an example:&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/assets/img/aws-route-table-duplicate-name.png&quot; alt=&quot;AWS routing tables in same VPC with the same name&quot; /&gt;&lt;/p&gt;

&lt;p&gt;The boto modules appear to get caught by this as well.  I have two VPCs in the same region.  Neither have the routing table named my_route_table.&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/assets/img/aws-two-vpc.png&quot; alt=&quot;two vpc&quot; /&gt;&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/assets/img/aws-no-route-table.png&quot; alt=&quot;no my_route_table &quot; /&gt;&lt;/p&gt;

&lt;p&gt;But yet when I run the following states instead of getting both to succeed, only one succeeds.&lt;/p&gt;

&lt;div class=&quot;language-yaml highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;na&quot;&gt;boto_vpcProdEast5_my_route_table&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt;
  &lt;span class=&quot;s&quot;&gt;boto_vpc.route_table_present&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt;
    &lt;span class=&quot;pi&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;name&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;my_route_table&lt;/span&gt;
    &lt;span class=&quot;pi&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;vpc_name&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;vpcProdEast5&lt;/span&gt;
    &lt;span class=&quot;pi&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;key&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX&lt;/span&gt;
    &lt;span class=&quot;pi&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;keyid&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;XXXXXXXXXXXXXXX&lt;/span&gt;
    &lt;span class=&quot;pi&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;region&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;us-east-2&lt;/span&gt;

&lt;span class=&quot;na&quot;&gt;boto_vpcProdEast6_my_route_table&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt;
  &lt;span class=&quot;s&quot;&gt;boto_vpc.route_table_present&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt;
    &lt;span class=&quot;pi&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;name&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;my_route_table&lt;/span&gt;
    &lt;span class=&quot;pi&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;vpc_name&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;vpcProdEast6&lt;/span&gt;
    &lt;span class=&quot;pi&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;key&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX&lt;/span&gt;
    &lt;span class=&quot;pi&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;keyid&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;XXXXXXXXXXXXXXX&lt;/span&gt;
    &lt;span class=&quot;pi&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;na&quot;&gt;region&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;us-east-2&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;
&lt;p&gt;The results show that the second state does not run because there is already a routing table by that name present, the one in the other VPC.&lt;/p&gt;

&lt;div class=&quot;language-yaml highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;s&quot;&gt;----------&lt;/span&gt;
          &lt;span class=&quot;s&quot;&gt;ID&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;boto_vpcProdEast5_my_route_table&lt;/span&gt;
    &lt;span class=&quot;s&quot;&gt;Function&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;boto_vpc.route_table_present&lt;/span&gt;
        &lt;span class=&quot;s&quot;&gt;Name&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;my_route_table&lt;/span&gt;
      &lt;span class=&quot;s&quot;&gt;Result&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;True&lt;/span&gt;
     &lt;span class=&quot;s&quot;&gt;Comment&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;Route table my_route_table created.&lt;/span&gt;
     &lt;span class=&quot;s&quot;&gt;Started&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;04:52:35.891737&lt;/span&gt;
    &lt;span class=&quot;s&quot;&gt;Duration&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;1887.427 ms&lt;/span&gt;
     &lt;span class=&quot;s&quot;&gt;Changes&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt;
              &lt;span class=&quot;s&quot;&gt;----------&lt;/span&gt;
              &lt;span class=&quot;s&quot;&gt;new&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt;
                  &lt;span class=&quot;s&quot;&gt;----------&lt;/span&gt;
                  &lt;span class=&quot;s&quot;&gt;route_table&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt;
                      &lt;span class=&quot;s&quot;&gt;rtb-1224827b&lt;/span&gt;
              &lt;span class=&quot;na&quot;&gt;old&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt;
                  &lt;span class=&quot;s&quot;&gt;----------&lt;/span&gt;
                  &lt;span class=&quot;s&quot;&gt;route_table&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt;
                      &lt;span class=&quot;s&quot;&gt;None&lt;/span&gt;
&lt;span class=&quot;s&quot;&gt;----------&lt;/span&gt;
          &lt;span class=&quot;s&quot;&gt;ID&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;boto_vpcProdEast6_my_route_table&lt;/span&gt;
    &lt;span class=&quot;s&quot;&gt;Function&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;boto_vpc.route_table_present&lt;/span&gt;
        &lt;span class=&quot;s&quot;&gt;Name&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;my_route_table&lt;/span&gt;
      &lt;span class=&quot;s&quot;&gt;Result&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;True&lt;/span&gt;
     &lt;span class=&quot;s&quot;&gt;Comment&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;Route table my_route_table (rtb-1224827b) present.&lt;/span&gt;
     &lt;span class=&quot;s&quot;&gt;Started&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;04:52:37.779406&lt;/span&gt;
    &lt;span class=&quot;s&quot;&gt;Duration&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;239.461 ms&lt;/span&gt;
     &lt;span class=&quot;s&quot;&gt;Changes&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt;

&lt;span class=&quot;s&quot;&gt;Summary for local-core-api-prod-1&lt;/span&gt;
&lt;span class=&quot;s&quot;&gt;------------&lt;/span&gt;
&lt;span class=&quot;na&quot;&gt;Succeeded&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s&quot;&gt;2 (changed=1)&lt;/span&gt;
&lt;span class=&quot;na&quot;&gt;Failed&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt;    &lt;span class=&quot;m&quot;&gt;0&lt;/span&gt;
&lt;span class=&quot;s&quot;&gt;------------&lt;/span&gt;
&lt;span class=&quot;na&quot;&gt;Total states run&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt;     &lt;span class=&quot;m&quot;&gt;2&lt;/span&gt;
&lt;span class=&quot;na&quot;&gt;Total run time&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt;   &lt;span class=&quot;s&quot;&gt;2.127 s&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Since the state requires both the routing table name and the VPC it is in, I would expect the above to work since the combination of vpc_name and name ( routing table name ) is unique. But looks like it is not. The method route_table_present in states/boto_vpc.py is being called, which eventually calls _find_resources in modules/boto_vpc.py.   _find_resources is only using the name tag to filter the list of routing tables.
So until the filter also includes the VPC name, we will not be able to have the same object name in multiple VPCs.&lt;/p&gt;

&lt;p&gt;In the past I have sometimes used globally unique names … Security groups is an example.  These needed to be globally unique since a Security Group can be referenced across a VPC Pairing. Guess I need to make this more general   So for now making all VPC object names globally unique is going to be the SaltStack best practice for boto_vpc states.&lt;/p&gt;

&lt;p&gt;&lt;a href=&quot;https://github.com/saltstack-formulas/aws-formula&quot;&gt;aws-formula&lt;/a&gt; has been updated to include this best practice.  All states will automatically append the VPC Name to all object names so you don’t have to clutter the pillar with repeat reverences to the VPC Name.&lt;/p&gt;
</description>
				<guid isPermaLink="true">http://todd.wells.ws/blog/aws-whats-in-a-name/</guid>
			</item>
		
			<item>
				<title>Can SaltStack do AWS, the VPC</title>
				<link>http://todd.wells.ws/blog/can-saltstack-do-aws/</link>
				<pubDate>Sun, 22 Jan 2017 00:00:00 +0000</pubDate>
				<description>&lt;p&gt;We started on Rackspace back when it was still trying to compete with AWS in the IaaS. As a startup, Rackspace worked just fine.  But if a company grows and needs more and their IaaS vendor is not growing their offering, there comes a tipping point.  Security was our tipping point.  We could not get the security we needed without either expensive dedicated hardware or a way to convoluted network architecture.  And so we are moving to a new IaaS vendor, AWS.&lt;/p&gt;

&lt;p&gt;To get started at AWS I created a VPC by hand:  subnets, routing tables, gateways, security groups. Add in a salt server and I am able to use Salt to spin up and manage my AWS servers. And I thought, like many others before me, “I can turn this infrastructure into a cloud formation template”.   And I did, all 1793 lines of it, in JSON.  Since everything I do in SaltStack is YAML, I would much rather use YAML. And as I look I find that the AWS export tool provides JSON, but CloudFormation will take either YAML or JSON.  A web translator and 1/2 hour later I have a YAML file, and it is only 1214 lines long.  Removing 588 lines containing only start or end brackets/braces makes it more readable, but it is still 1214 lines I have to go through and change references into CloudFormation variables so that I can use this as a template for another VPC.  Which could take days ( per a friend that did this same thing it took 2 days ).&lt;/p&gt;

&lt;p&gt;Should I invest two days into this with the results being a template that will create exactly one VPC design? Or should I try to use the native SaltStack states?  When I looked at this a couple of years ago the answer was to go with the CloudFormation template.  And when I look now I don’t find a lot more out there to indicate people are using states.  I find a few questions on how to do a VPC using salt states, but It seems like more people are using the boto_cfn to run their CloudFormation template from within saltstack. And there are no saltstack formulas that actually create a VPC and the base components like routing tables, gateways, etc…&lt;/p&gt;

&lt;p&gt;Are there no formulas because people can not make it work?  Or is it just that no one has taken the time to write one? Looking at SaltStack documentation it appears that the hard working SaltStack staff and volunteers have gotten all the pieces in place to make it possible to use states. So looks like option two. I guess I will have to try to write one.&lt;/p&gt;

&lt;p&gt;And a couple of days later I have a formula that works.  Well, it works 95%.  I get an error when trying to use nat_gateway_subnet_name inside a boto_vpc.route_table_present.  So SaltStack issue created and I find a workaround until that error gets fixed.  Which means a 2 run solution.  First formula run creates all the pieces. Then copy the NAT Gateway ID into the pillar and re-run the formula to add the NAT Gateway as the default for internal subnet routing table rules.&lt;/p&gt;

&lt;p&gt;Two days invested in creating an aws-formula is much better than creating an inflexible CloudFormation Template. And the &lt;a href=&quot;https://github.com/saltstack-formulas/aws-formula&quot;&gt;aws-formula&lt;/a&gt; is now live on salt-stack-formulas. The sample pillar shows the creation of a three tier, three Availability Zone VPC.  It creates:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;Key Pairs&lt;/li&gt;
  &lt;li&gt;VPC&lt;/li&gt;
  &lt;li&gt;Internet Gateway&lt;/li&gt;
  &lt;li&gt;Subnets ( web, app, db X 3 AZ)&lt;/li&gt;
  &lt;li&gt;NAT Gateways in the web subnet of each AZ&lt;/li&gt;
  &lt;li&gt;Public and private routing tables for each AZ&lt;/li&gt;
  &lt;li&gt;Add default routes with public and private routing tables ( Internet Gateway for public, NAT Gateway for private )&lt;/li&gt;
  &lt;li&gt;Associate Subnets with Routing Tables&lt;/li&gt;
  &lt;li&gt;Security Groups ( Web, App, Salt-master, openVPN, ipsec VPN)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;There are no servers in this, but those will all be created by Salt. Sure wish we had VPC pairing between regions.  That would allow this to really be complete.  But alas not yet. So those ipsec based VPN servers still have to be created by Salt and then the routes added to the AWS pillar.&lt;/p&gt;
</description>
				<guid isPermaLink="true">http://todd.wells.ws/blog/can-saltstack-do-aws/</guid>
			</item>
		
			<item>
				<title>Can Ops use Dev Techniques Part 3, Deployment Workflow</title>
				<link>http://todd.wells.ws/blog/dev-use-ops-technique-part3/</link>
				<pubDate>Tue, 13 Sep 2016 00:00:00 +0000</pubDate>
				<description>&lt;h4 id=&quot;piece-3-deployment-workflow&quot;&gt;Piece 3: Deployment Workflow&lt;/h4&gt;

&lt;p&gt;The last piece of the development “process” I want to look at is the Development Workflow. What is the process for getting the code from the developer and onto a physical server where customers can use it. Generally speaking companies have a set of environments that  code will flow through before it gets into production.  Lets keep this simple with three environments:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;development ( dev )&lt;/li&gt;
  &lt;li&gt;quality assurance ( qa )&lt;/li&gt;
  &lt;li&gt;production ( prod )&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;After code is written it gets deployed to a dev server where the newly created features are tested individually to make sure they work as expected.  Then the code is promoted to a qa server where the overall application is tested to make sure new changes did not affect the rest of the application in ways we did not expect.  And once this is validated, the code goes to a prod server.&lt;/p&gt;

&lt;p&gt;Can this also work for the operations automation code? We first need to work through differences environment definitions. My automation server deploys code to dev, qa and prod.  So this server is partly prod, partly qa, partly dev.  Anyone in Sysadmin or DevOps is used to this definition difficulty.  The environment lines are not so clear cut when it comes to Ops servers. But I think it is clear that our automation code needs to be tested.  So It is better to create a new set of environment definitions for the Ops servers/services.  Here are mine:&lt;/p&gt;

&lt;p&gt;My SaltStack automation server has three environments, Lets call them test, stage, prod.  Test is where I try out the SaltStack pillars and states I am updating.  I create servers just for the purpose of testing these changes.  Since this is only for testing salt code, the developers do not have any access to this environment. I use this environment for both testing individual features and testing the overall application, but since it is done separate from the “real world” it it is roughly the equivalent of dev.&lt;/p&gt;

&lt;p&gt;Once tested in dev, SaltStack code is moved to the stage environment.  All dev environment servers are in this automation environment, and so the automation code now in a real world with users and real code being run.  So from a environment standpoint this is roughly equivalent to qa.  It also means that either an automation change or a dev code change could be responsible for a Dev feature not working.  I have not found a way to work around this, and I don’t think we really need to.  Because this is not really different than front end and back end engineers testing their new features together and having a problem.  The issue has to be researched to determine which teams code the problem is in.&lt;/p&gt;

&lt;p&gt;Now that the SaltStack code is tested in “real world”, it gets promoted to prod.  The SaltStack prod environment contains both the qa and prod servers.  Using the same automation code makes qa and prod are as similar as possible to ensure the validity of our qa testing before our Dev code goes to prod.&lt;/p&gt;

&lt;p&gt;Using Ops specific environments, the automation code workflow looks very similar to the Dev code workflow.  And so once the answer to “can Ops use the same process as Dev” is theoretically yes.&lt;/p&gt;

&lt;p&gt;To make git flow work practically for my automation code, I use branches corresponding to the described environments.  I have three directories on the salt server.  Each directory is a copy of the automation repository set to a different branch.  Then in my master config I use Salt &lt;strong&gt;file_roots&lt;/strong&gt; to connect a directory to a salt environment and the &lt;strong&gt;top&lt;/strong&gt; file to connect servers to the appropriate environment.  The result of using a branch per environment is that my git flow has three persistent branches ( develop, stage, master ) instead of the typical two ( develop, master ).&lt;/p&gt;

&lt;p&gt;Just one more part of this series to go, where I look at the questions “Will Ops use the Dev processes?” and “Why is it important for Ops to do so?”&lt;/p&gt;
</description>
				<guid isPermaLink="true">http://todd.wells.ws/blog/dev-use-ops-technique-part3/</guid>
			</item>
		
			<item>
				<title>Can Ops use Dev Techniques Part 2, Code Workflow</title>
				<link>http://todd.wells.ws/blog/dev-use-ops-technique-part2/</link>
				<pubDate>Thu, 08 Sep 2016 00:00:00 +0000</pubDate>
				<description>&lt;h4 id=&quot;piece-2-code-workflow&quot;&gt;Piece 2: Code Workflow&lt;/h4&gt;

&lt;p&gt;Another piece of the the development “process” the the code workflow.  We have bunch of developers writing code with the goal of providing new and hopefully useful features to our customers.  So we need a way to organize how all these separate pieces of code get merged into that finished product.  This is code management.  After a couple of iterations, code management now typically uses a distributed code repository where multiple people can edit a piece of code and changes are added to the code base and then merged with other versions.  the most common tool for code management is &lt;a href=&quot;https://git-scm.com/&quot;&gt;git&lt;/a&gt;. But it is a tool with much flexibility, so like the previous post a framework/methodology is needed.  With git these are usually called &lt;strong&gt;branching strategies&lt;/strong&gt;.  And a popular one that our organization uses is &lt;strong&gt;git flow&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;With git flow, one ore more developers will work on a branch created for a particular feature. These branches can be deployed to servers and tested.  Then once the feature is complete it is merged into the develop branch along with other features.  At some point, usually at the end of a sprint, a release branch is created to test all the new features together.  There will likely be changes needed to have them all working, which are made on the release branch.   Once it is fully functional and thoroughly tested, the release branch is merged in to production ( master ) and also to develop.&lt;/p&gt;

&lt;p&gt;So can this development code workflow be used by operations too?  Well if the ops staff ( or the operations focused members of the DevOps team if you like that semantics better ) is doing everything by hand ( or with an loosely organized assortment of bash scripts), then the answer is no. So lets assume that Ops is using an automation tool to replace manually typed commands with “recipes” for creating servers, customizing the configuration and services available on those server and then deploying our applications to those servers.  Most of the automation tools ( like my current one &lt;a href=&quot;https://saltstack.com/&quot;&gt;Saltstack&lt;/a&gt; ) have these instructions written in files organized into a directory structure. Sounds a lot like “code”, hence the term Infrastructure as Code ( IaC).&lt;/p&gt;

&lt;p&gt;If Ops has automation code and more than one person working on it, then Ops is in the same code management boat as development.  So it seems reasonable that they manage it just like Dev.&lt;/p&gt;

&lt;p&gt;Unlike Scrum where it really requires the full team to participate and make it work, a code workflow like git flow can be used by a few people or even a single person.  I found it pretty easy to incorporate into my daily practice and it is working well for well for my automation code. There are some ops specific issues you will have to work through, like how to securely put passwords and other sensitive data into the automation repository, but those are doable details.&lt;/p&gt;

&lt;p&gt;Next post comes the last piece:  Deployment Workflow&lt;/p&gt;
</description>
				<guid isPermaLink="true">http://todd.wells.ws/blog/dev-use-ops-technique-part2/</guid>
			</item>
		
			<item>
				<title>DevOps, Plums and Apricots or Pluots. Can Ops use Dev Techniques?</title>
				<link>http://todd.wells.ws/blog/devops-plums-apricots-or-pluots/</link>
				<pubDate>Tue, 06 Sep 2016 00:00:00 +0000</pubDate>
				<description>&lt;p&gt;Is DevOps shoving plums and apricots into a bowl and pretending they are the same thing or is it breeding something new and giving it a new name like pluot?  When DevOps was coined in 2009, it was a label for a bottom up movement:  people in the IT trenches trying to figure out how to make things work better.  Agile programming had changed development and Ops was having trouble keeping up.  In the last 6 years the term has definitely gone corporate but retains its roots in the trenches.   So as a trench dweller I have to wrestle with the practicalities of DevOps every day.  Today I am wanting to see if the DevOps theory that Ops can use the same processes as Dev really works in practice.&lt;/p&gt;

&lt;p&gt;When I search Goole for “devops definition” the first result is &lt;a href=&quot;https://theagileadmin.com/what-is-devops/&quot;&gt;The Agile Admin&lt;/a&gt;.  There are two definitions listed:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;DevOps is the practice of operations and development engineers participating together in the entire service lifecycle, from design through the development process to production support.&lt;/li&gt;
  &lt;li&gt;DevOps is also characterized by operations staff making use many of the same techniques as developers for their systems work.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Can an operations staff managing servers, creating automation, supporting CI/CD solutions, and dealing with middle of the night outages use the same techniques as developers?  And if ops can, will they?  Why is it important that they do? Lets start by tearing development into some pieces to see if each piece can also be used by operations.  Today is piece one.&lt;/p&gt;

&lt;h4 id=&quot;piece-1-development-methodologiesframeworks&quot;&gt;Piece 1: Development Methodologies/Frameworks&lt;/h4&gt;
&lt;p&gt;One piece of the development “process” is the methodology and/or framework used. At there essence these methods/frameworks are ways to organize how work gets done. Many organizations are using some form of Agile, frequently Scrum. For a team using Scrum, business requirements get turned into features that are broken down into small pieces.  The team prioritizes those pieces and selects a subset of those pieces they think can be completed within a defined period of time.  The selected pieces are divided amongst the staff assigned to the project who work on and hopefully complete them within that time period. At the end of the time period, the team reviews the results and makes plans for the next defined period of time. And the process repeats.&lt;/p&gt;

&lt;p&gt;Can the above work for Ops? As an Ops person, I don’t have a Product Manager or a Product Owner determining business requirements for the infrastructure. But I can look at the infrastructure as it exists today and make a list of what pieces are missing and what can be improved.  This list and feedback from management allows me to organize and prioritize my work.  And I do need to organize my work.  So there is nothing that prevents me AKA Ops from using something like Scrum.&lt;/p&gt;

&lt;p&gt;Am I using Scrum for my Ops work?  At this point not really. I work daily with the developers in a DevOpsy way. but we are still trying to figure out the whole sprint thing after a period of rapid growth. Teams using a framework like Scrum have to go from framework to practice by trying things and seeing what works and what does not, then trying other things.  We tried a new tool for organizing our sprints that did not work well and Scrum suffered.  So we are changing that tool and re-booting our Scrum process.&lt;/p&gt;

&lt;p&gt;I have been here before and know that this is a normal part of starting with a framework and ending up with functional practices.  It is messy, it takes time, but it eventually gets figured out.  And I think the end result is much better than starting with a more rigid methodology and trying to conform our practices to that methodology.  And so I think I will be back to using Scrum soon.&lt;/p&gt;

&lt;p&gt;The next piece:  Code Workflow.  Stay tuned.&lt;/p&gt;
</description>
				<guid isPermaLink="true">http://todd.wells.ws/blog/devops-plums-apricots-or-pluots/</guid>
			</item>
		
			<item>
				<title>Chatops at 6 months. How has it changed development. Getting There</title>
				<link>http://todd.wells.ws/blog/chatops-at-6-months-getting-there/</link>
				<pubDate>Wed, 24 Aug 2016 00:00:00 +0000</pubDate>
				<description>&lt;p&gt;Using ChatOps to move from Ops-Serve to Self-Serve obviously took some technical work.  But as stated before I am focusing on the developer in this series, so I want to look at what it took to transition the development team to using this new tool.&lt;/p&gt;

&lt;p&gt;Changing our thinking and consequently our actions always takes work.  So as the implementer/expert/guru of something new I need to have a plan.  What can I do to help my team members in their process of thinking change? For me it means getting to the aha moment, where something clicks and I get the first glimpse of the bigger picture.  That glimpse helps drive me forward in learning and exploring, leading to thinking change.  It might not be the same aha for everyone, but I think we usually have a tipping point where our driving force changes and becomes more internal.&lt;/p&gt;

&lt;p&gt;An important thing to realize and plan for is the process of change takes time.  I implemented ChatOps and told the team about the new tool and what it could do.  Some people were excited and started trying it out right away. But not everyone did. Both are to be expected and both are fine. It is much better to give people the freedom to move at their own pace and to get to their personal aha moment than to force something on them, particularly forcing it on them “for their own good.”  Since this tool was designed to help my team mates, I want them to see the value in it and use it because it is valuable.&lt;/p&gt;

&lt;p&gt;Now the tool is launched, the team knows about it and some are trying it out.  Time to put extra effort into those early adopters. For me this generally meant three things:&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;Talking with them and learning what they want to do, then giving them example commands to do it.&lt;/li&gt;
  &lt;li&gt;Looking at the log of ChatOps commands to see what they were doing and giving them suggestions at how to do it better.&lt;/li&gt;
  &lt;li&gt;Looking at the log of invalid commands to see what they were not able to do because the syntax was unclear.  I would help them with the syntax and then try to update the ChatOps help so the syntax was clearer.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Just doing these three things over a month or two helped the early adopters see the value in the tool and how it could improve their workflow.  This is thinking change.  It was usually followed by change in action, which in this case was incorporating ChatOps into their workflow.  Doing the above also lead to thinking change in me.  When I learned how people wanted to do something my brain would churn on how to change existing commands or add new ChatOps commands to make it easer, and then I would go make the changes.  And those improvements helped the early adopters to aha faster and to ask if it could do xxxx.  And this circle continued.&lt;/p&gt;

&lt;p&gt;Once there was a few people using ChatOps as part of their development workflow, my role became much less active.  These early adopters used ChatOps as they collaborated, meaning the other team members got practical demonstrations of ChatOps.  It did not take many interactions like that before most of the remaining people started trying out ChatOps. And for the most part all I had to do was help people with syntax and making occasional suggestions on better ways to do things.&lt;/p&gt;

&lt;p&gt;Of course there were some people who did not use it for many months.  Some were “too busy” and did not really try to use it until they had breathing space.  Others might have a role where creating development server environments was not part of their normal job, or someone else always did it so they did not have to. Whatever the case this is to be expected.  At this point most everyone has transitioned their thinking and workflow to the new tool, so a few late adopters not really using it is not a concern.&lt;/p&gt;

&lt;p&gt;One significant item not mentioned above that was key to ChatOps success:  Fast Bug Fixes. Developers had sympathy for me because they are familiar with new implementations and finding bugs in new code.  But they are also under pressure to perform in their jobs.  So if I give them a tool and they find it does not work as needed due to bugs that are not fixed quickly, they might decide it is not worth the time and effort to learn a new tool AND to work around the bugs in that tool. Which would set the adoption process back with those important early developers. And so any time they discovered a bug I would give it high priority and usually have it fixed the same day.&lt;/p&gt;
</description>
				<guid isPermaLink="true">http://todd.wells.ws/blog/chatops-at-6-months-getting-there/</guid>
			</item>
		
			<item>
				<title>Chatops at 6 months. How has it changed development. After</title>
				<link>http://todd.wells.ws/blog/chatops-at-6months-after/</link>
				<pubDate>Fri, 19 Aug 2016 00:00:00 +0000</pubDate>
				<description>&lt;p&gt;In my &lt;a href=&quot;/blog/chatops-at-6months-before/&quot;&gt;last post&lt;/a&gt; I looked at where the development process was before ChatOps was discovered and implemented. My how things have changed in these six months.  Developers can do a lot more now.&lt;/p&gt;

&lt;h4 id=&quot;a-developer-can--with-a-single-slack-command-&quot;&gt;A developer can ( with a single Slack command )&lt;/h4&gt;
&lt;ul&gt;
  &lt;li&gt;Get a list of development servers&lt;/li&gt;
  &lt;li&gt;Get a list of development environments&lt;/li&gt;
  &lt;li&gt;Get details for all servers in a development environment&lt;/li&gt;
  &lt;li&gt;Create a single server fully configured, on the correct code branch.&lt;/li&gt;
  &lt;li&gt;Create a full environment with all needed servers fully configured and on the correct code branch. Web servers would be automatically pointed at the api server in the set.&lt;/li&gt;
  &lt;li&gt;Deploy new code branches to a server&lt;/li&gt;
  &lt;li&gt;Terminate a single server&lt;/li&gt;
  &lt;li&gt;Terminate an environment&lt;/li&gt;
&lt;/ul&gt;

&lt;h4 id=&quot;a-developer-can-sometimes-not&quot;&gt;A developer can sometimes not&lt;/h4&gt;
&lt;ul&gt;
  &lt;li&gt;Get the syntax for the Slack command correct&lt;/li&gt;
  &lt;li&gt;Troubleshoot why a particular server build failed&lt;/li&gt;
&lt;/ul&gt;

&lt;h4 id=&quot;a-developer-can-not&quot;&gt;A developer can not&lt;/h4&gt;
&lt;ul&gt;
  &lt;li&gt;Update the environment file ( .env ) for an application&lt;/li&gt;
  &lt;li&gt;Deploy a new application&lt;/li&gt;
&lt;/ul&gt;

&lt;h4 id=&quot;server-testing-process&quot;&gt;Server Testing Process&lt;/h4&gt;
&lt;p&gt;Like before, after working on code locally the developer moves that code to a server environment.  But the process of doing that is much simpler now.&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;Figure out what servers and code branches they needed for testing.&lt;/li&gt;
  &lt;li&gt;Run a Slack command to create the needed environment.&lt;/li&gt;
  &lt;li&gt;Proceed with testing.&lt;/li&gt;
  &lt;li&gt;Run a slack command to terminate the environment&lt;/li&gt;
&lt;/ul&gt;

&lt;h4 id=&quot;thinking-process&quot;&gt;Thinking Process&lt;/h4&gt;

&lt;p&gt;In the last few weeks I have been seeing the thinking process of many developers getting close to this:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;Creating a server development environment is easy&lt;/li&gt;
  &lt;li&gt;I can wait until I am ready for testing to create a server environment&lt;/li&gt;
  &lt;li&gt;If I need to make any changes, just terminate the environment and create a new one.&lt;/li&gt;
  &lt;li&gt;When I am done testing I can terminate the environment&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;I say &lt;strong&gt;getting close to&lt;/strong&gt; because thinking and habits don’t always change quickly.  Some of the developers are fully at the above thinking process.  Others are somewhere between the before ChatOps thinking and the above thinking.  Transitioning people’s thinking process, even if the change is to their benefit, still takes effort and time.  The transition of my developers thinking process was no different.  Next post will describe the transition process and what is needed to make sure it is successful.&lt;/p&gt;

&lt;h4 id=&quot;can-not-notes&quot;&gt;“Can Not” Notes&lt;/h4&gt;
&lt;p&gt;&lt;strong&gt;Troubleshoot why a particular server build failed&lt;/strong&gt; is was initially hard for a developer as ChatOps would return all the SaltStack failed states. This meant a simple error like incorrect branch would return 50+ lines of SaltStack JSON output due to all the states that failed because they were dependent on the git state. Filtering out these dependent failures cut out the noise.  Now a developer can pretty easily interpret the most common failure, typo in the branch to deploy, without understanding SaltStack or even knowing that the error message comes from SaltStack.  Here is an example:&lt;/p&gt;

&lt;div class=&quot;language-yaml highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;pi&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;git_|-xxxxxxx-repo_xxxxxxxxx_|-git@github.com:xxxxxxxx/xxxxxxxx.git_|-latest&quot;&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;pi&quot;&gt;{&lt;/span&gt;
 &lt;span class=&quot;nv&quot;&gt;   &quot;comment&quot;&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;No&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s&quot;&gt;revision&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s&quot;&gt;matching&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s&quot;&gt;'hotfix/x.xx.xx'&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s&quot;&gt;exists&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s&quot;&gt;in&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s&quot;&gt;the&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s&quot;&gt;remote&lt;/span&gt;&lt;span class=&quot;nv&quot;&gt; &lt;/span&gt;&lt;span class=&quot;s&quot;&gt;repository&quot;&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;,&lt;/span&gt;
 &lt;span class=&quot;nv&quot;&gt;   &quot;name&quot;&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;git@github.com:xxxxxxx/xxxxxxx.git&quot;&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;,&lt;/span&gt;
 &lt;span class=&quot;nv&quot;&gt;   &quot;start_time&quot;&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;s2&quot;&gt;&quot;&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;20:34:56.757768&quot;&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;,&lt;/span&gt;
 &lt;span class=&quot;nv&quot;&gt;   &quot;result&quot;&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;false&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;,&lt;/span&gt;
 &lt;span class=&quot;nv&quot;&gt;   &quot;duration&quot;&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;489.839&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;,&lt;/span&gt;
 &lt;span class=&quot;nv&quot;&gt;   &quot;__run_num__&quot;&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;nv&quot;&gt;3&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;,&lt;/span&gt;
 &lt;span class=&quot;nv&quot;&gt;   &quot;changes&quot;&lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;pi&quot;&gt;{}&lt;/span&gt;
 &lt;span class=&quot;nv&quot;&gt; &lt;/span&gt;&lt;span class=&quot;pi&quot;&gt;},&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;p&gt;Failures not caused by command syntax problems are usually not as clear and require Ops help to troubleshoot.  Fortunately these do not happen very often.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Deploying new applications&lt;/strong&gt; and &lt;strong&gt;updating environment files&lt;/strong&gt; are purposely not within the developer’s abilities.  The server development environment is a intermediate step between development and production. Therefore it is controlled to ensure it is a similar as possible to production and the tests run in this environment are valid tests of what will happen when this code gets deployed to production.&lt;/p&gt;
</description>
				<guid isPermaLink="true">http://todd.wells.ws/blog/chatops-at-6months-after/</guid>
			</item>
		
			<item>
				<title>Chatops at 6 months. How has it changed development. Before</title>
				<link>http://todd.wells.ws/blog/chatops-at-6months-before/</link>
				<pubDate>Mon, 15 Aug 2016 00:00:00 +0000</pubDate>
				<description>&lt;p&gt;Yesterday one of my developers created a server environment to test a feature branch and had a problem: one of the 4 servers in the environment did not get built. A short investigation showed a typo on the ChatOps command was the cause. When I explained what happened and suggested building just that one server the developer replied “I will just terminate the environment and recreate it.” Terminating and recreating servers is a normal/reasonable option for a situation like this, but for some reason that statement stuck in the back of my mind. A day later I realized why: it was said so casually. To the developer accomplishing what he said was easy. One Slack command would terminate the 3 servers and another command would build the 4 servers again. Why mess around with fixing a development environment that did not get built correctly the first time when you can create it again with 2 Slack commands.&lt;/p&gt;

&lt;p&gt;The above experience was the catalyst for me to look a the impact ChatOps has had on development and the developer’s thinking.  This is not going to discuss the technical aspects of making it happen.  That will have to be saved for another time.  But suffice it to say that ChatOps requires good IT Automation package ( I use &lt;a href=&quot;https://saltstack.com/&quot;&gt;SaltStack&lt;/a&gt; and a lot of work automating install/deployment to allow ChatOps to really shine.&lt;/p&gt;

&lt;p&gt;My “discovery” of ChatOps was 6 months ago and my &lt;a href=&quot;/blog/chatops-fomo/&quot;&gt;first post&lt;/a&gt; was five months ago.  At that time, the developer was really not able to do that much.&lt;/p&gt;

&lt;h4 id=&quot;a-developer-could&quot;&gt;A developer could&lt;/h4&gt;
&lt;ul&gt;
  &lt;li&gt;ssh to a development server and change the code branch&lt;/li&gt;
  &lt;li&gt;commit to a branch and a cron job would deploy the new branch&lt;/li&gt;
&lt;/ul&gt;

&lt;h4 id=&quot;a-developer-could-not&quot;&gt;A developer could not&lt;/h4&gt;
&lt;ul&gt;
  &lt;li&gt;Get a list of the current development servers&lt;/li&gt;
  &lt;li&gt;Get details about a development server ( app installed, code branch, API server pointed at)&lt;/li&gt;
  &lt;li&gt;Create a new development server&lt;/li&gt;
  &lt;li&gt;Configure the new server as a particular role ( web server, app server, … )&lt;/li&gt;
  &lt;li&gt;Install/configure an application&lt;/li&gt;
  &lt;li&gt;Setup the application to use a particular development version of an API.&lt;/li&gt;
  &lt;li&gt;Terminate an un-needed development server&lt;/li&gt;
&lt;/ul&gt;

&lt;h4 id=&quot;server-testing-process&quot;&gt;Server Testing Process&lt;/h4&gt;

&lt;p&gt;A web engineer would work on code locally and when they were ready to test it in a server environment follow a process like this:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;Figure out what servers and code branches they needed for testing.&lt;/li&gt;
  &lt;li&gt;Ask the Ops team member what development servers were currently built/active.&lt;/li&gt;
  &lt;li&gt;Ask around to see if any of the development web servers were currently unused.
    &lt;ul&gt;
      &lt;li&gt;If yes, ssh and change to the correct branch ( if they were command line savvy otherwise ask the Ops team member )&lt;/li&gt;
      &lt;li&gt;If no, either wait until it was available or ask Ops to create a new server.&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;Ask around to see if any of the development api servers were currently unused &lt;strong&gt;or&lt;/strong&gt; if all were in use was one of them on the needed branch of api.
    &lt;ul&gt;
      &lt;li&gt;If yes, ask Ops to point the web server at that api server. And in the case of unused ssh to server and change the branch ( if they were command line savvy otherwise ask Ops )&lt;/li&gt;
      &lt;li&gt;If no, either wait until it was available or ask Ops to create a new server.&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
  &lt;li&gt;Proceed with testing.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This process could take 30 minutes if all the planets aligned ( other developers responded promptly, servers were available, the Ops team member was available to repoint web servers ).  But I think on average it would take between several hours and two days.  And so a developer would have to plan ahead.  Back then I would frequently have developers say to me something like “I have a feature I am going to need to test next week.  Can you help me get the correct servers setup.”&lt;/p&gt;

&lt;h4 id=&quot;thinking-process&quot;&gt;Thinking Process&lt;/h4&gt;

&lt;p&gt;Based on my interactions with the developers during that time, the typical developer though process was:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;Getting a new feature onto a server is hard&lt;/li&gt;
  &lt;li&gt;I always need help from a busy Ops person&lt;/li&gt;
  &lt;li&gt;I have to coordinate with 15 other developers&lt;/li&gt;
  &lt;li&gt;Maybe I don’t need to test this feature on a server environment.  An untested hotfix might be easier.&lt;/li&gt;
  &lt;li&gt;It took so much work to get this environment setup as I want it so I am going to hold onto it even if I won’t be doing any testing in it for a few weeks.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;My &lt;a href=&quot;/blog/chatops-at-6months-after/&quot;&gt;next post&lt;/a&gt; will show how all of this has changed and the benefits it has provided to the developer and development workflow.&lt;/p&gt;
</description>
				<guid isPermaLink="true">http://todd.wells.ws/blog/chatops-at-6months-before/</guid>
			</item>
		
	</channel>
</rss>
