Skip to content
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

[AMS CLI] Added Azure Media Service CLI Module #6044

Merged
merged 106 commits into from
Apr 25, 2018

Conversation

lucasmarambio
Copy link
Contributor

@lucasmarambio lucasmarambio commented Apr 6, 2018

First version of Azure Media Services CLI Module. This version supports the following commands:

Account commands

  • az ams account create
  • az ams account update
  • az ams account show
  • az ams account list
  • az ams account delete
  • az ams account storage add
  • az ams account storage remove
  • az ams account sp create
  • az ams account sp reset-credentials

Transform commands

  • az ams transform create
  • az ams transform show
  • az ams transform list
  • az ams transform delete
  • az ams transform update
  • az ams transform output add
  • az ams transform output remove

Asset commands

  • az ams asset create
  • az ams asset update
  • az ams asset show
  • az ams asset list
  • az ams asset delete
  • az ams asset get-sas-urls

Job commands

  • az ams job start
  • az ams job show
  • az ams job list
  • az ams job cancel
  • az ams job delete

Streaming commands

  • az ams streaming locator create
  • az ams streaming locator show
  • az ams streaming locator list
  • az ams streaming locator get-paths
  • az ams streaming locator delete
  • az ams streaming policy create
  • az ams streaming policy show
  • az ams streaming policy list
  • az ams streaming policy delete

@promptws
Copy link

promptws commented Apr 6, 2018

View a preview at https://prompt.ws/r/Azure/azure-cli/6044
This is an experimental preview for @microsoft users.

@derekbekoe derekbekoe added this to the Sprint 36 (Build) milestone Apr 9, 2018
@lucasmarambio
Copy link
Contributor Author

@tjprescott the pull request is ready for review

@derekbekoe
Copy link
Member

Why is the SDK in azure/mediav3?

@damatojuan
Copy link

@derekbekoe we included the media SDK because it's not available in https://github.com/Azure/azure-sdk-for-python yet since is still in preview. We autogenerated it from https://github.com/Azure/azure-rest-api-specs/tree/MediaServices-2018-03-30-preview/specification/mediaservices/resource-manager/Microsoft.Media/preview/2018-03-30-preview.
If your question is about why we used the azure/mediav3 namespace, that's because we didn't find any guideline or documentation about placing an SDK inside the Azure-CLI so we based on https://github.com/Azure/azure-cli/blob/dev/src/azure-cli-core/azure/cli/core/commands/client_factory.py#L32.

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.

There are some coding issues I identified. Reach out to me if any don't make sense. Overall, looks good and the test coverage looks great. Would like @sptramer to review the help and @yugangw-msft to look over the SP create stuff.

Release History
===============

0.0.1
Copy link
Member

Choose a reason for hiding this comment

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

I believe this should be 0.1.0. @derekbekoe is that right? I realize we have done this differently in the past.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Done

class MediaServicesCommandsLoader(AzCommandsLoader):

def __init__(self, cli_ctx=None):
super(MediaServicesCommandsLoader, self).__init__(cli_ctx=cli_ctx)
Copy link
Member

Choose a reason for hiding this comment

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

You need to add the following kwarg:

super(MediaServicesCommandsLoader, self).__init__(cli_ctx=cli_ctx, min_profile='2017-03-10-profile')

Otherwise the module will appear on the Azure stack profile and cause errors.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Done

client = GraphRbacManagementClient(cred, tenant_id,
base_url=cli_ctx.cloud.endpoints.active_directory_graph_resource_id)
configure_common_settings(cli_ctx, client)
return client
Copy link
Member

Choose a reason for hiding this comment

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

These are duplicated from the azure-cli-role module. What do you need these for? If other modules need them, we can consider moving them into the core.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

This is used by the service principals commands. We need those methods (_auth_client_factory, _graph_client_factory) to retrieve the clients to manage the service principals for media accounts (create applications, grant access permissions, create secrets, etc).

Moving those methods to the core might be a good option. Is this something that you would like us to do? In that case, which will be the best place to put them? azure.cli.core.commands.client_factory seems a good place.

Copy link

@johndeu johndeu Apr 12, 2018

Choose a reason for hiding this comment

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

It would be nice to have them in the core for others to use. We really need to simplify the process of getting customer's their AAD application, Service Principals, and Keys for services that are moving their customers to AAD and off of ACS.

We are really complicating things when moving our customers off of simple Keys and trying to explain why they need an AAD AP, then a Service Principal, and then get a Key from that... very confusing stuff for our general customers who may not be core Azure devs.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

This is also related to #6044 (comment)

helps['ams streaming policy show'] = """
type: command
short-summary: Show the details of a streaming policy.
"""
Copy link
Member

Choose a reason for hiding this comment

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

@sptramer for help review.

parameters:
- name: --account-name
short-summary: The name of the Azure Media Services account within the resource group.
- name: --name
Copy link
Member

Choose a reason for hiding this comment

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

I don't think this will be applied if it is not listed as:

- name: --name -n
  short-summary: blah blah

Is there a reason you have the parameter help in the help.py file for this one command?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

You're right, we will list the help as you specified. We specified the parameters just because the --years argument doesn't show a fallback help text, so we'll remove the rest ones.

help='Enable Dash protocol.')
c.argument('hls',
arg_group='Encryption Protocols',
help='Enable Hls protocol.')
Copy link
Member

Choose a reason for hiding this comment

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

HLS

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Done

if not acc:
raise ValueError("Storage account named '{}' not found in the resource group '{}'.".
format(namespace.storage_account, namespace.resource_group_name))
namespace.storage_account = acc.id # pylint: disable=no-member
Copy link
Member

Choose a reason for hiding this comment

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

See this logic for the recommended way of implementing "name or ID" behavior:
https://github.com/Azure/azure-cli/blob/dev/doc/authoring_command_modules/authoring_commands.md#supporting-name-or-id-parameters

If it is NOT a valid ID (which there is a standard call for) then build the ID (in this case, assuming regular storageAccount not classic storage). Always assume it exists and let ARM fail if it doesn't. Don't do a GET just to make sure the account exists. If it does exists, the check wasn't necessary and you made extra REST calls for no reason. If it doesn't exist, it will fail either way.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Done

operations_tmpl='azure.cli.command_modules.ams.operations.{}#'.format(custom_module) + '{}',
client_factory=client_factory,
exception_handler=build_exception_wrapper()
)
Copy link
Member

Choose a reason for hiding this comment

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

The command registration seems much more verbose than I usually see, and I think the culprit may be this pattern. Did you emulate this pattern from an existing module?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Yes, we emulate this pattern from the storage module:

def get_custom_sdk(custom_module, client_factory, resource_type=ResourceType.DATA_STORAGE):

Should we consider changing this implementation?

Copy link
Member

Choose a reason for hiding this comment

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

You really should not follow storage. Nearly any other module would be much simpler. Please look at network and see if that pattern is simpler. It should be.

@ResourceGroupPreparer()
@StorageAccountPreparer(parameter_name='storage_account_for_create')
def test_ams_create_show(self, resource_group, storage_account_for_create):
amsname = self.create_random_name(prefix='ams', length=12)
Copy link
Member

Choose a reason for hiding this comment

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

Unless the AMS account name needs to be globally unique (like KeyVaults or StorageAccounts) you can get away with a static name here.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Given that unit tests run in parallel, using the same static account name for all tests leads to name collision. Media account names should be unique by location and all test accounts are created under the same location. We could use different static account names for each test, but we believe that generating names randomly minimizes the chance of potential collisions.

Copy link
Member

Choose a reason for hiding this comment

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

Fair enough. Most resources only need to be unique within the RG.

# --------------------------------------------------------------------------------------------


def build_exception_wrapper(message=None):
Copy link
Member

Choose a reason for hiding this comment

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

When I look at where this is used in commands.py, it doesn't look like there's any need for this to be a factory. You can simply remove this and pass "build_exception" directly

exception_handler=build_exception

I would also rename build_exception to something more descriptive like ams_exception_handler.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Good catch, we'll clean and rename this exception handler.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Done

@tjprescott tjprescott self-assigned this Apr 10, 2018
@tjprescott
Copy link
Member

@yugangw-msft would you please take a quick look at their sp create command using https://prompt.ws/r/Azure/azure-cli/6044 just to make sure it aligns with existing SP create commands?

@yugangw-msft
Copy link
Contributor

yugangw-msft commented Apr 10, 2018

 @yugangw-msft would you please take a quick look at their sp create command using https://prompt.ws/r/Azure/azure-cli/6044 just to make sure it aligns with existing SP create commands?

Guess it mostly copied and pasted the code from the azure-cli-role module. Any reason we can't point users to use the generic SP commands instead of mostly duplicating the same command here? The concerns is the SDK library of azure-mgmt-authorization (and azure-graphrbac possibly) will change, and the library upgrading could break the cloned commands.
Also it is common for cli users to use multiple command modules to get a workflow done. Only using commands from a single command doesn't necessary mean the superiority or better user experience, because having 2 places to do the same thing always ends up being confusing

@lucasmarambio
Copy link
Contributor Author

Thanks for the feedback @yugangw-msft.

Adding @johndeu to help deciding the best approach. Perhaps the alternatives are:

  1. Remove the SP commands from the azure-cli-ams and let users add permissions through the generic SP commands in azure-cli-role as @yugangw-msft suggests.
  2. Extract the logic for SP management that is common between the ams and role modules to the core module. This might not be a straight forward tasks and might require a considerable effort.
  3. Add an exception for this particular case to keep the duplicated pieces of code in both modules.

@johndeu
Copy link

johndeu commented Apr 12, 2018

Can you demonstrate the number of CLI commands required to do the equivalent amount of work with both workflows? I believe we were wrapping several steps into one in our command and returning the content in a format that was easier for our customers to consume. I'm trying to keep the AAD portion of our CLI as simple as possible, since we are targeting a slightly different audience than typical core Azure with some of our customer base. We will get a lot of customers that are Media focused, and just want to get a darn Key to connect to the API as easy as we can make it without learning about what AAD applications and a Service Principal really are.

@lucasmarambio
Copy link
Contributor Author

We just had an offline conversation with @johndeu to review the options regarding the SP command in the AMS module and agreed that it would be important to keep the current implementation as-is for the first release. For media focused customers this SP command is not just an easy way to create service principals and assign roles, but also to consolidate all the necessary information to connect to an AMS account (which is provided in the form of JSON/XML format in the command output).

@yugangw-msft @tjprescott could we add an exception and proceed with the current approach for the first release of the module?

@yugangw-msft
Copy link
Contributor

yugangw-msft commented Apr 13, 2018

  @yugangw-msft @tjprescott could we add an exception and proceed with the current approach for the first release of the module?

I understand your situation. Could you please share with me the commands to accomplish the end to end flow? If you can do all to avoid people ever getting to the generic RBAC commands, then it is your call. But by looking at the command signatures you provided, I don't see it is complete at a basic level. Say, I don't see SP list/show/delete command, so wonder a bit for how you can help people find the SP they are interested? Also for generic RBAC commands, we will keep on improving it, particularly for "my sp" support, so you don't need to wait for 20 minutes to list 1000000+ ones your org has, and also we will make it work with MS-Graph someday. With your cloned effort, your service will be left out.

If you still decide to proceed, please write an end to end test so to avoid the breaking when CLI upgrades the SDK dependencies

@yugangw-msft
Copy link
Contributor

>we included the media SDK because it's not available in https://github.com/Azure/azure-sdk-for-python yet since is still in preview.

@damatojuan, please create a wheel and check-in the binary to the privates folder which CI system recognizes. This way we can get rid of the generated SDK files from this PR and focus on the command logics, also the github web pages will be more responsive with less files involved

@lucasmarambio
Copy link
Contributor Author

@yugangw-msft find some answers below:

I understand your situation. Could you please share with me the commands to accomplish the end to end flow?

With this command users create a media account:

az ams account create -n {amsname} -g {rg} --storage-account {storageAccount} -l {location}

With this command users create a service principal with {role} access to the media account:

az ams account sp create -a {amsname} -n {spName} -g {rg} -p {spPassword} --role {role}

The output of this command provides all the information required to connect to the media account using Azure AD authentication:

{
  "AadClientId": "1598b742-a872-421e-a874-2475037db34b",
  "AadEndpoint": "https://login.microsoftonline.com",
  "AadSecret": {spPassword},
  "AadTenantId": "479472dc-cfef-474c-ba12-cba2854af0f6",
  "AccountName": {amsname},
  "ArmAadAudience": "https://management.core.windows.net/",
  "ArmEndpoint": "https://management.azure.com/",
  "Region": {rg-location},
  "ResourceGroup": {rg},
  "SubscriptionId": "d9b02582-2f4f-4b5d-a3dc-ba0015515f7b"
}

Say, I don't see SP list/show/delete command, so wonder a bit for how you can help people find the SP they are interested?

We only intended to provide a way to easily create and associate a SP with a media account, that's why only the ams account sp create and ams account sp reset-credentials commands are supported. For additional management, users should use the generic SP commands from the role module.

If you still decide to proceed, please write an end to end test so to avoid the breaking when CLI upgrades the SDK dependencies

We are currently providing tests for each command which should fail if there is any breaking change in the SDK dependencies.

@lucasmarambio
Copy link
Contributor Author

@damatojuan, please create a wheel and check-in the binary to the privates folder which CI system recognizes. This way we can get rid of the generated SDK files from this PR and focus on the command logics, also the github web pages will be more responsive with less files involved

@yugangw-msft the current version of the AMS SDK is still in preview, and some tweaks were required in the generated SDK files that need to be tracked here for the moment. Once AMS is released as part of the Azure Python SDK, we'll remove the generated SDK files from the repo.

@yugangw-msft
Copy link
Contributor

yugangw-msft commented Apr 13, 2018

@lucasmarambio I understand it is under preview. My point was, since we are not reviewing generated code, I suggest you check in the wheel (if you have Python SDK PR submitted, it should expose the link to the wheel you can download or you can build out on your own). This has the benefit that you can get CI green on you PR, also your setup file can stay unchanged; and all you need to do in future is to remove the privates\your-wheel-file once @lmazuel publishes the sdk for you.
EDIT, or your team will release the CLI w/o public SDKs? Please clarify

@lucasmarambio
Copy link
Contributor Author

@lucasmarambio I understand it is under preview. My point was, since we are not reviewing generated code, I suggest you check in the wheel (if you have Python SDK PR submitted, it should expose the link to the wheel you can download or you can build out on your own). This has the benefit that you can get CI green on you PR, also your setup file can stay unchanged; and all you need to do in future is to remove the privates\your-wheel-file once @lmazuel publishes the sdk for you.

Looping @tjprescott as we agreed with him to place the generated SDK files in this PR. @tjprescott could you help us with this? I am not quite familiar with Python wheels so maybe I'm missing something here. The main concern I see is that we made changes to the generated SDK files for the AMS CLI to work properly while in preview, so we need to track those changes here for everything to be on sync.

@yugangw-msft
Copy link
Contributor

To generate a wheel, you just run one command under the SDK folder with the setup.py: python setup.py bdist_wheel, and you should see the wheel generated under a sub-folder. It is you and @tjprescott's call by the way since you 2 will work the most on this PR. My main question was whether the CLI will be released w/o public Python SDK.

Lucas Marambio and others added 25 commits April 24, 2018 19:37
- Add MediaServicesCommandLoader
- Remove unnecesary parameters help commands
- Don't use tuple syntax
- Register account_name in ams scope
- Remove 'within the resource group'
- Set account_name help text generic
- Apply account_name_arg_type
- Typo: built-in
- Remove Customer-supplied
- Remove exception factory
- Rename `storage_account_id` to `validate_storage_account_id`
- Assume storage account id exists to build the storage_account_id.
- Set flag for `ams job cancel`
- Set flags for protocols in `ams streaming policy`
- Support multiple permissions for `ams asset get-sas-urls`
@tjprescott tjprescott merged commit 0cf5f8b into Azure:dev Apr 25, 2018
@damatojuan damatojuan deleted the add/ams-module branch July 2, 2018 20:37
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.

9 participants