def _CheckArgs(self, args): # This function should raise ArgumentParsingError, but: # 1. ArgumentParsingError requires the argument returned from add_argument) # and Args() method is static. So there is no elegant way to save it # to be reused here. # 2. _CheckArgs() is invoked from Run() and ArgumentParsingError thrown # from Run are not caught. if args.source_url is None: if args.source_revision is not None: raise exceptions.FunctionsError( 'argument --source-revision: can be given only if argument ' '--source-url is provided') if args.source_branch is not None: raise exceptions.FunctionsError( 'argument --source-branch: can be given only if argument ' '--source-url is provided') if args.source_tag is not None: raise exceptions.FunctionsError( 'argument --source-tag: can be given only if argument ' '--source-url is provided') if args.source is None: args.source = '.' if args.bucket is None: raise exceptions.FunctionsError( 'argument --bucket: required when the function is deployed from' ' a local directory (when argument --source-url is not provided)') util.ValidateDirectoryExistsOrRaiseFunctionError(args.source) else: if args.source is None: raise exceptions.FunctionsError( 'argument --source: required when argument --source-url is ' 'provided')
def _ValidateTriggerArgs(args): """Check if args related function triggers are valid. Args: args: parsed command line arguments. Raises: FunctionsError. """ # checked that Event Type is valid trigger_event = args.trigger_event trigger_resource = args.trigger_resource if trigger_event: trigger_provider = util.input_trigger_provider_registry.ProviderForEvent( trigger_event).label if not trigger_provider: raise exceptions.FunctionsError( 'Unsupported trigger_event {}'.format(trigger_event)) resource_type = util.input_trigger_provider_registry.Event( trigger_provider, trigger_event).resource_type if trigger_resource is None and resource_type != util.Resources.PROJECT: raise exceptions.FunctionsError( 'You must provide --trigger-resource when using ' '--trigger-event={}'.format(trigger_event)) if args.IsSpecified('retry') and args.IsSpecified('trigger_http'): raise calliope_exceptions.ConflictingArgumentsException( '--trigger-http', '--retry')
def ValidateTriggerArgs(trigger_event, trigger_resource, retry_specified, trigger_http_specified): """Check if args related function triggers are valid. Args: trigger_event: The trigger event trigger_resource: The trigger resource retry_specified: Whether or not `--retry` was specified trigger_http_specified: Whether or not `--trigger-http` was specified Raises: FunctionsError. """ # Check that Event Type is valid if trigger_event: trigger_provider = (triggers.INPUT_TRIGGER_PROVIDER_REGISTRY. ProviderForEvent(trigger_event).label) if not trigger_provider: raise exceptions.FunctionsError( 'Unsupported trigger_event {}'.format(trigger_event)) resource_type = triggers.INPUT_TRIGGER_PROVIDER_REGISTRY.Event( trigger_provider, trigger_event).resource_type if trigger_resource is None and resource_type != triggers.Resources.PROJECT: raise exceptions.FunctionsError( 'You must provide --trigger-resource when using ' '--trigger-event={}'.format(trigger_event)) if retry_specified and trigger_http_specified: raise calliope_exceptions.ConflictingArgumentsException( '--trigger-http', '--retry')
def _ValidateSourceArgs(args): """Check if args related to source code to deploy are valid. Args: args: parsed command line arguments. Raises: FunctionsError. """ if args.source_url is None: if args.source_revision is not None: raise exceptions.FunctionsError( 'argument --source-revision: can be given only if argument ' '--source-url is provided') if args.source_branch is not None: raise exceptions.FunctionsError( 'argument --source-branch: can be given only if argument ' '--source-url is provided') if args.source_tag is not None: raise exceptions.FunctionsError( 'argument --source-tag: can be given only if argument ' '--source-url is provided') else: if args.source_path is None: raise exceptions.FunctionsError( 'argument --source-path: required when argument --source-url is ' 'provided')
def _ValidateSourceArgs(args): """Check if args related to source code to deploy are valid. Args: args: parsed command line arguments. Raises: FunctionsError. """ if args.source_url is None: if args.source_revision is not None: raise exceptions.FunctionsError( 'argument --source-revision: can be given only if argument ' '--source-url is provided') if args.source_branch is not None: raise exceptions.FunctionsError( 'argument --source-branch: can be given only if argument ' '--source-url is provided') if args.source_tag is not None: raise exceptions.FunctionsError( 'argument --source-tag: can be given only if argument ' '--source-url is provided') if args.stage_bucket is None: raise exceptions.FunctionsError( 'argument --stage-bucket: required when the function is deployed ' 'from a local directory (when argument --source-url is not ' 'provided)') util.ValidateDirectoryExistsOrRaiseFunctionError(GetLocalPath(args)) else: if args.source_path is None: raise exceptions.FunctionsError( 'argument --source-path: required when argument --source-url is ' 'provided')
def _PrepareSourcesOnGcs(self, args): remote_zip_file = self._GenerateRemoteZipFileName(args) if args.bucket is None: # double check raise exceptions.FunctionsError('Missing bucket parameter' ' for function sources.') gcs_url = storage.BuildRemoteDestination(args.bucket, remote_zip_file) with file_utils.TemporaryDirectory() as tmp_dir: zip_file = self._CreateZipFile(tmp_dir, args) if self._UploadFile(zip_file, gcs_url) != 0: raise exceptions.FunctionsError('Function upload failed.') return gcs_url
def CreateSourcesZipFile(zip_dir, source_path, include_ignored_files): """Prepare zip file with source of the function to upload. Args: zip_dir: str, directory in which zip file will be located. Name of the file will be `fun.zip`. source_path: str, directory containing the sources to be zipped. include_ignored_files: bool, indicates whether `node_modules` directory and its content will be included in the zip. Returns: Path to the zip file (str). Raises: FunctionsError """ util.ValidateDirectoryExistsOrRaiseFunctionError(source_path) _ValidateUnpackedSourceSize(source_path, include_ignored_files) zip_file_name = os.path.join(zip_dir, 'fun.zip') try: if include_ignored_files: log.info( 'Not including node_modules in deployed code. To include ' 'node_modules in uploaded code use --include-ignored-files ' 'flag.') archive.MakeZipFromDir( zip_file_name, source_path, skip_file_regex=GetIgnoreFilesRegex(include_ignored_files)) except ValueError as e: raise exceptions.FunctionsError( 'Error creating a ZIP archive with the source code ' 'for directory {0}: {1}'.format(source_path, str(e))) return zip_file_name
def _GetOperationStatus(client, get_request, progress_tracker=None, try_set_invoker=None, on_every_poll=None): """Helper function for getting the status of an operation. Args: client: The client used to make requests. get_request: A GetOperationRequest message. progress_tracker: progress_tracker.ProgressTracker, A reference for the progress tracker to tick, in case this function is used in a Retryer. try_set_invoker: function to try setting invoker, see above TODO. on_every_poll: list of functions to execute every time we poll. Functions should take in Operation as an argument. Returns: True if the operation succeeded without error. False if the operation is not yet done. Raises: FunctionsError: If the operation is finished with error. """ if try_set_invoker: try_set_invoker() if progress_tracker: progress_tracker.Tick() op = client.operations.Get(get_request) if op.error: raise exceptions.FunctionsError(OperationErrorToString(op.error)) if on_every_poll: for function in on_every_poll: function(op) return op.done
def CreateSourcesZipFile(zip_dir, source_path, include_ignored_files): """Prepare zip file with source of the function to upload. Args: zip_dir: str, directory in which zip file will be located. Name of the file will be `fun.zip`. source_path: str, directory containing the sources to be zipped. include_ignored_files: bool, indicates whether `node_modules` directory and its content will be included in the zip. Returns: Path to the zip file (str). Raises: FunctionsError """ util.ValidateDirectoryExistsOrRaiseFunctionError(source_path) _ValidateUnpackedSourceSize(source_path, include_ignored_files) zip_file_name = os.path.join(zip_dir, 'fun.zip') try: if include_ignored_files: predicate = None else: chooser = _GetChooser(source_path) predicate = chooser.IsIncluded archive.MakeZipFromDir(zip_file_name, source_path, predicate=predicate) except ValueError as e: raise exceptions.FunctionsError( 'Error creating a ZIP archive with the source code ' 'for directory {0}: {1}'.format(source_path, str(e))) return zip_file_name
def _GetOperationStatus(client, get_request, progress_tracker=None, do_every_poll=None): """Helper function for getting the status of an operation. Args: client: The client used to make requests. get_request: A GetOperationRequest message. progress_tracker: progress_tracker.ProgressTracker, A reference for the progress tracker to tick, in case this function is used in a Retryer. do_every_poll: An optional side effect to do before getting the status. Returns: True if the operation succeeded without error. False if the operation is not yet done. Raises: FunctionsError: If the operation is finished with error. """ if do_every_poll: do_every_poll() if progress_tracker: progress_tracker.Tick() op = client.operations.Get(get_request) if op.error: raise exceptions.FunctionsError(OperationErrorToString(op.error)) return op.done
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: None Raises: FunctionsError: If the user doesn't confirm on prompt. """ client = util.GetApiClientInstance() messages = client.MESSAGES_MODULE function_ref = resources.REGISTRY.Parse( args.name, params={ 'projectsId': properties.VALUES.core.project.GetOrFail, 'locationsId': properties.VALUES.functions.region.GetOrFail }, collection='cloudfunctions.projects.locations.functions') function__url = function_ref.RelativeName() prompt_message = 'Resource [{0}] will be deleted.'.format( function__url) if not console_io.PromptContinue(message=prompt_message): raise exceptions.FunctionsError('Deletion aborted by user.') op = client.projects_locations_functions.Delete( messages.CloudfunctionsProjectsLocationsFunctionsDeleteRequest( name=function__url)) operations.Wait(op, messages, client) log.DeletedResource(function__url)
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: None Raises: FunctionsError: If the user doesn't confirm on prompt. """ client = self.context['functions_client'] messages = self.context['functions_messages'] registry = self.context['registry'] project = properties.VALUES.core.project.Get(required=True) function_ref = registry.Parse( args.name, params={'projectsId': project, 'locationsId': args.region}, collection='cloudfunctions.projects.locations.functions') function__url = function_ref.RelativeName() prompt_message = 'Resource [{0}] will be deleted.'.format(function__url) if not console_io.PromptContinue(message=prompt_message): raise exceptions.FunctionsError('Deletion aborted by user.') # TODO(user): Use resources.py here after b/21908671 is fixed. op = client.projects_locations_functions.Delete( messages.CloudfunctionsProjectsLocationsFunctionsDeleteRequest( name=function__url)) operations.Wait(op, messages, client) log.DeletedResource(function__url)
def _WaitForOperation(client, get_request, message): """Wait for an operation to complete. No operation is done instantly. Wait for it to finish following this logic: * we wait 1s (jitter is also 1s) * we query service * if the operation is not finished we loop to first point * wait limit is 620s - if we get to that point it means something is wrong and we can throw an exception Args: client: The client used to make requests. get_request: A GetOperatioRequest message. message: str, The string to print while polling. Returns: True if the operation succeeded without error. Raises: FunctionsError: If the operation takes more than 620s. """ with console_io.ProgressTracker(message, autotick=False) as pt: # This is actually linear retryer. retryer = retry.Retryer(exponential_sleep_multiplier=1, max_wait_ms=MAX_WAIT_MS, wait_ceiling_ms=WAIT_CEILING_MS) try: retryer.RetryOnResult(_GetOperationStatus, [client, get_request], {'progress_tracker': pt}, should_retry_if=None, sleep_ms=SLEEP_MS) except retry.WaitException: raise exceptions.FunctionsError( 'Operation {0} is taking too long'.format(get_request.name))
def _UploadFileToGeneratedUrl(source, messages, service, function_ref): """Upload function source to URL generated by API.""" url = _GetUploadUrl(messages, service, function_ref) upload = transfer.Upload.FromFile(source, mime_type='application/zip') upload_request = http_wrapper.Request( url, http_method='PUT', headers={ 'content-type': 'application/zip', # Magic header, request will fail without it. # Not documented at the moment this comment was being written. 'x-goog-content-length-range': '0,104857600', 'Content-Length': '{0:d}'.format(upload.total_size) }) upload_request.body = upload.stream.read() response = http_wrapper.MakeRequest(http_utils.Http(), upload_request, retry_func=upload.retry_func, retries=upload.num_retries) if not _CheckUploadStatus(response.status_code): raise exceptions.FunctionsError( 'Failed to upload the function source code to signed url: {url}. ' 'Status: [{code}:{detail}]'.format(url=url, code=response.status_code, detail=response.content)) return url
def _CreateSourcesZipFile(zip_dir, source_path, ignore_file=None): """Prepare zip file with source of the function to upload. Args: zip_dir: str, directory in which zip file will be located. Name of the file will be `fun.zip`. source_path: str, directory containing the sources to be zipped. ignore_file: custom ignore_file name. Override .gcloudignore file to customize files to be skipped. Returns: Path to the zip file (str). Raises: FunctionsError """ api_util.ValidateDirectoryExistsOrRaiseFunctionError(source_path) if ignore_file and not os.path.exists( os.path.join(source_path, ignore_file)): raise exceptions.FileNotFoundError( 'File {0} referenced by --ignore-file ' 'does not exist.'.format(ignore_file)) _ValidateUnpackedSourceSize(source_path, ignore_file) zip_file_name = os.path.join(zip_dir, 'fun.zip') try: chooser = _GetChooser(source_path, ignore_file) predicate = chooser.IsIncluded archive.MakeZipFromDir(zip_file_name, source_path, predicate=predicate) except ValueError as e: raise exceptions.FunctionsError( 'Error creating a ZIP archive with the source code ' 'for directory {0}: {1}'.format(source_path, six.text_type(e))) return zip_file_name
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: None Raises: FunctionsError: If the user doesn't confirm on prompt. """ client = self.context['functions_client'] messages = self.context['functions_messages'] project = properties.VALUES.core.project.Get(required=True) name = 'projects/{0}/locations/{1}/functions/{2}'.format( project, args.region, args.name) prompt_message = 'Resource [{0}] will be deleted.'.format(name) if not console_io.PromptContinue(message=prompt_message): raise exceptions.FunctionsError('Deletion aborted by user.') # TODO(user): Use resources.py here after b/21908671 is fixed. op = client.projects_locations_functions.Delete( messages.CloudfunctionsProjectsLocationsFunctionsDeleteRequest( name=name)) operations.Wait(op, messages, client) log.DeletedResource(name)
def _UploadFileToGcs(source, function_ref, stage_bucket): remote_zip_file = _GenerateRemoteZipFileName(function_ref.RelativeName()) gcs_url = storage.BuildRemoteDestination(stage_bucket, remote_zip_file) if storage.Upload(source, gcs_url) != 0: raise exceptions.FunctionsError( 'Failed to upload the function source code to the bucket {0}'. format(stage_bucket)) return gcs_url
def _CheckArgs(self, args): # This function should raise ArgumentParsingError, but: # 1. ArgumentParsingError requires the argument returned from add_argument) # and Args() method is static. So there is no elegant way to save it # to be reused here. # 2. _CheckArgs() is invoked from Run() and ArgumentParsingError thrown # from Run are not caught. if args.source_url is None: if args.source_revision is not None: raise exceptions.FunctionsError( 'argument --source-revision: can be given only if argument ' '--source-url is provided') if args.source_branch is not None: raise exceptions.FunctionsError( 'argument --source-branch: can be given only if argument ' '--source-url is provided') if args.source_tag is not None: raise exceptions.FunctionsError( 'argument --source-tag: can be given only if argument ' '--source-url is provided') stage_bucket = args.bucket or args.stage_bucket if stage_bucket is None: raise exceptions.FunctionsError( 'argument --stage-bucket: required when the function is deployed ' 'from a local directory (when argument --source-url is not ' 'provided)') util.ValidateDirectoryExistsOrRaiseFunctionError( self._GetLocalPath(args)) else: if args.source is None and args.source_path is None: raise exceptions.FunctionsError( 'argument --source-path: required when argument --source-url is ' 'provided') if args.bucket is not None: log.warn( '--bucket flag is deprecated. Use --stage-bucket instead.') if args.source is not None: log.warn( '--source flag is deprecated. Use --local-path (for sources on ' 'local file system) or --source-path (for sources in Cloud ' 'Source Repositories) instead.') if args.trigger_gs_uri is not None: log.warn( '--trigger-gs-uri flag is deprecated. Use --trigger-bucket ' 'instead.')
def ValidateDirectoryExistsOrRaiseFunctionError(directory): """Checks if a source directory exists. Args: directory: A string: a local path to directory provided by user. Returns: The argument provided, if found valid. Raises: ArgumentTypeError: If the user provided a directory which is not valid. """ if not os.path.exists(directory): raise exceptions.FunctionsError( 'argument `--source`: Provided directory does not exist') if not os.path.isdir(directory): raise exceptions.FunctionsError( 'argument `--source`: Provided path does not point to a directory') return directory
def _CreateZipFile(self, tmp_dir, args): zip_file_name = os.path.join(tmp_dir, 'fun.zip') try: archive.MakeZipFromDir(zip_file_name, args.source) except ValueError as e: raise exceptions.FunctionsError('Error creating a ZIP archive' ' with the source code: ' + str(e)) return zip_file_name
def _ApplyArgsToFunction(self, base_function, is_new_function, trigger_params, name, args, project): """Apply values from args to base_function. Args: base_function: function message to modify is_new_function: bool, indicates if this is a new function (and source code for it must be deployed) or an existing function (so it may keep its old source code). trigger_params: parameters for creating functions trigger. name: relative name of the function. args: commandline args specyfying how to modify the function. project: project of the function. """ if args.IsSpecified('retry'): retry = args.retry else: retry = None self._ApplyNonSourceArgsToFunction(base_function, name, args.entry_point, args.timeout, args.trigger_http, trigger_params, retry, args.memory) messages = util.GetApiMessagesModule() if args.source: deploy_util.AddSourceToFunction(base_function, args.source, args.include_ignored_files, args.name, args.stage_bucket, messages) elif args.source_url: deploy_util.CleanOldSourceInfo(base_function) source_path = args.source_path source_branch = args.source_branch or 'master' base_function.sourceRepository = messages.SourceRepository( url=self._GetSourceUrlFromArgs(project, tag=args.source_tag, branch=source_branch, revision=args.source_revision, source_url=args.source_url, source_path=source_path)) elif args.stage_bucket: # Do not change source of existing function unless instructed to. deploy_util.CleanOldSourceInfo(base_function) base_function.sourceArchiveUrl = self._PrepareSourcesOnGcs(args) elif is_new_function or args.local_path: raise exceptions.FunctionsError( 'argument --stage-bucket: required when the function is deployed ' 'from a local directory.') # Set information about deplouyment tool. labels_to_update = args.update_labels or {} labels_to_update['deployment-tool'] = 'cli-gcloud' updated_labels = labels_util.UpdateLabels( base_function.labels, messages.CloudFunction.LabelsValue, update_labels=labels_to_update, remove_labels=args.remove_labels) if updated_labels is not None: base_function.labels = updated_labels
def _PrepareSourcesOnGcs(self, args): remote_zip_file = self._GenerateFileName(args) # args.bucket is not None: Enforced in _CheckArgs(). gcs_url = storage.BuildRemoteDestination(args.bucket, remote_zip_file) with file_utils.TemporaryDirectory() as tmp_dir: zip_file = self._CreateZipFile(tmp_dir, args) if self._UploadFile(zip_file, gcs_url) != 0: raise exceptions.FunctionsError('Function upload failed.') return gcs_url
def _CreateZipFile(self, tmp_dir, args): zip_file_name = os.path.join(tmp_dir, 'fun.zip') local_path = deploy_util.GetLocalPath(args) try: archive.MakeZipFromDir(zip_file_name, local_path) except ValueError as e: raise exceptions.FunctionsError( 'Error creating a ZIP archive with the source code ' 'for directory {0}: {1}'.format(local_path, str(e))) return zip_file_name
def _ValidateTriggerArgs(args): """Check if args related function triggers are valid. Args: args: parsed command line arguments. Raises: FunctionsError. """ trigger_event = args.trigger_event trigger_provider = args.trigger_provider trigger_resource = args.trigger_resource if trigger_provider is None: if args.trigger_event is not None or args.trigger_resource is not None: raise exceptions.FunctionsError( '--trigger-event, --trigger-resource, and --trigger-path may only ' 'be used with --trigger-provider') else: if trigger_event is None: trigger_event = util.input_trigger_provider_registry.Provider( trigger_provider).default_event.label event_labels = list( util.input_trigger_provider_registry.EventsLabels( trigger_provider)) if trigger_event not in event_labels: raise exceptions.FunctionsError( 'You can use only one of [{}] with --trigger-provider={}'. format(','.join(event_labels), trigger_provider)) # checked that Event Type is correct resource_type = util.input_trigger_provider_registry.Event( trigger_provider, trigger_event).resource_type if trigger_resource is None and resource_type != util.Resources.PROJECT: raise exceptions.FunctionsError( 'You must provide --trigger-resource when using ' '--trigger-provider={} and --trigger-event={}'.format( trigger_provider, trigger_event)) # checked if Resource Type and Path were provided or not as required if args.IsSpecified('retry') and args.IsSpecified('trigger_http'): raise calliope_exceptions.ConflictingArgumentsException( '--trigger-http', '--retry')
def _UploadFileToGcs(source, function_ref, stage_bucket): """Upload local source files to GCS staging bucket.""" zip_file = _GenerateRemoteZipFileName(function_ref.RelativeName()) bucket_ref = storage_util.BucketReference.FromArgument(stage_bucket) gcs_url = storage_util.ObjectReference(bucket_ref, zip_file).ToUrl() upload_result = storage_util.RunGsutilCommand('cp', [source, gcs_url]) if upload_result != 0: raise exceptions.FunctionsError( 'Failed to upload the function source code to the bucket {0}'. format(stage_bucket)) return gcs_url
def _PrepareSourcesOnGcs(self, args): remote_zip_file = self._GenerateRemoteZipFileName(args) gcs_url = storage.BuildRemoteDestination(args.stage_bucket, remote_zip_file) with file_utils.TemporaryDirectory() as tmp_dir: zip_file = self._CreateZipFile(tmp_dir, args) if self._UploadFile(zip_file, gcs_url) != 0: raise exceptions.FunctionsError( 'Failed to upload the function source code to the bucket {0}' .format(args.stage_bucket)) return gcs_url
def _ValidateSourceArgs(args): """Check if args related to source code to deploy are valid. Args: args: parsed command line arguments. Raises: FunctionsError. """ if args.source_url is None: if args.source_revision is not None: raise exceptions.FunctionsError( 'argument --source-revision: can be given only if argument ' '--source-url is provided') if args.source_branch is not None: raise exceptions.FunctionsError( 'argument --source-branch: can be given only if argument ' '--source-url is provided') if args.source_tag is not None: raise exceptions.FunctionsError( 'argument --source-tag: can be given only if argument ' '--source-url is provided') stage_bucket = args.bucket or args.stage_bucket if stage_bucket is None: raise exceptions.FunctionsError( 'argument --stage-bucket: required when the function is deployed ' 'from a local directory (when argument --source-url is not ' 'provided)') util.ValidateDirectoryExistsOrRaiseFunctionError(GetLocalPath(args)) else: if args.source is None and args.source_path is None: raise exceptions.FunctionsError( 'argument --source-path: required when argument --source-url is ' 'provided') if args.bucket is not None: log.warn('--bucket flag is deprecated. Use --stage-bucket instead.') if args.source is not None: log.warn( '--source flag is deprecated. Use --local-path (for sources on ' 'local file system) or --source-path (for sources in Cloud ' 'Source Repositories) instead.')
def ValidateDirectoryExistsOrRaiseFunctionError(directory): """Checks if a source directory exists. Args: directory: A string: a local path to directory provided by user. Returns: The argument provided, if found valid. Raises: ArgumentTypeError: If the user provided a directory which is not valid. """ if not os.path.exists(directory): raise exceptions.FunctionsError( 'argument --source: Provided directory does not exist. If ' 'you intended to provide a path to Google Cloud Repository, you must ' 'specify the --source-url argument') if not os.path.isdir(directory): raise exceptions.FunctionsError( 'argument --source: Provided path does not point to a directory. If ' 'you intended to provide a path to Google Cloud Repository, you must ' 'specify the --source-url argument') return directory
def DeduceAndCheckArgs(args): """Check command arguments and deduce information if possible. 0. Check if --source-revision, --source-branch or --source-tag are present when --source-url is not present. (and fail if it is so) 1. Check if --source-bucket is present when --source-url is present. 2. Validate if local-path is a directory. 3. Check if --source-path is present when --source-url is present. 4. Check if --trigger-event, --trigger-resource or --trigger-params are present when --trigger-provider is not present. (and fail if it is so) 5. Check --trigger-* family of flags deducing default values if possible and necessary. Args: args: The argument namespace. Returns: args with all implicit information turned into explicit form. """ # This function should raise ArgumentParsingError, but: # 1. ArgumentParsingError requires the argument returned from add_argument) # and Args() method is static. So there is no elegant way to save it # to be reused here. # 2. _CheckArgs() is invoked from Run() and ArgumentParsingError thrown # from Run are not caught. if args.source_url is None: if args.source_revision is not None: raise exceptions.FunctionsError( 'argument --source-revision: can be given only if argument ' '--source-url is provided') if args.source_branch is not None: raise exceptions.FunctionsError( 'argument --source-branch: can be given only if argument ' '--source-url is provided') if args.source_tag is not None: raise exceptions.FunctionsError( 'argument --source-tag: can be given only if argument ' '--source-url is provided') stage_bucket = args.stage_bucket if stage_bucket is None: raise exceptions.FunctionsError( 'argument --stage-bucket: required when the function is deployed ' 'from a local directory (when argument --source-url is not ' 'provided)') util.ValidateDirectoryExistsOrRaiseFunctionError(GetLocalPath(args)) else: if args.source_path is None: raise exceptions.FunctionsError( 'argument --source-path: required when argument --source-url is ' 'provided') if args.trigger_provider is None and ((args.trigger_event is not None) or (args.trigger_resource is not None) or (args.trigger_params is not None)): raise exceptions.FunctionsError( '--trigger-event, --trigger-resource, and --trigger-params may only ' 'be used with --trigger-provider') if args.trigger_provider is not None: return _CheckTriggerProviderArgs(args)
def _ValidateTriggerArgs(args): """Check if args related function triggers are valid. Args: args: parsed command line arguments. Raises: FunctionsError. """ if args.trigger_provider is None and (args.trigger_event is not None or args.trigger_resource is not None): raise exceptions.FunctionsError( '--trigger-event, --trigger-resource, and --trigger-path may only ' 'be used with --trigger-provider')