Tôi có một tập lệnh Python để tạo danh sách các phiên bản EC2 trong tất cả các tài khoản AWS của chúng tôi [khoảng 150] và lưu trữ kết quả trong MongoDB
Tôi đang xuất bộ sưu tập mongodb sang tệp CSV bằng mô-đun gấu trúc Python. Nó hoạt động ngoại trừ các tiêu đề không theo thứ tự và tôi không muốn in Chỉ mục MongoDB
Trong phiên bản gốc của tập lệnh [trước khi thêm cơ sở dữ liệu], tôi đã sử dụng mô-đun CSV để ghi tệp và các tiêu đề đều chính xác.
Tôi đã thêm cơ sở dữ liệu như một bài tập học tập và vì nó giúp làm việc dễ dàng hơn với tất cả các tài khoản Amazon mà chúng tôi có
Nếu tôi xem json trong cơ sở dữ liệu mongo cho bộ sưu tập, tôi đang in tất cả các trường theo đúng thứ tự
{'_id': ObjectId['5f14f9ffa40de31278dade03'], 'AWS Account': 'jf-master-pd', 'Account Number': '123456789101', 'Name': 'usawsweb001', 'Instance ID': 'i-01e5e920b4d3d5dcb', 'AMI ID': 'ami-006219aba10688d0b', 'Volumes': 'vol-0ce8db4e071bc7229, vol-099f6d212a91121d0, vol-0bb36e343e9c01374, vol-05610645edfd02253, vol-05adc01d70d75d649', 'Private IP': '172.31.62.168', 'Public IP': 'xx.xx.xx.xx', 'Private DNS': 'ip-172-31-62-168.ec2.internal', 'Availability Zone': 'us-east-1e', 'VPC ID': 'vpc-68b1ff12', 'Type': 't2.micro', 'Key Pair Name': 'jf-timd', 'State': 'running', 'Launch Date': 'July 20 2020'}
{'_id': ObjectId['5f14f9ffa40de31278dade05'], 'AWS Account': 'jf-master-pd', 'Account Number': '123456789101', 'Name': 'usawsweb002', 'Instance ID': 'i-0b7db2bcab853ef96', 'AMI ID': 'ami-006219aba10688d0b', 'Volumes': 'vol-095a9dcf54ca97c0e, vol-0c8e96b71fbb7dfcf, vol-070c16c457f91c54e, vol-0dc1eaf2e826fa3a6, vol-0f0f157a8489ab939', 'Private IP': '172.31.63.131', 'Public IP': 'xx.xx.xx.xx', 'Private DNS': 'ip-172-31-63-131.ec2.internal', 'Availability Zone': 'us-east-1e', 'VPC ID': 'vpc-68b1ff12', 'Type': 't2.micro', 'Key Pair Name': 'jf-timd', 'State': 'running', 'Launch Date': 'July 20 2020'}
{'_id': ObjectId['5f14f9ffa40de31278dade07'], 'AWS Account': 'jf-master-pd', 'Account Number': '123456789101', 'Name': 'usawsweb003', 'Instance ID': 'i-0611acf4b6cc53b61', 'AMI ID': 'ami-006219aba10688d0b', 'Volumes': 'vol-0aa28f89f6ce50577, vol-0e37ff844e8b9c47a, vol-0d54c713ae231739c, vol-0e29df46edc814619, vol-07e0c40a8913b1d31', 'Private IP': '172.31.52.44', 'Public IP': 'xx.xx.xx.xx', 'Private DNS': 'ip-172-31-52-44.ec2.internal', 'Availability Zone': 'us-east-1e', 'VPC ID': 'vpc-68b1ff12', 'Type': 't2.micro', 'Key Pair Name': 'jf-timd', 'State': 'running', 'Launch Date': 'July 20 2020'}
Nhưng sử dụng gấu trúc python để xuất từ cơ sở dữ liệu mongo, các tiêu đề đã hết tác dụng. Dòng thông tin đến đúng tiêu đề, nhưng các cột hoàn toàn không theo thứ tự
Trong mã của tôi, tôi đang tạo một từ điển có thông tin máy chủ trong đó, sau đó chuyển từ điển sang hàm in bộ sưu tập Mongo
def list_instances[aws_account,aws_account_number, interactive, regions, show_details, instance_col]:
for region in regions:
if 'gov' in aws_account and not 'admin' in aws_account:
try:
session = boto3.Session[profile_name=aws_account, region_name=region]
except botocore.exceptions.ProfileNotFound as e:
profile_missing_message = f"An exception has occurred: {e}"
account_found = 'no'
raise
else:
try:
session = boto3.Session[profile_name=aws_account, region_name=region]
account_found = 'yes'
except botocore.exceptions.ProfileNotFound as e:
profile_missing_message = f"An exception has occurred: {e}"
raise
try:
ec2 = session.client["ec2"]
except Exception as e:
print[f"An exception has occurred: {e}"]
message = f" Region: {region} in {aws_account}: [{aws_account_number}] "
banner[message]
print[Fore.RESET]
# Loop through the instances
try:
instance_list = ec2.describe_instances[]
except Exception as e:
print[f"An exception has occurred: {e}"]
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
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
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]
raise
key_name = instance['KeyName'] if instance['KeyName'] else None
vpc_id = instance.get['VpcId'] if instance.get['VpcId'] else None
private_dns = instance['PrivateDnsName'] if instance['PrivateDnsName'] else None
ec2info[instance['InstanceId']] = {
'AWS Account': aws_account,
'Account Number': aws_account_number,
'Name': name,
'Instance ID': instance['InstanceId'],
'AMI ID': instance['ImageId'],
'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
}
mongo_instance_dict = {'_id': '', 'AWS Account': aws_account, "Account Number": aws_account_number, 'Name': name, 'Instance ID': instance["InstanceId"], 'AMI ID': instance['ImageId'], '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}
insert_doc[mongo_instance_dict]
mongo_export_to_file[interactive, aws_account]
Đây là chức năng chèn từ điển vào MongoDB
def insert_doc[mydict]:
mydb, mydb_name, instance_col = set_db[]
mydict['_id'] = ObjectId[]
instance_doc = instance_col.insert_one[mydict]
return instance_doc
Đây là chức năng ghi MongoDB vào tệp
def mongo_export_to_file[]:
aws_account = 'jf-master-pd'
today = datetime.today[]
today = today.strftime["%m-%d-%Y"]
mydb, mydb_name, instance_col = set_db[]
# make an API call to the MongoDB server
cursor = instance_col.find[]
# extract the list of documents from cursor obj
mongo_docs = list[cursor]
# create an empty DataFrame for storing documents
docs = pandas.DataFrame[columns=[]]
# iterate over the list of MongoDB dict documents
for num, doc in enumerate[mongo_docs]:
# convert ObjectId[] to str
doc["_id"] = str[doc["_id"]]
# get document _id from dict
doc_id = doc["_id"]
# create a Series obj from the MongoDB dict
series_obj = pandas.Series[ doc, name=doc_id ]
# append the MongoDB Series obj to the DataFrame obj
docs = docs.append[series_obj]
# get document _id from dict
doc_id = doc["_id"]
# Set the output file
output_dir = os.path.join['..', '..', 'output_files', 'aws_instance_list', 'csv', '']
output_file = os.path.join[output_dir, 'aws-instance-master-list-' + today +'.csv']
# export MongoDB documents to a CSV file
docs.to_csv[output_file, ","] # CSV delimited by commas
Đây là một liên kết đến thư mục mã gốc trong github. Các tệp chúng tôi muốn là aws_ec2_list_instances. py và ec2_mongo. py
Tại sao các cột và tiêu đề không theo thứ tự trong phiên bản MongoDB?
Pandas là một thư viện rất linh hoạt và linh hoạt để quản lý và phân tích dữ liệu. Sẽ là quá mức cần thiết nếu tất cả những gì bạn muốn làm là chuyển đổi bộ sưu tập MongoDB thành tệp CSV khi mô-đun csv
đạt tiêu chuẩn và cách bạn đang sử dụng nó rất kém hiệu quả. Một điều khác cần lưu ý là cho đến gần đây, cả Python và Pandas đều không cố gắng duy trì thứ tự của các mục trong một lệnh. Trước khi Python bắt đầu giữ trật tự trong phiên bản 3. 5, mã được viết dựa trên giả định rằng thứ tự của các mục trong lệnh là không quan trọng. Chỉ kể từ Python 3. 7 việc duy trì thứ tự của các mục chính tả có trở thành một tính năng ngôn ngữ chính thức không
DataFrame là cấu trúc dữ liệu chính của Pandas và nó đại diện cho một mảng dữ liệu 2 chiều. Một số điều về nó có thể gây nhầm lẫn và tôi nghĩ rằng bạn đã vấp phải sự thật là cả hàng và cột đều có thể có các chỉ mục được đặt tên. Nói chung, khi nói về dữ liệu trong Panda, "index" đề cập đến chỉ số hàng
Trong dữ liệu của bạn, chỉ mục hàng sẽ là giá trị của MongoDB _id
và bạn muốn vứt nó đi. Điều đó tốt, nhưng nó có thể khiến bạn nghĩ rằng "chỉ mục" có nghĩa là cột
Một Sê-ri thường có nghĩa là đại diện cho một cột dữ liệu. Khi được khởi tạo bằng lệnh, các khóa được coi là chỉ mục, nghĩa là nhãn hàng chứ không phải nhãn cột. Bạn sẽ thấy hầu hết các hoạt động giữa DataFrames và Sê-ri đều coi Sê-ri là cột. Nhưng như tôi đã nói, Pandas rất linh hoạt, vì vậy chúng có hàm DataFrame.append
coi Sê-ri là một hàng
Điều hấp dẫn là khi nối thêm một hàng, Pandas mong muốn Sê-ri sẽ nối thêm một hàng vào các cột hiện có. Khi Sê-ri có các chỉ mục [các khóa trong lệnh gốc] không tồn tại trong DataFrame, nó sẽ thêm chúng vào cuối các cột dưới dạng cột mới và như bạn thấy, nó sẽ thêm chúng theo thứ tự được sắp xếp. Đây thực sự là một lỗi trong phiên bản hiện tại [1. 0. 5] điều đó có lẽ đã được phép kéo dài đến mức này mà không được sửa chữa vì dù sao thì lệnh dict đã từng bị bỏ qua, nhưng hãy biết ơn vì điều đó, vì nó đã khiến bạn phải điều tra thêm
Việc bạn chuyển đổi bộ sưu tập MongoDB thành DataFrame bằng cách nối thêm Sê-ri vào DataFrame trống ban đầu thực sự không hiệu quả. DataFrame hoàn toàn có khả năng đọc bộ sưu tập MongoDB của bạn và thực hiện điều đó với ít mã hơn để bạn viết