-
Notifications
You must be signed in to change notification settings - Fork 3.3k
appservice: support to create plan when create a webapp #2550
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
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,47 @@ | ||
| # -------------------------------------------------------------------------------------------- | ||
| # Copyright (c) Microsoft Corporation. All rights reserved. | ||
| # Licensed under the MIT License. See License.txt in the project root for license information. | ||
| # -------------------------------------------------------------------------------------------- | ||
|
|
||
| from azure.cli.core._util import CLIError | ||
| from azure.cli.core.commands.validators import get_default_location_from_resource_group | ||
|
|
||
| def validate_plan_arg(namespace): | ||
| from ._client_factory import web_client_factory | ||
| namespace.create_plan = False | ||
| if namespace.plan: | ||
| from azure.cli.core.commands.arm import is_valid_resource_id | ||
| if not is_valid_resource_id(namespace.plan): | ||
| from msrestazure.azure_exceptions import CloudError | ||
| client = web_client_factory() | ||
| try: | ||
| client.app_service_plans.get(namespace.resource_group_name, namespace.plan) | ||
| except CloudError: | ||
| namespace.create_plan = True | ||
| else: | ||
| client = web_client_factory() | ||
| result = client.app_service_plans.list_by_resource_group(namespace.resource_group_name) | ||
| existing_plan = next((x for x in result if match_plan_location(x, namespace.location) and | ||
| namespace.is_linux == (x.kind == 'linux')), None) | ||
| if existing_plan: | ||
| namespace.plan = existing_plan.id | ||
| else: | ||
| namespace.create_plan = True | ||
| namespace.plan = namespace.name + '_plan' | ||
|
|
||
| if not namespace.create_plan and (namespace.sku or namespace.number_of_workers): | ||
| raise CLIError('Usage error: argument values for --sku or --number-of-workers will ' | ||
| 'be ignored, as the new web will be created using an existing ' | ||
| 'plan {}. Please use --plan to specify a new plan'.format(namespace.plan)) | ||
|
|
||
|
|
||
|
|
||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Extra empty line. Didn't pylint complain?
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Apparently not or it would not have passed CI 😁
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This will not be a pylint error, rather PEP 8 style check should catch it. I have opened #2562 to get that done. |
||
| def match_plan_location(plan, location): | ||
| # the problem with appservice is it uses display name, rather canonical name | ||
| # so we have to hack it | ||
| return plan.location.replace(' ', '').lower() == location.lower() | ||
|
|
||
|
|
||
| def process_webapp_create_namespace(namespace): | ||
| get_default_location_from_resource_group(namespace) | ||
| validate_plan_arg(namespace) | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -21,7 +21,7 @@ | |
| RestoreRequest, FrequencyUnit, Certificate, HostNameSslState) | ||
|
|
||
| from azure.cli.core.commands.client_factory import get_mgmt_service_client | ||
| from azure.cli.core.commands.arm import is_valid_resource_id, parse_resource_id | ||
| from azure.cli.core.commands.arm import parse_resource_id | ||
| from azure.cli.core.commands import LongRunningOperation | ||
|
|
||
| from azure.cli.core.prompting import prompt_pass, NoTTYException | ||
|
|
@@ -56,18 +56,25 @@ def _get_detail_error(self, ex): | |
| "azure/app-service-web/app-service-linux-intro") | ||
| elif 'Not enough available reserved instance servers to satisfy' in detail: | ||
| detail = ("Plan with Linux worker can only be created in a group " + | ||
| "which has never contained a Windows worker. Please use " + | ||
| "a new resource group. Original error:" + detail) | ||
| "which has never contained a Windows worker, and vice versa. " + | ||
| "Please use a new resource group. Original error:" + detail) | ||
| return CLIError(detail) | ||
| except: #pylint: disable=bare-except | ||
| return ex | ||
|
|
||
| def create_webapp(resource_group_name, name, plan): | ||
| def create_webapp(resource_group_name, name, | ||
| plan=None, create_plan=False, | ||
| sku=None, is_linux=False, number_of_workers=None, | ||
| location=None): | ||
| client = web_client_factory() | ||
| if is_valid_resource_id(plan): | ||
| plan = parse_resource_id(plan)['name'] | ||
| location = _get_location_from_app_service_plan(client, resource_group_name, plan) | ||
| webapp_def = Site(server_farm_id=plan, location=location) | ||
| plan_id = plan | ||
| if create_plan: | ||
| logger.warning("Create appservice plan: '%s'", plan) | ||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Why are we issuing a warning? We don't do this for other creates (VM/VMSS/LB/AG) that create extra resources.
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I thought about it before put in a warning. The situation here is a bit different, that we are creating a |
||
| result = create_app_service_plan(resource_group_name, plan, is_linux, | ||
| sku or 'S1', number_of_workers or 1, location) | ||
| plan_id = result.id | ||
|
|
||
| webapp_def = Site(server_farm_id=plan_id, location=location) | ||
| poller = client.web_apps.create_or_update(resource_group_name, name, webapp_def) | ||
| return AppServiceLongRunningOperation()(poller) | ||
|
|
||
|
|
||
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.
Can we get this metadata from SDK? It doesn't feel right for SDK to hard-code service options.
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.
Agreed, it is not right. But it is a known webapp api pattern, that offers no enum or choices. Yep, this makes lives a bit harder for client apps