def ImageDigestForContainerImage(name, tag): """Given a container image and tag, returns the digest for that image version. Args: name: the gcr.io registry name plus the image name tag: the image tag Returns: The digest of the image, or None if there is no such image. Raises: googlecloudsdk.core.UnsupportedRegistryError: If the path is valid, but belongs to an unsupported registry. i_util.InvalidImageNameError: If the image name is invalid. i_util.TokenRefreshError: If there is an error refreshing credentials needed to access the GCR repo. i_util.UserRecoverableV2Error: If a user-recoverable error occurs accessing the GCR repo. """ def _TaggedImage(): """Display the fully-qualified name.""" return '{}:{}'.format(name, tag) name = i_util.ValidateRepositoryPath(name) with i_util.WrapExpectedDockerlessErrors(name): with docker_image.FromRegistry( basic_creds=i_util.CredentialProvider(), name=docker_name.Tag(_TaggedImage()), transport=http.Http()) as r: return r.digest()
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. Returns: Some value that we want to have printed later. """ repository_arg = args.repository if not repository_arg: repository_arg = 'gcr.io/{0}'.format( properties.VALUES.core.project.Get(required=True)) # Throws if invalid. repository = util.ValidateRepositoryPath(repository_arg) def _DisplayName(c): """Display the fully-qualified name.""" return '{0}/{1}'.format(repository, c) http_obj = http.Http() with docker_image.FromRegistry(basic_creds=util.CredentialProvider(), name=repository, transport=http_obj) as r: images = [{'name': _DisplayName(c)} for c in r.children()] return images
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 testValid(self): # No exceptions should be thrown. for image in [ 'gcr.io/foo/bar', 'us.gcr.io/foo/bar/baz', ]: i = util.ValidateRepositoryPath(image) self.assertEqual(str(i), image)
def testSupportedRegistries(self): # No exceptions should be thrown. repository = 'myrepository/myimage' for registry in constants.ALL_SUPPORTED_REGISTRIES: r = util.ValidateRepositoryPath('{0}/{1}'.format( registry, repository)) self.assertEqual(r.registry, registry) self.assertEqual(r.repository, 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. Returns: Some value that we want to have printed later. Raises: exceptions.Error: If the repository could not be found, or access was denied. docker_http.V2DiagnosticException: Any other error occurred while accessing GCR. """ repository_arg = args.repository self._epilog = None if not repository_arg: project_id = properties.VALUES.core.project.Get(required=True) # Handle domain-scoped projects... project_id = project_id.replace(':', '/', 1) repository_arg = 'gcr.io/{0}'.format(project_id) self._epilog = 'Only listing images in {0}. '.format( repository_arg) self._epilog += 'Use --repository to list images in other repositories.' # Throws if invalid. repository = util.ValidateRepositoryPath(repository_arg) def _DisplayName(c): """Display the fully-qualified name.""" return '{0}/{1}'.format(repository, c) http_obj = http.Http() try: with docker_image.FromRegistry( basic_creds=util.CredentialProvider(), name=repository, transport=http_obj) as r: try: images = [{'name': _DisplayName(c)} for c in r.children()] return images except docker_http.V2DiagnosticException as err: if err.status in [httplib.UNAUTHORIZED, httplib.FORBIDDEN]: raise exceptions.Error( 'Access denied: {0}'.format(repository)) elif err.status == httplib.NOT_FOUND: raise exceptions.Error( 'Not found: {0}'.format(repository)) else: raise except docker_http.BadStateException as e: raise exceptions.Error(e)
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 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 testInvalid(self): for image in [ 'gcr.io/foo/ba$r', 'gcr.io/foo/bar' + 'a' * 500, 'gcr.io/foo/' ]: with self.assertRaises(util.InvalidImageNameError): util.ValidateRepositoryPath(image)
def testFullyQualified(self): for image in ['gcr.io/foo/bar:tag', 'gcr.io/foo/bar@digest']: with self.assertRaises(util.InvalidImageNameError): util.ValidateRepositoryPath(image)
def testUnsupportedRegistry(self): with self.assertRaises(docker.UnsupportedRegistryError): util.ValidateRepositoryPath('myhub.com/myrepository/myimage')