File: //snap/google-cloud-cli/current/lib/surface/container/fleet/identity_service/apply.py
# -*- coding: utf-8 -*- #
# Copyright 2022 Google LLC. All Rights Reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
"""The command to update Identity Service Feature."""
from __future__ import absolute_import
from __future__ import division
from __future__ import unicode_literals
from googlecloudsdk.command_lib.anthos.common import file_parsers
from googlecloudsdk.command_lib.container.fleet import resources
from googlecloudsdk.command_lib.container.fleet.features import base
from googlecloudsdk.command_lib.container.fleet.identity_service import utils
from googlecloudsdk.core import exceptions
from googlecloudsdk.core.util import retry
# Pull out the example text so the example command can be one line without the
# py linter complaining. The docgen tool properly breaks it into multiple lines.
EXAMPLES = """\
To apply an Identity Service configuration to a membership, run:
$ {command} --membership=MEMBERSHIP_NAME --config=/path/to/identity-service.yaml
To create or modify a fleet-level default membership configuration, run:
$ {command} --fleet-default-member-config=/path/to/identity-service.yaml
To apply an existing fleet-level default membership configuration to a membership, run:
$ {command} --origin=fleet --membership=MEMBERSHIP_NAME
"""
class Apply(base.UpdateCommand):
"""Update the Identity Service Feature.
This command updates the Identity Service Feature in a fleet.
"""
detailed_help = {'EXAMPLES': EXAMPLES}
feature_name = 'identityservice'
@classmethod
def Args(cls, parser):
command_args = parser.add_group(required=True, mutex=False)
command_args.add_argument(
'--fleet-default-member-config',
type=str,
help='The path to an identity-service.yaml configuration file.',
required=False,
)
per_member_config_args = command_args.add_group(required=False, mutex=False)
resources.AddMembershipResourceArg(per_member_config_args)
per_member_config_source = per_member_config_args.add_group(
mutex=True, required=True
)
per_member_config_source.add_argument(
'--config',
type=str,
help='The path to an identity-service.yaml configuration file.',
)
per_member_config_source.add_argument(
'--origin',
choices=['fleet'],
type=str,
help=(
'Applies the fleet-level default membership configuration to a'
' membership.'
),
)
def Run(self, args):
patch = self.messages.Feature()
update_mask = []
if args.config or args.origin:
self.preparePerMemberConfigPatch(args, patch, update_mask)
if args.fleet_default_member_config:
self.prepareFleetDefaultMemberConfigPatch(args, patch, update_mask)
try:
max_wait_ms = 60000 # 60 secs
retryer = retry.Retryer(
max_wait_ms=max_wait_ms, exponential_sleep_multiplier=1.1
)
retryer.RetryOnException(
self.Update, args=(update_mask, patch), sleep_ms=1000
)
except retry.MaxRetrialsException:
raise exceptions.Error(
'Retry limit exceeded while waiting for the {} feature to update'
.format(self.feature.display_name)
)
def prepareFleetDefaultMemberConfigPatch(self, args, patch, update_mask):
# Load the config YAML file.
loaded_config = file_parsers.YamlConfigFile(
file_path=args.fleet_default_member_config,
item_type=file_parsers.LoginConfigObject,
)
# Create a new identity service feature spec.
member_config = utils.parse_config(loaded_config, self.messages)
# Add the fleet default member config to the feature patch and update
# `update mask`.
patch.fleetDefaultMemberConfig = (
self.messages.CommonFleetDefaultMemberConfigSpec(
identityservice=member_config
)
)
update_mask.append('fleet_default_member_config')
def preparePerMemberConfigPatch(self, args, patch, update_mask):
# Get the membership the user is attempting to apply the configuration to.
# If no membership is specified, and there is a single membership available
# in the fleet, it would be automatically selected.
# If no membership is specified, and there are multiple memberships
# available in the fleet, the user would be prompted to select
# one from the ones available in the fleet.
membership = base.ParseMembership(
args, prompt=True, autoselect=True, search=True
)
membership_spec = self.messages.MembershipFeatureSpec()
if args.origin:
membership_spec.origin = self.messages.Origin(
type=self.messages.Origin.TypeValueValuesEnum('FLEET')
)
else:
# Load the config YAML file.
loaded_config = file_parsers.YamlConfigFile(
file_path=args.config, item_type=file_parsers.LoginConfigObject
)
# Create a new identity service feature spec.
member_config = utils.parse_config(loaded_config, self.messages)
membership_spec.identityservice = member_config
# Add the newly prepared membershipSpec to the feature patch and update
# `update mask`.
patch.membershipSpecs = self.hubclient.ToMembershipSpecs(
{membership: membership_spec}
)
update_mask.append('membership_specs')