# -*- 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', )