Python 解析 Amazon RDS 实例的字典输出的问题
Issues with Python parsing dictionary output of Amazon RDS instances
我正在尝试解析我猜想是 Python 中 AWS 的 boto 接口的字典输出,它应该会提供有关我的所有 Amazon RDS(数据库)实例的信息。我在这里使用的所有工具都是新手,所以请原谅我的无知。
我试图将其视为一个数组,这可能是一个糟糕的前提,因为它是一个字典类型。下面的代码可以很好地提取两 (2) 个实例,这很奇怪 - 它至少可重复一次,并且我通过打印 dict 输出验证显示我在 运行 中的所有四 (4) 个实例区域 - 但它不会在输出中拉出后两个。当我使用 len() 测量输出的长度时,它 returns 2.
有人能帮我理解我需要对这段代码做些什么才能让它真正解析出所有返回的实例吗? (然后功能是查找 rebootAllowed 标记,如果为 1,则停止实例...这似乎工作正常,但同样,仅针对返回的前两个结果。)
import json
import boto3
region = 'us-east-1'
rds = boto3.client('rds')
def lambda_handler(event, context):
# Ingest all RDS instances
dbinstances = rds.describe_db_instances() # Filtering by instance status is not supported
print('* * *')
# Set db instance counter for below loop
dbi = 0
# Loop through each running RDS instance, checking tags and shutting down if tags match
for dbinstance in dbinstances:
# Set default values for tags we'll parse
rebootAllowed = 0
# We'll need this later
try:
dbinstanceId = dbinstances.get('DBInstances')[dbi]['DBInstanceIdentifier']
dbinstanceArn = dbinstances.get('DBInstances')[dbi]['DBInstanceArn']
rdstags = rds.list_tags_for_resource(ResourceName=dbinstanceArn)
# Attempt to look into tags for EC2s that have them. If they don't, we'll get an exception
try:
# Does the instance have the rebootAllowed tag? Great, what's its value?
if 'rebootAllowed' in rdstags['TagList'][dbi]['Key']:
rebootAllowed = rdstags['TagList'][dbi]['Value']
# Let's log what we're doing.
print('Examining RDS instance ' + dbinstanceId + '...')
# Attempt to stop instance
try:
if rebootAllowed == '1':
message = '-- This instance CAN be stopped. Doing that now.'
rdsid = [dbinstanceId]
rds.stop_db_instance(DBInstanceIdentifier=dbinstanceId)
elif rebootAllowed == '0':
message = '-- This instance is BLOCKED from being stopped. Doing nothing.'
else:
message = '-- This instance does not have the tags used by this script. Skipping.'
except Exception, err:
message = 'Error with RDS instance: instanceId: ' + err
raise err
print (message)
print ('* * *')
dbi += 1
except:
print('Examining RDS instance ' + dbinstanceId + ')')
print('-- An EXECPTION occurred while analyzing this instance. This could be because the instance has no tags at all.')
print('* * *')
dbi += 1
except:
print('End of list. Script complete.')
很难确切地说出发生了什么,尤其是因为我们并不完全知道您要迭代的字典的形状是什么,但您似乎确实了解了潜在的含义问题:你并没有真正python巧妙地处理这个迭代。
我去查看了输出,发现了这个样本:
{
"DBInstances": [
{
"DBInstanceIdentifier": "mydbinstancecf",
"DBInstanceClass": "db.t3.small",
"Engine": "mysql",
"DBInstanceStatus": "available",
"MasterUsername": "masterawsuser",
"Endpoint": {
"Address": "mydbinstancecf.abcexample.us-east-1.rds.amazonaws.com",
"Port": 3306,
"HostedZoneId": "Z2R2ITUGPM61AM"
},
...some output truncated...
}
]
}
因此,您可以立即通过删除 dbinstances
中的无关数据来简化循环
# dbinstances = rds.describe_db_instances() becomes
dbinstances = rds.describe_db_instances()["DBInstances"]
现在,您正在处理一组数据库实例。在 python for 循环中,您将可迭代(列表)的每个元素作为变量。在这种情况下,根本没有必要维护 dbi
计数器。如果你做想要计算元素,你可以这样做for i, e in enumerate(my_list):
,其中i
是索引,e
是元素。
所以你的循环变得更像这样:
for instance in dbinstances:
# Set default values for tags we'll parse
rebootAllowed = 0
# We'll need this later
try:
dbinstanceId = instance['DBInstanceIdentifier']
dbinstanceArn = instance['DBInstanceArn']
rdstags = rds.list_tags_for_resource(ResourceName=dbinstanceArn)
# ... the rest is left as an exercise for Josh
作为一般建议,在Python中设计此类算法时,请大量使用REPL。您可以四处看看并尝试一下,以快速了解数据的实际结构。
我正在尝试解析我猜想是 Python 中 AWS 的 boto 接口的字典输出,它应该会提供有关我的所有 Amazon RDS(数据库)实例的信息。我在这里使用的所有工具都是新手,所以请原谅我的无知。
我试图将其视为一个数组,这可能是一个糟糕的前提,因为它是一个字典类型。下面的代码可以很好地提取两 (2) 个实例,这很奇怪 - 它至少可重复一次,并且我通过打印 dict 输出验证显示我在 运行 中的所有四 (4) 个实例区域 - 但它不会在输出中拉出后两个。当我使用 len() 测量输出的长度时,它 returns 2.
有人能帮我理解我需要对这段代码做些什么才能让它真正解析出所有返回的实例吗? (然后功能是查找 rebootAllowed 标记,如果为 1,则停止实例...这似乎工作正常,但同样,仅针对返回的前两个结果。)
import json
import boto3
region = 'us-east-1'
rds = boto3.client('rds')
def lambda_handler(event, context):
# Ingest all RDS instances
dbinstances = rds.describe_db_instances() # Filtering by instance status is not supported
print('* * *')
# Set db instance counter for below loop
dbi = 0
# Loop through each running RDS instance, checking tags and shutting down if tags match
for dbinstance in dbinstances:
# Set default values for tags we'll parse
rebootAllowed = 0
# We'll need this later
try:
dbinstanceId = dbinstances.get('DBInstances')[dbi]['DBInstanceIdentifier']
dbinstanceArn = dbinstances.get('DBInstances')[dbi]['DBInstanceArn']
rdstags = rds.list_tags_for_resource(ResourceName=dbinstanceArn)
# Attempt to look into tags for EC2s that have them. If they don't, we'll get an exception
try:
# Does the instance have the rebootAllowed tag? Great, what's its value?
if 'rebootAllowed' in rdstags['TagList'][dbi]['Key']:
rebootAllowed = rdstags['TagList'][dbi]['Value']
# Let's log what we're doing.
print('Examining RDS instance ' + dbinstanceId + '...')
# Attempt to stop instance
try:
if rebootAllowed == '1':
message = '-- This instance CAN be stopped. Doing that now.'
rdsid = [dbinstanceId]
rds.stop_db_instance(DBInstanceIdentifier=dbinstanceId)
elif rebootAllowed == '0':
message = '-- This instance is BLOCKED from being stopped. Doing nothing.'
else:
message = '-- This instance does not have the tags used by this script. Skipping.'
except Exception, err:
message = 'Error with RDS instance: instanceId: ' + err
raise err
print (message)
print ('* * *')
dbi += 1
except:
print('Examining RDS instance ' + dbinstanceId + ')')
print('-- An EXECPTION occurred while analyzing this instance. This could be because the instance has no tags at all.')
print('* * *')
dbi += 1
except:
print('End of list. Script complete.')
很难确切地说出发生了什么,尤其是因为我们并不完全知道您要迭代的字典的形状是什么,但您似乎确实了解了潜在的含义问题:你并没有真正python巧妙地处理这个迭代。
我去查看了输出,发现了这个样本:
{
"DBInstances": [
{
"DBInstanceIdentifier": "mydbinstancecf",
"DBInstanceClass": "db.t3.small",
"Engine": "mysql",
"DBInstanceStatus": "available",
"MasterUsername": "masterawsuser",
"Endpoint": {
"Address": "mydbinstancecf.abcexample.us-east-1.rds.amazonaws.com",
"Port": 3306,
"HostedZoneId": "Z2R2ITUGPM61AM"
},
...some output truncated...
}
]
}
因此,您可以立即通过删除 dbinstances
# dbinstances = rds.describe_db_instances() becomes
dbinstances = rds.describe_db_instances()["DBInstances"]
现在,您正在处理一组数据库实例。在 python for 循环中,您将可迭代(列表)的每个元素作为变量。在这种情况下,根本没有必要维护 dbi
计数器。如果你做想要计算元素,你可以这样做for i, e in enumerate(my_list):
,其中i
是索引,e
是元素。
所以你的循环变得更像这样:
for instance in dbinstances:
# Set default values for tags we'll parse
rebootAllowed = 0
# We'll need this later
try:
dbinstanceId = instance['DBInstanceIdentifier']
dbinstanceArn = instance['DBInstanceArn']
rdstags = rds.list_tags_for_resource(ResourceName=dbinstanceArn)
# ... the rest is left as an exercise for Josh
作为一般建议,在Python中设计此类算法时,请大量使用REPL。您可以四处看看并尝试一下,以快速了解数据的实际结构。