File: //snap/google-cloud-cli/394/lib/googlecloudsdk/command_lib/source/util.py
# -*- coding: utf-8 -*- #
# Copyright 2018 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.
"""General utilties for Cloud Source commands."""
from __future__ import absolute_import
from __future__ import division
from __future__ import unicode_literals
from googlecloudsdk.api_lib.util import apis
from googlecloudsdk.core import exceptions
from googlecloudsdk.core import properties
from googlecloudsdk.core import resources
_API_NAME = 'sourcerepo'
_API_VERSION = 'v1'
_MESSAGES = apis.GetMessagesModule(_API_NAME, _API_VERSION)
class InvalidTopicError(exceptions.Error):
"""Raised when a topic cannot be found within the repo."""
def CreateProjectResource(args):
return resources.REGISTRY.Create(
'sourcerepo.projects',
projectsId=args.project or properties.VALUES.core.project.GetOrFail())
def CreateTopicResource(topic_name, topic_project):
return resources.REGISTRY.Create(
'pubsub.projects.topics',
projectsId=topic_project,
topicsId=topic_name,
)
def ParseProjectConfigWithPushblock(args):
project_ref = CreateProjectResource(args)
project_name = project_ref.RelativeName()
enable_pushblock = args.enable_pushblock
return _MESSAGES.ProjectConfig(
enablePrivateKeyCheck=enable_pushblock,
name=project_name,
pubsubConfigs=None # No need to specify when only update key check.
)
def ParseSourceRepoWithModifiedTopic(args, repo):
"""Parse and create a new Repo message with modified topic."""
topic_name = GetTopicName(args)
if args.add_topic:
new_config = _ParsePubsubConfig(topic_name, args.message_format,
args.service_account)
return _AddTopicToResource(
topic_name, new_config, repo, resource_name='repo')
elif args.remove_topic:
return _RemoveTopicFromResource(topic_name, repo, resource_name='repo')
elif args.update_topic:
return _UpdateTopicInResource(topic_name, args, repo, resource_name='repo')
return repo
def ParseProjectConfigWithModifiedTopic(args, project_config):
"""Parse and create a new ProjectConfig message with modified topic."""
topic_name = GetTopicName(args)
if args.add_topic:
new_config = _ParsePubsubConfig(topic_name, args.message_format,
args.service_account)
return _AddTopicToResource(
topic_name, new_config, project_config, resource_name='project')
elif args.remove_topic:
return _RemoveTopicFromResource(
topic_name, project_config, resource_name='project')
elif args.update_topic:
return _UpdateTopicInResource(
topic_name, args, project_config, resource_name='project')
return project_config
def GetTopicName(args):
"""Get the topic name based on project and topic_project flags."""
if args.add_topic:
topic_ref = args.CONCEPTS.add_topic.Parse()
elif args.remove_topic:
topic_ref = args.CONCEPTS.remove_topic.Parse()
else:
topic_ref = args.CONCEPTS.update_topic.Parse()
return topic_ref.RelativeName()
def _AddTopicToResource(topic_name, new_config, resource, resource_name):
"""Add the PubsubConfig message to Repo/ProjectConfig message."""
if resource.pubsubConfigs is None:
config_additional_properties = []
else:
config_additional_properties = resource.pubsubConfigs.additionalProperties
resource_msg_module = _MESSAGES.ProjectConfig
if resource_name == 'repo':
resource_msg_module = _MESSAGES.Repo
config_additional_properties.append(
resource_msg_module.PubsubConfigsValue.AdditionalProperty(
key=topic_name, value=new_config))
return resource_msg_module(
name=resource.name,
pubsubConfigs=resource_msg_module.PubsubConfigsValue(
additionalProperties=config_additional_properties))
def _RemoveTopicFromResource(topic_name, resource, resource_name):
"""Remove the topic from the Repo/ProjectConfig message."""
if resource.pubsubConfigs is None:
raise InvalidTopicError('Invalid topic [{0}]: No topics are configured '
'in the {1}.'.format(topic_name, resource_name))
config_additional_properties = resource.pubsubConfigs.additionalProperties
for i, config in enumerate(config_additional_properties):
if config.key == topic_name:
del config_additional_properties[i]
break
else:
raise InvalidTopicError('Invalid topic [{0}]: You must specify a '
'topic that is already configured in the {1}.'
.format(topic_name, resource_name))
resource_msg_module = _MESSAGES.ProjectConfig
if resource_name == 'repo':
resource_msg_module = _MESSAGES.Repo
return resource_msg_module(
name=resource.name,
pubsubConfigs=resource_msg_module.PubsubConfigsValue(
additionalProperties=config_additional_properties))
def _UpdateTopicInResource(topic_name, args, resource, resource_name):
"""Update the topic in the configuration and return a new repo message."""
if resource.pubsubConfigs is None:
raise InvalidTopicError('Invalid topic [{0}]: No topics are configured '
'in the {1}.'.format(topic_name, resource_name))
config_additional_properties = resource.pubsubConfigs.additionalProperties
for i, config in enumerate(config_additional_properties):
if config.key == topic_name:
config_additional_properties[i].value = _UpdateConfigWithArgs(
config.value, args)
break
else:
raise InvalidTopicError('Invalid topic [{0}]: You must specify a '
'topic that is already configured in the {1}.'
.format(topic_name, resource_name))
resource_msg_module = _MESSAGES.ProjectConfig
if resource_name == 'repo':
resource_msg_module = _MESSAGES.Repo
return resource_msg_module(
name=resource.name,
pubsubConfigs=resource_msg_module.PubsubConfigsValue(
additionalProperties=config_additional_properties))
def _ParsePubsubConfig(topic_name, message_format=None, service_account=None):
"""Parse and create PubsubConfig message."""
message_format_enums = _MESSAGES.PubsubConfig.MessageFormatValueValuesEnum
if message_format == 'protobuf':
parsed_message_format = message_format_enums.PROTOBUF
else:
# By default, the message format is 'json'.
parsed_message_format = message_format_enums.JSON
return _MESSAGES.PubsubConfig(
messageFormat=parsed_message_format,
serviceAccountEmail=service_account,
topic=topic_name)
def _GetMessageFormatString(pubsub_config):
message_format_type = getattr(pubsub_config, 'messageFormat')
message_format_enums = _MESSAGES.PubsubConfig.MessageFormatValueValuesEnum
if message_format_type == message_format_enums.PROTOBUF:
return 'protobuf'
return 'json'
def _UpdateConfigWithArgs(pubsub_config, args):
message_format = args.message_format or _GetMessageFormatString(pubsub_config)
service_account = args.service_account or getattr(pubsub_config,
'serviceAccountEmail')
topic_name = pubsub_config.topic
return _ParsePubsubConfig(topic_name, message_format, service_account)