From 7c2689ec0e026123768698eb41ddda42af99d267 Mon Sep 17 00:00:00 2001 From: Omar Jarjur Date: Tue, 13 Feb 2018 13:41:14 -0800 Subject: [PATCH] Add some basic version information reporting: (#1956) 1. Add the version of the Cloud SDK and datalab component used to create an instance to that instance's metadata. 2. When connecting to an instance using the `--diagnose-me` flag, report the version info from that instance's metadata entries. --- tools/cli/commands/connect.py | 10 ++++++++++ tools/cli/commands/create.py | 23 +++++++++++++++++++---- tools/cli/commands/creategpu.py | 23 +++++++++++++++++++---- tools/cli/datalab.py | 25 ++++++++++++++++++++++--- 4 files changed, 70 insertions(+), 11 deletions(-) diff --git a/tools/cli/commands/connect.py b/tools/cli/commands/connect.py index 514c018c6..e43f4b255 100644 --- a/tools/cli/commands/connect.py +++ b/tools/cli/commands/connect.py @@ -363,10 +363,20 @@ def run(args, gcloud_compute, email='', in_cloud_shell=False, **unused_kwargs): status, metadata_items = utils.describe_instance( args, gcloud_compute, instance) for_user = metadata_items.get('for-user', '') + sdk_version = metadata_items.get('created-with-sdk-version', 'UNKNOWN') + datalab_version = metadata_items.get( + 'created-with-datalab-version', 'UNKNOWN') if (not args.no_user_checking) and for_user and (for_user != email): print(wrong_user_message_template.format(for_user, email)) return + if args.diagnose_me: + print('Instance {} was created with the following ' + 'Cloud SDK component versions:' + '\n\tCloud SDK: {}' + '\n\tDatalab: {}'.format( + instance, sdk_version, datalab_version)) + maybe_start(args, gcloud_compute, instance, status) connect(args, gcloud_compute, email, in_cloud_shell) return diff --git a/tools/cli/commands/create.py b/tools/cli/commands/create.py index cb766762e..79f9f7e1c 100644 --- a/tools/cli/commands/create.py +++ b/tools/cli/commands/create.py @@ -686,7 +686,8 @@ def prepare(args, gcloud_compute, gcloud_repos): def run(args, gcloud_compute, gcloud_repos, - email='', in_cloud_shell=False, gcloud_zone=None, **kwargs): + email='', in_cloud_shell=False, gcloud_zone=None, + sdk_version='UNKNOWN', datalab_version='UNKNOWN', **kwargs): """Implementation of the `datalab create` subcommand. Args: @@ -698,6 +699,8 @@ def run(args, gcloud_compute, gcloud_repos, in_cloud_shell: Whether or not the command is being run in the Google Cloud Shell gcloud_zone: The zone that gcloud is configured to use + sdk_version: The version of the Cloud SDK being used + datalab_version: The version of the datalab CLI being used Raises: subprocess.CalledProcessError: If a nested `gcloud` calls fails """ @@ -725,7 +728,9 @@ def run(args, gcloud_compute, gcloud_repos, with tempfile.NamedTemporaryFile(delete=False) as startup_script_file, \ tempfile.NamedTemporaryFile(delete=False) as user_data_file, \ tempfile.NamedTemporaryFile(delete=False) as for_user_file, \ - tempfile.NamedTemporaryFile(delete=False) as os_login_file: + tempfile.NamedTemporaryFile(delete=False) as os_login_file, \ + tempfile.NamedTemporaryFile(delete=False) as sdk_version_file, \ + tempfile.NamedTemporaryFile(delete=False) as datalab_version_file: try: startup_script_file.write(_DATALAB_STARTUP_SCRIPT.format( args.image_name, _DATALAB_NOTEBOOKS_REPOSITORY, enable_swap)) @@ -738,17 +743,25 @@ def run(args, gcloud_compute, gcloud_repos, for_user_file.close() os_login_file.write("FALSE") os_login_file.close() + sdk_version_file.write(sdk_version) + sdk_version_file.close() + datalab_version_file.write(datalab_version) + datalab_version_file.close() metadata_template = ( 'startup-script={0},' + 'user-data={1},' + 'for-user={2},' + - 'enable-oslogin={3}') + 'enable-oslogin={3},' + + 'created-with-sdk-version={4},' + + 'created-with-datalab-version={5}') metadata_from_file = ( metadata_template.format( startup_script_file.name, user_data_file.name, for_user_file.name, - os_login_file.name)) + os_login_file.name, + sdk_version_file.name, + datalab_version_file.name)) cmd.extend([ '--format=none', '--boot-disk-size=20GB', @@ -768,6 +781,8 @@ def run(args, gcloud_compute, gcloud_repos, os.remove(user_data_file.name) os.remove(for_user_file.name) os.remove(os_login_file.name) + os.remove(sdk_version_file.name) + os.remove(datalab_version_file.name) if (not args.no_connect) and (not args.for_user): connect.connect(args, gcloud_compute, email, in_cloud_shell) diff --git a/tools/cli/commands/creategpu.py b/tools/cli/commands/creategpu.py index b4eed5b9a..52a391990 100644 --- a/tools/cli/commands/creategpu.py +++ b/tools/cli/commands/creategpu.py @@ -212,7 +212,8 @@ def flags(parser): def run(args, gcloud_beta_compute, gcloud_repos, - email='', in_cloud_shell=False, gcloud_zone=None, **kwargs): + email='', in_cloud_shell=False, gcloud_zone=None, + sdk_version='UNKNOWN', datalab_version='UNKNOWN', **kwargs): """Implementation of the `datalab create` subcommand. Args: @@ -224,6 +225,8 @@ def run(args, gcloud_beta_compute, gcloud_repos, in_cloud_shell: Whether or not the command is being run in the Google Cloud Shell gcloud_zone: The zone that gcloud is configured to use + sdk_version: The version of the Cloud SDK being used + datalab_version: The version of the datalab CLI being used Raises: subprocess.CalledProcessError: If a nested `gcloud` calls fails """ @@ -267,7 +270,9 @@ def run(args, gcloud_beta_compute, gcloud_repos, with tempfile.NamedTemporaryFile(delete=False) as startup_script_file, \ tempfile.NamedTemporaryFile(delete=False) as user_data_file, \ tempfile.NamedTemporaryFile(delete=False) as for_user_file, \ - tempfile.NamedTemporaryFile(delete=False) as os_login_file: + tempfile.NamedTemporaryFile(delete=False) as os_login_file, \ + tempfile.NamedTemporaryFile(delete=False) as sdk_version_file, \ + tempfile.NamedTemporaryFile(delete=False) as datalab_version_file: try: startup_script_file.write(create._DATALAB_STARTUP_SCRIPT.format( args.image_name, create._DATALAB_NOTEBOOKS_REPOSITORY, @@ -282,17 +287,25 @@ def run(args, gcloud_beta_compute, gcloud_repos, for_user_file.close() os_login_file.write("FALSE") os_login_file.close() + sdk_version_file.write(sdk_version) + sdk_version_file.close() + datalab_version_file.write(datalab_version) + datalab_version_file.close() metadata_template = ( 'startup-script={0},' + 'user-data={1},' + 'for-user={2},' + - 'enable-oslogin={3}') + 'enable-oslogin={3},' + + 'created-with-sdk-version={4},' + + 'created-with-datalab-version={5}') metadata_from_file = ( metadata_template.format( startup_script_file.name, user_data_file.name, for_user_file.name, - os_login_file.name)) + os_login_file.name, + sdk_version_file.name, + datalab_version_file.name)) cmd.extend([ '--format=none', '--boot-disk-size=20GB', @@ -316,6 +329,8 @@ def run(args, gcloud_beta_compute, gcloud_repos, os.remove(user_data_file.name) os.remove(for_user_file.name) os.remove(os_login_file.name) + os.remove(sdk_version_file.name) + os.remove(datalab_version_file.name) if (not args.no_connect) and (not args.for_user): connect.connect(args, gcloud_beta_compute, email, in_cloud_shell) diff --git a/tools/cli/datalab.py b/tools/cli/datalab.py index a9a40bd36..935d569b4 100755 --- a/tools/cli/datalab.py +++ b/tools/cli/datalab.py @@ -22,6 +22,7 @@ from commands import create, creategpu, connect, list, stop, delete, utils import argparse +import json import os import subprocess import traceback @@ -104,6 +105,14 @@ """) +# Name of the core Cloud SDK component as reported by gcloud +sdk_core_component = 'Google Cloud SDK' + + +# Name of the datalab Cloud SDK component as reported by gcloud +datalab_component = 'datalab' + + try: with open(os.devnull, 'w') as dn: subprocess.call(['gcloud', '--version'], stderr=dn, stdout=dn) @@ -336,13 +345,22 @@ def run(): args.zone = args.top_level_zone if args.diagnose_me is None: args.diagnose_me = args.top_level_diagnose_me + + gcloud_version_json = subprocess.check_output([ + gcloud_cmd, 'version', '--format=json']).strip() + component_versions = json.loads(gcloud_version_json) + sdk_version = component_versions.get(sdk_core_component, 'UNKNOWN') + datalab_version = component_versions.get(datalab_component, 'UNKNOWN') + if args.diagnose_me: if args.verbosity is 'default': args.verbosity = 'debug' print('Running with diagnostic messages enabled') print('Using the command "{}" to invoke gcloud'.format(gcloud_cmd)) - print('The installed gcloud version is:') - subprocess.check_call([gcloud_cmd, 'version']) + print('The installed gcloud version is:' + '\n\tCloud SDK: {}\n\tDatalab: {}'.format( + sdk_version, datalab_version)) + gcloud_zone = "" if args.subcommand == 'beta': subcommand = _BETA_SUBCOMMANDS[args.beta_subcommand] @@ -356,7 +374,8 @@ def run(): args, compute, gcloud_repos=gcloud_repos, email=get_email_address(), in_cloud_shell=('DEVSHELL_CLIENT_PORT' in os.environ), - gcloud_zone=gcloud_zone) + gcloud_zone=gcloud_zone, + sdk_version=sdk_version, datalab_version=datalab_version) except subprocess.CalledProcessError as e: if utils.print_debug_messages(args): print('A nested call to gcloud failed.')