def _Run(args, track=None, enable_runtime=True, enable_build_worker_pool=False): """Run a function deployment with the given args.""" # Check for labels that start with `deployment`, which is not allowed. labels_util.CheckNoDeploymentLabels('--remove-labels', args.remove_labels) labels_util.CheckNoDeploymentLabels('--update-labels', args.update_labels) # Check that exactly one trigger type is specified properly. trigger_util.ValidateTriggerArgs(args.trigger_event, args.trigger_resource, args.IsSpecified('retry'), args.IsSpecified('trigger_http')) trigger_params = trigger_util.GetTriggerEventParams( args.trigger_http, args.trigger_bucket, args.trigger_topic, args.trigger_event, args.trigger_resource) function_ref = args.CONCEPTS.name.Parse() function_url = function_ref.RelativeName() messages = api_util.GetApiMessagesModule(track) # Get an existing function or create a new one. function = api_util.GetFunction(function_url) is_new_function = function is None had_vpc_connector = bool( function.vpcConnector) if not is_new_function else False if is_new_function: trigger_util.CheckTriggerSpecified(args) function = messages.CloudFunction() function.name = function_url elif trigger_params: # If the new deployment would implicitly change the trigger_event type # raise error trigger_util.CheckLegacyTriggerUpdate(function.eventTrigger, trigger_params['trigger_event']) # Keep track of which fields are updated in the case of patching. updated_fields = [] # Populate function properties based on args. if args.entry_point: function.entryPoint = args.entry_point updated_fields.append('entryPoint') if args.timeout: function.timeout = '{}s'.format(args.timeout) updated_fields.append('timeout') if args.memory: function.availableMemoryMb = utils.BytesToMb(args.memory) updated_fields.append('availableMemoryMb') if args.service_account: function.serviceAccountEmail = args.service_account updated_fields.append('serviceAccountEmail') if (args.IsSpecified('max_instances') or args.IsSpecified('clear_max_instances')): max_instances = 0 if args.clear_max_instances else args.max_instances function.maxInstances = max_instances updated_fields.append('maxInstances') if enable_runtime: if args.IsSpecified('runtime'): function.runtime = args.runtime updated_fields.append('runtime') if args.runtime in ['nodejs6']: log.warning( 'The Node.js 6 runtime is deprecated on Cloud Functions. ' 'Please migrate to Node.js 8 (--runtime=nodejs8) or Node.js 10 ' '(--runtime=nodejs10). ' 'See https://cloud.google.com/functions/docs/migrating/nodejs-runtimes' ) elif is_new_function: raise exceptions.RequiredArgumentException( 'runtime', 'Flag `--runtime` is required for new functions.') if args.vpc_connector or args.clear_vpc_connector: function.vpcConnector = ('' if args.clear_vpc_connector else args.vpc_connector) updated_fields.append('vpcConnector') if args.IsSpecified('egress_settings'): will_have_vpc_connector = ((had_vpc_connector and not args.clear_vpc_connector) or args.vpc_connector) if not will_have_vpc_connector: raise exceptions.RequiredArgumentException( 'vpc-connector', 'Flag `--vpc-connector` is ' 'required for setting `egress-settings`.') egress_settings_enum = arg_utils.ChoiceEnumMapper( arg_name='egress_settings', message_enum=function.VpcConnectorEgressSettingsValueValuesEnum, custom_mappings=flags.EGRESS_SETTINGS_MAPPING).GetEnumForChoice( args.egress_settings) function.vpcConnectorEgressSettings = egress_settings_enum updated_fields.append('vpcConnectorEgressSettings') if args.IsSpecified('ingress_settings'): ingress_settings_enum = arg_utils.ChoiceEnumMapper( arg_name='ingress_settings', message_enum=function.IngressSettingsValueValuesEnum, custom_mappings=flags.INGRESS_SETTINGS_MAPPING).GetEnumForChoice( args.ingress_settings) function.ingressSettings = ingress_settings_enum updated_fields.append('ingressSettings') if enable_build_worker_pool: if args.build_worker_pool or args.clear_build_worker_pool: function.buildWorkerPool = ('' if args.clear_build_worker_pool else args.build_worker_pool) updated_fields.append('buildWorkerPool') # Populate trigger properties of function based on trigger args. if args.trigger_http: function.httpsTrigger = messages.HttpsTrigger() function.eventTrigger = None updated_fields.extend(['eventTrigger', 'httpsTrigger']) if trigger_params: function.eventTrigger = trigger_util.CreateEventTrigger( **trigger_params) function.httpsTrigger = None updated_fields.extend(['eventTrigger', 'httpsTrigger']) if args.IsSpecified('retry'): updated_fields.append('eventTrigger.failurePolicy') if args.retry: function.eventTrigger.failurePolicy = messages.FailurePolicy() function.eventTrigger.failurePolicy.retry = messages.Retry() else: function.eventTrigger.failurePolicy = None elif function.eventTrigger: function.eventTrigger.failurePolicy = None # Populate source properties of function based on source args. # Only Add source to function if its explicitly provided, a new function, # using a stage bucket or deploy of an existing function that previously # used local source. if (args.source or args.stage_bucket or is_new_function or function.sourceUploadUrl): updated_fields.extend( source_util.SetFunctionSourceProps(function, function_ref, args.source, args.stage_bucket, args.ignore_file)) # Apply label args to function if labels_util.SetFunctionLabels(function, args.update_labels, args.remove_labels, args.clear_labels): updated_fields.append('labels') # Apply environment variables args to function updated_fields.extend(_ApplyEnvVarsArgsToFunction(function, args)) ensure_all_users_invoke = flags.ShouldEnsureAllUsersInvoke(args) deny_all_users_invoke = flags.ShouldDenyAllUsersInvoke(args) if is_new_function: if (not ensure_all_users_invoke and not deny_all_users_invoke and api_util.CanAddFunctionIamPolicyBinding(_GetProject(args))): ensure_all_users_invoke = console_io.PromptContinue(prompt_string=( 'Allow unauthenticated invocations of new function [{}]?'. format(args.NAME)), default=False) op = api_util.CreateFunction(function, function_ref.Parent().RelativeName()) if (not ensure_all_users_invoke and not deny_all_users_invoke): template = ('Function created with limited-access IAM policy. ' 'To enable unauthorized access consider "%s"') log.warning(template % _CreateBindPolicyCommand(args.NAME, args.region)) deny_all_users_invoke = True elif updated_fields: op = api_util.PatchFunction(function, updated_fields) else: op = None # Nothing to wait for if not ensure_all_users_invoke and not deny_all_users_invoke: log.status.Print('Nothing to update.') return stop_trying_perm_set = [False] # The server asyncrhonously sets allUsers invoker permissions some time after # we create the function. That means, to remove it, we need do so after the # server adds it. We can remove this mess after the default changes. # TODO(b/139026575): Remove the "remove" path, only bother adding. Remove the # logic from the polling loop. Remove the ability to add logic like this to # the polling loop. def TryToSetInvokerPermission(): """Try to make the invoker permission be what we said it should. This is for executing in the polling loop, and will stop trying as soon as it succeeds at making a change. """ if stop_trying_perm_set[0]: return try: if ensure_all_users_invoke: api_util.AddFunctionIamPolicyBinding(function.name) stop_trying_perm_set[0] = True elif deny_all_users_invoke: stop_trying_perm_set[0] = ( api_util.RemoveFunctionIamPolicyBindingIfFound( function.name)) except exceptions.HttpException: stop_trying_perm_set[0] = True log.warning('Setting IAM policy failed, try "%s"' % _CreateBindPolicyCommand(args.NAME, args.region)) if op: api_util.WaitForFunctionUpdateOperation( op, do_every_poll=TryToSetInvokerPermission) return api_util.GetFunction(function.name)
def _Run(args, track=None, enable_runtime=True, enable_max_instances=False, enable_vpc_connector=False, enable_traffic_control=False, enable_allow_unauthenticated=False): """Run a function deployment with the given args.""" # Check for labels that start with `deployment`, which is not allowed. labels_util.CheckNoDeploymentLabels('--remove-labels', args.remove_labels) labels_util.CheckNoDeploymentLabels('--update-labels', args.update_labels) # Check that exactly one trigger type is specified properly. trigger_util.ValidateTriggerArgs(args.trigger_event, args.trigger_resource, args.IsSpecified('retry'), args.IsSpecified('trigger_http')) trigger_params = trigger_util.GetTriggerEventParams( args.trigger_http, args.trigger_bucket, args.trigger_topic, args.trigger_event, args.trigger_resource) function_ref = args.CONCEPTS.name.Parse() function_url = function_ref.RelativeName() messages = api_util.GetApiMessagesModule(track) # Get an existing function or create a new one. function = api_util.GetFunction(function_url) is_new_function = function is None if is_new_function: trigger_util.CheckTriggerSpecified(args) function = messages.CloudFunction() function.name = function_url elif trigger_params: # If the new deployment would implicitly change the trigger_event type # raise error trigger_util.CheckLegacyTriggerUpdate(function.eventTrigger, trigger_params['trigger_event']) # Keep track of which fields are updated in the case of patching. updated_fields = [] # Populate function properties based on args. if args.entry_point: function.entryPoint = args.entry_point updated_fields.append('entryPoint') if args.timeout: function.timeout = '{}s'.format(args.timeout) updated_fields.append('timeout') if args.memory: function.availableMemoryMb = utils.BytesToMb(args.memory) updated_fields.append('availableMemoryMb') if args.service_account: function.serviceAccountEmail = args.service_account updated_fields.append('serviceAccountEmail') if enable_runtime: if args.IsSpecified('runtime'): function.runtime = args.runtime updated_fields.append('runtime') if args.runtime in ['nodejs', 'nodejs6']: # nodejs is nodejs6 alias log.warning( 'The Node.js 6 runtime is deprecated on Cloud Functions. ' 'Please migrate to Node.js 8 (--runtime=nodejs8) or Node.js 10 ' '(--runtime=nodejs10). ' 'See https://cloud.google.com/functions/docs/migrating/nodejs-runtimes' ) elif is_new_function: raise exceptions.RequiredArgumentException( 'runtime', 'Flag `--runtime` is required for new functions.') if enable_max_instances: if (args.IsSpecified('max_instances') or args.IsSpecified('clear_max_instances')): max_instances = 0 if args.clear_max_instances else args.max_instances function.maxInstances = max_instances updated_fields.append('maxInstances') if enable_vpc_connector: if args.IsSpecified('vpc_connector'): function.vpcConnector = args.vpc_connector updated_fields.append('vpcConnector') if enable_traffic_control: if args.IsSpecified('egress_settings'): egress_settings_enum = \ arg_utils.ChoiceEnumMapper( arg_name='egress_settings', message_enum=function.VpcConnectorEgressSettingsValueValuesEnum, custom_mappings=flags.EGRESS_SETTINGS_MAPPING,).GetEnumForChoice( args.egress_settings) function.vpcConnectorEgressSettings = egress_settings_enum updated_fields.append('vpcConnectorEgressSettings') if (args.IsSpecified('egress_settings') and not args.IsSpecified('vpc_connector')): raise exceptions.RequiredArgumentException( 'vpc-connector', 'Flag `--vpc-connector` is ' 'required for setting egress_settings.') if enable_traffic_control: if args.IsSpecified('ingress_settings'): ingress_settings_enum = \ arg_utils.ChoiceEnumMapper( arg_name='ingress_settings', message_enum=function.IngressSettingsValueValuesEnum, custom_mappings=flags.INGRESS_SETTINGS_MAPPING,).GetEnumForChoice( args.ingress_settings) function.ingressSettings = ingress_settings_enum updated_fields.append('ingressSettings') # Populate trigger properties of function based on trigger args. if args.trigger_http: function.httpsTrigger = messages.HttpsTrigger() function.eventTrigger = None updated_fields.extend(['eventTrigger', 'httpsTrigger']) if trigger_params: function.eventTrigger = trigger_util.CreateEventTrigger( **trigger_params) function.httpsTrigger = None updated_fields.extend(['eventTrigger', 'httpsTrigger']) if args.IsSpecified('retry'): updated_fields.append('eventTrigger.failurePolicy') if args.retry: function.eventTrigger.failurePolicy = messages.FailurePolicy() function.eventTrigger.failurePolicy.retry = messages.Retry() else: function.eventTrigger.failurePolicy = None elif function.eventTrigger: function.eventTrigger.failurePolicy = None # Populate source properties of function based on source args. # Only Add source to function if its explicitly provided, a new function, # using a stage bucket or deploy of an existing function that previously # used local source. if (args.source or args.stage_bucket or is_new_function or function.sourceUploadUrl): updated_fields.extend( source_util.SetFunctionSourceProps(function, function_ref, args.source, args.stage_bucket, args.ignore_file)) # Apply label args to function if labels_util.SetFunctionLabels(function, args.update_labels, args.remove_labels, args.clear_labels): updated_fields.append('labels') # Apply environment variables args to function updated_fields.extend(_ApplyEnvVarsArgsToFunction(function, args)) ensure_all_users_invoke = (enable_allow_unauthenticated and flags.ShouldEnsureAllUsersInvoke(args)) deny_all_users_invoke = (enable_allow_unauthenticated and flags.ShouldDenyAllUsersInvoke(args)) if is_new_function: if (enable_allow_unauthenticated and not ensure_all_users_invoke and not deny_all_users_invoke and api_util.CanAddFunctionIamPolicyBinding(_GetProject(args))): ensure_all_users_invoke = console_io.PromptContinue(prompt_string=( 'Allow unauthenticated invocations of new function [{}]?'. format(args.NAME)), default=False) op = api_util.CreateFunction(function, function_ref.Parent().RelativeName()) if (enable_allow_unauthenticated and not ensure_all_users_invoke and not deny_all_users_invoke): template = ('Function created with default IAM policy. ' 'To enable unauthorized access consider "%s"') log.warning(template % _CreateBindPolicyCommand(args.NAME, args.region)) elif updated_fields: op = api_util.PatchFunction(function, updated_fields) else: op = None # Nothing to wait for if not ensure_all_users_invoke and not deny_all_users_invoke: log.status.Print('Nothing to update.') return try: if ensure_all_users_invoke: api_util.AddFunctionIamPolicyBinding(function.name) elif deny_all_users_invoke: api_util.RemoveFunctionIamPolicyBindingIfFound(function.name) except exceptions.HttpException: log.warning('Setting IAM policy failed, try "%s"' % _CreateBindPolicyCommand(args.NAME, args.region)) if op: api_util.WaitForFunctionUpdateOperation(op) return api_util.GetFunction(function.name)
def _Run(args, track=None, enable_runtime=True, enable_max_instances=False, enable_connected_vpc=False): """Run a function deployment with the given args.""" # Check for labels that start with `deployment`, which is not allowed. labels_util.CheckNoDeploymentLabels('--remove-labels', args.remove_labels) labels_util.CheckNoDeploymentLabels('--update-labels', args.update_labels) # Check that exactly one trigger type is specified properly. trigger_util.ValidateTriggerArgs(args.trigger_event, args.trigger_resource, args.IsSpecified('retry'), args.IsSpecified('trigger_http')) trigger_params = trigger_util.GetTriggerEventParams( args.trigger_http, args.trigger_bucket, args.trigger_topic, args.trigger_event, args.trigger_resource) function_ref = args.CONCEPTS.name.Parse() function_url = function_ref.RelativeName() messages = api_util.GetApiMessagesModule(track) # Get an existing function or create a new one. function = api_util.GetFunction(function_url) is_new_function = function is None if is_new_function: trigger_util.CheckTriggerSpecified(args) function = messages.CloudFunction() function.name = function_url elif trigger_params: # If the new deployment would implicitly change the trigger_event type # raise error trigger_util.CheckLegacyTriggerUpdate(function.eventTrigger, trigger_params['trigger_event']) # Keep track of which fields are updated in the case of patching. updated_fields = [] # Populate function properties based on args. if args.entry_point: function.entryPoint = args.entry_point updated_fields.append('entryPoint') if args.timeout: function.timeout = '{}s'.format(args.timeout) updated_fields.append('timeout') if args.memory: function.availableMemoryMb = utils.BytesToMb(args.memory) updated_fields.append('availableMemoryMb') if args.service_account: function.serviceAccountEmail = args.service_account updated_fields.append('serviceAccountEmail') if enable_runtime: if args.IsSpecified('runtime'): function.runtime = args.runtime updated_fields.append('runtime') elif is_new_function: log.warning('Flag `--runtime` will become a required flag soon. ' 'Please specify the value for this flag.') if enable_max_instances: if (args.IsSpecified('max_instances') or args.IsSpecified('clear_max_instances')): max_instances = 0 if args.clear_max_instances else args.max_instances function.maxInstances = max_instances updated_fields.append('maxInstances') if enable_connected_vpc: if args.connected_vpc: function.network = args.connected_vpc updated_fields.append('network') if args.vpc_connector: function.vpcConnector = args.vpc_connector updated_fields.append('vpcConnector') # Populate trigger properties of function based on trigger args. if args.trigger_http: function.httpsTrigger = messages.HttpsTrigger() function.eventTrigger = None updated_fields.extend(['eventTrigger', 'httpsTrigger']) if trigger_params: function.eventTrigger = trigger_util.CreateEventTrigger( **trigger_params) function.httpsTrigger = None updated_fields.extend(['eventTrigger', 'httpsTrigger']) if args.IsSpecified('retry'): updated_fields.append('eventTrigger.failurePolicy') if args.retry: function.eventTrigger.failurePolicy = messages.FailurePolicy() function.eventTrigger.failurePolicy.retry = messages.Retry() else: function.eventTrigger.failurePolicy = None elif function.eventTrigger: function.eventTrigger.failurePolicy = None # Populate source properties of function based on source args. # Only Add source to function if its explicitly provided, a new function, # using a stage bucket or deploy of an existing function that previously # used local source. if (args.source or args.stage_bucket or is_new_function or function.sourceUploadUrl): updated_fields.extend( source_util.SetFunctionSourceProps(function, function_ref, args.source, args.stage_bucket)) # Apply label args to function if labels_util.SetFunctionLabels(function, args.update_labels, args.remove_labels, args.clear_labels): updated_fields.append('labels') # Apply environment variables args to function updated_fields.extend(_ApplyEnvVarsArgsToFunction(function, args)) if is_new_function: return api_util.CreateFunction(function, function_ref.Parent().RelativeName()) if updated_fields: return api_util.PatchFunction(function, updated_fields) log.status.Print('Nothing to update.')
def _Run(args, enable_runtime=False): """Run a function deployment with the given args.""" # Check for labels that start with `deployment`, which is not allowed. labels_util.CheckNoDeploymentLabels('--remove-labels', args.remove_labels) labels_util.CheckNoDeploymentLabels('--update-labels', args.update_labels) # Check that exactly one trigger type is specified properly. trigger_util.ValidateTriggerArgs(args.trigger_event, args.trigger_resource, args.IsSpecified('retry'), args.IsSpecified('trigger_http')) trigger_params = trigger_util.GetTriggerEventParams( args.trigger_http, args.trigger_bucket, args.trigger_topic, args.trigger_event, args.trigger_resource) function_ref = api_util.GetFunctionRef(args.name) function_url = function_ref.RelativeName() messages = api_util.GetApiMessagesModule() # Get an existing function or create a new one. function = api_util.GetFunction(function_url) is_new_function = function is None if is_new_function: trigger_util.CheckTriggerSpecified(args) function = messages.CloudFunction() function.name = function_url elif trigger_params: # If the new deployment would implicitly change the trigger_event type # raise error trigger_util.CheckLegacyTriggerUpdate(function.eventTrigger, trigger_params['trigger_event']) # Keep track of which fields are updated in the case of patching. updated_fields = [] # Populate function properties based on args. if args.entry_point: function.entryPoint = args.entry_point updated_fields.append('entryPoint') if args.timeout: function.timeout = '{}s'.format(args.timeout) updated_fields.append('timeout') if args.memory: function.availableMemoryMb = utils.BytesToMb(args.memory) updated_fields.append('availableMemoryMb') if enable_runtime: if args.IsSpecified('runtime'): function.runtime = args.runtime updated_fields.append('runtime') # Populate trigger properties of function based on trigger args. if args.trigger_http: function.httpsTrigger = messages.HttpsTrigger() function.eventTrigger = None updated_fields.extend(['eventTrigger', 'httpsTrigger']) if trigger_params: function.eventTrigger = trigger_util.CreateEventTrigger( **trigger_params) function.httpsTrigger = None updated_fields.extend(['eventTrigger', 'httpsTrigger']) if args.IsSpecified('retry'): updated_fields.append('eventTrigger.failurePolicy') if args.retry: function.eventTrigger.failurePolicy = messages.FailurePolicy() function.eventTrigger.failurePolicy.retry = messages.Retry() else: function.eventTrigger.failurePolicy = None elif function.eventTrigger: function.eventTrigger.failurePolicy = None # Populate source properties of function based on source args. # Only Add source to function if its explicitly provided, a new function, # using a stage budget or deploy of an existing function that previously # used local source. if (args.source or args.stage_bucket or is_new_function or function.sourceUploadUrl): updated_fields.extend( source_util.SetFunctionSourceProps(function, function_ref, args.source, args.stage_bucket)) # Apply label args to function if labels_util.SetFunctionLabels(function, args.update_labels, args.remove_labels, args.clear_labels): updated_fields.append('labels') if is_new_function: return api_util.CreateFunction(function) if updated_fields: return api_util.PatchFunction(function, updated_fields) log.status.Print('Nothing to update.')