Skip to content

Commit 9e79e60

Browse files
authored
Support for zoned public IP. Make global zone_type and zones_type. (Azure#16)
* Support for zoned public IP. Make global zone_type and zones_type. * Code review feedback.
1 parent 7436a62 commit 9e79e60

File tree

12 files changed

+711
-316
lines changed

12 files changed

+711
-316
lines changed

src/azure-cli-core/azure/cli/core/commands/parameters.py

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -223,6 +223,20 @@ def __call__(self, parser, namespace, values, option_string=None):
223223
action='store_true'
224224
)
225225

226+
zones_type = CliArgumentType(
227+
options_list=['--zones', '-z'],
228+
nargs='+',
229+
help='Space separated list of availability zones into which to provision the resource.',
230+
choices=['1', '2', '3']
231+
)
232+
233+
zone_type = CliArgumentType(
234+
options_list=['--zone', '-z'],
235+
help='Availability zone into which to provision the resource.',
236+
choices=['1', '2', '3'],
237+
nargs=1
238+
)
239+
226240
register_cli_argument('', 'resource_group_name', resource_group_name_type)
227241
register_cli_argument('', 'location', location_type)
228242
register_cli_argument('', 'deployment_name', deployment_name_type)

src/command_modules/azure-cli-network/HISTORY.rst

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ Release History
55

66
unreleased
77
+++++++++++++++++++
8+
* `public-ip`: Add availability zone support.
89
* `lb`: fixed issue where the certain child resource names did not resolve correctly when omitted
910

1011

src/command_modules/azure-cli-network/azure/cli/command_modules/network/_params.py

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@
1111
from azure.cli.core.commands.parameters import (location_type, get_resource_name_completion_list,
1212
enum_choice_list, tags_type, ignore_type,
1313
file_type, get_resource_group_completion_list,
14-
three_state_flag, model_choice_list)
14+
three_state_flag, model_choice_list, zone_type)
1515
from azure.cli.core.commands.validators import get_default_location_from_resource_group
1616
from azure.cli.core.commands.template_create import get_folded_parameter_help_string
1717
from azure.cli.command_modules.network._client_factory import _network_client_factory
@@ -468,6 +468,9 @@ def completer(prefix, action, parsed_args, **kwargs): # pylint: disable=unused-
468468
register_cli_argument('network public-ip create', 'dns_name', validator=process_public_ip_create_namespace)
469469
register_cli_argument('network public-ip create', 'dns_name_type', ignore_type)
470470

471+
with VersionConstraint(ResourceType.MGMT_NETWORK, min_api='2017-06-01') as c:
472+
c.register_cli_argument('network public-ip', 'zone', zone_type)
473+
471474
for item in ['create', 'update']:
472475
register_cli_argument('network public-ip {}'.format(item), 'allocation_method', help='IP address allocation method', **enum_choice_list(IPAllocationMethod))
473476
if supported_api_version(ResourceType.MGMT_NETWORK, min_api='2016-09-01'):

src/command_modules/azure-cli-network/azure/cli/command_modules/network/custom.py

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1405,7 +1405,7 @@ def update_nsg_rule(instance, protocol=None, source_address_prefix=None,
14051405

14061406
def create_public_ip(resource_group_name, public_ip_address_name, location=None, tags=None,
14071407
allocation_method=IPAllocationMethod.dynamic.value, dns_name=None,
1408-
idle_timeout=4, reverse_fqdn=None, version=None):
1408+
idle_timeout=4, reverse_fqdn=None, version=None, zone=None):
14091409
client = _network_client_factory().public_ip_addresses
14101410

14111411
public_ip_args = {
@@ -1417,6 +1417,8 @@ def create_public_ip(resource_group_name, public_ip_address_name, location=None,
14171417
}
14181418
if supported_api_version(ResourceType.MGMT_NETWORK, min_api='2016-09-01'):
14191419
public_ip_args['public_ip_address_version'] = version
1420+
if supported_api_version(ResourceType.MGMT_NETWORK, min_api='2017-06-01'):
1421+
public_ip_args['zones'] = zone
14201422
public_ip = PublicIPAddress(**public_ip_args)
14211423

14221424
if dns_name or reverse_fqdn:

src/command_modules/azure-cli-network/azure/cli/command_modules/network/tests/recordings/latest/test_network_public_ip.yaml

Lines changed: 214 additions & 186 deletions
Large diffs are not rendered by default.
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,156 @@
1+
interactions:
2+
- request:
3+
body: '{"location": "westus", "tags": {"use": "az-test"}}'
4+
headers:
5+
Accept: [application/json]
6+
Accept-Encoding: ['gzip, deflate']
7+
CommandName: [group create]
8+
Connection: [keep-alive]
9+
Content-Length: ['50']
10+
Content-Type: [application/json; charset=utf-8]
11+
User-Agent: [python/3.5.3 (Windows-10-10.0.15063-SP0) requests/2.9.1 msrest/0.4.11
12+
msrest_azure/0.4.11 resourcemanagementclient/1.1.0 Azure-SDK-For-Python
13+
AZURECLI/2.0.12+dev]
14+
accept-language: [en-US]
15+
method: PUT
16+
uri: https://management.azure.com/subscriptions/00000000-0000-0000-0000-000000000000/resourcegroups/cli_test_zoned_public_ip000001?api-version=2017-05-10
17+
response:
18+
body: {string: '{"id":"/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/cli_test_zoned_public_ip000001","name":"cli_test_zoned_public_ip000001","location":"westus","tags":{"use":"az-test"},"properties":{"provisioningState":"Succeeded"}}'}
19+
headers:
20+
cache-control: [no-cache]
21+
content-length: ['328']
22+
content-type: [application/json; charset=utf-8]
23+
date: ['Fri, 04 Aug 2017 20:29:11 GMT']
24+
expires: ['-1']
25+
pragma: [no-cache]
26+
strict-transport-security: [max-age=31536000; includeSubDomains]
27+
x-ms-ratelimit-remaining-subscription-writes: ['1197']
28+
status: {code: 201, message: Created}
29+
- request:
30+
body: '{"properties": {"idleTimeoutInMinutes": 4, "publicIPAllocationMethod":
31+
"Dynamic", "publicIPAddressVersion": "IPv4"}, "location": "centralus", "zones":
32+
["2"]}'
33+
headers:
34+
Accept: [application/json]
35+
Accept-Encoding: ['gzip, deflate']
36+
CommandName: [network public-ip create]
37+
Connection: [keep-alive]
38+
Content-Length: ['157']
39+
Content-Type: [application/json; charset=utf-8]
40+
User-Agent: [python/3.5.3 (Windows-10-10.0.15063-SP0) requests/2.9.1 msrest/0.4.11
41+
msrest_azure/0.4.11 networkmanagementclient/1.9999.0 Azure-SDK-For-Python
42+
AZURECLI/2.0.12+dev]
43+
accept-language: [en-US]
44+
method: PUT
45+
uri: https://management.azure.com/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/cli_test_zoned_public_ip000001/providers/Microsoft.Network/publicIPAddresses/pubip?api-version=2017-06-01
46+
response:
47+
body: {string: "{\r\n \"name\": \"pubip\",\r\n \"id\": \"/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/cli_test_zoned_public_ip000001/providers/Microsoft.Network/publicIPAddresses/pubip\"\
48+
,\r\n \"etag\": \"W/\\\"77534db0-ad28-4635-8199-0f62d603186c\\\"\",\r\n \
49+
\ \"location\": \"centralus\",\r\n \"zones\": [\r\n \"2\"\r\n ],\r\n\
50+
\ \"properties\": {\r\n \"provisioningState\": \"Updating\",\r\n \"\
51+
resourceGuid\": \"d0dfa65a-622b-4fb9-8f2a-d1a0e292a5e3\",\r\n \"publicIPAddressVersion\"\
52+
: \"IPv4\",\r\n \"publicIPAllocationMethod\": \"Dynamic\",\r\n \"idleTimeoutInMinutes\"\
53+
: 4\r\n },\r\n \"type\": \"Microsoft.Network/publicIPAddresses\"\r\n}"}
54+
headers:
55+
azure-asyncoperation: ['https://management.azure.com/subscriptions/00000000-0000-0000-0000-000000000000/providers/Microsoft.Network/locations/centralus/operations/9b4a3da6-f80a-4ea1-896b-e7294d257f53?api-version=2017-06-01']
56+
cache-control: [no-cache]
57+
content-length: ['632']
58+
content-type: [application/json; charset=utf-8]
59+
date: ['Fri, 04 Aug 2017 20:29:12 GMT']
60+
expires: ['-1']
61+
pragma: [no-cache]
62+
server: [Microsoft-HTTPAPI/2.0, Microsoft-HTTPAPI/2.0]
63+
strict-transport-security: [max-age=31536000; includeSubDomains]
64+
x-ms-ratelimit-remaining-subscription-writes: ['1199']
65+
status: {code: 201, message: Created}
66+
- request:
67+
body: null
68+
headers:
69+
Accept: [application/json]
70+
Accept-Encoding: ['gzip, deflate']
71+
CommandName: [network public-ip create]
72+
Connection: [keep-alive]
73+
Content-Type: [application/json; charset=utf-8]
74+
User-Agent: [python/3.5.3 (Windows-10-10.0.15063-SP0) requests/2.9.1 msrest/0.4.11
75+
msrest_azure/0.4.11 networkmanagementclient/1.9999.0 Azure-SDK-For-Python
76+
AZURECLI/2.0.12+dev]
77+
accept-language: [en-US]
78+
method: GET
79+
uri: https://management.azure.com/subscriptions/00000000-0000-0000-0000-000000000000/providers/Microsoft.Network/locations/centralus/operations/9b4a3da6-f80a-4ea1-896b-e7294d257f53?api-version=2017-06-01
80+
response:
81+
body: {string: "{\r\n \"status\": \"Succeeded\"\r\n}"}
82+
headers:
83+
cache-control: [no-cache]
84+
content-length: ['29']
85+
content-type: [application/json; charset=utf-8]
86+
date: ['Fri, 04 Aug 2017 20:29:15 GMT']
87+
expires: ['-1']
88+
pragma: [no-cache]
89+
server: [Microsoft-HTTPAPI/2.0, Microsoft-HTTPAPI/2.0]
90+
strict-transport-security: [max-age=31536000; includeSubDomains]
91+
transfer-encoding: [chunked]
92+
vary: [Accept-Encoding]
93+
status: {code: 200, message: OK}
94+
- request:
95+
body: null
96+
headers:
97+
Accept: [application/json]
98+
Accept-Encoding: ['gzip, deflate']
99+
CommandName: [network public-ip create]
100+
Connection: [keep-alive]
101+
Content-Type: [application/json; charset=utf-8]
102+
User-Agent: [python/3.5.3 (Windows-10-10.0.15063-SP0) requests/2.9.1 msrest/0.4.11
103+
msrest_azure/0.4.11 networkmanagementclient/1.9999.0 Azure-SDK-For-Python
104+
AZURECLI/2.0.12+dev]
105+
accept-language: [en-US]
106+
method: GET
107+
uri: https://management.azure.com/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/cli_test_zoned_public_ip000001/providers/Microsoft.Network/publicIPAddresses/pubip?api-version=2017-06-01
108+
response:
109+
body: {string: "{\r\n \"name\": \"pubip\",\r\n \"id\": \"/subscriptions/00000000-0000-0000-0000-000000000000/resourceGroups/cli_test_zoned_public_ip000001/providers/Microsoft.Network/publicIPAddresses/pubip\"\
110+
,\r\n \"etag\": \"W/\\\"2db5b8bc-f274-40e8-a238-0d7cad9d5332\\\"\",\r\n \
111+
\ \"location\": \"centralus\",\r\n \"zones\": [\r\n \"2\"\r\n ],\r\n\
112+
\ \"properties\": {\r\n \"provisioningState\": \"Succeeded\",\r\n \"\
113+
resourceGuid\": \"d0dfa65a-622b-4fb9-8f2a-d1a0e292a5e3\",\r\n \"publicIPAddressVersion\"\
114+
: \"IPv4\",\r\n \"publicIPAllocationMethod\": \"Dynamic\",\r\n \"idleTimeoutInMinutes\"\
115+
: 4\r\n },\r\n \"type\": \"Microsoft.Network/publicIPAddresses\"\r\n}"}
116+
headers:
117+
cache-control: [no-cache]
118+
content-length: ['633']
119+
content-type: [application/json; charset=utf-8]
120+
date: ['Fri, 04 Aug 2017 20:29:16 GMT']
121+
etag: [W/"2db5b8bc-f274-40e8-a238-0d7cad9d5332"]
122+
expires: ['-1']
123+
pragma: [no-cache]
124+
server: [Microsoft-HTTPAPI/2.0, Microsoft-HTTPAPI/2.0]
125+
strict-transport-security: [max-age=31536000; includeSubDomains]
126+
transfer-encoding: [chunked]
127+
vary: [Accept-Encoding]
128+
status: {code: 200, message: OK}
129+
- request:
130+
body: null
131+
headers:
132+
Accept: [application/json]
133+
Accept-Encoding: ['gzip, deflate']
134+
CommandName: [group delete]
135+
Connection: [keep-alive]
136+
Content-Length: ['0']
137+
Content-Type: [application/json; charset=utf-8]
138+
User-Agent: [python/3.5.3 (Windows-10-10.0.15063-SP0) requests/2.9.1 msrest/0.4.11
139+
msrest_azure/0.4.11 resourcemanagementclient/1.1.0 Azure-SDK-For-Python
140+
AZURECLI/2.0.12+dev]
141+
accept-language: [en-US]
142+
method: DELETE
143+
uri: https://management.azure.com/subscriptions/00000000-0000-0000-0000-000000000000/resourcegroups/cli_test_zoned_public_ip000001?api-version=2017-05-10
144+
response:
145+
body: {string: ''}
146+
headers:
147+
cache-control: [no-cache]
148+
content-length: ['0']
149+
date: ['Fri, 04 Aug 2017 20:29:17 GMT']
150+
expires: ['-1']
151+
location: ['https://management.azure.com/subscriptions/00000000-0000-0000-0000-000000000000/operationresults/eyJqb2JJZCI6IlJFU09VUkNFR1JPVVBERUxFVElPTkpPQi1DTEk6NUZURVNUOjVGWk9ORUQ6NUZQVUJMSUM6NUZJUFhIN1FRTk9TVlVUNUtFSnxCNDdGQTk5QUM4N0ZCQzMyLVdFU1RVUyIsImpvYkxvY2F0aW9uIjoid2VzdHVzIn0?api-version=2017-05-10']
152+
pragma: [no-cache]
153+
strict-transport-security: [max-age=31536000; includeSubDomains]
154+
x-ms-ratelimit-remaining-subscription-writes: ['1198']
155+
status: {code: 202, message: Accepted}
156+
version: 1

src/command_modules/azure-cli-network/azure/cli/command_modules/network/tests/test_network_commands.py

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -322,6 +322,19 @@ def body(self):
322322
s.cmd('network public-ip list -g {}'.format(rg), checks=JMESPathCheck("length[?name == '{}']".format(public_ip_dns), None))
323323

324324

325+
@api_version_constraint(ResourceType.MGMT_NETWORK, min_api='2017-06-01')
326+
class NetworkZonedPublicIpScenarioTest(ScenarioTest):
327+
328+
@ResourceGroupPreparer(name_prefix='cli_test_zoned_public_ip')
329+
def test_network_zoned_public_ip(self, resource_group):
330+
kwargs = {
331+
'rg': resource_group,
332+
'ip': 'pubip'
333+
}
334+
self.cmd('network public-ip create -g {rg} -n {ip} -l centralus -z 2'.format(**kwargs),
335+
checks=JMESPathCheck('publicIp.zones[0]', '2'))
336+
337+
325338
class NetworkExpressRouteScenarioTest(ResourceGroupVCRTestBase):
326339
def __init__(self, test_method):
327340
super(NetworkExpressRouteScenarioTest, self).__init__(__file__, test_method, resource_group='cli_test_express_route')

src/command_modules/azure-cli-vm/azure/cli/command_modules/vm/_params.py

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@
1616
(get_default_location_from_resource_group, validate_file_or_dict)
1717
from azure.cli.core.commands.parameters import \
1818
(location_type, get_one_of_subscription_locations,
19-
get_resource_name_completion_list, tags_type, file_type, enum_choice_list, ignore_type)
19+
get_resource_name_completion_list, tags_type, file_type, enum_choice_list, ignore_type, zone_type, zones_type)
2020
from azure.cli.command_modules.vm._actions import \
2121
(load_images_from_aliases_doc, get_vm_sizes, _resource_not_exists)
2222
from azure.cli.command_modules.vm._validators import \
@@ -64,9 +64,9 @@ def get_vm_size_completion_list(prefix, action, parsed_args, **kwargs): # pylin
6464
register_cli_argument('vm', 'name', arg_type=name_arg_type)
6565

6666
with VersionConstraint(ResourceType.MGMT_COMPUTE, min_api='2017-03-30') as c:
67-
c.register_cli_argument('vm', 'zones', help='availability zone the virtual machine will be in, e.g. 1, 2, etc')
68-
c.register_cli_argument('disk', 'zones', help='availability zone the disk will be in, e.g. 1, 2, etc.')
69-
c.register_cli_argument('vmss', 'zones', nargs='+', help='space separated availability zone list instances will be in, e.g. 1 2')
67+
c.register_cli_argument('vm', 'zone', zone_type)
68+
c.register_cli_argument('disk', 'zone', zone_type, options_list=['--zone']) # TODO: --size-gb currently has claimed -z. We can do a breaking change later if we want to.
69+
c.register_cli_argument('vmss', 'zones', zones_type)
7070

7171
for item in ['show', 'list']:
7272
register_cli_argument('vm {}'.format(item), 'show_details', action='store_true', options_list=('--show-details', '-d'), help='show public ip address, FQDN, and power states. command will run slow')

src/command_modules/azure-cli-vm/azure/cli/command_modules/vm/_template_builder.py

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -128,24 +128,24 @@ def build_storage_account_resource(name, location, tags, sku):
128128
return storage_account
129129

130130

131-
def build_public_ip_resource(name, location, tags, address_allocation, dns_name=None, zones=None):
131+
def build_public_ip_resource(name, location, tags, address_allocation, dns_name=None, zone=None):
132132

133133
public_ip_properties = {'publicIPAllocationMethod': address_allocation}
134134

135135
if dns_name:
136136
public_ip_properties['dnsSettings'] = {'domainNameLabel': dns_name}
137137

138138
public_ip = {
139-
'apiVersion': '2016-11-01' if zones else '2015-06-15',
139+
'apiVersion': '2016-11-01' if zone else '2015-06-15',
140140
'type': 'Microsoft.Network/publicIPAddresses',
141141
'name': name,
142142
'location': location,
143143
'tags': tags,
144144
'dependsOn': [],
145145
'properties': public_ip_properties
146146
}
147-
if zones:
148-
public_ip['zones'] = zones
147+
if zone:
148+
public_ip['zones'] = zone
149149

150150
return public_ip
151151

@@ -307,7 +307,7 @@ def build_vm_resource( # pylint: disable=too-many-locals
307307
os_caching=None, data_caching=None, storage_sku=None,
308308
os_publisher=None, os_offer=None, os_sku=None, os_version=None, os_vhd_uri=None,
309309
attach_os_disk=None, attach_data_disks=None, data_disk_sizes_gb=None, image_data_disks=None,
310-
custom_data=None, secrets=None, license_type=None, zones=None):
310+
custom_data=None, secrets=None, license_type=None, zone=None):
311311

312312
def _build_os_profile():
313313

@@ -440,8 +440,8 @@ def _build_storage_profile():
440440
'dependsOn': [],
441441
'properties': vm_properties,
442442
}
443-
if zones:
444-
vm['zones'] = zones
443+
if zone:
444+
vm['zones'] = zone
445445
return vm
446446

447447

src/command_modules/azure-cli-vm/azure/cli/command_modules/vm/custom.py

Lines changed: 6 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -299,7 +299,7 @@ def create_managed_disk(resource_group_name, disk_name, location=None,
299299
source=None, # pylint: disable=unused-argument
300300
# below are generated internally from 'source'
301301
source_blob_uri=None, source_disk=None, source_snapshot=None,
302-
source_storage_account_id=None, no_wait=False, tags=None, zones=None):
302+
source_storage_account_id=None, no_wait=False, tags=None, zone=None):
303303
Disk, CreationData, DiskCreateOption = get_sdk(ResourceType.MGMT_COMPUTE, 'Disk', 'CreationData',
304304
'DiskCreateOption', mod='models')
305305

@@ -319,8 +319,8 @@ def create_managed_disk(resource_group_name, disk_name, location=None,
319319
if size_gb is None and option == DiskCreateOption.empty:
320320
raise CLIError('usage error: --size-gb required to create an empty disk')
321321
disk = Disk(location, creation_data, (tags or {}), _get_sku_object(sku), disk_size_gb=size_gb)
322-
if zones:
323-
disk.zones = [zones]
322+
if zone:
323+
disk.zones = zone
324324

325325
client = _compute_client_factory()
326326
return client.disks.create_or_update(resource_group_name, disk_name, disk, raw=no_wait)
@@ -1567,7 +1567,7 @@ def create_vm(vm_name, resource_group_name, image=None, size='Standard_DS1_v2',
15671567
storage_account_type=None, vnet_type=None, nsg_type=None, public_ip_type=None, nic_type=None,
15681568
validate=False, custom_data=None, secrets=None, plan_name=None, plan_product=None, plan_publisher=None,
15691569
license_type=None, assign_identity=False, identity_scope=None,
1570-
identity_role=DefaultStr('Contributor'), identity_role_id=None, zones=None):
1570+
identity_role=DefaultStr('Contributor'), identity_role_id=None, zone=None):
15711571
from azure.cli.core.commands.client_factory import get_subscription_id
15721572
from azure.cli.core.util import random_string, hash_string
15731573
from azure.cli.command_modules.vm._template_builder import (ArmTemplateBuilder, build_vm_resource,
@@ -1586,10 +1586,6 @@ def create_vm(vm_name, resource_group_name, image=None, size='Standard_DS1_v2',
15861586
subscription=subscription_id, resource_group=resource_group_name,
15871587
namespace='Microsoft.Compute', type='virtualMachines', name=vm_name)
15881588

1589-
# Even for single zonal resources, like vm, services still require an array in payload, so convert here
1590-
if zones:
1591-
zones = [zones]
1592-
15931589
# determine final defaults and calculated values
15941590
tags = tags or {}
15951591
os_disk_name = os_disk_name or 'osdisk_{}'.format(hash_string(vm_id, length=10))
@@ -1632,7 +1628,7 @@ def create_vm(vm_name, resource_group_name, image=None, size='Standard_DS1_v2',
16321628
master_template.add_resource(build_public_ip_resource(public_ip_address, location,
16331629
tags,
16341630
public_ip_address_allocation,
1635-
public_ip_address_dns_name, zones))
1631+
public_ip_address_dns_name, zone))
16361632

16371633
subnet_id = subnet if is_valid_resource_id(subnet) else \
16381634
'{}/virtualNetworks/{}/subnets/{}'.format(network_id_template, vnet_name, subnet)
@@ -1685,7 +1681,7 @@ def create_vm(vm_name, resource_group_name, image=None, size='Standard_DS1_v2',
16851681
admin_password, ssh_key_value, ssh_dest_key_path, image, os_disk_name,
16861682
os_type, os_caching, data_caching, storage_sku, os_publisher, os_offer, os_sku, os_version,
16871683
os_vhd_uri, attach_os_disk, attach_data_disks, data_disk_sizes_gb, image_data_disks, custom_data, secrets,
1688-
license_type, zones)
1684+
license_type, zone)
16891685
vm_resource['dependsOn'] = vm_dependencies
16901686

16911687
if plan_name:

0 commit comments

Comments
 (0)