Skip to content

Support Wait/No-Wait#1463

Merged
yugangw-msft merged 11 commits intoAzure:masterfrom
yugangw-msft:nowait3
Dec 1, 2016
Merged

Support Wait/No-Wait#1463
yugangw-msft merged 11 commits intoAzure:masterfrom
yugangw-msft:nowait3

Conversation

@yugangw-msft
Copy link
Copy Markdown
Contributor

@yugangw-msft yugangw-msft commented Nov 29, 2016

Submit it to leverage CI to catch regressions. Still finalizing the change, but feel free to put in comments.
Fix #1071, Fix #1169

This change enable author to expose --no-wait from long running command, and also expose wait commands to wait on any conditions based on read api.

Command
    az vm wait

Arguments

Resource Id Arguments
    --ids              : One or more resource IDs. If provided, no other 'Resource Id' arguments
                         should be specified.
    --name -n          : The name of the virtual machine.
    --resource-group -g: Name of resource group.

Wait Condition Arguments
    --created          : Wait till created with 'provisioningState' at 'Succeeded'.
    --custom           : Wait until the condition satisfies a custom JMESPath query. E.g.
                         provisioningState!='InProgress',
                         instanceView.statuses[?code=='PowerState/running'].
    --deleted          : Wait till deleted.
    --exists           : Wait till the resource exists.
    --interval         : Polling interval in seconds.  Default: 30.
    --timeout          : Maximum wait in seconds.  Default: 3600.
    --updated          : Wait till updated with provisioningState at 'Succeeded'.

@mention-bot
Copy link
Copy Markdown

@yugangw-msft, thanks for your PR! By analyzing the history of the files in this pull request, we identified @derekbekoe, @johanste, @tjprescott, @brendandburns and @zooba to be potential reviewers.

@@ -240,10 +241,10 @@ def register_extra_cli_argument(command, dest, **kwargs):
_cli_extra_argument_registry[command][dest] = CliCommandArgument(dest, **kwargs)

def cli_command(module_name, name, operation,
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Should we add a **kwargs argument if we expect to add more of these "pass-through" parameters?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Agreed. After the main logic gets reviewed, I will consolidate

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Just so long as the public facing cli_command(...) call does not use kwargs (coughresource_idcough)

Copy link
Copy Markdown
Member

@tjprescott tjprescott left a comment

Choose a reason for hiding this comment

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

Mostly just some comments from what I saw in the help text. I'll do a more detailed review when you are ready to merge it.

cmd.add_argument('deleted', '--deleted', action='store_true', arg_group=group_name,
help='wait till deleted')
cmd.add_argument('created', '--created', action='store_true', arg_group=group_name,
help="wait till created with 'provisitioningState' at 'Succeeded'")
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

typo: provisioningState instead of provisitioningState. Also line 410.

help="wait till updated with provisitioningState at 'Succeeded'")
cmd.add_argument('exists', '--exists', action='store_true', arg_group=group_name,
help="wait till the resource exists")
cmd.add_argument('property', '--property', arg_group=group_name,
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Recommend '--custom' and a message like "Wait until the condition satisfies a custom JMESPath query."


cmd = CliCommand(name, handler, table_transformer=table_transformer,
arguments_loader=arguments_loader)
group_name = 'Wait'
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Recommend 'Wait Condition'

@colemickens
Copy link
Copy Markdown
Contributor

What would example usage of this look like with a template deployment for example? I guess I'd name the deployment and then I could later wait on the deployment?

az resource group create --name coletest1 --location westus
az resource group deployment create \
    --name deploy01 \
    --template-file "./template.json" \
    --parameters "@./parameters.json" \
    --nowait
az resource group deployment wait --name deploy01

Something like that roughly?

@tjprescott
Copy link
Copy Markdown
Member

@colemickens that's right. Each resource (deployment being the resource in this case) will expose a wait command which lets you poll on some property that is exposed through that resource's GET method. You would probably have to add the --created flag to your wait though.

@yugangw-msft
Copy link
Copy Markdown
Contributor Author

@colemickens, that is correct.

    az resource group deployment wait --name deploy01 --created

@yugangw-msft
Copy link
Copy Markdown
Contributor Author

@colemickens, you can also use --custom to wait on any other conditions.

@colemickens
Copy link
Copy Markdown
Contributor

In this case --created seems like a bit of a misnomer. Why --created and not --success or --succeeded ?

In this case, and normal ARM teminology... the deployment is "created" as soon as the 201/202 is sent back... and transitions from InProgess to Succeeded.

It's a tiny bit confusing, but I guess for other resources the meaning is pretty clear.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

So if 'raw' not in kwargs, we essentially ignore the --no-wait parameter?
Will this be a common thing, if so, consider adding logger.warning message like 'Ignoring no wait because ...'.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

The no-wait is a parameter alias on raw. This if condition makes sure the command returns nothing on no-wait, since we don't have yet the final result to return to users.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Or perhaps it should be an error instead of a warning. If you register no-wait on a command that doesn't support raw, then I would argue it would be better to have that fail positively than just vaguely "not work".

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

I will raise exception in _introspection.py where we do parameter excursion and alias

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

I think to match the parameter names:
create -> created
delete -> deleted
exits -> exists

If 'property' a valid flag?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

thanks, I forgot to rename it to custom

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

  1. Looks like 'property' was renamed 'custom' so this just needs to be updated. Also, 'exists' is misspelled 'exits'.

  2. We might consider having a default here instead of raising an error when nothing is specified.

  3. Also, recommend this form for the error: "incorrect usage: --created | --updated | --deleted | --exists | --custom JMESPATH"

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Do the wait commands return objects?
Looks like it won't return anything?

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Correct. When the wait is successful you are returned to the command prompt. GET is an implementation detail behind the wait, but there's no need to return the object from the final GET.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

More descriptive message like 'Wait operation timed-out after X seconds'

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Would be good if there was a validator on this parameter to check that the string is a valid JMESPath query so the command will fail even before any API calls are made.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

I think it does that at line 423 essentially. It compiles the JMESPath, which should raise an error if it is invalid.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Yep. Invalid JmesPath will be raised

@yugangw-msft
Copy link
Copy Markdown
Contributor Author

yugangw-msft commented Nov 30, 2016

@colemickens

In this case --created seems like a bit of a misnomer. Why --created and not --success or --succeeded ?

I felt about the same. Let me think about whether I can improve the naming. For lots of "create" commands, --created does make sense though.

@tjprescott
Copy link
Copy Markdown
Member

tjprescott commented Nov 30, 2016

@colemickens --created because your command was to create the deployment, but I see your point. I think --exists most closely matches what you are describing. The option names are still in flux so feedback is good. :)

But I don't think customers will care so much what the ARM team considers created, so we want to go with what will make sense to them.

Copy link
Copy Markdown
Member

@tjprescott tjprescott left a comment

Choose a reason for hiding this comment

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

Overall, I'm really excited to get this change in. Changes requested are mostly typos, but also some other questions.

@@ -240,10 +241,10 @@ def register_extra_cli_argument(command, dest, **kwargs):
_cli_extra_argument_registry[command][dest] = CliCommandArgument(dest, **kwargs)

def cli_command(module_name, name, operation,
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Just so long as the public facing cli_command(...) call does not use kwargs (coughresource_idcough)

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Or perhaps it should be an error instead of a warning. If you register no-wait on a command that doesn't support raw, then I would argue it would be better to have that fail positively than just vaguely "not work".

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

This should be positively resolved during the command registration, so I would argue you simply get the raw property here.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

My concern is it is possible (though very unlikely) an custom method might contain raw parameter for other purpose.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Or we can consider to letting the command registration flow to expose one more argument say no_wait_param, and default to raw. This way we have the decoupling and be explicit, of course the registration logic (public facing API) looks a bit more complex.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

I made the change. Please take a look. It is easy to rollback if we feel the complexity not worth it

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Since wait always returns nothing, table_transformer will never apply.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

updated

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Would this be a TypeError? Also, recommend the message contain type(getter_op) instead of just getter_op. If someone passed 10 it would say "Got '10'" instead of "Got 'int'".

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Okay, updated. Note, this is the code pattern which exists at several places. I just reused it.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

  1. Looks like 'property' was renamed 'custom' so this just needs to be updated. Also, 'exists' is misspelled 'exits'.

  2. We might consider having a default here instead of raising an error when nothing is specified.

  3. Also, recommend this form for the error: "incorrect usage: --created | --updated | --deleted | --exists | --custom JMESPATH"

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Correct. When the wait is successful you are returned to the command prompt. GET is an implementation detail behind the wait, but there's no need to return the object from the final GET.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

I think it does that at line 423 essentially. It compiles the JMESPath, which should raise an error if it is invalid.

@yugangw-msft yugangw-msft changed the title [do not merge]: Wait/No-Wait Support Wait/No-Wait Nov 30, 2016
@yugangw-msft
Copy link
Copy Markdown
Contributor Author

@tjprescott, please take another look.

if not expose_raw_as_no_wait:
excluded_params.append('raw')
elif not 'raw' in args:
raise ValueError("There is no 'raw' argument exposed for no-wait")
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

This would confuse me if I were not familiar with the implementation of no-wait. I would suggest something like "Unable to enable no-wait option. Operation '{}' does not have a 'raw' parameter.".format(operation.name)

In other words, make it clear that the method must have the 'raw' capability in order to expose no-wait through this argument.

def cli_command(module_name, name, operation,
client_factory=None, transform=None, table_transformer=None, expose_no_wait=False):
client_factory=None, transform=None, table_transformer=None,
expose_no_wait=False, no_wait_param=None):
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Having both expose_no_wait and no_wait_param seems redundant. If no_wait_param is None then you implicitly haven't enabled it. If it is anything else, then you have enabled it. However, I do like this way, of simply specifying the parameter name as it accomplishes the same thing with a little more flexibility.

I would add a check here to verify that the param no_wait_param refers to is a boolean type and throw if it is not. Otherwise someone will try and use a string field or something and things will work in mysterious ways.

Copy link
Copy Markdown
Member

@tjprescott tjprescott left a comment

Choose a reason for hiding this comment

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

I like the decoupling. Adds a little for flexibility for not much more complexity. Added a couple more comments for some minor changes.

Copy link
Copy Markdown
Member

@tjprescott tjprescott left a comment

Choose a reason for hiding this comment

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

LGTM!

@yugangw-msft yugangw-msft merged commit b60590d into Azure:master Dec 1, 2016
@yugangw-msft yugangw-msft deleted the nowait3 branch December 27, 2016 03:52
00Kai0 pushed a commit to 00Kai0/azure-cli that referenced this pull request Apr 7, 2021
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

8 participants