1# -*- coding: utf-8 -*- #
2# Copyright 2016 Google LLC. All Rights Reserved.
3#
4# Licensed under the Apache License, Version 2.0 (the "License");
5# you may not use this file except in compliance with the License.
6# You may obtain a copy of the License at
7#
8#    http://www.apache.org/licenses/LICENSE-2.0
9#
10# Unless required by applicable law or agreed to in writing, software
11# distributed under the License is distributed on an "AS IS" BASIS,
12# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13# See the License for the specific language governing permissions and
14# limitations under the License.
15
16
17"""CloudBuild resource transforms and symbols dict.
18
19A resource transform function converts a JSON-serializable resource to a string
20value. This module contains built-in transform functions that may be used in
21resource projection and filter expressions.
22
23NOTICE: Each TransformFoo() method is the implementation of a foo() transform
24function. Even though the implementation here is in Python the usage in resource
25projection and filter expressions is language agnostic. This affects the
26Pythonicness of the Transform*() methods:
27  (1) The docstrings are used to generate external user documentation.
28  (2) The method prototypes are included in the documentation. In particular the
29      prototype formal parameter names are stylized for the documentation.
30  (3) The 'r', 'kwargs', and 'projection' args are not included in the external
31      documentation. Docstring descriptions, other than the Args: line for the
32      arg itself, should not mention these args. Assume the reader knows the
33      specific item the transform is being applied to. When in doubt refer to
34      the output of $ gcloud topic projections.
35  (4) The types of some args, like r, are not fixed until runtime. Other args
36      may have either a base type value or string representation of that type.
37      It is up to the transform implementation to silently do the string=>type
38      conversions. That's why you may see e.g. int(arg) in some of the methods.
39  (5) Unless it is documented to do so, a transform function must not raise any
40      exceptions related to the resource r. The `undefined' arg is used to
41      handle all unusual conditions, including ones that would raise exceptions.
42      Exceptions for arguments explicitly under the caller's control are OK.
43"""
44
45from __future__ import absolute_import
46from __future__ import division
47from __future__ import unicode_literals
48
49from apitools.base.py import encoding as apitools_encoding
50from googlecloudsdk.api_lib.util import apis as core_apis
51from googlecloudsdk.core import resources
52
53
54def TransformBuildImages(r, undefined=''):
55  """Returns the formatted build results images.
56
57  Args:
58    r: JSON-serializable object.
59    undefined: Returns this value if the resource cannot be formatted.
60  Returns:
61    The formatted build results images.
62  """
63  messages = core_apis.GetMessagesModule('cloudbuild', 'v1')
64  b = apitools_encoding.DictToMessage(r, messages.Build)
65  if b.results is None:
66    return undefined
67  images = b.results.images
68  if not images:
69    return undefined
70  names = []
71  for i in images:
72    if i.name is None:
73      names.append(undefined)
74    else:
75      names.append(i.name)
76  if len(names) > 1:
77    return names[0] + ' (+{0} more)'.format(len(names)-1)
78  return names[0]
79
80
81def TransformBuildSource(r, undefined=''):
82  """Returns the formatted build source.
83
84  Args:
85    r: JSON-serializable object.
86    undefined: Returns this value if the resource cannot be formatted.
87  Returns:
88    The formatted build source.
89  """
90  messages = core_apis.GetMessagesModule('cloudbuild', 'v1')
91  b = apitools_encoding.DictToMessage(r, messages.Build)
92  if b.source is None:
93    return undefined
94  storage_source = b.source.storageSource
95  repo_source = b.source.repoSource
96  if storage_source is not None:
97    bucket = storage_source.bucket
98    obj = storage_source.object
99    if bucket is None or obj is None:
100      return undefined
101    return 'gs://{0}/{1}'.format(bucket, obj)
102  if repo_source is not None:
103    repo_name = repo_source.repoName or 'default'
104    branch_name = repo_source.branchName
105    if branch_name is not None:
106      return '{0}@{1}'.format(repo_name, branch_name)
107    tag_name = repo_source.tagName
108    if tag_name is not None:
109      return '{0}@{1}'.format(repo_name, tag_name)
110    commit_sha = repo_source.commitSha
111    if commit_sha is not None:
112      return '{0}@{1}'.format(repo_name, commit_sha)
113  return undefined
114
115
116def _GetUri(resource, undefined=None):
117  build_ref = resources.REGISTRY.Parse(
118      None,
119      params={
120          'projectId': resource.projectId,
121          'id': resource.id,
122      },
123      collection='cloudbuild.projects.builds')
124  return build_ref.SelfLink() or undefined
125
126
127_TRANSFORMS = {
128    'build_images': TransformBuildImages,
129    'build_source': TransformBuildSource,
130    'uri': _GetUri,
131}
132
133
134def GetTransforms():
135  """Returns the cloudbuild specific resource transform symbol table."""
136  return _TRANSFORMS
137