File: //snap/google-cloud-cli/current/lib/surface/container/fleet/mesh/update.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 Service Mesh Feature."""
from __future__ import absolute_import
from __future__ import division
from __future__ import unicode_literals
from apitools.base.py import exceptions as apitools_exceptions
from googlecloudsdk.api_lib.container.fleet import util
from googlecloudsdk.calliope import actions
from googlecloudsdk.calliope import base
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 as features_base
from googlecloudsdk.command_lib.container.fleet.membershipfeatures import base as mf_base
from googlecloudsdk.command_lib.container.fleet.mesh import utils
# LINT.IfChange(update_v2)
def _RunUpdateV2(cmd, args):
"""Runs the update command implementation that is common across release tracks.
For membership level spec update, we will use v2alpha API to directly update
the membership feature resource.
Args:
cmd: the release track specific command
args: the args passed to the command
"""
memberships = []
resource = False
update_mask = []
# Deprecated non-resource arg
if args.IsKnownAndSpecified('membership'):
resource = False
memberships = utils.ParseMemberships(args)
elif args.fleet_default_member_config is None:
resource = True
memberships = features_base.ParseMembershipsPlural(
args, prompt=True, search=True
)
for membership in memberships:
if not resource:
membership = cmd.MembershipResourceName(membership)
patch_v2 = cmd.messages_v2.FeatureSpec()
try:
existing_membership_feature = cmd.GetMembershipFeature(membership)
except apitools_exceptions.HttpNotFoundError:
existing_membership_feature = cmd.messages_v2.MembershipFeature()
if existing_membership_feature.spec:
patch_v2 = existing_membership_feature.spec
if not patch_v2.servicemesh:
patch_v2.servicemesh = cmd.messages_v2.ServiceMeshSpec()
if hasattr(args, 'origin') and args.origin is not None:
if args.origin == 'fleet':
patch_v2.origin = cmd.messages_v2.Origin(
type=cmd.messages_v2.Origin.TypeValueValuesEnum('FLEET')
)
if hasattr(args, 'management') and args.management is not None:
management_v2 = (
cmd.messages_v2.ServiceMeshSpec.ManagementValueValuesEnum(
'MANAGEMENT_MANUAL'))
if args.management == 'automatic':
management_v2 = (
cmd.messages_v2.ServiceMeshSpec.ManagementValueValuesEnum(
'MANAGEMENT_AUTOMATIC'))
if args.management == 'not_installed':
management_v2 = (
cmd.messages_v2.ServiceMeshSpec.ManagementValueValuesEnum(
'MANAGEMENT_NOT_INSTALLED'))
patch_v2.servicemesh.management = management_v2
if args.control_plane is not None:
control_plane_v2 = (
cmd.messages_v2.ServiceMeshSpec.ControlPlaneValueValuesEnum(
'MANUAL'))
if args.control_plane == 'automatic':
control_plane_v2 = (
cmd.messages_v2.ServiceMeshSpec.ControlPlaneValueValuesEnum(
'AUTOMATIC'))
elif args.control_plane == 'unspecified':
control_plane_v2 = (
cmd.messages_v2.ServiceMeshSpec.ControlPlaneValueValuesEnum(
'CONTROL_PLANE_MANAGEMENT_UNSPECIFIED'))
patch_v2.servicemesh.controlPlane = control_plane_v2
if hasattr(args, 'config_api') and args.config_api is not None:
config_api = (
cmd.messages_v2.ServiceMeshSpec.ConfigApiValueValuesEnum(
'CONFIG_API_UNSPECIFIED'
)
)
if args.config_api == 'istio':
config_api = (
cmd.messages_v2.ServiceMeshSpec.ConfigApiValueValuesEnum(
'CONFIG_API_ISTIO'
)
)
if args.config_api == 'gateway':
config_api = (
cmd.messages_v2.ServiceMeshSpec.ConfigApiValueValuesEnum(
'CONFIG_API_GATEWAY'
)
)
patch_v2.servicemesh.configApi = config_api
cmd.UpdateV2(
membership, ['spec'], cmd.messages_v2.MembershipFeature(spec=patch_v2)
)
f = cmd.messages.Feature()
if args.fleet_default_member_config:
# Load config YAML file.
loaded_config = file_parsers.YamlConfigFile(
file_path=args.fleet_default_member_config,
item_type=utils.FleetDefaultMemberConfigObject,
)
# Create new service mesh feature spec.
member_config = utils.ParseFleetDefaultMemberConfigV2(
loaded_config, cmd.messages
)
f.fleetDefaultMemberConfig = (
cmd.messages.CommonFleetDefaultMemberConfigSpec(mesh=member_config)
)
update_mask.append('fleet_default_member_config')
if update_mask:
cmd.Update(update_mask, f)
# LINT.ThenChange(:update_v1)
# LINT.IfChange(update_v1)
def _RunUpdate(cmd, args):
"""Runs the update command implementation that is common across release tracks.
Args:
cmd: the release track specific command
args: the args passed to the command
"""
memberships = []
resource = False
update_mask = []
# Deprecated non-resource arg
if args.IsKnownAndSpecified('membership'):
resource = False
memberships = utils.ParseMemberships(args)
update_mask = ['membershipSpecs']
elif args.fleet_default_member_config is None:
resource = True
memberships = features_base.ParseMembershipsPlural(
args, prompt=True, search=True
)
update_mask = ['membershipSpecs']
f = cmd.GetFeature()
membership_specs = {}
for membership in memberships:
if not resource:
membership = cmd.MembershipResourceName(membership)
patch = cmd.messages.MembershipFeatureSpec()
for name, spec in cmd.hubclient.ToPyDict(f.membershipSpecs).items():
if (
util.MembershipShortname(name) == util.MembershipShortname(membership)
and spec
):
patch = spec
if not patch.mesh:
patch.mesh = cmd.messages.ServiceMeshMembershipSpec()
if hasattr(args, 'origin') and args.origin is not None:
if args.origin == 'fleet':
patch.origin = cmd.messages.Origin(
type=cmd.messages.Origin.TypeValueValuesEnum('FLEET')
)
if hasattr(args, 'management') and args.management is not None:
management = (
cmd.messages.ServiceMeshMembershipSpec.ManagementValueValuesEnum(
'MANAGEMENT_MANUAL'
)
)
if args.management == 'automatic':
management = (
cmd.messages.ServiceMeshMembershipSpec.ManagementValueValuesEnum(
'MANAGEMENT_AUTOMATIC'
)
)
if args.management == 'not_installed':
management = (
cmd.messages_v2.ServiceMeshSpec.ManagementValueValuesEnum(
'MANAGEMENT_NOT_INSTALLED'))
patch.mesh.management = management
if args.control_plane is not None:
control_plane = (
cmd.messages.ServiceMeshMembershipSpec.ControlPlaneValueValuesEnum(
'MANUAL'
)
)
if args.control_plane == 'automatic':
control_plane = (
cmd.messages.ServiceMeshMembershipSpec.ControlPlaneValueValuesEnum(
'AUTOMATIC'
)
)
elif args.control_plane == 'unspecified':
control_plane = (
cmd.messages.ServiceMeshMembershipSpec.ControlPlaneValueValuesEnum(
'CONTROL_PLANE_MANAGEMENT_UNSPECIFIED'
)
)
patch.mesh.controlPlane = control_plane
if hasattr(args, 'config_api') and args.config_api is not None:
config_api = (
cmd.messages.ServiceMeshMembershipSpec.ConfigApiValueValuesEnum(
'CONFIG_API_UNSPECIFIED'
)
)
if args.config_api == 'istio':
config_api = (
cmd.messages.ServiceMeshMembershipSpec.ConfigApiValueValuesEnum(
'CONFIG_API_ISTIO'
)
)
if args.config_api == 'gateway':
config_api = (
cmd.messages.ServiceMeshMembershipSpec.ConfigApiValueValuesEnum(
'CONFIG_API_GATEWAY'
)
)
patch.mesh.configApi = config_api
membership_specs[membership] = patch
f = cmd.messages.Feature(
membershipSpecs=cmd.hubclient.ToMembershipSpecs(membership_specs)
)
if args.fleet_default_member_config:
# Load config YAML file.
loaded_config = file_parsers.YamlConfigFile(
file_path=args.fleet_default_member_config,
item_type=utils.FleetDefaultMemberConfigObject,
)
# Create new service mesh feature spec.
member_config = utils.ParseFleetDefaultMemberConfig(
loaded_config, cmd.messages
)
f.fleetDefaultMemberConfig = (
cmd.messages.CommonFleetDefaultMemberConfigSpec(mesh=member_config)
)
update_mask.append('fleet_default_member_config')
cmd.Update(update_mask, f)
# LINT.ThenChange(:update_v2)
@base.DefaultUniverseOnly
@base.ReleaseTracks(base.ReleaseTrack.ALPHA)
class UpdateAlpha(features_base.UpdateCommand, mf_base.UpdateCommand):
"""Update the configuration of the Service Mesh Feature.
Update the Service Mesh Feature Spec of a membership.
## EXAMPLES
To update the control plane management of comma separated memberships like
`MEMBERSHIP1,MEMBERSHIP2`, run:
$ {command} --memberships=MEMBERSHIP1,MEMBERSHIP2
--control-plane=CONTROL_PLANE
"""
feature_name = 'servicemesh'
mf_name = 'servicemesh'
@staticmethod
def Args(parser):
args_group = parser.add_mutually_exclusive_group(required=True)
args_group.add_argument(
'--fleet-default-member-config',
type=str,
help="""The path to a service-mesh.yaml configuration file.
To enable the Service Mesh Feature with a fleet-level default
membership configuration, run:
$ {command} --fleet-default-member-config=/path/to/service-mesh.yaml""",
)
membership_group = args_group.add_group(
'Component options',
)
membership_names_group = membership_group.add_mutually_exclusive_group()
resources.AddMembershipResourceArg(
membership_names_group,
plural=True,
membership_help=(
'Membership names to update, separated by commas if '
'multiple are supplied.'
),
)
membership_names_group.add_argument(
'--membership',
type=str,
help='Membership name to update.',
action=actions.DeprecationAction(
'--membership',
warn=(
'The {flag_name} flag is now '
'deprecated. Please use `--memberships` '
'instead.'
),
),
)
membership_config_group = membership_group.add_group(required=True)
membership_config_group.add_argument(
'--origin',
choices=['fleet'],
help='Changing the origin of the membership.',
)
membership_controlplane_group = (
membership_config_group.add_mutually_exclusive_group()
)
membership_controlplane_group.add_argument(
'--config-api',
choices=['istio', 'gateway'],
help='The API to use for mesh configuration.',
)
membership_controlplane_group.add_argument(
'--management',
choices=['automatic', 'manual', 'not_installed'],
help='The management mode to update to.',
)
membership_controlplane_group.add_argument(
'--control-plane',
choices=['automatic', 'manual', 'unspecified'],
help='Control plane management to update to.',
action=actions.DeprecationAction(
'--control-plane',
warn=(
'The {flag_name} flag is now '
'deprecated. Please use `--management` '
'instead. '
'See https://cloud.google.com/service-mesh/docs/managed/provision-managed-anthos-service-mesh'
),
),
)
def Run(self, args):
# If the user is using the fleet default config, we will still use the v1
# Feature API for the update.
use_fleet_default_config = (
hasattr(args, 'origin')
and args.origin == 'fleet'
)
if not use_fleet_default_config:
_RunUpdateV2(self, args)
else:
_RunUpdate(self, args)
@base.DefaultUniverseOnly
@base.ReleaseTracks(base.ReleaseTrack.BETA, base.ReleaseTrack.GA)
class UpdateGA(features_base.UpdateCommand, mf_base.UpdateCommand):
"""Update the configuration of the Service Mesh Feature.
Update the Service Mesh Feature Spec of a Membership.
## EXAMPLES
To update the control plane management of comma separated Memberships like
`membership1,membership2`, run:
$ {command} --memberships=membership1,membership2
--control-plane=CONTROL_PLANE
"""
feature_name = 'servicemesh'
mf_name = 'servicemesh'
@staticmethod
def Args(parser):
args_group = parser.add_mutually_exclusive_group(required=True)
args_group.add_argument(
'--fleet-default-member-config',
type=str,
help="""The path to a service-mesh.yaml configuration file.
To enable the Service Mesh Feature with a fleet-level default
membership configuration, run:
$ {command} --fleet-default-member-config=/path/to/service-mesh.yaml""",
)
membership_group = args_group.add_group()
membership_names_group = membership_group.add_mutually_exclusive_group()
resources.AddMembershipResourceArg(
membership_names_group,
plural=True,
membership_help=(
'Membership names to update, separated by commas if '
'multiple are supplied.'
),
)
membership_configs_group = membership_group.add_group(required=True)
membership_configs_group.add_argument(
'--origin',
choices=['fleet'],
help='Changing the origin of the membership.',
)
membership_controlplane_group = (
membership_configs_group.add_mutually_exclusive_group()
)
membership_controlplane_group.add_argument(
'--config-api',
choices=['istio', 'gateway'],
help='The API to use for mesh configuration.',
)
membership_controlplane_group.add_argument(
'--management',
choices=['automatic', 'manual'],
help='The management mode to update to.',
)
membership_controlplane_group.add_argument(
'--control-plane',
choices=['automatic', 'manual', 'unspecified'],
help='Control plane management to update to.',
action=actions.DeprecationAction(
'--control-plane',
warn=(
'The {flag_name} flag is now '
'deprecated. Please use `--management` '
'instead. '
'See https://cloud.google.com/service-mesh/docs/managed/provision-managed-anthos-service-mesh'
),
),
)
def Run(self, args):
# If the user is using the fleet default config, we will still use the v1
# Feature API for the update.
use_fleet_default_config = (
hasattr(args, 'origin')
and args.origin == 'fleet'
)
if not use_fleet_default_config:
_RunUpdateV2(self, args)
else:
_RunUpdate(self, args)