Skip to content

Commit 3eee2ae

Browse files
committed
Merge branch 'release-v5.10.1'
2 parents e14a7da + 79f96aa commit 3eee2ae

File tree

4 files changed

+44
-21
lines changed

4 files changed

+44
-21
lines changed

netfoundry/ctl.py

+5-4
Original file line numberDiff line numberDiff line change
@@ -94,6 +94,7 @@ def __call__(self, parser, namespace, values, option_string=None):
9494
@cli.argument('-Y', '--yes', action='store_true', arg_only=True, help='answer yes to potentially-destructive operations')
9595
@cli.argument('-W', '--wait', help='seconds to wait for long-running processes to finish', default=900)
9696
@cli.argument('--proxy', help=argparse.SUPPRESS)
97+
@cli.argument('--gateway', default="gateway", help=argparse.SUPPRESS)
9798
@cli.entrypoint('configure the CLI to manage a network')
9899
def main(cli):
99100
"""Configure the CLI to manage a network."""
@@ -155,7 +156,7 @@ def login(cli):
155156
summary_table = []
156157
summary_table.append(['Caller ID', f"{summary_object['caller']['name']} ({summary_object['caller']['email']}) in {organization.label} ({organization.name})"])
157158
if network_group:
158-
summary_table.append(['Network Resource Group', f"{summary_object['network_group']['name']} ({summary_object['network_group']['organizationShortName']}) with {summary_object['network_group']['networks_count']} networks"])
159+
summary_table.append(['Network Resource Group', f"{summary_object['network_group']['name']} ({summary_object['network_group']['shortName']}) with {summary_object['network_group']['networks_count']} networks"])
159160
if network:
160161
summary_table.append(['Configured Network', f"{summary_object['network']['name']} - {summary_object['network']['productVersion']} - {summary_object['network']['status']}"])
161162
if cli.config.general.borders:
@@ -686,13 +687,11 @@ def list(cli, echo: bool = True, spinner: object = None):
686687
valid_keys = valid_keys.union(match.keys())
687688

688689
# intersection of the set of valid, observed keys in the first match
689-
default_keys = ['name', 'label', 'organizationShortName', 'type', 'description',
690+
default_keys = ['name', 'label', 'shortName', 'type', 'description',
690691
'edgeRouterAttributes', 'serviceAttributes', 'endpointAttributes',
691692
'status', 'zitiId', 'provider', 'locationCode', 'ipAddress', 'networkVersion',
692693
'active', 'default', 'region', 'size', 'attributes', 'email', 'productVersion',
693694
'address', 'binding', 'component']
694-
if cli.config.list.names: # include identity IDs if --names
695-
default_keys.extend(IDENTITY_ID_PROPERTIES)
696695
if cli.args.keys:
697696
valid_keys = valid_keys.intersection(cli.args.keys)
698697
else:
@@ -1153,6 +1152,7 @@ def use_organization(cli, spinner: object = None, prompt: bool = True):
11531152
expiry_minimum=0,
11541153
proxy=cli.config.general.proxy,
11551154
logger=cli.log,
1155+
gateway=cli.config.general.gateway,
11561156
)
11571157
except NFAPINoCredentials:
11581158
if prompt:
@@ -1177,6 +1177,7 @@ def use_organization(cli, spinner: object = None, prompt: bool = True):
11771177
expiry_minimum=0,
11781178
proxy=cli.config.general.proxy,
11791179
logger=cli.log,
1180+
gateway=cli.config.general.gateway,
11801181
)
11811182
except PyJWTError:
11821183
spinner.fail("Not a valid token")

netfoundry/network_group.py

+5-5
Original file line numberDiff line numberDiff line change
@@ -28,14 +28,14 @@ def __init__(self, Organization: object, network_group_id: str = None, network_g
2828
self.network_group_id = network_group_id
2929
network_group_matches = [ng for ng in self.network_groups if ng['id'] == network_group_id]
3030
if len(network_group_matches) == 1:
31-
self.network_group_name = network_group_matches[0]['organizationShortName']
31+
self.network_group_name = network_group_matches[0]['shortName']
3232
self.logger.debug(f"found one match for group id '{network_group_id}'")
3333
else:
3434
raise RuntimeError(f"there was not exactly one network group matching the id '{network_group_id}'")
3535
# TODO: review the use of org short name ref https://mattermost.tools.netfoundry.io/netfoundry/pl/gegyzuybypb9jxnrw1g1imjywh
3636
elif network_group_name:
3737
self.network_group_name = network_group_name
38-
network_group_matches = [ng for ng in self.network_groups if caseless_equal(ng['organizationShortName'], self.network_group_name)]
38+
network_group_matches = [ng for ng in self.network_groups if caseless_equal(ng['shortName'], self.network_group_name)]
3939
if len(network_group_matches) == 1:
4040
self.network_group_id = network_group_matches[0]['id']
4141
self.logger.debug(f"found one match for group short name '{network_group_name}'")
@@ -44,10 +44,10 @@ def __init__(self, Organization: object, network_group_id: str = None, network_g
4444
elif len(self.network_groups) > 0:
4545
# first network group is typically the only network group
4646
self.network_group_id = self.network_groups[0]['id']
47-
self.network_group_name = normalize_caseless(self.network_groups[0]['organizationShortName'])
47+
self.network_group_name = normalize_caseless(self.network_groups[0]['shortName'])
4848
# warn if there are other groups
4949
if len(self.network_groups) > 1:
50-
self.logger.warning(f"using first network group {self.network_group_name} and ignoring {len(self.network_groups) - 1} other(s) e.g. {self.network_groups[1]['organizationShortName']}, etc...")
50+
self.logger.warning(f"using first network group {self.network_group_name} and ignoring {len(self.network_groups) - 1} other(s) e.g. {self.network_groups[1]['shortName']}, etc...")
5151
elif len(self.network_groups) == 1:
5252
self.logger.debug(f"using the only available network group: {self.network_group_name}")
5353
else:
@@ -149,7 +149,7 @@ def find_latest_network_version(self, network_versions: list = list(), is_active
149149

150150
find_latest_product_version = find_latest_network_version
151151

152-
def create_network(self, name: str, network_group_id: str = None, location: str = "us-ashburn-1", provider: str = "OCI", version: str = None, size: str = "medium", wait: int = 1200, sleep: int = 10, **kwargs):
152+
def create_network(self, name: str, network_group_id: str = None, location: str = "eu-amsterdam-1", provider: str = "OCI", version: str = None, size: str = "medium", wait: int = 1200, sleep: int = 10, **kwargs):
153153
"""
154154
Create a network in this network group.
155155

netfoundry/organization.py

+23-8
Original file line numberDiff line numberDiff line change
@@ -43,7 +43,8 @@ def __init__(self,
4343
log_file: str = None,
4444
debug: bool = False,
4545
logger: logging.Logger = None,
46-
proxy: str = None):
46+
proxy: str = None,
47+
gateway: str = "gateway"):
4748
"""Initialize an instance of organization."""
4849
# set debug and file if specified and let the calling application dictate logging handlers
4950
self.log_file = log_file
@@ -79,6 +80,14 @@ def __init__(self,
7980
else:
8081
self.verify = False
8182

83+
# users of older versions of nfsupport-cli will send literal None until they upgrade to a version that provides the --gateway option
84+
if gateway is None:
85+
self.gateway = "gateway"
86+
else:
87+
self.gateway = gateway
88+
89+
self.logger.debug(f"got 'gateway' param {self.gateway}")
90+
8291
epoch = round(time.time())
8392
self.expiry_seconds = 0 # initialize a placeholder for remaining seconds until expiry
8493
client_id = None
@@ -249,12 +258,15 @@ def __init__(self,
249258
self.logger.warning(f"unexpected environment '{self.environment}'")
250259

251260
if self.environment and not self.audience:
252-
self.audience = f'https://gateway.{self.environment}.netfoundry.io/'
261+
self.audience = f'https://{self.gateway}.{self.environment}.netfoundry.io/'
262+
self.logger.debug(f"computed audience URL from gateway and environment: {self.audience}")
253263

254264
if self.environment and self.audience:
255265
if not re.search(self.environment, self.audience):
256266
self.logger.error(f"mismatched audience URL '{self.audience}' and environment '{self.environment}'")
257267
exit(1)
268+
else:
269+
self.logger.debug(f"found audience already computed '{self.audience}' and matching environment '{self.environment}'")
258270

259271
# the purpose of this try-except block is to soft-fail all attempts
260272
# to parse the JWT, which is intended for the API, not this
@@ -284,15 +296,18 @@ def __init__(self,
284296
# extract the environment name from the authorization URL aka token API endpoint
285297
if self.environment is None:
286298
self.environment = re.sub(r'https://netfoundry-([^-]+)-.*', r'\1', token_endpoint, re.IGNORECASE)
287-
self.logger.debug(f"using environment parsed from token_endpoint URL {self.environment}")
299+
self.logger.debug(f"using environment parsed from authenticationUrl: {self.environment}")
288300
# re: scope: we're not using scopes with Cognito, but a non-empty value is required;
289301
# hence "/ignore-scope"
290-
scope = "https://gateway."+self.environment+".netfoundry.io//ignore-scope"
302+
scope = f"https://gateway.{self.environment}.netfoundry.io//ignore-scope"
303+
self.logger.debug(f"computed scope URL from 'gateway' and environment: {scope}")
291304
# we can gather the URL of the API from the first part of the scope string by
292305
# dropping the scope suffix
293306
self.audience = scope.replace(r'/ignore-scope', '')
294-
self.logger.debug(f"using audience parsed from token_endpoint URL {self.audience}")
295-
# e.g. https://gateway.production.netfoundry.io/
307+
self.logger.debug(f"computed audience from authenticationUrl sans the trailing '/ignore-scope': {self.audience}")
308+
audience_parts = self.audience.split('.')
309+
self.audience = '.'.join([f"https://{self.gateway}"]+audience_parts[1:])
310+
self.logger.debug(f"computed audience with substituted param 'gateway': {self.audience}")
296311
assertion = {
297312
"scope": scope,
298313
"grant_type": "client_credentials"
@@ -544,7 +559,7 @@ def get_network_group(self, network_group_id):
544559
545560
:param network_group_id: the UUID of the network group
546561
"""
547-
url = self.audience+'rest/v1/network-groups/'+network_group_id
562+
url = self.audience+'core/v2/network-groups/'+network_group_id
548563
try:
549564
network_group, status_symbol = get_generic_resource_by_url(setup=self, url=url)
550565
except Exception as e:
@@ -585,7 +600,7 @@ def find_network_groups_by_organization(self, **kwargs):
585600
586601
:param str kwargs: filter results by any supported query param
587602
"""
588-
url = self.audience+'rest/v1/network-groups'
603+
url = self.audience+'core/v2/network-groups'
589604
network_groups = list()
590605
for i in find_generic_resources(setup=self, url=url, embedded=RESOURCES['network-groups']._embedded, **kwargs):
591606
network_groups.extend(i)

netfoundry/utility.py

+11-4
Original file line numberDiff line numberDiff line change
@@ -319,6 +319,15 @@ def create_generic_resource(setup: object, url: str, body: dict, headers: dict =
319319
proxies=setup.proxies,
320320
verify=setup.verify,
321321
)
322+
if response.status_code in range(400, 600):
323+
req = response.request
324+
setup.logger.debug(
325+
'%s\n%s\r\n%s\r\n\r\n%s',
326+
'-----------START-----------',
327+
req.method + ' ' + req.url,
328+
'\r\n'.join('{}: {}'.format(k, v) for k, v in req.headers.items()),
329+
req.body
330+
)
322331
response.raise_for_status()
323332
resource = response.json()
324333

@@ -454,8 +463,6 @@ def find_generic_resources(setup: object, url: str, headers: dict = dict(), embe
454463
# only get requested page, else first page and all pages
455464
if params.get('page'):
456465
get_all_pages = False
457-
elif resource_type.name == 'network-groups':
458-
params['page'] = 1 # start at 1 instead of 0 to workaround https://netfoundry.atlassian.net/browse/MOP-17890
459466
else:
460467
params['page'] = 0
461468

@@ -658,6 +665,8 @@ def __post_init__(self):
658665
if self.find_url == 'default':
659666
if self.domain == 'network':
660667
setattr(self, 'find_url', f'core/v2/{self.name}')
668+
elif self.domain == 'network-group':
669+
setattr(self, 'find_url', f'core/v2/{self.name}')
661670
elif self.domain == 'identity':
662671
setattr(self, 'find_url', f'identity/v1/{self.name}')
663672
elif self.domain == 'authorization':
@@ -715,10 +724,8 @@ def __post_init__(self):
715724
'network-groups': ResourceType(
716725
name='network-groups',
717726
domain='network-group',
718-
_embedded='organizations',
719727
mutable=False,
720728
embeddable=False,
721-
find_url='rest/v1/network-groups',
722729
),
723730
'networks': ResourceType(
724731
name='networks',

0 commit comments

Comments
 (0)