kubectl config set-credentials: Add InteractiveMode and ProvideClusterInfo flags

`set-credentials` command can also be used to config kubeconfig with credentials
exec plugins. However, there is no flag provided by this command to set
`InteractiveMode` and `ProvideClusterInfo` fields in credentials exec plugins.
Since `InteractiveMode` is required field, this makes the command's output
is incomplete and invalid. This PR introduces 2 new flags in set-credentials
command to let users can configure these 2 fields in credentials exec plugins,
especially the one `InteractiveMode` which is required.
This commit is contained in:
Arda Güçlü 2023-11-23 15:32:32 +03:00
parent d61cbac69a
commit b088e65007
2 changed files with 118 additions and 9 deletions

View File

@ -279,6 +279,91 @@ func TestEmbedClientCert(t *testing.T) {
test.run(t)
}
func TestExecPlugin(t *testing.T) {
fakeCertFile, _ := os.CreateTemp(os.TempDir(), "")
defer utiltesting.CloseAndRemove(t, fakeCertFile)
fakeData := []byte("fake-data")
err := os.WriteFile(fakeCertFile.Name(), fakeData, 0600)
if err != nil {
t.Errorf("unexpected error %v", err)
}
expectedConfig := newRedFederalCowHammerConfig()
authInfo := clientcmdapi.NewAuthInfo()
authInfo.Exec = &clientcmdapi.ExecConfig{
Command: "example-client-go-exec-plugin",
Args: []string{"arg1", "arg2"},
Env: []clientcmdapi.ExecEnvVar{
{
Name: "FOO",
Value: "bar",
},
},
APIVersion: "client.authentication.k8s.io/v1",
ProvideClusterInfo: false,
InteractiveMode: "Never",
}
expectedConfig.AuthInfos["cred-exec-user"] = authInfo
test := configCommandTest{
args: []string{
"set-credentials",
"cred-exec-user",
"--exec-api-version=client.authentication.k8s.io/v1",
"--exec-command=example-client-go-exec-plugin",
"--exec-arg=arg1,arg2",
"--exec-env=FOO=bar",
"--exec-interactive-mode=Never",
},
startingConfig: newRedFederalCowHammerConfig(),
expectedConfig: expectedConfig,
}
test.run(t)
}
func TestExecPluginWithProveClusterInfo(t *testing.T) {
fakeCertFile, _ := os.CreateTemp(os.TempDir(), "")
defer utiltesting.CloseAndRemove(t, fakeCertFile)
fakeData := []byte("fake-data")
err := os.WriteFile(fakeCertFile.Name(), fakeData, 0600)
if err != nil {
t.Errorf("unexpected error %v", err)
}
expectedConfig := newRedFederalCowHammerConfig()
authInfo := clientcmdapi.NewAuthInfo()
authInfo.Exec = &clientcmdapi.ExecConfig{
Command: "example-client-go-exec-plugin",
Args: []string{"arg1", "arg2"},
Env: []clientcmdapi.ExecEnvVar{
{
Name: "FOO",
Value: "bar",
},
},
APIVersion: "client.authentication.k8s.io/v1",
ProvideClusterInfo: true,
InteractiveMode: "Always",
}
expectedConfig.AuthInfos["cred-exec-user"] = authInfo
test := configCommandTest{
args: []string{
"set-credentials",
"cred-exec-user",
"--exec-api-version=client.authentication.k8s.io/v1",
"--exec-command=example-client-go-exec-plugin",
"--exec-arg=arg1,arg2",
"--exec-env=FOO=bar",
"--exec-interactive-mode=Always",
"--exec-provide-cluster-info=true",
},
startingConfig: newRedFederalCowHammerConfig(),
expectedConfig: expectedConfig,
}
test.run(t)
}
func TestEmbedClientKey(t *testing.T) {
fakeKeyFile, _ := os.CreateTemp(os.TempDir(), "")
defer utiltesting.CloseAndRemove(t, fakeKeyFile)

View File

@ -48,21 +48,25 @@ type setCredentialsOptions struct {
authProviderArgs map[string]string
authProviderArgsToRemove []string
execCommand cliflag.StringFlag
execAPIVersion cliflag.StringFlag
execArgs []string
execEnv map[string]string
execEnvToRemove []string
execCommand cliflag.StringFlag
execAPIVersion cliflag.StringFlag
execInteractiveMode cliflag.StringFlag
execProvideClusterInfo bool
execArgs []string
execEnv map[string]string
execEnvToRemove []string
}
const (
flagAuthProvider = "auth-provider"
flagAuthProviderArg = "auth-provider-arg"
flagExecCommand = "exec-command"
flagExecAPIVersion = "exec-api-version"
flagExecArg = "exec-arg"
flagExecEnv = "exec-env"
flagExecCommand = "exec-command"
flagExecAPIVersion = "exec-api-version"
flagExecArg = "exec-arg"
flagExecEnv = "exec-env"
flagExecInteractiveMode = "exec-interactive-mode"
flagExecProvideClusterInfo = "exec-provide-cluster-info"
)
var (
@ -105,6 +109,9 @@ var (
# Enable new exec auth plugin for the "cluster-admin" entry
kubectl config set-credentials cluster-admin --exec-command=/path/to/the/executable --exec-api-version=client.authentication.k8s.io/v1beta1
# Enable new exec auth plugin for the "cluster-admin" entry with interactive mode
kubectl config set-credentials cluster-admin --exec-command=/path/to/the/executable --exec-api-version=client.authentication.k8s.io/v1beta1 --exec-interactive-mode=Never
# Define new exec auth plugin arguments for the "cluster-admin" entry
kubectl config set-credentials cluster-admin --exec-arg=arg1 --exec-arg=arg2
@ -179,6 +186,8 @@ func newCmdConfigSetCredentials(out io.Writer, options *setCredentialsOptions) *
cmd.Flags().StringSlice(flagAuthProviderArg, nil, "'key=value' arguments for the auth provider")
cmd.Flags().Var(&options.execCommand, flagExecCommand, "Command for the exec credential plugin for the user entry in kubeconfig")
cmd.Flags().Var(&options.execAPIVersion, flagExecAPIVersion, "API version of the exec credential plugin for the user entry in kubeconfig")
cmd.Flags().Var(&options.execInteractiveMode, flagExecInteractiveMode, "InteractiveMode of the exec credentials plugin for the user entry in kubeconfig")
cmd.Flags().BoolVar(&options.execProvideClusterInfo, flagExecProvideClusterInfo, options.execProvideClusterInfo, "ProvideClusterInfo of the exec credentials plugin for the user entry in kubeconfig")
cmd.Flags().StringSlice(flagExecArg, nil, "New arguments for the exec credential plugin command for the user entry in kubeconfig")
cmd.Flags().StringArray(flagExecEnv, nil, "'key=value' environment values for the exec credential plugin")
f := cmd.Flags().VarPF(&options.embedCertData, clientcmd.FlagEmbedCerts, "", "Embed client cert/key for the user entry in kubeconfig")
@ -293,6 +302,8 @@ func (o *setCredentialsOptions) modifyAuthInfo(existingAuthInfo clientcmdapi.Aut
// explicitly reset exec arguments
modifiedAuthInfo.Exec.Args = nil
}
modifiedAuthInfo.Exec.ProvideClusterInfo = o.execProvideClusterInfo
}
// modify next values only if Exec exists, ignore these changes otherwise
@ -306,6 +317,10 @@ func (o *setCredentialsOptions) modifyAuthInfo(existingAuthInfo clientcmdapi.Aut
modifiedAuthInfo.Exec.Args = o.execArgs
}
if o.execInteractiveMode.Provided() {
modifiedAuthInfo.Exec.InteractiveMode = clientcmdapi.ExecInteractiveMode(o.execInteractiveMode.Value())
}
// iterate over the existing exec env values and remove the specified
if o.execEnvToRemove != nil {
newExecEnv := []clientcmdapi.ExecEnvVar{}
@ -437,5 +452,14 @@ func (o setCredentialsOptions) validate() error {
}
}
if o.execInteractiveMode.Provided() {
interactiveMode := o.execInteractiveMode.Value()
if interactiveMode != string(clientcmdapi.IfAvailableExecInteractiveMode) &&
interactiveMode != string(clientcmdapi.AlwaysExecInteractiveMode) &&
interactiveMode != string(clientcmdapi.NeverExecInteractiveMode) {
return fmt.Errorf("invalid interactive mode type, can be only IfAvailable, Never, Always")
}
}
return nil
}