File: //snap/google-cloud-cli/current/lib/googlecloudsdk/api_lib/container/fleet/client.py
# -*- coding: utf-8 -*- #
# Copyright 2022 Google LLC. All Rights Reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
"""Version-agnostic Fleet API client."""
from __future__ import absolute_import
from __future__ import division
from __future__ import unicode_literals
import collections
from typing import Generator
from apitools.base.py import encoding
from apitools.base.py import list_pager
from googlecloudsdk.api_lib.container.fleet import gkehub_api_util
from googlecloudsdk.api_lib.container.fleet import types
from googlecloudsdk.api_lib.container.fleet import util
from googlecloudsdk.api_lib.util import waiter
from googlecloudsdk.calliope import base
from googlecloudsdk.core import resources
class HubClient(object):
"""Client for the GKE Hub API with related helper methods.
If not provided, the default client is for the GA (v1) track. This client
is a thin wrapper around the base client, and does not handle any exceptions.
Fields:
release_track: The release track of the command [ALPHA, BETA, GA].
client: The raw GKE Hub API client for the specified release track.
messages: The matching messages module for the client.
resourceless_waiter: A waiter.CloudOperationPollerNoResources for polling
LROs that do not return a resource (like Deletes).
feature_waiter: A waiter.CloudOperationPoller for polling Feature LROs.
"""
def __init__(self, release_track=base.ReleaseTrack.GA):
self.release_track = release_track
self.client = util.GetClientInstance(release_track)
self.messages = util.GetMessagesModule(release_track)
self.resourceless_waiter = waiter.CloudOperationPollerNoResources(
operation_service=self.client.projects_locations_operations
)
self.feature_waiter = gkehub_api_util.HubFeatureOperationPoller(
result_service=self.client.projects_locations_features,
operation_service=self.client.projects_locations_operations,
)
def CreateFeature(self, parent, feature_id, feature):
"""Creates a Feature and returns the long-running operation message.
Args:
parent: The parent in the form /projects/*/locations/*.
feature_id: The short ID for this Feature in the Hub API.
feature: A Feature message specifying the Feature data to create.
Returns:
The long running operation reference. Use the feature_waiter and
OperationRef to watch the operation and get the final status, typically
using waiter.WaitFor to present a user-friendly spinner.
"""
req = self.messages.GkehubProjectsLocationsFeaturesCreateRequest(
feature=feature,
featureId=feature_id,
parent=parent,
)
return self.client.projects_locations_features.Create(req)
def GetFeature(self, name):
"""Gets a Feature from the Hub API.
Args:
name: The full resource name in the form
/projects/*/locations/*/features/*.
Returns:
The Feature message.
"""
req = self.messages.GkehubProjectsLocationsFeaturesGetRequest(
name=name,
returnPartialSuccess=True,
)
return self.client.projects_locations_features.Get(req)
def ListFeatures(self, parent):
"""Lists Features from the Hub API.
Args:
parent: The parent in the form /projects/*/locations/*.
Returns:
A list of Features.
"""
req = self.messages.GkehubProjectsLocationsFeaturesListRequest(
parent=parent,
returnPartialSuccess=True,
)
# We skip the pagination for now, since it will never be hit.
resp = self.client.projects_locations_features.List(req)
return resp.resources
def UpdateFeature(self, name, mask, feature):
"""Creates a Feature and returns the long-running operation message.
Args:
name: The full resource name in the form
/projects/*/locations/*/features/*.
mask: A string list of the field paths to update.
feature: A Feature message containing the Feature data to update using the
mask.
Returns:
The long running operation reference. Use the feature_waiter and
OperationRef to watch the operation and get the final status, typically
using waiter.WaitFor to present a user-friendly spinner.
"""
req = self.messages.GkehubProjectsLocationsFeaturesPatchRequest(
name=name,
updateMask=','.join(mask),
feature=feature,
)
return self.client.projects_locations_features.Patch(req)
def DeleteFeature(self, name, force=False):
"""Deletes a Feature and returns the long-running operation message.
Args:
name: The full resource name in the form
/projects/*/locations/*/features/*.
force: Indicates the Feature should be force deleted.
Returns:
The long running operation. Use the feature_waiter and OperationRef to
watch the operation and get the final status, typically using
waiter.WaitFor to present a user-friendly spinner.
"""
req = self.messages.GkehubProjectsLocationsFeaturesDeleteRequest(
name=name,
force=force,
)
return self.client.projects_locations_features.Delete(req)
@staticmethod
def OperationRef(op: types.Operation) -> resources.Resource:
"""Parses a gkehub Operation reference from an operation."""
return resources.REGISTRY.ParseRelativeName(
op.name, collection='gkehub.projects.locations.operations'
)
@staticmethod
def ToPyDict(proto_map_value):
"""Helper to convert proto map Values to normal dictionaries.
encoding.MessageToPyValue recursively converts values to dicts, while this
method leaves the map values as proto objects.
Args:
proto_map_value: The map field "Value". For example, the `Feature.labels`
value (of type `Features.LabelsValue`). Can be None.
Returns:
An OrderedDict of the map's keys/values, in the original order.
"""
if proto_map_value is None or proto_map_value.additionalProperties is None:
return {}
return collections.OrderedDict(
(p.key, p.value) for p in proto_map_value.additionalProperties
)
@staticmethod
def ToPyDefaultDict(default_factory, proto_map_value):
"""Helper to convert proto map Values to default dictionaries.
encoding.MessageToPyValue recursively converts values to dicts, while this
method leaves the map values as proto objects.
Args:
default_factory: Pass-through to collections.defaultdict.
proto_map_value: The map field "Value". For example, the `Feature.labels`
value (of type `Features.LabelsValue`). Can be None.
Returns:
An defaultdict of the map's keys/values.
"""
return collections.defaultdict(
default_factory,
{} if proto_map_value is None else HubClient.ToPyDict(proto_map_value),
)
@staticmethod
def ToProtoMap(map_value_cls, value):
"""encoding.DictToAdditionalPropertyMessage wrapper to match ToPyDict."""
return encoding.DictToAdditionalPropertyMessage(
value, map_value_cls, sort_items=True
)
def ToMembershipSpecs(self, spec_map):
"""Convenience wrapper for ToProtoMap for Feature.membershipSpecs."""
return self.ToProtoMap(self.messages.Feature.MembershipSpecsValue, spec_map)
def ToScopeSpecs(self, spec_map):
"""Convenience wrapper for ToProtoMap for Feature.scopeSpecs."""
return self.ToProtoMap(self.messages.Feature.ScopeSpecsValue, spec_map)
class HubV2Client(object):
"""Client for the GKE Hub V2 API with related helper methods.
If not provided, the default client is for the GA (v2) track.
This client is a thin wrapper around the base client, and does not handle
any exceptions.
Fields:
release_track: The release track of the command [ALPHA].
client: The raw GKE Hub API client for the specified release track.
messages: The matching messages module for the client.
resourceless_waiter: A waiter.CloudOperationPollerNoResources for polling
LROs that do not return a resource (like Deletes).
membership_feature_waiter: A waiter.CloudOperationPoller for polling
Membership Feature LROs.
"""
def __init__(self, release_track=base.ReleaseTrack.GA):
self.release_track = release_track
self.client = util.GetV2ClientInstance(release_track)
self.messages = util.GetV2MessagesModule(release_track)
self.resourceless_waiter = waiter.CloudOperationPollerNoResources(
operation_service=self.client.projects_locations_operations
)
self.membership_feature_waiter = waiter.CloudOperationPoller(
result_service=self.client.projects_locations_memberships_features,
operation_service=self.client.projects_locations_operations,
)
def CreateMembershipFeature(self, parent, feature_id, membership_feature):
"""Creates a MembershipFeature and returns the long-running operation message.
Args:
parent: The parent in the form /projects/*/locations/*/memberships/*.
feature_id: The short ID for this Feature in the Hub API.
membership_feature: A MembershipFeature message specifying the
MembershipFeature data to create.
Returns:
The long running operation reference. Use the membership_feature_waiter
and OperationRef to watch the operation and get the final status,
typically using waiter.WaitFor to present a user-friendly spinner.
"""
req = self.messages.GkehubProjectsLocationsMembershipsFeaturesCreateRequest(
membershipFeature=membership_feature,
featureId=feature_id,
parent=parent,
)
return self.client.projects_locations_memberships_features.Create(req)
def GetMembershipFeature(self, name):
"""Gets a MembershipFeature from the Hub V2 API.
Args:
name: The full resource name in the form
/projects/*/locations/*/memberships/*/features/*.
Returns:
The MembershipFeature message.
"""
req = self.messages.GkehubProjectsLocationsMembershipsFeaturesGetRequest(
name=name
)
return self.client.projects_locations_memberships_features.Get(req)
def UpdateMembershipFeature(self, name, mask, membership_feature):
"""Updates a MembershipFeature and returns the long-running operation message.
Args:
name: The full resource name in the form
/projects/*/locations/*/memberships/*/features/*.
mask: A string list of the field paths to update.
membership_feature: A MembershipFeature message containing the Feature
data to update using the mask.
Returns:
The long running operation reference. Use the membership_feature_waiter
and
OperationRef to watch the operation and get the final status, typically
using waiter.WaitFor to present a user-friendly spinner.
"""
req = self.messages.GkehubProjectsLocationsMembershipsFeaturesPatchRequest(
name=name,
updateMask=','.join(mask),
membershipFeature=membership_feature,
allowMissing=True,
)
return self.client.projects_locations_memberships_features.Patch(req)
def DeleteMembershipFeature(self, name):
"""Deletes a MembershipFeature and returns the long-running operation message.
Args:
name: The full resource name in the form
/projects/*/locations/*/memberships/*/features/*.
Returns:
The long running operation. Use the membership_feature_waiter and
OperationRef to
watch the operation and get the final status, typically using
waiter.WaitFor to present a user-friendly spinner.
"""
req = self.messages.GkehubProjectsLocationsMembershipsFeaturesDeleteRequest(
name=name,
)
return self.client.projects_locations_memberships_features.Delete(req)
class FleetClient(object):
"""Client for the Fleet API with related helper methods.
If not provided, the default client is for the alpha (v1) track. This client
is a thin wrapper around the base client, and does not handle any exceptions.
Fields:
release_track: The release track of the command [ALPHA, BETA, GA].
client: The raw Fleet API client for the specified release track.
messages: The matching messages module for the client.
resourceless_waiter: A waiter.CloudOperationPollerNoResources for polling
LROs that do not return a resource (like Deletes).
fleet_waiter: A waiter.CloudOperationPoller for polling fleet LROs.
"""
def __init__(self, release_track=base.ReleaseTrack.GA):
self.release_track = release_track
self.client = util.GetClientInstance(release_track)
self.messages = util.GetMessagesModule(release_track)
self.resourceless_waiter = waiter.CloudOperationPollerNoResources(
operation_service=self.client.projects_locations_operations
)
if release_track == base.ReleaseTrack.ALPHA:
self.fleet_waiter = waiter.CloudOperationPoller(
result_service=self.client.projects_locations_fleets,
operation_service=self.client.projects_locations_operations,
)
def GetFleet(self, project):
"""Gets a fleet resource from the Fleet API.
Args:
project: the project containing the fleet.
Returns:
A fleet resource
Raises:
apitools.base.py.HttpError: if the request returns an HTTP error
"""
req = self.messages.GkehubProjectsLocationsFleetsGetRequest(
name=util.FleetResourceName(project)
)
return self.client.projects_locations_fleets.Get(req)
def CreateFleet(self, req: types.GkehubProjectsLocationsFleetsCreateRequest):
"""Creates a fleet resource from the Fleet API.
Args:
req: An HTTP create request to be sent to the API server.
Returns:
A long-running operation to be polled till completion, or returned
directly if user specifies async flag.
Raises:
apitools.base.py.HttpError: if the request returns an HTTP error
"""
return self.client.projects_locations_fleets.Create(req)
def DeleteFleet(
self, req: types.GkehubProjectsLocationsFleetsDeleteRequest
) -> types.Operation:
"""Deletes a fleet resource from the Fleet API.
Args:
req: An HTTP delete request to send to the API server.
Returns:
A long-running operation to be polled till completion, or returned
directly if user specifies async flag.
Raises:
apitools.base.py.HttpError: if the request returns an HTTP error
"""
return self.client.projects_locations_fleets.Delete(req)
def UpdateFleet(
self, req: types.GkehubProjectsLocationsFleetsPatchRequest
) -> types.Operation:
"""Updates a fleet resource from the Fleet API.
Args:
req: An HTTP patch request to send to the API server.
Returns:
A long-running operation to be polled till completion, or returned
directly if user specifies async flag.
Raises:
apitools.base.py.HttpError: if the request returns an HTTP error
"""
return self.client.projects_locations_fleets.Patch(req)
def ListFleets(self, project, organization):
"""Lists fleets in an organization.
Args:
project: the project to search.
organization: the organization to search.
Returns:
A ListFleetResponse (list of fleets and next page token)
Raises:
apitools.base.py.HttpError: if the request returns an HTTP error
"""
if organization:
parent = util.FleetOrgParentName(organization)
else:
parent = util.FleetParentName(project)
# Misleading name, parent is usually org, not project
req = self.messages.GkehubProjectsLocationsFleetsListRequest(
pageToken='', parent=parent
)
return list_pager.YieldFromList(
self.client.projects_locations_fleets,
req,
field='fleets',
batch_size_attribute=None,
)
def GetScope(self, scope_path):
"""Gets a scope resource from the GKEHub API.
Args:
scope_path: Full resource path of the scope.
Returns:
A scope resource.
Raises:
apitools.base.py.HttpError: If the request returns an HTTP error
"""
req = self.messages.GkehubProjectsLocationsScopesGetRequest(name=scope_path)
return self.client.projects_locations_scopes.Get(req)
def GetScopeIamPolicy(self, scope_path):
"""Gets the IAM policy for a scope resource.
Args:
scope_path: Full resource path of the scope.
Returns:
An Iam Policy.
Raises:
apitools.base.py.HttpError: If the request returns an HTTP error
"""
req = self.messages.GkehubProjectsLocationsScopesGetIamPolicyRequest(
resource=scope_path
)
return self.client.projects_locations_scopes.GetIamPolicy(req)
def SetScopeIamPolicy(self, scope_path, policy):
"""Sets the IAM policy for a scope resource.
Args:
scope_path: Full resource path of the scope.
policy: IAM policy to be set for the scope.
Returns:
An Iam Policy.
Raises:
apitools.base.py.HttpError: If the request returns an HTTP error
"""
policy_request = self.messages.SetIamPolicyRequest(
policy=policy,
)
req = self.messages.GkehubProjectsLocationsScopesSetIamPolicyRequest(
resource=scope_path,
setIamPolicyRequest=policy_request,
)
return self.client.projects_locations_scopes.SetIamPolicy(req)
def ListScopes(self, project):
"""Lists scopes in a project.
Args:
project: Project containing the scope.
Returns:
A ListScopesResponse (list of scopes and next page token).
Raises:
apitools.base.py.HttpError: If the request returns an HTTP error
"""
parent = util.ScopeParentName(project)
req = self.messages.GkehubProjectsLocationsScopesListRequest(
pageToken='', parent=parent
)
return list_pager.YieldFromList(
self.client.projects_locations_scopes,
req,
field='scopes',
batch_size_attribute=None,
)
def ListPermittedScopes(self, project):
"""Lists scopes in a project permitted to be viewed by the caller.
Args:
project: Project containing the scope.
Returns:
A ListPermittedScopesResponse (list of permitted scopes and next page
token).
Raises:
apitools.base.py.HttpError: If the request returns an HTTP error
"""
parent = util.ScopeParentName(project)
req = self.messages.GkehubProjectsLocationsScopesListPermittedRequest(
pageToken='', parent=parent
)
return list_pager.YieldFromList(
self.client.projects_locations_scopes,
req,
method='ListPermitted',
field='scopes',
batch_size_attribute=None,
)
def ListBoundMemberships(self, scope_path):
"""Lists memberships bound to a scope.
Args:
scope_path: Full resource path of the scope for listing bound memberships.
Returns:
A ListMembershipsResponse (list of memberships and next page token)
Raises:
apitools.base.py.HttpError: if the request returns an HTTP error
"""
req = self.messages.GkehubProjectsLocationsScopesListMembershipsRequest(
pageToken='', scopeName=scope_path
)
return list_pager.YieldFromList(
self.client.projects_locations_scopes,
req,
method='ListMemberships',
field='memberships',
batch_size_attribute=None,
)
def UpdateScope(
self, scope_path, labels=None, namespace_labels=None, mask=''
):
"""Updates a scope resource in the fleet.
Args:
scope_path: Full resource path of the scope.
labels: Labels for the resource.
namespace_labels: Namespace-level labels for the cluster namespace.
mask: A mask of the fields to update.
Returns:
A longrunning operation for updating the namespace.
"""
scope = self.messages.Scope(
name=scope_path,
labels=labels,
namespaceLabels=namespace_labels,
)
req = self.messages.GkehubProjectsLocationsScopesPatchRequest(
scope=scope,
name=scope_path,
updateMask=mask,
)
op = self.client.projects_locations_scopes.Patch(req)
op_resource = resources.REGISTRY.ParseRelativeName(
op.name, collection='gkehub.projects.locations.operations'
)
return waiter.WaitFor(
waiter.CloudOperationPoller(
self.client.projects_locations_scopes,
self.client.projects_locations_operations,
),
op_resource,
'Waiting for scope to be updated',
)
def GetScopeNamespace(self, namespace_path):
"""Gets a namespace resource from the GKEHub API.
Args:
namespace_path: Full resource path of the namespace.
Returns:
A namespace resource.
Raises:
apitools.base.py.HttpError: If the request returns an HTTP error
"""
req = self.messages.GkehubProjectsLocationsScopesNamespacesGetRequest(
name=namespace_path
)
return self.client.projects_locations_scopes_namespaces.Get(req)
def CreateScopeNamespace(
self, name, namespace_path, parent, labels=None, namespace_labels=None
):
"""Creates a namespace resource from the GKEHub API.
Args:
name: The namespace name.
namespace_path: Full resource path of the namespace.
parent: Full resource path of the scope containing the namespace.
labels: labels for namespace resource.
namespace_labels: Namespace-level labels for the cluster namespace.
Returns:
A namespace resource.
Raises:
apitools.base.py.HttpError: If the request returns an HTTP error.
"""
namespace = self.messages.Namespace(
name=namespace_path,
scope='',
labels=labels,
namespaceLabels=namespace_labels,
)
req = self.messages.GkehubProjectsLocationsScopesNamespacesCreateRequest(
namespace=namespace, scopeNamespaceId=name, parent=parent
)
op = self.client.projects_locations_scopes_namespaces.Create(req)
op_resource = resources.REGISTRY.ParseRelativeName(
op.name, collection='gkehub.projects.locations.operations'
)
return waiter.WaitFor(
waiter.CloudOperationPoller(
self.client.projects_locations_scopes_namespaces,
self.client.projects_locations_operations,
),
op_resource,
'Waiting for namespace to be created',
)
def DeleteScopeNamespace(self, namespace_path):
"""Deletes a namespace resource from the fleet.
Args:
namespace_path: Full resource path of the namespace.
Returns:
A long running operation for deleting the namespace.
Raises:
apitools.base.py.HttpError: If the request returns an HTTP error.
"""
req = self.messages.GkehubProjectsLocationsScopesNamespacesDeleteRequest(
name=namespace_path
)
op = self.client.projects_locations_scopes_namespaces.Delete(req)
op_resource = resources.REGISTRY.ParseRelativeName(
op.name, collection='gkehub.projects.locations.operations'
)
return waiter.WaitFor(
waiter.CloudOperationPollerNoResources(
self.client.projects_locations_operations,
),
op_resource,
'Waiting for namespace to be deleted',
)
def UpdateScopeNamespace(
self, namespace_path, labels=None, namespace_labels=None, mask=''
):
"""Updates a namespace resource in the fleet.
Args:
namespace_path: Full resource path of the namespace.
labels: Labels for the resource.
namespace_labels: Namespace-level labels for the cluster namespace.
mask: A mask of the fields to update.
Returns:
A longrunning operation for updating the namespace.
Raises:
"""
# Namespace containing fields with updated value(s)
namespace = self.messages.Namespace(
name=namespace_path,
scope='',
labels=labels,
namespaceLabels=namespace_labels,
)
req = self.messages.GkehubProjectsLocationsScopesNamespacesPatchRequest(
namespace=namespace,
name=namespace_path,
updateMask=mask,
)
op = self.client.projects_locations_scopes_namespaces.Patch(req)
op_resource = resources.REGISTRY.ParseRelativeName(
op.name, collection='gkehub.projects.locations.operations'
)
return waiter.WaitFor(
waiter.CloudOperationPoller(
self.client.projects_locations_scopes_namespaces,
self.client.projects_locations_operations,
),
op_resource,
'Waiting for namespace to be updated',
)
def ListScopeNamespaces(self, parent):
"""Lists namespaces in a project.
Args:
parent: Full resource path of the scope containing the namespace.
Returns:
A ListNamespaceResponse (list of namespaces and next page token).
Raises:
apitools.base.py.HttpError: If the request returns an HTTP error.
"""
req = self.messages.GkehubProjectsLocationsScopesNamespacesListRequest(
pageToken='', parent=parent
)
return list_pager.YieldFromList(
self.client.projects_locations_scopes_namespaces,
req,
field='scopeNamespaces',
batch_size_attribute=None,
)
def GetNamespace(self, project, name):
"""Gets a namespace resource from the GKEHub API.
Args:
project: the project containing the namespace.
name: the namespace name.
Returns:
A namespace resource
Raises:
apitools.base.py.HttpError: if the request returns an HTTP error
"""
req = self.messages.GkehubProjectsLocationsNamespacesGetRequest(
name=util.NamespaceResourceName(project, name)
)
return self.client.projects_locations_namespaces.Get(req)
def CreateNamespace(self, name, scope, project):
"""Creates a namespace resource from the GKEHub API.
Args:
name: the namespace name.
scope: the scope containing the namespace.
project: the project containing the namespace.
Returns:
A namespace resource
Raises:
apitools.base.py.HttpError: if the request returns an HTTP error
"""
namespace = self.messages.Namespace(
name=util.NamespaceResourceName(project, name), scope=scope
)
req = self.messages.GkehubProjectsLocationsNamespacesCreateRequest(
namespace=namespace,
namespaceId=name,
parent=util.NamespaceParentName(project),
)
op = self.client.projects_locations_namespaces.Create(req)
op_resource = resources.REGISTRY.ParseRelativeName(
op.name, collection='gkehub.projects.locations.operations'
)
return waiter.WaitFor(
waiter.CloudOperationPoller(
self.client.projects_locations_namespaces,
self.client.projects_locations_operations,
),
op_resource,
'Waiting for namespace to be created',
)
def DeleteNamespace(self, project, name):
"""Deletes a namespace resource from the fleet.
Args:
project: the project containing the namespace.
name: the name of the namespace.
Returns:
An operation
Raises:
apitools.base.py.HttpError: if the request returns an HTTP error
"""
req = self.messages.GkehubProjectsLocationsNamespacesDeleteRequest(
name=util.NamespaceResourceName(project, name)
)
op = self.client.projects_locations_namespaces.Delete(req)
op_resource = resources.REGISTRY.ParseRelativeName(
op.name, collection='gkehub.projects.locations.operations'
)
return waiter.WaitFor(
waiter.CloudOperationPollerNoResources(
self.client.projects_locations_operations,
),
op_resource,
'Waiting for namespace to be deleted',
)
def UpdateNamespace(self, name, scope, project, mask):
"""Updates a namespace resource in the fleet.
Args:
name: the namespace name.
scope: the scope containing the namespace.
project: the project containing the namespace.
mask: a mask of the fields to update.
Returns:
An operation
Raises:
apitools.base.py.HttpError: if the request returns an HTTP error
"""
# Namespace containing fields with updated value(s)
namespace = self.messages.Namespace(
name=util.NamespaceResourceName(project, name), scope=scope
)
req = self.messages.GkehubProjectsLocationsNamespacesPatchRequest(
namespace=namespace,
name=util.NamespaceResourceName(project, name),
updateMask=mask,
)
op = self.client.projects_locations_namespaces.Patch(req)
op_resource = resources.REGISTRY.ParseRelativeName(
op.name, collection='gkehub.projects.locations.operations'
)
return waiter.WaitFor(
waiter.CloudOperationPoller(
self.client.projects_locations_namespaces,
self.client.projects_locations_operations,
),
op_resource,
'Waiting for namespace to be updated',
)
def ListNamespaces(self, project):
"""Lists namespaces in a project.
Args:
project: the project to list namespaces from.
Returns:
A ListNamespaceResponse (list of namespaces and next page token)
Raises:
apitools.base.py.HttpError: if the request returns an HTTP error
"""
req = self.messages.GkehubProjectsLocationsNamespacesListRequest(
pageToken='', parent=util.NamespaceParentName(project)
)
return list_pager.YieldFromList(
self.client.projects_locations_namespaces,
req,
field='namespaces',
batch_size_attribute=None,
)
def GetRBACRoleBinding(self, name):
"""Gets an RBACRoleBinding resource from the GKEHub API.
Args:
name: the full rolebinding resource name.
Returns:
An RBACRoleBinding resource
Raises:
apitools.base.py.HttpError: if the request returns an HTTP error
"""
req = self.messages.GkehubProjectsLocationsNamespacesRbacrolebindingsGetRequest(
name=name
)
return self.client.projects_locations_namespaces_rbacrolebindings.Get(req)
def CreateRBACRoleBinding(self, name, role, user, group):
"""Creates an RBACRoleBinding resource from the GKEHub API.
Args:
name: the full rbacrolebinding resource name.
role: the role.
user: the user.
group: the group.
Returns:
An RBACRoleBinding resource
Raises:
apitools.base.py.HttpError: if the request returns an HTTP error
calliope_exceptions.RequiredArgumentException: if a required field is
missing
"""
rolebinding = self.messages.RBACRoleBinding(
name=name,
role=self.messages.Role(
predefinedRole=self.messages.Role.PredefinedRoleValueValuesEnum(
role.upper()
)
),
user=user,
group=group,
)
resource = resources.REGISTRY.ParseRelativeName(
name,
'gkehub.projects.locations.namespaces.rbacrolebindings',
api_version='v1alpha',
)
req = self.messages.GkehubProjectsLocationsNamespacesRbacrolebindingsCreateRequest(
rBACRoleBinding=rolebinding,
rbacrolebindingId=resource.Name(),
parent=resource.Parent().RelativeName(),
)
return self.client.projects_locations_namespaces_rbacrolebindings.Create(
req
)
def DeleteRBACRoleBinding(self, name):
"""Deletes an RBACRoleBinding resource from the fleet.
Args:
name: the resource name of the rolebinding.
Returns:
An operation
Raises:
apitools.base.py.HttpError: if the request returns an HTTP error
"""
req = self.messages.GkehubProjectsLocationsNamespacesRbacrolebindingsDeleteRequest(
name=name
)
return self.client.projects_locations_namespaces_rbacrolebindings.Delete(
req
)
def UpdateRBACRoleBinding(self, name, user, group, role, mask):
"""Updates an RBACRoleBinding resource in the fleet.
Args:
name: the rolebinding name.
user: the user.
group: the group.
role: the role.
mask: a mask of the fields to update.
Returns:
An operation
Raises:
apitools.base.py.HttpError: if the request returns an HTTP error
"""
# RoleBinding containing fields with updated value(s)
rolebinding = self.messages.RBACRoleBinding(
name=name,
user=user,
group=group,
role=self.messages.Role(
predefinedRole=self.messages.Role.PredefinedRoleValueValuesEnum(
role.upper()
)
),
)
req = self.messages.GkehubProjectsLocationsNamespacesRbacrolebindingsPatchRequest(
rBACRoleBinding=rolebinding, name=rolebinding.name, updateMask=mask
)
return self.client.projects_locations_namespaces_rbacrolebindings.Patch(req)
def ListRBACRoleBindings(self, project, namespace):
"""Lists rolebindings in a namespace.
Args:
project: the project containing the namespace to list rolebindings from.
namespace: the namespace to list rolebindings from.
Returns:
A ListNamespaceResponse (list of rolebindings and next page token)
Raises:
apitools.base.py.HttpError: if the request returns an HTTP error
"""
req = self.messages.GkehubProjectsLocationsNamespacesRbacrolebindingsListRequest(
pageToken='', parent=util.RBACRoleBindingParentName(project, namespace)
)
return list_pager.YieldFromList(
self.client.projects_locations_namespaces_rbacrolebindings,
req,
field='rbacrolebindings',
batch_size_attribute=None,
)
def GetScopeRBACRoleBinding(self, name):
"""Gets an ScopeRBACRoleBinding resource from the GKEHub API.
Args:
name: the full rolebinding resource name.
Returns:
An ScopeRBACRoleBinding resource
Raises:
apitools.base.py.HttpError: if the request returns an HTTP error
"""
req = self.messages.GkehubProjectsLocationsScopesRbacrolebindingsGetRequest(
name=name
)
return self.client.projects_locations_scopes_rbacrolebindings.Get(req)
def CreateScopeRBACRoleBinding(
self, name, role, custom_role, user, group, labels=None
):
"""Creates an ScopeRBACRoleBinding resource from the GKEHub API.
Args:
name: the full Scoperbacrolebinding resource name.
role: the role.
custom_role: the custom role.
user: the user.
group: the group.
labels: labels for the RBACRoleBinding resource.
Returns:
An ScopeRBACRoleBinding resource
Raises:
apitools.base.py.HttpError: if the request returns an HTTP error
calliope_exceptions.RequiredArgumentException: if a required field is
missing
"""
if custom_role:
roledef = self.messages.Role(customRole=custom_role)
else:
roledef = self.messages.Role(
predefinedRole=self.messages.Role.PredefinedRoleValueValuesEnum(
role.upper()
)
)
rolebinding = self.messages.RBACRoleBinding(
name=name,
role=roledef,
user=user,
group=group,
labels=labels,
)
resource = resources.REGISTRY.ParseRelativeName(
name,
'gkehub.projects.locations.scopes.rbacrolebindings',
api_version='v1alpha',
)
req = self.messages.GkehubProjectsLocationsScopesRbacrolebindingsCreateRequest(
rBACRoleBinding=rolebinding,
rbacrolebindingId=resource.Name(),
parent=resource.Parent().RelativeName(),
)
op = self.client.projects_locations_scopes_rbacrolebindings.Create(req)
op_resource = resources.REGISTRY.ParseRelativeName(
op.name, collection='gkehub.projects.locations.operations'
)
return waiter.WaitFor(
waiter.CloudOperationPoller(
self.client.projects_locations_scopes_rbacrolebindings,
self.client.projects_locations_operations,
),
op_resource,
'Waiting for rbacrolebinding to be created',
)
def DeleteScopeRBACRoleBinding(self, name):
"""Deletes an ScopeRBACRoleBinding resource from the fleet.
Args:
name: the resource name of the rolebinding.
Returns:
An operation
Raises:
apitools.base.py.HttpError: if the request returns an HTTP error
"""
req = self.messages.GkehubProjectsLocationsScopesRbacrolebindingsDeleteRequest(
name=name
)
op = self.client.projects_locations_scopes_rbacrolebindings.Delete(req)
op_resource = resources.REGISTRY.ParseRelativeName(
op.name, collection='gkehub.projects.locations.operations'
)
return waiter.WaitFor(
waiter.CloudOperationPollerNoResources(
self.client.projects_locations_operations,
),
op_resource,
'Waiting for rbacrolebinding to be deleted',
)
def UpdateScopeRBACRoleBinding(
self, name, user, group, role, custom_role, labels, mask
):
"""Updates an ScopeRBACRoleBinding resource in the fleet.
Args:
name: the rolebinding name.
user: the user.
group: the group.
role: the predefined role.
custom_role: the custom role.
labels: labels for the RBACRoleBinding resource.
mask: a mask of the fields to update.
Returns:
An operation
Raises:
apitools.base.py.HttpError: if the request returns an HTTP error
"""
roledef = None
if custom_role:
roledef = self.messages.Role(customRole=custom_role)
if role:
roledef = self.messages.Role(
predefinedRole=self.messages.Role.PredefinedRoleValueValuesEnum(
role.upper()
)
)
# RoleBinding containing fields with updated value(s)
rolebinding = self.messages.RBACRoleBinding(
name=name,
user=user,
group=group,
role=roledef,
labels=labels,
)
req = (
self.messages.GkehubProjectsLocationsScopesRbacrolebindingsPatchRequest(
rBACRoleBinding=rolebinding, name=rolebinding.name, updateMask=mask
)
)
op = self.client.projects_locations_scopes_rbacrolebindings.Patch(req)
op_resource = resources.REGISTRY.ParseRelativeName(
op.name, collection='gkehub.projects.locations.operations'
)
return waiter.WaitFor(
waiter.CloudOperationPoller(
self.client.projects_locations_scopes_rbacrolebindings,
self.client.projects_locations_operations,
),
op_resource,
'Waiting for rbacrolebinding to be updated',
)
def ListScopeRBACRoleBindings(self, project, scope):
"""Lists rolebindings in a scope.
Args:
project: the project containing the scope to list rolebindings from.
scope: the scope to list rolebindings from.
Returns:
A ListscopeResponse (list of rolebindings and next page token)
Raises:
apitools.base.py.HttpError: if the request returns an HTTP error
"""
req = (
self.messages.GkehubProjectsLocationsScopesRbacrolebindingsListRequest(
pageToken='',
parent=util.ScopeRBACRoleBindingParentName(project, scope),
)
)
return list_pager.YieldFromList(
self.client.projects_locations_scopes_rbacrolebindings,
req,
field='rbacrolebindings',
batch_size_attribute=None,
)
def GetMembershipBinding(self, name):
"""Gets a Membership-Binding resource from the GKEHub API.
Args:
name: the full membership-binding resource name.
Returns:
A Membership-Binding resource
Raises:
apitools.base.py.HttpError: if the request returns an HTTP error
"""
req = self.messages.GkehubProjectsLocationsMembershipsBindingsGetRequest(
name=name
)
return self.client.projects_locations_memberships_bindings.Get(req)
def CreateMembershipBinding(self, name, scope, labels=None):
"""Creates a Membership-Binding resource from the GKEHub API.
Args:
name: the full binding resource name.
scope: the Scope to be associated with Binding.
labels: labels for the membership binding resource
Returns:
A Membership-Binding resource
Raises:
apitools.base.py.HttpError: if the request returns an HTTP error
calliope_exceptions.RequiredArgumentException: if a required field is
missing
"""
binding = self.messages.MembershipBinding(
name=name, scope=scope, labels=labels
)
resource = resources.REGISTRY.ParseRelativeName(
name,
'gkehub.projects.locations.memberships.bindings',
api_version='v1alpha',
)
req = self.messages.GkehubProjectsLocationsMembershipsBindingsCreateRequest(
membershipBinding=binding,
membershipBindingId=resource.Name(),
parent=resource.Parent().RelativeName(),
)
op = self.client.projects_locations_memberships_bindings.Create(req)
op_resource = resources.REGISTRY.ParseRelativeName(
op.name, collection='gkehub.projects.locations.operations'
)
return waiter.WaitFor(
waiter.CloudOperationPoller(
self.client.projects_locations_memberships_bindings,
self.client.projects_locations_operations,
),
op_resource,
'Waiting for membership binding to be created',
)
def ListMembershipBindings(self, project, membership, location='global'):
"""Lists Bindings in a Membership.
Args:
project: the project containing the Membership to list Bindings from.
membership: the Membership to list Bindings from.
location: the Membrship location to list Bindings
Returns:
A ListMembershipBindingResponse (list of bindings and next page token)
Raises:
apitools.base.py.HttpError: if the request returns an HTTP error
"""
req = self.messages.GkehubProjectsLocationsMembershipsBindingsListRequest(
pageToken='',
parent=util.MembershipBindingParentName(
project, membership, location, self.release_track
),
)
return list_pager.YieldFromList(
self.client.projects_locations_memberships_bindings,
req,
field='membershipBindings',
batch_size_attribute=None,
)
def UpdateMembershipBinding(self, name, scope, labels, mask):
"""Updates a Membership-Binding resource.
Args:
name: the Binding name.
scope: the Scope associated with binding.
labels: the labels for the Membership Binding resource.
mask: a mask of the fields to update.
Returns:
An operation
Raises:
apitools.base.py.HttpError: if the request returns an HTTP error
"""
# Binding containing fields with updated value(s)
binding = self.messages.MembershipBinding(
name=name,
scope=scope,
labels=labels,
)
req = self.messages.GkehubProjectsLocationsMembershipsBindingsPatchRequest(
membershipBinding=binding, name=binding.name, updateMask=mask
)
op = self.client.projects_locations_memberships_bindings.Patch(req)
op_resource = resources.REGISTRY.ParseRelativeName(
op.name, collection='gkehub.projects.locations.operations'
)
return waiter.WaitFor(
waiter.CloudOperationPoller(
self.client.projects_locations_memberships_bindings,
self.client.projects_locations_operations,
),
op_resource,
'Waiting for membership binding to be updated',
)
def DeleteMembershipBinding(self, name):
"""Deletes a Membership-Binding resource.
Args:
name: the resource name of the Binding.
Returns:
An operation
Raises:
apitools.base.py.HttpError: if the request returns an HTTP error
"""
req = self.messages.GkehubProjectsLocationsMembershipsBindingsDeleteRequest(
name=name
)
op = self.client.projects_locations_memberships_bindings.Delete(req)
op_resource = resources.REGISTRY.ParseRelativeName(
op.name, collection='gkehub.projects.locations.operations'
)
return waiter.WaitFor(
waiter.CloudOperationPollerNoResources(
self.client.projects_locations_operations,
),
op_resource,
'Waiting for membership binding to be deleted',
)
def GetMembershipRbacRoleBinding(self, name):
"""Gets a Membership RBAC RoleBinding resource from the GKEHub API.
Args:
name: the full Membership RBAC RoleBinding resource name.
Returns:
A Membership RBAC Role Binding resource.
Raises:
apitools.base.py.HttpError: if the request returns an HTTP error.
"""
req = self.messages.GkehubProjectsLocationsMembershipsRbacrolebindingsGetRequest(
name=name
)
return self.client.projects_locations_memberships_rbacrolebindings.Get(req)
def CreateMembershipRbacRoleBinding(self, name, role, user, group):
"""Creates a Membership RBAC RoleBinding resource from the GKEHub API.
Args:
name: the full Membership RBAC Role Binding resource name.
role: the role for the RBAC policies.
user: the user to apply the RBAC policies for.
group: the group to apply the RBAC policies for.
Returns:
A Membership RBAC Role Binding resource.
Raises:
apitools.base.py.HttpError: if the request returns an HTTP error.
"""
rolebinding = self.messages.RBACRoleBinding(
name=name,
role=self.messages.Role(
predefinedRole=self.messages.Role.PredefinedRoleValueValuesEnum(
role.upper()
)
),
user=user,
group=group,
)
resource = resources.REGISTRY.ParseRelativeName(
name,
'gkehub.projects.locations.memberships.rbacrolebindings',
api_version='v1alpha',
)
req = self.messages.GkehubProjectsLocationsMembershipsRbacrolebindingsCreateRequest(
rBACRoleBinding=rolebinding,
rbacrolebindingId=resource.Name(),
parent=resource.Parent().RelativeName(),
)
return self.client.projects_locations_memberships_rbacrolebindings.Create(
req
)
def DeleteMembershipRbacRoleBinding(self, name):
"""Deletes a Membership RBAC RoleBinding resource.
Args:
name: the resource name of the Membership RBAC RoleBinding.
Returns:
A long running operation for the deletion.
Raises:
apitools.base.py.HttpError: if the request returns an HTTP error.
"""
req = self.messages.GkehubProjectsLocationsMembershipsRbacrolebindingsDeleteRequest(
name=name
)
return self.client.projects_locations_memberships_rbacrolebindings.Delete(
req
)
def GenerateMembershipRbacRoleBindingYaml(self, name, role, user, group):
"""Gets YAML containing RBAC policies for a membership RBAC role binding.
Args:
name: the full Membership RBAC Role Binding resource name.
role: the role for the RBAC policies.
user: the user to apply the RBAC policies for.
group: the group to apply the RBAC policies for.
Returns:
YAML text containing RBAC policies for a membership RBAC rolebinding.
Raises:
apitools.base.py.HttpError: if the request returns an HTTP error.
"""
rolebinding = self.messages.RBACRoleBinding(
name=name,
role=self.messages.Role(
predefinedRole=self.messages.Role.PredefinedRoleValueValuesEnum(
role.upper()
)
),
user=user,
group=group,
)
resource = resources.REGISTRY.ParseRelativeName(
name,
'gkehub.projects.locations.memberships.rbacrolebindings',
api_version='v1alpha',
)
req = self.messages.GkehubProjectsLocationsMembershipsRbacrolebindingsGenerateMembershipRBACRoleBindingYAMLRequest(
rBACRoleBinding=rolebinding,
rbacrolebindingId=resource.Name(),
parent=resource.Parent().RelativeName(),
)
return self.client.projects_locations_memberships_rbacrolebindings.GenerateMembershipRBACRoleBindingYAML(
req
)
def CreateRollout(
self, req: types.GkehubProjectsLocationsRolloutsCreateRequest
):
"""Creates a rollout resource from the Fleet rollout API.
Args:
req: An HTTP create rollout request to be sent to the API server.
Returns:
A long-running operation.
Raises:
apitools.base.py.HttpError: if the request returns an HTTP error
"""
return self.client.projects_locations_rollouts.Create(req)
def DescribeRollout(
self, req: types.GkehubProjectsLocationsRolloutsGetRequest
) -> types.Rollout:
"""Describes a fleet rollout."""
return self.client.projects_locations_rollouts.Get(req)
def ListRollouts(
self,
req: types.GkehubProjectsLocationsRolloutsListRequest,
page_size=None,
limit=None,
) -> types.RolloutGenerator:
"""Lists fleet rollouts."""
return list_pager.YieldFromList(
self.client.projects_locations_rollouts,
req,
field='rollouts',
batch_size=page_size,
limit=limit,
batch_size_attribute='pageSize',
)
def PauseRollout(
self, req: types.GkehubProjectsLocationsRolloutsPauseRequest
):
"""Pause a fleet rollout."""
return self.client.projects_locations_rollouts.Pause(req)
def ResumeRollout(
self, req: types.GkehubProjectsLocationsRolloutsResumeRequest
):
"""Resume a fleet rollout."""
return self.client.projects_locations_rollouts.Resume(req)
def DeleteRollout(
self, req: types.GkehubProjectsLocationsRolloutsDeleteRequest
):
"""Delete a fleet rollout."""
return self.client.projects_locations_rollouts.Delete(req)
def CreateRolloutSequence(
self, req: types.GkehubProjectsLocationsRolloutSequencesCreateRequest
):
"""Creates a rollout sequence resource.
Args:
req: An HTTP create rollout sequence request to be sent to the API server.
Returns:
A long-running operation.
Raises:
apitools.base.py.HttpError: if the request returns an HTTP error
"""
return self.client.projects_locations_rolloutSequences.Create(req)
def DescribeRolloutSequence(
self, req: types.GkehubProjectsLocationsRolloutSequencesGetRequest
) -> types.RolloutSequence:
"""Describes a rollout sequence."""
return self.client.projects_locations_rolloutSequences.Get(req)
def ListRolloutSequences(
self,
req: types.GkehubProjectsLocationsRolloutSequencesListRequest,
page_size=None,
limit=None,
) -> types.RolloutSequenceGenerator:
"""Lists rollout sequences."""
return list_pager.YieldFromList(
self.client.projects_locations_rolloutSequences,
req,
field='rolloutSequences',
batch_size=page_size,
limit=limit,
batch_size_attribute='pageSize',
)
def UpdateRolloutSequence(
self, req: types.GkehubProjectsLocationsRolloutSequencesPatchRequest
):
"""Updates a RolloutSequence and returns the long-running operation message."""
return self.client.projects_locations_rolloutSequences.Patch(req)
def DeleteRolloutSequence(
self, req: types.GkehubProjectsLocationsRolloutSequencesDeleteRequest
):
"""Deletes a rollout sequence."""
return self.client.projects_locations_rolloutSequences.Delete(req)
class OperationClient:
"""Client for the GKE Hub API long-running operations."""
def __init__(self, release_track: base.ReleaseTrack):
self.messages = util.GetMessagesModule(release_track)
self.client = util.GetClientInstance(release_track=release_track)
self.service = self.client.projects_locations_operations
def Wait(self, operation_ref: resources.Resource):
"""Waits for a long-running operation to complete.
Polling message is printed to the terminal periodically, until the operation
completes or times out.
Args:
operation_ref: Long-running peration in the format of resource argument.
Returns:
A completed long-running operation.
"""
return waiter.WaitFor(
waiter.CloudOperationPollerNoResources(self.service),
operation_ref,
'Waiting for operation [{}] to complete'.format(
operation_ref.RelativeName()
),
wait_ceiling_ms=10000,
max_wait_ms=43200000,
)
def Describe(self, req: types.GkehubProjectsLocationsOperationsGetRequest):
"""Describes a long-running operation."""
return self.client.projects_locations_operations.Get(req)
def List(
self,
req: types.GkehubProjectsLocationsOperationsListRequest,
page_size=None,
limit=None,
) -> Generator[types.Operation, None, None]:
"""Lists long-running operations.
Currently gcloud implements client-side filtering and limiting behavior.
Args:
req: List request to pass to the server.
page_size: Maximum number of resources per page.
limit: Client-side limit control.
Returns:
A list of long-running operations.
"""
return list_pager.YieldFromList(
self.client.projects_locations_operations,
req,
field='operations',
batch_size=page_size,
limit=limit,
batch_size_attribute='pageSize',
)