Рекурсивно создать словарь метаданных экземпляра AWS EC2 с Flask - PullRequest
0 голосов
/ 26 января 2020

Мне бы хотелось получить несколько советов по проекту, над которым я работаю. Я пытаюсь создать сценарий запуска и веб-приложение python для экземпляров AWS, которые будут отображать все подробности метаданных экземпляра на странице индекса. Я думаю, что это будет полезно, если мы работаем с несколькими экземплярами за балансировщиком нагрузки и устраняем неисправности или работаем с контейнерами. Я смог осуществить это для GCP, поскольку в их API был рекурсивный вызов, который выдавал все детали.

При AWS все данные экземпляра хранятся по этому адресу http://169.254.169.254/latest/meta-data/ , это возвращает набор папок, каждая из которых содержит указанную c информацию или несколько папок с дополнительной информацией. Я пытаюсь создать алгоритм, который рекурсивно выполняет вызовы API и создает вложенный словарь в процессе, чтобы мы могли преобразовать этот словарь в JSON и отобразить его на веб-странице.

Я поделился репозиторий GitHub здесь, дайте мне знать, если есть более простой способ сделать это, я, возможно, слишком усложняю это. Любые советы или предложения приветствуются.

https://github.com/RaguRJ/aws_instance_detail_flask_app

Фрагмент кода main.py ниже

from flask import Flask, render_template
import requests
import json


app = Flask(__name__)

# func to recursively return paths
metadata_server = "http://169.254.169.254/latest/"
metadata = {}
path_dict = {}
temp_dict = {}

def api_gen(key, url):
    value = requests.get(url).text
    path_list = [x for x in value.splitlines()]
    parent_key = key
    #print('api_gen url: ', url)
    return parent_key, {parent_key : path_list}, path_list



def met_gen(key, path_list, url):
    for p in path_list:
        # path_dict.update({ p : ''})
        print('p', p)
        if p[-1] != '/':
           api_call = api_gen(p, url+p)
           return api_call[1]
        else:
           api_call = api_gen(p, url+p)
           print('api_call[0]: ', api_call[0])
           print('api_call[2]: ', api_call[2])
           print('url: ', url+api_call[0])
           return met_gen(api_call[0], api_call[2], url+api_call[0])
    return

path_list = ["meta-data/"]
path_dict.update(met_gen(None, path_list, metadata_server))
json_data = json.dumps(path_dict, indent=4)


@app.route("/", methods=["GET"])
def hello():
    return render_template('index.html', json_data=json_data)


if __name__ == "__main__":
    app.run(host='0.0.0.0', port=8080)

Я пытаюсь рекурсивно вызывайте функцию met_gen, пока мы не достигнем окончательного значения в ветви папки. При этом получаются все данные, хранящиеся в экземпляре, но форматирование не является идеальным, если вместо создания вложенных элементов словаря создаются дублированные копии или новые записи в главном словаре.

1 Ответ

0 голосов
/ 28 января 2020

Мне удалось выяснить рекурсивные функции, которые были необходимы для создания вложенного словаря.

  • Функция api_gen () берет ключ и URL-адрес и возвращает parent_key и возвращаемый список значений. из AWS внутреннего сервера метаданных
  • функция met_gen () рекурсивно запускает все пути в мета-сервере и выполняет вызовы функций api_gen () и update ()
  • update ( ) Функция обновления получает словарь, ключ и значение в качестве входных данных. Эта функция рекурсивно ищет любое количество уровней во вложенном словаре и обновляет ключ с заданным значением.
  • После создания окончательного вложенного словаря любые чувствительные значения удаляются из словаря
  • Словарь затем преобразуется в JSON obje c
  • Объект JSON отправляется в файл 'index. html' через приложение flask и отображается как предварительно отформатированный текст

Main.py код, включенный ниже

from flask import Flask, render_template
import requests
import json


app = Flask(__name__)

# global variable initialization
metadata_server = "http://169.254.169.254/latest/"
path_dict = {"meta-data/" : ''}
temp_dict = {}

# function that returns a key and a list of value/values from the metadata server
def api_gen(key, url):
    value = requests.get(url).text
    path_list = [x for x in value.splitlines()]
    parent_key = key
    return parent_key, path_list


# recursive function that goes through each folder level in the metadata api
def met_gen(path_list, url):
    for p in path_list:
        if p[-1] != '/':
           api_call = api_gen(p, url+p)
           update(path_dict, api_call[0], api_call[1])
        else:
           api_call = api_gen(p, url+p)
           temp_dict = { k:[] for k in api_call[1]}
           update(path_dict, api_call[0], temp_dict)
           met_gen(api_call[1], url+api_call[0])
    return

# recursive function that finds a key in a nested dictionary and updates its value
def update(dic, key, value):
    for k,v in dic.items():
        if k == key:
            dic[k] = value
        elif isinstance(v, dict):
            update(dic.get(k), key, value)
        elif not k in dic.keys():
            dic.update({ key : value })
    return

#  initializing path_list and calling met_gen function
path_list = ["meta-data/"]
met_gen(path_list, metadata_server)

# Deleting sensitive information from the dictionary
del path_dict["meta-data/"]["identity-credentials/"]
del path_dict["meta-data/"]["public-keys/"]

json_data = json.dumps(path_dict, indent=4)


@app.route("/", methods=["GET"])
def hello():
    return render_template('index.html', json_data=json_data)


if __name__ == "__main__":
    app.run(host='0.0.0.0', port=8080)
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...