225 lines
7.6 KiB
Python
225 lines
7.6 KiB
Python
# -*- coding: utf-8 -*- #
|
|
# Copyright 2017 Google LLC. All Rights Reserved.
|
|
#
|
|
# Licensed under the Apache License, Version 2.0 (the "License");
|
|
# you may not use this file except in compliance with the License.
|
|
# You may obtain a copy of the License at
|
|
#
|
|
# http://www.apache.org/licenses/LICENSE-2.0
|
|
#
|
|
# Unless required by applicable law or agreed to in writing, software
|
|
# distributed under the License is distributed on an "AS IS" BASIS,
|
|
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
# See the License for the specific language governing permissions and
|
|
# limitations under the License.
|
|
"""The `gcloud meta test` command."""
|
|
|
|
from __future__ import absolute_import
|
|
from __future__ import division
|
|
from __future__ import print_function
|
|
from __future__ import unicode_literals
|
|
|
|
import os
|
|
import signal
|
|
import sys
|
|
import time
|
|
|
|
from googlecloudsdk.calliope import arg_parsers
|
|
from googlecloudsdk.calliope import base
|
|
from googlecloudsdk.calliope import parser_completer
|
|
from googlecloudsdk.calliope import parser_errors
|
|
from googlecloudsdk.command_lib.compute import completers
|
|
from googlecloudsdk.core import exceptions
|
|
from googlecloudsdk.core import execution_utils
|
|
from googlecloudsdk.core import module_util
|
|
from googlecloudsdk.core.console import console_io
|
|
from googlecloudsdk.core.console import progress_tracker
|
|
|
|
|
|
@base.UniverseCompatible
|
|
class Test(base.Command):
|
|
"""Run miscellaneous gcloud command and CLI test scenarios.
|
|
|
|
This command sets up scenarios for testing the gcloud command and CLI.
|
|
"""
|
|
|
|
@staticmethod
|
|
def Args(parser):
|
|
parser.add_argument(
|
|
'name',
|
|
nargs='*',
|
|
completer=completers.TestCompleter,
|
|
help='command_lib.compute.TestCompleter instance name test.')
|
|
scenarios = parser.add_group(mutex=True, required=True)
|
|
scenarios.add_argument(
|
|
'--arg-dict',
|
|
type=arg_parsers.ArgDict(),
|
|
metavar='ATTRIBUTES',
|
|
help='ArgDict flag value test.')
|
|
scenarios.add_argument(
|
|
'--arg-list',
|
|
type=arg_parsers.ArgList(),
|
|
metavar='ITEMS',
|
|
help='ArgList flag value test.')
|
|
scenarios.add_argument(
|
|
'--argumenterror-outside-argparse',
|
|
action='store_true',
|
|
help=('Trigger a calliope.parser_errors.ArgumentError exception '
|
|
'outside of argparse.'))
|
|
scenarios.add_argument(
|
|
'--core-exception',
|
|
action='store_true',
|
|
help='Trigger a core exception.')
|
|
scenarios.add_argument(
|
|
'--exec-file',
|
|
metavar='SCRIPT_FILE',
|
|
help='Runs `bash SCRIPT_FILE`.')
|
|
scenarios.add_argument(
|
|
'--interrupt',
|
|
action='store_true',
|
|
help='Kill the command with SIGINT.')
|
|
scenarios.add_argument(
|
|
'--is-interactive',
|
|
action='store_true',
|
|
help=('Call console_io.IsInteractive(heuristic=True) and exit 0 '
|
|
'if the return value is True, 1 if False.'))
|
|
scenarios.add_argument(
|
|
'--prompt-completer',
|
|
metavar='MODULE_PATH',
|
|
help=('Call console_io.PromptResponse() with a MODULE_PATH completer '
|
|
'and print the response on the standard output.'))
|
|
scenarios.add_argument(
|
|
'--progress-tracker',
|
|
metavar='SECONDS',
|
|
type=float,
|
|
default=0.0,
|
|
help='Run the progress tracker for SECONDS seconds and exit.')
|
|
scenarios.add_argument(
|
|
'--sleep',
|
|
metavar='SECONDS',
|
|
type=float,
|
|
default=0.0,
|
|
help='Sleep for SECONDS seconds and exit.')
|
|
scenarios.add_argument(
|
|
'--uncaught-exception',
|
|
action='store_true',
|
|
help='Trigger an exception that is not caught.')
|
|
scenarios.add_argument(
|
|
'--staged-progress-tracker',
|
|
action='store_true',
|
|
help='Run example staged progress tracker.')
|
|
scenarios.add_argument(
|
|
'--feature-flag',
|
|
action='store_true',
|
|
help='Print the value of a feature flag.')
|
|
|
|
def _RunArgDict(self, args):
|
|
return args.arg_dict
|
|
|
|
def _RunArgList(self, args):
|
|
return args.arg_list
|
|
|
|
def _RunArgumenterrorOutsideArgparse(self, args):
|
|
raise parser_errors.RequiredError(argument='--some-flag')
|
|
|
|
def _RunCoreException(self, args):
|
|
raise exceptions.Error('Some core exception.')
|
|
|
|
def _RunExecFile(self, args):
|
|
# We may want to add a timeout, though that will complicate the logic a bit
|
|
execution_utils.Exec(['bash', args.exec_file])
|
|
|
|
def _RunIsInteractive(self, args):
|
|
sys.exit(int(not console_io.IsInteractive(heuristic=True)))
|
|
|
|
def _RunInterrupt(self, args):
|
|
try:
|
|
# Windows hackery to simulate ^C and wait for it to register.
|
|
# NOTICE: This only works if this command is run from the console.
|
|
os.kill(os.getpid(), signal.CTRL_C_EVENT)
|
|
time.sleep(1)
|
|
except AttributeError:
|
|
# Back to normal where ^C is SIGINT and it works immediately.
|
|
os.kill(os.getpid(), signal.SIGINT)
|
|
raise exceptions.Error('SIGINT delivery failed.')
|
|
|
|
def _RunPromptCompleter(self, args):
|
|
completer_class = module_util.ImportModule(args.prompt_completer)
|
|
choices = parser_completer.ArgumentCompleter(completer_class, args)
|
|
response = console_io.PromptResponse('Complete this: ', choices=choices)
|
|
print(response)
|
|
|
|
def _RunProgressTracker(self, args):
|
|
start_time = time.time()
|
|
def message_callback():
|
|
remaining_time = args.progress_tracker - (time.time() - start_time)
|
|
return '{0:.1f}s remaining'.format(remaining_time)
|
|
with progress_tracker.ProgressTracker(
|
|
message='This is a progress tracker.',
|
|
detail_message_callback=message_callback):
|
|
time.sleep(args.progress_tracker)
|
|
|
|
def _RunSleep(self, args):
|
|
time.sleep(args.sleep)
|
|
|
|
def _RunUncaughtException(self, args):
|
|
raise ValueError('Catch me if you can.')
|
|
|
|
def _RunStagedProgressTracker(self, args):
|
|
get_bread = progress_tracker.Stage('Getting bread...', key='bread')
|
|
get_pb_and_j = progress_tracker.Stage('Getting peanut butter...', key='pb')
|
|
make_sandwich = progress_tracker.Stage('Making sandwich...', key='make')
|
|
stages = [get_bread, get_pb_and_j, make_sandwich]
|
|
with progress_tracker.StagedProgressTracker(
|
|
'Making sandwich...',
|
|
stages,
|
|
success_message='Time to eat!',
|
|
failure_message='Time to order delivery..!',
|
|
tracker_id='meta.make_sandwich') as tracker:
|
|
tracker.StartStage('bread')
|
|
time.sleep(0.5)
|
|
tracker.UpdateStage('bread', 'Looking for bread in the pantry')
|
|
time.sleep(0.5)
|
|
tracker.CompleteStage('bread', 'Got some whole wheat bread!')
|
|
tracker.StartStage('pb')
|
|
time.sleep(1)
|
|
tracker.CompleteStage('pb')
|
|
tracker.StartStage('make')
|
|
time.sleep(1)
|
|
tracker.CompleteStage('make')
|
|
|
|
def Run(self, args):
|
|
if args.arg_dict:
|
|
r = self._RunArgDict(args)
|
|
elif args.arg_list:
|
|
r = self._RunArgList(args)
|
|
elif args.argumenterror_outside_argparse:
|
|
r = self._RunArgumenterrorOutsideArgparse(args)
|
|
elif args.core_exception:
|
|
self._RunCoreException(args)
|
|
r = None
|
|
elif args.exec_file:
|
|
self._RunExecFile(args)
|
|
r = None
|
|
elif args.interrupt:
|
|
self._RunInterrupt(args)
|
|
r = None
|
|
elif args.is_interactive:
|
|
self._RunIsInteractive(args)
|
|
r = None
|
|
elif args.prompt_completer:
|
|
self._RunPromptCompleter(args)
|
|
r = None
|
|
elif args.progress_tracker:
|
|
self._RunProgressTracker(args)
|
|
r = None
|
|
elif args.sleep:
|
|
self._RunSleep(args)
|
|
r = None
|
|
elif args.uncaught_exception:
|
|
r = self._RunUncaughtException(args)
|
|
elif args.staged_progress_tracker:
|
|
self._RunStagedProgressTracker(args)
|
|
r = None
|
|
return r
|