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

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

View File

@@ -0,0 +1,375 @@
# -*- coding: utf-8 -*- #
# Copyright 2023 Google LLC. All Rights Reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
"""Apphub Applications API."""
from __future__ import absolute_import
from __future__ import division
from __future__ import unicode_literals
from apitools.base.py import list_pager
from googlecloudsdk.api_lib.apphub import consts as api_lib_consts
from googlecloudsdk.api_lib.apphub import utils as api_lib_utils
from googlecloudsdk.api_lib.util import waiter
from googlecloudsdk.calliope import base
from googlecloudsdk.command_lib.iam import iam_util
class ApplicationsClient(object):
"""Client for Applications in apphub API."""
def __init__(self, release_track=base.ReleaseTrack.ALPHA):
self.client = api_lib_utils.GetClientInstance(release_track)
self.messages = api_lib_utils.GetMessagesModule(release_track)
self._app_client = self.client.projects_locations_applications
self._lookup_client = self.client.projects_locations
self._poller = waiter.CloudOperationPoller(
self._app_client,
self.client.projects_locations_operations,
)
self._delete_poller = waiter.CloudOperationPollerNoResources(
self.client.projects_locations_operations,
)
self._lookup_poller = waiter.CloudOperationPoller(
self._lookup_client,
self.client.projects_locations_operations,
)
def Describe(self, app_id):
"""Describe an application in the Project/location.
Args:
app_id: str, the application id.
Returns:
Described service project Resource.
"""
describe_req = self.messages.ApphubProjectsLocationsApplicationsGetRequest(
name=app_id
)
return self._app_client.Get(describe_req)
def List(
self,
parent,
limit=None,
page_size=100,
):
"""List applications in the Projects/Location.
Args:
parent: str, projects/{projectId}/locations/{location}
limit: int or None, the total number of results to return. Default value
is None
page_size: int, the number of entries in each batch (affects requests
made, but not the yielded results). Default value is 100.
Returns:
Generator of matching service projects.
"""
list_req = self.messages.ApphubProjectsLocationsApplicationsListRequest(
parent=parent
)
return list_pager.YieldFromList(
self._app_client,
list_req,
field='applications',
batch_size=page_size,
limit=limit,
batch_size_attribute='pageSize',
)
def Create(
self,
app_id,
scope_type,
display_name,
description,
attributes,
async_flag,
parent,
):
"""Creates an application in the Project/location.
Args:
app_id: str, Application ID
scope_type: str, Scope of the Application
display_name: str, Human-friendly display name
description: str, Description of the Application
attributes: Attributes, Attributes of the Application
async_flag: Boolean value for async operation. If true the operation will
be async
parent: parent for project resource
Returns:
Application or Operation based on async flag value.
"""
application = self.messages.Application(
description=description,
displayName=display_name,
scope=self.messages.Scope(
type=self.messages.Scope.TypeValueValuesEnum(scope_type)
),
attributes=attributes,
)
create_req = self.messages.ApphubProjectsLocationsApplicationsCreateRequest(
application=application, applicationId=app_id, parent=parent
)
operation = self._app_client.Create(create_req)
if async_flag:
return operation
create_response = api_lib_utils.WaitForOperation(
self._poller,
operation,
api_lib_consts.CreateApplication.WAIT_FOR_ADD_MESSAGE,
api_lib_consts.CreateApplication.ADD_TIMELIMIT_SEC,
)
return create_response
def Update(self, args, app_ref, release_track=base.ReleaseTrack.ALPHA):
"""Updates an Apphub application.
Args:
args: args, Arguments provided by the client
app_ref: Application reference
release_track: release_track provided by the client
Returns:
Application or Operation based on async flag value.
"""
update_mask = ''
attributes = api_lib_utils.GetMessagesModule(release_track).Attributes()
application = self.messages.Application(attributes=attributes)
if args.environment_type is not None:
attributes.environment = api_lib_utils.GetMessagesModule(
release_track
).Environment(
type=api_lib_utils.GetMessagesModule(
release_track
).Environment.TypeValueValuesEnum(args.environment_type)
)
update_mask = api_lib_utils.AddToUpdateMask(
update_mask,
api_lib_consts.UpdateApplication.UPDATE_MASK_ENVIRONMENT_FIELD_NAME,
)
if args.criticality_type:
attributes.criticality = api_lib_utils.GetMessagesModule(
release_track
).Criticality(
type=api_lib_utils.GetMessagesModule(
release_track
).Criticality.TypeValueValuesEnum(args.criticality_type)
)
update_mask = api_lib_utils.AddToUpdateMask(
update_mask,
api_lib_consts.UpdateApplication.UPDATE_MASK_CRITICALITY_FIELD_NAME,
)
for b_owner in args.business_owners or []:
business_owner = api_lib_utils.GetMessagesModule(
release_track
).ContactInfo()
business_owner.email = b_owner.get('email', None)
if b_owner.get('display-name', None):
business_owner.displayName = b_owner.get('display-name', None)
if release_track == base.ReleaseTrack.ALPHA:
if b_owner.get('channel-uri', None):
business_owner.channel = api_lib_utils.GetMessagesModule(
release_track
).Channel(uri=b_owner.get('channel-uri'))
attributes.businessOwners.append(business_owner)
update_mask = api_lib_utils.AddToUpdateMask(
update_mask,
api_lib_consts.UpdateApplication.UPDATE_MASK_BUSINESS_OWNERS_FIELD_NAME,
)
for d_owner in args.developer_owners or []:
developer_owner = api_lib_utils.GetMessagesModule(
release_track
).ContactInfo()
developer_owner.email = d_owner.get('email', None)
if d_owner.get('display-name', None):
developer_owner.displayName = d_owner.get('display-name', None)
if release_track == base.ReleaseTrack.ALPHA:
if d_owner.get('channel-uri', None):
developer_owner.channel = api_lib_utils.GetMessagesModule(
release_track
).Channel(uri=d_owner.get('channel-uri'))
attributes.developerOwners.append(developer_owner)
update_mask = api_lib_utils.AddToUpdateMask(
update_mask,
api_lib_consts.UpdateApplication.UPDATE_MASK_DEVELOPER_OWNERS_FIELD_NAME,
)
for o_owner in args.operator_owners or []:
operator_owner = api_lib_utils.GetMessagesModule(
release_track
).ContactInfo()
operator_owner.email = o_owner.get('email', None)
if o_owner.get('display-name'):
operator_owner.displayName = o_owner.get('display-name')
if release_track == base.ReleaseTrack.ALPHA:
if o_owner.get('channel-uri'):
operator_owner.channel = api_lib_utils.GetMessagesModule(
release_track
).Channel(uri=o_owner.get('channel-uri'))
attributes.operatorOwners.append(operator_owner)
update_mask = api_lib_utils.AddToUpdateMask(
update_mask,
api_lib_consts.UpdateApplication.UPDATE_MASK_OPERATOR_OWNERS_FIELD_NAME,
)
if args.display_name is not None:
application.displayName = args.display_name
update_mask = api_lib_utils.AddToUpdateMask(
update_mask,
api_lib_consts.UpdateApplication.UPDATE_MASK_DISPLAY_NAME_FIELD_NAME,
)
if args.description is not None:
application.description = args.description
update_mask = api_lib_utils.AddToUpdateMask(
update_mask,
api_lib_consts.UpdateApplication.UPDATE_MASK_DESCRIPTION_FIELD_NAME,
)
patch_req = self.messages.ApphubProjectsLocationsApplicationsPatchRequest(
application=application,
name=app_ref.RelativeName(),
updateMask=update_mask,
)
operation = self._app_client.Patch(patch_req)
if args.async_:
return operation
patch_response = api_lib_utils.WaitForOperation(
self._poller,
operation,
api_lib_consts.UpdateApplication.WAIT_FOR_UPDATE_MESSAGE,
api_lib_consts.UpdateApplication.ADD_TIMELIMIT_SEC,
)
return patch_response
def Delete(self, app_id, async_flag):
"""Delete an application in the Project/location.
Args:
app_id: str, The name for the application being deleted
async_flag: Boolean value for async operation. If true the operation will
be async
Returns:
Empty Response Message or Operation based on async flag value.
"""
remove_req = self.messages.ApphubProjectsLocationsApplicationsDeleteRequest(
name=app_id
)
operation = self._app_client.Delete(remove_req)
if async_flag:
return operation
delete_response = api_lib_utils.WaitForOperation(
self._delete_poller,
operation,
api_lib_consts.DeleteApplication.WAIT_FOR_DELETE_MESSAGE,
api_lib_consts.DeleteApplication.REMOVE_TIMELIMIT_SEC,
)
return delete_response
def GetIamPolicy(self, app_id):
"""Fetch the IAM Policy attached to the sepcified application.
Args:
app_id: str, the application id.
Returns:
The application's IAM Policy.
"""
# version = iam_util.MAX_LIBRARY_IAM_SUPPORTED_VERSION
get_req = (
self.messages.ApphubProjectsLocationsApplicationsGetIamPolicyRequest(
resource=app_id,
)
)
return self._app_client.GetIamPolicy(get_req)
def SetIamPolicy(self, app_id, policy_file):
"""Sets an application's IamPolicy to the one provided.
If 'policy_file' has no etag specified, this will BLINDLY OVERWRITE the IAM
policy!
Args:
app_id: str, the application id..
policy_file: a policy file.
Returns:
The IAM Policy.
"""
policy = iam_util.ParsePolicyFile(policy_file, self.messages.Policy)
return self._SetIamPolicyHelper(app_id, policy)
def _SetIamPolicyHelper(self, app_id, policy):
set_req = (
self.messages.ApphubProjectsLocationsApplicationsSetIamPolicyRequest(
resource=app_id,
setIamPolicyRequest=self.messages.SetIamPolicyRequest(
policy=policy,),
))
return self._app_client.SetIamPolicy(set_req)
def AddIamPolicyBinding(self, app_id, member, role):
"""Does an atomic Read-Modify-Write, adding the member to the role.
Args:
app_id: str, the application id.
member: str, the principal to add the binding for.
role: predefined role, the role name to assign to the principal.
Returns:
The IAM Policy.
"""
policy = self.GetIamPolicy(app_id)
iam_util.AddBindingToIamPolicy(self.messages.Binding, policy, member, role)
return self._SetIamPolicyHelper(app_id, policy)
def RemoveIamPolicyBinding(self, app_id, member, role):
"""Does an atomic Read-Modify-Write, removing the member to the role.
Args:
app_id: str, the application id.
member: str, the principal to add the binding for.
role: predefined role, the role name to assign to the principal.
Returns:
The IAM Policy.
"""
policy = self.GetIamPolicy(app_id)
iam_util.RemoveBindingFromIamPolicy(policy, member, role)
return self._SetIamPolicyHelper(app_id, policy)

View File

@@ -0,0 +1,254 @@
# -*- coding: utf-8 -*- #
# Copyright 2023 Google LLC. All Rights Reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
"""Apphub Application Services API."""
from __future__ import absolute_import
from __future__ import division
from __future__ import unicode_literals
from apitools.base.py import list_pager
from googlecloudsdk.api_lib.apphub import consts as api_lib_consts
from googlecloudsdk.api_lib.apphub import utils as api_lib_utils
from googlecloudsdk.api_lib.util import waiter
from googlecloudsdk.calliope import base
from googlecloudsdk.core import log
class ServicesClient(object):
"""Client for Application services in apphub API."""
def __init__(self, release_track=base.ReleaseTrack.ALPHA):
self.client = api_lib_utils.GetClientInstance(release_track)
self.messages = api_lib_utils.GetMessagesModule(release_track)
self._app_services_client = (
self.client.projects_locations_applications_services
)
self._poller = waiter.CloudOperationPoller(
self._app_services_client,
self.client.projects_locations_operations,
)
self._delete_poller = waiter.CloudOperationPollerNoResources(
self.client.projects_locations_operations,
)
def Describe(self, service):
"""Describe a Application Service in the Project/location.
Args:
service: str, the name for the service being described.
Returns:
Described service Resource.
"""
describe_req = (
self.messages.ApphubProjectsLocationsApplicationsServicesGetRequest(
name=service
)
)
return self._app_services_client.Get(describe_req)
def List(
self,
parent,
limit=None,
page_size=100,
):
"""List application services in the Projects/Location.
Args:
parent: str,
projects/{projectId}/locations/{location}/applications/{application}
limit: int or None, the total number of results to return. Default value
is None
page_size: int, the number of entries in each batch (affects requests
made, but not the yielded results). Default value is 100.
Returns:
Generator of matching application services.
"""
list_req = (
self.messages.ApphubProjectsLocationsApplicationsServicesListRequest(
parent=parent
)
)
return list_pager.YieldFromList(
self._app_services_client,
list_req,
field='services',
batch_size=page_size,
limit=limit,
batch_size_attribute='pageSize',
)
def Delete(self, service, async_flag):
"""Delete a application service in the Project/location.
Args:
service: str, the name for the service being deleted
async_flag: Boolean value for async operation. If true the operation will
be async
Returns:
Empty Response Message or Operation based on async flag value.
"""
delete_req = (
self.messages.ApphubProjectsLocationsApplicationsServicesDeleteRequest(
name=service
)
)
operation = self._app_services_client.Delete(delete_req)
if async_flag:
return operation
delete_response = api_lib_utils.WaitForOperation(
self._delete_poller,
operation,
api_lib_consts.DeleteApplicationService.WAIT_FOR_DELETE_MESSAGE,
api_lib_consts.DeleteApplicationService.DELETE_TIMELIMIT_SEC,
)
return delete_response
def Create(
self,
service_id,
parent,
async_flag,
discovered_service,
display_name,
description,
attributes,
):
"""Creates an application in the Project/location.
Args:
service_id: str, Service ID
parent: parent for Application resource
async_flag: Boolean value for async operation. If true the operation will
be async
discovered_service: str, Discovered service name
display_name: str, Human-friendly display name
description: str, Description of the Service
attributes: Attributes, Attributes of the Service
Returns:
Service or Operation based on async flag value.
"""
service = self.messages.Service(
description=description,
displayName=display_name,
discoveredService=discovered_service,
attributes=attributes,
)
create_req = (
self.messages.ApphubProjectsLocationsApplicationsServicesCreateRequest(
service=service, serviceId=service_id, parent=parent
)
)
operation = self._app_services_client.Create(create_req)
if async_flag:
return operation
create_response = api_lib_utils.WaitForOperation(
self._poller,
operation,
api_lib_consts.CreateApplicationService.WAIT_FOR_CREATE_MESSAGE,
api_lib_consts.CreateApplicationService.CREATE_TIMELIMIT_SEC,
)
return create_response
def Update(self, service_id, async_flag, attributes, args):
"""Update application service."""
service, update_mask = self._UpdateHelper(args, attributes)
if not update_mask:
log.status.Print(
api_lib_consts.UpdateApplicationService.EMPTY_UPDATE_HELP_TEXT
)
return
update_request = (
self.messages.ApphubProjectsLocationsApplicationsServicesPatchRequest(
name=service_id,
service=service,
updateMask=update_mask,
)
)
operation = self._app_services_client.Patch(update_request)
if async_flag:
return operation
update_response = api_lib_utils.WaitForOperation(
self._poller,
operation,
api_lib_consts.UpdateApplicationService.WAIT_FOR_UPDATE_MESSAGE,
api_lib_consts.UpdateApplicationService.UPDATE_TIMELIMIT_SEC,
)
return update_response
def _UpdateHelper(self, args, attributes):
"""Helper to generate service and update_mask fields for update_request."""
service = self.messages.Service()
update_mask = ''
if args.display_name:
update_mask = api_lib_utils.AddToUpdateMask(
update_mask,
api_lib_consts.UpdateApplicationService.UPDATE_MASK_DISPLAY_NAME_FIELD_NAME,
)
service.displayName = args.display_name
if args.description:
update_mask = api_lib_utils.AddToUpdateMask(
update_mask,
api_lib_consts.UpdateApplicationService.UPDATE_MASK_DESCRIPTION_FIELD_NAME,
)
service.description = args.description
if attributes.criticality:
update_mask = api_lib_utils.AddToUpdateMask(
update_mask,
api_lib_consts.UpdateApplicationService.UPDATE_MASK_ATTR_CRITICALITY_FIELD_NAME,
)
if attributes.environment:
update_mask = api_lib_utils.AddToUpdateMask(
update_mask,
api_lib_consts.UpdateApplicationService.UPDATE_MASK_ATTR_ENVIRONMENT_FIELD_NAME,
)
if attributes.businessOwners:
update_mask = api_lib_utils.AddToUpdateMask(
update_mask,
api_lib_consts.UpdateApplicationService.UPDATE_MASK_ATTR_BUSINESS_OWNERS_FIELD_NAME,
)
if attributes.developerOwners:
update_mask = api_lib_utils.AddToUpdateMask(
update_mask,
api_lib_consts.UpdateApplicationService.UPDATE_MASK_ATTR_DEVELOPER_OWNERS_FIELD_NAME,
)
if attributes.operatorOwners:
update_mask = api_lib_utils.AddToUpdateMask(
update_mask,
api_lib_consts.UpdateApplicationService.UPDATE_MASK_ATTR_OPERATOR_OWNERS_FIELD_NAME,
)
service.attributes = attributes
return service, update_mask

View File

@@ -0,0 +1,254 @@
# -*- coding: utf-8 -*- #
# Copyright 2023 Google LLC. All Rights Reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
"""Apphub Application Workloads API."""
from __future__ import absolute_import
from __future__ import division
from __future__ import unicode_literals
from apitools.base.py import list_pager
from googlecloudsdk.api_lib.apphub import consts as api_lib_consts
from googlecloudsdk.api_lib.apphub import utils as api_lib_utils
from googlecloudsdk.api_lib.util import waiter
from googlecloudsdk.calliope import base
from googlecloudsdk.core import log
class WorkloadsClient(object):
"""Client for Application workloads in apphub API."""
def __init__(self, release_track=base.ReleaseTrack.ALPHA):
self.client = api_lib_utils.GetClientInstance(release_track)
self.messages = api_lib_utils.GetMessagesModule(release_track)
self._app_workloads_client = (
self.client.projects_locations_applications_workloads
)
self._poller = waiter.CloudOperationPoller(
self._app_workloads_client,
self.client.projects_locations_operations,
)
self._delete_poller = waiter.CloudOperationPollerNoResources(
self.client.projects_locations_operations,
)
def Describe(self, workload):
"""Describe a Application Workload in the Project/location.
Args:
workload: str, the name for the workload being described.
Returns:
Described workload Resource.
"""
describe_req = (
self.messages.ApphubProjectsLocationsApplicationsWorkloadsGetRequest(
name=workload
)
)
return self._app_workloads_client.Get(describe_req)
def List(
self,
parent,
limit=None,
page_size=100,
):
"""List application workloads in the Projects/Location.
Args:
parent: str,
projects/{projectId}/locations/{location}/applications/{application}
limit: int or None, the total number of results to return. Default value
is None
page_size: int, the number of entries in each batch (affects requests
made, but not the yielded results). Default value is 100.
Returns:
Generator of matching application workloads.
"""
list_req = (
self.messages.ApphubProjectsLocationsApplicationsWorkloadsListRequest(
parent=parent
)
)
return list_pager.YieldFromList(
self._app_workloads_client,
list_req,
field='workloads',
batch_size=page_size,
limit=limit,
batch_size_attribute='pageSize',
)
def Delete(self, workload, async_flag):
"""Delete a application workload in the Project/location.
Args:
workload: str, the name for the workload being deleted
async_flag: Boolean value for async operation. If true the operation will
be async
Returns:
Empty Response Message or Operation based on async flag value.
"""
delete_req = (
self.messages.ApphubProjectsLocationsApplicationsWorkloadsDeleteRequest(
name=workload
)
)
operation = self._app_workloads_client.Delete(delete_req)
if async_flag:
return operation
delete_response = api_lib_utils.WaitForOperation(
self._delete_poller,
operation,
api_lib_consts.DeleteApplicationWorkload.WAIT_FOR_DELETE_MESSAGE,
api_lib_consts.DeleteApplicationWorkload.DELETE_TIMELIMIT_SEC,
)
return delete_response
def Create(
self,
workload_id,
parent,
async_flag,
discovered_workload,
display_name,
description,
attributes,
):
"""Creates an application in the Project/location.
Args:
workload_id: str, Workload ID
parent: parent for Application resource
async_flag: Boolean value for async operation. If true the operation will
be async
discovered_workload: str, Discovered workload name
display_name: str, Human-friendly display name
description: str, Description of the Workload
attributes: Attributes, Attributes of the Workload
Returns:
Workload or Operation based on async flag value.
"""
workload = self.messages.Workload(
description=description,
displayName=display_name,
discoveredWorkload=discovered_workload,
attributes=attributes,
)
create_req = (
self.messages.ApphubProjectsLocationsApplicationsWorkloadsCreateRequest(
workload=workload, workloadId=workload_id, parent=parent
)
)
operation = self._app_workloads_client.Create(create_req)
if async_flag:
return operation
create_response = api_lib_utils.WaitForOperation(
self._poller,
operation,
api_lib_consts.CreateApplicationWorkload.WAIT_FOR_CREATE_MESSAGE,
api_lib_consts.CreateApplicationWorkload.CREATE_TIMELIMIT_SEC,
)
return create_response
def Update(self, workload_id, async_flag, attributes, args):
"""Update application workload."""
workload, update_mask = self._UpdateHelper(args, attributes)
if not update_mask:
log.status.Print(
api_lib_consts.UpdateApplicationWorkload.EMPTY_UPDATE_HELP_TEXT
)
return
update_request = (
self.messages.ApphubProjectsLocationsApplicationsWorkloadsPatchRequest(
name=workload_id,
workload=workload,
updateMask=update_mask,
)
)
operation = self._app_workloads_client.Patch(update_request)
if async_flag:
return operation
update_response = api_lib_utils.WaitForOperation(
self._poller,
operation,
api_lib_consts.UpdateApplicationWorkload.WAIT_FOR_UPDATE_MESSAGE,
api_lib_consts.UpdateApplicationWorkload.UPDATE_TIMELIMIT_SEC,
)
return update_response
def _UpdateHelper(self, args, attributes):
"""Helper to generate workload and update_mask fields for update_request."""
workload = self.messages.Workload()
update_mask = ''
if args.display_name:
update_mask = api_lib_utils.AddToUpdateMask(
update_mask,
api_lib_consts.UpdateApplicationWorkload.UPDATE_MASK_DISPLAY_NAME_FIELD_NAME,
)
workload.displayName = args.display_name
if args.description:
update_mask = api_lib_utils.AddToUpdateMask(
update_mask,
api_lib_consts.UpdateApplicationWorkload.UPDATE_MASK_DESCRIPTION_FIELD_NAME,
)
workload.description = args.description
if attributes.criticality:
update_mask = api_lib_utils.AddToUpdateMask(
update_mask,
api_lib_consts.UpdateApplicationWorkload.UPDATE_MASK_ATTR_CRITICALITY_FIELD_NAME,
)
if attributes.environment:
update_mask = api_lib_utils.AddToUpdateMask(
update_mask,
api_lib_consts.UpdateApplicationWorkload.UPDATE_MASK_ATTR_ENVIRONMENT_FIELD_NAME,
)
if attributes.businessOwners:
update_mask = api_lib_utils.AddToUpdateMask(
update_mask,
api_lib_consts.UpdateApplicationWorkload.UPDATE_MASK_ATTR_BUSINESS_OWNERS_FIELD_NAME,
)
if attributes.developerOwners:
update_mask = api_lib_utils.AddToUpdateMask(
update_mask,
api_lib_consts.UpdateApplicationWorkload.UPDATE_MASK_ATTR_DEVELOPER_OWNERS_FIELD_NAME,
)
if attributes.operatorOwners:
update_mask = api_lib_utils.AddToUpdateMask(
update_mask,
api_lib_consts.UpdateApplicationWorkload.UPDATE_MASK_ATTR_OPERATOR_OWNERS_FIELD_NAME,
)
workload.attributes = attributes
return workload, update_mask

View File

@@ -0,0 +1,75 @@
# -*- coding: utf-8 -*- #
# Copyright 2025 Google LLC. All Rights Reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
"""Apphub Boundary API."""
from googlecloudsdk.api_lib.apphub import consts as api_lib_consts
from googlecloudsdk.api_lib.apphub import utils as api_lib_utils
from googlecloudsdk.api_lib.util import waiter
from googlecloudsdk.calliope import exceptions
class BoundaryClient(object):
"""Client for boundaries in the App Hub API."""
def __init__(self, release_track):
self._client = api_lib_utils.GetClientInstance(release_track)
self._messages = api_lib_utils.GetMessagesModule(release_track)
self._service = self._client.projects_locations
self._poller = waiter.CloudOperationPoller(
self._service, self._client.projects_locations_operations
)
def Describe(self, boundary_name):
"""Gets a Boundary resource."""
request = self._messages.ApphubProjectsLocationsGetBoundaryRequest(
name=boundary_name
)
return self._service.GetBoundary(request)
def Update(self, boundary_name, args):
"""Updates a Boundary resource."""
update_mask = []
boundary = self._messages.Boundary()
if args.IsSpecified('crm_node'):
update_mask.append('crm_node')
if args.crm_node: # Check if the provided value is non-empty
boundary.crmNode = args.crm_node
if not update_mask:
raise exceptions.ToolException(
'Must specify at least one field to update.'
)
request = self._messages.ApphubProjectsLocationsUpdateBoundaryRequest(
name=boundary_name,
boundary=boundary,
updateMask=','.join(update_mask),
requestId=args.request_id,
)
operation = self._service.UpdateBoundary(request)
if args.async_:
return operation
# The WaitForOperation helper polls the LRO until it's done, which is a
# standard pattern in the App Hub gcloud implementation.
return api_lib_utils.WaitForOperation(
self._poller,
operation,
api_lib_consts.UpdateBoundary.WAIT_FOR_UPDATE_MESSAGE,
api_lib_consts.UpdateBoundary.UPDATE_TIMELIMIT_SEC,
)

View File

@@ -0,0 +1,141 @@
# -*- coding: utf-8 -*- #
# Copyright 2023 Google LLC. All Rights Reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
"""Consts for Apphub Cloud SDK."""
from __future__ import absolute_import
from __future__ import division
from __future__ import unicode_literals
class Resource:
WORKLOAD = 'workload'
SERVICE = 'service'
class AddServiceProject:
WAIT_FOR_ADD_MESSAGE = 'Adding service project'
ADD_TIMELIMIT_SEC = 60
class RemoveServiceProject:
WAIT_FOR_REMOVE_MESSAGE = 'Removing service project'
REMOVE_TIMELIMIT_SEC = 60
class CreateApplication:
WAIT_FOR_ADD_MESSAGE = 'Adding application'
ADD_TIMELIMIT_SEC = 60
class UpdateApplication:
"""Constants used by the update application command."""
WAIT_FOR_UPDATE_MESSAGE = 'Updating application'
ADD_TIMELIMIT_SEC = 60
# Constants for fields in the Application proto
UPDATE_MASK_DISPLAY_NAME_FIELD_NAME = 'displayName'
UPDATE_MASK_DESCRIPTION_FIELD_NAME = 'description'
UPDATE_MASK_CRITICALITY_FIELD_NAME = 'attributes.criticality'
UPDATE_MASK_ENVIRONMENT_FIELD_NAME = 'attributes.environment'
UPDATE_MASK_BUSINESS_OWNERS_FIELD_NAME = 'attributes.businessOwners'
UPDATE_MASK_DEVELOPER_OWNERS_FIELD_NAME = 'attributes.developerOwners'
UPDATE_MASK_OPERATOR_OWNERS_FIELD_NAME = 'attributes.operatorOwners'
class DeleteApplication:
WAIT_FOR_DELETE_MESSAGE = 'Deleting application'
REMOVE_TIMELIMIT_SEC = 60
class CreateApplicationWorkload:
WAIT_FOR_CREATE_MESSAGE = 'Adding application workload'
CREATE_TIMELIMIT_SEC = 60
class UpdateApplicationWorkload:
"""Provides const values for Update application workload."""
EMPTY_UPDATE_HELP_TEXT = 'Please specify fields to update.'
WAIT_FOR_UPDATE_MESSAGE = 'Updating application workload'
UPDATE_MASK_DISPLAY_NAME_FIELD_NAME = 'displayName'
UPDATE_MASK_DESCRIPTION_FIELD_NAME = 'description'
UPDATE_MASK_ATTRIBUTES_FIELD_NAME = 'attributes'
UPDATE_MASK_ATTR_CRITICALITY_FIELD_NAME = 'attributes.criticality'
UPDATE_MASK_ATTR_ENVIRONMENT_FIELD_NAME = 'attributes.environment'
UPDATE_MASK_ATTR_BUSINESS_OWNERS_FIELD_NAME = 'attributes.businessOwners'
UPDATE_MASK_ATTR_DEVELOPER_OWNERS_FIELD_NAME = 'attributes.developerOwners'
UPDATE_MASK_ATTR_OPERATOR_OWNERS_FIELD_NAME = 'attributes.operatorOwners'
UPDATE_TIMELIMIT_SEC = 60
class DeleteApplicationWorkload:
WAIT_FOR_DELETE_MESSAGE = 'Deleting application workload'
DELETE_TIMELIMIT_SEC = 60
class CreateApplicationService:
WAIT_FOR_CREATE_MESSAGE = 'Adding application service'
CREATE_TIMELIMIT_SEC = 60
class UpdateApplicationService:
"""Provides const values for Update application service."""
EMPTY_UPDATE_HELP_TEXT = 'Please specify fields to update.'
WAIT_FOR_UPDATE_MESSAGE = 'Updating application service'
UPDATE_MASK_DISPLAY_NAME_FIELD_NAME = 'displayName'
UPDATE_MASK_DESCRIPTION_FIELD_NAME = 'description'
UPDATE_MASK_ATTRIBUTES_FIELD_NAME = 'attributes'
UPDATE_MASK_ATTR_CRITICALITY_FIELD_NAME = 'attributes.criticality'
UPDATE_MASK_ATTR_ENVIRONMENT_FIELD_NAME = 'attributes.environment'
UPDATE_MASK_ATTR_BUSINESS_OWNERS_FIELD_NAME = 'attributes.businessOwners'
UPDATE_MASK_ATTR_DEVELOPER_OWNERS_FIELD_NAME = 'attributes.developerOwners'
UPDATE_MASK_ATTR_OPERATOR_OWNERS_FIELD_NAME = 'attributes.operatorOwners'
UPDATE_TIMELIMIT_SEC = 60
class DeleteApplicationService:
WAIT_FOR_DELETE_MESSAGE = 'Deleting application service'
DELETE_TIMELIMIT_SEC = 60
class UpdateBoundary:
"""Constants used by the update boundary command."""
WAIT_FOR_UPDATE_MESSAGE = 'Updating boundary'
UPDATE_TIMELIMIT_SEC = 60

View File

@@ -0,0 +1,134 @@
# -*- coding: utf-8 -*- #
# Copyright 2024 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.
"""Apphub Discovered Services API."""
from __future__ import absolute_import
from __future__ import division
from __future__ import unicode_literals
from apitools.base.py import list_pager
from googlecloudsdk.api_lib.apphub import utils as api_lib_utils
from googlecloudsdk.calliope import base
class DiscoveredServicesClient(object):
"""Client for services in apphub API."""
def __init__(self, release_track=base.ReleaseTrack.ALPHA):
self.client = api_lib_utils.GetClientInstance(release_track)
self.messages = api_lib_utils.GetMessagesModule(release_track)
self._dis_services_client = (
self.client.projects_locations_discoveredServices
)
def Describe(self, discovered_service):
"""Describe a Discovered Service in the Project/location.
Args:
discovered_service: str, the name for the discovered service being
described.
Returns:
Described discovered service Resource.
"""
describe_req = (
self.messages.ApphubProjectsLocationsDiscoveredServicesGetRequest(
name=discovered_service
)
)
return self._dis_services_client.Get(describe_req)
def List(
self,
parent,
limit=None,
page_size=100,
):
"""List discovered services that could be added to an application.
Args:
parent: str, projects/{projectId}/locations/{location}
limit: int or None, the total number of results to return. Default value
is None
page_size: int, the number of entries in each batch (affects requests
made, but not the yielded results). Default value is 100.
Returns:
Generator of matching discovered services.
"""
list_req = (
self.messages.ApphubProjectsLocationsDiscoveredServicesListRequest(
parent=parent
)
)
return list_pager.YieldFromList(
self._dis_services_client,
list_req,
field='discoveredServices',
batch_size=page_size,
limit=limit,
batch_size_attribute='pageSize',
)
def FindUnregistered(
self,
parent,
limit=None,
page_size=100,
):
"""List unregistered discovered services in the Projects/Location.
Args:
parent: str, projects/{projectId}/locations/{location}
limit: int or None, the total number of results to return. Default value
is None
page_size: int, the number of entries in each batch (affects requests
made, but not the yielded results). Default value is 100.
Returns:
Generator of matching discovered services.
"""
find_unregistered_req = self.messages.ApphubProjectsLocationsDiscoveredServicesFindUnregisteredRequest(
parent=parent
)
return list_pager.YieldFromList(
self._dis_services_client,
find_unregistered_req,
method='FindUnregistered',
field='discoveredServices',
batch_size=page_size,
limit=limit,
batch_size_attribute='pageSize',
)
def Lookup(self, parent, uri):
"""Lookup a discovered service in the Project/location with a given uri.
Args:
parent: str, projects/{projectId_or_projectNumber}/locations/{location}
uri: str, GCP resource URI to find service for Accepts both project number
and project id and does translation when needed.
Returns:
discoveredService: Discovered service
"""
lookup_req = (
self.messages.ApphubProjectsLocationsDiscoveredServicesLookupRequest(
parent=parent,
uri=uri,
)
)
return self._dis_services_client.Lookup(lookup_req)

View File

@@ -0,0 +1,134 @@
# -*- coding: utf-8 -*- #
# Copyright 2024 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.
"""Apphub Discovered Workloads API."""
from __future__ import absolute_import
from __future__ import division
from __future__ import unicode_literals
from apitools.base.py import list_pager
from googlecloudsdk.api_lib.apphub import utils as api_lib_utils
from googlecloudsdk.calliope import base
class DiscoveredWorkloadsClient(object):
"""Client for workloads in apphub API."""
def __init__(self, release_track=base.ReleaseTrack.ALPHA):
self.client = api_lib_utils.GetClientInstance(release_track)
self.messages = api_lib_utils.GetMessagesModule(release_track)
self._dis_workloads_client = (
self.client.projects_locations_discoveredWorkloads
)
def Describe(self, discovered_workload):
"""Describe a Discovered Workload in the Project/location.
Args:
discovered_workload: str, the name for the discovered workload being
described.
Returns:
Described discovered workload Resource.
"""
describe_req = (
self.messages.ApphubProjectsLocationsDiscoveredWorkloadsGetRequest(
name=discovered_workload
)
)
return self._dis_workloads_client.Get(describe_req)
def List(
self,
parent,
limit=None,
page_size=100,
):
"""List discovered workloads that could be added to an application.
Args:
parent: str, projects/{projectId}/locations/{location}
limit: int or None, the total number of results to return. Default value
is None
page_size: int, the number of entries in each batch (affects requests
made, but not the yielded results). Default value is 100.
Returns:
Generator of matching discovered workloads.
"""
list_req = (
self.messages.ApphubProjectsLocationsDiscoveredWorkloadsListRequest(
parent=parent
)
)
return list_pager.YieldFromList(
self._dis_workloads_client,
list_req,
field='discoveredWorkloads',
batch_size=page_size,
limit=limit,
batch_size_attribute='pageSize',
)
def FindUnregistered(
self,
parent,
limit=None,
page_size=100,
):
"""List unregistered discovered workloads in the Projects/Location.
Args:
parent: str, projects/{projectId}/locations/{location}
limit: int or None, the total number of results to return. Default value
is None
page_size: int, the number of entries in each batch (affects requests
made, but not the yielded results). Default value is 100.
Returns:
Generator of matching discovered workloads.
"""
find_unregistered_req = self.messages.ApphubProjectsLocationsDiscoveredWorkloadsFindUnregisteredRequest(
parent=parent
)
return list_pager.YieldFromList(
self._dis_workloads_client,
find_unregistered_req,
method='FindUnregistered',
field='discoveredWorkloads',
batch_size=page_size,
limit=limit,
batch_size_attribute='pageSize',
)
def Lookup(self, parent, uri):
"""Lookup a discovered workload in the Project/location with a given uri.
Args:
parent: str, projects/{projectId_or_projectNumber}/locations/{location}
uri: str, GCP resource URI to find workload for Accepts both project
number and project id and does translation when needed.
Returns:
discoveredWorkload: Discovered workload
"""
lookup_req = (
self.messages.ApphubProjectsLocationsDiscoveredWorkloadsLookupRequest(
parent=parent,
uri=uri,
)
)
return self._dis_workloads_client.Lookup(lookup_req)

View File

@@ -0,0 +1,75 @@
# -*- coding: utf-8 -*- #
# Copyright 2025 Google LLC. All Rights Reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
"""Apphub Extended Metadata Schemas API."""
from __future__ import absolute_import
from __future__ import division
from __future__ import unicode_literals
from apitools.base.py import list_pager
from googlecloudsdk.api_lib.apphub import utils as api_lib_utils
from googlecloudsdk.calliope import base
class ExtendedMetadataSchemasClient(object):
"""Client for extended metadata schemas in apphub API."""
def __init__(self, release_track=base.ReleaseTrack.ALPHA):
self.client = api_lib_utils.GetClientInstance(release_track)
self.messages = api_lib_utils.GetMessagesModule(release_track)
self._schemas_client = (
self.client.projects_locations_extendedMetadataSchemas
)
def Describe(self, schema_ref):
"""Describe an Extended Metadata Schema.
Args:
schema_ref: The resource reference to the schema to describe.
Returns:
The described schema resource.
"""
describe_req = (
self.messages.ApphubProjectsLocationsExtendedMetadataSchemasGetRequest(
name=schema_ref.RelativeName()
)
)
return self._schemas_client.Get(describe_req)
def List(self, parent, limit=None, page_size=100):
"""List extended metadata schemas.
Args:
parent: The resource reference to the parent location to list for.
limit: int, The maximum number of records to yield.
page_size: int, The number of records to fetch in each request.
Returns:
A generator of the schemas.
"""
list_req = (
self.messages.ApphubProjectsLocationsExtendedMetadataSchemasListRequest(
parent=parent
)
)
return list_pager.YieldFromList(
self._schemas_client,
list_req,
field='extendedMetadataSchemas',
batch_size=page_size,
limit=limit,
batch_size_attribute='pageSize',
)

View File

@@ -0,0 +1,70 @@
# -*- coding: utf-8 -*- #
# Copyright 2024 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.
"""Apphub Operations API."""
from __future__ import absolute_import
from __future__ import division
from __future__ import unicode_literals
from apitools.base.py import list_pager
from googlecloudsdk.api_lib.apphub import utils as api_lib_utils
from googlecloudsdk.calliope import base
class LocationsClient(object):
"""Client for locations in AppHub API."""
def __init__(self, release_track=base.ReleaseTrack.ALPHA):
self.client = api_lib_utils.GetClientInstance(release_track)
self.messages = api_lib_utils.GetMessagesModule(release_track)
self._lo_client = self.client.projects_locations
def List(self, parent, limit=None, page_size=100):
"""List all AppHub locations in the Project.
Args:
parent: str, projects/{projectId}
limit: int or None, the total number of results to return.
Default value is None
page_size: int, the number of entries in each batch (affects requests
made, but not the yielded results). Default value is 100.
Returns:
A list of AppHub locations that belong to the given parent.
"""
list_req = self.messages.ApphubProjectsLocationsListRequest(
name=parent)
return list_pager.YieldFromList(
self._lo_client,
list_req,
field='locations',
batch_size=page_size,
limit=limit,
batch_size_attribute='pageSize',
)
def Describe(self, location):
"""Describe an AppHub location.
Args:
location: str, the name for the AppHub Location being described.
Returns:
Described AppHub location resource.
"""
describe_req = self.messages.ApphubProjectsLocationsGetRequest(
name=location)
return self._lo_client.Get(describe_req)

View File

@@ -0,0 +1,70 @@
# -*- coding: utf-8 -*- #
# Copyright 2023 Google LLC. All Rights Reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
"""Apphub Operations API."""
from __future__ import absolute_import
from __future__ import division
from __future__ import unicode_literals
from apitools.base.py import list_pager
from googlecloudsdk.api_lib.apphub import utils as api_lib_utils
from googlecloudsdk.calliope import base
class OperationsClient(object):
"""Client for operations in AppHub API."""
def __init__(self, release_track=base.ReleaseTrack.ALPHA):
self.client = api_lib_utils.GetClientInstance(release_track)
self.messages = api_lib_utils.GetMessagesModule(release_track)
self._op_client = self.client.projects_locations_operations
def List(self, parent, limit=None, page_size=100):
"""List all AppHub operations in the Project/location.
Args:
parent: str, projects/{projectId}/locations/{location}
limit: int or None, the total number of results to return.
Default value is None
page_size: int, the number of entries in each batch (affects requests
made, but not the yielded results). Default value is 100.
Returns:
A list of AppHub operations that belong to the given parent.
"""
list_req = self.messages.ApphubProjectsLocationsOperationsListRequest(
name=parent)
return list_pager.YieldFromList(
self._op_client,
list_req,
field='operations',
batch_size=page_size,
limit=limit,
batch_size_attribute='pageSize',
)
def Describe(self, operation):
"""Describe an AppHub operation.
Args:
operation: str, the name for the AppHub Operation being described.
Returns:
Described AppHub operation resource.
"""
describe_req = self.messages.ApphubProjectsLocationsOperationsGetRequest(
name=operation)
return self._op_client.Get(describe_req)

View File

@@ -0,0 +1,190 @@
# -*- coding: utf-8 -*- #
# Copyright 2023 Google LLC. All Rights Reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
"""Apphub Service Projects API."""
from __future__ import absolute_import
from __future__ import division
from __future__ import unicode_literals
from apitools.base.py import list_pager
from googlecloudsdk.api_lib.apphub import consts as api_lib_consts
from googlecloudsdk.api_lib.apphub import utils as api_lib_utils
from googlecloudsdk.api_lib.util import waiter
from googlecloudsdk.calliope import base
class ServiceProjectsClient(object):
"""Client for service projects in apphub API."""
def __init__(self, release_track=base.ReleaseTrack.ALPHA):
self.client = api_lib_utils.GetClientInstance(release_track)
self.messages = api_lib_utils.GetMessagesModule(release_track)
self._sp_client = self.client.projects_locations_serviceProjectAttachments
self._project_locations_client = self.client.projects_locations
self._poller = waiter.CloudOperationPoller(
self._sp_client,
self.client.projects_locations_operations,
)
self._remove_poller = waiter.CloudOperationPollerNoResources(
self.client.projects_locations_operations,
)
def Describe(self, service_project):
"""Describe a service project in the Project/location.
Args:
service_project: str, the name for the service project being described.
Returns:
Described service project Resource.
"""
describe_req = self.messages.ApphubProjectsLocationsServiceProjectAttachmentsGetRequest(
name=service_project
)
return self._sp_client.Get(describe_req)
def List(
self,
parent,
limit=None,
page_size=100,
):
"""List service projects in the Projects/Location.
Args:
parent: str, projects/{projectId}/locations/{location}
limit: int or None, the total number of results to return.
Default value is None
page_size: int, the number of entries in each batch (affects requests
made, but not the yielded results). Default value is 100.
Returns:
Generator of matching service projects.
"""
list_req = (
self.messages.ApphubProjectsLocationsServiceProjectAttachmentsListRequest(
parent=parent
)
)
return list_pager.YieldFromList(
self._sp_client,
list_req,
field='serviceProjectAttachments',
batch_size=page_size,
limit=limit,
batch_size_attribute='pageSize',
)
def Add(
self,
service_project,
async_flag,
parent
):
"""Add a service project in the Project/location.
Args:
service_project: str, the name for the service project being created
async_flag: Boolean value for async operation. If true the operation will
be async
parent: parent for service project resource
Returns:
Service Project or Operation based on async flag value.
"""
service_project_attachment = self.messages.ServiceProjectAttachment(
serviceProject='projects/' + service_project
)
create_req = self.messages.ApphubProjectsLocationsServiceProjectAttachmentsCreateRequest(
parent=parent,
serviceProjectAttachment=service_project_attachment,
serviceProjectAttachmentId=service_project,
)
operation = self._sp_client.Create(create_req)
if async_flag:
return operation
create_response = api_lib_utils.WaitForOperation(
self._poller,
operation,
api_lib_consts.AddServiceProject.WAIT_FOR_ADD_MESSAGE,
api_lib_consts.AddServiceProject.ADD_TIMELIMIT_SEC,
)
return create_response
def Remove(self, service_project, async_flag):
"""Remove a service project in the Project/location.
Args:
service_project: str, the name for the service project being deleted
async_flag: Boolean value for async operation. If true the operation will
be async
Returns:
Empty Response Message or Operation based on async flag value.
"""
remove_req = self.messages.ApphubProjectsLocationsServiceProjectAttachmentsDeleteRequest(
name=service_project
)
operation = self._sp_client.Delete(remove_req)
if async_flag:
return operation
remove_response = api_lib_utils.WaitForOperation(
self._remove_poller,
operation,
api_lib_consts.RemoveServiceProject.WAIT_FOR_REMOVE_MESSAGE,
api_lib_consts.RemoveServiceProject.REMOVE_TIMELIMIT_SEC,
)
return remove_response
def Lookup(self, service_project):
"""Lookup a service project in the Project/location.
Args:
service_project: Service project id
Returns:
Service Project.
"""
lookup_req = self.messages.ApphubProjectsLocationsLookupServiceProjectAttachmentRequest(
name='projects/' + service_project + '/locations/global'
)
return self._project_locations_client.LookupServiceProjectAttachment(
lookup_req
)
def Detach(self, service_project):
"""Detach a service project in the Project/location.
Args:
service_project: Service project id
Returns:
None
"""
detach_req = self.messages.ApphubProjectsLocationsDetachServiceProjectAttachmentRequest(
name='projects/' + service_project + '/locations/global'
)
return self._project_locations_client.DetachServiceProjectAttachment(
detach_req
)

View File

@@ -0,0 +1,226 @@
# -*- coding: utf-8 -*- #
# Copyright 2023 Google LLC. All Rights Reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
"""Util for Apphub Cloud SDK."""
from __future__ import absolute_import
from __future__ import division
from __future__ import unicode_literals
from googlecloudsdk.api_lib.util import apis
from googlecloudsdk.api_lib.util import waiter
from googlecloudsdk.calliope import base
from googlecloudsdk.calliope import exceptions
from googlecloudsdk.core import properties
from googlecloudsdk.core import resources
VERSION_MAP = {
base.ReleaseTrack.ALPHA: 'v1alpha',
base.ReleaseTrack.GA: 'v1',
}
# The messages module can also be accessed from client.MESSAGES_MODULE
def GetMessagesModule(release_track=base.ReleaseTrack.ALPHA):
api_version = VERSION_MAP.get(release_track)
return apis.GetMessagesModule('apphub', api_version)
def GetClientInstance(release_track=base.ReleaseTrack.ALPHA):
api_version = VERSION_MAP.get(release_track)
return apis.GetClientInstance('apphub', api_version)
def AddToUpdateMask(update_mask, field_name):
if update_mask:
update_mask += ','
return update_mask + field_name
def GetOperationResource(operation, release_track=base.ReleaseTrack.ALPHA):
"""Converts an Operation to a Resource that can be used with `waiter.WaitFor`."""
api_version = VERSION_MAP.get(release_track)
return resources.Registry().ParseRelativeName(
operation.name,
'apphub.projects.locations.operations',
api_version=api_version,
)
def WaitForOperation(poller, operation, message, max_wait_sec):
return waiter.WaitFor(
poller,
GetOperationResource(operation),
message,
max_wait_ms=max_wait_sec * 1000,
)
def PopulateAttributes(args, release_track=base.ReleaseTrack.ALPHA):
"""Populate attirbutes from args."""
attributes = GetMessagesModule(release_track).Attributes()
if args.environment_type:
attributes.environment = GetMessagesModule(release_track).Environment(
type=GetMessagesModule(release_track).Environment.TypeValueValuesEnum(
args.environment_type
)
)
if args.criticality_type:
attributes.criticality = GetMessagesModule(release_track).Criticality(
type=GetMessagesModule(release_track).Criticality.TypeValueValuesEnum(
args.criticality_type
)
)
for b_owner in args.business_owners or []:
business_owner = GetMessagesModule(release_track).ContactInfo()
business_owner.email = b_owner.get('email', None)
if b_owner.get('display-name', None):
business_owner.displayName = b_owner.get('display-name', None)
if release_track == base.ReleaseTrack.ALPHA:
if b_owner.get('channel-uri', None):
business_owner.channel = GetMessagesModule(release_track).Channel(
uri=b_owner.get('channel-uri')
)
attributes.businessOwners.append(business_owner)
for d_owner in args.developer_owners or []:
developer_owner = GetMessagesModule(release_track).ContactInfo()
developer_owner.email = d_owner.get('email', None)
if d_owner.get('display-name', None):
developer_owner.displayName = d_owner.get('display-name', None)
if release_track == base.ReleaseTrack.ALPHA:
if d_owner.get('channel-uri', None):
developer_owner.channel = GetMessagesModule(release_track).Channel(
uri=d_owner.get('channel-uri')
)
attributes.developerOwners.append(developer_owner)
for o_owner in args.operator_owners or []:
operator_owner = GetMessagesModule(release_track).ContactInfo()
operator_owner.email = o_owner.get('email', None)
if o_owner.get('display-name'):
operator_owner.displayName = o_owner.get('display-name')
if release_track == base.ReleaseTrack.ALPHA:
if o_owner.get('channel-uri'):
operator_owner.channel = GetMessagesModule(release_track).Channel(
uri=o_owner.get('channel-uri')
)
attributes.operatorOwners.append(operator_owner)
return attributes
def MakeGetUriFunc(collection, release_track=base.ReleaseTrack.ALPHA):
"""Returns a function which turns a resource into a uri."""
def _GetUri(resource):
api_version = VERSION_MAP.get(release_track)
result = resources.Registry().ParseRelativeName(
resource.name, collection=collection, api_version=api_version
)
return result.SelfLink()
return _GetUri
def GetServiceProjectRef(args):
"""Returns a service project reference."""
service_project_ref = args.CONCEPTS.service_project.Parse()
if not service_project_ref.Name():
raise exceptions.InvalidArgumentException(
'service project', 'service project id must be non-empty.'
)
return service_project_ref
def GetOperationRef(args):
"""Returns a operation reference."""
operation_ref = args.CONCEPTS.operation.Parse()
if not operation_ref.Name():
raise exceptions.InvalidArgumentException(
'operation', 'operation id must be non-empty.'
)
return operation_ref
def GetLocationRef(args):
"""Returns a location reference."""
location_ref = args.CONCEPTS.location.Parse()
if not location_ref.Name():
raise exceptions.InvalidArgumentException(
'location', 'location id must be non-empty.'
)
return location_ref
def GetDiscoveredWorkloadRef(args):
"""Returns a discovered workload reference."""
discovered_workload_ref = args.CONCEPTS.discovered_workload.Parse()
if not discovered_workload_ref.Name():
raise exceptions.InvalidArgumentException(
'discovered workload', 'discovered workload id must be non-empty.'
)
return discovered_workload_ref
def GetDiscoveredServiceRef(args):
"""Returns a discovered service reference."""
discovered_service_ref = args.CONCEPTS.discovered_service.Parse()
if not discovered_service_ref.Name():
raise exceptions.InvalidArgumentException(
'discovered service', 'discovered service id must be non-empty.'
)
return discovered_service_ref
def GetApplicationRef(args):
"""Returns a application reference."""
app_ref = args.CONCEPTS.application.Parse()
if not app_ref.Name():
raise exceptions.InvalidArgumentException(
'application', 'application id must be non-empty.'
)
return app_ref
def GetApplicationWorkloadRef(args):
"""Returns a application workload reference."""
workload_ref = args.CONCEPTS.workload.Parse()
if not workload_ref.Name():
raise exceptions.InvalidArgumentException(
'workload', 'workload id must be non-empty.'
)
return workload_ref
def GetApplicationServiceRef(args):
"""Returns a application service reference."""
service_ref = args.CONCEPTS.service.Parse()
if not service_ref.Name():
raise exceptions.InvalidArgumentException(
'service', 'service id must be non-empty.'
)
return service_ref
def GetProjectRef():
"""Returns a project reference."""
return resources.REGISTRY.Parse(
properties.VALUES.core.project.GetOrFail(),
collection='apphub.projects',
)