File: //proc/thread-self/root/snap/google-cloud-cli/current/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)