{"id":6062,"date":"2017-07-18T17:27:32","date_gmt":"2017-07-19T00:27:32","guid":{"rendered":"http:\/\/tommymaynard.com\/?p=6062"},"modified":"2022-08-13T13:27:48","modified_gmt":"2022-08-13T20:27:48","slug":"aws-userdata-multiple-run-framework-2017","status":"publish","type":"post","link":"https:\/\/tommymaynard.com\/aws-userdata-multiple-run-framework-2017\/","title":{"rendered":"AWS UserData Multiple Run Framework"},"content":{"rendered":"<p>In AWS, we can utilize the UserData section in EC2 to run PowerShell against our EC2 instances at launch. I&#8217;ve said it before; I love this option. As someone that speaks PowerShell with what likely amounts to first language fluency, there&#8217;s so much I do to automate my machine builds with CloudFormation, UserData, and PowerShell.<\/p>\n<p>I&#8217;ve begun to have a need to do various pieces of automation at different times. This is to say I need to have multiple instance restarts, as an instance is coming online, in order to separate different pieces of configuration and installation. You&#8217;ll figure out when you need that, too. And, when you do, you can use what I&#8217;ve dubbed the &#8220;multiple run framework for AWS.&#8221; But really, you call it what you want. That hardly matters.<\/p>\n<p>We have to remember, that by default, UserData only runs once. It&#8217;s when the EC2 instance launches for the first time. In the below example, we&#8217;re going to do three restarts and four separate code runs.<\/p>\n<p>Our UserData section first needs to add a function to memory. I&#8217;ve called it <code>Set-SystemForNextRun<\/code> and its purpose is to (1) create what I call a &#8220;passfile&#8221; to help indicate where we are in the automation process, (2) enable UserData to run the next time the service is restarted (this happens at instance restart, obviously), and (3) restart the EC2 instance. Let&#8217;s have a look. Its three parameters and three <code>If<\/code> statements; simple stuff.<\/p>\n<pre class=\"brush: powershell; title: ; notranslate\" title=\"\">\r\nFunction Set-SystemForNextRun {\r\n    Param (\r\n        &#x5B;string]$PassFile,\r\n        &#x5B;switch]$UserData,\r\n        &#x5B;switch]$Restart\r\n    )\r\n    If ($PassFile) {\r\n        &#x5B;System.Void](New-Item -Path &quot;$env:SystemDrive\\passfile$PassFile.txt&quot; -ItemType File)\r\n    }\r\n    If ($UserData) {\r\n        $Path = &quot;$env:ProgramFiles\\Amazon\\Ec2ConfigService\\Settings\\config.xml&quot;\r\n        &#x5B;xml]$ConfigXml = Get-Content -Path $Path\r\n        ($ConfigXml.Ec2ConfigurationSettings.Plugins.Plugin |\r\n            Where-Object -Property Name -eq 'Ec2HandleUserData').State = 'Enabled'\r\n        $ConfigXml.Save($Path)\r\n    }\r\n    If ($Restart) {\r\n        Restart-Computer -Force\r\n    }\r\n}\r\n<\/pre>\n<p>The above function accepts three parameters: <strong>PassFile<\/strong>, <strong>UserData<\/strong>, and <strong>Restart<\/strong>. <strong>PassFile<\/strong> accepts a string value. You&#8217;ll see how this works in the upcoming <code>If-ElseIf<\/code> example. <strong>UserData<\/strong> and <strong>Restart<\/strong> are switch parameters. If they&#8217;re included when the function is invoked, they&#8217;re True (<code>$true<\/code>), and if they&#8217;re not included, they&#8217;re False <code>($false<\/code>).<\/p>\n<p>Each of the three parameters has its own <code>If<\/code> statement within the <code>Set-SystemforNextRun<\/code> function. If <strong>PassFile<\/strong> is included, it creates a text file called <code>C:\\passfile&lt;ValuePassedIn&gt;.txt<\/code>. If <strong>UserData<\/strong> is included, it resets UserData to enabled (it effectively, checks the check box in the Ec2Config GUI). If <strong>Restart<\/strong> is included, it restarts the instance, right then and there.<\/p>\n<p>Now let&#8217;s take a look at the <code>If-ElseIf<\/code> statement that completes four code runs and three restarts. We&#8217;ll discuss it further below, but before we do, a little reminder. Our CloudFormation UserData PowerShell is going to contain the above <code>Set-SystemForNextRun<\/code> function, and something like you&#8217;ll see below after you&#8217;ve edited it for your needs.<\/p>\n<pre class=\"brush: powershell; title: ; notranslate\" title=\"\">\r\nIf (-Not(Test-Path -Path &quot;$env:SystemDrive\\passfile1.txt&quot;)) {\r\n\r\n    # Place code here (1).\r\n\r\n    # Invoke Set-SystemForNextRun function.\r\n    Set-SystemForNextRun -PassFile '1' -UserData -Restart\r\n\r\n} ElseIf (-Not(Test-Path -Path &quot;$env:SystemDrive\\passfile2.txt&quot;)) {\r\n\r\n    # Place code here (2).\r\n\r\n    # Invoke Set-SystemForNextRun function.\r\n    Set-SystemForNextRun -PassFile '2' -UserData -Restart\r\n\r\n} ElseIf (-Not(Test-Path -Path &quot;$env:SystemDrive\\passfile3.txt&quot;)) {\r\n\r\n    # Place code here (3).\r\n\r\n    # Invoke Set-SystemForNextRun function.\r\n    Set-SystemForNextRun -PassFile '3' -UserData -Restart\r\n\r\n} ElseIf (-Not(Test-Path -Path &quot;$env:SystemDrive\\passfile4.txt&quot;)) {\r\n\r\n    # Place code here (4).\r\n\r\n    # Invoke Set-SystemForNextRun function.\r\n    Set-SystemForNextRun -PassFile '4'\r\n\r\n}\r\n<\/pre>\n<p>In line 1, we test whether or not the file <code>C:\\passfile1.txt<\/code> exists. If it doesn&#8217;t exist, we run the code in the <code>If<\/code> portion. This will run whatever PowerShell we add to that section. Then it&#8217;ll pass 1 to the <code>Set-SystemForNextRun<\/code> function to have <code>C:\\passfile01.txt<\/code> created. Additionally, because the <strong>UserData<\/strong> and <strong>Restart<\/strong> parameters are included, it&#8217;ll reset UserData to enabled, and restart the EC2 instance. Because the <code>C:\\passfile1.txt<\/code> file now exists, the next time the UserData runs, it&#8217;ll skip the <code>If<\/code> portion and evaluate the first <code>ElseIf<\/code> statement.<\/p>\n<p>This <code>ElseIf<\/code> statement determines whether or not the <code>C:\\passfile<strong>2<\/strong>.txt<\/code> file exists, or not. If it doesn&#8217;t, and it won&#8217;t after the first restart, then the code in this <code>ElseIf<\/code> will run. When it&#8217;s done, it&#8217;ll create the <code>passfile2.txt<\/code> file, reset UserData, and restart the instance. It&#8217;ll do this for the second <code>ElseIf<\/code> (third code run), and the final <code>ElseIf<\/code> (fourth code run), as well. Notice that the final invocation of the <code>Set-SystemForNextRun<\/code> function doesn&#8217;t enable UserData or Restart the instance. Be sure to add those if you need either completed after the final <code>ElseIf<\/code> completes.<\/p>\n<p>And that&#8217;s it. At this point in time, I always use my <code>Set-SystemForNextRun<\/code> function and a properly written <code>If-ElseIf<\/code> statement to separate the configuration and installation around the necessary amount of instance restarts. In closing, keep in mind that deleting those pass files from the root of the <code>C:\\<\/code> drive is <strong>not<\/strong> something you&#8217;ll likely want to do. In time, I may do a rewrite that stores entries in the Registry perhaps, so there&#8217;s less probability that one of these files might be removed by someone.<\/p>\n<p>Either way, I hope this is helpful for someone! If you&#8217;re in this space&#8212;AWS, CloudFormation, UserData, and PowerShell&#8212;then chances are good that at some point you&#8217;re going to want to restart an instance, and then continue to configure it.<\/p>\n<p><a href=\"http:\/\/tommymaynard.com\/aws-userdata-multiple-run-framework-part-ii-2017\/\">Read II<\/a><\/p>\n","protected":false},"excerpt":{"rendered":"<p>In AWS, we can utilize the UserData section in EC2 to run PowerShell against our EC2 instances at launch. I&#8217;ve said it before; I love this option. As someone that speaks PowerShell with what likely amounts to first language fluency, there&#8217;s so much I do to automate my machine builds with CloudFormation, UserData, and PowerShell. [&hellip;]<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"jetpack_post_was_ever_published":false,"_jetpack_newsletter_access":"","_jetpack_dont_email_post_to_subs":false,"_jetpack_newsletter_tier_id":0,"_jetpack_memberships_contains_paywalled_content":false,"_jetpack_memberships_contains_paid_content":false,"footnotes":"","jetpack_publicize_message":"","jetpack_publicize_feature_enabled":true,"jetpack_social_post_already_shared":true,"jetpack_social_options":{"image_generator_settings":{"template":"highway","default_image_id":0,"font":"","enabled":false},"version":2}},"categories":[420,2],"tags":[388,464,379,483,465],"class_list":["post-6062","post","type-post","status-publish","format-standard","hentry","category-aws","category-quick-learn","tag-aws","tag-cloudformation","tag-if-elseif","tag-set-systemfornextrun","tag-userdata"],"yoast_head":"<!-- This site is optimized with the Yoast SEO plugin v27.2 - https:\/\/yoast.com\/product\/yoast-seo-wordpress\/ -->\n<title>AWS UserData Multiple Run Framework - tommymaynard.com<\/title>\n<meta name=\"robots\" content=\"index, follow, max-snippet:-1, max-image-preview:large, max-video-preview:-1\" \/>\n<link rel=\"canonical\" href=\"https:\/\/tommymaynard.com\/aws-userdata-multiple-run-framework-2017\/\" \/>\n<meta property=\"og:locale\" content=\"en_US\" \/>\n<meta property=\"og:type\" content=\"article\" \/>\n<meta property=\"og:title\" content=\"AWS UserData Multiple Run Framework - tommymaynard.com\" \/>\n<meta property=\"og:description\" content=\"In AWS, we can utilize the UserData section in EC2 to run PowerShell against our EC2 instances at launch. I&#8217;ve said it before; I love this option. As someone that speaks PowerShell with what likely amounts to first language fluency, there&#8217;s so much I do to automate my machine builds with CloudFormation, UserData, and PowerShell. [&hellip;]\" \/>\n<meta property=\"og:url\" content=\"https:\/\/tommymaynard.com\/aws-userdata-multiple-run-framework-2017\/\" \/>\n<meta property=\"og:site_name\" content=\"tommymaynard.com\" \/>\n<meta property=\"article:published_time\" content=\"2017-07-19T00:27:32+00:00\" \/>\n<meta property=\"article:modified_time\" content=\"2022-08-13T20:27:48+00:00\" \/>\n<meta name=\"author\" content=\"Tommy Maynard\" \/>\n<meta name=\"twitter:card\" content=\"summary_large_image\" \/>\n<meta name=\"twitter:label1\" content=\"Written by\" \/>\n\t<meta name=\"twitter:data1\" content=\"Tommy Maynard\" \/>\n\t<meta name=\"twitter:label2\" content=\"Est. reading time\" \/>\n\t<meta name=\"twitter:data2\" content=\"4 minutes\" \/>\n<script type=\"application\/ld+json\" class=\"yoast-schema-graph\">{\"@context\":\"https:\/\/schema.org\",\"@graph\":[{\"@type\":\"Article\",\"@id\":\"https:\/\/tommymaynard.com\/aws-userdata-multiple-run-framework-2017\/#article\",\"isPartOf\":{\"@id\":\"https:\/\/tommymaynard.com\/aws-userdata-multiple-run-framework-2017\/\"},\"author\":{\"name\":\"Tommy Maynard\",\"@id\":\"https:\/\/tommymaynard.com\/#\/schema\/person\/c74505a44d3d93dc7f82a08502d81ff8\"},\"headline\":\"AWS UserData Multiple Run Framework\",\"datePublished\":\"2017-07-19T00:27:32+00:00\",\"dateModified\":\"2022-08-13T20:27:48+00:00\",\"mainEntityOfPage\":{\"@id\":\"https:\/\/tommymaynard.com\/aws-userdata-multiple-run-framework-2017\/\"},\"wordCount\":862,\"commentCount\":0,\"publisher\":{\"@id\":\"https:\/\/tommymaynard.com\/#\/schema\/person\/c74505a44d3d93dc7f82a08502d81ff8\"},\"keywords\":[\"AWS\",\"CloudFormation\",\"If-ElseIf\",\"Set-SystemForNextRun\",\"UserData\"],\"articleSection\":[\"AWS\",\"Quick Learn\"],\"inLanguage\":\"en-US\",\"potentialAction\":[{\"@type\":\"CommentAction\",\"name\":\"Comment\",\"target\":[\"https:\/\/tommymaynard.com\/aws-userdata-multiple-run-framework-2017\/#respond\"]}]},{\"@type\":\"WebPage\",\"@id\":\"https:\/\/tommymaynard.com\/aws-userdata-multiple-run-framework-2017\/\",\"url\":\"https:\/\/tommymaynard.com\/aws-userdata-multiple-run-framework-2017\/\",\"name\":\"AWS UserData Multiple Run Framework - tommymaynard.com\",\"isPartOf\":{\"@id\":\"https:\/\/tommymaynard.com\/#website\"},\"datePublished\":\"2017-07-19T00:27:32+00:00\",\"dateModified\":\"2022-08-13T20:27:48+00:00\",\"breadcrumb\":{\"@id\":\"https:\/\/tommymaynard.com\/aws-userdata-multiple-run-framework-2017\/#breadcrumb\"},\"inLanguage\":\"en-US\",\"potentialAction\":[{\"@type\":\"ReadAction\",\"target\":[\"https:\/\/tommymaynard.com\/aws-userdata-multiple-run-framework-2017\/\"]}]},{\"@type\":\"BreadcrumbList\",\"@id\":\"https:\/\/tommymaynard.com\/aws-userdata-multiple-run-framework-2017\/#breadcrumb\",\"itemListElement\":[{\"@type\":\"ListItem\",\"position\":1,\"name\":\"Home\",\"item\":\"https:\/\/tommymaynard.com\/\"},{\"@type\":\"ListItem\",\"position\":2,\"name\":\"AWS UserData Multiple Run Framework\"}]},{\"@type\":\"WebSite\",\"@id\":\"https:\/\/tommymaynard.com\/#website\",\"url\":\"https:\/\/tommymaynard.com\/\",\"name\":\"tommymaynard.com\",\"description\":\"A PowerShell Resource. Since June 2014.\",\"publisher\":{\"@id\":\"https:\/\/tommymaynard.com\/#\/schema\/person\/c74505a44d3d93dc7f82a08502d81ff8\"},\"potentialAction\":[{\"@type\":\"SearchAction\",\"target\":{\"@type\":\"EntryPoint\",\"urlTemplate\":\"https:\/\/tommymaynard.com\/?s={search_term_string}\"},\"query-input\":{\"@type\":\"PropertyValueSpecification\",\"valueRequired\":true,\"valueName\":\"search_term_string\"}}],\"inLanguage\":\"en-US\"},{\"@type\":[\"Person\",\"Organization\"],\"@id\":\"https:\/\/tommymaynard.com\/#\/schema\/person\/c74505a44d3d93dc7f82a08502d81ff8\",\"name\":\"Tommy Maynard\",\"image\":{\"@type\":\"ImageObject\",\"inLanguage\":\"en-US\",\"@id\":\"https:\/\/secure.gravatar.com\/avatar\/ff5e885ce365c2b895df63b9b0d98a7f1a1d1421def6bfb59336a95460fc2329?s=96&d=mm&r=g\",\"url\":\"https:\/\/secure.gravatar.com\/avatar\/ff5e885ce365c2b895df63b9b0d98a7f1a1d1421def6bfb59336a95460fc2329?s=96&d=mm&r=g\",\"contentUrl\":\"https:\/\/secure.gravatar.com\/avatar\/ff5e885ce365c2b895df63b9b0d98a7f1a1d1421def6bfb59336a95460fc2329?s=96&d=mm&r=g\",\"caption\":\"Tommy Maynard\"},\"logo\":{\"@id\":\"https:\/\/secure.gravatar.com\/avatar\/ff5e885ce365c2b895df63b9b0d98a7f1a1d1421def6bfb59336a95460fc2329?s=96&d=mm&r=g\"},\"description\":\"Windows PowerShell enthusiast with over 15 years of Information Technology experience.\"}]}<\/script>\n<!-- \/ Yoast SEO plugin. -->","yoast_head_json":{"title":"AWS UserData Multiple Run Framework - tommymaynard.com","robots":{"index":"index","follow":"follow","max-snippet":"max-snippet:-1","max-image-preview":"max-image-preview:large","max-video-preview":"max-video-preview:-1"},"canonical":"https:\/\/tommymaynard.com\/aws-userdata-multiple-run-framework-2017\/","og_locale":"en_US","og_type":"article","og_title":"AWS UserData Multiple Run Framework - tommymaynard.com","og_description":"In AWS, we can utilize the UserData section in EC2 to run PowerShell against our EC2 instances at launch. I&#8217;ve said it before; I love this option. As someone that speaks PowerShell with what likely amounts to first language fluency, there&#8217;s so much I do to automate my machine builds with CloudFormation, UserData, and PowerShell. [&hellip;]","og_url":"https:\/\/tommymaynard.com\/aws-userdata-multiple-run-framework-2017\/","og_site_name":"tommymaynard.com","article_published_time":"2017-07-19T00:27:32+00:00","article_modified_time":"2022-08-13T20:27:48+00:00","author":"Tommy Maynard","twitter_card":"summary_large_image","twitter_misc":{"Written by":"Tommy Maynard","Est. reading time":"4 minutes"},"schema":{"@context":"https:\/\/schema.org","@graph":[{"@type":"Article","@id":"https:\/\/tommymaynard.com\/aws-userdata-multiple-run-framework-2017\/#article","isPartOf":{"@id":"https:\/\/tommymaynard.com\/aws-userdata-multiple-run-framework-2017\/"},"author":{"name":"Tommy Maynard","@id":"https:\/\/tommymaynard.com\/#\/schema\/person\/c74505a44d3d93dc7f82a08502d81ff8"},"headline":"AWS UserData Multiple Run Framework","datePublished":"2017-07-19T00:27:32+00:00","dateModified":"2022-08-13T20:27:48+00:00","mainEntityOfPage":{"@id":"https:\/\/tommymaynard.com\/aws-userdata-multiple-run-framework-2017\/"},"wordCount":862,"commentCount":0,"publisher":{"@id":"https:\/\/tommymaynard.com\/#\/schema\/person\/c74505a44d3d93dc7f82a08502d81ff8"},"keywords":["AWS","CloudFormation","If-ElseIf","Set-SystemForNextRun","UserData"],"articleSection":["AWS","Quick Learn"],"inLanguage":"en-US","potentialAction":[{"@type":"CommentAction","name":"Comment","target":["https:\/\/tommymaynard.com\/aws-userdata-multiple-run-framework-2017\/#respond"]}]},{"@type":"WebPage","@id":"https:\/\/tommymaynard.com\/aws-userdata-multiple-run-framework-2017\/","url":"https:\/\/tommymaynard.com\/aws-userdata-multiple-run-framework-2017\/","name":"AWS UserData Multiple Run Framework - tommymaynard.com","isPartOf":{"@id":"https:\/\/tommymaynard.com\/#website"},"datePublished":"2017-07-19T00:27:32+00:00","dateModified":"2022-08-13T20:27:48+00:00","breadcrumb":{"@id":"https:\/\/tommymaynard.com\/aws-userdata-multiple-run-framework-2017\/#breadcrumb"},"inLanguage":"en-US","potentialAction":[{"@type":"ReadAction","target":["https:\/\/tommymaynard.com\/aws-userdata-multiple-run-framework-2017\/"]}]},{"@type":"BreadcrumbList","@id":"https:\/\/tommymaynard.com\/aws-userdata-multiple-run-framework-2017\/#breadcrumb","itemListElement":[{"@type":"ListItem","position":1,"name":"Home","item":"https:\/\/tommymaynard.com\/"},{"@type":"ListItem","position":2,"name":"AWS UserData Multiple Run Framework"}]},{"@type":"WebSite","@id":"https:\/\/tommymaynard.com\/#website","url":"https:\/\/tommymaynard.com\/","name":"tommymaynard.com","description":"A PowerShell Resource. Since June 2014.","publisher":{"@id":"https:\/\/tommymaynard.com\/#\/schema\/person\/c74505a44d3d93dc7f82a08502d81ff8"},"potentialAction":[{"@type":"SearchAction","target":{"@type":"EntryPoint","urlTemplate":"https:\/\/tommymaynard.com\/?s={search_term_string}"},"query-input":{"@type":"PropertyValueSpecification","valueRequired":true,"valueName":"search_term_string"}}],"inLanguage":"en-US"},{"@type":["Person","Organization"],"@id":"https:\/\/tommymaynard.com\/#\/schema\/person\/c74505a44d3d93dc7f82a08502d81ff8","name":"Tommy Maynard","image":{"@type":"ImageObject","inLanguage":"en-US","@id":"https:\/\/secure.gravatar.com\/avatar\/ff5e885ce365c2b895df63b9b0d98a7f1a1d1421def6bfb59336a95460fc2329?s=96&d=mm&r=g","url":"https:\/\/secure.gravatar.com\/avatar\/ff5e885ce365c2b895df63b9b0d98a7f1a1d1421def6bfb59336a95460fc2329?s=96&d=mm&r=g","contentUrl":"https:\/\/secure.gravatar.com\/avatar\/ff5e885ce365c2b895df63b9b0d98a7f1a1d1421def6bfb59336a95460fc2329?s=96&d=mm&r=g","caption":"Tommy Maynard"},"logo":{"@id":"https:\/\/secure.gravatar.com\/avatar\/ff5e885ce365c2b895df63b9b0d98a7f1a1d1421def6bfb59336a95460fc2329?s=96&d=mm&r=g"},"description":"Windows PowerShell enthusiast with over 15 years of Information Technology experience."}]}},"jetpack_publicize_connections":[],"jetpack_featured_media_url":"","jetpack_shortlink":"https:\/\/wp.me\/p8mce3-1zM","jetpack_sharing_enabled":true,"_links":{"self":[{"href":"https:\/\/tommymaynard.com\/wp-json\/wp\/v2\/posts\/6062","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/tommymaynard.com\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/tommymaynard.com\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/tommymaynard.com\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/tommymaynard.com\/wp-json\/wp\/v2\/comments?post=6062"}],"version-history":[{"count":6,"href":"https:\/\/tommymaynard.com\/wp-json\/wp\/v2\/posts\/6062\/revisions"}],"predecessor-version":[{"id":13031,"href":"https:\/\/tommymaynard.com\/wp-json\/wp\/v2\/posts\/6062\/revisions\/13031"}],"wp:attachment":[{"href":"https:\/\/tommymaynard.com\/wp-json\/wp\/v2\/media?parent=6062"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/tommymaynard.com\/wp-json\/wp\/v2\/categories?post=6062"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/tommymaynard.com\/wp-json\/wp\/v2\/tags?post=6062"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}