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:
      The specified function with its description and configured filter.
    """
        function_ref = args.CONCEPTS.name.Parse()
        return util.AddFunctionIamPolicyBinding(function_ref.RelativeName(),
                                                args.member, args.role)
Example #2
0
    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))
Example #3
0
def _Run(args,
         track=None,
         enable_runtime=True,
         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
    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 enable_vpc_connector:
        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 enable_traffic_control:
        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')
    # 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 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

    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)