def Run(self, args): running_state = (api_util.GetMessagesModule().Environment. StateValueValuesEnum.RUNNING) env_ref = args.CONCEPTS.environment.Parse() env_obj = environments_api_util.Get(env_ref) 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): pod = command_util.GetGkePod(pod_substr=WORKER_POD_SUBSTR) 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(kubectl_args, out_func=log.status.Print)
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 testRunKubectlCommand_KubectlError(self, exec_mock, tmp_kubeconfig_mock): kubectl_args = ['exec', '-it', 'airflow-worker12345', 'bash'] fake_exec = kubectl_util.FakeExec() exec_mock.side_effect = fake_exec tmp_kubeconfig_mock.side_effect = self.FakeTemporaryKubeconfig # kubectl returns with nonzero exit code fake_exec.AddCallback(0, lambda *_, **__: 1) with self.AssertRaisesExceptionMatches( command_util.KubectlError, 'kubectl returned non-zero status code'): command_util.RunKubectlCommand(kubectl_args) fake_exec.Verify()
def testRunKubectlCommand_Success(self, exec_mock, tmp_kubeconfig_mock): kubectl_args = ['exec', '-it', 'airflow-worker12345', 'bash'] expected_args = command_util.AddKubectlNamespace( self.TEST_KUBECTL_DEFAULT_NAMESPACE, [self.TEST_KUBECTL_PATH] + kubectl_args) fake_exec = kubectl_util.FakeExec() exec_mock.side_effect = fake_exec tmp_kubeconfig_mock.side_effect = self.FakeTemporaryKubeconfig fake_exec.AddCallback( 0, lambda args, **_: self.assertEqual(expected_args, args)) command_util.RunKubectlCommand( kubectl_args, namespace=self.TEST_KUBECTL_DEFAULT_NAMESPACE) fake_exec.Verify()
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 GetConfigConnectorIdentityForCluster(location, cluster_id, project_id): """Get Config Connector identity for the given cluster.""" with composer_util.TemporaryKubeconfig(location, cluster_id): output = io.StringIO() composer_util.RunKubectlCommand([ 'get', 'ConfigConnectorContext', '-o', 'jsonpath="{.items[0].spec.googleServiceAccount}"' ], out_func=output.write, err_func=log.err.write, namespace='config-control') identity = output.getvalue().replace('"', '') log.status.Print( 'Default Config Connector identity: [{identity}].\n' '\n' 'For example, to give Config Connector permission to manage Google Cloud resources in the same project:\n' 'gcloud projects add-iam-policy-binding {project_id} \\\n' ' --member \"serviceAccount:{identity}\" \\\n' ' --role \"roles/owner\" \\\n' ' --project {project_id}\n'.format(identity=identity, project_id=project_id))
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)
def testRunKubectlCommandSearchesEntirePath( self, exec_mock, tmp_kubeconfig_mock, config_paths_mock, find_executable_mock): kubectl_args = ['exec', '-it', 'airflow-worker12345', 'bash'] fake_exec = kubectl_util.FakeExec() exec_mock.side_effect = fake_exec tmp_kubeconfig_mock.side_effect = self.FakeTemporaryKubeconfig fake_exec.AddCallback(0, lambda *_, **__: 0) config_paths_mock.sdk_bin_path = self.TEST_GCLOUD_PATH # Find the executable only when searching entire path, not just SDK location def _FakeFindExecutableOnFullPath(executable, path=None, **_): if executable == 'kubectl': if path is None: return base.KubectlShellingUnitTest.TEST_KUBECTL_PATH return None find_executable_mock.side_effect = _FakeFindExecutableOnFullPath # An error would be thrown if kubectl path was not found command_util.RunKubectlCommand(kubectl_args) fake_exec.Verify()