mirror of
https://github.com/k3s-io/kubernetes.git
synced 2025-07-23 19:56:01 +00:00
Wire --filename flag to exec
This commit is contained in:
parent
39ed64ec4c
commit
9dac1699bf
@ -45,10 +45,10 @@ import (
|
|||||||
var (
|
var (
|
||||||
execExample = templates.Examples(i18n.T(`
|
execExample = templates.Examples(i18n.T(`
|
||||||
# Get output from running 'date' command from pod mypod, using the first container by default
|
# Get output from running 'date' command from pod mypod, using the first container by default
|
||||||
kubectl exec mypod date
|
kubectl exec mypod -- date
|
||||||
|
|
||||||
# Get output from running 'date' command in ruby-container from pod mypod
|
# Get output from running 'date' command in ruby-container from pod mypod
|
||||||
kubectl exec mypod -c ruby-container date
|
kubectl exec mypod -c ruby-container -- date
|
||||||
|
|
||||||
# Switch to raw terminal mode, sends stdin to 'bash' in ruby-container from pod mypod
|
# Switch to raw terminal mode, sends stdin to 'bash' in ruby-container from pod mypod
|
||||||
# and sends stdout/stderr from 'bash' back to the client
|
# and sends stdout/stderr from 'bash' back to the client
|
||||||
@ -62,15 +62,14 @@ var (
|
|||||||
kubectl exec mypod -i -t -- ls -t /usr
|
kubectl exec mypod -i -t -- ls -t /usr
|
||||||
|
|
||||||
# Get output from running 'date' command from the first pod of the deployment mydeployment, using the first container by default
|
# Get output from running 'date' command from the first pod of the deployment mydeployment, using the first container by default
|
||||||
kubectl exec deploy/mydeployment date
|
kubectl exec deploy/mydeployment -- date
|
||||||
|
|
||||||
# Get output from running 'date' command from the first pod of the service myservice, using the first container by default
|
# Get output from running 'date' command from the first pod of the service myservice, using the first container by default
|
||||||
kubectl exec svc/myservice date
|
kubectl exec svc/myservice -- date
|
||||||
`))
|
`))
|
||||||
)
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
execUsageStr = "expected 'exec (POD | TYPE/NAME) COMMAND [ARG1] [ARG2] ... [ARGN]'.\nPOD or TYPE/NAME and COMMAND are required arguments for the exec command"
|
|
||||||
defaultPodExecTimeout = 60 * time.Second
|
defaultPodExecTimeout = 60 * time.Second
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -96,6 +95,7 @@ func NewCmdExec(f cmdutil.Factory, streams genericclioptions.IOStreams) *cobra.C
|
|||||||
},
|
},
|
||||||
}
|
}
|
||||||
cmdutil.AddPodRunningTimeoutFlag(cmd, defaultPodExecTimeout)
|
cmdutil.AddPodRunningTimeoutFlag(cmd, defaultPodExecTimeout)
|
||||||
|
cmdutil.AddJsonFilenameFlag(cmd.Flags(), &options.FilenameOptions.Filenames, "to use to exec into the resource")
|
||||||
// TODO support UID
|
// TODO support UID
|
||||||
cmd.Flags().StringVarP(&options.ContainerName, "container", "c", options.ContainerName, "Container name. If omitted, the first container in the pod will be chosen")
|
cmd.Flags().StringVarP(&options.ContainerName, "container", "c", options.ContainerName, "Container name. If omitted, the first container in the pod will be chosen")
|
||||||
cmd.Flags().BoolVarP(&options.Stdin, "stdin", "i", options.Stdin, "Pass stdin to the container")
|
cmd.Flags().BoolVarP(&options.Stdin, "stdin", "i", options.Stdin, "Pass stdin to the container")
|
||||||
@ -146,9 +146,11 @@ type StreamOptions struct {
|
|||||||
// ExecOptions declare the arguments accepted by the Exec command
|
// ExecOptions declare the arguments accepted by the Exec command
|
||||||
type ExecOptions struct {
|
type ExecOptions struct {
|
||||||
StreamOptions
|
StreamOptions
|
||||||
|
resource.FilenameOptions
|
||||||
|
|
||||||
ResourceName string
|
ResourceName string
|
||||||
Command []string
|
Command []string
|
||||||
|
EnforceNamespace bool
|
||||||
|
|
||||||
ParentCommandName string
|
ParentCommandName string
|
||||||
EnableSuggestedCmdUsage bool
|
EnableSuggestedCmdUsage bool
|
||||||
@ -166,17 +168,22 @@ type ExecOptions struct {
|
|||||||
|
|
||||||
// Complete verifies command line arguments and loads data from the command environment
|
// Complete verifies command line arguments and loads data from the command environment
|
||||||
func (p *ExecOptions) Complete(f cmdutil.Factory, cmd *cobra.Command, argsIn []string, argsLenAtDash int) error {
|
func (p *ExecOptions) Complete(f cmdutil.Factory, cmd *cobra.Command, argsIn []string, argsLenAtDash int) error {
|
||||||
// Let kubectl exec follow rules for `--`, see #13004 issue
|
if len(argsIn) > 0 && argsLenAtDash != 0 {
|
||||||
if len(argsIn) == 0 || argsLenAtDash == 0 {
|
p.ResourceName = argsIn[0]
|
||||||
return cmdutil.UsageErrorf(cmd, execUsageStr)
|
}
|
||||||
|
if argsLenAtDash > -1 {
|
||||||
|
p.Command = argsIn[argsLenAtDash:]
|
||||||
|
} else if len(argsIn) > 1 {
|
||||||
|
fmt.Fprint(p.ErrOut, "kubectl exec [POD] [COMMAND] is DEPRECATED and will be removed in a future version. Use kubectl kubectl exec [POD] -- [COMMAND] instead.\n")
|
||||||
|
p.Command = argsIn[1:]
|
||||||
|
} else if len(argsIn) > 0 && len(p.FilenameOptions.Filenames) != 0 {
|
||||||
|
fmt.Fprint(p.ErrOut, "kubectl exec [POD] [COMMAND] is DEPRECATED and will be removed in a future version. Use kubectl kubectl exec [POD] -- [COMMAND] instead.\n")
|
||||||
|
p.Command = argsIn[0:]
|
||||||
|
p.ResourceName = ""
|
||||||
}
|
}
|
||||||
|
|
||||||
p.ResourceName = argsIn[0]
|
|
||||||
p.Command = argsIn[1:]
|
|
||||||
|
|
||||||
var err error
|
var err error
|
||||||
|
p.Namespace, p.EnforceNamespace, err = f.ToRawKubeConfigLoader().Namespace()
|
||||||
p.Namespace, _, err = f.ToRawKubeConfigLoader().Namespace()
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
@ -215,8 +222,8 @@ func (p *ExecOptions) Complete(f cmdutil.Factory, cmd *cobra.Command, argsIn []s
|
|||||||
|
|
||||||
// Validate checks that the provided exec options are specified.
|
// Validate checks that the provided exec options are specified.
|
||||||
func (p *ExecOptions) Validate() error {
|
func (p *ExecOptions) Validate() error {
|
||||||
if len(p.PodName) == 0 && len(p.ResourceName) == 0 {
|
if len(p.PodName) == 0 && len(p.ResourceName) == 0 && len(p.FilenameOptions.Filenames) == 0 {
|
||||||
return fmt.Errorf("pod or type/name must be specified")
|
return fmt.Errorf("pod, type/name or --filename must be specified")
|
||||||
}
|
}
|
||||||
if len(p.Command) == 0 {
|
if len(p.Command) == 0 {
|
||||||
return fmt.Errorf("you must specify at least one command for the container")
|
return fmt.Errorf("you must specify at least one command for the container")
|
||||||
@ -293,7 +300,11 @@ func (p *ExecOptions) Run() error {
|
|||||||
} else {
|
} else {
|
||||||
builder := p.Builder().
|
builder := p.Builder().
|
||||||
WithScheme(scheme.Scheme, scheme.Scheme.PrioritizedVersionsAllGroups()...).
|
WithScheme(scheme.Scheme, scheme.Scheme.PrioritizedVersionsAllGroups()...).
|
||||||
NamespaceParam(p.Namespace).DefaultNamespace().ResourceNames("pods", p.ResourceName)
|
FilenameParam(p.EnforceNamespace, &p.FilenameOptions).
|
||||||
|
NamespaceParam(p.Namespace).DefaultNamespace()
|
||||||
|
if len(p.ResourceName) > 0 {
|
||||||
|
builder = builder.ResourceNames("pods", p.ResourceName)
|
||||||
|
}
|
||||||
|
|
||||||
obj, err := builder.Do().Object()
|
obj, err := builder.Do().Object()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -103,7 +103,7 @@ func TestPodAndContainer(t *testing.T) {
|
|||||||
{
|
{
|
||||||
p: &ExecOptions{},
|
p: &ExecOptions{},
|
||||||
args: []string{"foo", "cmd"},
|
args: []string{"foo", "cmd"},
|
||||||
argsLenAtDash: -1,
|
argsLenAtDash: 1,
|
||||||
expectedPod: "foo",
|
expectedPod: "foo",
|
||||||
expectedArgs: []string{"cmd"},
|
expectedArgs: []string{"cmd"},
|
||||||
name: "cmd, w/o flags",
|
name: "cmd, w/o flags",
|
||||||
@ -112,7 +112,7 @@ func TestPodAndContainer(t *testing.T) {
|
|||||||
{
|
{
|
||||||
p: &ExecOptions{},
|
p: &ExecOptions{},
|
||||||
args: []string{"foo", "cmd"},
|
args: []string{"foo", "cmd"},
|
||||||
argsLenAtDash: 1,
|
argsLenAtDash: -1,
|
||||||
expectedPod: "foo",
|
expectedPod: "foo",
|
||||||
expectedArgs: []string{"cmd"},
|
expectedArgs: []string{"cmd"},
|
||||||
name: "cmd, cmd is behind dash",
|
name: "cmd, cmd is behind dash",
|
||||||
|
@ -81,14 +81,14 @@ run_kubectl_exec_resource_name_tests() {
|
|||||||
# POD test-pod is exists this is shouldn't have output not found
|
# POD test-pod is exists this is shouldn't have output not found
|
||||||
kube::test::if_has_not_string "${output_message}" 'not found'
|
kube::test::if_has_not_string "${output_message}" 'not found'
|
||||||
# These must be pass the validate
|
# These must be pass the validate
|
||||||
kube::test::if_has_not_string "${output_message}" 'pod or type/name must be specified'
|
kube::test::if_has_not_string "${output_message}" 'pod, type/name or --filename must be specified'
|
||||||
|
|
||||||
output_message=$(! kubectl exec replicaset/frontend date 2>&1)
|
output_message=$(! kubectl exec replicaset/frontend date 2>&1)
|
||||||
# Replicaset frontend is valid and exists will select the first pod.
|
# Replicaset frontend is valid and exists will select the first pod.
|
||||||
# and Shouldn't have output not found
|
# and Shouldn't have output not found
|
||||||
kube::test::if_has_not_string "${output_message}" 'not found'
|
kube::test::if_has_not_string "${output_message}" 'not found'
|
||||||
# These must be pass the validate
|
# These must be pass the validate
|
||||||
kube::test::if_has_not_string "${output_message}" 'pod or type/name must be specified'
|
kube::test::if_has_not_string "${output_message}" 'pod, type/name or --filename must be specified'
|
||||||
|
|
||||||
# Clean up
|
# Clean up
|
||||||
kubectl delete pods/test-pod
|
kubectl delete pods/test-pod
|
||||||
|
Loading…
Reference in New Issue
Block a user