Skip to content

Use CLI to target other clouds#1098

Merged
derekbekoe merged 9 commits intoAzure:masterfrom
derekbekoe:cloud-support
Oct 21, 2016
Merged

Use CLI to target other clouds#1098
derekbekoe merged 9 commits intoAzure:masterfrom
derekbekoe:cloud-support

Conversation

@derekbekoe
Copy link
Member

@derekbekoe derekbekoe commented Oct 19, 2016

Closes #651

Changes:

  • Add default subscription support to context
  • 'account list' should only return accounts for the current cloud
  • az account list now has a --all option
  • Override active context with env var
  • Rename environmentName to cloudName in 'account list'
  • use context instead of environment
  • cloud register/unregister
  • set base_url for SubscriptionClient
  • Remove _azure_env
  • new env and cloud commands
  • cloud list command

This change is Reviewable

@derekbekoe
Copy link
Member Author

CONTEXT COMMAND HELP

$ az context create -h

Command
    az context create

Arguments
    --cloud   [Required]: Name of the registered cloud.
    --name -n [Required]: Name of context.
    --use-later         : After creating the context, do not set it to be active immediately.
$ az context list -h

Command
    az context list

Arguments

$ az context show -h

Command
    az context show

Arguments
    --name -n  : Name of the context to modify. If not specified, we use the current context.
$ az context switch -h

Command
    az context switch

Arguments
    --name -n [Required]: Name of context.
$ az context modify -h

Command
    az context modify

Arguments
    --cloud               : Name of the registered cloud.
    --default-subscription: Name or id of the default subscription to be used with this context.
    --name -n             : Name of the context to modify. If not specified, we use the current
                            context.
$ az context delete -h

Command
    az context delete

Arguments
    --name -n [Required]: Name of context.

@derekbekoe
Copy link
Member Author

CLOUD COMMAND HELP

$ az cloud register -h

Command
    az cloud register
        Register a cloud by passing in the configuration for it. After a cloud is registered, it can
        be referenced in the context commands.

Arguments
    --name -n                                             [Required]: Name of the registered cloud.
    --endpoint-active-directory
    --endpoint-active-directory-graph-resource-id
    --endpoint-active-directory-resource-id
    --endpoint-gallery
    --endpoint-management
    --endpoint-resource-manager
    --endpoint-sql-management
    --param-azure-datalake-analytics-catalog-and-job-endpoint-suffix
    --param-azure-datalake-store-file-system-endpoint-suffix
    --param-keyvault-dns-suffix
    --param-sql-server-hostname-suffix
    --param-storage-endpoint-suffix
$ az cloud unregister -h

Command
    az cloud unregister

Arguments
    --name -n [Required]: Name of the registered cloud.
$ az cloud list -h

Command
    az cloud list: List the clouds registered in the CLI.

Arguments

$ az cloud show -h

Command
    az cloud show: Show the endpoints and parameters for a cloud registered in the CLI.

Arguments
    --name -n [Required]: Name of the registered cloud.

@derekbekoe
Copy link
Member Author

'az account list' has also been modified.
Now, it lists the accounts for the current cloud.
--all flag is available to list all accounts.

New help...

$ az account list -h

Command
    az account list: List the imported subscriptions.

Arguments
    --all      : List all subscriptions.

@tjprescott
Copy link
Member

For az context modify, why can you not specify arbitrary key/value pairs? If this is presumably the "bundle of settings" concept, there should be a mechanism to set these without resorting to opening the file in a text editor. Maybe not important for the PR.

Copy link
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.

Most comments are just discussion points, but I would like to see changes to the the CloudEndpointUrls and CloudParam classes.

return "The cloud '{}' is already registered.".format(self.cloud_name)

class CannotUnregisterCloudException(Exception):
pass
Copy link
Member

Choose a reason for hiding this comment

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

Does this intentionally do nothing? I would recommend a comment either stating why or a TODO to indicate that future work will be expected here.

Copy link
Member Author

Choose a reason for hiding this comment

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

pass

class CloudEndpointUrl(object): # pylint: disable=too-few-public-methods
MANAGEMENT = 'management'
Copy link
Member

Choose a reason for hiding this comment

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

I think @BurtBiel would suggest that these be lower cased since ultimately they're just properties and not really constants. For ease of creating Azure Stack endpoint objects, I would recommend you give these objects a constructor so you can do this:

myendpoint = CloudEndpointUrl(
  'managment.wonky.com',
  'sql.wonky.com',
  ...)

instead of:

myendpoint = CloudEndpointUrl()
myendpoint.MANAGEMENT = 'managment.wonky.com'
myendpoint.SQL_MANAGEMENT = 'sql.wonky.com'

The all caps in the second version are even more strange because it looks like you are setting the value of a constant (which of course they aren't really constants)

Finally, the init would allow you to default certain endpoints (perhaps to public Azure?) if you wanted to.

Copy link
Member Author

Choose a reason for hiding this comment

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

The class isn't used in this way.
It's more of a container for storing the key names for the cloud endpoints. Kind of like an enum with the value being a string instead of an int.

I don't call the constructor anywhere.

Copy link
Member

Choose a reason for hiding this comment

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

But you will need to call the constructor for Stack configurations, yes? I realize it was used this way in the original implementation, which was kind of wonky, but if we are going to be populating dynamic ones, it doesn't make sense to keep that implementation.

class CannotUnregisterCloudException(Exception):
pass

class CloudEndpointUrl(object): # pylint: disable=too-few-public-methods
Copy link
Member

Choose a reason for hiding this comment

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

Recommend changing the name to CloudEndpoints since the object itself isn't an URL, merely a container for URLs...

Copy link
Member Author

Choose a reason for hiding this comment

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

Will change to CloudEndpoint.

ACTIVE_DIRECTORY_RESOURCE_ID = 'active_directory_resource_id'
ACTIVE_DIRECTORY_GRAPH_RESOURCE_ID = 'active_directory_graph_resource_id'

class CloudParam(object): # pylint: disable=too-few-public-methods
Copy link
Member

Choose a reason for hiding this comment

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

Same general comments as above regarding __init__ and lower casing the property names. Also I would recommend naming the class CloudSuffixes since they are all URL suffixes and Param is pretty vague.

Also, the default strings here and above could just as well be empty strings because 'active_directory' isn't a valid URL suffix for anything.

Copy link
Member Author

Choose a reason for hiding this comment

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

As above, the case isn't used in this way as I don't call the constructor.

Also, the default strings here and above could just as well be empty strings because 'active_directory' isn't a valid URL suffix for anything.

It's the key for the entry, not the suffix (or endpoint) itself.

Will change the name from CloudParam to CloudSuffix though.

def __init__(self, name, endpoints=None, params=None):
self.name = name
self.endpoints = endpoints
self.params = params
Copy link
Member

Choose a reason for hiding this comment

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

recommend changing params to suffixes.

Copy link
Member Author

Choose a reason for hiding this comment

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

Changed.

if not skip_set_active_subsciption:
_set_active_subscription(get_active_context())

def get_context_names():
Copy link
Member

Choose a reason for hiding this comment

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

I like that "context" isn't "environment"... but context seems more vague and at least as confusing. Why not "settings"?

When I worked with Android, they use context all over the place, and I still to this day cannot really tell you what the hell a context is in the Android world (an instance of a THING is pretty close but it's very unintuitive).

Copy link
Member Author

@derekbekoe derekbekoe Oct 20, 2016

Choose a reason for hiding this comment

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

I like 'context' over 'settings' personally. Can't quite articulate why but it feels more natural than 'settings'.
I originally had 'environment' but we've had discussions about why we can't/shouldn't use that.

@johanste, @mayurid, @yugangw-msft thoughts?

Copy link
Member Author

Choose a reason for hiding this comment

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

As discussed, going with 'context'. At least for now.

# Licensed under the MIT License. See License.txt in the project root for license information.
#---------------------------------------------------------------------------------------------

import os
Copy link
Member

Choose a reason for hiding this comment

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

Should context.py really be part of CLI core? In theory the entire CLI and the cloud selection works without any "context". If that's the case, it seems to me like it would more appropriately fit in the extensions world, since it is a user convenience.

Copy link
Member Author

Choose a reason for hiding this comment

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

It needs to be part of CLI core as almost all operations require knowledge of 'the current cloud' and this is saved in context.

The user will not be exposed to context though unless they need it for their particular scenario.

raise CLIError(e)

# pylint: disable=unused-argument
def register_cloud(cloud_name,
Copy link
Member

Choose a reason for hiding this comment

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

We should expose a "discovery_endpoint" or similar thing that if specified would attempt to query the provided URL for all of these settings. Even if not every service or cloud supports it, it would be nice for those that do.

Copy link
Member Author

Choose a reason for hiding this comment

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

This does not exist yet but it's a good suggestion.
We can add support for this feature once the clouds have a discovery endpoint.

elif arg.startswith('param_') and method_args[arg]:
cloud_to_add.params[arg.replace('param_', '')] = method_args[arg]
try:
add_cloud(cloud_to_add)
Copy link
Member

Choose a reason for hiding this comment

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

So if I already have a cloud's config file, how would I import that? I think this command just takes the endpoints, formats them and puts them in the user's env_config folder. It would be nice to support a JSON string here (which you could then load using @ syntax from your file) or just take a file path, validate it and move it into the necessary folder.

We could just tell people to drop that config file into the necessary directory, but that seems... clunky?

Copy link
Member Author

Choose a reason for hiding this comment

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

Added support for passing in a cloud config file.


MSG_GLOBAL_SETTINGS_LOCATION = 'Your global settings can be found at {}'
MSG_ACTIVE_ENV_SETTINGS_LOCATION = 'Your current environment settings can be found at {}'
MSG_ACTIVE_CONTEXT_SETTINGS_LOCATION = 'Your current context settings can be found at {}'
Copy link
Member

Choose a reason for hiding this comment

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

This sort of illustrates my point on "context". I have no idea what "context settings" means. However, if you took it out and it said "Your current settings can be found at..." that does make a lot more sense to me.

Copy link
Member Author

@derekbekoe derekbekoe Oct 20, 2016

Choose a reason for hiding this comment

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

Changed to just say Your current settings...

@JasonRShaver
Copy link
Contributor

JasonRShaver commented Oct 19, 2016

For CLI-specific commands (as opposed to service-related), we should always include short-descriptions for Groups (context, cloud) and commands. #Resolved

Squashed commits:
[6b9df5b] support removing of default subscription
[261310c] fix some pylint
[0d312a1] Add default subscription support to context
[92a97d7] name change
[2361eaa] context_config to context
[92dc856] az account list now has a --all option
[0fa8d59] Override active context with env var
[40130b6] environment -> context
[14271ff] Rename environmentName to cloudName in 'account list'
- 'account list' should only return accounts for the current cloud
[60cf2c0] use context instead of environment
[fa03638] revert todict change and commented out environment commands
[a029bf9] remove todos (+9 squashed commits)
Squashed commits:
[53e0530] fix role and keyvault not loading
[fd6e087] cloud register/unregister :)
[dd00fa5] use exception convention
[f214720] cloud register commands
[ca6da4a] fix _CLOUD to CLOUD
[e27a466] need to set base_url for SubscriptionClient
[5272b9a] Remove _azure_env
[fc1b6bb] new env and cloud commands
[525330c] cloud list command
- vm module depends on  azure-storage SDK
- Storage data-plane suffix support
- set base urls
- After log in, we should show cloud name
- fix management endpoint for german cloud
- Don't remove the cached creds that match the current user when logging in
- modify cloud help
Squashed commits:
[126c9a8] Code review changes
[cd628d1] Add support for loading registering a cloud using a json file with the params in
[598fd3d] fix no dot
@derekbekoe
Copy link
Member Author

thanks!

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.

4 participants