-
Notifications
You must be signed in to change notification settings - Fork 3.1k
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
resource: support resource id for show/delete/tag #1280
Conversation
5f61e47
to
aaaea9b
Compare
@tjprescott, could you please take a look? |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
A few questions and some minor tweaks requested, but otherwise LGTM (and no I don't know why I'm reviewing PRs at 5 am)
|
||
register_cli_argument('resource', 'resource_type', help='The resource type in <namespace>/<type> format.', type=validate_resource_type, validator=resolve_resource_parameters) | ||
register_cli_argument('resource', 'parent_resource_path', help='The parent resource type in <type>/<name> format.', type=validate_parent, required=False, options_list=('--parent',)) | ||
register_cli_argument('resource', 'resource_id', options_list=('--id',), help='resource id') |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Should we reasonably expect the --ids
semantic (of looping through multiple ids) to work here? If it can be done easily, I would suggest that we do. If it can't, then I wouldn't worry about it for this PR.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thought about it, the ids will have to pair with api-versions
, and have a many to many association between 2 value groups won't make command easier to use. So let us punt for now
help="resource namespaces like 'Microsoft.Network'. You can also specify it through --resource-type parameter") | ||
register_cli_argument('resource', 'resource_type', help="types such as 'virtualNetworks', or optional include namespace such as 'Microsoft.Network/virtualNetworks'") | ||
register_cli_argument('resource', 'parent_resource_path', required=False, options_list=('--parent',), | ||
help="path in formats of '<parent-type>/<parent-name>' or '<grandparent-type>/<grandparent-name>/<parent-type>/<parent-name>'") |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Here it might be better to give examples such as a SQL server and database path for the grandparent case and pretty much any normal one for the parent-type/parent-name case.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Sql Server
and database
is still parent-child relationship. I have added a concrete example.
For grand parent relationship, I searched across cli, looks like we only have one case on app gateway url-path-map rules. Do you have related resource types detail?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ah, no, you're right.
register_cli_argument('resource', 'resource_id', options_list=('--id',), help='resource id') | ||
register_cli_argument('resource', 'resource_provider_namespace', options_list=('--namespace',), completer=get_providers_completion_list, | ||
help="resource namespaces like 'Microsoft.Network'. You can also specify it through --resource-type parameter") | ||
register_cli_argument('resource', 'resource_type', help="types such as 'virtualNetworks', or optional include namespace such as 'Microsoft.Network/virtualNetworks'") |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Should there be a completer on this? Are we maintaining the ability to optionally include the namespace here to avoid breaking changes?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes, we are still maintaining this ability. This one is a redundant, so I have removed. We have another similar registration at a few lines above which does have a completer
'API version is required and could not be resolved for resource {}/{}' | ||
.format(resource_type.namespace, resource_type.type)) | ||
|
||
def resolve_resource_parameters(namespace): |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If we maintain the ability to specify resource_type
as 'provider/type' then where do we do that sniffing/parsing/checking?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yep, we still maintain the logic, check out the new code in _ResourceUtils.__init__
api_version, | ||
parameters) | ||
except CloudError as ex: | ||
# TODO: Remove workaround once Swagger and SDK fix is implemented (#120123723) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm assuming this block of logic has been moved and not removed. Is this workaround still needed?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yep, this is the existing code, but agree we can remove now
the related issue is still active, but current generated code already handles 202 , I think we are good. The new tests I added also worked. So we can close that issue as well
parent_resource_path or resource_provider_namespace or | ||
resource_name): | ||
raise IncorrectUsageError( | ||
"You must specify either 'id' or other individual pieces, but not both") |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You might put this in usage statement form, like the error for incorrect use of --ids
does. So something like (--id ID | --resource-group RG --name NAME --provider ...)
register_cli_argument('resource', 'resource_provider_namespace', options_list=('--namespace',), completer=get_providers_completion_list, | ||
help="resource namespaces like 'Microsoft.Network'. You can also specify it through --resource-type parameter") | ||
register_cli_argument('resource', 'resource_type', help="types such as 'virtualNetworks', or optional include namespace such as 'Microsoft.Network/virtualNetworks'") | ||
register_cli_argument('resource', 'parent_resource_path', required=False, options_list=('--parent',), |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think we should add these parameters to the same arg_group as is automatically done with the --ids parameter. This would be a more consistent experience even if we don't support the automatic looping mechanic of --ids.
@@ -398,7 +397,7 @@ def __init__(self, resource_group_name=None, resource_provider_namespace=None, | |||
parent_resource_path or resource_provider_namespace or | |||
resource_name): | |||
raise IncorrectUsageError( | |||
"You must specify either 'id' or other individual pieces, but not both") | |||
"(--id ID | --resource-group RG --name NAME --namespace NAMESPACE --resource-type TYPE -n NAME)") #pylint: disable=line-too-long |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think the usage string would be (--id ID | --resource-group RG --name NAME [--namespace NAMESPACE] --resource-type TYPE)
since namespace is optional and you don't need --name NAME and -n NAME.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks for making this in!
type: command | ||
short-summary: list resource | ||
examples: | ||
- name: list all resource in a region |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I know this is not related to resource Id change, but "list all resource in a region" ? Why? Does it list all resources in a subscription?
text: > | ||
az resource show -g mygroup -n mywebapp --resource-type "Microsoft.web/sites" | ||
az resource show -g myGroup --namespace Microsoft.Network --parent applicationGateways/ag1/urlPathMaps/map1 --resource-type pathRules -n rule1 |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We want to move away from this "parent" parameter - only makes it harder for users to identify a resource.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
user can use --id
, we can't hide the --parent
|
||
helps['resource tag'] = """ | ||
type: command | ||
short-summary: tag a resource. Reference the examples for help with arguments. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I would have expected "resource tag create" to actually add a tag on a resource.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
please open an issue, imo, tag
is good enough, unless we will have list
, 'delete', etc
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes, we should definitely have a way to delete a tag (unless removal of tag by using update command with nulled out tag properties is already supported)
|
||
helps['resource update'] = """ | ||
type: command | ||
short-summary: update a resource |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
No help for this?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is so called generic update
, help for common flags is already provided
help="Provider namespace (Ex: 'Microsoft.Provider')") | ||
register_cli_argument('resource', 'resource_type', | ||
completer=get_resource_types_completion_list, | ||
help="The resource type (Ex: 'resC'). Can also accept namespace/type format (Ex: 'Microsoft.Provider/resC')") |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why would a resource type also accept provider namespace, like Microsoft.Provider/resc format? Does that mean the provider namespace parameter above is optional?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Correct, the namespace is optional. We saw vm show
, vnet show
etc, all return namespace/type
, so we decided to support it then people can pipe output
@@ -409,3 +389,124 @@ def get_policy_assignment_completion_list(prefix, **kwargs):#pylint: disable=unu | |||
result = policy_client.policy_assignments.list() | |||
return [i.name for i in result] | |||
|
|||
class _ResourceUtils(object): #pylint: disable=too-many-instance-attributes | |||
def __init__(self, resource_group_name=None, resource_provider_namespace=None, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Don't we validate the provided --id is in the correct format (/subscriptions/subId/resourceGroups/rgName/providers/Microsoft.Compute/vm) before making the request?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
By default we don't want to validate input for API which is not LRO and server error is clear. But for this command, we do validation when api-version is missing, which we expect would be the majority case
raise IncorrectUsageError('Resource type {} not found.' | ||
.format(resource_type_str)) | ||
if len(rt) == 1 and rt[0].api_versions: | ||
npv = [v for v in rt[0].api_versions if 'preview' not in v.lower()] |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Just curious - what does the var npv stand for? It isn't obvious to me.
raise IncorrectUsageError('Resource type {} not found.' | ||
.format(resource_type_str)) | ||
if len(rt) == 1 and rt[0].api_versions: | ||
npv = [v for v in rt[0].api_versions if 'preview' not in v.lower()] |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
So, we ignore the preview api versions here?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
correct. let us know we should use
return npv[0] if npv else rt[0].api_versions[0] | ||
else: | ||
raise IncorrectUsageError( | ||
'API version is required and could not be resolved for resource {}' |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm not sure if this is even possible. All resource types WILL have an api-version
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
this is mostly for when the type providerd by users are invalid
@yugangw-msft Thanks for making the changes for us. Do all ARM commands work for tenant level (no subscription) resources as well? |
@vivsriaus I don't think so. Does xplat work for that? Please provide more information |
@yugangw-msft xplat doesn't, but the generic resource cmdlets in powershell do (New-Resource, Get-Resource, Set-Resource, Remove-Resource). For example, to get a tenant level powerapps resource: Get-AzureRmResource -ResourceId providers/Microsoft.PowerApps/apps/69fb28f7-9bb3-2766-2b0e-b9449f10fa3c -ApiVersion 2015-02-01-preview |
@vivsriaus, good to know. Since only limited resource types can be tenant level, including |
No description provided.