Я хочу создать службу отдыха с помощью swagger-ui, которая создает новые экземпляры программного обеспечения, назовем его A. В основном, есть:
- create / destroy - instance / cluster
- установка / удаление
- запуск / остановка
Это операции, которые я хочу поддерживать. Чтобы сделать вещи более интересными, я хочу разрешить запускать все эти операции в разных версиях A, если только пользователь не предоставляет сопоставление для базовых команд. Давайте рассмотрим простой пример.
Application: A
Version: 1.0
Setup: setup -a target
Uninstall: uninstall --verify
Application: A
Version: 2.0
Setup: setup -u user -a target
Uninstall: uninstall
Выше представлены две разные версии одного и того же приложения, и хотя программа установки представила новый аргумент -u в 2.0, при удалении был удален обязательный параметр --verify. Как я справляюсь с этим, я создал файл схемы (yaml), который для каждой команды определяет аргументы, что требуется, что необязательно: флаг, строка или файл или что-то еще. Я читаю этот файл схемы и сопоставляю его с объектом, который затем создает flask -restplus.Models для всех из них.
Вот моя проблема: я хочу зарегистрировать (ну, это будет звучать глупо) динамически предварительно построенное пространство имен с flask ... Что я имею в виду. Подумайте:
@api.route(...)
class Instance(Resrouce):
@api.expect(already generated model)
def post(self, *args):
# create instance
pass
Вы получаете точку. У меня есть свои модели для всего. Поэтому я в основном пробовал бесчисленное количество способов обойти регистрацию динамически созданного пространства имен, но каждый раз терпел неудачу. Я попытался создать построитель пространства имен, например:
T = TypeVar('T', bound=ResourceBase)
class NamespaceBuilder(object):
api: Namespace
models: Dict[str, Model]
url_prefix: str
def __init__(self, version_info: str, repository: ModelBuilder):
self.url_prefix = version_info
self.api = Namespace(version_info)
for name, model in repository.models:
self.api.add_model(name, model)
def get_resource(self) -> Type[T]:
@self.api.route(f'/{self.url_prefix}')
class Instance(ResourceBase):
@self.api.expect(self.models['setup'], validate=True)
def get(self, *args):
print(*args)
return {}, 200
return Instance
Ну, он, конечно, создает API и регистрирует модели, но, конечно, фактическая маршрутизация не может использоваться таким образом. Затем я также попытался поместить класс Instance вне NamespaceBuilder, но затем я не могу использовать правильный экземпляр NamespaceBuilder, чтобы снова получить правильные API и модели. В качестве последнего средства я попытался создать метаклассы одноэтапного минимума из NamespaceBuilder, чтобы он генерировал все API со всеми связанными моделями, и чтобы ресурсы считывали эту информацию через экземпляр синглтона, но застрял, потому что класс Instance должен был знать version_info. ..
# nsbuilder.py:
class NamespaceBuilder(object, metaclass=Singleton):
api: Dict[str, Namespace]
models: Dict[str, Any]
...
# ns.py:
api: Namespace = NamespaceBuilder.get().api('no_version_info')
models: List[Model, ...] = NamespaceBuilder.get().models('still no version info')
@api.route('/')
class Instance(ResourceBase):
@expect(models.get('install'), verify=True)
def post(self, *args):
print(*args)
return {}, 200
....
# fl.py:
api: Api = Api(blueprint)
for version_info in version_infos:
api.add_namespace(Install.api, f'/{version_info}')
Конечно, это все еще не работает, потому что изнутри ns.py version_info недоступен, и, поскольку я не могу установить его динамически, этот подход также пошел к tra sh. Я начинаю чувствовать, что flask просто не может удовлетворить мои потребности. Я искал то же самое в django, который также, кажется, не поддерживает это поведение. Есть ли какие-либо рамки отдыха, которые я мог бы использовать, чтобы создать что-то вроде выше? В качестве альтернативы какое-нибудь извращенное хакерское решение для регистрации пространств имен, как указано выше в flask? После запуска приложения эти пространства имен будут оставаться там до тех пор, пока приложение не остановится. Я просто создаю их динамически, но я бы не хотел записывать python файлы в dis c с какой-нибудь строкой замещения magi c и использовать модуль importlib для добавления их в пространство имен flask ...