[DRAFT][ACR] Add enriched flag to `acr manifest show` and `acr manifest list`
Related command
acr manifest show and acr manifest list
Description
Adds enriched flag to acr manifest show and acr manifest list to add additional metadata to the output when the flag is present
Testing Guide
az acr manifest show -r myreg -n myrepo:latest -e
az acr manifest show -r myreg -n myrepo -e
History Notes
[ACR] az acr manifest show: Add enriched flag to provide additional metadata in output
[ACR] az acr manifest list: Add enriched flag to provide additional metadata in output
This checklist is used to make sure that common guidelines for a pull request are followed.
-
[x] The PR title and description has followed the guideline in Submitting Pull Requests.
-
[x] I adhere to the Command Guidelines.
-
[x] I adhere to the Error Handling Guidelines.
❌AzureCLI-FullTest
❌acr
️✔️2020-09-01-hybrid
️✔️3.11
️✔️3.9
❌latest
❌3.11
Type Test Case Error Message Line Failed test_manifest_show self = <azure.cli.command_modules.acr.tests.latest.test_acr_commands_mock.AcrMockCommandsTests testMethod=test_manifest_show>
mock_requests_get = <function request at 0x7fc8bd5bc360>
mock_get_manifest_digest = <function get_manifest_digest at 0x7fc8bd5bcb80>
mock_get_access_credentials = <function get_access_credentials at 0x7fc8bd5bd1c0>
mock_get_access_credentials_manifest = <function get_access_credentials at 0x7fc8bd5bd760>
@mock.patch('azure.cli.command_modules.acr.manifest.get_access_credentials', autospec=True)
@mock.patch('azure.cli.command_modules.acr.repository.get_access_credentials', autospec=True)
@mock.patch('azure.cli.command_modules.acr.repository.get_manifest_digest', autospec=True)
@mock.patch('requests.request', autospec=True)
def test_manifest_show(self, mock_requests_get, mock_get_manifest_digest, mock_get_access_credentials, mock_get_access_credentials_manifest):
cmd = self.setup_cmd()
response = mock.MagicMock()
response.headers = {}
response.status_code = 200
response.content = json.dumps({
'schemaVersion': 2,
'mediaType': 'application/vnd.docker.distribution.manifest.v2+json'
}).encode()
mock_requests_get.return_value = response
mock_get_access_credentials.return_value = 'testregistry.azurecr.io', 'username', 'password'
mock_get_access_credentials_manifest.return_value = 'testregistry.azurecr.io', 'username', 'password'
mock_get_manifest_digest.return_value = 'sha256:c5515758d4c5e1e838e9cd307f6c6a0d620b5e07e6f927b07d05f6d12a1ac8d7'
# Get manifest by tag
acr_manifest_show(cmd,
registry_name='testregistry',
manifest_spec='testrepository:testtag')
> mock_requests_get.assert_called_with(
method='get',
url='https://testregistry.azurecr.io/v2/testrepository/manifests/testtag',
headers=get_manifest_authorization_header('username', 'password'),
params=None,
json=None,
timeout=300,
verify=mock.ANY)
src/azure-cli/azure/cli/command_modules/acr/tests/latest/test_acr_commands_mock.py:482:
/opt/hostedtoolcache/Python/3.11.7/x64/lib/python3.11/unittest/mock.py:212: in assert_called_with
return mock.assert_called_with(*args, **kwargs)
_
self = <MagicMock name='request' spec='function' id='140500146870864'>
args = ()
kwargs = {'headers': {'Accept': '/, application/vnd.oci.artifact.manifest.v1+json, application/vnd.cncf.oras.artifact.manifes....list.v2+json', 'Authorization': 'Basic dXNlcm5hbWU6cGFzc3dvcmQ='}, 'json': None, 'method': 'get', 'params': None, ...}
expected = call('', ('get', 'https://testregistry.azurecr.io/v2/testrepository/manifests/testtag'), {'headers': {'Authorization':...cation/vnd.docker.distribution.manifest.list.v2+json'}, 'params': None, 'json': None, 'timeout': 300, 'verify': <ANY>})
actual = call('', ('get', "https://testregistry.azurecr.io/v2/testrepository/manifests/<MagicMock name='mock.json().getitem...ication/vnd.docker.distribution.manifest.list.v2+json'}, 'params': None, 'json': None, 'timeout': 300, 'verify': True})
_error_message = <function NonCallableMock.assert_called_with.._error_message at 0x7fc8bd5be2a0>
cause = None
def assert_called_with(self, /, args, **kwargs):
"""assert that the last call was made with the specified arguments.
Raises an AssertionError if the args and keyword args passed in are
different to the last call to the mock."""
if self.call_args is None:
expected = self._format_mock_call_signature(args, kwargs)
actual = 'not called.'
error_message = ('expected call not found.\nExpected: %s\n Actual: %s'
% (expected, actual))
raise AssertionError(error_message)
def _error_message():
msg = self._format_mock_failure_message(args, kwargs)
return msg
expected = self._call_matcher(_Call((args, kwargs), two=True))
actual = self._call_matcher(self.call_args)
if actual != expected:
cause = expected if isinstance(expected, Exception) else None
> raise AssertionError(_error_message()) from cause
E AssertionError: expected call not found.
E Expected: request(method='get', url='https://testregistry.azurecr.io/v2/testrepository/manifests/testtag', headers={'Authorization': 'Basic dXNlcm5hbWU6cGFzc3dvcmQ=', 'Accept': '/, application/vnd.oci.artifact.manifest.v1+json, application/vnd.cncf.oras.artifact.manifest.v1+json, application/vnd.oci.image.manifest.v1+json, application/vnd.oci.image.index.v1+json, application/vnd.docker.distribution.manifest.v2+json, application/vnd.docker.distribution.manifest.list.v2+json'}, params=None, json=None, timeout=300, verify=<ANY>)
E Actual: request(method='get', url="https://testregistry.azurecr.io/v2/testrepository/manifests/<MagicMock name='mock.json().getitem().getitem()' id='140500149017488'>", headers={'Authorization': 'Basic dXNlcm5hbWU6cGFzc3dvcmQ=', 'Accept': '/*, application/vnd.oci.artifact.manifest.v1+json, application/vnd.cncf.oras.artifact.manifest.v1+json, application/vnd.oci.image.manifest.v1+json, application/vnd.oci.image.index.v1+json, application/vnd.docker.distribution.manifest.v2+json, application/vnd.docker.distribution.manifest.list.v2+json'}, params=None, json=None, timeout=300, verify=True)
/opt/hostedtoolcache/Python/3.11.7/x64/lib/python3.11/unittest/mock.py:939: AssertionErrorazure/cli/command_modules/acr/tests/latest/test_acr_commands_mock.py:457 ❌3.9
Type Test Case Error Message Line Failed test_manifest_show self = <azure.cli.command_modules.acr.tests.latest.test_acr_commands_mock.AcrMockCommandsTests testMethod=test_manifest_show>
mock_requests_get = <function request at 0x7f3f813a9550>
mock_get_manifest_digest = <function get_manifest_digest at 0x7f3f813a9a60>
mock_get_access_credentials = <function get_access_credentials at 0x7f3f81857040>
mock_get_access_credentials_manifest = <function get_access_credentials at 0x7f3f818575e0>
@mock.patch('azure.cli.command_modules.acr.manifest.get_access_credentials', autospec=True)
@mock.patch('azure.cli.command_modules.acr.repository.get_access_credentials', autospec=True)
@mock.patch('azure.cli.command_modules.acr.repository.get_manifest_digest', autospec=True)
@mock.patch('requests.request', autospec=True)
def test_manifest_show(self, mock_requests_get, mock_get_manifest_digest, mock_get_access_credentials, mock_get_access_credentials_manifest):
cmd = self.setup_cmd()
response = mock.MagicMock()
response.headers = {}
response.status_code = 200
response.content = json.dumps({
'schemaVersion': 2,
'mediaType': 'application/vnd.docker.distribution.manifest.v2+json'
}).encode()
mock_requests_get.return_value = response
mock_get_access_credentials.return_value = 'testregistry.azurecr.io', 'username', 'password'
mock_get_access_credentials_manifest.return_value = 'testregistry.azurecr.io', 'username', 'password'
mock_get_manifest_digest.return_value = 'sha256:c5515758d4c5e1e838e9cd307f6c6a0d620b5e07e6f927b07d05f6d12a1ac8d7'
# Get manifest by tag
acr_manifest_show(cmd,
registry_name='testregistry',
manifest_spec='testrepository:testtag')
> mock_requests_get.assert_called_with(
method='get',
url='https://testregistry.azurecr.io/v2/testrepository/manifests/testtag',
headers=get_manifest_authorization_header('username', 'password'),
params=None,
json=None,
timeout=300,
verify=mock.ANY)
src/azure-cli/azure/cli/command_modules/acr/tests/latest/test_acr_commands_mock.py:482:
/opt/hostedtoolcache/Python/3.9.18/x64/lib/python3.9/unittest/mock.py:200: in assert_called_with
return mock.assert_called_with(*args, **kwargs)
_
self = <MagicMock name='request' spec='function' id='139910727844720'>
args = ()
kwargs = {'headers': {'Accept': '/, application/vnd.oci.artifact.manifest.v1+json, application/vnd.cncf.oras.artifact.manifes....list.v2+json', 'Authorization': 'Basic dXNlcm5hbWU6cGFzc3dvcmQ='}, 'json': None, 'method': 'get', 'params': None, ...}
expected = call('', ('get', 'https://testregistry.azurecr.io/v2/testrepository/manifests/testtag'), {'headers': {'Authorization':...cation/vnd.docker.distribution.manifest.list.v2+json'}, 'params': None, 'json': None, 'timeout': 300, 'verify': <ANY>})
actual = call('', ('get', "https://testregistry.azurecr.io/v2/testrepository/manifests/<MagicMock name='mock.json().getitem...ication/vnd.docker.distribution.manifest.list.v2+json'}, 'params': None, 'json': None, 'timeout': 300, 'verify': True})
_error_message = <function NonCallableMock.assert_called_with.._error_message at 0x7f3f81857f70>
cause = None
def assert_called_with(self, /, args, **kwargs):
"""assert that the last call was made with the specified arguments.
Raises an AssertionError if the args and keyword args passed in are
different to the last call to the mock."""
if self.call_args is None:
expected = self._format_mock_call_signature(args, kwargs)
actual = 'not called.'
error_message = ('expected call not found.\nExpected: %s\nActual: %s'
% (expected, actual))
raise AssertionError(error_message)
def _error_message():
msg = self._format_mock_failure_message(args, kwargs)
return msg
expected = self._call_matcher(_Call((args, kwargs), two=True))
actual = self._call_matcher(self.call_args)
if actual != expected:
cause = expected if isinstance(expected, Exception) else None
> raise AssertionError(_error_message()) from cause
E AssertionError: expected call not found.
E Expected: request(method='get', url='https://testregistry.azurecr.io/v2/testrepository/manifests/testtag', headers={'Authorization': 'Basic dXNlcm5hbWU6cGFzc3dvcmQ=', 'Accept': '/, application/vnd.oci.artifact.manifest.v1+json, application/vnd.cncf.oras.artifact.manifest.v1+json, application/vnd.oci.image.manifest.v1+json, application/vnd.oci.image.index.v1+json, application/vnd.docker.distribution.manifest.v2+json, application/vnd.docker.distribution.manifest.list.v2+json'}, params=None, json=None, timeout=300, verify=<ANY>)
E Actual: request(method='get', url="https://testregistry.azurecr.io/v2/testrepository/manifests/<MagicMock name='mock.json().getitem().getitem()' id='139910729569616'>", headers={'Authorization': 'Basic dXNlcm5hbWU6cGFzc3dvcmQ=', 'Accept': '/*, application/vnd.oci.artifact.manifest.v1+json, application/vnd.cncf.oras.artifact.manifest.v1+json, application/vnd.oci.image.manifest.v1+json, application/vnd.oci.image.index.v1+json, application/vnd.docker.distribution.manifest.v2+json, application/vnd.docker.distribution.manifest.list.v2+json'}, params=None, json=None, timeout=300, verify=True)
/opt/hostedtoolcache/Python/3.9.18/x64/lib/python3.9/unittest/mock.py:907: AssertionErrorazure/cli/command_modules/acr/tests/latest/test_acr_commands_mock.py:457 ️✔️acs
️✔️2020-09-01-hybrid
️✔️3.11
️✔️3.9
️✔️latest
️✔️3.11
️✔️3.9
️✔️advisor
️✔️latest
️✔️3.11
️✔️3.9
️✔️ams
️✔️latest
️✔️3.11
️✔️3.9
️✔️apim
️✔️latest
️✔️3.11
️✔️3.9
️✔️appconfig
️✔️latest
️✔️3.11
️✔️3.9
️✔️appservice
️✔️latest
️✔️3.11
️✔️3.9
️✔️aro
️✔️latest
️✔️3.11
️✔️3.9
️✔️backup
️✔️latest
️✔️3.11
️✔️3.9
️✔️batch
️✔️latest
️✔️3.11
️✔️3.9
️✔️batchai
️✔️latest
️✔️3.11
️✔️3.9
️✔️billing
️✔️latest
️✔️3.11
️✔️3.9
️✔️botservice
️✔️latest
️✔️3.11
️✔️3.9
️✔️cdn
️✔️latest
️✔️3.11
️✔️3.9
️✔️cloud
️✔️latest
️✔️3.11
️✔️3.9
️✔️cognitiveservices
️✔️latest
️✔️3.11
️✔️3.9
️✔️config
️✔️latest
️✔️3.11
️✔️3.9
️✔️configure
️✔️latest
️✔️3.11
️✔️3.9
️✔️consumption
️✔️latest
️✔️3.11
️✔️3.9
️✔️container
️✔️latest
️✔️3.11
️✔️3.9
️✔️containerapp
️✔️latest
️✔️3.11
️✔️3.9
️✔️core
️✔️2018-03-01-hybrid
️✔️3.11
️✔️3.9
️✔️2019-03-01-hybrid
️✔️3.11
️✔️3.9
️✔️2020-09-01-hybrid
️✔️3.11
️✔️3.9
️✔️latest
️✔️3.11
️✔️3.9
️✔️cosmosdb
️✔️latest
️✔️3.11
️✔️3.9
️✔️databoxedge
️✔️2019-03-01-hybrid
️✔️3.11
️✔️3.9
️✔️2020-09-01-hybrid
️✔️3.11
️✔️3.9
️✔️latest
️✔️3.11
️✔️3.9
️✔️dla
️✔️latest
️✔️3.11
️✔️3.9
️✔️dls
️✔️latest
️✔️3.11
️✔️3.9
️✔️dms
️✔️latest
️✔️3.11
️✔️3.9
️✔️eventgrid
️✔️latest
️✔️3.11
️✔️3.9
️✔️eventhubs
️✔️latest
️✔️3.11
️✔️3.9
️✔️feedback
️✔️latest
️✔️3.11
️✔️3.9
️✔️find
️✔️latest
️✔️3.11
️✔️3.9
️✔️hdinsight
️✔️latest
️✔️3.11
️✔️3.9
️✔️identity
️✔️latest
️✔️3.11
️✔️3.9
️✔️iot
️✔️2019-03-01-hybrid
️✔️3.11
️✔️3.9
️✔️2020-09-01-hybrid
️✔️3.11
️✔️3.9
️✔️latest
️✔️3.11
️✔️3.9
️✔️keyvault
️✔️2018-03-01-hybrid
️✔️3.11
️✔️3.9
️✔️2020-09-01-hybrid
️✔️3.11
️✔️3.9
️✔️latest
️✔️3.11
️✔️3.9
️✔️kusto
️✔️latest
️✔️3.11
️✔️3.9
️✔️lab
️✔️latest
️✔️3.11
️✔️3.9
️✔️managedservices
️✔️latest
️✔️3.11
️✔️3.9
️✔️maps
️✔️latest
️✔️3.11
️✔️3.9
️✔️marketplaceordering
️✔️latest
️✔️3.11
️✔️3.9
️✔️monitor
️✔️latest
️✔️3.11
️✔️3.9
️✔️mysql
️✔️latest
️✔️3.11
️✔️3.9
️✔️netappfiles
️✔️latest
️✔️3.11
️✔️3.9
️✔️network
️✔️2018-03-01-hybrid
️✔️3.11
️✔️3.9
️✔️latest
️✔️3.11
️✔️3.9
️✔️policyinsights
️✔️latest
️✔️3.11
️✔️3.9
️✔️privatedns
️✔️latest
️✔️3.11
️✔️3.9
️✔️profile
️✔️latest
️✔️3.11
️✔️3.9
️✔️rdbms
️✔️latest
️✔️3.11
️✔️3.9
️✔️redis
️✔️latest
️✔️3.11
️✔️3.9
️✔️relay
️✔️latest
️✔️3.11
️✔️3.9
️✔️resource
️✔️2018-03-01-hybrid
️✔️3.11
️✔️3.9
️✔️2019-03-01-hybrid
️✔️3.11
️✔️3.9
️✔️latest
️✔️3.11
️✔️3.9
️✔️role
️✔️latest
️✔️3.11
️✔️3.9
️✔️search
️✔️latest
️✔️3.11
️✔️3.9
️✔️security
️✔️latest
️✔️3.11
️✔️3.9
️✔️servicebus
️✔️latest
️✔️3.11
️✔️3.9
️✔️serviceconnector
️✔️latest
️✔️3.11
️✔️3.9
️✔️servicefabric
️✔️latest
️✔️3.11
️✔️3.9
️✔️signalr
️✔️latest
️✔️3.11
️✔️3.9
️✔️sql
️✔️latest
️✔️3.11
️✔️3.9
️✔️sqlvm
️✔️latest
️✔️3.11
️✔️3.9
️✔️storage
️✔️2018-03-01-hybrid
️✔️3.11
️✔️3.9
️✔️2019-03-01-hybrid
️✔️3.11
️✔️3.9
️✔️2020-09-01-hybrid
️✔️3.11
️✔️3.9
️✔️latest
️✔️3.11
️✔️3.9
️✔️synapse
️✔️latest
️✔️3.11
️✔️3.9
️✔️telemetry
️✔️2018-03-01-hybrid
️✔️3.11
️✔️3.9
️✔️2019-03-01-hybrid
️✔️3.11
️✔️3.9
️✔️2020-09-01-hybrid
️✔️3.11
️✔️3.9
️✔️latest
️✔️3.11
️✔️3.9
️✔️util
️✔️latest
️✔️3.11
️✔️3.9
️✔️vm
️✔️2018-03-01-hybrid
️✔️3.11
️✔️3.9
️✔️2019-03-01-hybrid
️✔️3.11
️✔️3.9
️✔️2020-09-01-hybrid
️✔️3.11
️✔️3.9
️✔️latest
️✔️3.11
️✔️3.9
⚠️AzureCLI-BreakingChangeTest
⚠️acr
rule cmd_name rule_message suggest_message ⚠️ 1006 - ParaAdd acr manifest list cmd acr manifest listadded parameterrepo_id⚠️ 1006 - ParaAdd acr manifest list cmd acr manifest listadded parameterverbose⚠️ 1009 - ParaPropRemove acr manifest list cmd acr manifest listupdate parameterrepo_id: removed propertynargs=*⚠️ 1010 - ParaPropUpdate acr manifest list cmd acr manifest listupdate parameterrepo_id: updated propertynamefromrepo_idtoregistry_name⚠️ 1010 - ParaPropUpdate acr manifest list cmd acr manifest listupdate parameterrepo_id: updated propertyoptionsfrom[]to['--registry', '-r']⚠️ 1006 - ParaAdd acr manifest show cmd acr manifest showadded parametermanifest_id⚠️ 1006 - ParaAdd acr manifest show cmd acr manifest showadded parameterverbose⚠️ 1009 - ParaPropRemove acr manifest show cmd acr manifest showupdate parametermanifest_id: removed propertynargs=*⚠️ 1010 - ParaPropUpdate acr manifest show cmd acr manifest showupdate parametermanifest_id: updated propertynamefrommanifest_idtoregistry_name⚠️ 1010 - ParaPropUpdate acr manifest show cmd acr manifest showupdate parametermanifest_id: updated propertyoptionsfrom[]to['--registry', '-r']
ACR