首页 > 解决方案 > Python函数根据列表内容重复输出

问题描述

我有一个列出 AWS EC2 中服务器的 python 函数。

出于某种原因,它为循环通过的每个区域重复相同的服务器信息(相同的实例 ID、IP 地址等)。问题是每个地区都应该是独一无二的,并且拥有自己的服务器,并提供不同的信息。

如果我在此列表中有一个区域,则服务器会列出一次:

regions = ['us-east-1']

如果列表中有两个区域,则相同的信息重复两次:

regions = ['us-east-1', 'us-east-2']

如果我有三个区域相同的信息重复 3 次,依此类推......

这是我的功能:

def list_instances(aws_account,aws_account_number, interactive, regions, fieldnames, show_details):
    today, aws_env_list, output_file, output_file_name, fieldnames = initialize(interactive, aws_account)
    options = arguments()
    instance_list = ''
    session = ''
    ec2 = ''
    account_found = ''
    PrivateDNS = None
    block_device_list = None
    instance_count = 0
    account_type_message = ''
    profile_missing_message = ''
    region = ''
    # Set the ec2 dictionary
    ec2info = {}
    # Write the file headers
    if interactive == 1:
        with open(output_file, mode='w+') as csv_file:
            writer = csv.DictWriter(csv_file, fieldnames=fieldnames, delimiter=',', lineterminator='\n')
            writer.writeheader()
    session = boto3.Session(profile_name=aws_account,region_name=region)
    print(Fore.CYAN)      
    report_gov_or_comm(aws_account, account_found)
    print(Fore.RESET)
    session = boto3.Session(profile_name=aws_account)
    account_found = 'yes'
    ec2 = session.client("ec2")
    for i in range(len(regions)):
        session = boto3.Session(profile_name=aws_account, region_name=region[i])
        print(f"*****Region: {region}*******")
        # Loop through the instances
        try:
            instance_list = ec2.describe_instances()
        except Exception as e:
                pass
        try:
            for reservation in instance_list["Reservations"]:
                for instance in reservation.get("Instances", []):
                    instance_count = instance_count + 1
                    launch_time = instance["LaunchTime"]
                    launch_time_friendly = launch_time.strftime("%B %d %Y")
                    tree = objectpath.Tree(instance)
                    block_devices = set(tree.execute('$..BlockDeviceMappings[\'Ebs\'][\'VolumeId\']'))
                    if block_devices:
                        block_devices = list(block_devices)
                        block_devices = str(block_devices).replace('[','').replace(']','').replace('\'','')
                    else:
                        block_devices = None
                    private_ips =  set(tree.execute('$..PrivateIpAddress'))
                    if private_ips:
                        private_ips_list = list(private_ips)
                        private_ips_list = str(private_ips_list).replace('[','').replace(']','').replace('\'','')
                    else:
                        private_ips_list = None
                    type(private_ips_list)
                    public_ips =  set(tree.execute('$..PublicIp'))
                    if len(public_ips) == 0:
                        public_ips = None
                    if public_ips:
                        public_ips_list = list(public_ips)
                        public_ips_list = str(public_ips_list).replace('[','').replace(']','').replace('\'','')
                    else:
                        public_ips_list = None
                    if 'KeyName' in instance:
                        key_name = instance['KeyName']
                    else:
                        key_name = None
                    name = None
                    if 'Tags' in instance:
                        try:
                            tags = instance['Tags']
                            name = None
                            for tag in tags:
                                if tag["Key"] == "Name":
                                    name = tag["Value"]
                                if tag["Key"] == "Engagement" or tag["Key"] == "Engagement Code":
                                    engagement = tag["Value"]
                        except ValueError:
                            # print("Instance: %s has no tags" % instance_id)
                            pass
                    if 'VpcId' in instance:
                        vpc_id = instance['VpcId']
                    else:
                        vpc_id = None
                    if 'PrivateDnsName' in instance:
                        private_dns = instance['PrivateDnsName']
                    else:
                        private_dns = None
                    ec2info[instance['InstanceId']] = {
                        'AWS Account': aws_account,
                        'Account Number': aws_account_number,
                        'Name': name,
                        'Instance ID': instance['InstanceId'],
                        'Volumes': block_devices,
                        'Private IP': private_ips_list,
                        'Public IP': public_ips_list,
                        'Private DNS': private_dns,
                        'Availability Zone': instance['Placement']['AvailabilityZone'],
                        'VPC ID': vpc_id,
                        'Type': instance['InstanceType'],
                        'Key Pair Name': key_name,
                        'State': instance['State']['Name'],
                        'Launch Date': launch_time_friendly
                    }
                    with open(output_file,'a') as csv_file:
                        writer = csv.DictWriter(csv_file, fieldnames=fieldnames, delimiter=',', lineterminator='\n')
                        writer.writerow({'AWS Account': aws_account, "Account Number": aws_account_number, 'Name': name, 'Instance ID': instance["InstanceId"], 'Volumes': block_devices,  'Private IP': private_ips_list, 'Public IP': public_ips_list, 'Private DNS': private_dns, 'Availability Zone': instance['Placement']['AvailabilityZone'], 'VPC ID': vpc_id, 'Type': instance["InstanceType"], 'Key Pair Name': key_name, 'State': instance["State"]["Name"], 'Launch Date': launch_time_friendly})
                    ec2_info_items = ec2info.items
                    if show_details == 'y' or show_details == 'yes':
                        for instance_id, instance in ec2_info_items():
                            if account_found == 'yes':
                                print(Fore.RESET + "-------------------------------------")
                                for key in [
                                    'AWS Account',
                                    'Account Number',
                                    'Name',
                                    'Instance ID',
                                    'Volumes',
                                    'Private IP',
                                    'Public IP',
                                    'Private DNS',
                                    'Availability Zone',
                                    'VPC ID',
                                    'Type',
                                    'Key Pair Name',
                                    'State',
                                    'Launch Date'
                                ]:
                                    print(Fore.GREEN + f"{key}: {instance.get(key)}")
                                print(Fore.RESET + "-------------------------------------")
                        else:
                            pass
                    reservation = {}
                    instance = {}
                    ec2_info_items = {}
                    ec2info = {}
                    with open(output_file,'a') as csv_file:
                        csv_file.close()
        except Exception as e:
            print(f"An exception has occurred: {e}")
    if profile_missing_message == '*':
        banner(profile_missing_message)
    print(Fore.GREEN)
    report_instance_stats(instance_count, aws_account, account_found)
    print(Fore.RESET + '\n')
    #breakpoint()
    return output_file

def main():
    aws_account = 'us-account-1'
    aws_account_number = '123456789101'
    regions = ['us-east-1', 'us-east-2']
    show_details = 'yes'
    output_file = list_instances(aws_account,aws_account_number, interactive, regions, fieldnames, show_details)

if __name__ == __main__:
    main()

我尝试在函数末尾重置一些值,以使其停止根据regions列表的内容一遍又一遍地重复相同的信息。但这没有用!

        reservation = {}
        instance = {}
        ec2_info_items = {}
        ec2info = {}

为什么根据列表的内容一遍又一遍地重复相同的信息regions

标签: pythonamazon-web-services

解决方案


问题是您已经为默认区域创建了一次 EC2 客户端对象,而您从未为其他区域更新它。

改变这个:

ec2 = session.client("ec2")
for i in range(len(regions)):
    session = boto3.Session(profile_name=aws_account, region_name=region[i])
    print(f"*****Region: {region}*******")
    # Loop through the instances
    try:
        instance_list = ec2.describe_instances()

对此:

for region in regions:
    session = boto3.Session(profile_name=aws_account, region_name=region)
    ec2 = session.client("ec2")
    print(f"*****Region: {region}*******")
    # Loop through the instances
    try:
        instance_list = ec2.describe_instances()

推荐阅读