feat: Add new gcloud commands, API clients, and third-party libraries across various services.

This commit is contained in:
2026-01-01 20:26:35 +01:00
parent 5e23cbece0
commit a19e592eb7
25221 changed files with 8324611 additions and 0 deletions

View File

@@ -0,0 +1 @@
["core", "gcloud-deps", "bq", "gcloud", "gcloud-crc32c", "gsutil"]

View File

@@ -0,0 +1,321 @@
# Copyright 2013 Google Inc. All Rights Reserved.
"""Common bootstrapping functionality used by the wrapper scripts."""
# Disables import order warning and unused import. Setup changes the python
# path so cloud sdk imports will actually work, so it must come first.
# pylint: disable=C6203
# pylint: disable=W0611
from __future__ import absolute_import
from __future__ import unicode_literals
# Python 3 is strict about imports and we use this file in different ways, which
# makes sub-imports difficult. In general, when a script is executed, that
# directory is put on the PYTHONPATH. The issue is that some of the wrapper
# scripts are executed from within the bootstrapping/ directory and some are
# executed from within the bin/ directory.
# pylint: disable=g-statement-before-imports
if '.' in __name__:
# Here, __name__ will be bootstrapping.bootstrapping. This indicates that this
# file was loaded as a member of package bootstrapping. This in turn indicates
# that the main file that was executed was not in the bootstrapping directory,
# so bin/ is on the path and bootstrapping is considered a python package.
# Do an import of setup from this current package.
from . import setup # pylint:disable=g-import-not-at-top
else:
# In this case, __name__ is bootstrapping, which indicates that the main
# script was executed from within this directory meaning that Python doesn't
# consider this a package but rather the root of the PYTHONPATH. We can't do
# the above import because since we are not in a package, the '.' doesn't
# refer to anything. Just do a direct import which will find setup on the
# PYTHONPATH (which is just this directory).
import setup # pylint:disable=g-import-not-at-top
import gcloud
import sys
# Reorder sys.path if needed right now before more modules loaded and cached
sys.path = gcloud.reorder_sys_path(sys.path)
# pylint: disable=g-import-not-at-top
import json
# pylint: enable=g-import-not-at-top
import os
import platform
from googlecloudsdk.core import config
from googlecloudsdk.core import execution_utils
from googlecloudsdk.core import metrics
from googlecloudsdk.core import properties
from googlecloudsdk.core.console import console_attr
from googlecloudsdk.core.credentials import store as c_store
from googlecloudsdk.core.updater import local_state
from googlecloudsdk.core.updater import update_manager
from googlecloudsdk.core.util import encoding
from googlecloudsdk.core.util import files
from googlecloudsdk.core.util import platforms
from six.moves import input
BOOTSTRAPPING_DIR = os.path.dirname(os.path.realpath(__file__))
BIN_DIR = os.path.dirname(BOOTSTRAPPING_DIR)
SDK_ROOT = os.path.dirname(BIN_DIR)
def DisallowIncompatiblePythonVersions():
if not platforms.PythonVersion().IsCompatible():
sys.exit(1)
def GetDecodedArgv():
return [console_attr.Decode(arg) for arg in sys.argv]
def _FullPath(tool_dir, exec_name):
return os.path.join(SDK_ROOT, tool_dir, exec_name)
def ExecutePythonTool(tool_dir, exec_name, *args):
"""Execute the given python script with the given args and command line.
Args:
tool_dir: the directory the tool is located in
exec_name: additional path to the executable under the tool_dir
*args: args for the command
"""
py_path = None # Let execution_utils resolve the path.
# Gsutil allows users to set the desired Python interpreter using a separate
# environment variable, so as to allow users to run gsutil using Python 3
# without forcing the rest of Google Cloud CLI to use Python 3 (as it would
# likely break at the time this comment was written).
extra_popen_kwargs = {}
if exec_name == 'gsutil':
gsutil_py = encoding.GetEncodedValue(os.environ, 'CLOUDSDK_GSUTIL_PYTHON')
# Since PY3, Python closes open FDs in child processes, since we need them
# open for completions to work we set the close_fds kwarg to Popen.
extra_popen_kwargs['close_fds'] = False
if gsutil_py:
py_path = gsutil_py
if exec_name == 'bq.py':
bq_py = encoding.GetEncodedValue(os.environ, 'CLOUDSDK_BQ_PYTHON')
if bq_py:
py_path = bq_py
_ExecuteTool(
execution_utils.ArgsForPythonTool(
_FullPath(tool_dir, exec_name), *args, python=py_path),
**extra_popen_kwargs)
def ExecuteJarTool(java_bin, jar_dir, jar_name, classname, flags=None, *args):
"""Execute a given jar with the given args and command line.
Args:
java_bin: str, path to the system Java binary
jar_dir: str, the directory the jar is located in
jar_name: str, file name of the jar under tool_dir
classname: str, name of the main class in the jar
flags: [str], flags for the java binary
*args: args for the command
"""
flags = flags or []
jar_path = _FullPath(jar_dir, jar_name)
classname_arg = [classname] if classname else []
java_args = ['-cp', jar_path] + flags + classname_arg + list(args)
_ExecuteTool(
execution_utils.ArgsForExecutableTool(java_bin, *java_args))
def ExecuteJavaClass(java_bin,
jar_dir,
main_jar,
main_class,
java_flags=None,
main_args=None):
"""Execute a given java class within a directory of jars.
Args:
java_bin: str, path to the system Java binary
jar_dir: str, directory of jars to put on class path
main_jar: str, main jar (placed first on class path)
main_class: str, name of the main class in the jar
java_flags: [str], flags for the java binary
main_args: args for the command
"""
java_flags = java_flags or []
main_args = main_args or []
jar_dir_path = os.path.join(SDK_ROOT, jar_dir, '*')
main_jar_path = os.path.join(SDK_ROOT, jar_dir, main_jar)
classpath = main_jar_path + os.pathsep + jar_dir_path
java_args = (['-cp', classpath]
+ list(java_flags)
+ [main_class]
+ list(main_args))
_ExecuteTool(execution_utils.ArgsForExecutableTool(java_bin, *java_args))
def ExecuteShellTool(tool_dir, exec_name, *args):
"""Execute the given bash script with the given args.
Args:
tool_dir: the directory the tool is located in
exec_name: additional path to the executable under the tool_dir
*args: args for the command
"""
_ExecuteTool(
execution_utils.ArgsForExecutableTool(_FullPath(tool_dir, exec_name),
*args))
def ExecuteCMDTool(tool_dir, exec_name, *args):
"""Execute the given batch file with the given args.
Args:
tool_dir: the directory the tool is located in
exec_name: additional path to the executable under the tool_dir
*args: args for the command
"""
_ExecuteTool(
execution_utils.ArgsForCMDTool(_FullPath(tool_dir, exec_name), *args))
def _GetToolEnv():
env = dict(os.environ)
encoding.SetEncodedValue(env, 'CLOUDSDK_WRAPPER', '1')
encoding.SetEncodedValue(env, 'CLOUDSDK_VERSION', config.CLOUD_SDK_VERSION)
encoding.SetEncodedValue(env, 'CLOUDSDK_PYTHON',
execution_utils.GetPythonExecutable())
return env
def _ExecuteTool(args, **extra_popen_kwargs):
"""Executes a new tool with the given args, plus the args from the cmdline.
Args:
args: [str], The args of the command to execute.
**extra_popen_kwargs: [dict], kwargs to be unpacked in Popen call for tool.
"""
execution_utils.Exec(
args + sys.argv[1:], env=_GetToolEnv(), **extra_popen_kwargs)
def GetDefaultInstalledComponents():
"""Gets the list of components to install by default.
Returns:
list(str), The component ids that should be installed. It will return []
if there are no default components, or if there is any error in reading
the file with the defaults.
"""
default_components_file = os.path.join(BOOTSTRAPPING_DIR,
'.default_components')
try:
with open(default_components_file) as f:
return json.load(f)
# pylint:disable=bare-except, If the file does not exist or is malformed,
# we don't want to expose this as an error. Setup will just continue
# without installing any components by default and will tell the user how
# to install the components they want manually.
except:
pass
return []
def WarnAndExitOnBlockedCommand(args, blocked_commands):
"""Block certain subcommands, warn the user, and exit.
Args:
args: the command line arguments, including the 0th argument which is
the program name.
blocked_commands: a map of blocked commands to the messages that should be
printed when they're run.
"""
bad_arg = None
for arg in args[1:]:
# Flags are skipped and --flag=value are skipped. It is possible for
# '--flag value' to result in a false positive if value happens to be a
# blocked command.
if arg and arg[0] == '-':
continue
if arg in blocked_commands:
bad_arg = arg
break
blocked = bad_arg is not None
if blocked:
sys.stderr.write('It looks like you are trying to run "%s %s".\n'
% (args[0], bad_arg))
sys.stderr.write('The "%s" command is no longer needed with '
'Google Cloud CLI.\n' % bad_arg)
sys.stderr.write(blocked_commands[bad_arg] + '\n')
answer = input('Really run this command? (y/N) ')
if answer not in ['y', 'Y']:
sys.exit(1)
def CheckUpdates(command_path):
"""Check for updates and inform the user.
Args:
command_path: str, The '.' separated path of the command that is currently
being run (i.e. gcloud.foo.bar).
"""
try:
update_manager.UpdateManager.PerformUpdateCheck(command_path=command_path)
# pylint:disable=broad-except, We never want this to escape, ever. Only
# messages printed should reach the user.
except Exception:
pass
def CommandStart(command_name, component_id=None, version=None):
"""Logs that the given command is being executed.
Args:
command_name: str, The name of the command being executed.
component_id: str, The component id that this command belongs to. Used for
version information if version was not specified.
version: str, Directly use this version instead of deriving it from
component.
"""
if version is None and component_id:
version = local_state.InstallationState.VersionForInstalledComponent(
component_id)
metrics.Executions(command_name, version)
def GetActiveProjectAndAccount():
"""Get the active project name and account for the active credentials.
For use with wrapping legacy tools that take projects and credentials on
the command line.
Returns:
(str, str), A tuple whose first element is the project, and whose second
element is the account.
"""
project_name = properties.VALUES.core.project.Get(validate=False)
account = properties.VALUES.core.account.Get(validate=False)
return (project_name, account)
def GetActiveImpersonateServiceAccount():
"""Get the active impersonate_service_account property.
For use with wrapping legacy tools that take impersonate_service_account on
the command line.
Returns:
str, The name of the service account to impersonate.
"""
return properties.VALUES.auth.impersonate_service_account.Get(validate=False)
def ReadFileContents(*path_parts):
"""Returns file content at specified relative path wrt SDK root path."""
return files.ReadFileContents(os.path.join(SDK_ROOT, *path_parts)).strip()
# Register some other sources for credentials and project.
c_store.GceCredentialProvider().Register()

View File

@@ -0,0 +1,167 @@
#!/usr/bin/env python
#
# Copyright 2013 Google Inc. All Rights Reserved.
#
"""A convenience wrapper for starting bq."""
from __future__ import absolute_import
from __future__ import unicode_literals
import os
import re
import bootstrapping
from googlecloudsdk.api_lib.iamcredentials import util as iamcred_util
from googlecloudsdk.calliope import exceptions
from googlecloudsdk.core import config
from googlecloudsdk.core import properties
from googlecloudsdk.core.credentials import gce
from googlecloudsdk.core.credentials import store
def _MaybeAddOption(args, name, value):
if value is None:
return
args.append('--{name}={value}'.format(name=name, value=value))
def _GetGoogleAuthFlagValue(argv):
for arg in argv[1:]:
if re.fullmatch(r'--use_google_auth(=(T|t)rue)*', arg):
return True
if re.fullmatch(r'(--nouse_google_auth|--use_google_auth=(F|f)alse)', arg):
return False
return None
def _IsOAuthAccessTokenFlagPresent(argv):
for arg in argv[1:]:
if re.fullmatch(r'--oauth_access_token=.+', arg):
return True
return False
def main():
"""Launches bq."""
version = bootstrapping.ReadFileContents('platform/bq', 'VERSION')
bootstrapping.CommandStart('bq', version=version)
blocked_commands = {
'init': 'To authenticate, run gcloud auth.',
}
argv = bootstrapping.GetDecodedArgv()
bootstrapping.WarnAndExitOnBlockedCommand(argv, blocked_commands)
cmd_args = [arg for arg in argv[1:] if not arg.startswith('-')]
use_google_auth = _GetGoogleAuthFlagValue(argv)
use_google_auth_unspecified = use_google_auth is None
nouse_google_auth = not use_google_auth and not use_google_auth_unspecified
args = []
print_logging = False
if len(cmd_args) == 1 and cmd_args[0] == 'info':
print_logging = True
# Check for credentials only if they are needed.
if (
cmd_args
and cmd_args[0] not in ('version', 'help')
and not _IsOAuthAccessTokenFlagPresent(argv)
):
store.IMPERSONATION_TOKEN_PROVIDER = (
iamcred_util.ImpersonationAccessTokenProvider()
)
creds = store.Load() # Checks if there are active credentials
project, account = bootstrapping.GetActiveProjectAndAccount()
if print_logging:
print('Project:', project)
print('Account:', account)
adc_path = config.Paths().LegacyCredentialsAdcPath(account)
single_store_path = config.Paths().LegacyCredentialsBqPath(account)
if use_google_auth:
if print_logging:
print('Using Google auth')
args = ['--use_google_auth']
elif bootstrapping.GetActiveImpersonateServiceAccount():
if print_logging:
print('Using Oauth')
args = ['--oauth_access_token', creds.token]
elif gce.Metadata() and account in gce.Metadata().Accounts():
if print_logging:
print('Using a GCE service account')
args = ['--use_gce_service_account']
elif os.path.isfile(adc_path) and nouse_google_auth:
if print_logging:
print('Using an ADC path')
args = [
'--nouse_google_auth',
'--application_default_credential_file',
adc_path,
'--credential_file',
single_store_path,
]
else:
p12_key_path = config.Paths().LegacyCredentialsP12KeyPath(account)
if os.path.isfile(p12_key_path):
if nouse_google_auth:
if print_logging:
print(
'Falling back to p12 credentials. '
'WARNING these are being deprecated.'
)
print(
'Using the deprecated P12 service account key format with legacy'
' auth may introduce security vulnerabilities and will soon be'
' unsupported. If you are unable to migrate to using the newer'
' JSON key format, file a report to inform the BQ CLI team of'
' your use case.'
)
args = [
'--nouse_google_auth',
'--service_account',
account,
'--service_account_credential_file',
single_store_path,
'--service_account_private_key_file',
p12_key_path,
]
use_client_cert = (
os.getenv('GOOGLE_API_USE_CLIENT_CERTIFICATE', 'false').upper()
== 'TRUE'
)
if use_client_cert:
if print_logging:
print('Using MTLS')
args.append('--mtls')
_MaybeAddOption(args, 'project_id', project)
bootstrapping.CheckUpdates('bq')
proxy_params = properties.VALUES.proxy
_MaybeAddOption(args, 'proxy_address', proxy_params.address.Get())
_MaybeAddOption(args, 'proxy_port', proxy_params.port.Get())
_MaybeAddOption(args, 'proxy_username', proxy_params.username.Get())
_MaybeAddOption(args, 'proxy_password', proxy_params.password.Get())
_MaybeAddOption(
args,
'disable_ssl_validation',
properties.VALUES.auth.disable_ssl_validation.GetBool(),
)
_MaybeAddOption(
args,
'ca_certificates_file',
properties.VALUES.core.custom_ca_certs_file.Get(),
)
if print_logging:
print('Args passed from gcloud:', args)
bootstrapping.ExecutePythonTool('platform/bq', 'bq.py', *args)
if __name__ == '__main__':
bootstrapping.DisallowIncompatiblePythonVersions()
try:
main()
except Exception as e: # pylint: disable=broad-except
exceptions.HandleError(e, 'bq')

View File

@@ -0,0 +1,174 @@
#!/usr/bin/env python
#
# Copyright 2013 Google Inc. All Rights Reserved.
#
"""A convenience wrapper for starting gsutil."""
from __future__ import absolute_import
from __future__ import unicode_literals
import json
import os
import bootstrapping
from googlecloudsdk.calliope import exceptions
from googlecloudsdk.core import config
from googlecloudsdk.core import context_aware
from googlecloudsdk.core import log
from googlecloudsdk.core import metrics
from googlecloudsdk.core import properties
from googlecloudsdk.core.credentials import gce as c_gce
from googlecloudsdk.core.util import encoding
from googlecloudsdk.core.util import files
def _MaybeAddBotoOption(args, section, name, value):
if value is None:
return
args.append('-o')
args.append('{section}:{name}={value}'.format(
section=section, name=name, value=value))
def _GetCertProviderCommand(context_config):
"""Returns the cert provider command from the context config."""
# TODO(b/190102217) - Cleanup code that handles both version of context_config
if hasattr(context_config, 'cert_provider_command'):
return context_config.cert_provider_command
try:
contents = files.ReadFileContents(context_config.config_path)
json_out = json.loads(contents)
if 'cert_provider_command' in json_out:
return json_out['cert_provider_command']
except files.Error as e:
log.debug('context aware settings discovery file %s - %s',
context_config.config_path, e)
def _AddContextAwareOptions(args):
"""Adds device certificate settings for mTLS."""
context_config = context_aware.Config()
# Enterprise certificate is not yet supported for gsutil.
if (
context_config
and context_config.config_type
== context_aware.ConfigType.ENTERPRISE_CERTIFICATE
):
return
# TODO(b/190102217) - Cleanup code that handles both version of context_config
use_client_certificate = (
context_config and
getattr(context_config, 'use_client_certificate', True))
_MaybeAddBotoOption(args, 'Credentials', 'use_client_certificate',
use_client_certificate)
if context_config:
cert_provider_command = _GetCertProviderCommand(context_config)
if isinstance(cert_provider_command, list):
# e.g. cert_provider_command = ['*/apihelper', '--print_certificate']
cert_provider_command = ' '.join(cert_provider_command)
# Don't need to pass mTLS data if gsutil shouldn't be using it.
_MaybeAddBotoOption(args, 'Credentials', 'cert_provider_command',
cert_provider_command)
def main():
"""Launches gsutil."""
args = []
project, account = bootstrapping.GetActiveProjectAndAccount()
pass_credentials = (
properties.VALUES.core.pass_credentials_to_gsutil.GetBool() and
not properties.VALUES.auth.disable_credentials.GetBool())
_MaybeAddBotoOption(args, 'GSUtil', 'default_project_id', project)
if pass_credentials:
# Allow gsutil to only check for the '1' string value, as is done
# with regard to the 'CLOUDSDK_WRAPPER' environment variable.
encoding.SetEncodedValue(
os.environ, 'CLOUDSDK_CORE_PASS_CREDENTIALS_TO_GSUTIL', '1')
if account in c_gce.Metadata().Accounts():
# Tell gsutil that it should obtain credentials from the GCE metadata
# server for the instance's configured service account.
_MaybeAddBotoOption(args, 'GoogleCompute', 'service_account', 'default')
# For auth'n debugging purposes, allow gsutil to reason about whether the
# configured service account was set in a boto file or passed from here.
encoding.SetEncodedValue(
os.environ, 'CLOUDSDK_PASSED_GCE_SERVICE_ACCOUNT_TO_GSUTIL', '1')
else:
legacy_config_path = config.Paths().LegacyCredentialsGSUtilPath(account)
# We construct a BOTO_PATH that tacks the config containing our
# credentials options onto the end of the list of config paths. We ensure
# the other credential options are loaded first so that ours will take
# precedence and overwrite them.
boto_config = encoding.GetEncodedValue(os.environ, 'BOTO_CONFIG', '')
boto_path = encoding.GetEncodedValue(os.environ, 'BOTO_PATH', '')
if boto_config:
boto_path = os.pathsep.join([boto_config, legacy_config_path])
elif boto_path:
boto_path = os.pathsep.join([boto_path, legacy_config_path])
else:
path_parts = ['/etc/boto.cfg',
os.path.expanduser(os.path.join('~', '.boto')),
legacy_config_path]
boto_path = os.pathsep.join(path_parts)
encoding.SetEncodedValue(os.environ, 'BOTO_CONFIG', None)
encoding.SetEncodedValue(os.environ, 'BOTO_PATH', boto_path)
# Tell gsutil whether gcloud analytics collection is enabled.
encoding.SetEncodedValue(
os.environ, 'GA_CID', metrics.GetCIDIfMetricsEnabled())
# Set proxy settings. Note that if these proxy settings are configured in a
# boto config file, the options here will be loaded afterward, overriding
# them.
proxy_params = properties.VALUES.proxy
proxy_address = proxy_params.address.Get()
if proxy_address:
_MaybeAddBotoOption(args, 'Boto', 'proxy', proxy_address)
_MaybeAddBotoOption(args, 'Boto', 'proxy_port', proxy_params.port.Get())
_MaybeAddBotoOption(args, 'Boto', 'proxy_rdns', proxy_params.rdns.GetBool())
_MaybeAddBotoOption(args, 'Boto', 'proxy_user', proxy_params.username.Get())
_MaybeAddBotoOption(args, 'Boto', 'proxy_pass', proxy_params.password.Get())
# Set SSL-related settings.
disable_ssl = properties.VALUES.auth.disable_ssl_validation.GetBool()
_MaybeAddBotoOption(args, 'Boto', 'https_validate_certificates',
None if disable_ssl is None else not disable_ssl)
_MaybeAddBotoOption(args, 'Boto', 'ca_certificates_file',
properties.VALUES.core.custom_ca_certs_file.Get())
# Sync device certificate settings for mTLS.
_AddContextAwareOptions(args)
# Note that the original args to gsutil will be appended after the args we've
# supplied here.
bootstrapping.ExecutePythonTool('platform/gsutil', 'gsutil', *args)
if __name__ == '__main__':
try:
version = bootstrapping.ReadFileContents('platform/gsutil', 'VERSION')
bootstrapping.CommandStart('gsutil', version=version)
blocked_commands = {
'update': 'To update, run: gcloud components update',
}
argv = bootstrapping.GetDecodedArgv()
bootstrapping.WarnAndExitOnBlockedCommand(argv, blocked_commands)
# Don't call bootstrapping.PreRunChecks because anonymous access is
# supported for some endpoints. gsutil will output the appropriate
# error message upon receiving an authentication error.
bootstrapping.CheckUpdates('gsutil')
main()
except Exception as e: # pylint: disable=broad-except
exceptions.HandleError(e, 'gsutil')

View File

@@ -0,0 +1,358 @@
#!/usr/bin/env python
#
# Copyright 2013 Google Inc. All Rights Reserved.
#
"""Do initial setup for the Cloud CLI."""
from __future__ import absolute_import
from __future__ import print_function
from __future__ import unicode_literals
import bootstrapping
# pylint:disable=g-bad-import-order
import argparse
import os
import sys
from googlecloudsdk.calliope import actions
from googlecloudsdk.calliope import exceptions
from googlecloudsdk.core import config
from googlecloudsdk.core import platforms_install
from googlecloudsdk.core import properties
from googlecloudsdk.core.console import console_io
from googlecloudsdk.core.updater import python_manager
from googlecloudsdk.core.updater import update_manager
from googlecloudsdk.core.util import encoding
from googlecloudsdk.core.util import platforms
from googlecloudsdk import gcloud_main
# pylint:disable=superfluous-parens
_CLI = gcloud_main.CreateCLI([])
def ParseArgs():
"""Parse args for the installer, so interactive prompts can be avoided."""
def Bool(s):
return s.lower() in ['true', '1']
parser = argparse.ArgumentParser()
parser.add_argument(
'--usage-reporting',
default=None,
type=Bool,
help='(true/false) Enable anonymous usage reporting.',
)
parser.add_argument(
'--screen-reader',
default=None,
type=Bool,
help='(true/false) Enable screen reader mode.',
)
parser.add_argument(
'--universe-domain',
default=None,
help=(
'Universe domain to default to. If specified, sets the'
' [core/universe_domain] property installation-wide.'
),
)
parser.add_argument(
'--rc-path',
help=(
'Profile to update with PATH and completion. If'
' given without --command-completion or'
' --path-update in "quiet" mode, a line will be'
' added to this profile for both command completion'
' and path updating.'
),
)
parser.add_argument(
'--command-completion',
'--bash-completion',
default=None,
type=Bool,
help=(
'(true/false) Add a line for command completion in'
' the profile. In "quiet" mode, if True and you do'
' not provide--rc-path, the default profile'
' will be updated.'
),
)
parser.add_argument(
'--path-update',
default=None,
type=Bool,
help=(
'(true/false) Add a line for path updating in the'
' profile. In "quiet" mode, if True and you do not'
' provide --rc-path, the default profile will be'
' updated.'
),
)
parser.add_argument(
'--disable-installation-options',
action='store_true',
help='DEPRECATED. This flag is no longer used.',
)
parser.add_argument(
'--override-components',
nargs='*',
help=(
'Override the components that would be installed by '
'default and install these instead.'
),
)
parser.add_argument(
'--additional-components',
nargs='+',
help=(
'Additional components to install by default. These'
' components will either be added to the default install '
'list, or to the override-components (if provided).'
),
)
parser.add_argument(
'--update-installed-components',
action='store_true',
help=(
'Update previously installed components. Checks the install folder '
'to make sure that there are no installed components that need '
'to be updated. This is currently just used for updating gcloud '
'via homebrew.'
)
)
# Must have a None default so properties are not always overridden when the
# arg is not provided.
parser.add_argument(
'--quiet',
'-q',
default=None,
action=actions.StoreConstProperty(
properties.VALUES.core.disable_prompts, True
),
help=(
'Disable all interactive prompts. If input is '
'required, defaults will be used or an error will be '
'raised'
),
)
parser.add_argument(
'--install-python',
default=True,
type=Bool,
help='(true/false) Attempt to install Python. MacOS only.',
)
parser.add_argument(
'--no-compile-python',
action='store_false',
help=(
'False. If set, skips python compilation after component'
' installation.'
),
)
return parser.parse_args(bootstrapping.GetDecodedArgv()[1:])
def Prompts(usage_reporting, universe_domain):
"""Display prompts to opt out of usage reporting.
Args:
usage_reporting: bool, If True, enable usage reporting. If None, check the
environmental variable. If None, check if its alternate release channel.
If not, ask.
universe_domain: str, if specified and not 'googleapis.com', set
usage-reporting to False.
"""
if usage_reporting is None:
if (
encoding.GetEncodedValue(
os.environ, 'CLOUDSDK_CORE_DISABLE_USAGE_REPORTING'
)
is not None
):
usage_reporting = not encoding.GetEncodedValue(
os.environ, 'CLOUDSDK_CORE_DISABLE_USAGE_REPORTING'
)
else:
if (
universe_domain is not None
and universe_domain != properties.VALUES.core.universe_domain.default
):
usage_reporting = False
elif config.InstallationConfig.Load().IsAlternateReleaseChannel():
usage_reporting = True
print("""
Usage reporting is always on for alternate release channels.
""")
else:
print("""
To help improve the quality of this product, we collect anonymized usage data
and anonymized stacktraces when crashes are encountered; additional information
is available at <https://cloud.google.com/sdk/usage-statistics>. This data is
handled in accordance with our privacy policy
<https://cloud.google.com/terms/cloud-privacy-notice>. You may choose to opt in this
collection now (by choosing 'Y' at the below prompt), or at any time in the
future by running the following command:
gcloud config set disable_usage_reporting false
""")
usage_reporting = console_io.PromptContinue(
prompt_string='Do you want to help improve the Google Cloud CLI',
default=False)
properties.PersistProperty(
properties.VALUES.core.disable_usage_reporting, not usage_reporting,
scope=properties.Scope.INSTALLATION)
def GetInstalledComponents():
# Check if .install folder already has components installed
platform = platforms.Platform.Current()
manager = update_manager.UpdateManager(platform_filter=platform, warn=False)
installed_components = manager.GetCurrentVersionsInformation()
return list(installed_components.keys())
def Install(
override_components, update_installed_components,
additional_components, compile_python):
"""Do the normal installation of the Cloud CLI."""
# Install the OS specific wrapper scripts for gcloud and any pre-configured
# components for the CLI.
to_install = (override_components if override_components is not None
else bootstrapping.GetDefaultInstalledComponents())
# If there are components that are to be installed by default, this means we
# are working with an incomplete Cloud CLI package. This comes from the curl
# installer or the Windows installer or downloading a seed directly. In this
# case, we will update to the latest version of the CLI. If there are no
# default components, this is a fully packaged CLI. If there are additional
# components requested, just install them without updating the version.
update = bool(to_install)
# If gcloud was previously installed, there may still be some old installed
# components. Ensure those components are up to date. This ensures
# upgrades outside of `gcloud components update` still update installed
# components.
if (update_installed_components and
(installed_components := GetInstalledComponents())):
to_install.extend(installed_components)
if additional_components:
to_install.extend(additional_components)
InstallOrUpdateComponents(to_install, compile_python, update=update)
# Show the list of components if there were no pre-configured ones.
if not to_install:
_CLI.Execute(['--quiet', 'components', 'list'])
def ReInstall(component_ids, compile_python):
"""Do a forced reinstallation of Google Cloud CLI.
Args:
component_ids: [str], The components that should be automatically installed.
compile_python: bool, False if we skip compile python
"""
to_install = bootstrapping.GetDefaultInstalledComponents()
to_install.extend(component_ids)
# We always run in update mode here because we are reinstalling and trying
# to get the latest version anyway.
InstallOrUpdateComponents(component_ids, compile_python, update=True)
def InstallOrUpdateComponents(component_ids, compile_python, update):
"""Installs or updates the given components.
Args:
component_ids: [str], The components to install or update.
compile_python: bool, False if we skip compile python
update: bool, True if we should run update, False to run install. If there
are no components to install, this does nothing unless in update mode (in
which case everything gets updated).
"""
# If we are in installation mode, and there are no specific components to
# install, there is nothing to do. If there are no components in update mode
# things will still get updated to latest.
if not update and not component_ids:
return
print(
"""
This will install all the core command line tools necessary for working with
the Google Cloud Platform.
"""
)
verb = 'update' if update else 'install'
execute_arg_list = ['--quiet', 'components', verb]
if not compile_python:
execute_arg_list.append('--no-compile-python')
else:
execute_arg_list.append('--compile-python')
_CLI.Execute(
execute_arg_list + component_ids
)
def main():
properties.VALUES.context_aware.use_client_certificate.Set(False)
pargs = ParseArgs()
if pargs.screen_reader is not None:
properties.PersistProperty(properties.VALUES.accessibility.screen_reader,
pargs.screen_reader,
scope=properties.Scope.INSTALLATION)
if pargs.universe_domain is not None:
properties.PersistProperty(properties.VALUES.core.universe_domain,
pargs.universe_domain,
scope=properties.Scope.INSTALLATION)
update_manager.RestartIfUsingBundledPython(sdk_root=config.Paths().sdk_root,
command=__file__)
reinstall_components = encoding.GetEncodedValue(
os.environ, 'CLOUDSDK_REINSTALL_COMPONENTS')
try:
if reinstall_components:
ReInstall(reinstall_components.split(','), pargs.no_compile_python)
else:
Prompts(pargs.usage_reporting, pargs.universe_domain)
bootstrapping.CommandStart('INSTALL', component_id='core')
if not config.INSTALLATION_CONFIG.disable_updater:
Install(
pargs.override_components,
pargs.update_installed_components,
pargs.additional_components,
pargs.no_compile_python,
)
platforms_install.UpdateRC(
completion_update=pargs.command_completion,
path_update=pargs.path_update,
rc_path=pargs.rc_path,
bin_path=bootstrapping.BIN_DIR,
sdk_root=bootstrapping.SDK_ROOT,
)
if pargs.install_python:
python_manager.PromptAndInstallPythonOnMac()
print("""\
For more information on how to get started, please visit:
https://cloud.google.com/sdk/docs/quickstarts
""")
except exceptions.ToolException as e:
print(e)
sys.exit(1)
if __name__ == '__main__':
main()

View File

@@ -0,0 +1,50 @@
# Copyright 2017 Google Inc. All Rights Reserved.
#
"""A convenience wrapper for starting dev_appserver for appengine for Java."""
from __future__ import absolute_import
from __future__ import unicode_literals
import os
import bootstrapping
from googlecloudsdk.command_lib.util import java
from googlecloudsdk.core.updater import update_manager
# Path to the jar's directory relative to the SDK root
_JAR_DIR = os.path.join('platform', 'google_appengine', 'google', 'appengine',
'tools', 'java', 'lib')
# Filename of the jar
_JAR_NAME = 'appengine-tools-api.jar'
# Flags, (enable assertions)
_FLAGS = ['-ea']
# Name of the main class
_CLASSNAME = 'com.google.appengine.tools.KickStart'
# Additional arguments, comes before sys.argv.
# The KickStart main class accepts this classname as its first arg
_ARGS = [
'com.google.appengine.tools.development.DevAppServerMain',
'--promote_yaml'
]
def main():
"""Launches the Java dev_appserver 1."""
update_manager.UpdateManager.EnsureInstalledAndRestart(
['app-engine-java'],
command=__file__)
java_bin = java.RequireJavaInstalled('Java local development server')
bootstrapping.ExecuteJarTool(
java_bin, _JAR_DIR, _JAR_NAME, _CLASSNAME, _FLAGS, *_ARGS)
if __name__ == '__main__':
bootstrapping.DisallowIncompatiblePythonVersions()
bootstrapping.CommandStart('dev_appserver_java', component_id='core')
bootstrapping.CheckUpdates('dev_appserver_java')
main()

View File

@@ -0,0 +1,66 @@
# Copyright 2013 Google Inc. All Rights Reserved.
"""Does some initial setup and checks for all the bootstrapping scripts."""
from __future__ import absolute_import
from __future__ import unicode_literals
import os
import sys
# We don't want to import any libraries at this point so we handle py2/3
# manually.
SITE_PACKAGES = 'CLOUDSDK_PYTHON_SITEPACKAGES'
VIRTUAL_ENV = 'VIRTUAL_ENV'
if sys.version_info[0] == 2:
SITE_PACKAGES = SITE_PACKAGES.encode('utf-8')
VIRTUAL_ENV = VIRTUAL_ENV.encode('utf-8')
# If we're in a virtualenv, always import site packages. Also, upon request.
# We can't import anything from googlecloudsdk here so we are just going to
# assume no one has done anything as silly as to put any unicode in either of
# these env vars.
import_site_packages = (os.environ.get(SITE_PACKAGES) or
os.environ.get(VIRTUAL_ENV))
if import_site_packages:
# pylint:disable=unused-import
# pylint:disable=g-import-not-at-top
import site
# Put Google Cloud CLI libs on the path
root_dir = os.path.normpath(os.path.join(
os.path.dirname(os.path.realpath(__file__)), '..', '..'))
lib_dir = os.path.join(root_dir, 'lib')
third_party_dir = os.path.join(lib_dir, 'third_party')
sys.path = [lib_dir, third_party_dir] + sys.path
# When python is not invoked with the -S option, it can preload google module
# via .pth file setting its __path__. After this happens, our vendored google
# package may not in the __path__. After our vendored dependency directory is
# put at the first place in the sys.path, google module should be reloaded,
# so that our vendored copy can be preferred.
if 'google' in sys.modules:
import google # pylint: disable=g-import-not-at-top
try:
reload(google)
except NameError:
import importlib # pylint: disable=g-import-not-at-top
importlib.reload(google)
# pylint: disable=g-import-not-at-top
from googlecloudsdk.core.util import platforms
# Add more methods to this list for universal checks that need to be performed
def DoAllRequiredChecks():
if not platforms.PythonVersion().IsCompatible():
sys.exit(1)
DoAllRequiredChecks()