1# -*- coding: utf-8 -*- # 2# Copyright 2019 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"""Command line flags for Anthos commands.""" 16 17from __future__ import absolute_import 18from __future__ import division 19from __future__ import unicode_literals 20 21from googlecloudsdk.calliope import arg_parsers 22from googlecloudsdk.calliope import base 23from googlecloudsdk.core.util import files 24 25 26_MERGE_STRATEGIES = { 27 'resource-merge': ('perform a structural comparison of the ' 28 'original/updated Resources, and merge the changes ' 29 'into the local package.'), 30 'fast-forward': ('fail without updating if the local package was modified' 31 ' since it was fetched.'), 32 'alpha-git-patch': ("use 'git format-patch' and 'git am' to apply a patch " 33 "of the changes between the source version and " 34 "destination version. Requires the local package to " 35 "have been committed to a local git repo."), 36 'force-delete-replace': ('This will wipe all local changes to the package. ' 37 'Deletes the contents of local package from ' 38 'PACKAGE_DIR and replace them with the remote '), 39} 40 41 42def GetFlagOrPositional(name, positional=False, **kwargs): 43 """Return argument called name as either flag or positional.""" 44 dest = name.replace('-', '_').upper() 45 if positional: 46 flag = dest 47 kwargs.pop('required', None) 48 else: 49 flag = '--{}'.format(name.replace('_', '-').lower()) 50 if not positional: 51 kwargs['dest'] = dest 52 return base.Argument(flag, **kwargs) 53 54 55def GetRepoURIFlag(positional=True, required=True, 56 help_override=None, metavar=None): 57 """Get REPO_URI flag.""" 58 help_txt = help_override or """\ 59 Git repository URI containing 1 or more packages as where: 60 61 * REPO_URI - URI of a git repository containing 1 or more packages as 62 subdirectories. In most cases the .git suffix should be specified to 63 delimit the REPO_URI from the PKG_PATH, but this is not required for 64 widely recognized repo prefixes. If REPO_URI cannot be parsed then 65 an error will be printed an asking for '.git' to be specified 66 as part of the argument. e.g. https://github.com/kubernetes/examples.git 67 68 * PKG_PATH (optional) - Path to Git subdirectory containing Anthos package files. 69 Uses '/' as the path separator (regardless of OS). e.g. staging/cockroachdb. 70 Defaults to the root directory. 71 72 * GIT_REF (optional)- A git tag, branch, ref or commit for the remote version of the 73 package to fetch. Defaults to the repository master branch e.g. @master 74 """ 75 if not metavar: 76 metavar = 'REPO_URI[.git]/[PKG_PATH][@GIT_REF]' 77 return GetFlagOrPositional( 78 name='repo_uri', 79 positional=positional, 80 required=required, 81 help=help_txt, 82 metavar=metavar) 83 84 85def GetPackagePathFlag(metavar=None): 86 return GetFlagOrPositional( 87 name='package_path', 88 positional=False, 89 required=False, 90 help="""\ 91 Path to remote subdirectory containing Kubernetes Resource configuration 92 files or directories. 93 Defaults to the root directory. 94 Uses '/' as the path separator (regardless of OS). 95 e.g. staging/cockroachdb 96 """, 97 metavar=metavar) 98 99 100def GetLocalDirFlag(positional=True, required=True, 101 help_override=None, metavar=None): 102 """Get Local Package directory flag.""" 103 help_txt = help_override or """\ 104 The local directory to fetch the package to. 105 e.g. ./my-cockroachdb-copy 106 * If the directory does NOT exist: create the specified directory 107 and write the package contents to it 108 109 * If the directory DOES exist: create a NEW directory under the 110 specified one, defaulting the name to the Base of REPO/PKG_PATH 111 112 * If the directory DOES exist and already contains a directory with 113 the same name of the one that would be created: fail 114 """ 115 return GetFlagOrPositional( 116 name='LOCAL_DIR', 117 positional=positional, 118 required=required, 119 type=ExpandLocalDirAndVersion, 120 help=help_txt, 121 metavar=metavar) 122 123 124def GetFilePatternFlag(): 125 return GetFlagOrPositional( 126 name='pattern', 127 positional=False, 128 required=False, 129 help="""\ 130 Pattern to use for writing files. May contain the following formatting 131 verbs %n: metadata.name, %s: metadata.namespace, %k: kind 132 (default "%n_%k.yaml") 133 """) 134 135 136def GetStrategyFlag(): 137 return base.Argument( 138 '--strategy', 139 required=False, 140 choices=_MERGE_STRATEGIES, 141 help='Controls how changes to the local package are handled.') 142 143 144def GetDryRunFlag(help_override=None): 145 help_txt = help_override or ('If true and command fails print the ' 146 'underlying command that was executed and ' 147 'its exit status.') 148 return base.Argument( 149 '--dry-run', 150 action='store_true', 151 required=False, 152 help=help_txt) 153 154 155def GetDescriptionFlag(): 156 return base.Argument( 157 '--description', 158 required=False, 159 help='Description of the Package.') 160 161 162def GetNameFlag(): 163 return base.Argument( 164 '--name', 165 required=False, 166 help='Name of the package.') 167 168 169def GetTagsFlag(): 170 return base.Argument( 171 '--tags', 172 required=False, 173 type=arg_parsers.ArgDict(), 174 metavar='TAG=VALUE', 175 help='Tags for the package.') 176 177 178def GetInfoUrlFlag(): 179 return base.Argument( 180 '--info-url', 181 required=False, 182 help='Url with more info about the package.') 183 184 185def ExpandLocalDirAndVersion(directory): 186 """Expand HOME relative (~) directory with optional git_ref. 187 188 Args: 189 directory: str, directory path in the format PATH[/][@git_ref]. 190 Returns: 191 str, expanded full directory path with git_ref (if provided) 192 """ 193 path = directory.split('@') if directory else '' 194 full_dir = files.ExpandHomeDir(path[0]) 195 if len(path) == 2: 196 full_dir += '@' + path[1] 197 198 return full_dir 199 200 201# Anthos Auth 202def GetClusterFlag(positional=False, required=False, 203 help_override=None, metavar=None): 204 """Anthos operation cluster name flag.""" 205 help_txt = help_override or ('Cluster to authenticate against. If no cluster ' 206 'is specified, the command will print a list ' 207 'of available options.') 208 return GetFlagOrPositional( 209 name='CLUSTER', 210 positional=positional, 211 required=required, 212 help=help_txt, 213 metavar=metavar) 214 215 216def GetLoginConfigFlag(): 217 return base.Argument( 218 '--login-config', 219 required=False, 220 help='Specifies the configuration yaml ' 221 'file for login. Can be a file path or a URL.') 222 223 224def GetLoginConfigCertFlag(): 225 return base.Argument( 226 '--login-config-cert', 227 required=False, 228 type=ExpandLocalDirAndVersion, 229 help='Specifies the CA certificate file to be added to trusted pool ' 230 'for making HTTPS connections to a `--login-config` URL.') 231 232 233def GetUserFlag(): 234 return base.Argument( 235 '--user', 236 required=False, 237 help='If configuring multiple user accounts in the same kubecconfig ' 238 'file, you can specify a user to differentiate between them.') 239 240 241def GetSetPreferredAuthenticationFlag(): 242 return base.Argument( 243 '--set-preferred-auth', 244 required=False, 245 action='store_true', 246 help='If set, forces update of preferred ' 247 'authentication for given cluster') 248 249 250def GetOutputDirFlag(positional=False, required=False, 251 help_override=None, metavar='OUTPUT-DIR', default=None): 252 """Anthos operation local output directory flag.""" 253 help_txt = help_override or ('The output directory of the cluster resources.' 254 ' If empty will export files to ./CLUSTER_NAME') 255 return GetFlagOrPositional( 256 name='OUTPUT_DIRECTORY', 257 positional=positional, 258 required=required, 259 type=ExpandLocalDirAndVersion, 260 help=help_txt, 261 default=default, 262 metavar=metavar) 263 264 265def GetLocationFlag(): 266 """Anthos location flag.""" 267 return base.Argument( 268 '--location', 269 required=False, 270 help='Specifies the Google Cloud location to use. If not' 271 'specified will use the current compute/zone property.') 272 273 274def GetMergeFromFlag(): 275 """Anthos create-login-config Merge-From flag.""" 276 return base.Argument( 277 '--merge-from', 278 required=False, 279 help='Specifies the file path of an existing login ' 280 'configuration file to merge with.') 281 282 283def GetConfigOutputFileFlag(): 284 """Anthos create-login-config output flag.""" 285 return base.Argument( 286 '--output', 287 required=False, 288 type=ExpandLocalDirAndVersion, 289 help='Destination to write login configuration file. ' 290 'Defaults to "kubectl-anthos-config.yaml".') 291