1# -*- coding: utf-8 -*- # 2# Copyright 2020 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"""Service-specific printer.""" 17 18from __future__ import absolute_import 19from __future__ import division 20from __future__ import print_function 21from __future__ import unicode_literals 22 23import collections 24 25from googlecloudsdk.api_lib.run import container_resource 26from googlecloudsdk.api_lib.run import revision 27from googlecloudsdk.command_lib.run import k8s_object_printer 28from googlecloudsdk.core.resource import custom_printer_base as cp 29import six 30 31 32REVISION_PRINTER_FORMAT = 'revision' 33 34 35def FormatSecretKeyRef(v): 36 return '{}:{}'.format(v.secretKeyRef.name, v.secretKeyRef.key) 37 38 39def FormatSecretVolumeSource(v): 40 if v.items: 41 return '{}:{}'.format(v.secretName, v.items[0].key) 42 else: 43 return v.secretName 44 45 46def FormatConfigMapKeyRef(v): 47 return '{}:{}'.format(v.configMapKeyRef.name, v.configMapKeyRef.key) 48 49 50def FormatConfigMapVolumeSource(v): 51 if v.items: 52 return '{}:{}'.format(v.name, v.items[0].key) 53 else: 54 return v.name 55 56 57class RevisionPrinter(k8s_object_printer.K8sObjectPrinter): 58 """Prints the run Revision in a custom human-readable format. 59 60 Format specific to Cloud Run revisions. Only available on Cloud Run commands 61 that print revisions. 62 """ 63 64 def Transform(self, record): 65 """Transform a service into the output structure of marker classes.""" 66 fmt = cp.Lines([ 67 self._GetHeader(record), 68 self._GetLabels(record.labels), 69 ' ', 70 self.TransformSpec(record), 71 self._GetReadyMessage(record)]) 72 return fmt 73 74 @staticmethod 75 def GetLimits(rev): 76 return collections.defaultdict(str, rev.resource_limits) 77 78 @staticmethod 79 def GetUserEnvironmentVariables(record): 80 return cp.Mapped( 81 k8s_object_printer.OrderByKey( 82 record.env_vars.literals)) 83 84 @staticmethod 85 def GetSecrets(record): 86 secrets = {} 87 secrets.update({ 88 k: FormatSecretKeyRef(v) 89 for k, v in record.env_vars.secrets.items() 90 }) 91 secrets.update({ 92 k: FormatSecretVolumeSource(v) 93 for k, v in record.MountedVolumeJoin('secrets').items() 94 }) 95 return cp.Mapped(k8s_object_printer.OrderByKey(secrets)) 96 97 @staticmethod 98 def GetConfigMaps(record): 99 config_maps = {} 100 config_maps.update({ 101 k: FormatConfigMapKeyRef(v) 102 for k, v in record.env_vars.config_maps.items() 103 }) 104 config_maps.update({ 105 k: FormatConfigMapVolumeSource(v) 106 for k, v in record.MountedVolumeJoin('config_maps').items() 107 }) 108 return cp.Mapped(k8s_object_printer.OrderByKey(config_maps)) 109 110 @staticmethod 111 def GetCloudSqlInstances(record): 112 instances = record.annotations.get(container_resource.CLOUDSQL_ANNOTATION, 113 '') 114 return instances.replace(',', ', ') 115 116 @staticmethod 117 def GetTimeout(record): 118 if record.timeout is not None: 119 return '{}s'.format(record.timeout) 120 return None 121 122 @staticmethod 123 def GetVpcConnector(record): 124 return cp.Labeled([ 125 ('Name', 126 record.annotations.get(container_resource.VPC_ACCESS_ANNOTATION, '')), 127 ('Egress', 128 record.annotations.get(container_resource.EGRESS_SETTINGS_ANNOTATION, 129 '')) 130 ]) 131 132 @staticmethod 133 def GetMinInstances(record): 134 return record.annotations.get(revision.MIN_SCALE_ANNOTATION, '') 135 136 @staticmethod 137 def GetMaxInstances(record): 138 return record.annotations.get(revision.MAX_SCALE_ANNOTATION, '') 139 140 @staticmethod 141 def TransformSpec(record): 142 limits = RevisionPrinter.GetLimits(record) 143 return cp.Labeled([ 144 ('Image', record.UserImage()), 145 ('Command', ' '.join(record.container.command)), 146 ('Args', ' '.join(record.container.args)), 147 ('Port', ' '.join( 148 six.text_type(p.containerPort) 149 for p in record.container.ports)), 150 ('Memory', limits['memory']), 151 ('CPU', limits['cpu']), 152 ('Service account', record.spec.serviceAccountName), 153 ('Env vars', RevisionPrinter.GetUserEnvironmentVariables(record)), 154 ('Secrets', RevisionPrinter.GetSecrets(record)), 155 ('Config Maps', RevisionPrinter.GetConfigMaps(record)), 156 ('Concurrency', record.concurrency), 157 ('Min Instances', RevisionPrinter.GetMinInstances(record)), 158 ('Max Instances', RevisionPrinter.GetMaxInstances(record)), 159 ('SQL connections', RevisionPrinter.GetCloudSqlInstances(record)), 160 ('Timeout', RevisionPrinter.GetTimeout(record)), 161 ('VPC connector', RevisionPrinter.GetVpcConnector(record)), 162 ]) 163