{"id":43,"date":"2013-11-22T05:14:06","date_gmt":"2013-11-22T05:14:06","guid":{"rendered":"http:\/\/blogs.nd.edu\/devops\/?p=43"},"modified":"2013-11-22T05:26:32","modified_gmt":"2013-11-22T05:26:32","slug":"scripting-aws-with-boto","status":"publish","type":"post","link":"https:\/\/sites.nd.edu\/devops\/2013\/11\/22\/scripting-aws-with-boto\/","title":{"rendered":"Scripting AWS with Boto"},"content":{"rendered":"<p>It&#8217;s pretty easy to get yourself an Amazon Web Services account, log into the web console, and start firing up instances left and right. \u00a0It feels awesome, and it should, because you are doing a lot of cool things with just a few mouse clicks. \u00a0Soon, however, that buzz is going to wear off, because working this way is not sustainable at scale, and it is not easily repeatable. \u00a0If you want to get to #DevOps nirvana, creating and destroying instances automatically with each branch commit, you are going to have to abandon that GUI and get to the command line.\u00a0<em><br \/>\n<\/em><\/p>\n<p>So you google up &#8220;aws command line,&#8221; and behold: <a href=\"http:\/\/aws.amazon.com\/cli\/\">AWS Command Line Interface.<\/a>\u00a0 These tools are great, and probably worth a blog post in themselves. \u00a0They are an attempt to provide a unified CLI to replace prior offerings that were unique to each service (e.g., an ec2 tool, a CloudFormation tool), and they let you do quite a bit from the command line. But wait, because if you want to control everything in AWS while also leveraging the power of a mature scripting language, you want\u00a0<a href=\"http:\/\/aws.amazon.com\/sdkforpython\/\">Boto for Python<\/a>.<\/p>\n<p>First, we&#8217;ll need python. \u00a0Mac and Linux users are good to go; Windows users will need to <a href=\"http:\/\/docs.python-guide.org\/en\/latest\/starting\/install\/win\/\">install it first<\/a>. \u00a0We&#8217;re also going to need the python package manager, called pip. \u00a0For some reason it doesn&#8217;t come with python, but there&#8217;s a python tool that&#8217;ll fetch it for us. \u00a0This worked on my mac:<\/p>\n<pre>$ sudo easy_install pip\r\n\r\n<\/pre>\n<p>Okay, now you&#8217;d better\u00a0<a href=\"http:\/\/www.python.org\/about\/gettingstarted\/\">learn some basic Python syntax<\/a>. Go ahead; I&#8217;ll wait.<\/p>\n<p>Good. \u00a0Now we&#8217;re ready. \u00a0Install the boto SDK with pip:<\/p>\n<pre>$ pip install boto\r\n\r\n<\/pre>\n<p>Then create a file called .boto in your home directory with the following contents:<\/p>\n<pre>[Credentials]\r\naws_access_key_id = YOUR_ACCESS_KEY_ID\r\naws_secret_access_key = YOUR_SECRET_ACCESS_KEY\r\n\r\n<\/pre>\n<p>Where to get those credentials? \u00a0<a href=\"http:\/\/www.cloudberrylab.com\/blog\/how-to-find-your-aws-access-key-id-and-secret-access-key-and-register-with-cloudberry-s3-explorer\/\">I&#8217;ll let this guy tell you<\/a>.<\/p>\n<p>Now we&#8217;re ready for some examples. \u00a0Readers in the OIT can check out the <a href=\"https:\/\/oit-svn.cc.nd.edu\/es\/master\/trunk\/devops\/boto\">full scripts here<\/a>. \u00a0Let&#8217;s start by making a Virtual Private Cloud, aka a virtual data center. \u00a0VPCs are constructs that, despite their relative importance in a cloud infrastructure, are quite simple to create. \u00a0From create_vpc.py:<\/p>\n<pre>#!\/usr\/bin\/python\r\nimport boto\r\nfrom boto.vpc import VPCConnection\r\n\r\n<\/pre>\n<p>You&#8217;ve got the typical shebang directive, which invokes the python interpreter and lets us execute the script directly. \u00a0Then the important part: importing boto. \u00a0The first import is really all you need, but if you want to be able to reference parts of the boto library without fully qualifying them, you&#8217;ll want to do something like line 3 there. \u00a0This lets us reference &#8220;VPCConnection&#8221; instead of having to say &#8220;boto.vpc.VPCConnection.&#8221;<\/p>\n<p>The parameters for creating a VPC are&#8230;<\/p>\n<ul>\n<li><strong>name<\/strong>: friendly name for the VPC (we&#8217;ll use VPC_ND_Datacenter. \u00a0This is actually optional, but we&#8217;re going to tag the VPC with a &#8220;Name&#8221; key after we make it)<\/li>\n<li><strong>cidr_block<\/strong>: a\u00a0<a href=\"http:\/\/en.wikipedia.org\/wiki\/CIDR\" target=\"_blank\">Classless Inter-Domain Routing<\/a>\u00a0block, of course (alright, Bob Winding helped me. \u00a0I&#8217;ll update with clarification later) Example:\u00a010.0.0.0\/16<\/li>\n<li><strong>tenancy<\/strong>: default \/ dedicated. \u00a0Dedicated requires you to pay a flat fee to Amazon, but it means you never have to worry that you&#8217;re sharing hardware with another AWS customer.<\/li>\n<li><strong>dry_run<\/strong>: set to True if you want to run the command without persisting the result<\/li>\n<\/ul>\n<p>&nbsp;<\/p>\n<p>Basically the cidr_block is the only thing you really even need. \u00a0I told you it was a simple construct! \u00a0Note that variables exist for each in the create_vpc line below.<\/p>\n<pre>c = VPCConnection()\r\ndatacenters = c.get_all_vpcs(filters=[(\"cidrBlock\", cidr)])\r\nif not len(datacenters):\r\n    datacenter = c.create_vpc( cidr_block=cidr, instance_tenancy=tenancy, dry_run=dryrun )\r\n     print datacenter\r\nelse:\r\n     datacenter = datacenters.pop(0)\r\n     print \"Requested VPC already exists!\"\r\n\r\ndatacenter.add_tag(\"Name\", \"My awesome VPC\")\r\n\r\n<\/pre>\n<p>First, get the VPCConnection object, which has the methods we&#8217;ll use to list\/create a VPC. \u00a0Note that this is available due to the &#8220;from..import&#8221; above. \u00a0Next, use the method &#8220;get_all_vpcs&#8221; with a filter to check that no VPC with this cidr block already exists.<\/p>\n<p>If that list is empty, we&#8217;ll call create_vpc. \u00a0Otherwise, we&#8217;ll print a message that it already exists. \u00a0We can also pop the first item off the list, and that&#8217;s the object representing the existing VPC. \u00a0Finally, we&#8217;ll add a tag to name our VPC.<\/p>\n<p>This stuff is that easy.<\/p>\n<p>Once you divide that VPC into subnets and create a security group or two, how about creating an actual ec2 instance?<\/p>\n<pre>ec2 = EC2Connection()\r\n\r\nreservation = new_instance ec2.run_instances(\r\nimage_id='ami-83e4bcea',\r\nsubnet_id='MY_SUBNET_ID',\r\ninstance_type='t1.micro',\r\nsecurity_group_ids=['SOME_SECURITYGROUP_ID', 'ANOTHER_ONE')\r\n\r\nreservation.instances[0].add_tag(\"Name\", \"world's greatest ec2 instance\")\r\n\r\n<\/pre>\n<p>Similar setup here. \u00a0We&#8217;re using the EC2Connection object instead. \u00a0Note that the run_instances method doesn&#8217;t pass back the instance directly, but gives you a &#8220;reservation&#8221; object that can apparently have an array of instances. \u00a0AFAIK you can only create one at a time with this method. \u00a0Anyway, we tag it and boom! \u00a0Here&#8217;s our instance, initializing:<\/p>\n<div id=\"attachment_99\" style=\"width: 310px\" class=\"wp-caption alignnone\"><a href=\"http:\/\/blogs.nd.edu\/devops\/files\/2013\/11\/Screen-Shot-2013-11-21-at-11.54.09-PM.png\"><img loading=\"lazy\" decoding=\"async\" aria-describedby=\"caption-attachment-99\" class=\"size-medium wp-image-99\" alt=\"i could do this all day\" src=\"http:\/\/blogs.nd.edu\/devops\/files\/2013\/11\/Screen-Shot-2013-11-21-at-11.54.09-PM-300x73.png\" width=\"300\" height=\"73\" srcset=\"https:\/\/sites.nd.edu\/devops\/files\/2013\/11\/Screen-Shot-2013-11-21-at-11.54.09-PM-300x73.png 300w, https:\/\/sites.nd.edu\/devops\/files\/2013\/11\/Screen-Shot-2013-11-21-at-11.54.09-PM-500x122.png 500w, https:\/\/sites.nd.edu\/devops\/files\/2013\/11\/Screen-Shot-2013-11-21-at-11.54.09-PM.png 903w\" sizes=\"auto, (max-width: 300px) 100vw, 300px\" \/><\/a><p id=\"caption-attachment-99\" class=\"wp-caption-text\">and to think you wanted to click buttons<\/p><\/div>\n<p>We&#8217;ve got more work to do before we can create this instance and provision it via puppet, deploy applications on it, run services, and make it available as a Notre Dame domain. \u00a0Still, this is a great start. \u00a0Maybe some OIT folks want to jump in and help! \u00a0Talk to me, and be sure to check out the <a href=\"http:\/\/boto.readthedocs.org\/en\/latest\/index.html\">full boto API reference<\/a> for all available methods.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>It&#8217;s pretty easy to get yourself an Amazon Web Services account, log into the web console, and start firing up instances left and right. \u00a0It feels awesome, and it should, because you are doing a lot of cool things with &hellip; <a href=\"https:\/\/sites.nd.edu\/devops\/2013\/11\/22\/scripting-aws-with-boto\/\">Continue reading <span class=\"meta-nav\">&rarr;<\/span><\/a><\/p>\n","protected":false},"author":1550,"featured_media":0,"comment_status":"closed","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[1],"tags":[],"class_list":["post-43","post","type-post","status-publish","format-standard","hentry","category-uncategorized"],"_links":{"self":[{"href":"https:\/\/sites.nd.edu\/devops\/wp-json\/wp\/v2\/posts\/43","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/sites.nd.edu\/devops\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/sites.nd.edu\/devops\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/sites.nd.edu\/devops\/wp-json\/wp\/v2\/users\/1550"}],"replies":[{"embeddable":true,"href":"https:\/\/sites.nd.edu\/devops\/wp-json\/wp\/v2\/comments?post=43"}],"version-history":[{"count":14,"href":"https:\/\/sites.nd.edu\/devops\/wp-json\/wp\/v2\/posts\/43\/revisions"}],"predecessor-version":[{"id":202,"href":"https:\/\/sites.nd.edu\/devops\/wp-json\/wp\/v2\/posts\/43\/revisions\/202"}],"wp:attachment":[{"href":"https:\/\/sites.nd.edu\/devops\/wp-json\/wp\/v2\/media?parent=43"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/sites.nd.edu\/devops\/wp-json\/wp\/v2\/categories?post=43"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/sites.nd.edu\/devops\/wp-json\/wp\/v2\/tags?post=43"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}