def testFetchKubectlNamespace(self, exec_mock, tmp_kubeconfig_mock): env_image_version = 'composer-1.2.3-airflow-4.5.6' fake_exec = kubectl_util.FakeExec() exec_mock.side_effect = fake_exec tmp_kubeconfig_mock.side_effect = self.FakeTemporaryKubeconfig # NOTE: FetchKubectlNamespace() results are returned in asc order by # creation timestamp. # Scenario // 2 active namespaces. fake_exec.AddCallback( 0, self.MakeFetchKubectlNamespaceCallback( [('default', 'Active'), ('composer-1-2-3-airflow-4-5-6-aabbccdd', 'Active')])) # Scenario // 3 active namespaces. fake_exec.AddCallback( 1, self.MakeFetchKubectlNamespaceCallback( [('default', 'Active'), ('composer-1-2-3-airflow-4-5-6-aabbccdd', 'Active'), ('composer-1-2-3-airflow-4-5-6-beeffeed', 'Active')])) # Scenario // 3 namespaces; # 2 active namespaces, but most recent namespace in 'Terminating' state. fake_exec.AddCallback( 2, self.MakeFetchKubectlNamespaceCallback( [('default', 'Active'), ('composer-1-2-3-airflow-4-5-6-aabbccdd', 'Active'), ('composer-1-2-3-airflow-4-5-6-beeffeed', 'Terminating')])) # Scenario // 3 namespaces, but none match image-version prefix. fake_exec.AddCallback( 3, self.MakeFetchKubectlNamespaceCallback([('foo', 'Active'), ('bar', 'Terminating'), ('baz', 'Active')])) self.assertEqual('composer-1-2-3-airflow-4-5-6-aabbccdd', command_util.FetchKubectlNamespace(env_image_version)) self.assertEqual('composer-1-2-3-airflow-4-5-6-beeffeed', command_util.FetchKubectlNamespace(env_image_version)) self.assertEqual('composer-1-2-3-airflow-4-5-6-aabbccdd', command_util.FetchKubectlNamespace(env_image_version)) self.assertEqual('default', command_util.FetchKubectlNamespace(env_image_version)) fake_exec.Verify()
def Run(self, args): self.DeprecationWarningPrompt(args) self.CheckForRequiredCmdArgs(args) running_state = (api_util.GetMessagesModule( release_track=self.ReleaseTrack()).Environment. StateValueValuesEnum.RUNNING) env_ref = args.CONCEPTS.environment.Parse() env_obj = environments_api_util.Get(env_ref, release_track=self.ReleaseTrack()) if env_obj.state != running_state: raise command_util.Error( 'Cannot execute subcommand for environment in state {}. ' 'Must be RUNNING.'.format(env_obj.state)) cluster_id = env_obj.config.gkeCluster cluster_location_id = command_util.ExtractGkeClusterLocationId(env_obj) tty = 'no-tty' not in args with command_util.TemporaryKubeconfig(cluster_location_id, cluster_id): try: image_version = env_obj.config.softwareConfig.imageVersion airflow_version = self._ExtractAirflowVersion(image_version) self.CheckSubcommandAirflowSupport(args, airflow_version) self.CheckSubcommandNestedAirflowSupport(args, airflow_version) kubectl_ns = command_util.FetchKubectlNamespace(image_version) pod = command_util.GetGkePod(pod_substr=WORKER_POD_SUBSTR, kubectl_namespace=kubectl_ns) log.status.Print( 'Executing within the following Kubernetes cluster namespace: ' '{}'.format(kubectl_ns)) self.BypassConfirmationPrompt(args, airflow_version) kubectl_args = ['exec', pod, '--stdin'] if tty: kubectl_args.append('--tty') kubectl_args.extend([ '--container', WORKER_CONTAINER, '--', 'airflow', args.subcommand ]) if args.subcommand_nested: kubectl_args.append(args.subcommand_nested) if args.cmd_args: kubectl_args.extend(args.cmd_args) command_util.RunKubectlCommand( command_util.AddKubectlNamespace(kubectl_ns, kubectl_args), out_func=log.out.Print) except command_util.KubectlError as e: raise self.ConvertKubectlError(e, env_obj)
def Run(self, args): self.DeprecationWarningPrompt(args) running_state = ( api_util.GetMessagesModule(release_track=self.ReleaseTrack()) .Environment.StateValueValuesEnum.RUNNING) env_ref = args.CONCEPTS.environment.Parse() env_obj = environments_api_util.Get( env_ref, release_track=self.ReleaseTrack()) if env_obj.state != running_state: raise command_util.Error( 'Cannot execute subcommand for environment in state {}. ' 'Must be RUNNING.'.format(env_obj.state)) cluster_id = env_obj.config.gkeCluster cluster_location_id = command_util.ExtractGkeClusterLocationId(env_obj) with command_util.TemporaryKubeconfig(cluster_location_id, cluster_id): try: kubectl_ns = command_util.FetchKubectlNamespace( env_obj.config.softwareConfig.imageVersion) pod = command_util.GetGkePod( pod_substr=WORKER_POD_SUBSTR, kubectl_namespace=kubectl_ns) log.status.Print( 'Executing within the following kubectl namespace: {}'.format( kubectl_ns)) self.BypassConfirmationPrompt(args) kubectl_args = [ 'exec', pod, '-tic', WORKER_CONTAINER, 'airflow', args.subcommand ] if args.cmd_args: # Add '--' to the argument list so kubectl won't eat the command args. kubectl_args.extend(['--'] + args.cmd_args) command_util.RunKubectlCommand( command_util.AddKubectlNamespace(kubectl_ns, kubectl_args), out_func=log.status.Print) except command_util.KubectlError as e: raise self.ConvertKubectlError(e, env_obj)
def Run(self, args): env_ref = args.CONCEPTS.environment.Parse() env_obj = environments_api_util.Get(env_ref, release_track=self.ReleaseTrack()) cluster_id = env_obj.config.gkeCluster cluster_location_id = command_util.ExtractGkeClusterLocationId(env_obj) tty = 'no-tty' not in args with command_util.TemporaryKubeconfig(cluster_location_id, cluster_id): try: image_version = env_obj.config.softwareConfig.imageVersion kubectl_ns = command_util.FetchKubectlNamespace(image_version) pod = command_util.GetGkePod(pod_substr=WORKER_POD_SUBSTR, kubectl_namespace=kubectl_ns) log.status.Print( 'Executing within the following Kubernetes cluster namespace: ' '{}'.format(kubectl_ns)) kubectl_args = ['exec', pod, '--stdin'] if tty: kubectl_args.append('--tty') kubectl_args.extend(['--container', WORKER_CONTAINER, '--']) if args.tree: kubectl_args.extend( ['python', '-m', 'pipdeptree', '--warn']) else: kubectl_args.extend(['python', '-m', 'pip', 'list']) command_util.RunKubectlCommand( command_util.AddKubectlNamespace(kubectl_ns, kubectl_args), out_func=log.out.Print) except command_util.KubectlError as e: raise self.ConvertKubectlError(e, env_obj)