{"id":2107,"date":"2020-11-30T21:44:21","date_gmt":"2020-11-30T18:44:21","guid":{"rendered":"https:\/\/artem.services\/?p=2105"},"modified":"2020-12-07T15:05:27","modified_gmt":"2020-12-07T12:05:27","slug":"2107","status":"publish","type":"post","link":"https:\/\/artem.services\/?p=2107&lang=en","title":{"rendered":"Lambda &#8212; For stopping EC2 instances, RDS instances and ASG downscale in all regions"},"content":{"rendered":"<p><img loading=\"lazy\" class=\"aligncenter size-full wp-image-214\" src=\"https:\/\/artem.services\/wp-content\/uploads\/2018\/11\/AWS-Logo.png\" alt=\"\" width=\"975\" height=\"450\" srcset=\"https:\/\/artem.services\/wp-content\/uploads\/2018\/11\/AWS-Logo.png 975w, https:\/\/artem.services\/wp-content\/uploads\/2018\/11\/AWS-Logo-300x138.png 300w, https:\/\/artem.services\/wp-content\/uploads\/2018\/11\/AWS-Logo-768x354.png 768w, https:\/\/artem.services\/wp-content\/uploads\/2018\/11\/AWS-Logo-954x440.png 954w\" sizes=\"(max-width: 975px) 100vw, 975px\" \/><\/p>\n<p>This Python script gets a list of all regions, finds <strong>EC2 instances<\/strong>, <strong>RDS instances<\/strong> and <strong>ASG<\/strong> in them, and if there is no &quot;<strong>prevent_stop<\/strong>&quot; tag equal to &quot;<strong>true<\/strong>&quot; on the resource, then it stops this resource, and in the case of <strong>ASG<\/strong> it scaledown it to <strong>0<\/strong>.<\/p>\n<h3>main.py:<\/h3>\n<pre class=\"brush: python; title: ; notranslate\" title=\"\">\r\nimport boto3\r\n\r\ncustom_ec2_filter = [\r\n    {\r\n        'Name': 'instance-state-name',\r\n        'Values': ['running', 'pending']\r\n    }\r\n]\r\n\r\n# Get list of EC2 regions\r\nec2 = boto3.client('ec2')\r\nregions = [region['RegionName'] for region in ec2.describe_regions()['Regions']]\r\n\r\ndef main(event, context):\r\n    for region in regions:\r\n        print(&quot;Region: &quot; + str(region))\r\n        # ASG\r\n        print(&quot;Searching for ASG...&quot;)\r\n        asg = boto3.client('autoscaling', region_name = region)\r\n        asg_list = [asg_name['AutoScalingGroupName'] for asg_name in asg.describe_auto_scaling_groups()['AutoScalingGroups']]\r\n        for asg_name in asg_list:\r\n            api_response = asg.describe_auto_scaling_groups(\r\n                AutoScalingGroupNames = [\r\n                    asg_name,\r\n                ]\r\n            )\r\n            tags = (api_response[&quot;AutoScalingGroups&quot;][0][&quot;Tags&quot;])\r\n            asg_scaledown = False \r\n            if 'prevent_stop' not in [tag['Key'] for tag in tags]:\r\n                asg_scaledown = True\r\n            else:\r\n                for tag in tags:\r\n                    if tag[&quot;Key&quot;] == 'prevent_stop' and tag[&quot;Value&quot;] != 'true':\r\n                        asg_scaledown = True\r\n            if asg_scaledown == True:\r\n                minSize = (api_response[&quot;AutoScalingGroups&quot;][0][&quot;MinSize&quot;])\r\n                maxSize = (api_response[&quot;AutoScalingGroups&quot;][0][&quot;MaxSize&quot;])\r\n                desiredCapacity = (api_response[&quot;AutoScalingGroups&quot;][0][&quot;DesiredCapacity&quot;])\r\n                if minSize != 0 or maxSize != 0 or desiredCapacity != 0:\r\n                    print(&quot;Scalling down ASG: &quot; + str(asg_name))\r\n                    asg.update_auto_scaling_group(\r\n                        AutoScalingGroupName = asg_name,\r\n                        MinSize = 0,\r\n                        MaxSize = 0,\r\n                        DesiredCapacity = 0\r\n                    )\r\n        # EC2 Instances\r\n        print(&quot;Searching for running instances...&quot;)\r\n        ec2 = boto3.resource('ec2', region_name = region)\r\n        instances_list = ec2.instances.filter(Filters = custom_ec2_filter)\r\n        for instance in instances_list:\r\n            if 'prevent_stop' not in [tag['Key'] for tag in instance.tags]:\r\n                print(&quot;Stopping instance: &quot; + str(instance.id))\r\n                instance.stop()\r\n            else:\r\n                for tag in instance.tags:\r\n                    if tag[&quot;Key&quot;] == 'prevent_stop' and tag[&quot;Value&quot;] != 'true':\r\n                        print(&quot;Stopping instance: &quot; + str(instance.id))\r\n                        instance.stop()\r\n        # RDS\r\n        print(&quot;Searching for running RDS instances...&quot;)\r\n        rds = boto3.client('rds', region_name = region)\r\n        rds_list = [instance['DBInstanceIdentifier'] for instance in rds.describe_db_instances()['DBInstances']]\r\n        for instance in rds_list:\r\n            arn = rds.describe_db_instances(DBInstanceIdentifier = instance)['DBInstances'][0]['DBInstanceArn']\r\n            tags = rds.list_tags_for_resource(ResourceName = arn)['TagList']\r\n            stop_instance = False\r\n            if 'prevent_stop' not in [tag['Key'] for tag in tags]:\r\n                stop_instance = True\r\n            else:\r\n                for tag in tags:\r\n                    if tag[&quot;Key&quot;] == 'prevent_stop' and tag[&quot;Value&quot;] != 'true':\r\n                        stop_instance = True\r\n            if stop_instance == True:\r\n                instance_status = rds.describe_db_instances(DBInstanceIdentifier = instance)['DBInstances'][0]['DBInstanceStatus']\r\n                if instance_status != &quot;stopping&quot; and instance_status != &quot;stopped&quot;:\r\n                    engine = rds.describe_db_instances(DBInstanceIdentifier = instance)['DBInstances'][0]['Engine']\r\n                    print(&quot;Engine: &quot; + str(engine))\r\n                    if engine.startswith('aurora') == True:\r\n                        cluster_id = rds.describe_db_instances(DBInstanceIdentifier = instance)['DBInstances'][0]['DBClusterIdentifier']\r\n                        print(&quot;Stopping Aurora cluster: &quot; + str(cluster_id))\r\n                        rds.stop_db_cluster(DBClusterIdentifier = cluster_id)\r\n                    else:\r\n                        print(&quot;Stopping RDS instances: &quot; + str(instance))\r\n                        rds.stop_db_instance(DBInstanceIdentifier = instance)\r\n        print(&quot;----------------------------------------&quot;)\r\n\r\nif __name__ == '__main__':\r\n    main()\r\n<\/pre>\n<p>&nbsp;<\/p>\n<p>List of required permissions to run (besides the &quot;<strong>AWSLambdaExecute<\/strong>&quot; policy):<\/p>\n<ul>\n<li>ec2:DescribeRegions<\/li>\n<li>ec2:DescribeInstances<\/li>\n<li>ec2:StopInstances<\/li>\n<li>rds:ListTagsForResource<\/li>\n<li>rds:DescribeDBInstances<\/li>\n<li>rds:StopDBInstance<\/li>\n<li>autoscaling:DescribeAutoScalingGroups<\/li>\n<li>autoscaling:UpdateAutoScalingGroup<\/li>\n<\/ul>\n","protected":false},"excerpt":{"rendered":"<p>This Python script gets a list of all regions, finds EC2 instances, RDS instances and ASG in them, and if there is no &quot;prevent_stop&quot; tag equal to &quot;true&quot; on the resource, then it stops this resource, and in the case of ASG it scaledown it to 0. main.py: &nbsp; List of required permissions to run &hellip; <a href=\"https:\/\/artem.services\/?p=2107&#038;lang=en\" class=\"more-link\">\u041f\u0440\u043e\u0434\u043e\u043b\u0436\u0438\u0442\u044c \u0447\u0438\u0442\u0430\u0442\u044c<span class=\"screen-reader-text\"> &quot;Lambda &#8212; For stopping EC2 instances, RDS instances and ASG downscale in all regions&quot;<\/span><\/a><\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":[],"categories":[599],"tags":[543,1439,885,1527,1529],"_links":{"self":[{"href":"https:\/\/artem.services\/index.php?rest_route=\/wp\/v2\/posts\/2107"}],"collection":[{"href":"https:\/\/artem.services\/index.php?rest_route=\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/artem.services\/index.php?rest_route=\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/artem.services\/index.php?rest_route=\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/artem.services\/index.php?rest_route=%2Fwp%2Fv2%2Fcomments&post=2107"}],"version-history":[{"count":4,"href":"https:\/\/artem.services\/index.php?rest_route=\/wp\/v2\/posts\/2107\/revisions"}],"predecessor-version":[{"id":2120,"href":"https:\/\/artem.services\/index.php?rest_route=\/wp\/v2\/posts\/2107\/revisions\/2120"}],"wp:attachment":[{"href":"https:\/\/artem.services\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=2107"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/artem.services\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=2107"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/artem.services\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=2107"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}