-
Notifications
You must be signed in to change notification settings - Fork 3k
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
Add new command budget to consumption #6024
Conversation
View a preview at https://prompt.ws/r/Azure/azure-cli/6024 |
@@ -2,6 +2,10 @@ | |||
|
|||
Release History | |||
=============== | |||
0.3.1 | |||
+++++ | |||
* Added commands `budget`. |
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.
Change to clearer description. Currently, this gives very little information.
Here are some examples from previous releases of the module.
https://docs.microsoft.com/en-us/cli/azure/release-notes-azure-cli?view=azure-cli-latest#consumption
https://docs.microsoft.com/en-us/cli/azure/release-notes-azure-cli?view=azure-cli-latest#consumption-1
return Decimal(string) | ||
except ValueError: | ||
raise ValueError("the value passed cannot be converted to decimal") | ||
return decimal_type |
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 shouldn't need the wrapper function get_decimal_type
.
Just define decimal_type
as is then in your param definition, pass the function decimal_type
instead of doing get_decimal_type ()
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.
Same with get_datetime_type
above.
"""lowercase the time grain for comparison""" | ||
budgetcategory = namespace.category.lower() | ||
if budgetcategory != 'cost' and budgetcategory != 'usage': | ||
raise CLIError("usage error: --parameters.category must be set to either cost or usage") |
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.
The param name is --category
. User won't know what --parameters.category
is.
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.
Additionally, this should be covered by using get_enum_type
in the param registration.
https://github.com/Azure/azure-cli/blob/dev/doc/authoring_command_modules/authoring_commands.md#registering-enums
time_grain = namespace.time_grain.lower().strip() | ||
|
||
if time_grain != 'annually' and time_grain != 'quarterly' and time_grain != 'monthly': | ||
raise CLIError("usage error: --parameters.time_grain can be 'Annually', 'Quarterly', or 'Monthly'.") |
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.
Same 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.
raise CLIError("usage error: --parameters.time_grain can be 'Annually', 'Quarterly', or 'Monthly'.") | ||
|
||
if namespace.amount < 0: | ||
raise CLIError("usage error: --parameters.amount must be greater than 0") |
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.
Same here.
exception_handler=consumption_exception_handler, validator=validate_budget_parameters, client_factory=budget_mgmt_client_factory) | ||
|
||
p.custom_command('delete', 'cli_consumption_delete_budget', transform=None, | ||
exception_handler=consumption_exception_handler, client_factory=budget_mgmt_client_factory) |
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.
Instead of duplicating exception_handler
and client_factory
everywhere, you should be able to define them in the command_group
and it'll be used for all in the group.
def cli_consumption_list_budgets(client, resource_group_name=None): | ||
if resource_group_name: | ||
return list(client.list_by_resource_group_name(resource_group_name)) | ||
return list(client.list()) |
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 need to call list()
around the SDK calls. The CLI handles this.
@derekbekoe @tjprescott All comments above are addressed. Please proceed on your side. |
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.
Ditto all of @derekbekoe's comments. Added some of my own.
@@ -34,3 +36,15 @@ def load_arguments(self, _): | |||
cmp.argument('top', options_list=['--top', '-t'], type=int, help='Maximum number of items to return. Value range: 1-1000.') | |||
cmp.argument('start_date', options_list=['--start-date', '-s'], type=get_datetime_type(), help='Start date (YYYY-MM-DD in UTC). If specified, also requires --end-date.') | |||
cmp.argument('end_date', options_list=['--end-date', '-e'], type=get_datetime_type(), help='End date (YYYY-MM-DD in UTC). If specified, also requires --start-date.') | |||
|
|||
with self.argument_context('consumption budget') as cb: | |||
cb.argument('resource_group_name', options_list='--resource-group-name', type=str, help='Resource group of the budget.') |
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 overriding the global resource group aliasing, but shouldn't.
|
||
with self.argument_context('consumption budget') as cb: | ||
cb.argument('resource_group_name', options_list='--resource-group-name', type=str, help='Resource group of the budget.') | ||
cb.argument('budget_name', options_list='--budget-name', type=str, help='Name of a budget.') |
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.
Options list is not required here. Type is not required.
with self.argument_context('consumption budget') as cb: | ||
cb.argument('resource_group_name', options_list='--resource-group-name', type=str, help='Resource group of the budget.') | ||
cb.argument('budget_name', options_list='--budget-name', type=str, help='Name of a budget.') | ||
cb.argument('category', options_list=['--category', '-c'], type=str, help='Category of the budget can be cost or usage.') |
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 be enum type. Type kwarg not required.
cb.argument('budget_name', options_list='--budget-name', type=str, help='Name of a budget.') | ||
cb.argument('category', options_list=['--category', '-c'], type=str, help='Category of the budget can be cost or usage.') | ||
cb.argument('amount', options_list=['--amount', '-a'], type=get_decimal_type(), help='Amount of a budget.') | ||
cb.argument('time_grain', options_list='--time-grain', type=str, help='Time grain of the budget can be monthly, quarterly, or annually.') |
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.
Options list not required. Type not required. Should be enum type...
cb.argument('time_grain', options_list='--time-grain', type=str, help='Time grain of the budget can be monthly, quarterly, or annually.') | ||
cb.argument('start_date', options_list=['--start-date', '-s'], type=get_datetime_type(), help='Start date (YYYY-MM-DD in UTC) of time period of a budget.') | ||
cb.argument('end_date', options_list=['--end-date', '-e'], type=get_datetime_type(), help='End date (YYYY-MM-DD in UTC) of time period of a budget.') | ||
cb.argument('resource_groups', options_list='--resource-groups', nargs='+', help='Space-separated list of resource groups to filter on.') |
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.
Options list not required. These filter type arguments should have arg_group='Filter'
so they stand out in help. Right now, you'll have
--resource-group -g The "resource group"
--resource-groups Resources groups to filter on
You might also consider making the property name something like "--filter-groups" or something. Right now, --resource-group
and --resource-groups
would be easy to confuse.
cb.argument('start_date', options_list=['--start-date', '-s'], type=get_datetime_type(), help='Start date (YYYY-MM-DD in UTC) of time period of a budget.') | ||
cb.argument('end_date', options_list=['--end-date', '-e'], type=get_datetime_type(), help='End date (YYYY-MM-DD in UTC) of time period of a budget.') | ||
cb.argument('resource_groups', options_list='--resource-groups', nargs='+', help='Space-separated list of resource groups to filter on.') | ||
cb.argument('resources', options_list='--resources', nargs='+', help='Space-separated list of resource instances to filter on.') |
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.
Options list not required.
cb.argument('end_date', options_list=['--end-date', '-e'], type=get_datetime_type(), help='End date (YYYY-MM-DD in UTC) of time period of a budget.') | ||
cb.argument('resource_groups', options_list='--resource-groups', nargs='+', help='Space-separated list of resource groups to filter on.') | ||
cb.argument('resources', options_list='--resources', nargs='+', help='Space-separated list of resource instances to filter on.') | ||
cb.argument('meters', options_list='--meters', nargs='+', help='Space-separated list of meters to filter on. Required if category is usage.') |
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.
Options list not required. What are meters?
exception_handler=consumption_exception_handler, validator=validate_budget_parameters, client_factory=budget_mgmt_client_factory) | ||
|
||
p.custom_command('delete', 'cli_consumption_delete_budget', transform=None, | ||
exception_handler=consumption_exception_handler, client_factory=budget_mgmt_client_factory) |
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.
The default values of validator and transform are None, so you can (and should) omit those.
@derekbekoe @tjprescott Resolved comments from both of you. Please refer to the latest iteration and proceed. |
@tjprescott Can you take a look and review also? |
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.
Overall looks much better. Still a few small issues.
|
||
|
||
def load_arguments(self, _): | ||
with self.argument_context('consumption usage') as c: | ||
c.argument('top', options_list=['--top', '-t'], type=int, help='Maximum number of items to return. Value range: 1-1000.') | ||
c.argument('include_additional_properties', options_list=['--include-additional-properties', '-a'], action='store_true', help='Include additional properties in the usages.') | ||
c.argument('include_meter_details', options_list=['--include-meter-details', '-m'], action='store_true', help='Include meter details in the usages.') | ||
c.argument('start_date', options_list=['--start-date', '-s'], type=get_datetime_type(), help='Start date (YYYY-MM-DD in UTC). If specified, also requires --end-date.') | ||
c.argument('end_date', options_list=['--end-date', '-e'], type=get_datetime_type(), help='End date (YYYY-MM-DD in UTC). If specified, also requires --start-date.') | ||
c.argument('start_date', options_list=['--start-date', '-s'], type=datetime_type, help='Start date (YYYY-MM-DD in UTC). If specified, also requires --end-date.') |
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.
Consider using the get_datetime_type
method from azure.cli.core.commands.parameters
. They are methods because you have to parameterize, but the intention will be to standardize date handling using these configurable methods. Try it on one command and let me know whether it fits your scenario.
|
||
with self.argument_context('consumption budget') as cb: | ||
cb.argument('budget_name', help='Name of a budget.') | ||
cb.argument('category', arg_type=get_enum_type(['cost', 'usage']), help='Category of the budget can be cost or usage.') |
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 are these enums not in your SDK?
cb.argument('time_grain', arg_type=get_enum_type(['monthly', 'quarterly', 'annually']), help='Time grain of the budget can be monthly, quarterly, or annually.') | ||
cb.argument('start_date', options_list=['--start-date', '-s'], type=datetime_type, help='Start date (YYYY-MM-DD in UTC) of time period of a budget.') | ||
cb.argument('end_date', options_list=['--end-date', '-e'], type=datetime_type, help='End date (YYYY-MM-DD in UTC) of time period of a budget.') | ||
cb.argument('resource_groups', options_list='--resource-group-filter', nargs='+', help='Space-separated list of resource groups to filter on.') |
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 fine, but you should still add arg_group='Filter'
to these so they are grouped together in help.
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.
Added
raise ValueError("Input '{}' not valid. Valid example: 2017-02-11T23:59:59Z".format(string)) | ||
return datetime_type | ||
accepted_date_formats = ['%Y-%m-%dT%H:%M:%SZ', '%Y-%m-%dT%H:%MZ', '%Y-%m-%dT%HZ', '%Y-%m-%d'] | ||
for form in accepted_date_formats: |
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.
Try the version and core. If you feel it doesn't support you scenarios, let me know so I can improve it.
raise CLIError("usage error: --category must be set to either cost or usage") | ||
time_grain = namespace.time_grain.lower().strip() | ||
if time_grain != 'annually' and time_grain != 'quarterly' and time_grain != 'monthly': | ||
raise CLIError("usage error: --time_grain can be 'Annually', 'Quarterly', or 'Monthly'.") |
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.
These enums should not be validated in code at all. That's why you register them as enums. The CLI handles all of that. Validating the amount is fine though.
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.
Removed validation on category and time grain
@tjprescott get_datetime_type method got errors when running test cases. Will prefer to keep original datetime_type. |
This checklist is used to make sure that common guidelines for a pull request are followed.
The PR has modified HISTORY.rst describing any customer-facing, functional changes. Note that this does not include changes only to help content. (see Modifying change log).
I adhere to the Command Guidelines.