Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 4 additions & 4 deletions src/aaz_dev/cli/controller/az_arg_group_generator.py
Original file line number Diff line number Diff line change
Expand Up @@ -294,6 +294,10 @@ def render_arg_base(arg, cmd_ctx, arg_kwargs=None):

if isinstance(arg, CMDAnyTypeArgBase):
arg_type = "AAZAnyTypeArg"
elif isinstance(arg, CMDByteArgBase):
raise NotImplementedError()
elif isinstance(arg, CMDBinaryArgBase):
arg_type = "AAZFileUploadArg"
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why it names AAZFileUploadArg? Maybe directly use the AAZFileArg as the name

elif isinstance(arg, CMDStringArgBase):
arg_type = "AAZStrArg"
enum_kwargs = parse_arg_enum(arg.enum)
Expand Down Expand Up @@ -347,10 +351,6 @@ def render_arg_base(arg, cmd_ctx, arg_kwargs=None):
"resource_group_arg": resource_group_arg
}
}
elif isinstance(arg, CMDByteArgBase):
raise NotImplementedError()
elif isinstance(arg, CMDBinaryArgBase):
raise NotImplementedError()
Comment on lines -350 to -353
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Any reason to move it out of the string arg? I think it should be part of the string arg right?

elif isinstance(arg, CMDDurationArgBase):
arg_type = "AAZDurationArg"
elif isinstance(arg, CMDDateArgBase):
Expand Down
40 changes: 38 additions & 2 deletions src/aaz_dev/cli/controller/az_operation_generator.py
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
from command.model.configuration import (
CMDHttpOperation, CMDHttpRequestJsonBody, CMDArraySchema, CMDInstanceUpdateOperation, CMDRequestJson,
CMDHttpOperation, CMDHttpRequestJsonBody, CMDArraySchema, CMDInstanceUpdateOperation, CMDRequestJson, CMDHttpRequestBinaryBody, CMDRequestBinary,
CMDHttpResponseJsonBody, CMDObjectSchema, CMDSchema, CMDStringSchemaBase, CMDIntegerSchemaBase, CMDFloatSchemaBase,
CMDBooleanSchemaBase, CMDObjectSchemaBase, CMDArraySchemaBase, CMDClsSchemaBase, CMDJsonInstanceUpdateAction,
CMDObjectSchemaDiscriminator, CMDSchemaEnum, CMDJsonInstanceCreateAction, CMDJsonInstanceDeleteAction,
CMDObjectSchemaDiscriminator, CMDSchemaEnum, CMDJsonInstanceCreateAction, CMDJsonInstanceDeleteAction, CMDBinarySchema,
CMDInstanceCreateOperation, CMDInstanceDeleteOperation, CMDClientEndpointsByTemplate, CMDIdentityObjectSchemaBase, CMDAnyTypeSchemaBase)
from utils import exceptions
from utils.case import to_snake_case
Expand Down Expand Up @@ -114,10 +114,14 @@ def __init__(self, name, cmd_ctx, operation, client_endpoints):
self.content = None
self.form_content = None
self.stream_content = None
self.content_as_binary = None
if self._operation.http.request.body:
body = self._operation.http.request.body
if isinstance(body, CMDHttpRequestJsonBody):
self.content = AzHttpRequestContentGenerator(self._cmd_ctx, body)
elif isinstance(body, CMDHttpRequestBinaryBody):
self.content_as_binary = True
self.content = AzHttpRequestContentBytesGenerator(self._cmd_ctx, body)
else:
raise NotImplementedError()

Expand Down Expand Up @@ -260,6 +264,19 @@ def header_parameters(self):
True,
{}
])
elif isinstance(body, CMDHttpRequestBinaryBody):
parameters.append([
"Content-Type",
"application/octet-stream",
True,
{}
])
parameters.append([
"Content-Length",
"self.ctx.file_length",
False,
{}
])
if self.success_responses:
for response in self.success_responses:
if response._response.body is not None and isinstance(response._response.body, CMDHttpResponseJsonBody):
Expand Down Expand Up @@ -510,6 +527,23 @@ def iter_scopes(self):
for scopes in _iter_request_scopes_by_schema_base(self.schema, self.BUILDER_NAME, None, arg_key, self._cmd_ctx):
yield scopes

class AzHttpRequestContentBytesGenerator:

def __init__(self, cmd_ctx, body):
self._cmd_ctx = cmd_ctx
assert isinstance(body.bytes, CMDRequestBinary)
self._bodycontent = body.bytes
self.ref = None
if self._bodycontent.ref:
self.ref, is_selector = self._cmd_ctx.get_variant(self._bodycontent.ref)
assert not is_selector
self.arg_key = "self.ctx.args"
if self.ref is None:
assert isinstance(self._bodycontent.schema, CMDSchema)
if self._bodycontent.schema.arg:
self.arg_key, hide = self._cmd_ctx.get_argument(self._bodycontent.schema.arg)
assert not hide


class AzHttpResponseGenerator:

Expand Down Expand Up @@ -990,6 +1024,8 @@ def render_schema_base(schema, cls_map, schema_kwargs=None):
schema_type = "AAZFloatType"
elif isinstance(schema, CMDIdentityObjectSchemaBase):
schema_type = "AAZIdentityObjectType"
elif isinstance(schema, CMDBinarySchema):
schema_type = "AAZFileUploadType"
elif isinstance(schema, CMDObjectSchemaBase):
if schema.props or schema.discriminators:
schema_type = "AAZObjectType"
Expand Down
26 changes: 25 additions & 1 deletion src/aaz_dev/cli/templates/aaz/command/_cmd.py.j2
Original file line number Diff line number Diff line change
Expand Up @@ -236,11 +236,21 @@ class {{ leaf.cls_name }}(

@register_callback
def pre_operations(self):
{%- if leaf.http_operations[0].content is not none and leaf.http_operations[0].content_as_binary is not none %}
self.ctx.file_content, self.ctx.file_handler, self.ctx.file_length = {{ leaf.http_operations[0].content.arg_key }}.to_serialized_data()
{%- else %}
pass
{%- endif %}

@register_callback
def post_operations(self):
{%- if leaf.http_operations[0].content is not none and leaf.http_operations[0].content_as_binary is not none %}
if self.ctx.file_handler is not None:
self.ctx.file_handler.close()
self.ctx.file_handler = None
{%- else %}
pass
{%- endif %}

{%- for op in leaf.operations %}
{%- if op.name in ("pre_instance_update", "post_instance_update", "post_instance_create") %}
Expand Down Expand Up @@ -485,7 +495,7 @@ class {{ leaf.cls_name }}(
return parameters
{%- endif %}

{%- if op.content is not none %}
{%- if op.content is not none and op.content_as_binary is none %}

@property
def content(self):
Expand Down Expand Up @@ -548,6 +558,13 @@ class {{ leaf.cls_name }}(
return self.serialize_content({{ op.content.VALUE_NAME }})
{%- endif %}

{%- if op.content is not none and op.content_as_binary is not none %}

@property
def content(self):
return self.ctx.file_content
{%- endif %}

{%- if op.form_content is not none %}

@property
Expand All @@ -556,6 +573,13 @@ class {{ leaf.cls_name }}(
return None
{%- endif %}

{%- if op.content is not none and op.content_as_binary is not none %}

@property
def stream_content(self):
return self.ctx.file_handler
{%- endif %}

{%- if op.stream_content is not none %}

@property
Expand Down
4 changes: 2 additions & 2 deletions src/aaz_dev/command/model/configuration/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@
CMDConditionAndOperator, CMDConditionOrOperator, CMDConditionNotOperator, CMDConditionHasValueOperator, \
CMDCondition
from ._configuration import CMDConfiguration
from ._content import CMDRequestJson, CMDResponseJson
from ._content import CMDRequestJson, CMDResponseJson, CMDRequestBinary
from ._example import CMDCommandExample
from ._fields import CMDBooleanField, CMDStageField, CMDVariantField, CMDClassField, \
CMDPrimitiveField, CMDRegularExpressionField, CMDVersionField, CMDResourceIdField, CMDCommandNameField, \
Expand All @@ -47,7 +47,7 @@
CMDHttpRequest, \
CMDHttpResponseHeaderItem, CMDHttpResponseHeader, CMDHttpResponse, \
CMDHttpAction
from ._http_request_body import CMDHttpRequestBody, CMDHttpRequestJsonBody
from ._http_request_body import CMDHttpRequestBody, CMDHttpRequestJsonBody, CMDHttpRequestBinaryBody
from ._http_response_body import CMDHttpResponseBody, CMDHttpResponseJsonBody
from ._instance_create import CMDInstanceCreateAction, CMDJsonInstanceCreateAction
from ._instance_delete import CMDInstanceDeleteAction, CMDJsonInstanceDeleteAction
Expand Down
8 changes: 4 additions & 4 deletions src/aaz_dev/command/model/configuration/_arg.py
Original file line number Diff line number Diff line change
Expand Up @@ -384,20 +384,20 @@ def _reformat(self, **kwargs):


# byte: base64 encoded characters
class CMDByteArgBase(CMDStringArgBase):
class CMDByteArgBase(CMDArgBase):
TYPE_VALUE = "byte"


class CMDByteArg(CMDByteArgBase, CMDStringArg):
class CMDByteArg(CMDByteArgBase, CMDArg):
pass


# binary: any sequence of octets
class CMDBinaryArgBase(CMDStringArgBase):
class CMDBinaryArgBase(CMDArgBase):
TYPE_VALUE = "binary"


class CMDBinaryArg(CMDBinaryArgBase, CMDStringArg):
class CMDBinaryArg(CMDBinaryArgBase, CMDArg):
pass


Expand Down
4 changes: 3 additions & 1 deletion src/aaz_dev/command/model/configuration/_arg_builder.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
from ._format import CMDFormat
from ._schema import CMDObjectSchema, CMDSchema, CMDSchemaBase, CMDObjectSchemaBase, CMDObjectSchemaDiscriminator, \
CMDArraySchemaBase, CMDArraySchema, CMDObjectSchemaAdditionalProperties, CMDResourceIdSchema, \
CMDResourceLocationSchemaBase, CMDPasswordSchema, CMDBooleanSchemaBase
CMDResourceLocationSchemaBase, CMDPasswordSchema, CMDBooleanSchemaBase, CMDBinarySchema
from ..configuration._schema import CMDIdentityObjectSchema, CMDStringSchemaBase, \
CMDStringSchema

Expand Down Expand Up @@ -381,6 +381,8 @@ def get_options(self):

if self.schema.action is not None and self.schema.name in ["userAssigned", "systemAssigned"]:
return [opt_name, "mi-" + opt_name]
if isinstance(self.schema, CMDBinarySchema):
return [opt_name, "body-file", "body-file-path"]
else:
raise NotImplementedError()
return [opt_name, ]
Expand Down
54 changes: 53 additions & 1 deletion src/aaz_dev/command/model/configuration/_content.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
from ._arg_builder import CMDArgBuilder
from ._fields import CMDVariantField
from ._schema import CMDSchemaBaseField, CMDSchema, CMDClsSchema, CMDClsSchemaBase, \
CMDObjectSchemaBase, CMDArraySchemaBase, CMDObjectSchemaDiscriminator
CMDObjectSchemaBase, CMDArraySchemaBase, CMDObjectSchemaDiscriminator, CMDBinarySchema
from ._utils import CMDDiffLevelEnum


Expand Down Expand Up @@ -63,6 +63,58 @@ def reformat(self, schema_cls_map, **kwargs):
def register_cls(self, cls_register_map, **kwargs):
_iter_over_schema_for_cls_register(self.schema, cls_register_map)

class CMDRequestBinary(Model):
"""Used for Request Binary Body"""

ref = CMDVariantField()

schema = PolyModelType(CMDBinarySchema, allow_subclasses=False)

class Options:
serialize_when_none = False

def generate_args(self, ref_args, var_prefix=None, is_update_action=False):
if not self.schema:
return []
assert isinstance(self.schema, CMDBinarySchema)
builder = CMDArgBuilder.new_builder(
schema=self.schema,
ref_args=ref_args,
var_prefix=var_prefix,
is_update_action=is_update_action
)
args = builder.get_args()
return args

def diff(self, old, level):
diff = {}
if level >= CMDDiffLevelEnum.BreakingChange:
if (self.ref is not None) != (old.ref is not None):
diff["ref"] = f"{old.ref} != {self.ref}"
schema_diff = self.schema.diff(old.schema, level)
if schema_diff:
diff["schema"] = schema_diff

if level >= CMDDiffLevelEnum.Associate:
if self.ref != old.ref:
diff["ref"] = f"{old.ref} != {self.ref}"
return diff

def reformat(self, schema_cls_map, **kwargs):
if self.schema:
if getattr(self.schema, 'cls', None):
if not schema_cls_map.get(self.schema.cls, None):
schema_cls_map[self.schema.cls] = self.schema
else:
# replace by CMDClsSchema
self.schema = CMDClsSchema.build_from_schema(self.schema, schema_cls_map[self.schema.cls])

_iter_over_schema(self.schema, schema_cls_map)

self.schema.reformat(**kwargs)

def register_cls(self, cls_register_map, **kwargs):
_iter_over_schema_for_cls_register(self.schema, cls_register_map)

class CMDResponseJson(Model):
# properties as tags
Expand Down
21 changes: 20 additions & 1 deletion src/aaz_dev/command/model/configuration/_http_request_body.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
from schematics.models import Model
from schematics.types import ModelType

from ._content import CMDRequestJson
from ._content import CMDRequestJson, CMDRequestBinary


class CMDHttpRequestBody(Model):
Expand Down Expand Up @@ -50,3 +50,22 @@ def reformat(self, **kwargs):

def register_cls(self, **kwargs):
self.json.register_cls(**kwargs)

class CMDHttpRequestBinaryBody(CMDHttpRequestBody):
POLYMORPHIC_KEY = "bytes"

bytes = ModelType(CMDRequestBinary, required=True)

def generate_args(self, ref_args, var_prefix=None):
return self.bytes.generate_args(ref_args=ref_args, var_prefix=var_prefix)

def diff(self, old, level):
if not isinstance(old, self.__class__):
return f"Response type changed: '{type(old)}' != '{self.__class__}'"
return self.bytes.diff(old.bytes, level)

def reformat(self, **kwargs):
self.bytes.reformat(**kwargs)

def register_cls(self, **kwargs):
self.bytes.register_cls(**kwargs)
18 changes: 14 additions & 4 deletions src/aaz_dev/command/model/configuration/_schema.py
Original file line number Diff line number Diff line change
Expand Up @@ -489,22 +489,32 @@ class CMDStringSchema(CMDStringSchemaBase, CMDSchema):


# byte: base64 encoded characters
class CMDByteSchemaBase(CMDStringSchemaBase):
class CMDByteSchemaBase(CMDSchemaBase):
TYPE_VALUE = "byte"
ARG_TYPE = CMDByteArgBase


class CMDByteSchema(CMDByteSchemaBase, CMDStringSchema):
class CMDByteSchema(CMDByteSchemaBase, CMDSchema):
ARG_TYPE = CMDByteArg


# binary: any sequence of octets
class CMDBinarySchemaBase(CMDStringSchemaBase):
class CMDBinarySchemaBase(CMDSchemaBase):
TYPE_VALUE = "binary"
ARG_TYPE = CMDBinaryArgBase
name = StringType(required=True)
arg = CMDVariantField()
required = CMDBooleanField()

description = CMDDescriptionField()

fmt = ModelType(
CMDStringFormat,
serialized_name='format',
deserialize_from='format'
)

class CMDBinarySchema(CMDBinarySchemaBase, CMDStringSchema):
class CMDBinarySchema(CMDBinarySchemaBase, CMDSchema):
ARG_TYPE = CMDBinaryArg


Expand Down
Loading