{"id":2105,"date":"2020-11-30T21:44:21","date_gmt":"2020-11-30T18:44:21","guid":{"rendered":"https:\/\/artem.services\/?p=2105"},"modified":"2021-04-05T17:36:49","modified_gmt":"2021-04-05T14:36:49","slug":"lambda-%d0%b4%d0%bb%d1%8f-%d0%be%d1%81%d1%82%d0%b0%d0%bd%d0%be%d0%b2%d0%ba%d0%b8-ec2-%d0%b8%d0%bd%d1%81%d1%82%d0%b0%d0%bd%d1%81%d0%be%d0%b2-rds-%d0%b8%d0%bd%d1%81%d1%82%d0%b0%d0%bd%d1%81%d0%be","status":"publish","type":"post","link":"https:\/\/artem.services\/?p=2105","title":{"rendered":"Lambda &#8212; \u0414\u043b\u044f \u043e\u0441\u0442\u0430\u043d\u043e\u0432\u043a\u0438 EC2 \u0438\u043d\u0441\u0442\u0430\u043d\u0441\u043e\u0432, RDS \u0438\u043d\u0441\u0442\u0430\u043d\u0441\u043e\u0432 \u0438 \u0441\u0434\u0443\u0432\u0430\u043d\u0438\u044f ASG \u0432\u043e \u0432\u0441\u0435\u0445 \u0440\u0435\u0433\u0438\u043e\u043d\u0430\u0445"},"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>\u0414\u0430\u043d\u043d\u044b\u0439 <strong>Python<\/strong> \u0441\u043a\u0440\u0438\u043f\u0442 \u043f\u043e\u043b\u0443\u0447\u0430\u0435\u0442 \u0441\u043f\u0438\u0441\u043e\u043a \u0432\u0441\u0435\u0445 \u0440\u0435\u0433\u0438\u043e\u043d\u043e\u0432, \u043d\u0430\u0445\u043e\u0434\u0438\u0442 \u0432 \u043d\u0438\u0445 <strong>EC2<\/strong> \u0438\u043d\u0441\u0442\u0430\u043d\u0441\u044b, <strong>RDS<\/strong> \u0438\u043d\u0441\u0442\u0430\u043d\u0441\u044b \u0438 <strong>ASG<\/strong>, \u0438 \u0435\u0441\u043b\u0438 \u043d\u0430 \u0440\u0435\u0441\u0443\u0440\u0441\u0435 \u043d\u0435\u0442 \u0442\u0435\u0433\u0430 &quot;<strong>prevent_stop<\/strong>&quot; \u0440\u0430\u0432\u043d\u043e\u0433\u043e \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u044e &quot;<strong>true<\/strong>&quot;, \u0442\u043e \u043e\u0441\u0442\u0430\u043d\u0430\u0432\u043b\u0438\u0432\u0430\u0435\u0442 \u0434\u0430\u043d\u043d\u044b\u0439 \u0440\u0435\u0441\u0443\u0440\u0441, \u0430 \u0432 \u0441\u043b\u0443\u0447\u0430\u0435 \u0441 <strong>ASG<\/strong> \u0441\u0436\u0438\u043c\u0430\u0435\u0442 \u0435\u0433\u043e \u0434\u043e <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>\u0421\u043f\u0438\u0441\u043e\u043a \u043d\u0443\u0436\u043d\u044b\u0445 \u0440\u0430\u0437\u0440\u0435\u0448\u0435\u043d\u0438\u0439 \u0434\u043b\u044f \u0437\u0430\u043f\u0443\u0441\u043a\u0430 (\u043f\u043e\u043c\u0438\u043c\u043e &quot;<strong>AWSLambdaExecute<\/strong>&quot; \u043f\u043e\u043b\u0438\u0442\u0438\u043a\u0438):<\/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>rds:StopDBCluster<\/li>\n<li>autoscaling:DescribeAutoScalingGroups<\/li>\n<li>autoscaling:UpdateAutoScalingGroup<\/li>\n<\/ul>\n","protected":false},"excerpt":{"rendered":"<p>\u0414\u0430\u043d\u043d\u044b\u0439 Python \u0441\u043a\u0440\u0438\u043f\u0442 \u043f\u043e\u043b\u0443\u0447\u0430\u0435\u0442 \u0441\u043f\u0438\u0441\u043e\u043a \u0432\u0441\u0435\u0445 \u0440\u0435\u0433\u0438\u043e\u043d\u043e\u0432, \u043d\u0430\u0445\u043e\u0434\u0438\u0442 \u0432 \u043d\u0438\u0445 EC2 \u0438\u043d\u0441\u0442\u0430\u043d\u0441\u044b, RDS \u0438\u043d\u0441\u0442\u0430\u043d\u0441\u044b \u0438 ASG, \u0438 \u0435\u0441\u043b\u0438 \u043d\u0430 \u0440\u0435\u0441\u0443\u0440\u0441\u0435 \u043d\u0435\u0442 \u0442\u0435\u0433\u0430 &quot;prevent_stop&quot; \u0440\u0430\u0432\u043d\u043e\u0433\u043e \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u044e &quot;true&quot;, \u0442\u043e \u043e\u0441\u0442\u0430\u043d\u0430\u0432\u043b\u0438\u0432\u0430\u0435\u0442 \u0434\u0430\u043d\u043d\u044b\u0439 \u0440\u0435\u0441\u0443\u0440\u0441, \u0430 \u0432 \u0441\u043b\u0443\u0447\u0430\u0435 \u0441 ASG \u0441\u0436\u0438\u043c\u0430\u0435\u0442 \u0435\u0433\u043e \u0434\u043e 0. main.py: &nbsp; \u0421\u043f\u0438\u0441\u043e\u043a \u043d\u0443\u0436\u043d\u044b\u0445 \u0440\u0430\u0437\u0440\u0435\u0448\u0435\u043d\u0438\u0439 \u0434\u043b\u044f \u0437\u0430\u043f\u0443\u0441\u043a\u0430 (\u043f\u043e\u043c\u0438\u043c\u043e &quot;AWSLambdaExecute&quot; \u043f\u043e\u043b\u0438\u0442\u0438\u043a\u0438): ec2:DescribeRegions ec2:DescribeInstances ec2:StopInstances rds:ListTagsForResource rds:DescribeDBInstances rds:StopDBInstance &hellip; <a href=\"https:\/\/artem.services\/?p=2105\" 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; \u0414\u043b\u044f \u043e\u0441\u0442\u0430\u043d\u043e\u0432\u043a\u0438 EC2 \u0438\u043d\u0441\u0442\u0430\u043d\u0441\u043e\u0432, RDS \u0438\u043d\u0441\u0442\u0430\u043d\u0441\u043e\u0432 \u0438 \u0441\u0434\u0443\u0432\u0430\u043d\u0438\u044f ASG \u0432\u043e \u0432\u0441\u0435\u0445 \u0440\u0435\u0433\u0438\u043e\u043d\u0430\u0445&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":[24],"tags":[25,1423,893,1159,1161],"_links":{"self":[{"href":"https:\/\/artem.services\/index.php?rest_route=\/wp\/v2\/posts\/2105"}],"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=2105"}],"version-history":[{"count":6,"href":"https:\/\/artem.services\/index.php?rest_route=\/wp\/v2\/posts\/2105\/revisions"}],"predecessor-version":[{"id":2171,"href":"https:\/\/artem.services\/index.php?rest_route=\/wp\/v2\/posts\/2105\/revisions\/2171"}],"wp:attachment":[{"href":"https:\/\/artem.services\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=2105"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/artem.services\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=2105"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/artem.services\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=2105"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}