def RunCommand(self): """Command entry point for the acl command.""" action_subcommand = self.args.pop(0) self.ParseSubOpts(check_args=True) # Commands with both suboptions and subcommands need to reparse for # suboptions, so we log again. LogCommandParams(sub_opts=self.sub_opts) self.def_acl = False if action_subcommand == 'get': LogCommandParams(subcommands=[action_subcommand]) policy = self._GetIam(self.args[0]) bindings = [ json.loads(protojson.encode_message(b)) for b in policy.bindings ] print json.dumps(bindings, sort_keys=True, indent=2) elif action_subcommand == 'set': LogCommandParams(subcommands=[action_subcommand]) self._SetIam() elif action_subcommand == 'ch': LogCommandParams(subcommands=[action_subcommand]) self._PatchIam() else: raise CommandException( 'Invalid subcommand "%s" for the %s command.\n' 'See "gsutil help iam".' % (action_subcommand, self.command_name)) return 0
def _GetIam(self, thread_state=None): """Gets IAM policy for single bucket or object.""" pattern = self.args[0] matches = PluralityCheckableIterator( self.WildcardIterator(pattern).IterAll( bucket_listing_fields=['name'])) if matches.IsEmpty(): raise CommandException('%s matched no URLs' % pattern) if matches.HasPlurality(): raise CommandException( '%s matched more than one URL, which is not allowed by the %s ' 'command' % (pattern, self.command_name)) storage_url = StorageUrlFromString(list(matches)[0].url_string) policy = self.GetIamHelper(storage_url, thread_state=thread_state) policy_json = json.loads(protojson.encode_message(policy)) policy_str = json.dumps( policy_json, sort_keys=True, separators=(',', ': '), indent=2, ) print(policy_str)
def testUpdateFromFile(self): wp_in = self.msg.WorkerPool() wp_in.workerConfig = self.msg.WorkerConfig() wp_in.name = 'fake_name' update_mask = cloudbuild_util.MessageToFieldPaths(wp_in) wp_out = copy.deepcopy(wp_in) wp_out.createTime = self.frozen_time_str wp_out.state = self.msg.WorkerPool.StateValueValuesEnum.RUNNING self.mocked_cloudbuild_v1alpha2.projects_workerPools.Patch.Expect( self.msg.CloudbuildProjectsWorkerPoolsPatchRequest( name=u'projects/{}/workerPools/{}'.format( self.project_id, wp_in.name), workerPool=wp_in, updateMask=','.join(update_mask)), response=wp_out) wp_path = self.Touch('.', 'workerpool.yaml', contents=protojson.encode_message(wp_in)) self._Run([ 'alpha', 'builds', 'worker-pools', 'update', '--config-from-file', wp_path ]) self.AssertOutputContains("""\ NAME CREATE_TIME STATE fake_name {} RUNNING """.format(self.frozen_time_str), normalize_space=True)
def RunCommand(self): """Command entry point for the acl command.""" action_subcommand = self.args.pop(0) self.ParseSubOpts(check_args=True) # Commands with both suboptions and subcommands need to reparse for # suboptions, so we log again. LogCommandParams(sub_opts=self.sub_opts) self.def_acl = False if action_subcommand == 'get': LogCommandParams(subcommands=[action_subcommand]) policy = self._GetIam(self.args[0]) bindings = [ json.loads(protojson.encode_message(b)) for b in policy.bindings] print json.dumps(bindings, sort_keys=True, indent=2) elif action_subcommand == 'set': LogCommandParams(subcommands=[action_subcommand]) self._SetIam() elif action_subcommand == 'ch': LogCommandParams(subcommands=[action_subcommand]) self._PatchIam() else: raise CommandException( 'Invalid subcommand "%s" for the %s command.\n' 'See "gsutil help iam".' % (action_subcommand, self.command_name)) return 0
def testCreateFromFile(self): wp_in = self.msg.WorkerPool() wp_in.workerConfig = self.msg.WorkerConfig() wp_in.name = 'fake_name' wp_in.networkConfig = self.msg.NetworkConfig() wp_in.networkConfig.peeredNetwork = 'fake_network' wp_out = copy.deepcopy(wp_in) wp_out.createTime = self.frozen_time_str wp_out.state = self.msg.WorkerPool.StateValueValuesEnum.RUNNING self.mocked_cloudbuild_client.projects_locations_workerPools.Create.Expect( self.msg.CloudbuildProjectsLocationsWorkerPoolsCreateRequest( parent='projects/{}/locations/{}'.format( self.project_id, self.workerpool_location), workerPool=wp_in, workerPoolId='fake_name'), response=self.msg.Operation(response=encoding.JsonToMessage( self.msg.Operation.ResponseValue, encoding.MessageToJson( wp_out)))) wp_path = self.Touch('.', 'workerpool.yaml', contents=protojson.encode_message(wp_in)) self._Run([ 'builds', 'worker-pools', 'create', '--region', self.workerpool_location, '--config-from-file', wp_path ]) self.AssertOutputContains("""\ NAME CREATE_TIME STATE fake_name {} RUNNING """.format(self.frozen_time_str), normalize_space=True)
def testEnumerationNegativeTestWithEmptyString(self): """The enum value is an empty string.""" # The message should successfully decode. message = protojson.decode_message(MyMessage, '{"an_enum": ""}') expected_message = MyMessage() self.assertEquals(expected_message, message) # The roundtrip should result in equivalent encoded message. self.assertEquals('{"an_enum": ""}', protojson.encode_message(message))
def testNumericEnumerationNegativeTest(self): """Test with an invalid number for the enum value.""" # The message should successfully decode. message = protojson.decode_message(MyMessage, '{"an_enum": 89}') expected_message = MyMessage() self.assertEquals(expected_message, message) # The roundtrip should result in equivalent encoded # message. self.assertEquals('{"an_enum": 89}', protojson.encode_message(message))
def testAlphaEnumerationNegativeTest(self): """The alpha enum value is invalid.""" # The message should successfully decode. message = protojson.decode_message(MyMessage, '{"an_enum": "IAMINVALID"}') expected_message = MyMessage() self.assertEquals(expected_message, message) # The roundtrip should result in equivalent encoded message. self.assertEquals('{"an_enum": "IAMINVALID"}', protojson.encode_message(message))
def testCreateTriggerDefaultBroker(self): """Test the create trigger api call.""" source_obj = self._MakeSource( **{'metadata.name': 'source-for-my-trigger'}) trigger_obj = self._MakeTrigger( **{ 'metadata.name': 'my-trigger', 'metadata.annotations.additionalProperties': [{ 'key': trigger.DEPENDENCY_ANNOTATION_FIELD, 'value': protojson.encode_message(source_obj.AsObjectReference()) }, { 'key': trigger._INJECTION_ANNOTATION_FIELD, 'value': 'enabled' }], 'spec.subscriber.ref': { 'name': 'my-service', 'kind': 'Service', 'apiVersion': 'serving.knative.dev/v1alpha1' }, 'spec.filter.attributes.additionalProperties': [{ 'key': trigger.SOURCE_TRIGGER_LINK_FIELD, 'value': 'link0' }, { 'key': trigger.EVENT_TYPE_FIELD, 'value': 'google.com.my.event.type' }], 'spec.broker': 'default', }) expected_request = ( self.messages.AnthoseventsNamespacesTriggersCreateRequest( trigger=trigger_obj.Message(), parent=self._NamespaceRef(project='default').RelativeName())) self.mock_client.namespaces_triggers.Create.Expect( expected_request, trigger_obj.Message()) self._MakeEventType('CloudPubSubSource', 'cloudpubsubsources') created_trigger = self.anthosevents_client.CreateTrigger( self._TriggerRef('my-trigger', 'default'), source_obj, self.event_type.type, collections.OrderedDict(), 'my-service', 'default', ) self.assertEqual(created_trigger, trigger_obj)
def testEncodeDateTime(self): for datetime_string, datetime_vals in ( ('2012-09-30T15:31:50.262000', (2012, 9, 30, 15, 31, 50, 262000)), ('2012-09-30T15:31:50.262123', (2012, 9, 30, 15, 31, 50, 262123)), ('2012-09-30T15:31:50', (2012, 9, 30, 15, 31, 50, 0))): decoded_message = protojson.encode_message( MyMessage(a_datetime=datetime.datetime(*datetime_vals))) expected_decoding = '{"a_datetime": "%s"}' % datetime_string self.CompareEncoded(expected_decoding, decoded_message)
def SerializeBindingsTuple(bindings_tuple): """Serializes the BindingsValueListEntry instances in a BindingsTuple. This is necessary when passing instances of BindingsTuple through Command.Apply, as apitools_messages classes are not by default pickleable. Args: bindings_tuple: A BindingsTuple instance to be serialized. Returns: A serialized BindingsTuple object. """ return (bindings_tuple.is_grant, [protojson.encode_message(t) for t in bindings_tuple.bindings])
def _GetIam(self, thread_state=None): """Gets IAM policy for single bucket or object.""" pattern = self.args[0] matches = PluralityCheckableIterator(self.WildcardIterator(pattern).IterAll(bucket_listing_fields=["name"])) if matches.IsEmpty(): raise CommandException("%s matched no URLs" % pattern) if matches.HasPlurality(): raise CommandException( "%s matched more than one URL, which is not allowed by the %s " "command" % (pattern, self.command_name) ) storage_url = StorageUrlFromString(list(matches)[0].url_string) policy = self.GetIamHelper(storage_url, thread_state=thread_state) print json.dumps(json.loads(protojson.encode_message(policy)), sort_keys=True, indent=2)
def testUpdateFromFileWithFlags(self): wp_in = self.msg.WorkerPool() wp_in.workerConfig = self.msg.WorkerConfig() wp_in.name = 'fake_name' wp_out = copy.deepcopy(wp_in) wp_out.createTime = self.frozen_time_str wp_out.state = self.msg.WorkerPool.StateValueValuesEnum.RUNNING wp_path = self.Touch('.', 'workerpool.yaml', contents=protojson.encode_message(wp_in)) with self.assertRaises(MockArgumentError): self._Run([ 'alpha', 'builds', 'worker-pools', 'update', wp_in.name, '--config-from-file', wp_path ])
def testCreateTriggerFailsIfAlreadyExists(self): """Test the create trigger api call.""" source_obj = self._MakeSource(**{'metadata.name': 'source-for-my-trigger'}) trigger_obj = self._MakeTrigger( **{ 'metadata.name': 'my-trigger', 'metadata.annotations.additionalProperties': [{ 'key': trigger.DEPENDENCY_ANNOTATION_FIELD, 'value': protojson.encode_message(source_obj.AsObjectReference()) }], 'spec.subscriber.ref': { 'name': 'my-service', 'kind': 'Service', 'apiVersion': 'serving.knative.dev/v1alpha1' }, 'spec.filter.attributes.additionalProperties': [{ 'key': trigger.SOURCE_TRIGGER_LINK_FIELD, 'value': 'link0' }, { 'key': trigger.EVENT_TYPE_FIELD, 'value': 'google.com.my.event.type' }], 'spec.broker': 'my-broker', }) expected_request = ( self.messages.RunNamespacesTriggersCreateRequest( trigger=trigger_obj.Message(), parent=self._NamespaceRef(project='default').RelativeName())) self.mock_client.namespaces_triggers.Create.Expect( expected_request, exception=api_exceptions.HttpConflictError(None, None, None)) self._MakeEventType('CloudPubSubSource', 'cloudpubsubsources') with self.assertRaises(exceptions.TriggerCreationError): self.eventflow_client.CreateTrigger( self._TriggerRef('my-trigger', 'default'), source_obj, self.event_type.type, collections.OrderedDict(), 'my-service', 'my-broker', )
def _SetIam(self): """Set IAM policy for given wildcards on the command line.""" self.continue_on_error = False self.recursion_requested = False self.all_versions = False force_etag = False etag = '' if self.sub_opts: for o, arg in self.sub_opts: if o in ['-r', '-R']: self.recursion_requested = True elif o == '-f': self.continue_on_error = True elif o == '-a': self.all_versions = True elif o == '-e': etag = str(arg) force_etag = True else: self.RaiseInvalidArgumentException() file_url = self.args[0] patterns = self.args[1:] # Load the IAM policy file and raise error if the file is invalid JSON or # does not exist. try: with open(file_url, 'r') as fp: policy = json.loads(fp.read()) except IOError: raise ArgumentException( 'Specified IAM policy file "%s" does not exist.' % file_url) except ValueError as e: self.logger.debug('Invalid IAM policy file, ValueError:\n', e) raise ArgumentException('Invalid IAM policy file "%s".' % file_url) bindings = policy.get('bindings', []) if not force_etag: etag = policy.get('etag', '') policy_json = json.dumps({'bindings': bindings, 'etag': etag}) try: policy = protojson.decode_message(apitools_messages.Policy, policy_json) except DecodeError: raise ArgumentException( 'Invalid IAM policy file "%s" or etag "%s".' % (file_url, etag)) self.everything_set_okay = True # This list of wildcard strings will be handled by NameExpansionIterator. threaded_wildcards = [] for pattern in patterns: surl = StorageUrlFromString(pattern) if surl.IsBucket(): if self.recursion_requested: surl.object_name = '*' threaded_wildcards.append(surl.url_string) else: self.SetIamHelper(surl, policy) else: threaded_wildcards.append(surl.url_string) # N.B.: If threaded_wildcards contains a non-existent bucket # (e.g. ["gs://non-existent", "gs://existent"]), NameExpansionIterator # will raise an exception in iter.next. This halts all iteration, even # when -f is set. This behavior is also evident in acl set. This behavior # also appears for any exception that will be raised when iterating over # wildcard expansions (access denied if bucket cannot be listed, etc.). if threaded_wildcards: name_expansion_iterator = NameExpansionIterator( self.command_name, self.debug, self.logger, self.gsutil_api, threaded_wildcards, self.recursion_requested, all_versions=self.all_versions, continue_on_error=self.continue_on_error or self.parallel_operations, bucket_listing_fields=['name']) seek_ahead_iterator = SeekAheadNameExpansionIterator( self.command_name, self.debug, self.GetSeekAheadGsutilApi(), threaded_wildcards, self.recursion_requested, all_versions=self.all_versions) policy_it = itertools.repeat(protojson.encode_message(policy)) self.Apply(_SetIamWrapper, itertools.izip(policy_it, name_expansion_iterator), _SetIamExceptionHandler, fail_on_error=not self.continue_on_error, seek_ahead_iterator=seek_ahead_iterator) self.everything_set_okay &= not GetFailureCount() > 0 # TODO: Add an error counter for files and objects. if not self.everything_set_okay: raise CommandException('Some IAM policies could not be set.')
def testEncodeCustom(self): decoded_message = protojson.encode_message(MyMessage(a_custom=1)) self.CompareEncoded('{"a_custom": 1}', decoded_message)
def _SetIam(self): """Set IAM policy for given wildcards on the command line.""" self.continue_on_error = False self.recursion_requested = False self.all_versions = False if self.sub_opts: for o, unused_a in self.sub_opts: if o in ['-r', '-R']: self.recursion_requested = True elif o == '-f': self.continue_on_error = True elif o == '-a': self.all_versions = True else: self.RaiseInvalidArgumentException() file_url = self.args[0] patterns = self.args[1:] # Load the IAM policy file and raise error if the file is invalid JSON or # does not exist. try: with open(file_url, 'r') as fp: bindings = json.loads(fp.read()) except (IOError, ValueError): raise ArgumentException('Invalid IAM policy file "%s".' % file_url) policy = apitools_messages.Policy(bindings=bindings) self.everything_set_okay = True # This list of wildcard strings will be handled by NameExpansionIterator. threaded_wildcards = [] for pattern in patterns: surl = StorageUrlFromString(pattern) if surl.IsBucket(): if self.recursion_requested: surl.object_name = '*' threaded_wildcards.append(surl.url_string) else: self.SetIamHelper(surl, policy) else: threaded_wildcards.append(surl.url_string) # N.B.: If threaded_wildcards contains a non-existent bucket # (e.g. ["gs://non-existent", "gs://existent"]), NameExpansionIterator # will raise an exception in iter.next. This halts all iteration, even # when -f is set. This behavior is also evident in acl set. This behavior # also appears for any exception that will be raised when iterating over # wildcard expansions (access denied if bucket cannot be listed, etc.). if threaded_wildcards: name_expansion_iterator = NameExpansionIterator( self.command_name, self.debug, self.logger, self.gsutil_api, threaded_wildcards, self.recursion_requested, all_versions=self.all_versions, continue_on_error=self.continue_on_error or self.parallel_operations, bucket_listing_fields=['name']) seek_ahead_iterator = SeekAheadNameExpansionIterator( self.command_name, self.debug, self.GetSeekAheadGsutilApi(), threaded_wildcards, self.recursion_requested, all_versions=self.all_versions) # We cannot curry policy along due to a Python2.6 bug; see comments in # IamCommand._PatchIam for more information. policy_it = itertools.repeat(protojson.encode_message(policy)) self.Apply( _SetIamWrapper, itertools.izip( policy_it, name_expansion_iterator), _SetIamExceptionHandler, fail_on_error=not self.continue_on_error, seek_ahead_iterator=seek_ahead_iterator) self.everything_set_okay &= not GetFailureCount() > 0 # TODO: Add an error counter for files and objects. if not self.everything_set_okay: raise CommandException('Some IAM policies could not be set.')
def dependency(self, k8s_obj): """Set the knative dependency annotation by passing a k8s_object.KubernetesObject.""" self.annotations[ DEPENDENCY_ANNOTATION_FIELD] = protojson.encode_message( k8s_obj.AsObjectReference())