def Run(self, args): """This is what gets called when the user runs this command. Args: args: an argparse namespace. All the arguments that were provided to this command invocation. Raises: InvalidImageNameError: If the user specified an invalid image name. Returns: Some value that we want to have printed later. """ repository = util.ValidateRepositoryPath(args.image) http_obj = http.Http() with docker_image.FromRegistry( basic_creds=util.CredentialProvider(), name=repository, transport=http_obj) as image: try: return util.TransformManifests( image.manifests(), repository, show_occurrences=args.show_occurrences, occurrence_filter=args.occurrence_filter) except docker_http.V2DiagnosticException as err: raise util.GcloudifyRecoverableV2Errors(err, { 403: 'Access denied: {0}'.format(repository), 404: 'Not found: {0}'.format(repository) })
def Run(self, args): """This is what gets called when the user runs this command. Args: args: an argparse namespace. All the arguments that were provided to this command invocation. Raises: ArgumentError: If the user provided the flag --show-occurrences-from but --show-occurrences=False. InvalidImageNameError: If the user specified an invalid image name. Returns: Some value that we want to have printed later. """ # Verify that --show-occurrences-from is set iff --show-occurrences=True. if args.IsSpecified( 'show_occurrences_from') and not args.show_occurrences: raise ArgumentError( '--show-occurrences-from may only be set if --show-occurrences=True' ) repository = util.ValidateRepositoryPath(args.image_name) http_obj = http.Http() with docker_image.FromRegistry(basic_creds=util.CredentialProvider(), name=repository, transport=http_obj) as image: try: manifests = image.manifests() # Only consider the top _DEFAULT_SHOW_OCCURRENCES_FROM images # to reduce computation time. most_recent_resource_urls = None if args.show_occurrences_from: # This block is skipped when the user provided # --show-occurrences-from=unlimited on the CLI. most_recent_resource_urls = [ 'https://%s@%s' % (args.image_name, k) for k in heapq.nlargest( args.show_occurrences_from, manifests, key=lambda k: manifests[k]['timeCreatedMs']) ] return util.TransformManifests( manifests, repository, show_occurrences=args.show_occurrences, occurrence_filter=args.occurrence_filter, resource_urls=most_recent_resource_urls) except docker_http.V2DiagnosticException as err: raise util.GcloudifyRecoverableV2Errors( err, { 403: 'Access denied: {0}'.format(repository), 404: 'Not found: {0}'.format(repository) })
def Run(self, args): """This is what gets called when the user runs this command. Args: args: an argparse namespace. All the arguments that were provided to this command invocation. Raises: ArgumentError: If the user provided the flag --show-occurrences-from but --show-occurrences=False. InvalidImageNameError: If the user specified an invalid image name. Returns: Some value that we want to have printed later. """ # Verify that --show-occurrences-from is set iff --show-occurrences=True. if args.IsSpecified( 'show_occurrences_from') and not args.show_occurrences: raise ArgumentError( '--show-occurrences-from may only be set if --show-occurrences=True' ) repository = util.ValidateRepositoryPath(args.image_name) http_obj = http.Http() with util.WrapExpectedDockerlessErrors(repository): with docker_image.FromRegistry( basic_creds=util.CredentialProvider(), name=repository, transport=http_obj) as image: manifests = image.manifests() # Only consider the top _DEFAULT_SHOW_OCCURRENCES_FROM images # to reduce computation time. most_recent_resource_urls = None occ_filter = filter_util.ContainerAnalysisFilter() occ_filter.WithCustomFilter(args.occurrence_filter) occ_filter.WithResourcePrefix('https://{}'.format(repository)) if args.show_occurrences_from: # This block is skipped when the user provided # --show-occurrences-from=unlimited on the CLI. most_recent_resource_urls = [ 'https://%s@%s' % (args.image_name, k) for k in heapq.nlargest( args.show_occurrences_from, manifests, key=lambda k: manifests[k]['timeCreatedMs']) ] occ_filter.WithResources(most_recent_resource_urls) return util.TransformManifests( manifests, repository, show_occurrences=args.show_occurrences, occurrence_filter=occ_filter)
def testNoTags(self): response = { 'digest1': { 'timeCreatedMs': 123e6 }, 'digest2': { 'timeCreatedMs': 234e6 } } transformed = util.TransformManifests(response, self._repository) self.assertEqual(len(response), len(transformed)) # Make sure each digest is in the transformed response. digests = set([t['digest'] for t in transformed]) for digest in response: self.assertIn(digest, digests) for t in transformed: self.assertEqual(t['tags'], [])
def Run(self, args): """This is what gets called when the user runs this command. Args: args: an argparse namespace. All the arguments that were provided to this command invocation. Raises: InvalidImageNameError: If the user specified an invalid image name. Returns: Some value that we want to have printed later. """ repository = util.ValidateRepositoryPath(args.image_name) http_obj = http.Http() with util.WrapExpectedDockerlessErrors(repository): with docker_image.FromRegistry( basic_creds=util.CredentialProvider(), name=repository, transport=http_obj) as image: manifests = image.manifests() return util.TransformManifests(manifests, repository)
def testTagsNoOccurrences(self): response = { 'digest1': { 'timeCreatedMs': 123e6, 'tag': ['a', 'b', 'c'] }, 'digest2': { 'timeCreatedMs': 234e6, 'tag': ['d', 'e', 'f'] } } self.fetch_occurrence_mock.return_value = {} transformed = util.TransformManifests(response, self._repository) self.assertEqual(len(response), len(transformed)) # Make sure each digest is in the transformed response. digests = set([t['digest'] for t in transformed]) for digest in response: self.assertIn(digest, digests) for t in transformed: self.assertEqual(t['tags'], response[t['digest']]['tag'])
def testTagsOneWithOccurrence(self): response = { 'digest1': { 'timeCreatedMs': 123e6, 'tag': ['a', 'b', 'c'] }, 'digest2': { 'timeCreatedMs': 234e6, 'tag': ['d', 'e', 'f'] } } messages = apis.GetMessagesModule('containeranalysis', 'v1alpha1') pvo = messages.Occurrence( kind=messages.Occurrence.KindValueValuesEnum.PACKAGE_VULNERABILITY) bdo = messages.Occurrence( kind=messages.Occurrence.KindValueValuesEnum.BUILD_DETAILS) self.fetch_occurrence_mock.return_value = { 'https://{repo}@digest1'.format(repo=str(self._repository)): [pvo, bdo], } transformed = util.TransformManifests(response, self._repository, show_occurrences=True) self.assertEqual(len(response), len(transformed)) # Make sure each digest is in the transformed response. digests = set([t['digest'] for t in transformed]) for digest in response: self.assertIn(digest, digests) for t in transformed: if t['digest'] != 'digest1': continue self.assertEqual([pvo], t[pvo.kind]) self.assertEqual([bdo], t[bdo.kind]) for t in transformed: self.assertEqual(t['tags'], response[t['digest']]['tag'])