def AssertInstanceGroupManagerExists(igm_ref, project, messages, compute, http, batch_url): """Makes sure the given Instance Group Manager exists. Args: igm_ref: reference to the Instance Group Manager. project: project owning resources. messages: module containing message classes. compute: module representing compute api. http: communication channel. batch_url: batch url. """ request = messages.ComputeInstanceGroupManagersGetRequest(project=project) request.zone = igm_ref.zone request.instanceGroupManager = igm_ref.Name() errors = [] # Run throught the generator to actually make the requests and get potential # errors. igm_details = list( request_helper.MakeRequests( requests=[(compute.instanceGroupManagers, 'Get', request)], http=http, batch_url=batch_url, errors=errors, custom_get_requests=None, )) if errors or len(igm_details) != 1: utils.RaiseException(errors, ResourceNotFoundException, error_message='Could not fetch resource:')
def ProcessEditedResource(self, file_contents, args): """Returns an updated resource that was edited by the user.""" # It's very important that we replace the characters of comment # lines with spaces instead of removing the comment lines # entirely. JSON and YAML deserialization give error messages # containing line, column, and the character offset of where the # error occurred. If the deserialization fails; we want to make # sure those numbers map back to what the user actually had in # front of him or her otherwise the errors will not be very # useful. non_comment_lines = '\n'.join( ' ' * len(line) if line.startswith('#') else line for line in file_contents.splitlines()) modified_record = _DeserializeValue(non_comment_lines, args.format or BaseEdit.DEFAULT_FORMAT) # Normalizes all of the fields that refer to other # resource. (i.e., translates short names to URIs) reference_normalizer = property_selector.PropertySelector( transformations=self.reference_normalizers) modified_record = reference_normalizer.Apply(modified_record) if self.modifiable_record == modified_record: new_object = None else: modified_record['name'] = self.original_record['name'] fingerprint = self.original_record.get('fingerprint') if fingerprint: modified_record['fingerprint'] = fingerprint new_object = encoding.DictToMessage( modified_record, self._resource_spec.message_class) # If existing object is equal to the proposed object or if # there is no new object, then there is no work to be done, so we # return the original object. if not new_object or self.original_object == new_object: return [self.original_object] errors = [] resources = list(request_helper.MakeRequests( requests=[self.GetSetRequest(args, new_object, self.original_object)], http=self.http, batch_url=self.batch_url, errors=errors, custom_get_requests=None)) if errors: utils.RaiseToolException( errors, error_message='Could not update resource:') return resources
def _GetResources(service, project, scopes, scope_name, filter_expr, http, batch_url, errors): """Helper for the Get{Zonal,Regional,Global}Resources functions.""" requests = FormatListRequests(service, project, scopes, scope_name, filter_expr) return request_helper.MakeRequests(requests=requests, http=http, batch_url=batch_url, errors=errors, custom_get_requests=None)
def GetResources(self, args, errors): """Yields regional and/or global resources.""" # This is true if the user provided no flags indicating scope no_scope_flags = args.regions is None and not getattr(args, 'global') requests = [] filter_expr = self.GetFilterExpr(args) max_results = constants.MAX_RESULTS_PER_PAGE project = self.project # If --global is present OR no scope flags are present then we have to fetch # the global resources. if getattr(args, 'global'): requests.append( (self.global_service, 'List', self.global_service.GetRequestType('List')( filter=filter_expr, maxResults=max_results, project=project))) # If --regions is present with no arguments OR no scope flags are present # then we have to do an aggregated list # pylint:disable=g-explicit-bool-comparison if args.regions == [] or no_scope_flags: requests.append( (self.regional_service, 'AggregatedList', self.regional_service.GetRequestType('AggregatedList')( filter=filter_expr, maxResults=max_results, project=project))) # Else if some regions were provided then only list within them elif args.regions: region_names = set( self.CreateGlobalReference(region, resource_type='regions').Name() for region in args.regions) for region_name in sorted(region_names): requests.append( (self.regional_service, 'List', self.regional_service.GetRequestType('List')( filter=filter_expr, maxResults=max_results, region=region_name, project=project))) return request_helper.MakeRequests( requests=requests, http=self.http, batch_url=self.batch_url, errors=errors, custom_get_requests=None)
def _GetResources(self, args): """Retrieves response with named ports.""" group_ref = self.CreateZonalReference(args.name, args.zone) request = self.service.GetRequestType('Get')( instanceGroup=group_ref.Name(), zone=group_ref.zone, project=self.project) errors = [] results = list(request_helper.MakeRequests( requests=[(self.service, 'Get', request)], http=self.http, batch_url=self.batch_url, errors=errors, custom_get_requests=None)) return results, errors
def GetImage(self, image_ref): """Returns the image resource corresponding to the given reference.""" errors = [] res = list(request_helper.MakeRequests( requests=[(self.compute.images, 'Get', self.messages.ComputeImagesGetRequest( image=image_ref.Name(), project=image_ref.project))], http=self.http, batch_url=self.batch_url, errors=errors, custom_get_requests=None)) if errors: utils.RaiseToolException( errors, error_message='Could not fetch image resource:') return res[0]
def GetProject(self): """Returns the project object.""" errors = [] objects = list( request_helper.MakeRequests(requests=[ (self.compute.projects, 'Get', self.messages.ComputeProjectsGetRequest( project=properties.VALUES.core.project.Get( required=True), )) ], http=self.http, batch_url=self.batch_url, errors=errors, custom_get_requests=None)) if errors: utils.RaiseToolException( errors, error_message='Could not fetch project resource:') return objects[0]
def GetInstanceExternalIpAddress(self, instance_ref): """Returns the external ip address for the given instance.""" request = (self.compute.instances, 'Get', self.messages.ComputeInstancesGetRequest( instance=instance_ref.Name(), project=self.project, zone=instance_ref.zone)) errors = [] objects = list( request_helper.MakeRequests(requests=[request], http=self.http, batch_url=self.batch_url, errors=errors, custom_get_requests=None)) if errors: utils.RaiseToolException(errors, error_message='Could not fetch instance:') return GetExternalIPAddress(objects[0])
def GetAddress(self, address_ref): """Returns the address resource corresponding to the given reference.""" errors = [] res = list(request_helper.MakeRequests( requests=[(self.compute.addresses, 'Get', self.messages.ComputeAddressesGetRequest( address=address_ref.Name(), project=address_ref.project, region=address_ref.region))], http=self.http, batch_url=self.batch_url, errors=errors, custom_get_requests=None)) if errors: utils.RaiseToolException( errors, error_message='Could not fetch address resource:') return res[0]
def SetProjectMetadata(self, new_metadata): """Sets the project metadata to the new metadata.""" compute = self.compute errors = [] list( request_helper.MakeRequests(requests=[ (compute.projects, 'SetCommonInstanceMetadata', self.messages.ComputeProjectsSetCommonInstanceMetadataRequest( metadata=new_metadata, project=properties.VALUES.core.project.Get(required=True), )) ], http=self.http, batch_url=self.batch_url, errors=errors, custom_get_requests=None)) if errors: utils.RaiseToolException( errors, error_message='Could not add SSH key to project metadata:')
def LookupUsers(self, users): """Makes a get request for each user in users and returns results.""" requests = [] for user in users: request = (self.clouduseraccounts.users, 'Get', self.clouduseraccounts.MESSAGES_MODULE. ClouduseraccountsUsersGetRequest(project=self.project, user=user)) requests.append(request) errors = [] res = list( request_helper.MakeRequests(requests=requests, http=self.http, batch_url=self.batch_url, errors=errors, custom_get_requests=None)) if errors: utils.RaiseException(errors, UserException, error_message='Could not fetch some users:') return res
def RemovePublicKey(self, user, fingerprint): """Removes a public key from a user.""" request = (self.clouduseraccounts.users, 'RemovePublicKey', self.clouduseraccounts.MESSAGES_MODULE. ClouduseraccountsUsersRemovePublicKeyRequest( project=self.project, fingerprint=fingerprint, user=user)) requests = [request] errors = [] res = list( request_helper.MakeRequests(requests=requests, http=self.http, batch_url=self.batch_url, errors=errors, custom_get_requests=None)) if errors: utils.RaiseException(errors, UserException, error_message='Could not remove public key:') return res
def Run(self, args, request_protobufs=None, service=None): if request_protobufs is None: request_protobufs = self.CreateRequests(args) if service is None: service = self.service requests = [] # If a method is not passed as part of a tuple then use the self.method # default for request in request_protobufs: if isinstance(request, tuple): method = request[0] proto = request[1] else: method = self.method proto = request requests.append((service, method, proto)) errors = [] # We want to run through the generator that MakeRequests returns in order to # actually make the requests, since these requests mutate resources. resources = list(request_helper.MakeRequests( requests=requests, http=self.http, batch_url=self.batch_url, errors=errors, custom_get_requests=self.custom_get_requests)) resources = lister.ProcessResults( resources=resources, field_selector=property_selector.PropertySelector( properties=None, transformations=self.transformations)) if errors: utils.RaiseToolException(errors) return resources
def GetZones(self, resource_refs): """Fetches zone resources.""" errors = [] requests = [] zone_names = set() for resource_ref in resource_refs: if resource_ref.zone not in zone_names: zone_names.add(resource_ref.zone) requests.append((self.compute.zones, 'Get', self.messages.ComputeZonesGetRequest( project=self.project, zone=resource_ref.zone))) res = list( request_helper.MakeRequests(requests=requests, http=self.http, batch_url=self.batch_url, errors=errors, custom_get_requests=None)) if errors: return None else: return res
def GetMatchingImages(self, image, alias, errors): """Yields images from a public image project and the user's project.""" service = self.compute.images requests = [ (service, 'List', self.messages.ComputeImagesListRequest( filter='name eq ^{0}(-.+)*-v.+'.format(alias.name_prefix), maxResults=constants.MAX_RESULTS_PER_PAGE, project=alias.project)), (service, 'List', self.messages.ComputeImagesListRequest( filter='name eq ^{0}$'.format(image), maxResults=constants.MAX_RESULTS_PER_PAGE, project=self.project)), ] return request_helper.MakeRequests( requests=requests, http=self.http, batch_url=self.batch_url, errors=errors, custom_get_requests=None)
def _GetGroupFingerprint(self, name, zone): """Gets fingerprint of given instance group.""" get_request = self.messages.ComputeInstanceGroupsGetRequest( instanceGroup=name, zone=zone, project=self.project) errors = [] resources = list(request_helper.MakeRequests( requests=[( self.compute.instanceGroups, 'Get', get_request)], http=self.http, batch_url=self.batch_url, errors=errors, custom_get_requests=None)) if errors: utils.RaiseException( errors, FingerprintFetchException, error_message='Could not set named ports for resource:') return resources[0].fingerprint
def Run(self, args): self.ref = self.CreateReference(args) get_request = self.GetGetRequest(args) errors = [] objects = list(request_helper.MakeRequests( requests=[get_request], http=self.http, batch_url=self.batch_url, errors=errors, custom_get_requests=None)) if errors: utils.RaiseToolException( errors, error_message='Could not fetch resource:') self.original_object = objects[0] self.original_record = encoding.MessageToDict(self.original_object) # Selects only the fields that can be modified. field_selector = property_selector.PropertySelector( properties=self._resource_spec.editables) self.modifiable_record = field_selector.Apply(self.original_record) buf = cStringIO.StringIO() for line in _HELP.splitlines(): buf.write('#') if line: buf.write(' ') buf.write(line) buf.write('\n') buf.write('\n') buf.write(_SerializeDict(self.modifiable_record, args.format or BaseEdit.DEFAULT_FORMAT)) buf.write('\n') example = _SerializeDict( encoding.MessageToDict(self.example_resource), args.format or BaseEdit.DEFAULT_FORMAT) _WriteResourceInCommentBlock(example, 'Example resource:', buf) buf.write('#\n') original = _SerializeDict(self.original_record, args.format or BaseEdit.DEFAULT_FORMAT) _WriteResourceInCommentBlock(original, 'Original resource:', buf) file_contents = buf.getvalue() while True: try: file_contents = edit.OnlineEdit(file_contents) except edit.NoSaveException: raise calliope_exceptions.ToolException('Edit aborted by user.') try: resources = self.ProcessEditedResource(file_contents, args) break except (ValueError, yaml.error.YAMLError, protorpc.messages.ValidationError, calliope_exceptions.ToolException) as e: if isinstance(e, ValueError): message = e.message else: message = str(e) if isinstance(e, calliope_exceptions.ToolException): problem_type = 'applying' else: problem_type = 'parsing' message = ('There was a problem {0} your changes: {1}' .format(problem_type, message)) if not console_io.PromptContinue( message=message, prompt_string='Would you like to edit the resource again?'): raise calliope_exceptions.ToolException('Edit aborted by user.') resources = lister.ProcessResults( resources=resources, field_selector=property_selector.PropertySelector( properties=None, transformations=self.transformations)) for resource in resources: yield resource