Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Feature support userAssignedIdentities object #89

Merged
merged 5 commits into from
Jul 20, 2022
Merged
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
24 changes: 11 additions & 13 deletions src/aaz_dev/cli/controller/az_arg_group_generator.py
Original file line number Diff line number Diff line change
Expand Up @@ -238,9 +238,6 @@ def render_arg(arg, cmd_ctx, arg_group=None):
if arg.default:
arg_kwargs["default"] = arg.default.value

if arg.blank:
arg_kwargs["blank"] = arg.blank.value

arg_type, arg_kwargs, cls_builder_name = render_arg_base(arg, cmd_ctx, arg_kwargs)

return arg_type, arg_kwargs, cls_builder_name
Expand All @@ -260,6 +257,9 @@ def render_arg_base(arg, cmd_ctx, arg_kwargs=None):
if arg.nullable:
arg_kwargs['nullable'] = True

if arg.blank:
arg_kwargs["blank"] = arg.blank.value

if isinstance(arg, CMDStringArgBase):
arg_type = "AAZStrArg"
enum = parse_arg_enum(arg.enum)
Expand Down Expand Up @@ -395,34 +395,32 @@ def render_arg_base(arg, cmd_ctx, arg_kwargs=None):
# raise NotImplementedError()

elif isinstance(arg, CMDObjectArgBase):
if arg.args:
arg_type = "AAZObjectArg"
if arg.additional_props:
raise NotImplementedError()
if arg.additional_props:
arg_type = "AAZDictArg"
if arg.fmt is not None:
assert isinstance(arg.fmt, CMDObjectFormat)
arg_kwargs['fmt'] = fmt = {
"cls": "AAZObjectArgFormat",
"cls": "AAZDictArgFormat",
"kwargs": {}
}
if arg.fmt.max_properties is not None:
fmt['kwargs']['max_properties'] = arg.fmt.max_properties
if arg.fmt.min_properties is not None:
fmt['kwargs']['min_properties'] = arg.fmt.min_properties
elif arg.additional_props:
arg_type = "AAZDictArg"
else:
arg_type = "AAZObjectArg"
if arg.additional_props:
raise NotImplementedError()
if arg.fmt is not None:
assert isinstance(arg.fmt, CMDObjectFormat)
arg_kwargs['fmt'] = fmt = {
"cls": "AAZDictArgFormat",
"cls": "AAZObjectArgFormat",
"kwargs": {}
}
if arg.fmt.max_properties is not None:
fmt['kwargs']['max_properties'] = arg.fmt.max_properties
if arg.fmt.min_properties is not None:
fmt['kwargs']['min_properties'] = arg.fmt.min_properties
else:
raise NotImplementedError()

elif isinstance(arg, CMDArrayArgBase):
arg_type = "AAZListArg"
Expand Down
29 changes: 15 additions & 14 deletions src/aaz_dev/cli/controller/az_operation_generator.py
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,8 @@ def __init__(self, name, cmd_ctx, operation):
self.success_responses.append(AzHttpResponseGenerator(self._cmd_ctx, response))
else:
if not isinstance(response.body, CMDHttpResponseJsonBody):
raise NotImplementedError()
raise exceptions.InvalidAPIUsage(
f"Invalid error response body: Only support json, current is '{type(response.body)}'")
schema = response.body.json.schema
if not isinstance(schema, CMDClsSchemaBase):
raise NotImplementedError()
Expand Down Expand Up @@ -490,24 +491,27 @@ def _iter_request_scopes_by_schema_base(schema, name, scope_define, arg_key, cmd
s_name = s.name
s_typ, s_typ_kwargs, cls_builder_name = render_schema(s, cmd_ctx.update_clses, s_name)
if s.arg:
# current schema linked with argument
s_arg_key, hide = cmd_ctx.get_argument(s.arg)
if hide:
continue
else:
# current schema not linked with argument, then use current arg_key
s_arg_key = arg_key

# handle enum item attached with argument
has_enum_argument = False
if hasattr(s, "enum") and isinstance(s.enum, CMDSchemaEnum):
for item in s.enum.items:
if item.arg:
# enum item linked with argument
item_arg_key, hide = cmd_ctx.get_argument(item.arg)
if hide:
continue
has_enum_argument = True
r_key = item_arg_key.replace(arg_key, '')
if not r_key:
r_key = '.'
r_key = '.' # which means if the arg exist, fill it
is_const = True
const_value = item.value
rendered_schemas.append(
Expand All @@ -517,7 +521,7 @@ def _iter_request_scopes_by_schema_base(schema, name, scope_define, arg_key, cmd
if not has_enum_argument:
r_key = s_arg_key.replace(arg_key, '')
if not r_key:
r_key = '.' if s.required else None
r_key = '.' if s.required else None # which means if the parent exist, fill it

is_const = False
const_value = None
Expand All @@ -533,15 +537,12 @@ def _iter_request_scopes_by_schema_base(schema, name, scope_define, arg_key, cmd
search_schemas[s_name] = (s, s_arg_key)

elif schema.additional_props:
assert schema.additional_props.item is not None
assert schema.additional_props.item is not None # make sure additional props schema defined its element schema
s = schema.additional_props.item
s_name = '{}'
s_typ, s_typ_kwargs, cls_builder_name = render_schema_base(s, cmd_ctx.update_clses)
s_arg_key = arg_key + '{}'
if not isinstance(s, (CMDObjectSchemaBase, CMDArraySchemaBase)):
r_key = '.'
else:
r_key = None
r_key = '.' # if element exist, always fill it

is_const = False
const_value = None
Expand All @@ -560,17 +561,20 @@ def _iter_request_scopes_by_schema_base(schema, name, scope_define, arg_key, cmd
s_name = s.name
s_typ, s_typ_kwargs, cls_builder_name = render_schema(s, cmd_ctx.update_clses, s_name)
if s.arg:
# current schema linked with argument
s_arg_key, hide = cmd_ctx.get_argument(s.arg)
if hide:
continue
else:
# current schema not linked with argument, then use current arg_key
s_arg_key = arg_key

# handle enum item attached with argument
has_enum_argument = False
if hasattr(s, "enum") and isinstance(s.enum, CMDSchemaEnum):
for item in s.enum.items:
if item.arg:
# enum item linked with argument
item_arg_key, hide = cmd_ctx.get_argument(item.arg)
if hide:
continue
Expand Down Expand Up @@ -600,19 +604,16 @@ def _iter_request_scopes_by_schema_base(schema, name, scope_define, arg_key, cmd
)
if not cls_builder_name and not is_const \
and isinstance(s, (CMDObjectSchemaBase, CMDArraySchemaBase)):
# step into object and array schemas
search_schemas[s_name] = (s, s_arg_key)

elif isinstance(schema, CMDArraySchemaBase):
assert schema.item is not None
assert schema.item is not None # make sure array schema defined its element schema
s = schema.item
s_name = "[]"
s_typ, s_typ_kwargs, cls_builder_name = render_schema_base(s, cmd_ctx.update_clses)
s_arg_key = arg_key + '[]'

if not isinstance(s, (CMDObjectSchemaBase, CMDArraySchemaBase)):
r_key = '.'
else:
r_key = None
r_key = '.' # if element exist, always fill it

is_const = False
const_value = None
Expand Down
1 change: 1 addition & 0 deletions src/aaz_dev/command/model/configuration/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,7 @@
CMDFloat32SchemaBase, CMDFloat32Schema, \
CMDFloat64SchemaBase, CMDFloat64Schema, \
CMDObjectSchemaDiscriminator, CMDObjectSchemaAdditionalProperties, CMDObjectSchemaBase, CMDObjectSchema, \
CMDIdentityObjectSchemaBase, CMDIdentityObjectSchema, \
CMDArraySchemaBase, CMDArraySchema
from ._utils import CMDDiffLevelEnum, DEFAULT_CONFIRMATION_PROMPT
from ._xml import XMLSerializer
9 changes: 7 additions & 2 deletions src/aaz_dev/command/model/configuration/_arg.py
Original file line number Diff line number Diff line change
Expand Up @@ -101,6 +101,8 @@ class CMDArgBase(Model):

nullable = CMDBooleanField() # whether can pass null value or not.

blank = ModelType(CMDArgBlank) # blank value is used when argument don't have any value

class Options:
serialize_when_none = False

Expand Down Expand Up @@ -130,6 +132,7 @@ def _claim_polymorphic(cls, data):
def build_arg_base(cls, builder):
arg_base = cls()
arg_base.nullable = builder.get_nullable()
arg_base.blank = builder.get_blank()
return arg_base

def _reformat_base(self, **kwargs):
Expand Down Expand Up @@ -196,7 +199,6 @@ class CMDArg(CMDArgBase):
# properties as nodes
help = ModelType(CMDArgumentHelp)
default = ModelType(CMDArgDefault) # default value is used when argument isn't in command
blank = ModelType(CMDArgBlank) # blank value is used when argument don't have any value

def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
Expand All @@ -222,7 +224,6 @@ def build_arg(cls, builder):

arg.required = builder.get_required()
arg.default = builder.get_default()
arg.blank = builder.get_blank()

arg.hide = builder.get_hide()
return arg
Expand Down Expand Up @@ -607,6 +608,10 @@ def build_arg_base(cls, builder):
raise
arg.args = builder.get_sub_args()
arg.additional_props = builder.get_additional_props()
if not arg.args and not arg.additional_props:
# when object arg don't have args or additional_props, set its blank value as empty dict
arg.blank = CMDArgBlank()
arg.blank.value = {}
arg.cls = builder.get_cls()
return arg

Expand Down
2 changes: 1 addition & 1 deletion src/aaz_dev/command/model/configuration/_format.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
from schematics.models import Model
from schematics.types import StringType, FloatType, IntType
from ._fields import CMDRegularExpressionField, CMDBooleanField, CMDVariantField
from ._fields import CMDRegularExpressionField, CMDBooleanField
from ._utils import CMDDiffLevelEnum


Expand Down
12 changes: 12 additions & 0 deletions src/aaz_dev/command/model/configuration/_schema.py
Original file line number Diff line number Diff line change
Expand Up @@ -875,6 +875,18 @@ def _diff(self, old, level, diff):
return diff


class CMDIdentityObjectSchemaBase(CMDObjectSchemaBase):
""" And identity object which contains 'userAssignedIdentities' property and 'type' property
with "SystemAssigned", "UserAssigned", "SystemAssigned, UserAssigned" and "None" enum values.
"""
TYPE_VALUE = "IdentityObject"
ARG_TYPE = CMDObjectArgBase


class CMDIdentityObjectSchema(CMDIdentityObjectSchemaBase, CMDObjectSchema):
ARG_TYPE = CMDObjectArg


# array
class CMDArraySchemaBase(CMDSchemaBase):
TYPE_VALUE = "array"
Expand Down
4 changes: 2 additions & 2 deletions src/aaz_dev/swagger/model/schema/cmd_builder.py
Original file line number Diff line number Diff line change
Expand Up @@ -187,8 +187,8 @@ def build_schema(self, schema):
else:
raise exceptions.InvalidSwaggerValueError(
f"format is not supported", key=getattr(schema, "traces", None), value=[schema_type, schema.format])
elif schema_type == "object" or getattr(schema, "properties", None) or getattr(schema, "additional_properties",
None):
elif schema_type == "object" or getattr(schema, "properties", None) or \
getattr(schema, "additional_properties", None):
if schema.format is None:
if self.in_base:
model = CMDObjectSchemaBase()
Expand Down
18 changes: 15 additions & 3 deletions src/aaz_dev/swagger/model/schema/schema.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
CMDStringSchema, CMDResourceIdSchema, CMDResourceIdFormat, \
CMDResourceLocationSchema, \
CMDObjectSchemaBase, CMDObjectSchemaDiscriminator, CMDObjectSchemaAdditionalProperties, \
CMDArraySchemaBase, CMDObjectSchema
CMDArraySchemaBase, CMDObjectSchema, CMDIdentityObjectSchema, CMDIdentityObjectSchemaBase
from command.model.configuration import CMDSchemaEnum, CMDSchemaEnumItem, CMDSchema, CMDSchemaBase
from swagger.utils import exceptions
from .external_documentation import ExternalDocumentation
Expand Down Expand Up @@ -436,7 +436,7 @@ def to_cmd(self, builder, **kwargs):
# because required property will not be included in a cls definition,
# so it's fine to update it in parent level when prop_dict[name] is a cls definition.
prop_dict[name].required = True
# when a property is required, it's frozen status must be consist with the defined schema.
# when a property is required, it's frozen status must be consisted with the defined schema.
# This can help to for empty object schema.
prop_dict[name].frozen = builder.frozen

Expand Down Expand Up @@ -521,6 +521,15 @@ def to_cmd(self, builder, **kwargs):
prop_dict['location'] = CMDResourceLocationSchema(raw_data=raw_data)

if prop_dict:
if "userAssignedIdentities" in prop_dict and "type" in prop_dict:
if isinstance(model, CMDObjectSchema):
# Transfer to IdentityObjectSchema
model = CMDIdentityObjectSchema(model.to_native())
elif isinstance(model, CMDObjectSchemaBase):
# Transfer to IdentityObjectSchemaBase
model = CMDIdentityObjectSchemaBase(model.to_native())
else:
raise NotImplementedError()
model.props = []
for prop in prop_dict.values():
model.props.append(prop)
Expand All @@ -533,7 +542,9 @@ def to_cmd(self, builder, **kwargs):
assert isinstance(v, CMDSchemaBase)
model.additional_props = CMDObjectSchemaAdditionalProperties()
model.additional_props.item = v
model.additional_props.frozen = v.frozen
# item is required, it's frozen status must be consisted with the defined schema.
# This can help to for empty object.
model.additional_props.item.frozen = builder.frozen
# Note: not support additional_properties without schema define
# elif self.additional_properties is True:
# model.additional_props = CMDObjectSchemaAdditionalProperties()
Expand Down Expand Up @@ -568,6 +579,7 @@ def to_cmd(self, builder, **kwargs):
# Note: model will always frozen when object without any props, additional_props or discriminators,
# If this property is required by parent schema, it will be updated in parent.
model.frozen = need_frozen

else:
if self.all_of is not None:
# inherent from allOf
Expand Down
23 changes: 14 additions & 9 deletions src/web/src/views/workspace/WSEditorCommandArgumentsContent.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -1145,13 +1145,16 @@ function ArgumentPropsReviewer(props: {
onSelectSubArg: (subArgVar: string) => void,
}) {
const groupArgs: { [name: string]: CMDArg[] } = {};
props.args.forEach((arg) => {
const groupName: string = arg.group.length > 0 ? arg.group : "";
if (!(groupName in groupArgs)) {
groupArgs[groupName] = []
}
groupArgs[groupName].push(arg)
})
if (props.args !== undefined) {
props.args.forEach((arg) => {
const groupName: string = arg.group.length > 0 ? arg.group : "";
if (!(groupName in groupArgs)) {
groupArgs[groupName] = []
}
groupArgs[groupName].push(arg)
})
}

const groups: ArgGroup[] = []

for (const groupName in groupArgs) {
Expand Down Expand Up @@ -1265,6 +1268,10 @@ function ArgumentPropsReviewer(props: {
</Box>)
}

if (groups.length == 0) {
return (<></>)
}

return (<React.Fragment>
<Box sx={{
p: 2,
Expand Down Expand Up @@ -1560,8 +1567,6 @@ function decodeArgBase(response: any): { argBase: CMDArgBase, clsDefineMap: ClsA
type: argBaseType,
item: itemArgBaseParse.argBase
}
} else {
throw Error("Invalid object arguments, neither args nor additionalProps exist")
}

if (response.cls) {
Expand Down