diff --git a/src/aaz_dev/command/api/_cmds.py b/src/aaz_dev/command/api/_cmds.py index 278c49c0..557e0cc0 100644 --- a/src/aaz_dev/command/api/_cmds.py +++ b/src/aaz_dev/command/api/_cmds.py @@ -160,7 +160,7 @@ def generate_command_models_from_swagger(swagger_tag, workspace_path=None): sys.exit(1) -@bp.cli.command("generate-all", short_help="Fully generate data model from OpenAPI specification, mainly for use in https://github.com/magodo/az-rs.") +@bp.cli.command("generate-all", short_help="Fully generate metadata from the specification, mainly for use in https://github.com/magodo/az-rs, and additionally to validate compatibility.") @click.option( "--swagger-path", '-s', type=click.Path(file_okay=False, dir_okay=True, readable=True, resolve_path=True), @@ -230,6 +230,10 @@ def to_aaz(module_name): aaz_manager=AAZSpecsManager(), source=SourceTypeEnum.OpenAPI, ) + for resource in resources: + resource["options"] = { + "non_flatten": True + } ws.add_new_resources_by_swagger(mod_names=module_name, version=version, resources=resources) # provide default short summary diff --git a/src/aaz_dev/command/model/configuration/_arg_builder.py b/src/aaz_dev/command/model/configuration/_arg_builder.py index e20e592d..a1cd60ab 100644 --- a/src/aaz_dev/command/model/configuration/_arg_builder.py +++ b/src/aaz_dev/command/model/configuration/_arg_builder.py @@ -110,6 +110,8 @@ def _build_arg(self): def _need_flatten(self): if isinstance(self.schema, CMDObjectSchema): + if self.schema.non_flatten: + return False if self.get_cls(): # not support to flatten object which is a cls. return False diff --git a/src/aaz_dev/command/model/configuration/_schema.py b/src/aaz_dev/command/model/configuration/_schema.py index a7ceb010..a5c65465 100644 --- a/src/aaz_dev/command/model/configuration/_schema.py +++ b/src/aaz_dev/command/model/configuration/_schema.py @@ -890,6 +890,8 @@ class CMDObjectSchemaBase(CMDSchemaBase): discriminators = ListType(CMDObjectSchemaDiscriminatorField()) additional_props = CMDObjectSchemaAdditionalPropertiesField() + non_flatten = None + # define a schema cls which can be used by others, # cls definition will not include properties in CMDSchema only, such as following properties: # - name diff --git a/src/aaz_dev/swagger/controller/command_generator.py b/src/aaz_dev/swagger/controller/command_generator.py index 4c418681..48631f45 100644 --- a/src/aaz_dev/swagger/controller/command_generator.py +++ b/src/aaz_dev/swagger/controller/command_generator.py @@ -445,6 +445,7 @@ def create_draft_command_group(self, resource, command_group.commands = [] path_item = self.get_path_item(resource) parameterized_host = self.get_parameterized_host(resource) + non_flatten = kwargs.get("non_flatten", None) if path_item.get is not None and 'get' in methods: cmd_builder = CMDBuilder(path=resource.path, method='get', mutability=MutabilityEnum.Read, @@ -463,14 +464,14 @@ def create_draft_command_group(self, resource, if path_item.put is not None and 'put' in methods: cmd_builder = CMDBuilder(path=resource.path, method='put', mutability=MutabilityEnum.Create, - parameterized_host=parameterized_host) + parameterized_host=parameterized_host, non_flatten=non_flatten) op = self.generate_operation(cmd_builder, path_item, instance_var) create_command = self.generate_command(path_item, resource, instance_var, cmd_builder, op) command_group.commands.append(create_command) if path_item.post is not None and 'post' in methods: cmd_builder = CMDBuilder(path=resource.path, method='post', mutability=MutabilityEnum.Create, - parameterized_host=parameterized_host) + parameterized_host=parameterized_host, non_flatten=non_flatten) op = self.generate_operation(cmd_builder, path_item, instance_var) action_command = self.generate_command(path_item, resource, instance_var, cmd_builder, op) command_group.commands.append(action_command) @@ -488,12 +489,12 @@ def create_draft_command_group(self, resource, update_by_generic_command = None if path_item.patch is not None and 'patch' in methods: cmd_builder = CMDBuilder(path=resource.path, method='patch', mutability=MutabilityEnum.Update, - parameterized_host=parameterized_host) + parameterized_host=parameterized_host, non_flatten=non_flatten) op = self.generate_operation(cmd_builder, path_item, instance_var) update_by_patch_command = self.generate_command(path_item, resource, instance_var, cmd_builder, op) if path_item.get is not None and path_item.put is not None and 'get' in methods and 'put' in methods: cmd_builder = CMDBuilder(path=resource.path, - parameterized_host=parameterized_host) + parameterized_host=parameterized_host, non_flatten=non_flatten) get_op = self.generate_operation( cmd_builder, path_item, instance_var, method='get', mutability=MutabilityEnum.Read) put_op = self.generate_operation( @@ -511,7 +512,7 @@ def create_draft_command_group(self, resource, if 'get' not in methods or 'put' not in methods: raise exceptions.InvalidAPIUsage(f"Invalid update_by resource: '{resource}': 'get' or 'put' not in methods: '{methods}'") cmd_builder = CMDBuilder(path=resource.path, - parameterized_host=parameterized_host) + parameterized_host=parameterized_host, non_flatten=non_flatten) get_op = self.generate_operation( cmd_builder, path_item, instance_var, method='get', mutability=MutabilityEnum.Read) put_op = self.generate_operation( @@ -529,7 +530,7 @@ def create_draft_command_group(self, resource, raise exceptions.InvalidAPIUsage(f"Invalid update_by resource: '{resource}': 'patch' not in methods: '{methods}'") if kwargs.get('is_identity', False) is True: - cmd_builder = CMDBuilder(path=resource.path, parameterized_host=parameterized_host) + cmd_builder = CMDBuilder(path=resource.path, parameterized_host=parameterized_host, non_flatten=non_flatten) get_op = self.generate_operation(cmd_builder, path_item, instance_var, method='get', mutability=MutabilityEnum.Read) patch_op = self.generate_operation(cmd_builder, path_item, instance_var, method='patch', mutability=MutabilityEnum.Update) specific_update_command = self.generate_specific_update_command(path_item, resource, instance_var, cmd_builder, get_op, patch_op) @@ -541,7 +542,7 @@ def create_draft_command_group(self, resource, else: cmd_builder = CMDBuilder(path=resource.path, method='patch', mutability=MutabilityEnum.Update, - parameterized_host=parameterized_host) + parameterized_host=parameterized_host, non_flatten=non_flatten) op = self.generate_operation(cmd_builder, path_item, instance_var) patch_update_command = self.generate_command(path_item, resource, instance_var, cmd_builder, op) command_group.commands.append(patch_update_command) diff --git a/src/aaz_dev/swagger/model/schema/cmd_builder.py b/src/aaz_dev/swagger/model/schema/cmd_builder.py index 9e8e6ce9..b017a208 100644 --- a/src/aaz_dev/swagger/model/schema/cmd_builder.py +++ b/src/aaz_dev/swagger/model/schema/cmd_builder.py @@ -42,7 +42,7 @@ class CMDBuilder: - def __init__(self, path, method=None, mutability=None, in_base=False, frozen=False, parent_ids=None, cls_definitions=None, parameterized_host=None): + def __init__(self, path, method=None, mutability=None, in_base=False, frozen=False, parent_ids=None, cls_definitions=None, parameterized_host=None, non_flatten=None): self.path = path self.method = method self.mutability = mutability @@ -53,6 +53,7 @@ def __init__(self, path, method=None, mutability=None, in_base=False, frozen=Fal self.parent_ids = parent_ids or [] self.cls_definitions = {} if cls_definitions is None else cls_definitions self.parameterized_host = parameterized_host + self.non_flatten=non_flatten def __call__(self, schema, **kwargs): sub_builder = CMDBuilder( @@ -63,7 +64,8 @@ def __call__(self, schema, **kwargs): frozen=kwargs.pop('frozen', self.frozen), parent_ids=[*self.parent_ids, self.id], cls_definitions=kwargs.pop('cls_definitions', self.cls_definitions), - parameterized_host=kwargs.pop('parameterized_host', self.parameterized_host) + parameterized_host=kwargs.pop('parameterized_host', self.parameterized_host), + non_flatten=kwargs.pop('non_flatten', self.non_flatten) ) if getattr(schema, 'read_only', None): sub_builder.read_only = True @@ -84,6 +86,7 @@ def __call__(self, schema, **kwargs): key=sub_builder.id, value=sub_builder.parent_ids.index(sub_builder.id), ) + return schema.to_cmd(sub_builder, **kwargs) def find_traces(self, traces): @@ -232,6 +235,8 @@ def build_schema(self, schema): raise exceptions.InvalidSwaggerValueError( f"type is not supported", key=getattr(schema, "traces", None), value=[schema_type]) + if isinstance(model, CMDObjectSchemaBase): + model.non_flatten = self.non_flatten model.read_only = self.read_only model.frozen = self.frozen return model diff --git a/src/aaz_dev/swagger/model/schema/parameter.py b/src/aaz_dev/swagger/model/schema/parameter.py index 502e8fc6..5ed17cda 100644 --- a/src/aaz_dev/swagger/model/schema/parameter.py +++ b/src/aaz_dev/swagger/model/schema/parameter.py @@ -219,6 +219,7 @@ def to_cmd(self, builder, **kwargs): if isinstance(v, CMDObjectSchema): # flatten body parameter v.client_flatten = True + v.non_flatten = None else: raise exceptions.InvalidSwaggerValueError( msg="Invalid Request type",