feat: Add new gcloud commands, API clients, and third-party libraries across various services.

This commit is contained in:
2026-01-01 20:26:35 +01:00
parent 5e23cbece0
commit a19e592eb7
25221 changed files with 8324611 additions and 0 deletions

View File

@@ -0,0 +1,107 @@
# -*- coding: utf-8 -*- #
# Copyright 2014 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 main command group for cloud container."""
from __future__ import absolute_import
from __future__ import division
from __future__ import unicode_literals
from googlecloudsdk.api_lib.container import api_adapter
from googlecloudsdk.calliope import base
@base.ReleaseTracks(base.ReleaseTrack.GA)
class Container(base.Group):
"""Deploy and manage clusters of machines for running containers.
The gcloud container command group lets you create and manage Google
Kubernetes Engine containers and clusters.
Kubernetes Engine is a cluster manager and orchestration system for
running your Docker containers. Kubernetes Engine schedules your containers
into the cluster and manages them automatically based on requirements you
define, such as CPU and memory.
More information on Kubernetes Engine can be found here:
https://cloud.google.com/kubernetes-engine and detailed documentation
can be found here: https://cloud.google.com/kubernetes-engine/docs/
"""
category = base.COMPUTE_CATEGORY
def Filter(self, context, args):
"""Modify the context that will be given to this group's commands when run.
Args:
context: {str:object}, A set of key-value pairs that can be used for
common initialization among commands.
args: argparse.Namespace: The same namespace given to the corresponding
.Run() invocation.
Returns:
The refined command context.
"""
base.DisableUserProjectQuota()
context['api_adapter'] = api_adapter.NewAPIAdapter('v1')
return context
@base.ReleaseTracks(base.ReleaseTrack.BETA)
class ContainerBeta(Container):
"""Deploy and manage clusters of machines for running containers."""
def Filter(self, context, args):
"""Modify the context that will be given to this group's commands when run.
Args:
context: {str:object}, A set of key-value pairs that can be used for
common initialization among commands.
args: argparse.Namespace: The same namespace given to the corresponding
.Run() invocation.
Returns:
The refined command context.
"""
base.DisableUserProjectQuota()
context['api_adapter'] = api_adapter.NewAPIAdapter('v1beta1')
self.EnableSelfSignedJwtForTracks([base.ReleaseTrack.BETA])
return context
@base.ReleaseTracks(base.ReleaseTrack.ALPHA)
class ContainerAlpha(Container):
"""Deploy and manage clusters of machines for running containers."""
def Filter(self, context, args):
"""Modify the context that will be given to this group's commands when run.
Args:
context: {str:object}, A set of key-value pairs that can be used for
common initialization among commands.
args: argparse.Namespace: The same namespace given to the corresponding
.Run() invocation.
Returns:
The refined command context.
"""
base.DisableUserProjectQuota()
context['api_adapter'] = api_adapter.NewAPIAdapter('v1alpha1')
# Enable self signed jwt for alpha track
self.EnableSelfSignedJwtForTracks([base.ReleaseTrack.ALPHA])
return context

View File

@@ -0,0 +1,31 @@
# -*- coding: utf-8 -*- #
# Copyright 2025 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 group for the AI CLI."""
from __future__ import absolute_import
from __future__ import division
from __future__ import unicode_literals
from googlecloudsdk.calliope import base
from googlecloudsdk.command_lib.projects import util
@base.UniverseCompatible
@base.ReleaseTracks(base.ReleaseTrack.ALPHA, base.ReleaseTrack.GA)
class AI(base.Group):
"""Manage AI related workloads for GKE."""
category = base.SDK_TOOLS_CATEGORY

View File

@@ -0,0 +1,45 @@
# -*- coding: utf-8 -*- #
# Copyright 2025 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 group for the profiles CLI."""
from __future__ import absolute_import
from __future__ import division
from __future__ import unicode_literals
from googlecloudsdk.calliope import base
from googlecloudsdk.command_lib.projects import util
@base.UniverseCompatible
@base.ReleaseTracks(base.ReleaseTrack.ALPHA, base.ReleaseTrack.GA)
class Profiles(base.Group):
"""Quickstart engine for GKE AI workloads.
The GKE Inference Quickstart helps simplify deploying AI inference on Google
Kubernetes Engine (GKE). It provides tailored profiles based on
Google's internal benchmarks. Provide inputs like your preferred open-source
model (e.g. Llama, Gemma, or Mistral) and your application's performance
target. Based on these inputs, the quickstart generates accelerator choices
with performance metrics, and detailed, ready-to-deploy profiles for
compute, load balancing, and autoscaling. These profiles are provided
as standard Kubernetes YAML manifests, which you can deploy or modify.
To visualize the benchmarking data that support these estimates, see the
accompanying Colab notebook:
https://colab.research.google.com/github/GoogleCloudPlatform/kubernetes-engine-samples/blob/main/ai-ml/notebooks/giq_visualizations.ipynb
"""
category = base.SDK_TOOLS_CATEGORY

View File

@@ -0,0 +1,29 @@
# -*- coding: utf-8 -*- #
# Copyright 2025 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 group for the accelerators CLI."""
from __future__ import absolute_import
from __future__ import division
from __future__ import unicode_literals
from googlecloudsdk.calliope import base
from googlecloudsdk.command_lib.projects import util
@base.UniverseCompatible
@base.ReleaseTracks(base.ReleaseTrack.ALPHA)
class ModelServers(base.Group):
"""Manage supported accelerators for GKE Inference Quickstart."""

View File

@@ -0,0 +1,190 @@
# -*- coding: utf-8 -*- #
# Copyright 2025 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.
"""Lists compatible accelerator profiles for GKE Inference Quickstart."""
from googlecloudsdk.api_lib.ai.recommender import util
from googlecloudsdk.calliope import base
from googlecloudsdk.command_lib.run import commands
from googlecloudsdk.command_lib.run.printers import profiles_printer
from googlecloudsdk.core import exceptions
from googlecloudsdk.core import log
from googlecloudsdk.core.resource import resource_printer
_EXAMPLES = """
To list compatible accelerator profiles for a model, run:
$ {command} --model=deepseek-ai/DeepSeek-R1-Distill-Qwen-7B
"""
def decimal_to_amount(decimal_value):
"""Converts a decimal representation to an Amount proto."""
units = int(decimal_value)
nanos = int((decimal_value - units) * 1e9)
return (units, nanos)
@base.DefaultUniverseOnly
@base.ReleaseTracks(base.ReleaseTrack.ALPHA)
class List(commands.List):
"""List compatible accelerator profiles.
This command lists all supported accelerators with their performance details.
By default, the supported accelerators are displayed in a table format with
select information for each accelerator. To see all details, use
--format=yaml.
To get supported model, model servers, and model server versions, run `gcloud
alpha container ai profiles models list`, `gcloud alpha container ai
profiles model-servers list`, and `gcloud alpha container ai profiles
model-server-versions list`.
Alternatively, run `gcloud alpha container ai profiles
model-and-server-combinations list` to get all supported model and server
combinations.
"""
@staticmethod
def Args(parser):
parser.add_argument(
"--model",
required=True,
help="The model.",
)
parser.add_argument(
"--model-server",
help=(
"The model server. If not specified, this defaults to any model"
" server."
),
)
parser.add_argument(
"--model-server-version",
help=(
"The model server version. If not specified, this defaults to the"
" latest version."
),
)
parser.add_argument(
"--max-ntpot-milliseconds",
type=int,
help=(
"The maximum normalized time per output token (NTPOT) in"
" milliseconds. NTPOT is measured as the request_latency /"
" output_tokens. If this field is set, the command will only return"
" accelerators that can meet the target ntpot milliseconds and"
" display their throughput performance at the target latency."
" Otherwise, the command will return all accelerators and display"
" their highest throughput performance."
),
)
parser.add_argument(
"--target-cost-per-million-output-tokens",
hidden=True,
type=float,
required=False,
help=(
"The target cost per million output tokens to filter profiles by,"
" unit is 1 USD up to 5 decimal places."
),
)
parser.add_argument(
"--target-cost-per-million-input-tokens",
hidden=True,
type=float,
required=False,
help=(
"The target cost per million input tokens to filter profiles by,"
" unit is 1 USD up to 5 decimal places."
),
)
parser.add_argument(
"--pricing-model",
hidden=True,
required=False,
type=str,
help=(
"The pricing model to use to calculate token cost. Currently, this"
" supports on-demand, spot, 3-years-cud, 1-year-cud"
),
)
parser.add_argument(
"--format",
type=str,
help="The format to use for the output. Default is table. yaml|table",
)
resource_printer.RegisterFormatter(
profiles_printer.PROFILES_PRINTER_FORMAT,
profiles_printer.ProfilePrinter,
)
parser.display_info.AddFormat(profiles_printer.PROFILES_PRINTER_FORMAT)
parser.display_info.AddFormat(
"table("
"acceleratorType,"
"modelAndModelServerInfo.modelName,"
"modelAndModelServerInfo.modelServerName,"
"modelAndModelServerInfo.modelServerVersion,"
"resourcesUsed.acceleratorCount,"
"performanceStats.outputTokensPerSecond,"
"performanceStats.ntpotMilliseconds"
")"
)
def Run(self, args):
client = util.GetClientInstance(base.ReleaseTrack.ALPHA)
messages = util.GetMessagesModule(base.ReleaseTrack.ALPHA)
try:
request = messages.GkerecommenderAcceleratorsListRequest(
modelName=args.model,
modelServerName=args.model_server,
modelServerVersion=args.model_server_version,
performanceRequirements_maxNtpotMilliseconds=args.max_ntpot_milliseconds,
performanceRequirements_cost_pricingModel=args.pricing_model,
)
if args.target_cost_per_million_output_tokens:
units, nanos = decimal_to_amount(
args.target_cost_per_million_output_tokens
)
request.performanceRequirements_cost_costPerMillionNormalizedOutputTokens_units = (
units
)
request.performanceRequirements_cost_costPerMillionNormalizedOutputTokens_nanos = (
nanos
)
if args.target_cost_per_million_input_tokens:
units, nanos = decimal_to_amount(
args.target_cost_per_million_input_tokens
)
request.performanceRequirements_cost_costPerMillionInputTokens_units = (
units
)
request.performanceRequirements_cost_costPerMillionInputTokens_nanos = (
nanos
)
response = client.accelerators.List(request)
self.comments = response.comments
if response:
return response
else:
return []
except exceptions.Error as e:
log.error(f"An error has occurred: {e}")
log.status.Print(f"An error has occurred: {e}")
return []

View File

@@ -0,0 +1,29 @@
# -*- coding: utf-8 -*- #
# Copyright 2025 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 group for the benchmarks CLI."""
from __future__ import absolute_import
from __future__ import division
from __future__ import unicode_literals
from googlecloudsdk.calliope import base
from googlecloudsdk.command_lib.projects import util
@base.UniverseCompatible
@base.ReleaseTracks(base.ReleaseTrack.GA)
class Benchmarks(base.Group):
"""Manage benchmarks for GKE Inference Quickstart."""

View File

@@ -0,0 +1,179 @@
# -*- coding: utf-8 -*- #
# Copyright 2025 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.
"""Outputs benchmarking data for GKE Inference Quickstart."""
from apitools.base.py import exceptions as apitools_exceptions
from googlecloudsdk.api_lib.ai.recommender import util
from googlecloudsdk.api_lib.util import exceptions
from googlecloudsdk.calliope import base
from googlecloudsdk.command_lib.run import commands
from googlecloudsdk.command_lib.run.printers import profiles_csv_printer
from googlecloudsdk.core.resource import resource_printer
_EXAMPLE = """
To get benchmarking data for a given model and model server, run:
$ {command} --model=google/gemma-2-27b-it --model-server=vllm --pricing-model=spot
"""
def amount_to_decimal(cost):
"""Converts cost to a decimal representation."""
units = cost.units
if not units:
units = 0
decimal_value = +(units + cost.nanos / 1e9)
return f"{decimal_value:.3f}"
def get_decimal_cost(costs):
"""Returns the cost per million normalized output tokens as a decimal.
Args:
costs: The costs to convert.
"""
output_token_cost = "N/A"
if costs and costs[0].costPerMillionOutputTokens:
output_token_cost = amount_to_decimal(costs[0].costPerMillionOutputTokens)
input_token_cost = "N/A"
if costs and costs[0].costPerMillionInputTokens:
input_token_cost = amount_to_decimal(costs[0].costPerMillionInputTokens)
return (input_token_cost, output_token_cost)
@base.DefaultUniverseOnly
@base.ReleaseTracks(base.ReleaseTrack.GA)
class List(commands.List):
"""List benchmarks for a given model and model server.
This command lists all benchmarking data for a given model and model server.
By default, the benchmarks are displayed in a CSV format.
For examples of visualizing the benchmarking data, see the accompanying Colab
notebook:
https://colab.research.google.com/github/GoogleCloudPlatform/kubernetes-engine-samples/blob/main/ai-ml/notebooks/giq_visualizations.ipynb
"""
@staticmethod
def Args(parser):
parser.add_argument(
"--model",
required=True,
help="The model.",
)
parser.add_argument(
"--model-server",
required=True,
help="The model server.",
)
parser.add_argument(
"--model-server-version",
help=(
"The model server version. Default is latest. Other options include"
" the model server version of a profile, all which returns all"
" versions."
),
)
parser.add_argument(
"--instance-type",
help=(
"The instance type. If not specified, this defaults to any"
"instance type."
),
)
parser.add_argument(
"--format",
help=(
"The format to print the output in. Default is csvprofile, which"
" displays the profile information in a CSV format, including"
"cost conversions."
),
)
parser.add_argument(
"--pricing-model",
required=False,
help=(
"The pricing model to use to calculate token cost. Currently, this"
" supports on-demand, spot, 3-years-cud, 1-year-cud"
),
)
parser.add_argument(
"--use-case",
required=False,
help=(
"If specified, results will only show profiles that match the"
" provided use case. Options are: Advanced Customer Support, Code"
" Completion, Text Summarization, Chatbot (ShareGPT), Code"
" Generation, Deep Research."
),
)
parser.add_argument(
"--serving-stack",
required=False,
help=(
"The serving stack to filter benchmarking data by. If not"
" provided, benchmarking data for all serving stacks that support"
" the given model and model server will be returned."
),
)
parser.add_argument(
"--serving-stack-version",
required=False,
help=(
"The serving stack version to filter benchmarking data by. If not"
" provided, benchmarking data for all versions that support"
" the given model and model server will be returned."
),
)
resource_printer.RegisterFormatter(
profiles_csv_printer.PROFILES_PRINTER_FORMAT,
profiles_csv_printer.ProfileCSVPrinter,
)
parser.display_info.AddFormat(profiles_csv_printer.PROFILES_PRINTER_FORMAT)
def Run(self, args):
client = util.GetClientInstance(base.ReleaseTrack.GA)
messages = util.GetMessagesModule(base.ReleaseTrack.GA)
try:
model_server_info = messages.ModelServerInfo(
model=args.model,
modelServer=args.model_server,
modelServerVersion=args.model_server_version,
)
serving_stack = None
if args.serving_stack:
serving_stack = messages.ServingStack(
name=args.serving_stack,
)
if args.serving_stack_version:
serving_stack.version = args.serving_stack_version
request = messages.FetchBenchmarkingDataRequest(
modelServerInfo=model_server_info,
instanceType=args.instance_type,
pricingModel=args.pricing_model,
useCase=args.use_case,
servingStack=serving_stack,
)
response = client.benchmarkingData.Fetch(request)
if not response.profile:
return []
else:
return response.profile
except apitools_exceptions.HttpError as error:
raise exceptions.HttpException(error, util.HTTP_ERROR_FORMAT)

View File

@@ -0,0 +1,323 @@
# -*- coding: utf-8 -*- #
# Copyright 2025 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.
"""Lists compatible accelerator profiles for GKE Inference Quickstart."""
from apitools.base.py import exceptions as apitools_exceptions
from googlecloudsdk.api_lib.ai.recommender import util
from googlecloudsdk.api_lib.util import exceptions
from googlecloudsdk.calliope import base
from googlecloudsdk.command_lib.run import commands
from googlecloudsdk.command_lib.run.printers import profiles_csv_printer
from googlecloudsdk.command_lib.run.printers import profiles_printer_ga as profiles_printer
from googlecloudsdk.core.resource import resource_printer
_EXAMPLES = """
To list compatible accelerator profiles for a model, run:
$ {command} --model=deepseek-ai/DeepSeek-R1-Distill-Qwen-7B
"""
def decimal_to_amount(decimal_value):
"""Converts a decimal representation to an Amount proto."""
units = int(decimal_value)
nanos = int((decimal_value - units) * 1e9)
return (units, nanos)
def amount_to_decimal(cost):
"""Converts cost to a decimal representation."""
units = cost.units
if not units:
units = 0
decimal_value = +(units + cost.nanos / 1e9)
return f"{decimal_value:.3f}"
def get_decimal_cost(costs):
"""Returns the cost per million normalized output tokens as a decimal.
Args:
costs: The costs to convert.
"""
output_token_cost = "N/A"
if costs and costs[0].costPerMillionOutputTokens:
output_token_cost = amount_to_decimal(
costs[0].costPerMillionOutputTokens
)
input_token_cost = "N/A"
if costs and costs[0].costPerMillionInputTokens:
input_token_cost = amount_to_decimal(costs[0].costPerMillionInputTokens)
return (input_token_cost, output_token_cost)
@base.DefaultUniverseOnly
@base.ReleaseTracks(base.ReleaseTrack.GA)
class List(commands.List):
"""List compatible accelerator profiles.
This command lists all supported accelerators with their performance details.
By default, the supported accelerators are displayed in a table format with
select information for each accelerator. To see all details, use
--format=yaml or --format=csvprofile.
To get supported model, model servers, and model server versions, run `gcloud
container ai profiles models list`, `gcloud container ai
profiles model-servers list`, and `gcloud container ai profiles
model-server-versions list`.
"""
@staticmethod
def Args(parser):
parser.add_argument(
"--model",
help="The model.",
)
parser.add_argument(
"--model-server",
help=(
"The model server version. Default is latest. Other options include"
" the model server version of a profile, all which returns all"
" versions."
),
)
parser.add_argument(
"--model-server-version",
help=(
"The model server version. If not specified, this defaults to the"
" latest version."
),
)
parser.add_argument(
"--target-ntpot-milliseconds",
type=int,
help=(
"The target normalized time per output token (NTPOT) in"
" milliseconds. NTPOT is measured as the request_latency /"
" output_tokens. If this field is set, the command will only return"
" accelerators that can meet the target ntpot milliseconds and"
" display their throughput performance at the target latency."
" Otherwise, the command will return all accelerators and display"
" their highest throughput performance."
),
)
parser.add_argument(
"--target-ttft-milliseconds",
type=int,
help=(
"The target time to first token (TTFT) in"
" milliseconds. TTFT is measured as the request_latency /"
" output_tokens. If this field is set, the command will only return"
" profiles that can meet the target ttft milliseconds and"
" display their throughput performance at the target latency."
" Otherwise, the command will return all profiles and display"
" their highest throughput performance."
),
)
parser.add_argument(
"--target-itl-milliseconds",
type=int,
help=(
"If specified, results will only show profiles with instance types"
" that can meet the latency target and will show their throughput"
" performances at the target inter-token latency (ITL)."
),
)
parser.add_argument(
"--target-cost-per-million-output-tokens",
type=float,
required=False,
help=(
"The target cost per million output tokens to filter profiles by,"
" unit is 1 USD up to 5 decimal places."
),
)
parser.add_argument(
"--target-cost-per-million-input-tokens",
type=float,
required=False,
help=(
"The target cost per million input tokens to filter profiles by,"
" unit is 1 USD up to 5 decimal places."
),
)
parser.add_argument(
"--pricing-model",
required=False,
type=str,
help=(
"The pricing model to use to calculate token cost. Currently, this"
" supports on-demand, spot, 3-years-cud, 1-year-cud"
),
)
parser.add_argument(
"--format",
help=(
"The output format. Default is profile, which displays the profile"
" information in a table format, including cost conversions."
" csvprofile displays the profile information in a CSV"
" format.Options include csvprofile, profile, and yaml. "
),
)
parser.add_argument(
"--use-case",
required=False,
type=str,
help=(
" If specified, results will only show profiles that match the"
" provided use case. Options are: Advanced Customer Support, Code"
" Completion, Text Summarization, Chatbot (ShareGPT), Text"
" Generation, Deep Research"
),
)
parser.add_argument(
"--target-input-length",
required=False,
type=int,
help=(
" If specified, results will only show profiles that have an input"
" length within 20% of the specified one. Only works alongside"
" output length."
),
)
parser.add_argument(
"--target-output-length",
required=False,
type=int,
help=(
"If specified, results will only show profiles that have an output"
" length within 20% of the specified one. Only works alongside"
" input length."
),
)
parser.add_argument(
"--serving-stack",
required=False,
help=(
"The serving stack to filter profiles by. If not"
" provided, profiles for all serving stacks that support"
" the given model and model server will be returned."
),
)
parser.add_argument(
"--serving-stack-version",
required=False,
help=(
"The serving stack version to filter profiles by. If not"
" provided, profiles for all versions that support"
" the given model and model server will be returned."
),
)
resource_printer.RegisterFormatter(
profiles_printer.PROFILES_PRINTER_FORMAT,
profiles_printer.ProfilePrinter,
)
resource_printer.RegisterFormatter(
profiles_csv_printer.PROFILES_PRINTER_FORMAT,
profiles_csv_printer.ProfileCSVPrinter,
)
parser.display_info.AddFormat(profiles_printer.PROFILES_PRINTER_FORMAT)
def Run(self, args):
client = util.GetClientInstance(base.ReleaseTrack.GA)
messages = util.GetMessagesModule(base.ReleaseTrack.GA)
performance_requirements = messages.PerformanceRequirements()
workload_spec = messages.WorkloadSpec()
if args.target_ntpot_milliseconds:
performance_requirements.targetNtpotMilliseconds = (
args.target_ntpot_milliseconds
)
if args.target_ttft_milliseconds:
performance_requirements.targetTtftMilliseconds = (
args.target_ttft_milliseconds
)
if args.target_itl_milliseconds:
performance_requirements.targetItlMilliseconds = (
args.target_itl_milliseconds
)
if args.use_case:
workload_spec.useCase = (
args.use_case
)
if args.target_input_length:
workload_spec.averageInputLength = (
args.target_input_length
)
if args.target_output_length:
workload_spec.averageOutputLength = (
args.target_output_length
)
if (
args.target_cost_per_million_output_tokens
or args.target_cost_per_million_input_tokens
or args.pricing_model
):
cost = messages.Cost()
if args.target_cost_per_million_output_tokens:
units, nanos = decimal_to_amount(
args.target_cost_per_million_output_tokens
)
cost.costPerMillionOutputTokens = messages.Amount(
units=units, nanos=nanos
)
if args.target_cost_per_million_input_tokens:
units, nanos = decimal_to_amount(
args.target_cost_per_million_input_tokens
)
cost.costPerMillionInputTokens = messages.Amount(
units=units, nanos=nanos
)
if args.pricing_model:
cost.pricingModel = args.pricing_model
performance_requirements.targetCost = cost
serving_stack = None
if args.serving_stack:
serving_stack = messages.ServingStack(
name=args.serving_stack,
)
if args.serving_stack_version:
serving_stack.version = args.serving_stack_version
try:
request = messages.FetchProfilesRequest(
model=args.model,
modelServer=args.model_server,
modelServerVersion=args.model_server_version,
servingStack=serving_stack,
)
if (
performance_requirements.targetNtpotMilliseconds is not None
or performance_requirements.targetTtftMilliseconds is not None
or performance_requirements.targetCost is not None
):
request.performanceRequirements = performance_requirements
if (
workload_spec.useCase is not None
or workload_spec.averageInputLength is not None
or workload_spec.averageOutputLength is not None
):
request.workloadSpec = workload_spec
response = client.profiles.Fetch(request)
if response.profile:
return response.profile
else:
return []
except apitools_exceptions.HttpError as error:
raise exceptions.HttpException(error, util.HTTP_ERROR_FORMAT)

View File

@@ -0,0 +1,29 @@
# -*- coding: utf-8 -*- #
# Copyright 2025 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 group for the manifests CLI."""
from __future__ import absolute_import
from __future__ import division
from __future__ import unicode_literals
from googlecloudsdk.calliope import base
from googlecloudsdk.command_lib.projects import util
@base.UniverseCompatible
@base.ReleaseTracks(base.ReleaseTrack.ALPHA, base.ReleaseTrack.GA)
class Manifests(base.Group):
"""Generate optimized Kubernetes manifests."""

View File

@@ -0,0 +1,358 @@
# -*- coding: utf-8 -*- #
# Copyright 2025 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.
"""Generates optimized Kubernetes manifests for GKE Inference Quickstart."""
from apitools.base.py import exceptions as apitools_exceptions
from googlecloudsdk.api_lib.ai.recommender import util
from googlecloudsdk.api_lib.util import exceptions as api_lib_exceptions
from googlecloudsdk.calliope import base
from googlecloudsdk.core import exceptions
from googlecloudsdk.core import log
from googlecloudsdk.core.util import files
@base.DefaultUniverseOnly
@base.ReleaseTracks(base.ReleaseTrack.GA)
class Create(base.CreateCommand):
"""Generate ready-to-deploy Kubernetes manifests with compute, load balancing, and autoscaling capabilities.
To get supported model, model servers, and model server versions, run `gcloud
alpha container ai profiles model-and-server-combinations list`. To get
supported accelerators with their performance metrics, run `gcloud alpha
container ai profiles accelerators list`.
"""
@staticmethod
def Args(parser):
parser.add_argument(
"--model",
required=True,
help="The model.",
)
parser.add_argument(
"--model-server",
required=True,
help="The model server.",
)
parser.add_argument(
"--model-server-version",
help=(
"The model server version. If not specified, this defaults to the"
" latest version."
),
)
parser.add_argument(
"--target-ntpot-milliseconds",
type=int,
help=(
"The maximum normalized time per output token (NTPOT) in"
" milliseconds. NTPOT is measured as the request_latency /"
" output_tokens. If this is set, the manifests will include"
" Horizontal Pod Autoscaler (HPA) resources which automatically"
" adjust the model server replica count in response to changes in"
" model server load to keep p50 NTPOT below the specified"
" threshold. If the provided target-ntpot-milliseconds is too low"
" to achieve, the HPA manifest will not be generated. "
),
)
parser.add_argument(
"--target-ttft-milliseconds",
type=int,
help=(
"If specified, results will only show accelerators that can meet"
" the latency target and will show their throughput performances at"
" the target ttft target to achieve, the HPA manifest will not be"
" generated. "
),
)
parser.add_argument(
"--accelerator-type",
required=True,
help="The accelerator type.",
)
parser.add_argument(
"--namespace",
help=(
"The namespace to deploy the manifests in. Default namespace is"
" 'default'."
),
)
parser.add_argument(
"--output",
choices=["manifest", "comments", "all"],
default="all",
help="The output to display. Default is all.",
)
parser.add_argument(
"--output-path",
help=(
"The path to save the output to. If not specified, output to the"
" terminal."
),
)
parser.add_argument(
"--model-bucket-uri",
help=(
"The Google Cloud Storage bucket URI to load the model from. This"
" URI must point to the directory containing the model's config"
" file (config.json) and model weights. If unspecified, defaults to"
" loading the model from Hugging Face."
),
)
parser.add_argument(
"--target-itl-milliseconds",
type=int,
help=(
"The target inter-token latency (ITL) in milliseconds. If this is"
" set, the manifest will include Horizontal Pod Autoscaler (HPA)"
" resources which automatically adjust the model server replica"
" count in response to changes in model server load to keep p50 ITL"
" below the specified threshold. If the provided"
" target-itl-milliseconds is too low to achieve, the HPA manifest"
" will not be generated."
),
)
parser.add_argument(
"--use-case",
help=(
"The manifest will be optimized for this use case. Options are:"
" Advanced Customer Support, Code Completion, Text Summarization,"
" Chatbot (ShareGPT), Code Generation, Deep Research. Will default"
" to Chatbot if not specified."
),
)
parser.add_argument(
"--serving-stack",
required=False,
help=(
"The serving stack to filter manifests by. If not"
" provided, manifests for all serving stacks that support"
" the given model and model server will be considered."
),
)
parser.add_argument(
"--serving-stack-version",
required=False,
help=(
"The serving stack version to filter manifests by. If not"
" provided, manifests for all versions that support"
" the given model and model server will be considered."
),
)
def Run(self, args):
client = util.GetClientInstance(base.ReleaseTrack.GA)
messages = util.GetMessagesModule(base.ReleaseTrack.GA)
try:
model_server_info = messages.ModelServerInfo(
model=args.model,
modelServer=args.model_server,
modelServerVersion=args.model_server_version,
)
performance_requirements = messages.PerformanceRequirements()
if args.target_ntpot_milliseconds:
performance_requirements.targetNtpotMilliseconds = (
args.target_ntpot_milliseconds
)
if args.target_ttft_milliseconds:
performance_requirements.targetTtftMilliseconds = (
args.target_ttft_milliseconds
)
if args.target_itl_milliseconds:
performance_requirements.targetItlMilliseconds = (
args.target_itl_milliseconds
)
storage_config = messages.StorageConfig()
if args.model_bucket_uri:
storage_config.modelBucketUri = args.model_bucket_uri
serving_stack = None
if args.serving_stack:
serving_stack = messages.ServingStack(
name=args.serving_stack,
)
if args.serving_stack_version:
serving_stack.version = args.serving_stack_version
request = messages.GenerateOptimizedManifestRequest(
modelServerInfo=model_server_info,
acceleratorType=args.accelerator_type,
kubernetesNamespace=args.namespace,
servingStack=serving_stack,
)
if (
performance_requirements.targetNtpotMilliseconds is not None
or performance_requirements.targetTtftMilliseconds is not None
or performance_requirements.targetItlMilliseconds is not None
):
request.performanceRequirements = performance_requirements
if storage_config.modelBucketUri is not None:
request.storageConfig = storage_config
if args.use_case:
request.useCase = args.use_case
response = client.optimizedManifest.Generate(request)
return response
except apitools_exceptions.HttpError as error:
raise api_lib_exceptions.HttpException(error, util.HTTP_ERROR_FORMAT)
def Display(self, args, resources):
if not resources:
log.out.Print("No manifests generated.")
return
output_content = ""
if args.output != "comments":
for manifest in resources.kubernetesManifests:
output_content += manifest.content + "\n---\n"
if resources.comments:
comment_string = "\n".join([f"# {line}" for line in resources.comments])
output_content += comment_string
if args.output_path:
try:
with files.FileWriter(args.output_path, output_content) as f:
f.write(output_content)
log.out.Print(f"Output saved to {args.output_path}")
except exceptions.Error as e:
log.error(f"An error occurred while saving output to file: {e}")
else:
log.out.Print(output_content)
@base.DefaultUniverseOnly
@base.ReleaseTracks(base.ReleaseTrack.ALPHA)
class CreateAlpha(base.CreateCommand):
"""Generate ready-to-deploy Kubernetes manifests with compute, load balancing, and autoscaling capabilities.
To get supported model, model servers, and model server versions, run `gcloud
alpha container ai profiles model-and-server-combinations list`. To get
supported accelerators with their performance metrics, run `gcloud alpha
container ai profiles accelerators list`.
"""
@staticmethod
def Args(parser):
parser.add_argument(
"--model",
required=True,
help="The model.",
)
parser.add_argument(
"--model-server",
required=True,
help="The model server.",
)
parser.add_argument(
"--model-server-version",
help=(
"The model server version. If not specified, this defaults to the"
" latest version."
),
)
parser.add_argument(
"--target-ntpot-milliseconds",
type=int,
help=(
"The maximum normalized time per output token (NTPOT) in"
" milliseconds. NTPOT is measured as the request_latency /"
" output_tokens. If this is set, the manifests will include"
" Horizontal Pod Autoscaler (HPA) resources which automatically"
" adjust the model server replica count in response to changes in"
" model server load to keep p50 NTPOT below the specified"
" threshold. If the provided target-ntpot-milliseconds is too low"
" to achieve, the HPA manifest will not be generated. "
),
)
parser.add_argument(
"--accelerator-type",
required=True,
help="The accelerator type.",
)
parser.add_argument(
"--namespace",
help=(
"The namespace to deploy the manifests in. Default namespace is"
" 'default'."
),
)
parser.add_argument(
"--output",
choices=["manifest", "comments", "all"],
default="all",
help="The output to display. Default is all.",
)
parser.add_argument(
"--output-path",
help=(
"The path to save the output to. If not specified, output to the"
" terminal."
),
)
parser.add_argument(
"--model-bucket-uri",
hidden=True,
help=(
"GCS bucket URI to pull model from. If not specified, default"
" to the model hoster."
),
)
def Run(self, args):
client = util.GetClientInstance(base.ReleaseTrack.ALPHA)
messages = util.GetMessagesModule(base.ReleaseTrack.ALPHA)
try:
request = messages.GkerecommenderOptimizedManifestRequest(
modelAndModelServerInfo_modelName=args.model,
modelAndModelServerInfo_modelServerName=args.model_server,
modelAndModelServerInfo_modelServerVersion=args.model_server_version,
targetNtpotMilliseconds=args.target_ntpot_milliseconds,
acceleratorType=args.accelerator_type,
kubernetesNamespace=args.namespace,
storageConfig_modelBucketUri=args.model_bucket_uri,
)
response = client.v1alpha1.OptimizedManifest(request)
return response
except exceptions.Error as e:
log.error(f"An error has occurred: {e}")
log.status.Print(f"An error has occurred: {e}")
return []
def Display(self, args, resources):
if not resources:
log.out.Print("No manifests generated.")
return
output_content = ""
if args.output == "manifest" or args.output == "all":
for manifest in resources.k8sManifests:
output_content += manifest.content + "\n---\n"
if args.output == "comments" or args.output == "all":
if resources.comments:
comment_string = "\n".join([f"# {line}" for line in resources.comments])
output_content += comment_string
if args.output_path:
try:
with files.FileWriter(args.output_path, output_content) as f:
f.write(output_content)
log.out.Print(f"Output saved to {args.output_path}")
except exceptions.Error as e:
log.error(f"An error occurred while saving output to file: {e}")
else:
log.out.Print(output_content)

View File

@@ -0,0 +1,29 @@
# -*- coding: utf-8 -*- #
# Copyright 2025 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 group for the model and model server combinations CLI."""
from __future__ import absolute_import
from __future__ import division
from __future__ import unicode_literals
from googlecloudsdk.calliope import base
from googlecloudsdk.command_lib.projects import util
@base.UniverseCompatible
@base.ReleaseTracks(base.ReleaseTrack.ALPHA)
class ModelServers(base.Group):
"""Manage supported model and model servers for GKE Inference Quickstart."""

View File

@@ -0,0 +1,81 @@
# -*- coding: utf-8 -*- #
# Copyright 2025 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.
"""Lists supported model and server combinations for GKE Inference Quickstart."""
from googlecloudsdk.api_lib.ai.recommender import util
from googlecloudsdk.calliope import base
from googlecloudsdk.command_lib.run import commands
from googlecloudsdk.core import exceptions
from googlecloudsdk.core import log
_EXAMPLES = """
To list all supported model and server combinations, run:
$ {command}
"""
@base.DefaultUniverseOnly
@base.ReleaseTracks(base.ReleaseTrack.ALPHA)
class List(commands.List):
"""List supported model and server combinations.
This command lists all supported model, model server, and model server version
combinations.
"""
@staticmethod
def Args(parser):
parser.add_argument(
"--model",
help="The model. If not specified, this defaults to any model.",
)
parser.add_argument(
"--model-server",
help=(
"The model server. If not specified, this defaults to any model"
" server."
),
)
parser.add_argument(
"--model-server-version",
help=(
"The model server version. If not specified, this defaults to the"
" any model server version."
),
)
parser.display_info.AddFormat(
"table(modelName, modelServerName, modelServerVersion)"
)
def Run(self, args):
client = util.GetClientInstance(base.ReleaseTrack.ALPHA)
messages = util.GetMessagesModule(base.ReleaseTrack.ALPHA)
try:
request = messages.GkerecommenderModelsAndServersListRequest(
modelName=args.model,
modelServerName=args.model_server,
modelServerVersion=args.model_server_version,
)
response = client.modelsAndServers.List(request)
if response.modelAndModelServerInfo:
return response.modelAndModelServerInfo
else:
return []
except exceptions.Error as e:
log.error(f"An error has occurred: {e}")
log.status.Print(f"An error has occurred: {e}")
return []

View File

@@ -0,0 +1,29 @@
# -*- coding: utf-8 -*- #
# Copyright 2025 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 group for the model server versions CLI."""
from __future__ import absolute_import
from __future__ import division
from __future__ import unicode_literals
from googlecloudsdk.calliope import base
from googlecloudsdk.command_lib.projects import util
@base.UniverseCompatible
@base.ReleaseTracks(base.ReleaseTrack.ALPHA, base.ReleaseTrack.GA)
class ModelServers(base.Group):
"""Manage supported model server versions for GKE Inference Quickstart."""

View File

@@ -0,0 +1,137 @@
# -*- coding: utf-8 -*- #
# Copyright 2025 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.
"""Lists supported model server versions for GKE Inference Quickstart."""
from apitools.base.py import exceptions as apitools_exceptions
from googlecloudsdk.api_lib.ai.recommender import util
from googlecloudsdk.api_lib.util import exceptions as api_lib_exceptions
from googlecloudsdk.calliope import base
from googlecloudsdk.command_lib.run import commands
from googlecloudsdk.core import exceptions
from googlecloudsdk.core import log
_EXAMPLES = """
To list all supported model server versions for a model and model server, run:
$ {command} --model=deepseek-ai/DeepSeek-R1-Distill-Qwen-7B --model-server=vllm
"""
@base.DefaultUniverseOnly
@base.ReleaseTracks(base.ReleaseTrack.GA)
class List(commands.List):
"""List supported model server versions.
To get supported model and model servers, run `gcloud container ai
profiles models list` and `gcloud container ai profiles
model-servers list`.
"""
@staticmethod
def Args(parser):
parser.add_argument(
"--model",
required=True,
help="The model.",
)
parser.add_argument(
"--model-server",
required=True,
help=(
"The model server. If not specified, this defaults to any model"
" server."
),
)
def Run(self, args):
client = util.GetClientInstance(base.ReleaseTrack.GA)
messages = util.GetMessagesModule(base.ReleaseTrack.GA)
try:
request = messages.GkerecommenderModelServerVersionsFetchRequest(
model=args.model, modelServer=args.model_server
)
response = client.modelServerVersions.Fetch(request)
if response.modelServerVersions:
return response.modelServerVersions
else:
return []
except apitools_exceptions.HttpError as error:
raise api_lib_exceptions.HttpException(error, util.HTTP_ERROR_FORMAT)
def Display(self, _, resources):
if resources:
log.out.Print("Supported model server versions:")
for model_server_version in resources:
log.out.Print("- ", model_server_version)
else:
log.out.Print("No supported model server versions found.")
@base.DefaultUniverseOnly
@base.ReleaseTracks(base.ReleaseTrack.ALPHA)
class ListAlpha(commands.List):
"""List supported model server versions.
To get supported model and model servers, run `gcloud alpha container ai
profiles models list` and `gcloud alpha container ai profiles
model-servers list`.
Alternatively, run `gcloud alpha container ai profiles
model-and-server-combinations list` to get all supported model and server
combinations.
"""
@staticmethod
def Args(parser):
parser.add_argument(
"--model",
required=True,
help="The model.",
)
parser.add_argument(
"--model-server",
required=True,
help=(
"The model server. If not specified, this defaults to any model"
" server."
),
)
def Run(self, args):
client = util.GetClientInstance(base.ReleaseTrack.ALPHA)
messages = util.GetMessagesModule(base.ReleaseTrack.ALPHA)
try:
request = messages.GkerecommenderModelServersVersionsListRequest(
modelName=args.model, modelServerName=args.model_server
)
response = client.modelServers_versions.List(request)
if response.modelServerVersions:
return response.modelServerVersions
else:
return []
except exceptions.Error as e:
log.error(f"An error has occurred: {e}")
log.status.Print(f"An error has occurred: {e}")
return []
def Display(self, _, resources):
if resources:
log.out.Print("Supported model server versions:")
for model_server_version in resources:
log.out.Print("- ", model_server_version)
else:
log.out.Print("No supported model server versions found.")

View File

@@ -0,0 +1,29 @@
# -*- coding: utf-8 -*- #
# Copyright 2025 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 group for the model servers CLI."""
from __future__ import absolute_import
from __future__ import division
from __future__ import unicode_literals
from googlecloudsdk.calliope import base
from googlecloudsdk.command_lib.projects import util
@base.UniverseCompatible
@base.ReleaseTracks(base.ReleaseTrack.ALPHA, base.ReleaseTrack.GA)
class ModelServers(base.Group):
"""Manage supported model servers for GKE Inference Quickstart."""

View File

@@ -0,0 +1,118 @@
# -*- coding: utf-8 -*- #
# Copyright 2025 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.
"""Lists supported model servers for GKE Inference Quickstart."""
from apitools.base.py import exceptions as apitools_exceptions
from googlecloudsdk.api_lib.ai.recommender import util
from googlecloudsdk.api_lib.util import exceptions as api_lib_exceptions
from googlecloudsdk.calliope import base
from googlecloudsdk.command_lib.run import commands
from googlecloudsdk.core import exceptions
from googlecloudsdk.core import log
_EXAMPLE = """
To list all supported model servers for a model, run:
$ {command} --model=deepseek-ai/DeepSeek-R1-Distill-Qwen-7B
"""
@base.DefaultUniverseOnly
@base.ReleaseTracks(base.ReleaseTrack.GA)
class List(commands.List):
"""List supported model servers for a given model.
To get supported models, run `gcloud container ai profiles models
list`.
"""
@staticmethod
def Args(parser):
parser.add_argument(
"--model",
required=True,
help="The model.",
)
def Run(self, args):
client = util.GetClientInstance(base.ReleaseTrack.GA)
messages = util.GetMessagesModule(base.ReleaseTrack.GA)
try:
request = messages.GkerecommenderModelServersFetchRequest(
model=args.model
)
response = client.modelServers.Fetch(request)
if response.modelServers:
return response.modelServers
else:
return []
except apitools_exceptions.HttpError as error:
raise api_lib_exceptions.HttpException(error, util.HTTP_ERROR_FORMAT)
def Display(self, _, resources):
if resources:
log.out.Print("Supported model servers:")
for model_server_name in resources:
log.out.Print("- ", model_server_name)
else:
log.out.Print("No supported model servers found.")
@base.DefaultUniverseOnly
@base.ReleaseTracks(base.ReleaseTrack.ALPHA)
class ListAlpha(commands.List):
"""List supported model servers for a given model.
To get supported models, run `gcloud alpha container ai profiles models
list` or to get all supported model and server combinations, run `gcloud alpha
container ai profiles model-and-server-combinations
list`.
"""
@staticmethod
def Args(parser):
parser.add_argument(
"--model",
required=True,
help="The model.",
)
def Run(self, args):
client = util.GetClientInstance(base.ReleaseTrack.ALPHA)
messages = util.GetMessagesModule(base.ReleaseTrack.ALPHA)
try:
request = messages.GkerecommenderModelServersListRequest(
modelName=args.model
)
response = client.modelServers.List(request)
if response.modelServerNames:
return response.modelServerNames
else:
return []
except exceptions.Error as e:
log.error(f"An error has occurred: {e}")
log.status.Print(f"An error has occurred: {e}")
return []
def Display(self, _, resources):
if resources:
log.out.Print("Supported model servers:")
for model_server_name in resources:
log.out.Print("- ", model_server_name)
else:
log.out.Print("No supported model servers found.")

View File

@@ -0,0 +1,29 @@
# -*- coding: utf-8 -*- #
# Copyright 2025 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 group for the models CLI."""
from __future__ import absolute_import
from __future__ import division
from __future__ import unicode_literals
from googlecloudsdk.calliope import base
from googlecloudsdk.command_lib.projects import util
@base.UniverseCompatible
@base.ReleaseTracks(base.ReleaseTrack.ALPHA, base.ReleaseTrack.GA)
class Models(base.Group):
"""Manage supported models for GKE Inference Quickstart."""

View File

@@ -0,0 +1,88 @@
# -*- coding: utf-8 -*- #
# Copyright 2025 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.
"""Lists supported models for GKE Inference Quickstart."""
from apitools.base.py import exceptions as apitools_exceptions
from googlecloudsdk.api_lib.ai.recommender import util
from googlecloudsdk.api_lib.util import exceptions as api_lib_exceptions
from googlecloudsdk.calliope import base
from googlecloudsdk.command_lib.run import commands
from googlecloudsdk.core import exceptions
from googlecloudsdk.core import log
_EXAMPLES = """
To list all supported models, run:
$ {command}
"""
@base.DefaultUniverseOnly
@base.ReleaseTracks(base.ReleaseTrack.GA)
class List(commands.List):
"""List supported models."""
def Run(self, _):
client = util.GetClientInstance(base.ReleaseTrack.GA)
messages = util.GetMessagesModule(base.ReleaseTrack.GA)
try:
response = client.models.Fetch(
messages.GkerecommenderModelsFetchRequest()
)
if response.models:
return response.models
else:
return []
except apitools_exceptions.HttpError as error:
raise api_lib_exceptions.HttpException(error, util.HTTP_ERROR_FORMAT)
def Display(self, _, resources):
if resources:
log.out.Print("Supported models:")
for model_name in resources:
log.out.Print("- ", model_name)
else:
log.out.Print("No supported models found.")
@base.DefaultUniverseOnly
@base.ReleaseTracks(base.ReleaseTrack.ALPHA)
class ListAlpha(commands.List):
"""List supported models."""
def Run(self, _):
client = util.GetClientInstance(base.ReleaseTrack.ALPHA)
messages = util.GetMessagesModule(base.ReleaseTrack.ALPHA)
try:
response = client.models.List(messages.GkerecommenderModelsListRequest())
if response.modelNames:
return response.modelNames
else:
return []
except exceptions.Error as e:
log.error(f"An error has occurred: {e}")
log.status.Print(f"An error has occured: {e}")
return []
def Display(self, _, resources):
if resources:
log.out.Print("Supported models:")
for model_name in resources:
log.out.Print("- ", model_name)
else:
log.out.Print("No supported models found.")

View File

@@ -0,0 +1,24 @@
# -*- coding: utf-8 -*- #
# Copyright 2025 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 group for the serving stack versions CLI."""
from googlecloudsdk.calliope import base
from googlecloudsdk.command_lib.projects import util
@base.UniverseCompatible
@base.ReleaseTracks(base.ReleaseTrack.GA)
class ServingStackVersions(base.Group):
"""List supported serving stack versions for GKE Inference Quickstart."""

View File

@@ -0,0 +1,69 @@
# -*- coding: utf-8 -*- #
# Copyright 2025 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.
"""Lists supported serving stack versions for GKE Inference Quickstart."""
from apitools.base.py import exceptions as apitools_exceptions
from googlecloudsdk.api_lib.ai.recommender import util
from googlecloudsdk.api_lib.util import exceptions as api_lib_exceptions
from googlecloudsdk.calliope import base
from googlecloudsdk.command_lib.run import commands
_EXAMPLES = """
To list all supported serving stack versions, run:
$ {command} --serving-stack=llm-d
"""
@base.ReleaseTracks(base.ReleaseTrack.GA)
class List(commands.List):
"""List supported serving stack versions that were used to generate the inference profiles."""
@staticmethod
def Args(parser):
parser.display_info.AddFormat("table(version)")
parser.add_argument(
"--model",
help="The model to filter serving stack versions by.",
)
parser.add_argument(
"--model-server",
help="The model server to filter serving stack versions by.",
)
parser.add_argument(
"--serving-stack",
required=True,
help="The serving stack to filter serving stack versions by.",
)
def Run(self, args):
client = util.GetClientInstance(base.ReleaseTrack.GA)
messages = util.GetMessagesModule(base.ReleaseTrack.GA)
try:
response = client.servingStackVersions.Fetch(
messages.GkerecommenderServingStackVersionsFetchRequest(
model=args.model,
modelServer=args.model_server,
servingStack=args.serving_stack,
)
)
if response.servingStackVersions:
return [{"version": v} for v in response.servingStackVersions]
else:
return []
except apitools_exceptions.HttpError as error:
raise api_lib_exceptions.HttpException(error, util.HTTP_ERROR_FORMAT)

View File

@@ -0,0 +1,24 @@
# -*- coding: utf-8 -*- #
# Copyright 2025 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 group for the serving stack CLI."""
from googlecloudsdk.calliope import base
from googlecloudsdk.command_lib.projects import util
@base.UniverseCompatible
@base.ReleaseTracks(base.ReleaseTrack.GA)
class ServingStacks(base.Group):
"""List supported serving stacks for GKE Inference Quickstart."""

View File

@@ -0,0 +1,65 @@
# -*- coding: utf-8 -*- #
# Copyright 2025 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.
"""Lists supported serving stacks for GKE Inference Quickstart."""
from apitools.base.py import exceptions as apitools_exceptions
from googlecloudsdk.api_lib.ai.recommender import util
from googlecloudsdk.api_lib.util import exceptions as api_lib_exceptions
from googlecloudsdk.calliope import base
from googlecloudsdk.command_lib.run import commands
_EXAMPLES = """
To list all supported serving stacks, run:
$ {command}
"""
@base.ReleaseTracks(base.ReleaseTrack.GA)
class List(commands.List):
"""List supported serving stacks that were used to generate the inference profiles."""
@staticmethod
def Args(parser):
parser.display_info.AddFormat(
"table(name,version)"
)
parser.add_argument(
"--model",
help="The model to filter serving stacks by.",
)
parser.add_argument(
"--model-server",
help="The model server to filter serving stacks by.",
)
def Run(self, args):
client = util.GetClientInstance(base.ReleaseTrack.GA)
messages = util.GetMessagesModule(base.ReleaseTrack.GA)
try:
response = client.servingStacks.Fetch(
messages.GkerecommenderServingStacksFetchRequest(
model=args.model,
modelServer=args.model_server,
)
)
if response.servingStacks:
return response.servingStacks
else:
return []
except apitools_exceptions.HttpError as error:
raise api_lib_exceptions.HttpException(error, util.HTTP_ERROR_FORMAT)

View File

@@ -0,0 +1,29 @@
# -*- coding: utf-8 -*- #
# Copyright 2025 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 group for the models CLI."""
from __future__ import absolute_import
from __future__ import division
from __future__ import unicode_literals
from googlecloudsdk.calliope import base
from googlecloudsdk.command_lib.projects import util
@base.UniverseCompatible
@base.ReleaseTracks(base.ReleaseTrack.GA)
class UseCase(base.Group):
"""List supported use cases for GKE Inference Quickstart."""

View File

@@ -0,0 +1,54 @@
# -*- coding: utf-8 -*- #
# Copyright 2025 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.
"""Lists supported use cases for GKE Inference Quickstart."""
from apitools.base.py import exceptions as apitools_exceptions
from googlecloudsdk.api_lib.ai.recommender import util
from googlecloudsdk.api_lib.util import exceptions as api_lib_exceptions
from googlecloudsdk.calliope import base
from googlecloudsdk.command_lib.run import commands
_EXAMPLES = """
To list all supported use cases, run:
$ {command}
"""
@base.ReleaseTracks(base.ReleaseTrack.GA)
class List(commands.List):
"""List supported use cases that were used to generate the inference profiles."""
@staticmethod
def Args(parser):
parser.display_info.AddFormat(
"table(useCase,averageInputLength,averageOutputLength)"
)
def Run(self, _):
client = util.GetClientInstance(base.ReleaseTrack.GA)
messages = util.GetMessagesModule(base.ReleaseTrack.GA)
try:
response = client.useCases.Fetch(
messages.FetchUseCasesRequest()
)
if response.workloadSpecs:
return response.workloadSpecs
else:
return []
except apitools_exceptions.HttpError as error:
raise api_lib_exceptions.HttpException(error, util.HTTP_ERROR_FORMAT)

View File

@@ -0,0 +1,32 @@
# -*- 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.
"""Command group `gcloud container attached`."""
from __future__ import absolute_import
from __future__ import division
from __future__ import unicode_literals
from googlecloudsdk.calliope import base
from googlecloudsdk.command_lib.projects import util
@base.ReleaseTracks(base.ReleaseTrack.ALPHA, base.ReleaseTrack.GA)
class Attached(base.Group):
"""Manage Attached clusters for running containers."""
category = base.COMPUTE_CATEGORY
def Filter(self, context, args):
del context, args

View File

@@ -0,0 +1,32 @@
# -*- 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.
"""Command group `gcloud container attached clusters`."""
from __future__ import absolute_import
from __future__ import division
from __future__ import unicode_literals
from googlecloudsdk.calliope import base
from googlecloudsdk.command_lib.projects import util
from googlecloudsdk.core import log
@base.ReleaseTracks(base.ReleaseTrack.ALPHA, base.ReleaseTrack.GA)
class Clusters(base.Group):
"""Create and manage Attached clusters."""
@staticmethod
def Args(parser):
pass

View File

@@ -0,0 +1,69 @@
# -*- 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.
"""Command to delete a registered AttachedCluster resource.."""
from __future__ import absolute_import
from __future__ import division
from __future__ import unicode_literals
from googlecloudsdk.api_lib.container.gkemulticloud import attached as api_util
from googlecloudsdk.calliope import base
from googlecloudsdk.command_lib.container.attached import resource_args
from googlecloudsdk.command_lib.container.gkemulticloud import command_util
from googlecloudsdk.command_lib.container.gkemulticloud import constants
from googlecloudsdk.command_lib.container.gkemulticloud import endpoint_util
from googlecloudsdk.command_lib.container.gkemulticloud import flags
_EXAMPLES = """
To delete an AttachedCluster resource named ``my-cluster'' managed in location
``us-west1'', run:
$ {command} my-cluster --location=us-west1
"""
@base.ReleaseTracks(base.ReleaseTrack.ALPHA, base.ReleaseTrack.GA)
class Delete(base.DeleteCommand):
"""Delete a registered AttachedCluster resource."""
detailed_help = {'EXAMPLES': _EXAMPLES}
@staticmethod
def Args(parser):
"""Register flags for this command."""
resource_args.AddAttachedClusterResourceArg(parser, 'to delete')
flags.AddValidateOnly(parser, 'cluster to delete')
flags.AddAllowMissing(parser, 'cluster')
flags.AddIgnoreErrors(parser, constants.ATTACHED, 'cluster')
base.ASYNC_FLAG.AddToParser(parser)
def Run(self, args):
"""Runs the delete command."""
location = resource_args.ParseAttachedClusterResourceArg(args).locationsId
with endpoint_util.GkemulticloudEndpointOverride(location):
cluster_ref = resource_args.ParseAttachedClusterResourceArg(args)
cluster_client = api_util.ClustersClient()
message = command_util.ClusterMessage(
cluster_ref.attachedClustersId, kind=constants.ATTACHED
)
command_util.DeleteWithIgnoreErrors(
args,
cluster_client,
cluster_ref,
message,
constants.ATTACHED_CLUSTER_KIND,
)

View File

@@ -0,0 +1,51 @@
# -*- 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.
"""Command to describe an Attached cluster."""
from __future__ import absolute_import
from __future__ import division
from __future__ import unicode_literals
from googlecloudsdk.api_lib.container.gkemulticloud import attached as api_util
from googlecloudsdk.calliope import base
from googlecloudsdk.command_lib.container.attached import resource_args
from googlecloudsdk.command_lib.container.gkemulticloud import endpoint_util
_EXAMPLES = """
To describe a cluster named ``my-cluster'' managed in location ``us-west1'',
run:
$ {command} my-cluster --location=us-west1
"""
@base.ReleaseTracks(base.ReleaseTrack.ALPHA, base.ReleaseTrack.GA)
class Describe(base.DescribeCommand):
"""Describe an Attached cluster."""
detailed_help = {'EXAMPLES': _EXAMPLES}
@staticmethod
def Args(parser):
"""Registers flags for this command."""
resource_args.AddAttachedClusterResourceArg(parser, 'to describe')
def Run(self, args):
"""Runs the describe command."""
location = resource_args.ParseAttachedClusterResourceArg(args).locationsId
with endpoint_util.GkemulticloudEndpointOverride(location):
cluster_ref = resource_args.ParseAttachedClusterResourceArg(args)
cluster_client = api_util.ClustersClient()
return cluster_client.Get(cluster_ref)

View File

@@ -0,0 +1,74 @@
# -*- 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.
"""Command to generate install manifest for Attached cluster."""
from __future__ import absolute_import
from __future__ import division
from __future__ import unicode_literals
from googlecloudsdk.api_lib.container.gkemulticloud import locations as api_util
from googlecloudsdk.calliope import base
from googlecloudsdk.command_lib.container.attached import flags as attached_flags
from googlecloudsdk.command_lib.container.attached import resource_args
from googlecloudsdk.command_lib.container.gkemulticloud import endpoint_util
from googlecloudsdk.command_lib.container.gkemulticloud import flags
from googlecloudsdk.core import log
_EXAMPLES = """
To generate install manifest for cluster named ``my-cluster'' managed in location ``us-west1'', run:
$ {command} my-cluster --location=us-west1 --platform-version=PLATFORM_VERSION
To store the manifest in a file named ``manifest.yaml'', run:
$ {command} my-cluster --location=us-west1 --platform-version=PLATFORM_VERSION --output-file=manifest.yaml
"""
@base.ReleaseTracks(base.ReleaseTrack.ALPHA, base.ReleaseTrack.GA)
class Describe(base.Command):
"""Generate Install Manifest for an Attached cluster."""
detailed_help = {'EXAMPLES': _EXAMPLES}
@staticmethod
def Args(parser):
"""Registers flags for this command."""
resource_args.AddAttachedClusterResourceArg(
parser, 'to generate install manifest'
)
attached_flags.AddPlatformVersion(parser)
attached_flags.AddProxyConfig(parser)
flags.AddOutputFile(parser, 'to store manifest')
def Run(self, args):
"""Runs the generate-install-manifest command."""
location = resource_args.ParseAttachedClusterResourceArg(args).locationsId
with endpoint_util.GkemulticloudEndpointOverride(location):
cluster_ref = resource_args.ParseAttachedClusterResourceArg(args)
client = api_util.LocationsClient()
resp = client.GenerateInstallManifest(cluster_ref, args=args)
if args.output_file:
log.WriteToFileOrStdout(
args.output_file,
resp.manifest,
overwrite=True,
binary=False,
private=True,
)
return None
return resp

View File

@@ -0,0 +1,76 @@
# -*- 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.
"""Command to get credentials of an Attached cluster."""
from __future__ import absolute_import
from __future__ import division
from __future__ import unicode_literals
from googlecloudsdk.api_lib.container.gkemulticloud import attached as api_util
from googlecloudsdk.api_lib.container.gkemulticloud import util
from googlecloudsdk.calliope import base
from googlecloudsdk.command_lib.container.attached import resource_args
from googlecloudsdk.command_lib.container.gkemulticloud import endpoint_util
from googlecloudsdk.command_lib.container.gkemulticloud import flags
from googlecloudsdk.command_lib.container.gkemulticloud import kubeconfig
from googlecloudsdk.core import log
@base.ReleaseTracks(base.ReleaseTrack.ALPHA, base.ReleaseTrack.GA)
class GetCredentials(base.Command):
"""Get credentials of an Attached cluster."""
detailed_help = {
'EXAMPLES': kubeconfig.COMMAND_EXAMPLE,
'DESCRIPTION': kubeconfig.COMMAND_DESCRIPTION.format(
cluster_type='Attached cluster'
),
}
@staticmethod
def Args(parser):
resource_args.AddAttachedClusterResourceArg(parser, 'to get credentials')
flags.AddAuthProviderCmdPath(parser)
def Run(self, args):
"""Runs the get-credentials command."""
with endpoint_util.GkemulticloudEndpointOverride(
resource_args.ParseAttachedClusterResourceArg(args).locationsId,
self.ReleaseTrack(),
):
cluster_ref = resource_args.ParseAttachedClusterResourceArg(args)
cluster_client = api_util.ClustersClient()
log.status.Print('Fetching cluster endpoint and auth data.')
resp = cluster_client.Get(cluster_ref)
if (
resp.state
!= util.GetMessagesModule().GoogleCloudGkemulticloudV1AttachedCluster.StateValueValuesEnum.RUNNING
):
log.warning(
kubeconfig.NOT_RUNNING_MSG.format(cluster_ref.attachedClustersId)
)
context = kubeconfig.GenerateContext(
'attached',
cluster_ref.projectsId,
cluster_ref.locationsId,
cluster_ref.attachedClustersId,
)
kubeconfig.GenerateAttachedKubeConfig(
resp,
cluster_ref.attachedClustersId,
context,
args.auth_provider_cmd_path,
)

View File

@@ -0,0 +1,160 @@
# -*- 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.
"""Command to import an Attached cluster."""
from __future__ import absolute_import
from __future__ import division
from __future__ import unicode_literals
from googlecloudsdk.api_lib.container.gkemulticloud import attached as api_util
from googlecloudsdk.api_lib.container.gkemulticloud import locations as loc_util
from googlecloudsdk.calliope import base
from googlecloudsdk.command_lib.container.attached import cluster_util
from googlecloudsdk.command_lib.container.attached import flags as attached_flags
from googlecloudsdk.command_lib.container.attached import resource_args
from googlecloudsdk.command_lib.container.fleet import kube_util
from googlecloudsdk.command_lib.container.gkemulticloud import command_util
from googlecloudsdk.command_lib.container.gkemulticloud import constants
from googlecloudsdk.command_lib.container.gkemulticloud import endpoint_util
from googlecloudsdk.command_lib.container.gkemulticloud import flags
from googlecloudsdk.command_lib.run import pretty_print
from googlecloudsdk.core import exceptions
from googlecloudsdk.core.console import console_io
from googlecloudsdk.core.util import retry
import six
_EXAMPLES = """
To import the fleet membership of an attached cluster in fleet ``FLEET_MEMBERSHIP'' managed in location ``us-west1'', run:
$ {command} --location=us-west1 --platform-version=PLATFORM_VERSION --fleet-membership=FLEET_MEMBERSHIP --distribution=DISTRIBUTION --context=CLUSTER_CONTEXT --kubeconfig=KUBECONFIG_PATH
"""
@base.ReleaseTracks(base.ReleaseTrack.ALPHA, base.ReleaseTrack.GA)
@base.DefaultUniverseOnly
class Import(base.Command):
"""Import fleet membership for an Attached cluster."""
detailed_help = {'EXAMPLES': _EXAMPLES}
@staticmethod
def Args(parser):
"""Registers flags for this command."""
resource_args.AddLocationResourceArg(parser, 'to import attached cluster.')
resource_args.AddFleetMembershipResourceArg(parser)
attached_flags.AddPlatformVersion(parser)
attached_flags.AddDistribution(parser, required=True)
attached_flags.AddKubectl(parser)
attached_flags.AddProxyConfig(parser)
attached_flags.AddSkipClusterAdminCheck(parser)
flags.AddValidateOnly(parser, 'cluster to import')
base.ASYNC_FLAG.AddToParser(parser)
def Run(self, args):
"""Runs the import command."""
location_ref = args.CONCEPTS.location.Parse()
fleet_membership_ref = args.CONCEPTS.fleet_membership.Parse()
with endpoint_util.GkemulticloudEndpointOverride(location_ref.locationsId):
manifest = self._get_manifest(
args, location_ref, fleet_membership_ref.membershipsId
)
import_resp = ''
with kube_util.KubernetesClient(
kubeconfig=attached_flags.GetKubeconfig(args),
context=attached_flags.GetContext(args),
enable_workload_identity=True,
) as kube_client:
if not attached_flags.GetSkipClusterAdminCheck(args):
kube_client.CheckClusterAdminPermissions()
try:
if not flags.GetValidateOnly(args):
pretty_print.Info('Creating in-cluster install agent')
kube_client.Apply(manifest)
retryer = retry.Retryer(
max_retrials=constants.ATTACHED_INSTALL_AGENT_VERIFY_RETRIES
)
retryer.RetryOnException(
cluster_util.verify_install_agent_deployed,
args=(kube_client,),
sleep_ms=constants.ATTACHED_INSTALL_AGENT_VERIFY_WAIT_MS,
)
import_resp = self._import_attached_cluster(
args, location_ref, fleet_membership_ref
)
except retry.RetryException as e:
self._remove_manifest(args, kube_client, manifest)
# last_result[1] holds information about the last exception the
# retryer caught. last_result[1][1] holds the exception type and
# last_result[1][2] holds the exception value. The retry exception is
# not useful to users, so reraise whatever error caused it to timeout.
if e.last_result[1]:
exceptions.reraise(e.last_result[1][1], e.last_result[1][2])
raise
except console_io.OperationCancelledError:
msg = """To manually clean up the in-cluster install agent, run:
$ gcloud {} container attached clusters generate-install-manifest --location={} --platform-version={} --format="value(manifest)" {} | kubectl delete -f -
AFTER the attach operation completes.
""".format(
six.text_type(self.ReleaseTrack()).lower(),
location_ref.locationsId,
attached_flags.GetPlatformVersion(args),
fleet_membership_ref.membershipsId,
)
pretty_print.Info(msg)
raise
except: # pylint: disable=broad-except
self._remove_manifest(args, kube_client, manifest)
raise
self._remove_manifest(args, kube_client, manifest)
return import_resp
def _get_manifest(self, args, location_ref, memberships_id):
location_client = loc_util.LocationsClient()
resp = location_client.GenerateInstallManifestForImport(
location_ref, memberships_id, args=args
)
return resp.manifest
def _remove_manifest(self, args, kube_client, manifest):
if not flags.GetValidateOnly(args):
pretty_print.Info('Deleting in-cluster install agent')
kube_client.Delete(manifest)
def _import_attached_cluster(self, args, location_ref, fleet_membership_ref):
cluster_client = api_util.ClustersClient()
message = command_util.ClusterMessage(
fleet_membership_ref.RelativeName(),
action='Importing',
kind=constants.ATTACHED,
)
return command_util.Import(
location_ref=location_ref,
resource_client=cluster_client,
fleet_membership_ref=fleet_membership_ref,
args=args,
message=message,
kind=constants.ATTACHED_CLUSTER_KIND,
)

View File

@@ -0,0 +1,51 @@
# -*- 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.
"""Command to list Attached clusters."""
from __future__ import absolute_import
from __future__ import division
from __future__ import unicode_literals
from googlecloudsdk.api_lib.container.gkemulticloud import attached as api_util
from googlecloudsdk.calliope import base
from googlecloudsdk.command_lib.container.attached import resource_args
from googlecloudsdk.command_lib.container.gkemulticloud import constants
from googlecloudsdk.command_lib.container.gkemulticloud import endpoint_util
_EXAMPLES = """
To lists all clusters managed in location ``us-west1'', run:
$ {command} --location=us-west1
"""
@base.ReleaseTracks(base.ReleaseTrack.ALPHA, base.ReleaseTrack.GA)
class Describe(base.ListCommand):
"""List Attached clusters."""
detailed_help = {'EXAMPLES': _EXAMPLES}
@staticmethod
def Args(parser):
resource_args.AddLocationResourceArg(parser, 'to list')
parser.display_info.AddFormat(constants.ATTACHED_CLUSTERS_FORMAT)
def Run(self, args):
"""Runs the list command."""
location_ref = args.CONCEPTS.location.Parse()
with endpoint_util.GkemulticloudEndpointOverride(location_ref.locationsId):
cluster_client = api_util.ClustersClient()
items, _ = cluster_client.List(location_ref, args.page_size, args.limit)
return items

View File

@@ -0,0 +1,217 @@
# -*- coding: utf-8 -*- #
# Copyright 2025 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.
"""Command to register an Attached cluster with the fleet.
This command performs the full end-to-end steps required to attach a cluster.
"""
from __future__ import absolute_import
from __future__ import division
from __future__ import unicode_literals
import json
from googlecloudsdk.api_lib.container.gkemulticloud import attached as api_util
from googlecloudsdk.api_lib.container.gkemulticloud import locations as loc_util
from googlecloudsdk.calliope import base
from googlecloudsdk.command_lib.container.attached import cluster_util
from googlecloudsdk.command_lib.container.attached import flags as attached_flags
from googlecloudsdk.command_lib.container.attached import resource_args
from googlecloudsdk.command_lib.container.fleet import kube_util
from googlecloudsdk.command_lib.container.gkemulticloud import command_util
from googlecloudsdk.command_lib.container.gkemulticloud import constants
from googlecloudsdk.command_lib.container.gkemulticloud import endpoint_util
from googlecloudsdk.command_lib.container.gkemulticloud import errors
from googlecloudsdk.command_lib.container.gkemulticloud import flags
from googlecloudsdk.command_lib.run import exceptions as run_exceptions
from googlecloudsdk.command_lib.run import pretty_print
from googlecloudsdk.core import exceptions
from googlecloudsdk.core.console import console_io
from googlecloudsdk.core.util import retry
import six
# Command needs to be in one line for the docgen tool to format properly.
_EXAMPLES = """
Register a cluster to a fleet.
To register a cluster with a private OIDC issuer, run:
$ {command} my-cluster --location=us-west1 --platform-version=PLATFORM_VERSION --fleet-project=FLEET_PROJECT_NUM --distribution=DISTRIBUTION --context=CLUSTER_CONTEXT --has-private-issuer
To register a cluster with a public OIDC issuer, run:
$ {command} my-cluster --location=us-west1 --platform-version=PLATFORM_VERSION --fleet-project=FLEET_PROJECT_NUM --distribution=DISTRIBUTION --context=CLUSTER_CONTEXT --issuer-url=https://ISSUER_URL
To specify a kubeconfig file, run:
$ {command} my-cluster --location=us-west1 --platform-version=PLATFORM_VERSION --fleet-project=FLEET_PROJECT_NUM --distribution=DISTRIBUTION --context=CLUSTER_CONTEXT --has-private-issuer --kubeconfig=KUBECONFIG_PATH
To register and set cluster admin users, run:
$ {command} my-cluster --location=us-west1 --platform-version=PLATFORM_VERSION --fleet-project=FLEET_PROJECT_NUM --distribution=DISTRIBUTION --context=CLUSTER_CONTEXT --issuer-url=https://ISSUER_URL --admin-users=USER1,USER2
To specify custom tolerations and labels for system component pods, run:
$ {command} my-cluster --location=us-west1 --platform-version=PLATFORM_VERSION --fleet-project=FLEET_PROJECT_NUM --distribution=DISTRIBUTION --context=CLUSTER_CONTEXT --system-component-tolerations=TOLERATIONS --system-component-labels=LABELS
where TOLERATIONS have the format:
key=value:Effect:NoSchedule (examples: key1=value1:Equal:NoSchedule,key2:Exists:PreferNoSchedule, :Exists:NoExecute)
and LABELS have the format:
key=value (examples: key1=value1,key2="")
"""
@base.ReleaseTracks(base.ReleaseTrack.ALPHA, base.ReleaseTrack.GA)
@base.DefaultUniverseOnly
class Register(base.CreateCommand):
"""Register an Attached cluster."""
detailed_help = {'EXAMPLES': _EXAMPLES}
@staticmethod
def Args(parser):
"""Registers flags for this command."""
resource_args.AddAttachedClusterResourceArg(parser, 'to register')
attached_flags.AddPlatformVersion(parser)
attached_flags.AddRegisterOidcConfig(parser)
attached_flags.AddDistribution(parser, required=True)
attached_flags.AddAdminUsers(parser)
attached_flags.AddKubectl(parser)
attached_flags.AddProxyConfig(parser)
attached_flags.AddSkipClusterAdminCheck(parser)
attached_flags.AddSystemComponentTolerations(parser)
attached_flags.AddSystemComponentLabels(parser)
flags.AddAnnotations(parser)
flags.AddValidateOnly(parser, 'cluster to create')
flags.AddFleetProject(parser)
flags.AddDescription(parser)
flags.AddLogging(parser, True)
flags.AddMonitoringConfig(parser, True, True)
flags.AddBinauthzEvaluationMode(parser)
flags.AddAdminGroups(parser)
flags.AddWorkloadVulnerabilityScanning(parser)
flags.AddResourceManagerTags(parser)
parser.display_info.AddFormat(constants.ATTACHED_CLUSTERS_FORMAT)
def Run(self, args):
location = resource_args.ParseAttachedClusterResourceArg(args).locationsId
if (
attached_flags.GetHasPrivateIssuer(args)
and attached_flags.GetDistribution(args) == 'eks'
):
raise run_exceptions.ArgumentError(
'Distributions of type "eks" cannot use the `has-private-issuer`'
' flag.'
)
# Validate system component tolerations early to fail fast.
attached_flags.GetSystemComponentTolerations(args)
with endpoint_util.GkemulticloudEndpointOverride(location):
cluster_ref = resource_args.ParseAttachedClusterResourceArg(args)
manifest = self._get_manifest(args, cluster_ref)
with kube_util.KubernetesClient(
kubeconfig=attached_flags.GetKubeconfig(args),
context=attached_flags.GetContext(args),
enable_workload_identity=True,
) as kube_client:
if not attached_flags.GetSkipClusterAdminCheck(args):
kube_client.CheckClusterAdminPermissions()
if attached_flags.GetHasPrivateIssuer(args):
pretty_print.Info('Fetching cluster OIDC information')
issuer_url, jwks = self._get_authority(kube_client)
setattr(args, 'issuer_url', issuer_url)
setattr(args, 'oidc_jwks', jwks)
try:
if not flags.GetValidateOnly(args):
pretty_print.Info('Creating in-cluster install agent')
kube_client.Apply(manifest)
retryer = retry.Retryer(
max_retrials=constants.ATTACHED_INSTALL_AGENT_VERIFY_RETRIES
)
retryer.RetryOnException(
cluster_util.verify_install_agent_deployed,
args=(kube_client,),
sleep_ms=constants.ATTACHED_INSTALL_AGENT_VERIFY_WAIT_MS,
)
create_resp = self._create_attached_cluster(args, cluster_ref)
except retry.RetryException as e:
self._remove_manifest(args, kube_client, manifest)
# last_result[1] holds information about the last exception the
# retryer caught. last_result[1][1] holds the exception type and
# last_result[1][2] holds the exception value. The retry exception is
# not useful to users, so reraise whatever error caused it to timeout.
if e.last_result[1]:
exceptions.reraise(e.last_result[1][1], e.last_result[1][2])
raise
except console_io.OperationCancelledError:
msg = """To manually clean up the in-cluster install agent, run:
$ gcloud container attached clusters generate-install-manifest --location={} --platform-version={} --format="value(manifest)" {} | kubectl delete -f -
AFTER the attach operation completes.
""".format(
location,
attached_flags.GetPlatformVersion(args),
cluster_ref.attachedClustersId,
)
pretty_print.Info(msg)
raise
except: # pylint: disable=broad-except
self._remove_manifest(args, kube_client, manifest)
raise
self._remove_manifest(args, kube_client, manifest)
return create_resp
def _get_manifest(self, args, cluster_ref):
location_client = loc_util.LocationsClient()
resp = location_client.GenerateInstallManifest(cluster_ref, args=args)
return resp.manifest
def _remove_manifest(self, args, kube_client, manifest):
if not flags.GetValidateOnly(args):
pretty_print.Info('Deleting in-cluster install agent')
kube_client.Delete(manifest)
def _get_authority(self, kube_client):
openid_config_json = six.ensure_str(
kube_client.GetOpenIDConfiguration(), encoding='utf-8'
)
issuer_url = json.loads(openid_config_json).get('issuer')
if not issuer_url:
raise errors.MissingOIDCIssuerURL(openid_config_json)
jwks = kube_client.GetOpenIDKeyset()
return issuer_url, jwks
def _create_attached_cluster(self, args, cluster_ref):
cluster_client = api_util.ClustersClient()
message = command_util.ClusterMessage(
cluster_ref.attachedClustersId,
action='Creating',
kind=constants.ATTACHED,
)
return command_util.Create(
resource_ref=cluster_ref,
resource_client=cluster_client,
args=args,
message=message,
kind=constants.ATTACHED_CLUSTER_KIND,
)

View File

@@ -0,0 +1,80 @@
# -*- 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.
"""Command to update an Attached cluster."""
from __future__ import absolute_import
from __future__ import division
from __future__ import unicode_literals
from googlecloudsdk.api_lib.container.gkemulticloud import attached as api_util
from googlecloudsdk.calliope import base
from googlecloudsdk.command_lib.container.attached import flags as attached_flags
from googlecloudsdk.command_lib.container.attached import resource_args
from googlecloudsdk.command_lib.container.gkemulticloud import command_util
from googlecloudsdk.command_lib.container.gkemulticloud import constants
from googlecloudsdk.command_lib.container.gkemulticloud import endpoint_util
from googlecloudsdk.command_lib.container.gkemulticloud import flags
# Command needs to be in one line for the docgen tool to format properly.
_EXAMPLES = """
To update a cluster named ``my-cluster'' managed in location ``us-west1'', run:
$ {command} my-cluster --location=us-west1 --description=testcluster
"""
@base.ReleaseTracks(base.ReleaseTrack.ALPHA, base.ReleaseTrack.GA)
@base.DefaultUniverseOnly
class Update(base.UpdateCommand):
"""Update an Attached cluster."""
detailed_help = {'EXAMPLES': _EXAMPLES}
@staticmethod
def Args(parser):
resource_args.AddAttachedClusterResourceArg(parser, 'to update')
flags.AddDescription(parser, required=False)
flags.AddClearDescription(parser)
flags.AddAnnotations(parser)
flags.AddValidateOnly(parser, 'update of the cluster')
flags.AddLogging(parser, True)
flags.AddMonitoringConfig(parser, False, True)
flags.AddBinauthzEvaluationMode(parser)
flags.AddAdminGroupsForUpdate(parser)
flags.AddWorkloadVulnerabilityScanning(parser)
attached_flags.AddAdminUsersForUpdate(parser)
attached_flags.AddPlatformVersion(parser, required=False)
attached_flags.AddProxyConfig(parser)
base.ASYNC_FLAG.AddToParser(parser)
parser.display_info.AddFormat(constants.ATTACHED_CLUSTERS_FORMAT)
def Run(self, args):
"""Runs the update command."""
location = resource_args.ParseAttachedClusterResourceArg(args).locationsId
with endpoint_util.GkemulticloudEndpointOverride(location):
cluster_ref = resource_args.ParseAttachedClusterResourceArg(args)
cluster_client = api_util.ClustersClient()
message = command_util.ClusterMessage(
cluster_ref.attachedClustersId, action='Updating'
)
return command_util.Update(
resource_ref=cluster_ref,
resource_client=cluster_client,
args=args,
message=message,
kind=constants.ATTACHED_CLUSTER_KIND,
)

View File

@@ -0,0 +1,57 @@
# -*- 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.
"""Command to get Anthos Multi-Cloud server configuration for Attached clusters."""
from __future__ import absolute_import
from __future__ import division
from __future__ import unicode_literals
from googlecloudsdk.api_lib.container.gkemulticloud import locations as api_util
from googlecloudsdk.calliope import base
from googlecloudsdk.command_lib.container.attached import resource_args
from googlecloudsdk.command_lib.container.gkemulticloud import constants
from googlecloudsdk.command_lib.container.gkemulticloud import endpoint_util
from googlecloudsdk.core import log
_EXAMPLES = """
To return supported Attached cluster valid platform versions in location ``us-west1'', run:
$ {command} --location=us-west1
"""
@base.ReleaseTracks(base.ReleaseTrack.ALPHA, base.ReleaseTrack.GA)
class GetServerConfig(base.Command):
"""Get Anthos Multi-Cloud server configuration for Attached clusters."""
detailed_help = {'EXAMPLES': _EXAMPLES}
@staticmethod
def Args(parser):
resource_args.AddLocationResourceArg(parser, 'to get server configuration')
parser.display_info.AddFormat(constants.ATTACHED_SERVER_CONFIG_FORMAT)
def Run(self, args):
"""Runs the get-server-config command."""
location_ref = args.CONCEPTS.location.Parse()
with endpoint_util.GkemulticloudEndpointOverride(location_ref.locationsId):
log.status.Print(
'Fetching server config for {location}'.format(
location=location_ref.locationsId
)
)
client = api_util.LocationsClient()
return client.GetAttachedServerConfig(location_ref)

View File

@@ -0,0 +1,32 @@
# -*- 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.
"""Command group `gcloud container attached operations`."""
from __future__ import absolute_import
from __future__ import division
from __future__ import unicode_literals
from googlecloudsdk.calliope import base
from googlecloudsdk.command_lib.projects import util
from googlecloudsdk.core import log
@base.ReleaseTracks(base.ReleaseTrack.ALPHA, base.ReleaseTrack.GA)
class Operations(base.Group):
"""Manage Anthos Multi-Cloud long running operations for Attached clusters."""
@staticmethod
def Args(parser):
pass

View File

@@ -0,0 +1,52 @@
# -*- 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.
"""Command to describe an operation."""
from __future__ import absolute_import
from __future__ import division
from __future__ import unicode_literals
from googlecloudsdk.api_lib.container.gkemulticloud import operations as op_api_util
from googlecloudsdk.calliope import base
from googlecloudsdk.command_lib.container.attached import resource_args
from googlecloudsdk.command_lib.container.gkemulticloud import endpoint_util
_EXAMPLES = """
To describe an operation in location ``us-west1'', run:
$ {command} OPERATION_ID --location=us-west1
"""
@base.ReleaseTracks(base.ReleaseTrack.ALPHA, base.ReleaseTrack.GA)
class Describe(base.DescribeCommand):
"""Describe an operation."""
detailed_help = {'EXAMPLES': _EXAMPLES}
@staticmethod
def Args(parser):
"""Registers flags for this command."""
resource_args.AddOperationResourceArg(parser, 'to describe')
def Run(self, args):
"""Runs the describe command."""
with endpoint_util.GkemulticloudEndpointOverride(
resource_args.ParseOperationResourceArg(args).locationsId,
self.ReleaseTrack(),
):
op_client = op_api_util.OperationsClient()
op_ref = resource_args.ParseOperationResourceArg(args)
return op_client.Get(op_ref)

View File

@@ -0,0 +1,61 @@
# -*- 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.
"""Commmand to list operations."""
from __future__ import absolute_import
from __future__ import division
from __future__ import unicode_literals
from googlecloudsdk.api_lib.container.gkemulticloud import operations as op_api_util
from googlecloudsdk.calliope import base
from googlecloudsdk.command_lib.container.attached import resource_args
from googlecloudsdk.command_lib.container.gkemulticloud import endpoint_util
from googlecloudsdk.command_lib.container.gkemulticloud import operations
_EXAMPLES = """
To list all operations in location ``us-west1'', run:
$ {command} --location=us-west1
"""
@base.ReleaseTracks(base.ReleaseTrack.ALPHA, base.ReleaseTrack.GA)
class List(base.ListCommand):
"""List operations."""
detailed_help = {'EXAMPLES': _EXAMPLES}
@staticmethod
def Args(parser):
"""Registers flags for this command."""
resource_args.AddLocationResourceArg(parser, 'to list operations')
operations.AddFormat(parser)
def Run(self, args):
"""Runs the describe command."""
release_track = self.ReleaseTrack()
location_ref = args.CONCEPTS.location.Parse()
with endpoint_util.GkemulticloudEndpointOverride(
location_ref.locationsId, release_track
):
op_client = op_api_util.OperationsClient()
items, empty = op_client.List(
location_ref, args.page_size, args.limit, parent_field='name'
)
if not empty:
# ListOperations returns AWS, Azure, and attached operations.
# Add a filter for attached operations.
operations.AddFilter(args, 'attached')
return items

View File

@@ -0,0 +1,56 @@
# -*- 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.
"""Command to wait for an operation to complete."""
from __future__ import absolute_import
from __future__ import division
from __future__ import unicode_literals
from googlecloudsdk.api_lib.container.gkemulticloud import operations as op_api_util
from googlecloudsdk.calliope import base
from googlecloudsdk.command_lib.container.attached import resource_args
from googlecloudsdk.command_lib.container.gkemulticloud import endpoint_util
_EXAMPLES = """
To wait for an operation in location ``us-west1'' to complete, run:
$ {command} OPERATION_ID --location=us-west1
"""
@base.ReleaseTracks(base.ReleaseTrack.ALPHA, base.ReleaseTrack.GA)
class Describe(base.DescribeCommand):
"""Wait for an operation to complete."""
detailed_help = {'EXAMPLES': _EXAMPLES}
@staticmethod
def Args(parser):
"""Registers flags for this command."""
resource_args.AddOperationResourceArg(parser, 'to wait for')
def Run(self, args):
"""Runs the wait command."""
with endpoint_util.GkemulticloudEndpointOverride(
resource_args.ParseOperationResourceArg(args).locationsId,
self.ReleaseTrack(),
):
op_client = op_api_util.OperationsClient()
op_ref = resource_args.ParseOperationResourceArg(args)
op_client.Wait(
op_ref,
'Waiting for operation {} to complete'.format(op_ref.RelativeName()),
)
return op_client.Get(op_ref)

View File

@@ -0,0 +1,46 @@
# -*- coding: utf-8 -*- #
# Copyright 2021 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.
"""Command group `gcloud container aws`."""
from __future__ import absolute_import
from __future__ import division
from __future__ import unicode_literals
from googlecloudsdk.calliope import base
from googlecloudsdk.command_lib.projects import util
@base.Deprecate(
is_removed=False,
warning=(
"This command is deprecated. See"
" https://cloud.google.com/kubernetes-engine/multi-cloud/docs/aws/deprecations/deprecation-announcement"
" for more details."
),
error=(
"This command has been removed. See"
" https://cloud.google.com/kubernetes-engine/multi-cloud/docs/aws/deprecations/deprecation-announcement"
" for more details."
),
)
@base.UniverseCompatible
@base.ReleaseTracks(base.ReleaseTrack.ALPHA, base.ReleaseTrack.GA)
class Aws(base.Group):
"""Deploy and manage clusters of machines on AWS for running containers."""
category = base.COMPUTE_CATEGORY
def Filter(self, context, args):
del context, args

View File

@@ -0,0 +1,32 @@
# -*- coding: utf-8 -*- #
# Copyright 2021 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.
"""Command group `gcloud container aws clusters`."""
from __future__ import absolute_import
from __future__ import division
from __future__ import unicode_literals
from googlecloudsdk.calliope import base
from googlecloudsdk.command_lib.projects import util
from googlecloudsdk.core import log
@base.ReleaseTracks(base.ReleaseTrack.ALPHA, base.ReleaseTrack.GA)
class Clusters(base.Group):
"""Create and manage Anthos clusters on AWS."""
@staticmethod
def Args(parser):
pass

View File

@@ -0,0 +1,132 @@
# -*- coding: utf-8 -*- #
# Copyright 2021 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.
"""Command to create an Anthos cluster on AWS."""
from __future__ import absolute_import
from __future__ import division
from __future__ import unicode_literals
from googlecloudsdk.api_lib.container.gkemulticloud import aws as api_util
from googlecloudsdk.calliope import arg_parsers
from googlecloudsdk.calliope import base
from googlecloudsdk.command_lib.container.aws import flags as aws_flags
from googlecloudsdk.command_lib.container.aws import resource_args
from googlecloudsdk.command_lib.container.gkemulticloud import command_util
from googlecloudsdk.command_lib.container.gkemulticloud import constants
from googlecloudsdk.command_lib.container.gkemulticloud import endpoint_util
from googlecloudsdk.command_lib.container.gkemulticloud import flags
# Command needs to be in one line for the docgen tool to format properly.
_EXAMPLES = """
To create a cluster named ``my-cluster'' managed in location ``us-west1'',
run:
$ {command} my-cluster --location=us-west1 --aws-region=AWS_REGION --cluster-version=CLUSTER_VERSION --database-encryption-kms-key-arn=KMS_KEY_ARN --iam-instance-profile=IAM_INSTANCE_PROFILE --pod-address-cidr-blocks=POD_ADDRESS_CIDR_BLOCKS --role-arn=ROLE_ARN --service-address-cidr-blocks=SERVICE_ADDRESS_CIDR_BLOCKS --subnet-ids=SUBNET_ID --vpc-id=VPC_ID
"""
@base.ReleaseTracks(base.ReleaseTrack.GA)
class Create(base.CreateCommand):
"""Create an Anthos cluster on AWS."""
detailed_help = {'EXAMPLES': _EXAMPLES}
@staticmethod
def Args(parser):
"""Registers flags for this command."""
resource_args.AddAwsClusterResourceArg(parser, 'to create')
parser.add_argument(
'--subnet-ids',
required=True,
type=arg_parsers.ArgList(),
metavar='SUBNET_ID',
help=(
'Subnet ID of an existing VNET to use for the cluster control'
' plane.'
),
)
flags.AddPodAddressCidrBlocks(parser)
flags.AddServiceAddressCidrBlocks(parser)
flags.AddClusterVersion(parser)
flags.AddRootVolumeSize(parser)
flags.AddMainVolumeSize(parser)
flags.AddValidateOnly(parser, 'cluster to create')
flags.AddFleetProject(parser)
flags.AddTags(parser, 'cluster')
flags.AddAdminUsers(parser)
flags.AddAdminGroups(parser)
flags.AddDescription(parser)
flags.AddAnnotations(parser)
flags.AddLogging(parser)
flags.AddMonitoringConfig(parser, True)
flags.AddBinauthzEvaluationMode(parser)
aws_flags.AddAwsRegion(parser)
aws_flags.AddIamInstanceProfile(parser)
aws_flags.AddInstanceType(parser)
aws_flags.AddSshEC2KeyPair(parser)
aws_flags.AddConfigEncryptionKmsKeyArn(parser)
aws_flags.AddDatabaseEncryptionKmsKeyArn(parser)
aws_flags.AddRoleArn(parser)
aws_flags.AddRoleSessionName(parser)
aws_flags.AddVpcId(parser)
aws_flags.AddSecurityGroupIds(parser, kind='control plane')
aws_flags.AddPerNodePoolSGRules(parser)
aws_flags.AddRootVolumeType(parser)
aws_flags.AddRootVolumeIops(parser)
aws_flags.AddRootVolumeThroughput(parser)
aws_flags.AddRootVolumeKmsKeyArn(parser)
aws_flags.AddMainVolumeType(parser)
aws_flags.AddMainVolumeIops(parser)
aws_flags.AddMainVolumeThroughput(parser)
aws_flags.AddMainVolumeKmsKeyArn(parser)
aws_flags.AddProxyConfig(parser)
base.ASYNC_FLAG.AddToParser(parser)
parser.display_info.AddFormat(constants.AWS_CLUSTERS_FORMAT)
def Run(self, args):
"""Runs the create command."""
location = resource_args.ParseAwsClusterResourceArg(args).locationsId
with endpoint_util.GkemulticloudEndpointOverride(location):
cluster_ref = resource_args.ParseAwsClusterResourceArg(args)
cluster_client = api_util.ClustersClient()
message = command_util.ClusterMessage(
cluster_ref.awsClustersId,
action='Creating',
kind=constants.AWS,
region=args.aws_region,
)
return command_util.Create(
resource_ref=cluster_ref,
resource_client=cluster_client,
args=args,
message=message,
kind=constants.AWS_CLUSTER_KIND,
)
@base.ReleaseTracks(base.ReleaseTrack.ALPHA)
class CreateAlpha(Create):
"""Create an Anthos cluster on AWS."""
@staticmethod
def Args(parser, track=base.ReleaseTrack.ALPHA):
"""Registers alpha track flags for this command."""
Create.Args(parser)
aws_flags.AddInstancePlacement(parser)

View File

@@ -0,0 +1,72 @@
# -*- coding: utf-8 -*- #
# Copyright 2021 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.
"""Command to delete an Anthos cluster on AWS."""
from __future__ import absolute_import
from __future__ import division
from __future__ import unicode_literals
from googlecloudsdk.api_lib.container.gkemulticloud import aws as api_util
from googlecloudsdk.calliope import base
from googlecloudsdk.command_lib.container.aws import resource_args
from googlecloudsdk.command_lib.container.gkemulticloud import command_util
from googlecloudsdk.command_lib.container.gkemulticloud import constants
from googlecloudsdk.command_lib.container.gkemulticloud import endpoint_util
from googlecloudsdk.command_lib.container.gkemulticloud import flags
_EXAMPLES = """
To delete a cluster named ``my-cluster'' managed in location ``us-west1'',
run:
$ {command} my-cluster --location=us-west1
"""
@base.ReleaseTracks(base.ReleaseTrack.ALPHA, base.ReleaseTrack.GA)
class Delete(base.DeleteCommand):
"""Delete an Anthos cluster on AWS."""
detailed_help = {'EXAMPLES': _EXAMPLES}
@staticmethod
def Args(parser):
"""Register flags for this command."""
resource_args.AddAwsClusterResourceArg(parser, 'to delete')
flags.AddValidateOnly(parser, 'cluster to delete')
flags.AddAllowMissing(parser, 'cluster')
flags.AddIgnoreErrors(parser, constants.AWS, 'cluster')
base.ASYNC_FLAG.AddToParser(parser)
def Run(self, args):
"""Runs the delete command."""
location = resource_args.ParseAwsClusterResourceArg(args).locationsId
with endpoint_util.GkemulticloudEndpointOverride(location):
cluster_ref = resource_args.ParseAwsClusterResourceArg(args)
cluster_client = api_util.ClustersClient()
cluster = cluster_client.Get(cluster_ref)
message = command_util.ClusterMessage(
cluster_ref.awsClustersId,
kind=constants.AWS,
region=cluster.awsRegion,
)
command_util.DeleteWithIgnoreErrors(
args,
cluster_client,
cluster_ref,
message,
constants.AWS_CLUSTER_KIND,
)

View File

@@ -0,0 +1,63 @@
# -*- coding: utf-8 -*- #
# Copyright 2021 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.
"""Command to describe an Anthos cluster on AWS."""
from __future__ import absolute_import
from __future__ import division
from __future__ import unicode_literals
from googlecloudsdk.api_lib.container.gkemulticloud import aws as api_util
from googlecloudsdk.calliope import base
from googlecloudsdk.command_lib.container.aws import resource_args
from googlecloudsdk.command_lib.container.gkemulticloud import constants
from googlecloudsdk.command_lib.container.gkemulticloud import endpoint_util
from googlecloudsdk.command_lib.container.gkemulticloud import versions
from googlecloudsdk.core import log
_EXAMPLES = """
To describe a cluster named ``my-cluster'' managed in location ``us-west1'',
run:
$ {command} my-cluster --location=us-west1
"""
@base.ReleaseTracks(base.ReleaseTrack.ALPHA, base.ReleaseTrack.GA)
class Describe(base.DescribeCommand):
"""Describe an Anthos cluster on AWS."""
detailed_help = {'EXAMPLES': _EXAMPLES}
@staticmethod
def Args(parser):
"""Registers flags for this command."""
resource_args.AddAwsClusterResourceArg(parser, 'to describe')
def Run(self, args):
"""Runs the describe command."""
self._upgrade_hint = None
cluster_ref = resource_args.ParseAwsClusterResourceArg(args)
with endpoint_util.GkemulticloudEndpointOverride(cluster_ref.locationsId):
cluster_client = api_util.ClustersClient()
cluster_info = cluster_client.Get(cluster_ref)
self._upgrade_hint = versions.upgrade_hint_cluster(
cluster_ref, cluster_info, constants.AWS
)
return cluster_info
def Epilog(self, results_were_displayed):
if self._upgrade_hint:
log.status.Print(self._upgrade_hint)

View File

@@ -0,0 +1,95 @@
# -*- coding: utf-8 -*- #
# Copyright 2021 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.
"""Command to get credentials of an Anthos cluster on AWS."""
from __future__ import absolute_import
from __future__ import division
from __future__ import unicode_literals
from googlecloudsdk.api_lib.container.gkemulticloud import aws as api_util
from googlecloudsdk.api_lib.container.gkemulticloud import util
from googlecloudsdk.calliope import base
from googlecloudsdk.command_lib.container.aws import resource_args
from googlecloudsdk.command_lib.container.gkemulticloud import endpoint_util
from googlecloudsdk.command_lib.container.gkemulticloud import flags
from googlecloudsdk.command_lib.container.gkemulticloud import kubeconfig
from googlecloudsdk.core import log
@base.ReleaseTracks(base.ReleaseTrack.ALPHA, base.ReleaseTrack.GA)
class GetCredentials(base.Command):
"""Get credentials of an Anthos cluster on AWS."""
detailed_help = {
'EXAMPLES': kubeconfig.COMMAND_EXAMPLE,
'DESCRIPTION': kubeconfig.COMMAND_DESCRIPTION.format(
cluster_type='Anthos cluster on AWS'
),
}
@staticmethod
def Args(parser):
resource_args.AddAwsClusterResourceArg(parser, 'to get credentials')
flags.AddAuthProviderCmdPath(parser)
flags.AddPrivateEndpoint(parser)
def Run(self, args):
"""Runs the get-credentials command."""
with endpoint_util.GkemulticloudEndpointOverride(
resource_args.ParseAwsClusterResourceArg(args).locationsId,
self.ReleaseTrack(),
):
cluster_ref = resource_args.ParseAwsClusterResourceArg(args)
cluster_client = api_util.ClustersClient()
log.status.Print('Fetching cluster endpoint and auth data.')
resp = cluster_client.Get(cluster_ref)
if (
resp.state
!= util.GetMessagesModule().GoogleCloudGkemulticloudV1AwsCluster.StateValueValuesEnum.RUNNING
):
log.warning(
kubeconfig.NOT_RUNNING_MSG.format(cluster_ref.awsClustersId)
)
if not args.private_endpoint and kubeconfig.ConnectGatewayInNodePools(
resp, cluster_ref.awsClustersId
):
kubeconfig.CheckClusterHasNodePools(
api_util.NodePoolsClient(), cluster_ref
)
kubeconfig.ValidateClusterVersion(resp, cluster_ref.awsClustersId)
context = kubeconfig.GenerateContext(
'aws',
cluster_ref.projectsId,
cluster_ref.locationsId,
cluster_ref.awsClustersId,
)
cmd_args = kubeconfig.GenerateAuthProviderCmdArgs(
'aws',
cluster_ref.awsClustersId,
cluster_ref.locationsId,
cluster_ref.projectsId,
)
kubeconfig.GenerateKubeconfig(
resp,
cluster_ref.awsClustersId,
context,
args.auth_provider_cmd_path,
cmd_args,
args.private_endpoint,
)

View File

@@ -0,0 +1,74 @@
# -*- coding: utf-8 -*- #
# Copyright 2021 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.
"""Command to list Anthos clusters on AWS."""
from __future__ import absolute_import
from __future__ import division
from __future__ import unicode_literals
from googlecloudsdk.api_lib.container.gkemulticloud import aws as api_util
from googlecloudsdk.calliope import base
from googlecloudsdk.command_lib.container.aws import resource_args
from googlecloudsdk.command_lib.container.gkemulticloud import constants
from googlecloudsdk.command_lib.container.gkemulticloud import endpoint_util
from googlecloudsdk.command_lib.container.gkemulticloud import versions
from googlecloudsdk.core import log
_EXAMPLES = """
To lists all clusters managed in location ``us-west1'', run:
$ {command} --location=us-west1
"""
@base.ReleaseTracks(base.ReleaseTrack.ALPHA, base.ReleaseTrack.GA)
class List(base.ListCommand):
"""List Anthos clusters on AWS."""
detailed_help = {'EXAMPLES': _EXAMPLES}
@staticmethod
def Args(parser):
resource_args.AddLocationResourceArg(parser, 'to list')
parser.display_info.AddFormat(constants.AWS_CLUSTERS_FORMAT)
def Run(self, args):
"""Runs the list command."""
self._upgrade_hint = None
location_ref = args.CONCEPTS.location.Parse()
with endpoint_util.GkemulticloudEndpointOverride(location_ref.locationsId):
cluster_client = api_util.ClustersClient()
items, is_empty = cluster_client.List(
location_ref, args.page_size, args.limit
)
if is_empty:
return items
platform = constants.AWS
cluster_info_table, end_of_life_flag = (
versions.generate_cluster_versions_table(
location_ref,
platform,
items,
)
)
if end_of_life_flag:
self._upgrade_hint = versions.upgrade_hint_cluster_list(platform)
return cluster_info_table
def Epilog(self, results_were_displayed):
super(List, self).Epilog(results_were_displayed)
if self._upgrade_hint:
log.status.Print(self._upgrade_hint)

View File

@@ -0,0 +1,51 @@
# -*- coding: utf-8 -*- #
# Copyright 2021 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.
"""Command to print access tokens for an Anthos cluster on AWS."""
from __future__ import absolute_import
from __future__ import division
from __future__ import unicode_literals
from googlecloudsdk.api_lib.container.gkemulticloud import aws as api_util
from googlecloudsdk.calliope import base
from googlecloudsdk.command_lib.container.aws import resource_args
from googlecloudsdk.command_lib.container.gkemulticloud import endpoint_util
from googlecloudsdk.command_lib.container.gkemulticloud import flags
from googlecloudsdk.command_lib.container.gkemulticloud import kubeconfig
@base.Hidden
@base.ReleaseTracks(base.ReleaseTrack.ALPHA, base.ReleaseTrack.GA)
class PrintAccessToken(base.Command):
"""Generate an access token for an Anthos cluster on AWS."""
@staticmethod
def Args(parser):
"""Register flags for this command."""
resource_args.AddAwsClusterResourceArg(parser, 'to access')
flags.AddExecCredential(parser)
def Run(self, args):
"""Runs the command."""
cluster_ref = args.CONCEPTS.cluster.Parse()
with endpoint_util.GkemulticloudEndpointOverride(cluster_ref.locationsId):
cluster_client = api_util.ClustersClient()
response = cluster_client.GenerateAccessToken(cluster_ref)
if args.exec_credential:
return kubeconfig.ExecCredential(
expiration_timestamp=response.expirationTime,
access_token=response.accessToken,
)
return response

View File

@@ -0,0 +1,100 @@
# -*- coding: utf-8 -*- #
# Copyright 2021 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.
"""Command to update an Anthos cluster on AWS."""
from __future__ import absolute_import
from __future__ import division
from __future__ import unicode_literals
from googlecloudsdk.api_lib.container.gkemulticloud import aws as api_util
from googlecloudsdk.calliope import base
from googlecloudsdk.command_lib.container.aws import flags as aws_flags
from googlecloudsdk.command_lib.container.aws import resource_args
from googlecloudsdk.command_lib.container.gkemulticloud import command_util
from googlecloudsdk.command_lib.container.gkemulticloud import constants
from googlecloudsdk.command_lib.container.gkemulticloud import endpoint_util
from googlecloudsdk.command_lib.container.gkemulticloud import flags
# Command needs to be in one line for the docgen tool to format properly.
_EXAMPLES = """
To update a cluster named ``my-cluster'' managed in location ``us-west1'', run:
$ {command} my-cluster --location=us-west1 --cluster-version=CLUSTER_VERSION
"""
@base.ReleaseTracks(base.ReleaseTrack.GA)
class Update(base.UpdateCommand):
"""Update an Anthos cluster on AWS."""
detailed_help = {'EXAMPLES': _EXAMPLES}
@staticmethod
def Args(parser):
resource_args.AddAwsClusterResourceArg(parser, 'to update')
flags.AddClusterVersion(parser, required=False)
flags.AddValidateOnly(parser, 'update of the cluster')
flags.AddAdminUsers(parser, create=False)
flags.AddAdminGroups(parser)
flags.AddRootVolumeSize(parser)
flags.AddDescriptionForUpdate(parser)
flags.AddAnnotationsForUpdate(parser, 'cluster')
flags.AddTagsForUpdate(parser, 'control plane')
flags.AddLogging(parser)
flags.AddMonitoringConfig(parser)
flags.AddBinauthzEvaluationMode(parser)
aws_flags.AddInstanceType(parser)
aws_flags.AddRoleArn(parser, required=False)
aws_flags.AddRoleSessionName(parser)
aws_flags.AddConfigEncryptionKmsKeyArn(parser, required=False)
aws_flags.AddSecurityGroupFlagsForUpdate(parser, 'control plane')
aws_flags.AddPerNodePoolSGRulesForUpdate(parser)
aws_flags.AddProxyConfigForUpdate(parser, 'control plane')
aws_flags.AddRootVolumeKmsKeyArn(parser)
aws_flags.AddRootVolumeType(parser)
aws_flags.AddRootVolumeIops(parser)
aws_flags.AddRootVolumeThroughput(parser)
aws_flags.AddSshEC2KeyPairForUpdate(parser)
aws_flags.AddIamInstanceProfile(parser, required=False)
base.ASYNC_FLAG.AddToParser(parser)
parser.display_info.AddFormat(constants.AWS_CLUSTERS_FORMAT)
def Run(self, args):
"""Runs the update command."""
location = resource_args.ParseAwsClusterResourceArg(args).locationsId
with endpoint_util.GkemulticloudEndpointOverride(location):
cluster_ref = resource_args.ParseAwsClusterResourceArg(args)
cluster_client = api_util.ClustersClient()
message = command_util.ClusterMessage(
cluster_ref.awsClustersId, action='Updating'
)
return command_util.Update(
resource_ref=cluster_ref,
resource_client=cluster_client,
args=args,
message=message,
kind=constants.AWS_CLUSTER_KIND,
)
@base.ReleaseTracks(base.ReleaseTrack.ALPHA)
class UpdateAlpha(Update):
"""Update an Anthos cluster on AWS."""
@staticmethod
def Args(parser, track=base.ReleaseTrack.ALPHA):
"""Registers alpha track flags for this command."""
Update.Args(parser)

View File

@@ -0,0 +1,57 @@
# -*- coding: utf-8 -*- #
# Copyright 2021 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.
"""Command to get Anthos Multi-Cloud server configuration for AWS."""
from __future__ import absolute_import
from __future__ import division
from __future__ import unicode_literals
from googlecloudsdk.api_lib.container.gkemulticloud import locations as api_util
from googlecloudsdk.calliope import base
from googlecloudsdk.command_lib.container.aws import resource_args
from googlecloudsdk.command_lib.container.gkemulticloud import constants
from googlecloudsdk.command_lib.container.gkemulticloud import endpoint_util
from googlecloudsdk.core import log
_EXAMPLES = """
To return supported AWS regions and valid versions in location ``us-west1'', run:
$ {command} --location=us-west1
"""
@base.ReleaseTracks(base.ReleaseTrack.ALPHA, base.ReleaseTrack.GA)
class GetServerConfig(base.Command):
"""Get Anthos Multi-Cloud server configuration for AWS."""
detailed_help = {'EXAMPLES': _EXAMPLES}
@staticmethod
def Args(parser):
resource_args.AddLocationResourceArg(parser, 'to get server configuration')
parser.display_info.AddFormat(constants.AWS_SERVER_CONFIG_FORMAT)
def Run(self, args):
"""Runs the get-server-config command."""
location_ref = args.CONCEPTS.location.Parse()
with endpoint_util.GkemulticloudEndpointOverride(location_ref.locationsId):
log.status.Print(
'Fetching server config for {location}'.format(
location=location_ref.locationsId
)
)
client = api_util.LocationsClient()
return client.GetAwsServerConfig(location_ref)

View File

@@ -0,0 +1,32 @@
# -*- coding: utf-8 -*- #
# Copyright 2021 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.
"""Command group `gcloud container aws node-pools`."""
from __future__ import absolute_import
from __future__ import division
from __future__ import unicode_literals
from googlecloudsdk.calliope import base
from googlecloudsdk.command_lib.projects import util
from googlecloudsdk.core import log
@base.ReleaseTracks(base.ReleaseTrack.ALPHA, base.ReleaseTrack.GA)
class NodePools(base.Group):
"""Create and manage node pools in an Anthos cluster on AWS."""
@staticmethod
def Args(parser):
pass

View File

@@ -0,0 +1,113 @@
# -*- coding: utf-8 -*- #
# Copyright 2021 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.
"""Command to create a node pool in an Anthos cluster on AWS."""
from __future__ import absolute_import
from __future__ import division
from __future__ import unicode_literals
from googlecloudsdk.api_lib.container.gkemulticloud import aws as api_util
from googlecloudsdk.calliope import base
from googlecloudsdk.command_lib.container.aws import flags as aws_flags
from googlecloudsdk.command_lib.container.aws import resource_args
from googlecloudsdk.command_lib.container.gkemulticloud import command_util
from googlecloudsdk.command_lib.container.gkemulticloud import constants
from googlecloudsdk.command_lib.container.gkemulticloud import endpoint_util
from googlecloudsdk.command_lib.container.gkemulticloud import flags
# Command needs to be in one line for the docgen tool to format properly.
_EXAMPLES = """
To create a node pool named ``my-node-pool'' in a cluster named ``my-cluster''
managed in location ``us-west1'', run:
$ {command} my-node-pool --cluster=my-cluster --location=us-west1 --iam-instance-profile=IAM_INSTANCE_PROFILE --node-version=NODE_VERSION --subnet-id=SUBNET_ID
"""
@base.DefaultUniverseOnly
@base.ReleaseTracks(base.ReleaseTrack.GA)
class Create(base.CreateCommand):
"""Create a node pool in an Anthos cluster on AWS."""
detailed_help = {'EXAMPLES': _EXAMPLES}
@staticmethod
def Args(parser, track=base.ReleaseTrack.GA):
resource_args.AddAwsNodePoolResourceArg(parser, 'to create')
flags.AddNodeVersion(parser)
flags.AddSubnetID(parser, 'the node pool')
flags.AddAutoscaling(parser)
flags.AddMaxPodsPerNode(parser)
flags.AddRootVolumeSize(parser)
flags.AddValidateOnly(parser, 'node pool to create')
flags.AddTags(parser, 'node pool')
flags.AddNodeLabels(parser)
flags.AddNodeTaints(parser)
flags.AddAnnotations(parser, 'node pool')
flags.AddEnableAutoRepair(parser, True)
flags.AddMaxSurgeUpdate(parser)
flags.AddMaxUnavailableUpdate(parser, for_create=True)
aws_flags.AddOnDemandOrSpotInstanceType(parser, kind='node pool')
aws_flags.AddSshEC2KeyPair(parser, kind='node pool')
aws_flags.AddIamInstanceProfile(parser, kind='node pool')
aws_flags.AddSecurityGroupIds(parser, kind='node pool')
aws_flags.AddRootVolumeType(parser)
aws_flags.AddRootVolumeIops(parser)
aws_flags.AddRootVolumeThroughput(parser)
aws_flags.AddRootVolumeKmsKeyArn(parser)
aws_flags.AddProxyConfig(parser)
aws_flags.AddConfigEncryptionKmsKeyArn(parser)
aws_flags.AddAutoScalingMetricsCollection(parser)
aws_flags.AddKubeletConfigCpuManagerPolicy(parser)
aws_flags.AddKubeletConfigCpuCfsQuota(parser)
aws_flags.AddKubeletConfigCpuCfsQuotaPeriod(parser)
aws_flags.AddKubeletConfigPodPidsLimit(parser)
base.ASYNC_FLAG.AddToParser(parser)
parser.display_info.AddFormat(constants.AWS_NODEPOOLS_FORMAT)
def Run(self, args):
"""Runs the create command."""
location = resource_args.ParseAwsNodePoolResourceArg(args).locationsId
with endpoint_util.GkemulticloudEndpointOverride(location):
node_pool_ref = resource_args.ParseAwsNodePoolResourceArg(args)
node_pool_client = api_util.NodePoolsClient()
message = command_util.NodePoolMessage(
node_pool_ref.awsNodePoolsId,
action='Creating',
cluster=node_pool_ref.awsClustersId,
)
return command_util.Create(
resource_ref=node_pool_ref,
resource_client=node_pool_client,
args=args,
message=message,
kind=constants.AWS_NODEPOOL_KIND,
)
@base.DefaultUniverseOnly
@base.ReleaseTracks(base.ReleaseTrack.ALPHA)
class CreateAlpha(Create):
"""Create a node pool in an Anthos cluster on AWS."""
@staticmethod
def Args(parser):
"""Registers alpha track flags for this command."""
Create.Args(parser, base.ReleaseTrack.ALPHA)
aws_flags.AddInstancePlacement(parser)
flags.AddImageType(parser)

View File

@@ -0,0 +1,68 @@
# -*- coding: utf-8 -*- #
# Copyright 2021 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.
"""Command to delete a node pool in an Anthos cluster on AWS."""
from __future__ import absolute_import
from __future__ import division
from __future__ import unicode_literals
from googlecloudsdk.api_lib.container.gkemulticloud import aws as api_util
from googlecloudsdk.calliope import base
from googlecloudsdk.command_lib.container.aws import resource_args
from googlecloudsdk.command_lib.container.gkemulticloud import command_util
from googlecloudsdk.command_lib.container.gkemulticloud import constants
from googlecloudsdk.command_lib.container.gkemulticloud import endpoint_util
from googlecloudsdk.command_lib.container.gkemulticloud import flags
_EXAMPLES = """
To delete a node pool named ``my-node-pool'' in a cluster named ``my-cluster''
managed in location ``us-west1'', run:
$ {command} my-node-pool --cluster=my-cluster --location=us-west1
"""
@base.ReleaseTracks(base.ReleaseTrack.ALPHA, base.ReleaseTrack.GA)
class Delete(base.DeleteCommand):
"""Delete a node pool in an Anthos cluster on AWS."""
detailed_help = {'EXAMPLES': _EXAMPLES}
@staticmethod
def Args(parser):
resource_args.AddAwsNodePoolResourceArg(parser, 'to delete')
flags.AddValidateOnly(parser, 'node pool to delete')
flags.AddAllowMissing(parser, 'node pool')
flags.AddIgnoreErrors(parser, constants.AWS, 'node pool')
base.ASYNC_FLAG.AddToParser(parser)
def Run(self, args):
"""Runs the delete command."""
location = resource_args.ParseAwsNodePoolResourceArg(args).locationsId
with endpoint_util.GkemulticloudEndpointOverride(location):
node_pool_ref = resource_args.ParseAwsNodePoolResourceArg(args)
node_pool_client = api_util.NodePoolsClient()
message = command_util.NodePoolMessage(
node_pool_ref.awsNodePoolsId, cluster=node_pool_ref.awsClustersId
)
command_util.DeleteWithIgnoreErrors(
args,
node_pool_client,
node_pool_ref,
message,
constants.AWS_NODEPOOL_KIND,
)

View File

@@ -0,0 +1,62 @@
# -*- coding: utf-8 -*- #
# Copyright 2021 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.
"""Command to describe a node pool in an Anthos cluster on AWS."""
from __future__ import absolute_import
from __future__ import division
from __future__ import unicode_literals
from googlecloudsdk.api_lib.container.gkemulticloud import aws as api_util
from googlecloudsdk.calliope import base
from googlecloudsdk.command_lib.container.aws import resource_args
from googlecloudsdk.command_lib.container.gkemulticloud import constants
from googlecloudsdk.command_lib.container.gkemulticloud import endpoint_util
from googlecloudsdk.command_lib.container.gkemulticloud import versions
from googlecloudsdk.core import log
_EXAMPLES = """
To describe a node pool named ``my-node-pool'' in a cluster named
``my-cluster'' managed in location ``us-west1'', run:
$ {command} my-node-pool --cluster=my-cluster --location=us-west1
"""
@base.ReleaseTracks(base.ReleaseTrack.ALPHA, base.ReleaseTrack.GA)
class Describe(base.DescribeCommand):
"""Describe a node pool in an Anthos cluster on AWS."""
detailed_help = {'EXAMPLES': _EXAMPLES}
@staticmethod
def Args(parser):
resource_args.AddAwsNodePoolResourceArg(parser, 'to describe')
def Run(self, args):
"""Runs the describe command."""
self._upgrade_hint = None
node_pool_ref = resource_args.ParseAwsNodePoolResourceArg(args)
with endpoint_util.GkemulticloudEndpointOverride(node_pool_ref.locationsId):
node_pool_client = api_util.NodePoolsClient()
node_pool_info = node_pool_client.Get(node_pool_ref)
self._upgrade_hint = versions.upgrade_hint_node_pool(
node_pool_ref, node_pool_info, constants.AWS
)
return node_pool_info
def Epilog(self, results_were_displayed):
if self._upgrade_hint:
log.status.Print(self._upgrade_hint)

View File

@@ -0,0 +1,78 @@
# -*- coding: utf-8 -*- #
# Copyright 2021 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.
"""Command to list node pools in an Anthos cluster on AWS."""
from __future__ import absolute_import
from __future__ import division
from __future__ import unicode_literals
from googlecloudsdk.api_lib.container.gkemulticloud import aws as api_util
from googlecloudsdk.calliope import base
from googlecloudsdk.command_lib.container.aws import resource_args
from googlecloudsdk.command_lib.container.gkemulticloud import constants
from googlecloudsdk.command_lib.container.gkemulticloud import endpoint_util
from googlecloudsdk.command_lib.container.gkemulticloud import versions
from googlecloudsdk.core import log
_EXAMPLES = """
To list all node pools in a cluster named ``my-cluster''
managed in location ``us-west1'', run:
$ {command} --cluster=my-cluster --location=us-west1
"""
@base.ReleaseTracks(base.ReleaseTrack.ALPHA, base.ReleaseTrack.GA)
class List(base.ListCommand):
"""List node pools in an Anthos cluster on AWS."""
detailed_help = {'EXAMPLES': _EXAMPLES}
@staticmethod
def Args(parser):
resource_args.AddAwsClusterResourceArg(parser, 'to list', positional=False)
parser.display_info.AddFormat(constants.AWS_NODEPOOLS_FORMAT)
def Run(self, args):
"""Runs the list command."""
self._upgrade_hint = None
cluster_ref = args.CONCEPTS.cluster.Parse()
with endpoint_util.GkemulticloudEndpointOverride(cluster_ref.locationsId):
node_pool_client = api_util.NodePoolsClient()
items, is_empty = node_pool_client.List(
cluster_ref, args.page_size, args.limit
)
if is_empty:
return items
platform = constants.AWS
node_pool_info_table, end_of_life_flag = (
versions.generate_node_pool_versions_table(
cluster_ref,
platform,
items,
)
)
if end_of_life_flag:
self._upgrade_hint = versions.upgrade_hint_node_pool_list(
platform, cluster_ref
)
return node_pool_info_table
def Epilog(self, results_were_displayed):
super(List, self).Epilog(results_were_displayed)
if self._upgrade_hint:
log.status.Print(self._upgrade_hint)

View File

@@ -0,0 +1,64 @@
# -*- coding: utf-8 -*- #
# Copyright 2023 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.
"""Command to rollback a node pool in an Anthos cluster on AWS."""
from __future__ import absolute_import
from __future__ import division
from __future__ import unicode_literals
from googlecloudsdk.api_lib.container.gkemulticloud import aws as api_util
from googlecloudsdk.calliope import base
from googlecloudsdk.command_lib.container.aws import resource_args
from googlecloudsdk.command_lib.container.gkemulticloud import command_util
from googlecloudsdk.command_lib.container.gkemulticloud import constants
from googlecloudsdk.command_lib.container.gkemulticloud import endpoint_util
from googlecloudsdk.command_lib.container.gkemulticloud import flags
_EXAMPLES = """
To roll back a canceled or failed update in node pool named ``my-node-pool''
in a cluster named ``my-cluster'' managed in location ``us-west1'', run:
$ {command} my-node-pool --cluster=my-cluster --location=us-west1
"""
@base.ReleaseTracks(base.ReleaseTrack.ALPHA, base.ReleaseTrack.GA)
class Rollback(base.Command):
"""Rollback a node pool in an Anthos cluster on AWS."""
detailed_help = {'EXAMPLES': _EXAMPLES}
@staticmethod
def Args(parser):
resource_args.AddAwsNodePoolResourceArg(parser, 'to rollback')
flags.AddRespectPodDisruptionBudget(parser)
base.ASYNC_FLAG.AddToParser(parser)
def Run(self, args):
"""Runs the rollback command."""
location = resource_args.ParseAwsNodePoolResourceArg(args).locationsId
with endpoint_util.GkemulticloudEndpointOverride(location):
node_pool_ref = resource_args.ParseAwsNodePoolResourceArg(args)
node_pool_client = api_util.NodePoolsClient()
message = command_util.NodePoolMessage(
node_pool_ref.awsNodePoolsId, cluster=node_pool_ref.awsClustersId
)
return command_util.Rollback(
resource_ref=node_pool_ref,
resource_client=node_pool_client,
message=message,
args=args,
kind=constants.AWS_NODEPOOL_KIND,
)

View File

@@ -0,0 +1,100 @@
# -*- coding: utf-8 -*- #
# Copyright 2021 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.
"""Command to update a node pool in an Anthos cluster on AWS."""
from __future__ import absolute_import
from __future__ import division
from __future__ import unicode_literals
from googlecloudsdk.api_lib.container.gkemulticloud import aws as api_util
from googlecloudsdk.calliope import base
from googlecloudsdk.command_lib.container.aws import flags as aws_flags
from googlecloudsdk.command_lib.container.aws import resource_args
from googlecloudsdk.command_lib.container.gkemulticloud import command_util
from googlecloudsdk.command_lib.container.gkemulticloud import constants
from googlecloudsdk.command_lib.container.gkemulticloud import endpoint_util
from googlecloudsdk.command_lib.container.gkemulticloud import flags
# Command needs to be in one line for the docgen tool to format properly.
_EXAMPLES = """
To update a node pool named ``my-node-pool'' in a cluster named ``my-cluster''
managed in location ``us-west1'', run:
$ {command} my-node-pool --cluster=my-cluster --location=us-west1 --node-version=NODE_VERSION
"""
@base.ReleaseTracks(base.ReleaseTrack.GA)
class Update(base.UpdateCommand):
"""Update a node pool in an Anthos cluster on AWS."""
detailed_help = {'EXAMPLES': _EXAMPLES}
@staticmethod
def Args(parser):
resource_args.AddAwsNodePoolResourceArg(parser, 'to update')
flags.AddNodeVersion(parser, required=False)
flags.AddValidateOnly(parser, 'node pool to update')
flags.AddAutoscaling(parser, required=False)
flags.AddAnnotationsForUpdate(parser, 'node pool')
flags.AddTagsForUpdate(parser, 'node pool')
flags.AddRootVolumeSize(parser)
flags.AddNodeLabelsForUpdate(parser)
flags.AddEnableAutoRepair(parser, False)
flags.AddMaxSurgeUpdate(parser)
flags.AddMaxUnavailableUpdate(parser)
aws_flags.AddSecurityGroupFlagsForUpdate(parser, 'node pool')
aws_flags.AddRootVolumeKmsKeyArn(parser)
aws_flags.AddRootVolumeType(parser)
aws_flags.AddRootVolumeIops(parser)
aws_flags.AddRootVolumeThroughput(parser)
aws_flags.AddConfigEncryptionKmsKeyArn(parser, required=False)
aws_flags.AddProxyConfigForUpdate(parser, 'node pool')
aws_flags.AddSshEC2KeyPairForUpdate(parser, 'node pool')
aws_flags.AddIamInstanceProfile(parser, kind='node pool', required=False)
aws_flags.AddAutoScalingMetricsCollectionForUpdate(parser)
aws_flags.AddInstanceType(parser, kind='node pool')
base.ASYNC_FLAG.AddToParser(parser)
parser.display_info.AddFormat(constants.AWS_NODEPOOLS_FORMAT)
def Run(self, args):
"""Runs the update command."""
location = resource_args.ParseAwsNodePoolResourceArg(args).locationsId
with endpoint_util.GkemulticloudEndpointOverride(location):
node_pool_ref = resource_args.ParseAwsNodePoolResourceArg(args)
node_pool_client = api_util.NodePoolsClient()
message = command_util.NodePoolMessage(
node_pool_ref.awsNodePoolsId,
action='Updating',
cluster=node_pool_ref.awsClustersId,
)
return command_util.Update(
resource_ref=node_pool_ref,
resource_client=node_pool_client,
args=args,
message=message,
kind=constants.AWS_NODEPOOL_KIND,
)
@base.ReleaseTracks(base.ReleaseTrack.ALPHA)
class UpdateAlpha(Update):
"""Update a node pool in an Anthos cluster on AWS."""
@staticmethod
def Args(parser, track=base.ReleaseTrack.ALPHA):
"""Registers alpha track flags for this command."""
Update.Args(parser)

View File

@@ -0,0 +1,32 @@
# -*- coding: utf-8 -*- #
# Copyright 2021 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.
"""Command group `gcloud container aws operations`."""
from __future__ import absolute_import
from __future__ import division
from __future__ import unicode_literals
from googlecloudsdk.calliope import base
from googlecloudsdk.command_lib.projects import util
from googlecloudsdk.core import log
@base.ReleaseTracks(base.ReleaseTrack.ALPHA, base.ReleaseTrack.GA)
class Operations(base.Group):
"""Manage Anthos Multi-Cloud long running operations for AWS."""
@staticmethod
def Args(parser):
pass

View File

@@ -0,0 +1,58 @@
# -*- 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.
"""Command to cancel an operation."""
from __future__ import absolute_import
from __future__ import division
from __future__ import unicode_literals
from googlecloudsdk.api_lib.container.gkemulticloud import operations as op_api_util
from googlecloudsdk.calliope import base
from googlecloudsdk.command_lib.container.aws import resource_args
from googlecloudsdk.command_lib.container.gkemulticloud import command_util
from googlecloudsdk.command_lib.container.gkemulticloud import endpoint_util
from googlecloudsdk.core import log
_EXAMPLES = """
To cancel an operation in location ``us-west1'', run:
$ {command} OPERATION_ID --location=us-west1
"""
@base.ReleaseTracks(base.ReleaseTrack.ALPHA, base.ReleaseTrack.GA)
class Cancel(base.Command):
"""Cancel an operation."""
detailed_help = {'EXAMPLES': _EXAMPLES}
@staticmethod
def Args(parser):
"""Registers flags for this command."""
resource_args.AddOperationResourceArg(parser, 'to cancel')
def Run(self, args):
"""Runs the cancel command."""
with endpoint_util.GkemulticloudEndpointOverride(
resource_args.ParseOperationResourceArg(args).locationsId,
self.ReleaseTrack(),
):
op_client = op_api_util.OperationsClient()
op_ref = resource_args.ParseOperationResourceArg(args)
op = op_client.Get(op_ref)
command_util.CancelOperationPrompt(op.name)
op_client.Cancel(op_ref)
log.status.Print(command_util.CancelOperationMessage(op.name, 'aws'))
return op_client.Get(op_ref)

View File

@@ -0,0 +1,52 @@
# -*- coding: utf-8 -*- #
# Copyright 2021 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.
"""Command to describe an operation."""
from __future__ import absolute_import
from __future__ import division
from __future__ import unicode_literals
from googlecloudsdk.api_lib.container.gkemulticloud import operations as op_api_util
from googlecloudsdk.calliope import base
from googlecloudsdk.command_lib.container.aws import resource_args
from googlecloudsdk.command_lib.container.gkemulticloud import endpoint_util
_EXAMPLES = """
To describe an operation in location ``us-west1'', run:
$ {command} OPERATION_ID --location=us-west1
"""
@base.ReleaseTracks(base.ReleaseTrack.ALPHA, base.ReleaseTrack.GA)
class Describe(base.DescribeCommand):
"""Describe an operation."""
detailed_help = {'EXAMPLES': _EXAMPLES}
@staticmethod
def Args(parser):
"""Registers flags for this command."""
resource_args.AddOperationResourceArg(parser, 'to describe')
def Run(self, args):
"""Runs the describe command."""
with endpoint_util.GkemulticloudEndpointOverride(
resource_args.ParseOperationResourceArg(args).locationsId,
self.ReleaseTrack(),
):
op_client = op_api_util.OperationsClient()
op_ref = resource_args.ParseOperationResourceArg(args)
return op_client.Get(op_ref)

View File

@@ -0,0 +1,61 @@
# -*- coding: utf-8 -*- #
# Copyright 2021 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.
"""Commmand to list operations."""
from __future__ import absolute_import
from __future__ import division
from __future__ import unicode_literals
from googlecloudsdk.api_lib.container.gkemulticloud import operations as op_api_util
from googlecloudsdk.calliope import base
from googlecloudsdk.command_lib.container.aws import resource_args
from googlecloudsdk.command_lib.container.gkemulticloud import endpoint_util
from googlecloudsdk.command_lib.container.gkemulticloud import operations
_EXAMPLES = """
To list all operations in location ``us-west1'', run:
$ {command} --location=us-west1
"""
@base.ReleaseTracks(base.ReleaseTrack.ALPHA, base.ReleaseTrack.GA)
class List(base.ListCommand):
"""List operations."""
detailed_help = {'EXAMPLES': _EXAMPLES}
@staticmethod
def Args(parser):
"""Registers flags for this command."""
resource_args.AddLocationResourceArg(parser, 'to list operations')
operations.AddFormat(parser)
def Run(self, args):
"""Runs the describe command."""
release_track = self.ReleaseTrack()
location_ref = args.CONCEPTS.location.Parse()
with endpoint_util.GkemulticloudEndpointOverride(
location_ref.locationsId, release_track
):
op_client = op_api_util.OperationsClient()
items, empty = op_client.List(
location_ref, args.page_size, args.limit, parent_field='name'
)
if not empty:
# ListOperations returns AWS, Azure, and attached operations.
# Add a filter for AWS operations.
operations.AddFilter(args, 'aws')
return items

View File

@@ -0,0 +1,56 @@
# -*- coding: utf-8 -*- #
# Copyright 2021 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.
"""Command to wait for an operation to complete."""
from __future__ import absolute_import
from __future__ import division
from __future__ import unicode_literals
from googlecloudsdk.api_lib.container.gkemulticloud import operations as op_api_util
from googlecloudsdk.calliope import base
from googlecloudsdk.command_lib.container.aws import resource_args
from googlecloudsdk.command_lib.container.gkemulticloud import endpoint_util
_EXAMPLES = """
To wait for an operation in location ``us-west1'' to complete, run:
$ {command} OPERATION_ID --location=us-west1
"""
@base.ReleaseTracks(base.ReleaseTrack.ALPHA, base.ReleaseTrack.GA)
class Describe(base.DescribeCommand):
"""Wait for an operation to complete."""
detailed_help = {'EXAMPLES': _EXAMPLES}
@staticmethod
def Args(parser):
"""Registers flags for this command."""
resource_args.AddOperationResourceArg(parser, 'to wait for')
def Run(self, args):
"""Runs the wait command."""
with endpoint_util.GkemulticloudEndpointOverride(
resource_args.ParseOperationResourceArg(args).locationsId,
self.ReleaseTrack(),
):
op_client = op_api_util.OperationsClient()
op_ref = resource_args.ParseOperationResourceArg(args)
op_client.Wait(
op_ref,
'Waiting for operation {} to complete'.format(op_ref.RelativeName()),
)
return op_client.Get(op_ref)

View File

@@ -0,0 +1,44 @@
# -*- coding: utf-8 -*- #
# Copyright 2021 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.
"""Command group `gcloud container azure`."""
from __future__ import absolute_import
from __future__ import division
from __future__ import unicode_literals
from googlecloudsdk.calliope import base
from googlecloudsdk.command_lib.projects import util
@base.Deprecate(
is_removed=False,
warning=(
"This command is deprecated. See"
" https://cloud.google.com/kubernetes-engine/multi-cloud/docs/azure/deprecations/deprecation-announcement"
" for more details."
),
error=(
"This command has been removed. See"
" https://cloud.google.com/kubernetes-engine/multi-cloud/docs/azure/deprecations/deprecation-announcement"
" for more details."
),
)
@base.UniverseCompatible
@base.ReleaseTracks(base.ReleaseTrack.ALPHA, base.ReleaseTrack.GA)
class Azure(base.Group):
"""Deploy and manage clusters of machines on Azure for running containers."""
category = base.COMPUTE_CATEGORY

View File

@@ -0,0 +1,32 @@
# -*- coding: utf-8 -*- #
# Copyright 2021 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.
"""Command group `gcloud container azure clients`."""
from __future__ import absolute_import
from __future__ import division
from __future__ import unicode_literals
from googlecloudsdk.calliope import base
from googlecloudsdk.command_lib.projects import util
from googlecloudsdk.core import log
@base.ReleaseTracks(base.ReleaseTrack.ALPHA, base.ReleaseTrack.GA)
class Clients(base.Group):
"""Create and manage Azure clients."""
@staticmethod
def Args(parser):
pass

View File

@@ -0,0 +1,81 @@
# -*- coding: utf-8 -*- #
# Copyright 2021 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.
"""Command to create an Azure client."""
from __future__ import absolute_import
from __future__ import division
from __future__ import unicode_literals
from googlecloudsdk.api_lib.container.gkemulticloud import azure as api_util
from googlecloudsdk.calliope import base
from googlecloudsdk.command_lib.container.azure import resource_args
from googlecloudsdk.command_lib.container.gkemulticloud import command_util
from googlecloudsdk.command_lib.container.gkemulticloud import constants
from googlecloudsdk.command_lib.container.gkemulticloud import endpoint_util
from googlecloudsdk.command_lib.container.gkemulticloud import flags
# Command needs to be in one line for the docgen tool to format properly.
_EXAMPLES = """
To create an Azure client named ``my-client'' in
location ``us-west1'', run:
$ {command} my-client --location=us-west1 --application-id=APP_ID --tenant-id=TENANT_ID
"""
@base.ReleaseTracks(base.ReleaseTrack.ALPHA, base.ReleaseTrack.GA)
class Create(base.CreateCommand):
"""Create an Azure client."""
detailed_help = {"EXAMPLES": _EXAMPLES}
@staticmethod
def Args(parser):
resource_args.AddAzureClientResourceArg(parser, "to create")
parser.add_argument(
"--tenant-id",
required=True,
help=(
"Azure Active Directory (AAD) tenant ID (GUID) to associate with"
" the client."
),
)
parser.add_argument(
"--application-id",
required=True,
dest="app_id",
help="Azure Active Directory (AAD) Application/Client ID (GUID).",
)
base.ASYNC_FLAG.AddToParser(parser)
flags.AddValidateOnly(parser, "creation of the client")
parser.display_info.AddFormat(constants.AZURE_CLIENT_FORMAT)
def Run(self, args):
"""Runs the create command."""
location = resource_args.ParseAzureClientResourceArg(args).locationsId
with endpoint_util.GkemulticloudEndpointOverride(location):
client_ref = resource_args.ParseAzureClientResourceArg(args)
api_client = api_util.ClientsClient()
message = command_util.ClientMessage(
client_ref.azureClientsId, action="Creating"
)
return command_util.Create(
resource_ref=client_ref,
resource_client=api_client,
message=message,
args=args,
kind=constants.AZURE_CLIENT_KIND,
)

View File

@@ -0,0 +1,64 @@
# -*- coding: utf-8 -*- #
# Copyright 2021 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.
"""Command to delete an Azure Client."""
from __future__ import absolute_import
from __future__ import division
from __future__ import unicode_literals
from googlecloudsdk.api_lib.container.gkemulticloud import azure as api_util
from googlecloudsdk.calliope import base
from googlecloudsdk.command_lib.container.azure import resource_args
from googlecloudsdk.command_lib.container.gkemulticloud import command_util
from googlecloudsdk.command_lib.container.gkemulticloud import constants
from googlecloudsdk.command_lib.container.gkemulticloud import endpoint_util
from googlecloudsdk.command_lib.container.gkemulticloud import flags
_EXAMPLES = """
To delete an Azure client named ``my-client'' in location ``us-west1'', run:
$ {command} my-client --location=us-west1
"""
@base.ReleaseTracks(base.ReleaseTrack.ALPHA, base.ReleaseTrack.GA)
class Delete(base.DeleteCommand):
"""Delete an Azure client."""
detailed_help = {'EXAMPLES': _EXAMPLES}
@staticmethod
def Args(parser):
resource_args.AddAzureClientResourceArg(parser, 'to delete')
base.ASYNC_FLAG.AddToParser(parser)
flags.AddAllowMissing(parser, 'client')
def Run(self, args):
"""Runs the delete command."""
location = resource_args.ParseAzureClientResourceArg(args).locationsId
with endpoint_util.GkemulticloudEndpointOverride(location):
client_ref = resource_args.ParseAzureClientResourceArg(args)
api_client = api_util.ClientsClient()
message = command_util.ClientMessage(
client_ref.azureClientsId, region=location
)
return command_util.Delete(
resource_ref=client_ref,
resource_client=api_client,
message=message,
args=args,
kind=constants.AZURE_CLIENT_KIND,
)

View File

@@ -0,0 +1,53 @@
# -*- coding: utf-8 -*- #
# Copyright 2021 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.
"""Command to describe an Azure Client."""
from __future__ import absolute_import
from __future__ import division
from __future__ import unicode_literals
from googlecloudsdk.api_lib.container.gkemulticloud import azure as api_util
from googlecloudsdk.calliope import base
from googlecloudsdk.command_lib.container.azure import resource_args
from googlecloudsdk.command_lib.container.gkemulticloud import endpoint_util
_EXAMPLES = """
To describe an Azure client named ``my-client'' in
location ``us-west1'', run:
$ {command} my-client --location=us-west1
"""
@base.ReleaseTracks(base.ReleaseTrack.ALPHA, base.ReleaseTrack.GA)
class Describe(base.DescribeCommand):
"""Describe an Azure client."""
detailed_help = {'EXAMPLES': _EXAMPLES}
@staticmethod
def Args(parser):
resource_args.AddAzureClientResourceArg(parser, 'to describe')
def Run(self, args):
"""Runs the describe command."""
with endpoint_util.GkemulticloudEndpointOverride(
resource_args.ParseAzureClientResourceArg(args).locationsId,
self.ReleaseTrack(),
):
client_ref = resource_args.ParseAzureClientResourceArg(args)
api_client = api_util.ClientsClient()
return api_client.Get(client_ref)

View File

@@ -0,0 +1,83 @@
# -*- coding: utf-8 -*- #
# Copyright 2021 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.
"""Command to get the public certificate of an Azure Client."""
from __future__ import absolute_import
from __future__ import division
from __future__ import unicode_literals
import base64
from apitools.base.py import encoding
from googlecloudsdk.api_lib.container.gkemulticloud import azure as api_util
from googlecloudsdk.calliope import base
from googlecloudsdk.command_lib.container.azure import resource_args
from googlecloudsdk.command_lib.container.gkemulticloud import endpoint_util
from googlecloudsdk.command_lib.container.gkemulticloud import flags
from googlecloudsdk.core import log
_EXAMPLES = """
To get the public certificate of an Azure client named ``my-client'' in
location ``us-west1'', run:
$ {command} my-client --location=us-west1
To store the certificate in a file named ``client.crt'', run:
$ {command} my-client --location=us-west1 --output-file=client.crt
"""
@base.ReleaseTracks(base.ReleaseTrack.ALPHA, base.ReleaseTrack.GA)
class GetPublicCert(base.DescribeCommand):
"""Get the public certificate of an Azure client."""
detailed_help = {'EXAMPLES': _EXAMPLES}
@staticmethod
def Args(parser):
resource_args.AddAzureClientResourceArg(
parser, 'to get the public certificate'
)
flags.AddOutputFile(parser, 'to store PEM')
def Run(self, args):
"""Runs the get-public-cert command."""
with endpoint_util.GkemulticloudEndpointOverride(
resource_args.ParseAzureClientResourceArg(args).locationsId,
self.ReleaseTrack(),
):
client_ref = resource_args.ParseAzureClientResourceArg(args)
api_client = api_util.ClientsClient()
client = api_client.Get(client_ref)
cert = self._GetCert(client)
log.WriteToFileOrStdout(
args.output_file if args.output_file else '-',
cert,
overwrite=True,
binary=False,
private=True,
)
def _GetCert(self, client):
if client.pemCertificate:
return client.pemCertificate
# Support older versions with certificate instead of pemCertificate.
# This is needed because "certificate" was removed from the proto so
# the apigen tool doesn't generate it in the AzureClient class.
client_dict = encoding.MessageToPyValue(client)
if 'certificate' in client_dict:
return base64.b64decode(client_dict['certificate'].encode('utf-8'))

View File

@@ -0,0 +1,54 @@
# -*- coding: utf-8 -*- #
# Copyright 2021 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.
"""Command to list Azure clients."""
from __future__ import absolute_import
from __future__ import division
from __future__ import unicode_literals
from googlecloudsdk.api_lib.container.gkemulticloud import azure as api_util
from googlecloudsdk.calliope import base
from googlecloudsdk.command_lib.container.azure import resource_args
from googlecloudsdk.command_lib.container.gkemulticloud import constants
from googlecloudsdk.command_lib.container.gkemulticloud import endpoint_util
_EXAMPLES = """
To lists all clients in location ``us-west1'', run:
$ {command} --location=us-west1
"""
@base.ReleaseTracks(base.ReleaseTrack.ALPHA, base.ReleaseTrack.GA)
class List(base.ListCommand):
"""List Azure clients."""
detailed_help = {'EXAMPLES': _EXAMPLES}
@staticmethod
def Args(parser):
resource_args.AddLocationResourceArg(parser, 'to list Azure clients')
parser.display_info.AddFormat(constants.AZURE_CLIENT_FORMAT)
def Run(self, args):
"""Runs the list command."""
location_ref = args.CONCEPTS.location.Parse()
with endpoint_util.GkemulticloudEndpointOverride(location_ref.locationsId):
api_client = api_util.ClientsClient()
items, _ = api_client.List(
location_ref, page_size=args.page_size, limit=args.limit
)
return items

View File

@@ -0,0 +1,32 @@
# -*- coding: utf-8 -*- #
# Copyright 2021 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.
"""Command group `gcloud container azure clusters`."""
from __future__ import absolute_import
from __future__ import division
from __future__ import unicode_literals
from googlecloudsdk.calliope import base
from googlecloudsdk.command_lib.projects import util
from googlecloudsdk.core import log
@base.ReleaseTracks(base.ReleaseTrack.ALPHA, base.ReleaseTrack.GA)
class Clusters(base.Group):
"""Create and manage Anthos clusters on Azure."""
@staticmethod
def Args(parser):
pass

View File

@@ -0,0 +1,109 @@
# -*- coding: utf-8 -*- #
# Copyright 2021 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.
"""Command to create an Anthos cluster on Azure."""
from __future__ import absolute_import
from __future__ import division
from __future__ import unicode_literals
from googlecloudsdk.api_lib.container.gkemulticloud import azure as api_util
from googlecloudsdk.calliope import base
from googlecloudsdk.command_lib.container.azure import resource_args
from googlecloudsdk.command_lib.container.gkemulticloud import command_util
from googlecloudsdk.command_lib.container.gkemulticloud import constants
from googlecloudsdk.command_lib.container.gkemulticloud import endpoint_util
from googlecloudsdk.command_lib.container.gkemulticloud import flags
# Command needs to be in one line for the docgen tool to format properly.
_EXAMPLES = """
To create a cluster named ``my-cluster'' managed in location ``us-west1'', run:
$ {command} my-cluster --location=us-west1 --azure-region=AZURE_REGION --cluster-version=CLUSTER_VERSION --client=CLIENT --pod-address-cidr-blocks=POD_ADDRESS_CIDR_BLOCKS --resource-group-id=RESOURCE_GROUP_ID --ssh-public-key=SSH_PUBLIC_KEY --subnet-id=SUBNET_ID --vnet-id=VNET_ID
"""
@base.ReleaseTracks(base.ReleaseTrack.GA)
class Create(base.CreateCommand):
"""Create an Anthos cluster on Azure."""
detailed_help = {'EXAMPLES': _EXAMPLES}
@staticmethod
def Args(parser):
auth_config_group = parser.add_argument_group(
'Authentication configuration', mutex=True, required=True
)
resource_args.AddAzureClusterAndClientResourceArgs(
parser, auth_config_group
)
flags.AddAzureServicesAuthentication(auth_config_group)
flags.AddAzureRegion(parser)
flags.AddEndpointSubnetId(parser)
flags.AddVnetId(parser)
flags.AddResourceGroupId(parser)
flags.AddServiceLoadBalancerSubnetId(parser)
flags.AddPodAddressCidrBlocks(parser)
flags.AddServiceAddressCidrBlocks(parser)
flags.AddClusterVersion(parser)
flags.AddSubnetID(parser, 'the cluster control plane', required=False)
flags.AddVMSize(parser)
flags.AddSSHPublicKey(parser)
flags.AddRootVolumeSize(parser)
flags.AddMainVolumeSize(parser)
flags.AddReplicaPlacements(parser)
flags.AddTags(parser, 'cluster')
flags.AddValidateOnly(parser, 'creation of the cluster')
flags.AddDatabaseEncryption(parser)
flags.AddConfigEncryption(parser)
flags.AddProxyConfig(parser)
flags.AddFleetProject(parser)
flags.AddAdminUsers(parser)
flags.AddAdminGroups(parser)
flags.AddDescription(parser)
flags.AddAnnotations(parser)
flags.AddLogging(parser)
flags.AddMonitoringConfig(parser, True)
base.ASYNC_FLAG.AddToParser(parser)
parser.display_info.AddFormat(constants.AZURE_CLUSTERS_FORMAT)
def Run(self, args):
"""Runs the create command."""
location = resource_args.ParseAzureClusterResourceArg(args).locationsId
with endpoint_util.GkemulticloudEndpointOverride(location):
cluster_ref = resource_args.ParseAzureClusterResourceArg(args)
cluster_client = api_util.ClustersClient()
message = command_util.ClusterMessage(
cluster_ref.azureClustersId,
action='Creating',
kind=constants.AZURE,
region=args.azure_region,
)
return command_util.Create(
resource_ref=cluster_ref,
resource_client=cluster_client,
args=args,
message=message,
kind=constants.AZURE_CLUSTER_KIND,
)
@base.ReleaseTracks(base.ReleaseTrack.ALPHA)
class CreateAlpha(Create):
"""Create an Anthos cluster on Azure."""
@staticmethod
def Args(parser, track=base.ReleaseTrack.ALPHA):
"""Registers alpha track flags for this command."""
Create.Args(parser)

View File

@@ -0,0 +1,69 @@
# -*- coding: utf-8 -*- #
# Copyright 2021 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.
"""Command to delete an Anthos cluster on Azure."""
from __future__ import absolute_import
from __future__ import division
from __future__ import unicode_literals
from googlecloudsdk.api_lib.container.gkemulticloud import azure as api_util
from googlecloudsdk.calliope import base
from googlecloudsdk.command_lib.container.azure import resource_args
from googlecloudsdk.command_lib.container.gkemulticloud import command_util
from googlecloudsdk.command_lib.container.gkemulticloud import constants
from googlecloudsdk.command_lib.container.gkemulticloud import endpoint_util
from googlecloudsdk.command_lib.container.gkemulticloud import flags
_EXAMPLES = """
To delete a cluster named ``my-cluster'' managed in location ``us-west1'', run:
$ {command} my-cluster --location=us-west1
"""
@base.ReleaseTracks(base.ReleaseTrack.ALPHA, base.ReleaseTrack.GA)
class Delete(base.DeleteCommand):
"""Delete an Anthos cluster on Azure."""
detailed_help = {'EXAMPLES': _EXAMPLES}
@staticmethod
def Args(parser):
resource_args.AddAzureClusterResourceArg(parser, 'to delete')
flags.AddAllowMissing(parser, 'cluster')
flags.AddIgnoreErrors(parser, constants.AZURE, 'cluster')
base.ASYNC_FLAG.AddToParser(parser)
def Run(self, args):
"""Runs the delete command."""
location = resource_args.ParseAzureClusterResourceArg(args).locationsId
with endpoint_util.GkemulticloudEndpointOverride(location):
cluster_ref = resource_args.ParseAzureClusterResourceArg(args)
cluster_client = api_util.ClustersClient()
cluster = cluster_client.Get(cluster_ref)
message = command_util.ClusterMessage(
cluster_ref.azureClustersId,
kind=constants.AZURE,
region=cluster.azureRegion,
)
command_util.DeleteWithIgnoreErrors(
args,
cluster_client,
cluster_ref,
message,
constants.AZURE_CLUSTER_KIND,
)

View File

@@ -0,0 +1,61 @@
# -*- coding: utf-8 -*- #
# Copyright 2021 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.
"""Command to describe an Anthos cluster on Azure."""
from __future__ import absolute_import
from __future__ import division
from __future__ import unicode_literals
from googlecloudsdk.api_lib.container.gkemulticloud import azure as api_util
from googlecloudsdk.calliope import base
from googlecloudsdk.command_lib.container.azure import resource_args
from googlecloudsdk.command_lib.container.gkemulticloud import constants
from googlecloudsdk.command_lib.container.gkemulticloud import endpoint_util
from googlecloudsdk.command_lib.container.gkemulticloud import versions
from googlecloudsdk.core import log
_EXAMPLES = """
To describe a cluster named ``my-cluster'' managed in location ``us-west1'', run:
$ {command} my-cluster --location=us-west1
"""
@base.ReleaseTracks(base.ReleaseTrack.ALPHA, base.ReleaseTrack.GA)
class Describe(base.DescribeCommand):
"""Describe an Anthos cluster on Azure."""
detailed_help = {'EXAMPLES': _EXAMPLES}
@staticmethod
def Args(parser):
resource_args.AddAzureClusterResourceArg(parser, 'to describe')
def Run(self, args):
"""Runs the describe command."""
self._upgrade_hint = None
cluster_ref = resource_args.ParseAzureClusterResourceArg(args)
with endpoint_util.GkemulticloudEndpointOverride(cluster_ref.locationsId):
cluster_client = api_util.ClustersClient()
cluster_info = cluster_client.Get(cluster_ref)
self._upgrade_hint = versions.upgrade_hint_cluster(
cluster_ref, cluster_info, constants.AZURE
)
return cluster_info
def Epilog(self, results_were_displayed):
if self._upgrade_hint:
log.status.Print(self._upgrade_hint)

View File

@@ -0,0 +1,95 @@
# -*- coding: utf-8 -*- #
# Copyright 2021 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.
"""Command to get credentials of an Anthos cluster on Azure."""
from __future__ import absolute_import
from __future__ import division
from __future__ import unicode_literals
from googlecloudsdk.api_lib.container.gkemulticloud import azure as api_util
from googlecloudsdk.api_lib.container.gkemulticloud import util
from googlecloudsdk.calliope import base
from googlecloudsdk.command_lib.container.azure import resource_args
from googlecloudsdk.command_lib.container.gkemulticloud import endpoint_util
from googlecloudsdk.command_lib.container.gkemulticloud import flags
from googlecloudsdk.command_lib.container.gkemulticloud import kubeconfig
from googlecloudsdk.core import log
@base.ReleaseTracks(base.ReleaseTrack.ALPHA, base.ReleaseTrack.GA)
class GetCredentials(base.Command):
"""Get credentials of an Anthos cluster on Azure."""
detailed_help = {
'EXAMPLES': kubeconfig.COMMAND_EXAMPLE,
'DESCRIPTION': kubeconfig.COMMAND_DESCRIPTION.format(
cluster_type='Anthos cluster on Azure'
),
}
@staticmethod
def Args(parser):
resource_args.AddAzureClusterResourceArg(parser, 'to get credentials')
flags.AddAuthProviderCmdPath(parser)
flags.AddPrivateEndpoint(parser)
def Run(self, args):
"""Runs the get-credentials command."""
with endpoint_util.GkemulticloudEndpointOverride(
resource_args.ParseAzureClusterResourceArg(args).locationsId,
self.ReleaseTrack(),
):
cluster_ref = resource_args.ParseAzureClusterResourceArg(args)
client = api_util.ClustersClient()
log.status.Print('Fetching cluster endpoint and auth data.')
resp = client.Get(cluster_ref)
if (
resp.state
!= util.GetMessagesModule().GoogleCloudGkemulticloudV1AzureCluster.StateValueValuesEnum.RUNNING
):
log.warning(
kubeconfig.NOT_RUNNING_MSG.format(cluster_ref.azureClustersId)
)
if not args.private_endpoint and kubeconfig.ConnectGatewayInNodePools(
resp, cluster_ref.azureClustersId
):
kubeconfig.CheckClusterHasNodePools(
api_util.NodePoolsClient(), cluster_ref
)
kubeconfig.ValidateClusterVersion(resp, cluster_ref.azureClustersId)
context = kubeconfig.GenerateContext(
'azure',
cluster_ref.projectsId,
cluster_ref.locationsId,
cluster_ref.azureClustersId,
)
cmd_args = kubeconfig.GenerateAuthProviderCmdArgs(
'azure',
cluster_ref.azureClustersId,
cluster_ref.locationsId,
cluster_ref.projectsId,
)
kubeconfig.GenerateKubeconfig(
resp,
cluster_ref.azureClustersId,
context,
args.auth_provider_cmd_path,
cmd_args,
args.private_endpoint,
)

View File

@@ -0,0 +1,75 @@
# -*- coding: utf-8 -*- #
# Copyright 2021 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.
"""Command to list Anthos clusters on Azure."""
from __future__ import absolute_import
from __future__ import division
from __future__ import unicode_literals
from googlecloudsdk.api_lib.container.gkemulticloud import azure as api_util
from googlecloudsdk.calliope import base
from googlecloudsdk.command_lib.container.azure import resource_args
from googlecloudsdk.command_lib.container.gkemulticloud import constants
from googlecloudsdk.command_lib.container.gkemulticloud import endpoint_util
from googlecloudsdk.command_lib.container.gkemulticloud import versions
from googlecloudsdk.core import log
_EXAMPLES = """
To lists all clusters managed in location ``us-west1'', run:
$ {command} --location=us-west1
"""
@base.ReleaseTracks(base.ReleaseTrack.ALPHA, base.ReleaseTrack.GA)
class List(base.ListCommand):
"""List Anthos clusters on Azure."""
detailed_help = {'EXAMPLES': _EXAMPLES}
@staticmethod
def Args(parser):
resource_args.AddLocationResourceArg(parser, 'to list Azure clusters')
parser.display_info.AddFormat(constants.AZURE_CLUSTERS_FORMAT)
def Run(self, args):
"""Runs the list command."""
self._upgrade_hint = None
location_ref = args.CONCEPTS.location.Parse()
with endpoint_util.GkemulticloudEndpointOverride(location_ref.locationsId):
api_client = api_util.ClustersClient()
items, is_empty = api_client.List(
location_ref, page_size=args.page_size, limit=args.limit
)
if is_empty:
return items
platform = constants.AZURE
cluster_info_table, end_of_life_flag = (
versions.generate_cluster_versions_table(
location_ref,
platform,
items,
)
)
if end_of_life_flag:
self._upgrade_hint = versions.upgrade_hint_cluster_list(platform)
return cluster_info_table
def Epilog(self, results_were_displayed):
super(List, self).Epilog(results_were_displayed)
if self._upgrade_hint:
log.status.Print(self._upgrade_hint)

View File

@@ -0,0 +1,54 @@
# -*- coding: utf-8 -*- #
# Copyright 2021 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.
"""Command to print access tokens for an Anthos cluster on Azure."""
from __future__ import absolute_import
from __future__ import division
from __future__ import unicode_literals
from googlecloudsdk.api_lib.container.gkemulticloud import azure as api_util
from googlecloudsdk.calliope import base
from googlecloudsdk.command_lib.container.azure import resource_args
from googlecloudsdk.command_lib.container.gkemulticloud import endpoint_util
from googlecloudsdk.command_lib.container.gkemulticloud import flags
from googlecloudsdk.command_lib.container.gkemulticloud import kubeconfig
@base.Hidden
@base.ReleaseTracks(base.ReleaseTrack.ALPHA, base.ReleaseTrack.GA)
class PrintAccessToken(base.Command):
"""Generate an access token for an Anthos cluster on Azure."""
@staticmethod
def Args(parser):
"""Registers flags for this command."""
resource_args.AddAzureClusterResourceArg(parser, "to access")
flags.AddExecCredential(parser)
def Run(self, args):
"""Runs the print-access-token command."""
with endpoint_util.GkemulticloudEndpointOverride(
resource_args.ParseAzureClusterResourceArg(args).locationsId,
self.ReleaseTrack(),
):
cluster_ref = resource_args.ParseAzureClusterResourceArg(args)
client = api_util.ClustersClient()
response = client.GenerateAccessToken(cluster_ref)
if args.exec_credential:
return kubeconfig.ExecCredential(
expiration_timestamp=response.expirationTime,
access_token=response.accessToken,
)
return response

View File

@@ -0,0 +1,90 @@
# -*- coding: utf-8 -*- #
# Copyright 2021 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.
"""Command to update an Anthos cluster on Azure."""
from __future__ import absolute_import
from __future__ import division
from __future__ import unicode_literals
from googlecloudsdk.api_lib.container.gkemulticloud import azure as api_util
from googlecloudsdk.calliope import base
from googlecloudsdk.command_lib.container.azure import resource_args
from googlecloudsdk.command_lib.container.gkemulticloud import command_util
from googlecloudsdk.command_lib.container.gkemulticloud import constants
from googlecloudsdk.command_lib.container.gkemulticloud import endpoint_util
from googlecloudsdk.command_lib.container.gkemulticloud import flags
# Command needs to be in one line for the docgen tool to format properly.
_EXAMPLES = """
To update a cluster named ``my-cluster'' managed in location ``us-west1'', run:
$ {command} my-cluster --location=us-west1 --cluster-version=CLUSTER_VERSION --client=CLIENT
"""
@base.ReleaseTracks(base.ReleaseTrack.GA)
class Update(base.UpdateCommand):
"""Update an Anthos cluster on Azure."""
detailed_help = {'EXAMPLES': _EXAMPLES}
@staticmethod
def Args(parser):
auth_config_group = parser.add_argument_group(
'Authentication configuration', mutex=True
)
resource_args.AddAzureClusterAndClientResourceArgs(
parser, auth_config_group, update=True
)
flags.AddAzureServicesAuthentication(auth_config_group, create=False)
flags.AddClusterVersion(parser, required=False)
flags.AddVMSize(parser)
flags.AddAdminUsers(parser, create=False)
flags.AddAdminGroups(parser)
flags.AddSSHPublicKey(parser, required=False)
flags.AddValidateOnly(parser, 'update of the cluster')
flags.AddDescriptionForUpdate(parser)
flags.AddAnnotationsForUpdate(parser, 'cluster')
flags.AddLogging(parser)
flags.AddMonitoringConfig(parser)
base.ASYNC_FLAG.AddToParser(parser)
parser.display_info.AddFormat(constants.AZURE_CLUSTERS_FORMAT)
def Run(self, args):
"""Runs the update command."""
location = resource_args.ParseAzureClusterResourceArg(args).locationsId
with endpoint_util.GkemulticloudEndpointOverride(location):
cluster_ref = resource_args.ParseAzureClusterResourceArg(args)
cluster_client = api_util.ClustersClient()
message = command_util.ClusterMessage(
cluster_ref.azureClustersId, action='Updating'
)
return command_util.Update(
resource_ref=cluster_ref,
resource_client=cluster_client,
args=args,
message=message,
kind=constants.AZURE_CLUSTER_KIND,
)
@base.ReleaseTracks(base.ReleaseTrack.ALPHA)
class UpdateAlpha(Update):
"""Update an Anthos cluster on Azure."""
@staticmethod
def Args(parser, track=base.ReleaseTrack.ALPHA):
"""Registers alpha track flags for this command."""
Update.Args(parser)

View File

@@ -0,0 +1,57 @@
# -*- coding: utf-8 -*- #
# Copyright 2021 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.
"""Command to get Anthos Multi-Cloud server configuration for Azure."""
from __future__ import absolute_import
from __future__ import division
from __future__ import unicode_literals
from googlecloudsdk.api_lib.container.gkemulticloud import locations as api_util
from googlecloudsdk.calliope import base
from googlecloudsdk.command_lib.container.azure import resource_args
from googlecloudsdk.command_lib.container.gkemulticloud import constants
from googlecloudsdk.command_lib.container.gkemulticloud import endpoint_util
from googlecloudsdk.core import log
_EXAMPLES = """
To return supported Azure regions and valid versions in location ``us-west1'', run:
$ {command} --location=us-west1
"""
@base.ReleaseTracks(base.ReleaseTrack.ALPHA, base.ReleaseTrack.GA)
class GetServerConfig(base.Command):
"""Get Anthos Multi-Cloud server configuration for Azure."""
detailed_help = {'EXAMPLES': _EXAMPLES}
@staticmethod
def Args(parser):
resource_args.AddLocationResourceArg(parser, 'to get server configuration')
parser.display_info.AddFormat(constants.AZURE_SERVER_CONFIG_FORMAT)
def Run(self, args):
"""Runs the get-server-config command."""
location_ref = args.CONCEPTS.location.Parse()
with endpoint_util.GkemulticloudEndpointOverride(location_ref.locationsId):
log.status.Print(
'Fetching server config for {location}'.format(
location=location_ref.locationsId
)
)
client = api_util.LocationsClient()
return client.GetAzureServerConfig(location_ref)

View File

@@ -0,0 +1,33 @@
# -*- coding: utf-8 -*- #
# Copyright 2021 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.
"""Command group `gcloud container azure node-pools`."""
from __future__ import absolute_import
from __future__ import division
from __future__ import unicode_literals
from googlecloudsdk.calliope import base
from googlecloudsdk.command_lib.projects import util
from googlecloudsdk.core import log
@base.ReleaseTracks(base.ReleaseTrack.ALPHA, base.ReleaseTrack.GA)
class NodePools(base.Group):
"""Create and manage node pools in an Anthos cluster on Azure."""
@staticmethod
def Args(parser):
pass

View File

@@ -0,0 +1,97 @@
# -*- coding: utf-8 -*- #
# Copyright 2021 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.
"""Command to create a node pool in an Anthos cluster on Azure."""
from __future__ import absolute_import
from __future__ import division
from __future__ import unicode_literals
from googlecloudsdk.api_lib.container.gkemulticloud import azure as api_util
from googlecloudsdk.calliope import base
from googlecloudsdk.command_lib.container.azure import resource_args
from googlecloudsdk.command_lib.container.gkemulticloud import command_util
from googlecloudsdk.command_lib.container.gkemulticloud import constants
from googlecloudsdk.command_lib.container.gkemulticloud import endpoint_util
from googlecloudsdk.command_lib.container.gkemulticloud import flags
# Command needs to be in one line for the docgen tool to format properly.
_EXAMPLES = """
To create a node pool named ``my-node-pool'' in a cluster named ``my-cluster''
managed in location ``us-west1'', run:
$ {command} my-node-pool --cluster=my-cluster --location=us-west1 --node-version=NODE_VERSION --ssh-public-key=SSH_PUBLIC_KEY --subnet-id=SUBNET_ID
"""
@base.ReleaseTracks(base.ReleaseTrack.GA)
class Create(base.CreateCommand):
"""Create a node pool in an Anthos cluster on Azure."""
detailed_help = {'EXAMPLES': _EXAMPLES}
@staticmethod
def Args(parser):
resource_args.AddAzureNodePoolResourceArg(
parser, 'to create', positional=True
)
flags.AddNodeVersion(parser)
flags.AddAutoscaling(parser)
flags.AddSubnetID(parser, 'the node pool')
flags.AddVMSize(parser)
flags.AddSSHPublicKey(parser)
flags.AddRootVolumeSize(parser)
flags.AddTags(parser, 'node pool')
flags.AddValidateOnly(parser, 'creation of the node pool')
flags.AddMaxPodsPerNode(parser)
flags.AddNodeLabels(parser)
flags.AddNodeTaints(parser)
flags.AddAzureAvailabilityZone(parser)
flags.AddProxyConfig(parser)
flags.AddConfigEncryption(parser)
flags.AddAnnotations(parser, 'node pool')
flags.AddEnableAutoRepair(parser, True)
base.ASYNC_FLAG.AddToParser(parser)
parser.display_info.AddFormat(constants.AZURE_NODE_POOL_FORMAT)
def Run(self, args):
"""Runs the create command."""
location = resource_args.ParseAzureNodePoolResourceArg(args).locationsId
with endpoint_util.GkemulticloudEndpointOverride(location):
node_pool_ref = resource_args.ParseAzureNodePoolResourceArg(args)
node_pool_client = api_util.NodePoolsClient()
message = command_util.NodePoolMessage(
node_pool_ref.azureNodePoolsId,
action='Creating',
cluster=node_pool_ref.azureClustersId,
)
return command_util.Create(
resource_ref=node_pool_ref,
resource_client=node_pool_client,
args=args,
message=message,
kind=constants.AZURE_NODEPOOL_KIND,
)
@base.ReleaseTracks(base.ReleaseTrack.ALPHA)
class CreateAlpha(Create):
"""Create a node pool in an Anthos cluster on Azure."""
@staticmethod
def Args(parser, track=base.ReleaseTrack.ALPHA):
"""Registers alpha track flags for this command."""
Create.Args(parser)
flags.AddImageType(parser)

View File

@@ -0,0 +1,67 @@
# -*- coding: utf-8 -*- #
# Copyright 2021 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.
"""Command to delete a node pool in an Anthos cluster on Azure."""
from __future__ import absolute_import
from __future__ import division
from __future__ import unicode_literals
from googlecloudsdk.api_lib.container.gkemulticloud import azure as api_util
from googlecloudsdk.calliope import base
from googlecloudsdk.command_lib.container.azure import resource_args
from googlecloudsdk.command_lib.container.gkemulticloud import command_util
from googlecloudsdk.command_lib.container.gkemulticloud import constants
from googlecloudsdk.command_lib.container.gkemulticloud import endpoint_util
from googlecloudsdk.command_lib.container.gkemulticloud import flags
_EXAMPLES = """
To delete a node pool named ``my-node-pool'' in a cluster named ``my-cluster''
managed in location ``us-west1'', run:
$ {command} my-node-pool --cluster=my-cluster --location=us-west1
"""
@base.ReleaseTracks(base.ReleaseTrack.ALPHA, base.ReleaseTrack.GA)
class Delete(base.DeleteCommand):
"""Delete a node pool in an Anthos cluster on Azure."""
detailed_help = {'EXAMPLES': _EXAMPLES}
@staticmethod
def Args(parser):
resource_args.AddAzureNodePoolResourceArg(parser, 'to delete')
flags.AddAllowMissing(parser, 'node pool')
flags.AddIgnoreErrors(parser, constants.AZURE, 'node pool')
base.ASYNC_FLAG.AddToParser(parser)
def Run(self, args):
"""Runs the delete command."""
location = resource_args.ParseAzureNodePoolResourceArg(args).locationsId
with endpoint_util.GkemulticloudEndpointOverride(location):
node_pool_ref = resource_args.ParseAzureNodePoolResourceArg(args)
node_pool_client = api_util.NodePoolsClient()
message = command_util.NodePoolMessage(
node_pool_ref.azureNodePoolsId, cluster=node_pool_ref.azureClustersId
)
command_util.DeleteWithIgnoreErrors(
args,
node_pool_client,
node_pool_ref,
message,
constants.AZURE_NODEPOOL_KIND,
)

View File

@@ -0,0 +1,63 @@
# -*- coding: utf-8 -*- #
# Copyright 2021 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.
"""Command to describe a node pool in an Anthos cluster on Azure."""
from __future__ import absolute_import
from __future__ import division
from __future__ import unicode_literals
from googlecloudsdk.api_lib.container.gkemulticloud import azure as api_util
from googlecloudsdk.calliope import base
from googlecloudsdk.command_lib.container.azure import resource_args
from googlecloudsdk.command_lib.container.gkemulticloud import constants
from googlecloudsdk.command_lib.container.gkemulticloud import endpoint_util
from googlecloudsdk.command_lib.container.gkemulticloud import versions
from googlecloudsdk.core import log
_EXAMPLES = """
To describe a node pool named ``my-node-pool'' in a cluster named
``my-cluster'' managed in location ``us-west1'', run:
$ {command} my-node-pool --cluster=my-cluster --location=us-west1
"""
@base.ReleaseTracks(base.ReleaseTrack.ALPHA, base.ReleaseTrack.GA)
class Describe(base.DescribeCommand):
"""Describe a node pool in an Anthos cluster on Azure."""
detailed_help = {'EXAMPLES': _EXAMPLES}
@staticmethod
def Args(parser):
resource_args.AddAzureNodePoolResourceArg(parser, 'to describe')
def Run(self, args):
"""Runs the describe command."""
self._upgrade_hint = None
node_pool_ref = resource_args.ParseAzureNodePoolResourceArg(args)
with endpoint_util.GkemulticloudEndpointOverride(node_pool_ref.locationsId):
node_pool_client = api_util.NodePoolsClient()
node_pool_info = node_pool_client.Get(node_pool_ref)
self._upgrade_hint = versions.upgrade_hint_node_pool(
node_pool_ref, node_pool_info, constants.AZURE
)
return node_pool_info
def Epilog(self, results_were_displayed):
if self._upgrade_hint:
log.status.Print(self._upgrade_hint)

View File

@@ -0,0 +1,80 @@
# -*- coding: utf-8 -*- #
# Copyright 2021 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.
"""Command to list node pools in an Anthos cluster on Azure."""
from __future__ import absolute_import
from __future__ import division
from __future__ import unicode_literals
from googlecloudsdk.api_lib.container.gkemulticloud import azure as api_util
from googlecloudsdk.calliope import base
from googlecloudsdk.command_lib.container.azure import resource_args
from googlecloudsdk.command_lib.container.gkemulticloud import constants
from googlecloudsdk.command_lib.container.gkemulticloud import endpoint_util
from googlecloudsdk.command_lib.container.gkemulticloud import versions
from googlecloudsdk.core import log
_EXAMPLES = """
To list all node pools in a cluster named ``my-cluster''
managed in location ``us-west1'', run:
$ {command} --cluster=my-cluster --location=us-west1
"""
@base.ReleaseTracks(base.ReleaseTrack.ALPHA, base.ReleaseTrack.GA)
class List(base.ListCommand):
"""List node pools in an Anthos cluster on Azure."""
detailed_help = {'EXAMPLES': _EXAMPLES}
@staticmethod
def Args(parser):
resource_args.AddAzureClusterResourceArg(
parser, 'to list Azure node pools', positional=False
)
parser.display_info.AddFormat(constants.AZURE_NODE_POOL_FORMAT)
def Run(self, args):
"""Runs the list command."""
self._upgrade_hint = None
cluster_ref = args.CONCEPTS.cluster.Parse()
with endpoint_util.GkemulticloudEndpointOverride(cluster_ref.locationsId):
api_client = api_util.NodePoolsClient()
items, is_empty = api_client.List(
cluster_ref, page_size=args.page_size, limit=args.limit
)
if is_empty:
return items
platform = constants.AZURE
node_pool_info_table, end_of_life_flag = (
versions.generate_node_pool_versions_table(
cluster_ref,
platform,
items,
)
)
if end_of_life_flag:
self._upgrade_hint = versions.upgrade_hint_node_pool_list(
platform, cluster_ref
)
return node_pool_info_table
def Epilog(self, results_were_displayed):
super(List, self).Epilog(results_were_displayed)
if self._upgrade_hint:
log.status.Print(self._upgrade_hint)

View File

@@ -0,0 +1,87 @@
# -*- coding: utf-8 -*- #
# Copyright 2021 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.
"""Command to update a node pool in an Anthos cluster on Azure."""
from __future__ import absolute_import
from __future__ import division
from __future__ import unicode_literals
from googlecloudsdk.api_lib.container.gkemulticloud import azure as api_util
from googlecloudsdk.calliope import base
from googlecloudsdk.command_lib.container.azure import resource_args
from googlecloudsdk.command_lib.container.gkemulticloud import command_util
from googlecloudsdk.command_lib.container.gkemulticloud import constants
from googlecloudsdk.command_lib.container.gkemulticloud import endpoint_util
from googlecloudsdk.command_lib.container.gkemulticloud import flags
# Command needs to be in one line for the docgen tool to format properly.
_EXAMPLES = """
To update a node pool named ``my-node-pool'' in a cluster named ``my-cluster''
managed in location ``us-west1'', run:
$ {command} my-node-pool --cluster=my-cluster --location=us-west1 --node-version=NODE_VERSION
"""
@base.ReleaseTracks(base.ReleaseTrack.GA)
class Update(base.UpdateCommand):
"""Update a node pool in an Anthos cluster on Azure."""
detailed_help = {'EXAMPLES': _EXAMPLES}
@staticmethod
def Args(parser):
resource_args.AddAzureNodePoolResourceArg(
parser, 'to update', positional=True
)
flags.AddNodeVersion(parser, required=False)
flags.AddAutoscaling(parser, required=False)
flags.AddSSHPublicKey(parser, required=False)
flags.AddAnnotationsForUpdate(parser, 'node pool')
flags.AddValidateOnly(parser, 'update of the node pool')
flags.AddEnableAutoRepair(parser, False)
base.ASYNC_FLAG.AddToParser(parser)
parser.display_info.AddFormat(constants.AZURE_NODE_POOL_FORMAT)
def Run(self, args):
"""Runs the update command."""
location = resource_args.ParseAzureNodePoolResourceArg(args).locationsId
with endpoint_util.GkemulticloudEndpointOverride(location):
node_pool_ref = resource_args.ParseAzureNodePoolResourceArg(args)
node_pool_client = api_util.NodePoolsClient()
message = command_util.NodePoolMessage(
node_pool_ref.azureNodePoolsId,
action='Updating',
cluster=node_pool_ref.azureClustersId,
)
return command_util.Update(
resource_ref=node_pool_ref,
resource_client=node_pool_client,
args=args,
message=message,
kind=constants.AZURE_NODEPOOL_KIND,
)
@base.ReleaseTracks(base.ReleaseTrack.ALPHA)
class UpdateAlpha(Update):
"""Update a node pool in an Anthos cluster on Azure."""
@staticmethod
def Args(parser, track=base.ReleaseTrack.ALPHA):
"""Registers alpha track flags for this command."""
Update.Args(parser)

View File

@@ -0,0 +1,32 @@
# -*- coding: utf-8 -*- #
# Copyright 2021 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.
"""Command group for `gcloud container azure operations`."""
from __future__ import absolute_import
from __future__ import division
from __future__ import unicode_literals
from googlecloudsdk.calliope import base
from googlecloudsdk.command_lib.projects import util
from googlecloudsdk.core import log
@base.ReleaseTracks(base.ReleaseTrack.ALPHA, base.ReleaseTrack.GA)
class Operations(base.Group):
"""Manage Anthos Multi-Cloud long running operations for Azure."""
@staticmethod
def Args(parser):
pass

View File

@@ -0,0 +1,58 @@
# -*- 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.
"""Command to cancel an operation."""
from __future__ import absolute_import
from __future__ import division
from __future__ import unicode_literals
from googlecloudsdk.api_lib.container.gkemulticloud import operations as op_api_util
from googlecloudsdk.calliope import base
from googlecloudsdk.command_lib.container.azure import resource_args
from googlecloudsdk.command_lib.container.gkemulticloud import command_util
from googlecloudsdk.command_lib.container.gkemulticloud import endpoint_util
from googlecloudsdk.core import log
_EXAMPLES = """
To cancel an operation in location ``us-west1'', run:
$ {command} OPERATION_ID --location=us-west1
"""
@base.ReleaseTracks(base.ReleaseTrack.ALPHA, base.ReleaseTrack.GA)
class Cancel(base.Command):
"""Cancel an operation."""
detailed_help = {'EXAMPLES': _EXAMPLES}
@staticmethod
def Args(parser):
"""Registers flags for this command."""
resource_args.AddOperationResourceArg(parser, 'to cancel')
def Run(self, args):
"""Runs the cancel command."""
with endpoint_util.GkemulticloudEndpointOverride(
resource_args.ParseOperationResourceArg(args).locationsId,
self.ReleaseTrack(),
):
op_client = op_api_util.OperationsClient()
op_ref = resource_args.ParseOperationResourceArg(args)
op = op_client.Get(op_ref)
command_util.CancelOperationPrompt(op.name)
op_client.Cancel(op_ref)
log.status.Print(command_util.CancelOperationMessage(op.name, 'azure'))
return op_client.Get(op_ref)

View File

@@ -0,0 +1,52 @@
# -*- coding: utf-8 -*- #
# Copyright 2021 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.
"""Command to describe an operation."""
from __future__ import absolute_import
from __future__ import division
from __future__ import unicode_literals
from googlecloudsdk.api_lib.container.gkemulticloud import operations as op_api_util
from googlecloudsdk.calliope import base
from googlecloudsdk.command_lib.container.azure import resource_args
from googlecloudsdk.command_lib.container.gkemulticloud import endpoint_util
_EXAMPLES = """
To describe an operation in location ``us-west1'', run:
$ {command} OPERATION_ID --location=us-west1
"""
@base.ReleaseTracks(base.ReleaseTrack.ALPHA, base.ReleaseTrack.GA)
class Describe(base.DescribeCommand):
"""Describe an operation."""
detailed_help = {'EXAMPLES': _EXAMPLES}
@staticmethod
def Args(parser):
"""Registers flags for this command."""
resource_args.AddOperationResourceArg(parser, 'to describe')
def Run(self, args):
"""Runs the describe command."""
with endpoint_util.GkemulticloudEndpointOverride(
resource_args.ParseOperationResourceArg(args).locationsId,
self.ReleaseTrack(),
):
op_client = op_api_util.OperationsClient()
op_ref = resource_args.ParseOperationResourceArg(args)
return op_client.Get(op_ref)

View File

@@ -0,0 +1,61 @@
# -*- coding: utf-8 -*- #
# Copyright 2021 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.
"""Command to list operations."""
from __future__ import absolute_import
from __future__ import division
from __future__ import unicode_literals
from googlecloudsdk.api_lib.container.gkemulticloud import operations as op_api_util
from googlecloudsdk.calliope import base
from googlecloudsdk.command_lib.container.azure import resource_args
from googlecloudsdk.command_lib.container.gkemulticloud import endpoint_util
from googlecloudsdk.command_lib.container.gkemulticloud import operations
_EXAMPLES = """
To list all operations in location ``us-west1'', run:
$ {command} --location=us-west1
"""
@base.ReleaseTracks(base.ReleaseTrack.ALPHA, base.ReleaseTrack.GA)
class List(base.ListCommand):
"""List operations."""
detailed_help = {'EXAMPLES': _EXAMPLES}
@staticmethod
def Args(parser):
"""Registers flags for this command."""
resource_args.AddLocationResourceArg(parser, 'to list operations')
operations.AddFormat(parser)
def Run(self, args):
"""Runs the describe command."""
release_track = self.ReleaseTrack()
location_ref = args.CONCEPTS.location.Parse()
with endpoint_util.GkemulticloudEndpointOverride(
location_ref.locationsId, release_track
):
op_client = op_api_util.OperationsClient()
items, empty = op_client.List(
location_ref, args.page_size, args.limit, parent_field='name'
)
if not empty:
# ListOperations returns AWS, Azure, and attached operations.
# Add a filter for Azure operations.
operations.AddFilter(args, 'azure')
return items

View File

@@ -0,0 +1,57 @@
# -*- coding: utf-8 -*- #
# Copyright 2021 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.
"""Command to wait for an operation to complete."""
from __future__ import absolute_import
from __future__ import division
from __future__ import unicode_literals
from googlecloudsdk.api_lib.container.gkemulticloud import operations as op_api_util
from googlecloudsdk.calliope import base
from googlecloudsdk.command_lib.container.azure import resource_args
from googlecloudsdk.command_lib.container.gkemulticloud import endpoint_util
_EXAMPLES = """
To wait for an operation in location ``us-west1'' to complete, run:
$ {command} OPERATION_ID --location=us-west1
"""
@base.ReleaseTracks(base.ReleaseTrack.ALPHA, base.ReleaseTrack.GA)
class Describe(base.DescribeCommand):
"""Wait for an operation to complete."""
detailed_help = {'EXAMPLES': _EXAMPLES}
@staticmethod
def Args(parser):
"""Registers flags for this command."""
resource_args.AddOperationResourceArg(parser, 'to wait for')
def Run(self, args):
"""Runs the wait command."""
with endpoint_util.GkemulticloudEndpointOverride(
resource_args.ParseOperationResourceArg(args).locationsId,
self.ReleaseTrack(),
):
op_client = op_api_util.OperationsClient()
op_ref = resource_args.ParseOperationResourceArg(args)
op_client.Wait(
op_ref,
'Waiting for operation {} to complete'.format(op_ref.RelativeName()),
)
return op_client.Get(op_ref)

View File

@@ -0,0 +1,33 @@
# -*- coding: utf-8 -*- #
# Copyright 2021 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.
"""Command group for Backup for GKE."""
from __future__ import absolute_import
from __future__ import division
from __future__ import unicode_literals
from googlecloudsdk.calliope import base
@base.ReleaseTracks(base.ReleaseTrack.ALPHA, base.ReleaseTrack.BETA)
class GKEBackup(base.Group):
"""Backup for GKE Services."""
category = base.COMPUTE_CATEGORY
def Filter(self, context, args):
"""See base class."""
base.RequireProjectID(args)
return context

View File

@@ -0,0 +1,29 @@
# -*- coding: utf-8 -*- #
# Copyright 2025 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.
"""Command group for Backup Channel."""
from __future__ import absolute_import
from __future__ import division
from __future__ import unicode_literals
from googlecloudsdk.calliope import base
@base.DefaultUniverseOnly
@base.ReleaseTracks(base.ReleaseTrack.ALPHA, base.ReleaseTrack.BETA)
class BackupChannels(base.Group):
"""Backup for GKE Backup Channels."""
category = base.BACKUP_CATEGORY

View File

@@ -0,0 +1,40 @@
- release_tracks: [ALPHA, BETA]
help_text:
brief: Create a backup channel.
description: |
Create a Backup for GKE backup channel.
## EXAMPLES
To create a backup channel ``my-backup-channel'' in project ``my-project'' in location ``us-central1'' with destination project ``projects/backup-project'', run:
$ {command} my-backup-channel --project=my-project --location=us-central1 --destination-project=projects/backup-project
request:
collection: gkebackup.projects.locations.backupChannels
api_version: v1
async:
collection: gkebackup.projects.locations.operations
arguments:
resource:
help_text: |
Name of the backup channel to create. Once the channel is created, this name can't be
changed. This must be 63 or fewer characters long and must be unique within
the project and location. The name may be provided either as a relative name, e.g.
`projects/<project>/locations/<location>/backupChannels/<backupChannel>`
or as a single ID name (with the parent resources provided via options or through
properties), e.g.
`BACKUP_CHANNEL --project=<project> --location=<location>`.
spec: !REF googlecloudsdk.command_lib.container.backup_restore.resources:positional_backup_channel
params:
- _REF_: googlecloudsdk.command_lib.container.backup_restore.flags:backup_destination_project
required: true
- _REF_: googlecloudsdk.command_lib.container.backup_restore.flags:backup_channel_description
labels:
api_field: backupChannel.labels

View File

@@ -0,0 +1,37 @@
- release_tracks: [ALPHA, BETA]
help_text:
brief: Delete a backup channel.
description: |
Delete a Backup for GKE backup channel.
## EXAMPLES
To delete a backup channel ``my-backup-channel'' in project ``my-project'' in location ``us-central1'', run:
$ {command} my-backup-channel --project=my-project --location=us-central1
request:
collection: gkebackup.projects.locations.backupChannels
modify_request_hooks:
- googlecloudsdk.command_lib.container.backup_restore.hooks:AddForceToDeleteRequest
api_version: v1
arguments:
resource:
help_text: |
Name of the backup channel to delete. The name may be provided either as a relative name, e.g.
`projects/<project>/locations/<location>/backupChannels/<backupChannel>`
or as a single ID name (with the parent resources provided via options or through
properties), e.g.
`BACKUP_CHANNEL --project=<project> --location=<location>`.
spec: !REF googlecloudsdk.command_lib.container.backup_restore.resources:positional_backup_channel
params:
- _REF_: googlecloudsdk.command_lib.container.backup_restore.flags:etag
async:
collection: gkebackup.projects.locations.operations
api_version: v1
extract_resource_result: false

View File

@@ -0,0 +1,28 @@
- release_tracks: [ALPHA, BETA]
help_text:
brief: Describe a backup channel.
description: |
Describe a Backup for GKE backup channel.
## EXAMPLES
To describe a backup channel ``my-backup-channel'' in project ``my-project'' in location ``us-central1'', run:
$ {command} my-backup-channel --project=my-project --location=us-central1
request:
collection: gkebackup.projects.locations.backupChannels
api_version: v1
arguments:
resource:
help_text: |
Name of the backup channel to describe. The name may be provided either as a relative name,
e.g.
`projects/<project>/locations/<location>/backupChannels/<backupChannel>`
or as a single ID name (with the parent resources provided via options or through
properties), e.g.
`BACKUP_CHANNEL --project=<project> --location=<location>`
spec: !REF googlecloudsdk.command_lib.container.backup_restore.resources:positional_backup_channel

View File

@@ -0,0 +1,40 @@
- release_tracks: [ALPHA, BETA]
help_text:
brief: List backup channels.
description: |
List Backup for GKE backup channels.
## EXAMPLES
To list all backup channels in project ``my-project'' in location ``us-central1'', run:
$ {command} --project=my-project --location=us-central1
To list all backup channels in project ``my-project'' across all locations, run:
$ {command} --project=my-project
request:
collection: gkebackup.projects.locations.backupChannels
api_version: v1
response:
id_field: name
arguments:
resource:
help_text: |
Name of the location from which to list backup channels (provided via options or through
properties):
`--project=<project> --location=<location>`.
spec: !REF googlecloudsdk.command_lib.container.backup_restore.resources:default_location
output:
format: |
table(
name.basename():label=NAME,
name.segment(3):label=LOCATION,
destinationProject:label=DESTINATION_PROJECT
)

View File

@@ -0,0 +1,39 @@
- release_tracks: [ALPHA, BETA]
help_text:
brief: Update a backup channel.
description: |
Update a Backup for GKE backup channel.
## EXAMPLES
To update a backup channel ``my-backup-channel'' in project ``my-project'' in location ``us-central1'' to add new description, run:
$ {command} my-backup-channel --project=my-project --location=us-central1 --description="New description"
request:
collection: gkebackup.projects.locations.backupChannels
api_version: v1
async:
collection: gkebackup.projects.locations.operations
arguments:
resource:
help_text: |
Name of the backup channel to update. The name may be provided either as a relative name, e.g.
`projects/<project>/locations/<location>/backupChannels/<backupChannel>`
or as a single ID name (with the parent resources provided via options or through
properties), e.g. `BACKUP_CHANNEL --project=<project> --location=<location>`.
spec: !REF googlecloudsdk.command_lib.container.backup_restore.resources:positional_backup_channel
params:
- _REF_: googlecloudsdk.command_lib.container.backup_restore.flags:backup_channel_etag
- _REF_: googlecloudsdk.command_lib.container.backup_restore.flags:backup_channel_description
labels:
api_field: backupChannel.labels
update:
read_modify_update: true

View File

@@ -0,0 +1,29 @@
# -*- coding: utf-8 -*- #
# Copyright 2025 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.
"""Command group for Backup Plan Bindings."""
from __future__ import absolute_import
from __future__ import division
from __future__ import unicode_literals
from googlecloudsdk.calliope import base
@base.DefaultUniverseOnly
@base.ReleaseTracks(base.ReleaseTrack.ALPHA, base.ReleaseTrack.BETA)
class BackupPlanBindings(base.Group):
"""Backup for GKE Backup Plan Bindings."""
category = base.BACKUP_CATEGORY

View File

@@ -0,0 +1,27 @@
- release_tracks: [ALPHA, BETA]
help_text:
brief: Describe a backup plan binding.
description: |
Describe a Backup for GKE backup plan binding.
## EXAMPLES
To describe a backup plan binding ``my-backup-plan-binding'' in project ``my-project'' in location ``us-central1'' under backup channel ``my-backup-channel'', run:
$ {command} my-backup-plan-binding --backup-channel=my-backup-channel --project=my-project --location=us-central1
request:
collection: gkebackup.projects.locations.backupChannels.backupPlanBindings
api_version: v1
arguments:
resource:
help_text: |
Name of the backup plan binding to describe. The name may be provided either as a relative name, e.g.
`projects/<project>/locations/<location>/backupChannels/<backupChannel>/backupPlanBindings/<backupPlanBinding>`
or as a single ID name (with the parent resources provided via options or through
properties), e.g.
`BACKUP_PLAN_BINDING --project=<project> --location=<location> --backup-channel=<backupChannel>`.
spec: !REF googlecloudsdk.command_lib.container.backup_restore.resources:backup_plan_binding

View File

@@ -0,0 +1,43 @@
- release_tracks: [ALPHA, BETA]
help_text:
brief: List backup plan bindings.
description: |
List Backup Plan Bindings for GKE backup plan bindings.
## EXAMPLES
To list all backup plan bindings in project ``my-project'' in location ``us-central1'' under backup channel ``my-backup-channel'', run:
$ {command} --backup-channel=my-backup-channel --project=my-project --location=us-central1
To list all backup plan bindings in project ``my-project'' across all locations under all backup channels, run:
$ {command} --project=my-project
request:
collection: gkebackup.projects.locations.backupChannels.backupPlanBindings
api_version: v1
response:
id_field: name
arguments:
resource:
help_text: |
Name of the backup channel from which to list backup plan bindings (provided via options or through
properties), e.g.
`--project=<project> --location=<location> --backup-channel=<backupChannel>`.
spec: !REF googlecloudsdk.command_lib.container.backup_restore.resources:backup_channel
output:
format: |
table(
name.basename():label=NAME,
name.segment(3):label=LOCATION,
name.segment(5):label=BACKUP_CHANNEL,
createTime.date('%Y-%m-%dT%H:%M:%S %Z', tz=LOCAL),
cluster,
backupPlan
)

View File

@@ -0,0 +1,29 @@
# -*- coding: utf-8 -*- #
# Copyright 2021 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.
"""Command group for Backup Plan."""
from __future__ import absolute_import
from __future__ import division
from __future__ import unicode_literals
from googlecloudsdk.calliope import base
@base.DefaultUniverseOnly
@base.ReleaseTracks(base.ReleaseTrack.ALPHA, base.ReleaseTrack.BETA)
class BackupPlans(base.Group):
"""Backup for GKE Backup Plans."""
category = base.BACKUP_CATEGORY

View File

@@ -0,0 +1,76 @@
- release_tracks: [ALPHA, BETA]
help_text:
brief: Create a backup plan.
description: |
Create a Backup for GKE backup plan.
## EXAMPLES
To create a backup plan ``my-backup-plan'' in project ``my-project'' in location ``us-central1'', run:
$ {command} my-backup-plan --project=my-project --location=us-central1 --cluster=projects/my-project/locations/us-central1/clusters/my-cluster --all-namespaces
request:
collection: gkebackup.projects.locations.backupPlans
api_version: v1
async:
collection: gkebackup.projects.locations.operations
arguments:
resource:
help_text: |
Name of the backup plan to create. Once the plan is created, this name can't be changed.
This must be 63 or fewer characters long and must be unique within the project and location.
The name may be provided either as a relative name, e.g.
`projects/<project>/locations/<location>/backupPlans/<backupPlan>`
or as a single ID name (with the parent resources provided via options or through
properties), e.g.
`BACKUP_PLAN --project=<project> --location=<location>`.
spec: !REF googlecloudsdk.command_lib.container.backup_restore.resources:positional_backup_plan
params:
- _REF_: googlecloudsdk.command_lib.container.backup_restore.flags:backup_plan_cluster
- _REF_: googlecloudsdk.command_lib.container.backup_restore.flags:backup_plan_description
- _REF_: googlecloudsdk.command_lib.container.backup_restore.flags:deactivated
- _REF_: googlecloudsdk.command_lib.container.backup_restore.flags:backup_plan_tags
# Retention policy
- group:
required: false
params:
- _REF_: googlecloudsdk.command_lib.container.backup_restore.flags:backup_delete_lock_days
- _REF_: googlecloudsdk.command_lib.container.backup_restore.flags:backup_retain_days
- _REF_: googlecloudsdk.command_lib.container.backup_restore.flags:locked
# Backup schedule
- group:
params:
- _REF_: googlecloudsdk.command_lib.container.backup_restore.flags:paused
- group:
params:
- _REF_: googlecloudsdk.command_lib.container.backup_restore.flags:cron_schedule
- group:
params:
- _REF_: googlecloudsdk.command_lib.container.backup_restore.flags:target_rpo_minutes
required: true
- _REF_: googlecloudsdk.command_lib.container.backup_restore.flags:exclusion_windows_file
# Backup scope
- group:
required: true
mutex: true
params:
- _REF_: googlecloudsdk.command_lib.container.backup_restore.flags:all_namespaces
- _REF_: googlecloudsdk.command_lib.container.backup_restore.flags:selected_namespaces
- _REF_: googlecloudsdk.command_lib.container.backup_restore.flags:selected_applications
- _REF_: googlecloudsdk.command_lib.container.backup_restore.flags:selected_namespace_labels
# Backup config
- group:
params:
- _REF_: googlecloudsdk.command_lib.container.backup_restore.flags:include_volume_data
- _REF_: googlecloudsdk.command_lib.container.backup_restore.flags:include_secrets
- _REF_: googlecloudsdk.command_lib.container.backup_restore.flags:encryption_key
- _REF_: googlecloudsdk.command_lib.container.backup_restore.flags:permissive_mode
labels:
api_field: backupPlan.labels

Some files were not shown because too many files have changed in this diff Show More