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

[ACR] Improve perf and fix permission in repository commands #4566

Merged
merged 5 commits into from
Oct 3, 2017

Conversation

djyou
Copy link
Member

@djyou djyou commented Sep 28, 2017

  • Avoid making list-manifests call when users wish to force delete a manifest either by digest or tag.
  • Fix an issue with AAD authentication when logged in using read-access-only role service principal.

This checklist is used to make sure that common guidelines for a pull request are followed.

General Guidelines

  • The PR has modified HISTORY.rst describing any customer-facing, functional changes. Note that this does not include changes only to help content. (see Modifying change log).

Command Guidelines

  • Each command and parameter has a meaningful description.
  • Each new command has a test.

(see Authoring Command Modules)

@djyou
Copy link
Member Author

djyou commented Sep 28, 2017

/cc @sajayantony

@sajayantony
Copy link
Contributor

/cc @yuwaMSFT2

if username is None:
auth = _bearer_auth_str(password)
else:
auth = _basic_auth_str(username, password)

if is_manifest:
Copy link
Contributor

Choose a reason for hiding this comment

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

Can you break this out into its own function like AddManifestHeader

retry_times=3, # pylint: disable=unused-argument
retry_interval=5): # pylint: disable=unused-argument
registryEndpoint = 'https://' + login_server
def _params(count=20):
Copy link
Contributor

Choose a reason for hiding this comment

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

This function name is too generic and will lead to ambiguity. Please make it more accurate.

else:
raise CLIError(response.text)
def _delete_data_from_registry(login_server, path, username, password, **kwargs):
retry_times = kwargs['retry_times'] if 'retry_times' in kwargs else 3
Copy link
Contributor

Choose a reason for hiding this comment

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

If retry_times is a value given by user through command line option, the default value should be defined with the parameter.

Copy link
Contributor

Choose a reason for hiding this comment

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

Otherwise, why not list retry_times and retry_interval as the parameter in the method signature and define default value along with it?

raise CLIError(response.text)
def _delete_data_from_registry(login_server, path, username, password, **kwargs):
retry_times = kwargs['retry_times'] if 'retry_times' in kwargs else 3
retry_interval = kwargs['retry_interval'] if 'retry_interval' in kwargs else 5
Copy link
Contributor

Choose a reason for hiding this comment

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

Same as above.


if errorMessage:
Copy link
Contributor

Choose a reason for hiding this comment

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

headers=_headers(username, password)
)

if response.status_code == 200 or response.status_code == 202:
Copy link
Contributor

Choose a reason for hiding this comment

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

Is this condition too rigorous? Do the other status code in 2XX represents a failure?

def _obtain_data_from_registry(login_server, path, username, password, **kwargs):
result_index = kwargs['result_index'] if 'result_index' in kwargs else ''
retry_times = kwargs['retry_times'] if 'retry_times' in kwargs else 3
retry_interval = kwargs['retry_interval'] if 'retry_interval' in kwargs else 5
Copy link
Contributor

Choose a reason for hiding this comment

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

Same as above.

@@ -130,9 +146,43 @@ def _obtain_data_from_registry(login_server,
return resultList


def _get_manifest_digest(login_server, path, username, password, **kwargs):
retry_times = kwargs['retry_times'] if 'retry_times' in kwargs else 3
retry_interval = kwargs['retry_interval'] if 'retry_interval' in kwargs else 5
Copy link
Contributor

Choose a reason for hiding this comment

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

Same as above.

try:
errorMessage = None
response = requests.get(
'https://{}/{}'.format(login_server, path),
Copy link
Contributor

Choose a reason for hiding this comment

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

Are login_server and path from user input? If so, should this be validated before form this URL?

Copy link
Member Author

Choose a reason for hiding this comment

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

login_server is queried from ACR RP.

for i in range(0, retry_times):
try:
errorMessage = None
response = requests.get(

Choose a reason for hiding this comment

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

Is this sending a manifest GET request? If you only want to know the digest from response header, you can send HEAD request to avoid transferring the body which you don't care.

@@ -226,6 +276,7 @@ def acr_repository_show_tags(registry_name,
registry_name=registry_name,
resource_group_name=resource_group_name,
path='/v2/{}/tags/list'.format(repository),
permission='pull',

Choose a reason for hiding this comment

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

one question: for CLI to send request to registry, does it first get a challenge response from registry? If we do, there is information in the challenge response on what permission is needed. If we are not getting challenge response but hard-code the permission, there is a concern that this may change from the server side (although unlikely, just keep in mind).

retry_times=3, # pylint: disable=unused-argument
retry_interval=5): # pylint: disable=unused-argument
registryEndpoint = 'https://' + login_server
def _params(count=20):

Choose a reason for hiding this comment

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

So this query parameter is used for all list related API calls (list manifest, catalog, tag list)?

Copy link
Member Author

Choose a reason for hiding this comment

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

Correct, all registry list calls will use this pagination count by default.

registryEndpoint + path,
headers=_headers(username, password)
)
def _pagination_params(count):
Copy link
Contributor

Choose a reason for hiding this comment

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

A preferable method naming schema is verb + noun.

print(login_server)
print(username)
print(password)
print(pagination)
Copy link
Contributor

Choose a reason for hiding this comment

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

Wait ... what's this? Please don't print password.

Copy link
Member Author

Choose a reason for hiding this comment

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

Missed the cleanup here :-)

repository,
tag,
manifest,
yes):
Copy link
Contributor

Choose a reason for hiding this comment

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

yes is not a good parameter name. how about changes it to confirmed

Copy link
Member Author

Choose a reason for hiding this comment

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

yes is the parameter exposed to users so it seems natural to use it along the path rather than creating a new name internally.

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 "yes" is required by the CLI for confirmation... #2520

Copy link
Contributor

Choose a reason for hiding this comment

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

Oh, my bad. But it is not a good name anyway. We may need to address this in the core.

path='/v2/{}/manifests/{}'.format(repository, tag),
username=username,
password=password
)
Copy link
Contributor

Choose a reason for hiding this comment

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

The indentations and condition statement can be saved in the following form:

manifest = manifest or _get_manifest_digest(...)



class Unauthorized(Exception):
class RetryableException(Exception):
Copy link
Contributor

Choose a reason for hiding this comment

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

Why do you define a new type of exception while there isn't any mechanism to treat this exception differently (for example, except RetryableException.)?

Please avoid introducing new exception type unless there is specific logic build around it.

if errorMessage:
raise CLIError(errorMessage)
if errorMessage:
raise CLIError(errorMessage)
Copy link
Contributor

Choose a reason for hiding this comment

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

Ugr, this is not a minor formatting update. This change the control flow. Please double check and make sure this is what you intended to 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 is an intended change, the error should be on the retry for loop.

@djyou
Copy link
Member Author

djyou commented Sep 29, 2017

@troydai Please merge this PR if there is no more comments, thank you.

@djyou
Copy link
Member Author

djyou commented Oct 2, 2017

@troydai Can you please merge this? Thank you :-)

@troydai troydai merged commit 5198bd8 into Azure:master Oct 3, 2017
@djyou djyou deleted the doyou/delete branch October 3, 2017 17:58
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

6 participants