# -*- 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