Introduces config cmd's for set-credentials and get-credentials
to manage authentication information for clusters. Includes username/password, certificate and token options. Change-Id: If95e5bbf5c3ddc4732465e81de407d5ad416e8f2
This commit is contained in:
parent
8c6ebb66d9
commit
36a302fce1
@ -13,13 +13,15 @@ func NewConfigCommand(rootSettings *environment.AirshipCTLSettings) *cobra.Comma
|
|||||||
DisableFlagsInUseLine: true,
|
DisableFlagsInUseLine: true,
|
||||||
Short: ("Modify airshipctl config files"),
|
Short: ("Modify airshipctl config files"),
|
||||||
Long: (`Modify airshipctl config files using subcommands
|
Long: (`Modify airshipctl config files using subcommands
|
||||||
like "airshipctl config set-current-context my-context" `),
|
like "airshipctl config set-context --current-context my-context" `),
|
||||||
}
|
}
|
||||||
configRootCmd.AddCommand(NewCmdConfigSetCluster(rootSettings))
|
configRootCmd.AddCommand(NewCmdConfigSetCluster(rootSettings))
|
||||||
configRootCmd.AddCommand(NewCmdConfigGetCluster(rootSettings))
|
configRootCmd.AddCommand(NewCmdConfigGetCluster(rootSettings))
|
||||||
configRootCmd.AddCommand(NewCmdConfigSetContext(rootSettings))
|
configRootCmd.AddCommand(NewCmdConfigSetContext(rootSettings))
|
||||||
configRootCmd.AddCommand(NewCmdConfigGetContext(rootSettings))
|
configRootCmd.AddCommand(NewCmdConfigGetContext(rootSettings))
|
||||||
configRootCmd.AddCommand(NewCmdConfigInit(rootSettings))
|
configRootCmd.AddCommand(NewCmdConfigInit(rootSettings))
|
||||||
|
configRootCmd.AddCommand(NewCmdConfigSetAuthInfo(rootSettings))
|
||||||
|
configRootCmd.AddCommand(NewCmdConfigGetAuthInfo(rootSettings))
|
||||||
|
|
||||||
return configRootCmd
|
return configRootCmd
|
||||||
}
|
}
|
||||||
|
89
cmd/config/get_authinfo.go
Normal file
89
cmd/config/get_authinfo.go
Normal file
@ -0,0 +1,89 @@
|
|||||||
|
/*
|
||||||
|
Copyright 2014 The Kubernetes Authors.
|
||||||
|
|
||||||
|
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.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package config
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"io"
|
||||||
|
|
||||||
|
"github.com/spf13/cobra"
|
||||||
|
|
||||||
|
"opendev.org/airship/airshipctl/pkg/config"
|
||||||
|
"opendev.org/airship/airshipctl/pkg/environment"
|
||||||
|
)
|
||||||
|
|
||||||
|
var (
|
||||||
|
getAuthInfoLong = (`Display a specific user information, or all defined users if no name is provided`)
|
||||||
|
|
||||||
|
getAuthInfoExample = (`# List all the users airshipctl knows about
|
||||||
|
airshipctl config get-credential
|
||||||
|
|
||||||
|
# Display a specific user information
|
||||||
|
airshipctl config get-credential e2e`)
|
||||||
|
)
|
||||||
|
|
||||||
|
// An AuthInfo refers to a particular user for a cluster
|
||||||
|
// NewCmdConfigGetAuthInfo returns a Command instance for 'config -AuthInfo' sub command
|
||||||
|
func NewCmdConfigGetAuthInfo(rootSettings *environment.AirshipCTLSettings) *cobra.Command {
|
||||||
|
theAuthInfo := &config.AuthInfoOptions{}
|
||||||
|
getauthinfocmd := &cobra.Command{
|
||||||
|
Use: "get-credentials NAME",
|
||||||
|
Short: "Gets a user entry from the airshipctl config",
|
||||||
|
Long: getAuthInfoLong,
|
||||||
|
Example: getAuthInfoExample,
|
||||||
|
RunE: func(cmd *cobra.Command, args []string) error {
|
||||||
|
if len(args) == 1 {
|
||||||
|
theAuthInfo.Name = args[0]
|
||||||
|
}
|
||||||
|
return runGetAuthInfo(theAuthInfo, cmd.OutOrStdout(), rootSettings.Config())
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
return getauthinfocmd
|
||||||
|
}
|
||||||
|
|
||||||
|
// runGetAuthInfo performs the execution of 'config get-credentials' sub command
|
||||||
|
func runGetAuthInfo(o *config.AuthInfoOptions, out io.Writer, airconfig *config.Config) error {
|
||||||
|
if o.Name == "" {
|
||||||
|
return getAuthInfos(out, airconfig)
|
||||||
|
}
|
||||||
|
return getAuthInfo(o, out, airconfig)
|
||||||
|
}
|
||||||
|
|
||||||
|
func getAuthInfo(o *config.AuthInfoOptions, out io.Writer, airconfig *config.Config) error {
|
||||||
|
cName := o.Name
|
||||||
|
authinfo, err := airconfig.GetAuthInfo(cName)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
fmt.Fprintln(out, authinfo)
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func getAuthInfos(out io.Writer, airconfig *config.Config) error {
|
||||||
|
authinfos, err := airconfig.GetAuthInfos()
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
if len(authinfos) == 0 {
|
||||||
|
fmt.Fprintln(out, "No User credentials found in the configuration.")
|
||||||
|
}
|
||||||
|
for _, authinfo := range authinfos {
|
||||||
|
fmt.Fprintln(out, authinfo)
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
106
cmd/config/get_authinfo_test.go
Normal file
106
cmd/config/get_authinfo_test.go
Normal file
@ -0,0 +1,106 @@
|
|||||||
|
/*
|
||||||
|
Copyright 2014 The Kubernetes Authors.
|
||||||
|
|
||||||
|
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.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package config_test
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"testing"
|
||||||
|
|
||||||
|
kubeconfig "k8s.io/client-go/tools/clientcmd/api"
|
||||||
|
|
||||||
|
cmd "opendev.org/airship/airshipctl/cmd/config"
|
||||||
|
"opendev.org/airship/airshipctl/pkg/config"
|
||||||
|
"opendev.org/airship/airshipctl/pkg/environment"
|
||||||
|
"opendev.org/airship/airshipctl/testutil"
|
||||||
|
)
|
||||||
|
|
||||||
|
const (
|
||||||
|
fooAuthInfo = "AuthInfoFoo"
|
||||||
|
barAuthInfo = "AuthInfoBar"
|
||||||
|
bazAuthInfo = "AuthInfoBaz"
|
||||||
|
missingAuthInfo = "authinfoMissing"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestGetAuthInfoCmd(t *testing.T) {
|
||||||
|
conf := &config.Config{
|
||||||
|
AuthInfos: map[string]*config.AuthInfo{
|
||||||
|
fooAuthInfo: getTestAuthInfo(),
|
||||||
|
barAuthInfo: getTestAuthInfo(),
|
||||||
|
bazAuthInfo: getTestAuthInfo(),
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
settings := &environment.AirshipCTLSettings{}
|
||||||
|
settings.SetConfig(conf)
|
||||||
|
|
||||||
|
cmdTests := []*testutil.CmdTest{
|
||||||
|
{
|
||||||
|
Name: "get-credentials",
|
||||||
|
CmdLine: fmt.Sprintf("%s", fooAuthInfo),
|
||||||
|
Cmd: cmd.NewCmdConfigGetAuthInfo(settings),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Name: "get-all-credentials",
|
||||||
|
CmdLine: fmt.Sprintf("%s %s", fooAuthInfo, barAuthInfo),
|
||||||
|
Cmd: cmd.NewCmdConfigGetAuthInfo(settings),
|
||||||
|
},
|
||||||
|
// This is not implemented yet
|
||||||
|
{
|
||||||
|
Name: "get-multiple-credentials",
|
||||||
|
CmdLine: fmt.Sprintf("%s %s", fooAuthInfo, barAuthInfo),
|
||||||
|
Cmd: cmd.NewCmdConfigGetAuthInfo(settings),
|
||||||
|
},
|
||||||
|
|
||||||
|
{
|
||||||
|
Name: "missing",
|
||||||
|
CmdLine: fmt.Sprintf("%s", missingAuthInfo),
|
||||||
|
Cmd: cmd.NewCmdConfigGetAuthInfo(settings),
|
||||||
|
Error: fmt.Errorf("User %s information was not "+
|
||||||
|
"found in the configuration.", missingAuthInfo),
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, tt := range cmdTests {
|
||||||
|
testutil.RunTest(t, tt)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestNoAuthInfosGetAuthInfoCmd(t *testing.T) {
|
||||||
|
settings := &environment.AirshipCTLSettings{}
|
||||||
|
settings.SetConfig(&config.Config{})
|
||||||
|
cmdTest := &testutil.CmdTest{
|
||||||
|
Name: "no-credentials",
|
||||||
|
CmdLine: "",
|
||||||
|
Cmd: cmd.NewCmdConfigGetAuthInfo(settings),
|
||||||
|
}
|
||||||
|
testutil.RunTest(t, cmdTest)
|
||||||
|
}
|
||||||
|
|
||||||
|
func getTestAuthInfo() *config.AuthInfo {
|
||||||
|
kAuthInfo := &kubeconfig.AuthInfo{
|
||||||
|
Username: "dummy_user",
|
||||||
|
Password: "dummy_password",
|
||||||
|
ClientCertificate: "dummy_certificate",
|
||||||
|
ClientKey: "dummy_key",
|
||||||
|
Token: "dummy_token",
|
||||||
|
}
|
||||||
|
|
||||||
|
newAuthInfo := &config.AuthInfo{}
|
||||||
|
newAuthInfo.SetKubeAuthInfo(kAuthInfo)
|
||||||
|
|
||||||
|
return newAuthInfo
|
||||||
|
}
|
162
cmd/config/set_authinfo.go
Normal file
162
cmd/config/set_authinfo.go
Normal file
@ -0,0 +1,162 @@
|
|||||||
|
/*
|
||||||
|
Copyright 2016 The Kubernetes Authors.
|
||||||
|
|
||||||
|
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.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package config
|
||||||
|
|
||||||
|
import (
|
||||||
|
"errors"
|
||||||
|
"fmt"
|
||||||
|
|
||||||
|
"github.com/spf13/cobra"
|
||||||
|
|
||||||
|
"opendev.org/airship/airshipctl/pkg/config"
|
||||||
|
"opendev.org/airship/airshipctl/pkg/environment"
|
||||||
|
"opendev.org/airship/airshipctl/pkg/log"
|
||||||
|
)
|
||||||
|
|
||||||
|
var (
|
||||||
|
setAuthInfoLong = fmt.Sprintf(`Sets a user entry in airshipctl config
|
||||||
|
Specifying a name that already exists will merge new fields on top of existing values.
|
||||||
|
|
||||||
|
Client-certificate flags:
|
||||||
|
--%v=certfile --%v=keyfile
|
||||||
|
|
||||||
|
Bearer token flags:
|
||||||
|
--%v=bearer_token
|
||||||
|
|
||||||
|
Basic auth flags:
|
||||||
|
--%v=basic_user --%v=basic_password
|
||||||
|
|
||||||
|
Bearer token and basic auth are mutually exclusive.`,
|
||||||
|
config.FlagCertFile,
|
||||||
|
config.FlagKeyFile,
|
||||||
|
config.FlagBearerToken,
|
||||||
|
config.FlagUsername,
|
||||||
|
config.FlagPassword)
|
||||||
|
|
||||||
|
setAuthInfoExample = fmt.Sprintf(`
|
||||||
|
# Set only the "client-key" field on the "cluster-admin"
|
||||||
|
# entry, without touching other values:
|
||||||
|
airshipctl config set-credentials cluster-admin --%v=~/.kube/admin.key
|
||||||
|
|
||||||
|
# Set basic auth for the "cluster-admin" entry
|
||||||
|
airshipctl config set-credentials cluster-admin --%v=admin --%v=uXFGweU9l35qcif
|
||||||
|
|
||||||
|
# Embed client certificate data in the "cluster-admin" entry
|
||||||
|
airshipctl config set-credentials cluster-admin --%v=~/.kube/admin.crt --%v=true`,
|
||||||
|
config.FlagUsername,
|
||||||
|
config.FlagUsername,
|
||||||
|
config.FlagPassword,
|
||||||
|
config.FlagCertFile,
|
||||||
|
config.FlagEmbedCerts,
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
|
// NewCmdConfigSetAuthInfo creates a command object for the "set-credentials" action, which
|
||||||
|
// defines a new AuthInfo airship config.
|
||||||
|
func NewCmdConfigSetAuthInfo(rootSettings *environment.AirshipCTLSettings) *cobra.Command {
|
||||||
|
theAuthInfo := &config.AuthInfoOptions{}
|
||||||
|
|
||||||
|
setauthinfo := &cobra.Command{
|
||||||
|
Use: "set-credentials NAME",
|
||||||
|
Short: "Sets a user entry in the airshipctl config",
|
||||||
|
Long: setAuthInfoLong,
|
||||||
|
Example: setAuthInfoExample,
|
||||||
|
Args: cobra.ExactArgs(1),
|
||||||
|
RunE: func(cmd *cobra.Command, args []string) error {
|
||||||
|
theAuthInfo.Name = args[0]
|
||||||
|
modified, err := runSetAuthInfo(theAuthInfo, rootSettings.Config())
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
if modified {
|
||||||
|
fmt.Fprintf(cmd.OutOrStdout(), "User information %q modified.\n", theAuthInfo.Name)
|
||||||
|
} else {
|
||||||
|
fmt.Fprintf(cmd.OutOrStdout(), "User information %q created.\n", theAuthInfo.Name)
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
err := suInitFlags(theAuthInfo, setauthinfo)
|
||||||
|
if err != nil {
|
||||||
|
log.Fatal(err)
|
||||||
|
}
|
||||||
|
return setauthinfo
|
||||||
|
}
|
||||||
|
|
||||||
|
func suInitFlags(o *config.AuthInfoOptions, setauthinfo *cobra.Command) error {
|
||||||
|
setauthinfo.Flags().StringVar(&o.ClientCertificate, config.FlagCertFile, o.ClientCertificate,
|
||||||
|
"Path to "+config.FlagCertFile+" file for the user entry in airshipctl")
|
||||||
|
err := setauthinfo.MarkFlagFilename(config.FlagCertFile)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
setauthinfo.Flags().StringVar(&o.ClientKey, config.FlagKeyFile, o.ClientKey,
|
||||||
|
"Path to "+config.FlagKeyFile+" file for the user entry in airshipctl")
|
||||||
|
err = setauthinfo.MarkFlagFilename(config.FlagKeyFile)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
setauthinfo.Flags().StringVar(&o.Token, config.FlagBearerToken, o.Token,
|
||||||
|
config.FlagBearerToken+" for the user entry in airshipctl")
|
||||||
|
|
||||||
|
setauthinfo.Flags().StringVar(&o.Username, config.FlagUsername, o.Username,
|
||||||
|
config.FlagUsername+" for the user entry in airshipctl")
|
||||||
|
|
||||||
|
setauthinfo.Flags().StringVar(&o.Password, config.FlagPassword, o.Password,
|
||||||
|
config.FlagPassword+" for the user entry in airshipctl")
|
||||||
|
|
||||||
|
setauthinfo.Flags().BoolVar(&o.EmbedCertData, config.FlagEmbedCerts, false,
|
||||||
|
"Embed client cert/key for the user entry in airshipctl")
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func runSetAuthInfo(o *config.AuthInfoOptions, airconfig *config.Config) (bool, error) {
|
||||||
|
authinfoWasModified := false
|
||||||
|
err := o.Validate()
|
||||||
|
if err != nil {
|
||||||
|
return authinfoWasModified, err
|
||||||
|
}
|
||||||
|
|
||||||
|
authinfoIWant := o.Name
|
||||||
|
authinfo, err := airconfig.GetAuthInfo(authinfoIWant)
|
||||||
|
if err != nil {
|
||||||
|
var cerr config.ErrMissingConfig
|
||||||
|
if !errors.As(err, &cerr) {
|
||||||
|
// An error occurred, but it wasn't a "missing" config error.
|
||||||
|
return authinfoWasModified, err
|
||||||
|
}
|
||||||
|
|
||||||
|
// authinfo didn't exist, create it
|
||||||
|
// ignoring the returned added authinfo
|
||||||
|
airconfig.AddAuthInfo(o)
|
||||||
|
} else {
|
||||||
|
// AuthInfo exists, lets update
|
||||||
|
airconfig.ModifyAuthInfo(authinfo, o)
|
||||||
|
authinfoWasModified = true
|
||||||
|
}
|
||||||
|
// Update configuration file just in time persistence approach
|
||||||
|
if err := airconfig.PersistConfig(); err != nil {
|
||||||
|
// Error that it didnt persist the changes
|
||||||
|
return authinfoWasModified, config.ErrConfigFailed{}
|
||||||
|
}
|
||||||
|
|
||||||
|
return authinfoWasModified, nil
|
||||||
|
}
|
158
cmd/config/set_authinfo_test.go
Normal file
158
cmd/config/set_authinfo_test.go
Normal file
@ -0,0 +1,158 @@
|
|||||||
|
/*
|
||||||
|
Copyright 2017 The Kubernetes Authors.
|
||||||
|
|
||||||
|
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.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package config
|
||||||
|
|
||||||
|
import (
|
||||||
|
"bytes"
|
||||||
|
"testing"
|
||||||
|
|
||||||
|
kubeconfig "k8s.io/client-go/tools/clientcmd/api"
|
||||||
|
|
||||||
|
"github.com/stretchr/testify/assert"
|
||||||
|
"github.com/stretchr/testify/require"
|
||||||
|
|
||||||
|
"opendev.org/airship/airshipctl/pkg/config"
|
||||||
|
"opendev.org/airship/airshipctl/pkg/environment"
|
||||||
|
"opendev.org/airship/airshipctl/testutil"
|
||||||
|
)
|
||||||
|
|
||||||
|
const (
|
||||||
|
testUsername = "admin@kubernetes"
|
||||||
|
testPassword = "adminPassword"
|
||||||
|
testNewname = "dummy"
|
||||||
|
testOldname = "def-user"
|
||||||
|
pwdDelta = "_changed"
|
||||||
|
)
|
||||||
|
|
||||||
|
type setAuthInfoTest struct {
|
||||||
|
description string
|
||||||
|
config *config.Config
|
||||||
|
args []string
|
||||||
|
flags []string
|
||||||
|
expected string
|
||||||
|
expectedConfig *config.Config
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestConfigSetAuthInfo(t *testing.T) {
|
||||||
|
cmdTests := []*testutil.CmdTest{
|
||||||
|
{
|
||||||
|
Name: "config-cmd-set-authinfo-with-help",
|
||||||
|
CmdLine: "--help",
|
||||||
|
Cmd: NewCmdConfigSetAuthInfo(nil),
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, tt := range cmdTests {
|
||||||
|
testutil.RunTest(t, tt)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func initConfig(t *testing.T, withUser bool, testname string) (*config.Config, *config.Config) {
|
||||||
|
conf := config.InitConfig(t)
|
||||||
|
if withUser {
|
||||||
|
kAuthInfo := kubeconfig.NewAuthInfo()
|
||||||
|
kAuthInfo.Username = testUsername
|
||||||
|
kAuthInfo.Password = testPassword
|
||||||
|
conf.KubeConfig().AuthInfos[testname] = kAuthInfo
|
||||||
|
conf.AuthInfos[testname].SetKubeAuthInfo(kAuthInfo)
|
||||||
|
}
|
||||||
|
|
||||||
|
expconf := config.InitConfig(t)
|
||||||
|
expconf.AuthInfos[testname] = config.NewAuthInfo()
|
||||||
|
|
||||||
|
expkAuthInfo := kubeconfig.NewAuthInfo()
|
||||||
|
expkAuthInfo.Username = testUsername
|
||||||
|
expkAuthInfo.Password = testPassword
|
||||||
|
expconf.KubeConfig().AuthInfos[testname] = expkAuthInfo
|
||||||
|
expconf.AuthInfos[testname].SetKubeAuthInfo(expkAuthInfo)
|
||||||
|
|
||||||
|
return conf, expconf
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestSetAuthInfo(t *testing.T) {
|
||||||
|
conf, expconf := initConfig(t, false, testNewname)
|
||||||
|
|
||||||
|
test := setAuthInfoTest{
|
||||||
|
description: "Testing 'airshipctl config set-credential' with a new user",
|
||||||
|
config: conf,
|
||||||
|
args: []string{testNewname},
|
||||||
|
flags: []string{
|
||||||
|
"--" + config.FlagUsername + "=" + testUsername,
|
||||||
|
"--" + config.FlagPassword + "=" + testPassword,
|
||||||
|
},
|
||||||
|
expected: `User information "` + testNewname + `" created.` + "\n",
|
||||||
|
expectedConfig: expconf,
|
||||||
|
}
|
||||||
|
test.run(t)
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestModifyAuthInfo(t *testing.T) {
|
||||||
|
conf, expconf := initConfig(t, true, testOldname)
|
||||||
|
expconf.AuthInfos[testOldname].KubeAuthInfo().Password = testPassword + pwdDelta
|
||||||
|
|
||||||
|
test := setAuthInfoTest{
|
||||||
|
description: "Testing 'airshipctl config set-credential' with an existing user",
|
||||||
|
config: conf,
|
||||||
|
args: []string{testOldname},
|
||||||
|
flags: []string{
|
||||||
|
"--" + config.FlagPassword + "=" + testPassword + pwdDelta,
|
||||||
|
},
|
||||||
|
expected: `User information "` + testOldname + `" modified.` + "\n",
|
||||||
|
expectedConfig: expconf,
|
||||||
|
}
|
||||||
|
test.run(t)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (test setAuthInfoTest) run(t *testing.T) {
|
||||||
|
// Get the Environment
|
||||||
|
settings := &environment.AirshipCTLSettings{}
|
||||||
|
settings.SetConfig(test.config)
|
||||||
|
|
||||||
|
buf := bytes.NewBuffer([]byte{})
|
||||||
|
|
||||||
|
cmd := NewCmdConfigSetAuthInfo(settings)
|
||||||
|
cmd.SetOutput(buf)
|
||||||
|
cmd.SetArgs(test.args)
|
||||||
|
err := cmd.Flags().Parse(test.flags)
|
||||||
|
require.NoErrorf(t, err, "unexpected error flags args to command: %v, flags: %v", err, test.flags)
|
||||||
|
|
||||||
|
// Execute the Command
|
||||||
|
// Which should Persist the File
|
||||||
|
err = cmd.Execute()
|
||||||
|
require.NoErrorf(t, err, "unexpected error executing command: %v, args: %v, flags: %v", err, test.args, test.flags)
|
||||||
|
|
||||||
|
afterRunConf := settings.Config()
|
||||||
|
|
||||||
|
// Find the AuthInfo Created or Modified
|
||||||
|
afterRunAuthInfo, err := afterRunConf.GetAuthInfo(test.args[0])
|
||||||
|
require.NoError(t, err)
|
||||||
|
require.NotNil(t, afterRunAuthInfo)
|
||||||
|
|
||||||
|
afterKauthinfo := afterRunAuthInfo.KubeAuthInfo()
|
||||||
|
require.NotNil(t, afterKauthinfo)
|
||||||
|
|
||||||
|
testKauthinfo := test.expectedConfig.KubeConfig().AuthInfos[test.args[0]]
|
||||||
|
require.NotNil(t, testKauthinfo)
|
||||||
|
|
||||||
|
assert.EqualValues(t, testKauthinfo.Username, afterKauthinfo.Username)
|
||||||
|
assert.EqualValues(t, testKauthinfo.Password, afterKauthinfo.Password)
|
||||||
|
|
||||||
|
// Test that the Return Message looks correct
|
||||||
|
if len(test.expected) != 0 {
|
||||||
|
assert.EqualValues(t, test.expected, buf.String())
|
||||||
|
}
|
||||||
|
}
|
@ -56,7 +56,7 @@ airshipctl config set-cluster e2e --%v-type=target --%v=true --%v=".airship/cert
|
|||||||
)
|
)
|
||||||
|
|
||||||
// NewCmdConfigSetCluster creates a command object for the "set-cluster" action, which
|
// NewCmdConfigSetCluster creates a command object for the "set-cluster" action, which
|
||||||
// defines a new cluster airship config.
|
// defines a new cluster airshipctl config.
|
||||||
func NewCmdConfigSetCluster(rootSettings *environment.AirshipCTLSettings) *cobra.Command {
|
func NewCmdConfigSetCluster(rootSettings *environment.AirshipCTLSettings) *cobra.Command {
|
||||||
theCluster := &config.ClusterOptions{}
|
theCluster := &config.ClusterOptions{}
|
||||||
|
|
||||||
|
@ -46,7 +46,7 @@ airshipctl config set-context e2e --%v=true`,
|
|||||||
)
|
)
|
||||||
|
|
||||||
// NewCmdConfigSetContext creates a command object for the "set-context" action, which
|
// NewCmdConfigSetContext creates a command object for the "set-context" action, which
|
||||||
// defines a new Context airship config.
|
// defines a new Context airshipctl config.
|
||||||
func NewCmdConfigSetContext(rootSettings *environment.AirshipCTLSettings) *cobra.Command {
|
func NewCmdConfigSetContext(rootSettings *environment.AirshipCTLSettings) *cobra.Command {
|
||||||
theContext := &config.ContextOptions{}
|
theContext := &config.ContextOptions{}
|
||||||
|
|
||||||
|
@ -1,16 +1,18 @@
|
|||||||
Modify airshipctl config files using subcommands
|
Modify airshipctl config files using subcommands
|
||||||
like "airshipctl config set-current-context my-context"
|
like "airshipctl config set-context --current-context my-context"
|
||||||
|
|
||||||
Usage:
|
Usage:
|
||||||
config [command]
|
config [command]
|
||||||
|
|
||||||
Available Commands:
|
Available Commands:
|
||||||
get-cluster Display a specific cluster or all defined clusters if no name is provided
|
get-cluster Display a specific cluster or all defined clusters if no name is provided
|
||||||
get-context Display a specific context, the current-context or all defined contexts if no name is provided
|
get-context Display a specific context, the current-context or all defined contexts if no name is provided
|
||||||
help Help about any command
|
get-credentials Gets a user entry from the airshipctl config
|
||||||
init Generate initial configuration files for airshipctl
|
help Help about any command
|
||||||
set-cluster Sets a cluster entry in the airshipctl config
|
init Generate initial configuration files for airshipctl
|
||||||
set-context Sets a context entry or updates current-context in the airshipctl config
|
set-cluster Sets a cluster entry in the airshipctl config
|
||||||
|
set-context Sets a context entry or updates current-context in the airshipctl config
|
||||||
|
set-credentials Sets a user entry in the airshipctl config
|
||||||
|
|
||||||
Flags:
|
Flags:
|
||||||
-h, --help help for config
|
-h, --help help for config
|
||||||
|
@ -1,16 +1,18 @@
|
|||||||
Modify airshipctl config files using subcommands
|
Modify airshipctl config files using subcommands
|
||||||
like "airshipctl config set-current-context my-context"
|
like "airshipctl config set-context --current-context my-context"
|
||||||
|
|
||||||
Usage:
|
Usage:
|
||||||
config [command]
|
config [command]
|
||||||
|
|
||||||
Available Commands:
|
Available Commands:
|
||||||
get-cluster Display a specific cluster or all defined clusters if no name is provided
|
get-cluster Display a specific cluster or all defined clusters if no name is provided
|
||||||
get-context Display a specific context, the current-context or all defined contexts if no name is provided
|
get-context Display a specific context, the current-context or all defined contexts if no name is provided
|
||||||
help Help about any command
|
get-credentials Gets a user entry from the airshipctl config
|
||||||
init Generate initial configuration files for airshipctl
|
help Help about any command
|
||||||
set-cluster Sets a cluster entry in the airshipctl config
|
init Generate initial configuration files for airshipctl
|
||||||
set-context Sets a context entry or updates current-context in the airshipctl config
|
set-cluster Sets a cluster entry in the airshipctl config
|
||||||
|
set-context Sets a context entry or updates current-context in the airshipctl config
|
||||||
|
set-credentials Sets a user entry in the airshipctl config
|
||||||
|
|
||||||
Flags:
|
Flags:
|
||||||
-h, --help help for config
|
-h, --help help for config
|
||||||
|
37
cmd/config/testdata/TestConfigSetAuthInfoGoldenOutput/config-cmd-set-authinfo-with-help.golden
vendored
Normal file
37
cmd/config/testdata/TestConfigSetAuthInfoGoldenOutput/config-cmd-set-authinfo-with-help.golden
vendored
Normal file
@ -0,0 +1,37 @@
|
|||||||
|
Sets a user entry in airshipctl config
|
||||||
|
Specifying a name that already exists will merge new fields on top of existing values.
|
||||||
|
|
||||||
|
Client-certificate flags:
|
||||||
|
--client-certificate=certfile --client-key=keyfile
|
||||||
|
|
||||||
|
Bearer token flags:
|
||||||
|
--token=bearer_token
|
||||||
|
|
||||||
|
Basic auth flags:
|
||||||
|
--username=basic_user --password=basic_password
|
||||||
|
|
||||||
|
Bearer token and basic auth are mutually exclusive.
|
||||||
|
|
||||||
|
Usage:
|
||||||
|
set-credentials NAME [flags]
|
||||||
|
|
||||||
|
Examples:
|
||||||
|
|
||||||
|
# Set only the "client-key" field on the "cluster-admin"
|
||||||
|
# entry, without touching other values:
|
||||||
|
airshipctl config set-credentials cluster-admin --username=~/.kube/admin.key
|
||||||
|
|
||||||
|
# Set basic auth for the "cluster-admin" entry
|
||||||
|
airshipctl config set-credentials cluster-admin --username=admin --password=uXFGweU9l35qcif
|
||||||
|
|
||||||
|
# Embed client certificate data in the "cluster-admin" entry
|
||||||
|
airshipctl config set-credentials cluster-admin --client-certificate=~/.kube/admin.crt --embed-certs=true
|
||||||
|
|
||||||
|
Flags:
|
||||||
|
--client-certificate string Path to client-certificate file for the user entry in airshipctl
|
||||||
|
--client-key string Path to client-key file for the user entry in airshipctl
|
||||||
|
--embed-certs Embed client cert/key for the user entry in airshipctl
|
||||||
|
-h, --help help for set-credentials
|
||||||
|
--password string password for the user entry in airshipctl
|
||||||
|
--token string token for the user entry in airshipctl
|
||||||
|
--username string username for the user entry in airshipctl
|
21
cmd/config/testdata/TestGetAuthInfoCmdGoldenOutput/get-all-credentials.golden
vendored
Normal file
21
cmd/config/testdata/TestGetAuthInfoCmdGoldenOutput/get-all-credentials.golden
vendored
Normal file
@ -0,0 +1,21 @@
|
|||||||
|
LocationOfOrigin: ""
|
||||||
|
client-certificate: dummy_certificate
|
||||||
|
client-key: dummy_key
|
||||||
|
password: dummy_password
|
||||||
|
token: dummy_token
|
||||||
|
username: dummy_user
|
||||||
|
|
||||||
|
LocationOfOrigin: ""
|
||||||
|
client-certificate: dummy_certificate
|
||||||
|
client-key: dummy_key
|
||||||
|
password: dummy_password
|
||||||
|
token: dummy_token
|
||||||
|
username: dummy_user
|
||||||
|
|
||||||
|
LocationOfOrigin: ""
|
||||||
|
client-certificate: dummy_certificate
|
||||||
|
client-key: dummy_key
|
||||||
|
password: dummy_password
|
||||||
|
token: dummy_token
|
||||||
|
username: dummy_user
|
||||||
|
|
7
cmd/config/testdata/TestGetAuthInfoCmdGoldenOutput/get-credentials.golden
vendored
Normal file
7
cmd/config/testdata/TestGetAuthInfoCmdGoldenOutput/get-credentials.golden
vendored
Normal file
@ -0,0 +1,7 @@
|
|||||||
|
LocationOfOrigin: ""
|
||||||
|
client-certificate: dummy_certificate
|
||||||
|
client-key: dummy_key
|
||||||
|
password: dummy_password
|
||||||
|
token: dummy_token
|
||||||
|
username: dummy_user
|
||||||
|
|
21
cmd/config/testdata/TestGetAuthInfoCmdGoldenOutput/get-multiple-credentials.golden
vendored
Normal file
21
cmd/config/testdata/TestGetAuthInfoCmdGoldenOutput/get-multiple-credentials.golden
vendored
Normal file
@ -0,0 +1,21 @@
|
|||||||
|
LocationOfOrigin: ""
|
||||||
|
client-certificate: dummy_certificate
|
||||||
|
client-key: dummy_key
|
||||||
|
password: dummy_password
|
||||||
|
token: dummy_token
|
||||||
|
username: dummy_user
|
||||||
|
|
||||||
|
LocationOfOrigin: ""
|
||||||
|
client-certificate: dummy_certificate
|
||||||
|
client-key: dummy_key
|
||||||
|
password: dummy_password
|
||||||
|
token: dummy_token
|
||||||
|
username: dummy_user
|
||||||
|
|
||||||
|
LocationOfOrigin: ""
|
||||||
|
client-certificate: dummy_certificate
|
||||||
|
client-key: dummy_key
|
||||||
|
password: dummy_password
|
||||||
|
token: dummy_token
|
||||||
|
username: dummy_user
|
||||||
|
|
14
cmd/config/testdata/TestGetAuthInfoCmdGoldenOutput/missing.golden
vendored
Normal file
14
cmd/config/testdata/TestGetAuthInfoCmdGoldenOutput/missing.golden
vendored
Normal file
@ -0,0 +1,14 @@
|
|||||||
|
Error: Missing configuration: User credentials with name 'authinfoMissing'
|
||||||
|
Usage:
|
||||||
|
get-credentials NAME [flags]
|
||||||
|
|
||||||
|
Examples:
|
||||||
|
# List all the users airshipctl knows about
|
||||||
|
airshipctl config get-credential
|
||||||
|
|
||||||
|
# Display a specific user information
|
||||||
|
airshipctl config get-credential e2e
|
||||||
|
|
||||||
|
Flags:
|
||||||
|
-h, --help help for get-credentials
|
||||||
|
|
1
cmd/config/testdata/TestNoAuthInfosGetAuthInfoCmdGoldenOutput/no-credentials.golden
vendored
Normal file
1
cmd/config/testdata/TestNoAuthInfosGetAuthInfoCmdGoldenOutput/no-credentials.golden
vendored
Normal file
@ -0,0 +1 @@
|
|||||||
|
No User credentials found in the configuration.
|
@ -62,3 +62,28 @@ func (o *ContextOptions) Validate() error {
|
|||||||
// TODO Manifest, Cluster could be validated against the existing config maps
|
// TODO Manifest, Cluster could be validated against the existing config maps
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (o *AuthInfoOptions) Validate() error {
|
||||||
|
if len(o.Token) > 0 && (len(o.Username) > 0 || len(o.Password) > 0) {
|
||||||
|
return fmt.Errorf("you cannot specify more than one authentication method at the same time: --%v or --%v/--%v",
|
||||||
|
FlagBearerToken, FlagUsername, FlagPassword)
|
||||||
|
}
|
||||||
|
if !o.EmbedCertData {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
certPath := o.ClientCertificate
|
||||||
|
if certPath == "" {
|
||||||
|
return fmt.Errorf("you must specify a --%s to embed", FlagCertFile)
|
||||||
|
}
|
||||||
|
if _, err := ioutil.ReadFile(certPath); err != nil {
|
||||||
|
return fmt.Errorf("error reading %s data from %s: %v", FlagCertFile, certPath, err)
|
||||||
|
}
|
||||||
|
keyPath := o.ClientKey
|
||||||
|
if keyPath == "" {
|
||||||
|
return fmt.Errorf("you must specify a --%s to embed", FlagKeyFile)
|
||||||
|
}
|
||||||
|
if _, err := ioutil.ReadFile(keyPath); err != nil {
|
||||||
|
return fmt.Errorf("error reading %s data from %s: %v", FlagKeyFile, keyPath, err)
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
@ -68,3 +68,15 @@ func TestValidateContext(t *testing.T) {
|
|||||||
err := co.Validate()
|
err := co.Validate()
|
||||||
assert.NoError(t, err)
|
assert.NoError(t, err)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestValidateAuthInfo(t *testing.T) {
|
||||||
|
co := DummyAuthInfoOptions()
|
||||||
|
// Token and cert error case
|
||||||
|
err := co.Validate()
|
||||||
|
assert.Error(t, err)
|
||||||
|
|
||||||
|
// Valid Data case
|
||||||
|
co.Token = ""
|
||||||
|
err = co.Validate()
|
||||||
|
assert.NoError(t, err)
|
||||||
|
}
|
||||||
|
@ -18,3 +18,13 @@ type ContextOptions struct {
|
|||||||
Manifest string
|
Manifest string
|
||||||
Namespace string
|
Namespace string
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type AuthInfoOptions struct {
|
||||||
|
Name string
|
||||||
|
ClientCertificate string
|
||||||
|
ClientKey string
|
||||||
|
Token string
|
||||||
|
Username string
|
||||||
|
Password string
|
||||||
|
EmbedCertData bool
|
||||||
|
}
|
||||||
|
@ -240,6 +240,7 @@ func (c *Config) reconcileAuthInfos() {
|
|||||||
// Add the reference
|
// Add the reference
|
||||||
c.AuthInfos[key] = NewAuthInfo()
|
c.AuthInfos[key] = NewAuthInfo()
|
||||||
}
|
}
|
||||||
|
c.AuthInfos[key].SetKubeAuthInfo(authinfo)
|
||||||
}
|
}
|
||||||
// Checking if there is any AuthInfo reference in airship config that does not match
|
// Checking if there is any AuthInfo reference in airship config that does not match
|
||||||
// an actual Auth Info struct in kubeconfig
|
// an actual Auth Info struct in kubeconfig
|
||||||
@ -619,6 +620,61 @@ func (c *Config) CurrentContextManifest() (*Manifest, error) {
|
|||||||
return c.Manifests[currentContext.Manifest], nil
|
return c.Manifests[currentContext.Manifest], nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Credential or AuthInfo related methods
|
||||||
|
func (c *Config) GetAuthInfo(aiName string) (*AuthInfo, error) {
|
||||||
|
authinfo, exists := c.AuthInfos[aiName]
|
||||||
|
if !exists {
|
||||||
|
return nil, ErrMissingConfig{What: fmt.Sprintf("User credentials with name '%s'", aiName)}
|
||||||
|
}
|
||||||
|
return authinfo, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *Config) GetAuthInfos() ([]*AuthInfo, error) {
|
||||||
|
authinfos := []*AuthInfo{}
|
||||||
|
for cName := range c.AuthInfos {
|
||||||
|
authinfo, err := c.GetAuthInfo(cName)
|
||||||
|
if err == nil {
|
||||||
|
authinfos = append(authinfos, authinfo)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return authinfos, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *Config) AddAuthInfo(theAuthInfo *AuthInfoOptions) *AuthInfo {
|
||||||
|
// Create the new Airship config context
|
||||||
|
nAuthInfo := NewAuthInfo()
|
||||||
|
c.AuthInfos[theAuthInfo.Name] = nAuthInfo
|
||||||
|
// Create a new Kubeconfig AuthInfo object as well
|
||||||
|
kAuthInfo := kubeconfig.NewAuthInfo()
|
||||||
|
nAuthInfo.SetKubeAuthInfo(kAuthInfo)
|
||||||
|
c.KubeConfig().AuthInfos[theAuthInfo.Name] = kAuthInfo
|
||||||
|
|
||||||
|
c.ModifyAuthInfo(nAuthInfo, theAuthInfo)
|
||||||
|
return nAuthInfo
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *Config) ModifyAuthInfo(authinfo *AuthInfo, theAuthInfo *AuthInfoOptions) {
|
||||||
|
kAuthInfo := authinfo.KubeAuthInfo()
|
||||||
|
if kAuthInfo == nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if theAuthInfo.ClientCertificate != "" {
|
||||||
|
kAuthInfo.ClientCertificate = theAuthInfo.ClientCertificate
|
||||||
|
}
|
||||||
|
if theAuthInfo.Token != "" {
|
||||||
|
kAuthInfo.Token = theAuthInfo.Token
|
||||||
|
}
|
||||||
|
if theAuthInfo.Username != "" {
|
||||||
|
kAuthInfo.Username = theAuthInfo.Username
|
||||||
|
}
|
||||||
|
if theAuthInfo.Password != "" {
|
||||||
|
kAuthInfo.Password = theAuthInfo.Password
|
||||||
|
}
|
||||||
|
if theAuthInfo.ClientKey != "" {
|
||||||
|
kAuthInfo.ClientKey = theAuthInfo.ClientKey
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// CurrentContextBootstrapInfo returns bootstrap info for current context
|
// CurrentContextBootstrapInfo returns bootstrap info for current context
|
||||||
func (c *Config) CurrentContextBootstrapInfo() (*Bootstrap, error) {
|
func (c *Config) CurrentContextBootstrapInfo() (*Bootstrap, error) {
|
||||||
currentCluster, err := c.CurrentContextCluster()
|
currentCluster, err := c.CurrentContextCluster()
|
||||||
@ -738,17 +794,25 @@ func (c *Context) ClusterType() string {
|
|||||||
// AuthInfo functions
|
// AuthInfo functions
|
||||||
func (c *AuthInfo) Equal(d *AuthInfo) bool {
|
func (c *AuthInfo) Equal(d *AuthInfo) bool {
|
||||||
if d == nil {
|
if d == nil {
|
||||||
return d == c
|
return c == d
|
||||||
}
|
}
|
||||||
return c == d
|
return c.kAuthInfo == d.kAuthInfo
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *AuthInfo) String() string {
|
func (c *AuthInfo) String() string {
|
||||||
yaml, err := yaml.Marshal(&c)
|
kauthinfo := c.KubeAuthInfo()
|
||||||
|
kyaml, err := yaml.Marshal(&kauthinfo)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return ""
|
return ""
|
||||||
}
|
}
|
||||||
return string(yaml)
|
return string(kyaml)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *AuthInfo) KubeAuthInfo() *kubeconfig.AuthInfo {
|
||||||
|
return c.kAuthInfo
|
||||||
|
}
|
||||||
|
func (c *AuthInfo) SetKubeAuthInfo(kc *kubeconfig.AuthInfo) {
|
||||||
|
c.kAuthInfo = kc
|
||||||
}
|
}
|
||||||
|
|
||||||
// Manifest functions
|
// Manifest functions
|
||||||
@ -931,3 +995,11 @@ func KContextString(kContext *kubeconfig.Context) string {
|
|||||||
|
|
||||||
return string(yaml)
|
return string(yaml)
|
||||||
}
|
}
|
||||||
|
func KAuthInfoString(kAuthInfo *kubeconfig.AuthInfo) string {
|
||||||
|
yaml, err := yaml.Marshal(&kAuthInfo)
|
||||||
|
if err != nil {
|
||||||
|
return ""
|
||||||
|
}
|
||||||
|
|
||||||
|
return string(yaml)
|
||||||
|
}
|
||||||
|
@ -32,6 +32,8 @@ import (
|
|||||||
"opendev.org/airship/airshipctl/testutil"
|
"opendev.org/airship/airshipctl/testutil"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
const stringDelta = "_changed"
|
||||||
|
|
||||||
func TestString(t *testing.T) {
|
func TestString(t *testing.T) {
|
||||||
fSys := testutil.SetupTestFs(t, "testdata")
|
fSys := testutil.SetupTestFs(t, "testdata")
|
||||||
|
|
||||||
@ -215,7 +217,7 @@ func TestLoadConfig(t *testing.T) {
|
|||||||
require.Contains(t, conf.Clusters, "def")
|
require.Contains(t, conf.Clusters, "def")
|
||||||
assert.Len(t, conf.Clusters["def"].ClusterTypes, 2)
|
assert.Len(t, conf.Clusters["def"].ClusterTypes, 2)
|
||||||
assert.Len(t, conf.Contexts, 3)
|
assert.Len(t, conf.Contexts, 3)
|
||||||
assert.Len(t, conf.AuthInfos, 2)
|
assert.Len(t, conf.AuthInfos, 3)
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestPersistConfig(t *testing.T) {
|
func TestPersistConfig(t *testing.T) {
|
||||||
@ -385,6 +387,15 @@ func TestKContextString(t *testing.T) {
|
|||||||
}
|
}
|
||||||
assert.EqualValues(t, KClusterString(nil), "null\n")
|
assert.EqualValues(t, KClusterString(nil), "null\n")
|
||||||
}
|
}
|
||||||
|
func TestKAuthInfoString(t *testing.T) {
|
||||||
|
conf := InitConfig(t)
|
||||||
|
kAuthInfos := conf.KubeConfig().AuthInfos
|
||||||
|
for kAi := range kAuthInfos {
|
||||||
|
assert.NotEmpty(t, KAuthInfoString(kAuthInfos[kAi]))
|
||||||
|
}
|
||||||
|
assert.EqualValues(t, KAuthInfoString(nil), "null\n")
|
||||||
|
}
|
||||||
|
|
||||||
func TestComplexName(t *testing.T) {
|
func TestComplexName(t *testing.T) {
|
||||||
cName := "aCluster"
|
cName := "aCluster"
|
||||||
ctName := Ephemeral
|
ctName := Ephemeral
|
||||||
@ -434,13 +445,13 @@ func TestAddCluster(t *testing.T) {
|
|||||||
assert.EqualValues(t, conf.Clusters[co.Name].ClusterTypes[co.ClusterType], cluster)
|
assert.EqualValues(t, conf.Clusters[co.Name].ClusterTypes[co.ClusterType], cluster)
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestModifyluster(t *testing.T) {
|
func TestModifyCluster(t *testing.T) {
|
||||||
co := DummyClusterOptions()
|
co := DummyClusterOptions()
|
||||||
conf := InitConfig(t)
|
conf := InitConfig(t)
|
||||||
cluster, err := conf.AddCluster(co)
|
cluster, err := conf.AddCluster(co)
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
|
|
||||||
co.Server += "/changes"
|
co.Server += stringDelta
|
||||||
co.InsecureSkipTLSVerify = true
|
co.InsecureSkipTLSVerify = true
|
||||||
co.EmbedCAData = true
|
co.EmbedCAData = true
|
||||||
mcluster, err := conf.ModifyCluster(cluster, co)
|
mcluster, err := conf.ModifyCluster(cluster, co)
|
||||||
@ -533,3 +544,75 @@ func TestGetContext(t *testing.T) {
|
|||||||
_, err = conf.GetContext("unknown")
|
_, err = conf.GetContext("unknown")
|
||||||
assert.Error(t, err)
|
assert.Error(t, err)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestAddContext(t *testing.T) {
|
||||||
|
co := DummyContextOptions()
|
||||||
|
conf := InitConfig(t)
|
||||||
|
context := conf.AddContext(co)
|
||||||
|
assert.EqualValues(t, conf.Contexts[co.Name], context)
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestModifyContext(t *testing.T) {
|
||||||
|
co := DummyContextOptions()
|
||||||
|
conf := InitConfig(t)
|
||||||
|
context := conf.AddContext(co)
|
||||||
|
|
||||||
|
co.Namespace += stringDelta
|
||||||
|
co.Cluster += stringDelta
|
||||||
|
co.AuthInfo += stringDelta
|
||||||
|
co.Manifest += stringDelta
|
||||||
|
conf.ModifyContext(context, co)
|
||||||
|
assert.EqualValues(t, conf.Contexts[co.Name].KubeContext().Namespace, co.Namespace)
|
||||||
|
assert.EqualValues(t, conf.Contexts[co.Name].KubeContext().Cluster, co.Cluster)
|
||||||
|
assert.EqualValues(t, conf.Contexts[co.Name].KubeContext().AuthInfo, co.AuthInfo)
|
||||||
|
assert.EqualValues(t, conf.Contexts[co.Name].Manifest, co.Manifest)
|
||||||
|
assert.EqualValues(t, conf.Contexts[co.Name], context)
|
||||||
|
}
|
||||||
|
|
||||||
|
// AuthInfo Related
|
||||||
|
|
||||||
|
func TestGetAuthInfos(t *testing.T) {
|
||||||
|
conf := InitConfig(t)
|
||||||
|
authinfos, err := conf.GetAuthInfos()
|
||||||
|
require.NoError(t, err)
|
||||||
|
assert.Len(t, authinfos, 3)
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestGetAuthInfo(t *testing.T) {
|
||||||
|
conf := InitConfig(t)
|
||||||
|
authinfo, err := conf.GetAuthInfo("def-user")
|
||||||
|
require.NoError(t, err)
|
||||||
|
|
||||||
|
// Test Positives
|
||||||
|
assert.EqualValues(t, authinfo.KubeAuthInfo().Username, "dummy_username")
|
||||||
|
|
||||||
|
// Test Wrong Cluster
|
||||||
|
_, err = conf.GetAuthInfo("unknown")
|
||||||
|
assert.Error(t, err)
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestAddAuthInfo(t *testing.T) {
|
||||||
|
co := DummyAuthInfoOptions()
|
||||||
|
conf := InitConfig(t)
|
||||||
|
authinfo := conf.AddAuthInfo(co)
|
||||||
|
assert.EqualValues(t, conf.AuthInfos[co.Name], authinfo)
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestModifyAuthInfo(t *testing.T) {
|
||||||
|
co := DummyAuthInfoOptions()
|
||||||
|
conf := InitConfig(t)
|
||||||
|
authinfo := conf.AddAuthInfo(co)
|
||||||
|
|
||||||
|
co.Username += stringDelta
|
||||||
|
co.Password += stringDelta
|
||||||
|
co.ClientCertificate += stringDelta
|
||||||
|
co.ClientKey += stringDelta
|
||||||
|
co.Token += stringDelta
|
||||||
|
conf.ModifyAuthInfo(authinfo, co)
|
||||||
|
assert.EqualValues(t, conf.AuthInfos[co.Name].KubeAuthInfo().Username, co.Username)
|
||||||
|
assert.EqualValues(t, conf.AuthInfos[co.Name].KubeAuthInfo().Password, co.Password)
|
||||||
|
assert.EqualValues(t, conf.AuthInfos[co.Name].KubeAuthInfo().ClientCertificate, co.ClientCertificate)
|
||||||
|
assert.EqualValues(t, conf.AuthInfos[co.Name].KubeAuthInfo().ClientKey, co.ClientKey)
|
||||||
|
assert.EqualValues(t, conf.AuthInfos[co.Name].KubeAuthInfo().Token, co.Token)
|
||||||
|
assert.EqualValues(t, conf.AuthInfos[co.Name], authinfo)
|
||||||
|
}
|
||||||
|
@ -104,7 +104,15 @@ func DummyRepository() *Repository {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func DummyAuthInfo() *AuthInfo {
|
func DummyAuthInfo() *AuthInfo {
|
||||||
return NewAuthInfo()
|
a := NewAuthInfo()
|
||||||
|
authinfo := kubeconfig.NewAuthInfo()
|
||||||
|
authinfo.Username = "dummy_username"
|
||||||
|
authinfo.Password = "dummy_password"
|
||||||
|
authinfo.ClientCertificate = "dummy_certificate"
|
||||||
|
authinfo.ClientKey = "dummy_key"
|
||||||
|
authinfo.Token = "dummy_token"
|
||||||
|
a.SetKubeAuthInfo(authinfo)
|
||||||
|
return a
|
||||||
}
|
}
|
||||||
|
|
||||||
func DummyModules() *Modules {
|
func DummyModules() *Modules {
|
||||||
@ -168,6 +176,16 @@ func DummyContextOptions() *ContextOptions {
|
|||||||
return co
|
return co
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func DummyAuthInfoOptions() *AuthInfoOptions {
|
||||||
|
authinfo := &AuthInfoOptions{}
|
||||||
|
authinfo.Username = "dummy_username"
|
||||||
|
authinfo.Password = "dummy_password"
|
||||||
|
authinfo.ClientCertificate = "dummy_certificate"
|
||||||
|
authinfo.ClientKey = "dummy_key"
|
||||||
|
authinfo.Token = "dummy_token"
|
||||||
|
return authinfo
|
||||||
|
}
|
||||||
|
|
||||||
func DummyBootstrap() *Bootstrap {
|
func DummyBootstrap() *Bootstrap {
|
||||||
bs := &Bootstrap{}
|
bs := &Bootstrap{}
|
||||||
cont := Container{
|
cont := Container{
|
||||||
@ -224,7 +242,8 @@ modules-config:
|
|||||||
dummy-for-tests: ""
|
dummy-for-tests: ""
|
||||||
users:
|
users:
|
||||||
k-admin: {}
|
k-admin: {}
|
||||||
k-other: {}`
|
k-other: {}
|
||||||
|
def-user: {}`
|
||||||
|
|
||||||
//nolint:lll
|
//nolint:lll
|
||||||
testKubeConfigYAML = `apiVersion: v1
|
testKubeConfigYAML = `apiVersion: v1
|
||||||
@ -262,6 +281,11 @@ current-context: ""
|
|||||||
kind: Config
|
kind: Config
|
||||||
preferences: {}
|
preferences: {}
|
||||||
users:
|
users:
|
||||||
|
users:
|
||||||
|
- name: def-user
|
||||||
|
user:
|
||||||
|
username: dummy_username
|
||||||
|
password: dummy_password
|
||||||
- name: k-admin
|
- name: k-admin
|
||||||
user:
|
user:
|
||||||
client-certificate-data: LS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0tCk1JSUM4akNDQWRxZ0F3SUJBZ0lJQXhEdzk2RUY4SXN3RFFZSktvWklodmNOQVFFTEJRQXdGVEVUTUJFR0ExVUUKQXhNS2EzVmlaWEp1WlhSbGN6QWVGdzB4T1RBNU1qa3hOekF6TURsYUZ3MHlNREE1TWpneE56QXpNVEphTURReApGekFWQmdOVkJBb1REbk41YzNSbGJUcHRZWE4wWlhKek1Sa3dGd1lEVlFRREV4QnJkV0psY201bGRHVnpMV0ZrCmJXbHVNSUlCSWpBTkJna3Foa2lHOXcwQkFRRUZBQU9DQVE4QU1JSUJDZ0tDQVFFQXV6R0pZdlBaNkRvaTQyMUQKSzhXSmFaQ25OQWQycXo1cC8wNDJvRnpRUGJyQWd6RTJxWVZrek9MOHhBVmVSN1NONXdXb1RXRXlGOEVWN3JyLwo0K0hoSEdpcTVQbXF1SUZ5enpuNi9JWmM4alU5eEVmenZpa2NpckxmVTR2UlhKUXdWd2dBU05sMkFXQUloMmRECmRUcmpCQ2ZpS1dNSHlqMFJiSGFsc0J6T3BnVC9IVHYzR1F6blVRekZLdjJkajVWMU5rUy9ESGp5UlJKK0VMNlEKQlltR3NlZzVQNE5iQzllYnVpcG1NVEFxL0p1bU9vb2QrRmpMMm5acUw2Zkk2ZkJ0RjVPR2xwQ0IxWUo4ZnpDdApHUVFaN0hUSWJkYjJ0cDQzRlZPaHlRYlZjSHFUQTA0UEoxNSswV0F5bVVKVXo4WEE1NDRyL2J2NzRKY0pVUkZoCmFyWmlRd0lEQVFBQm95Y3dKVEFPQmdOVkhROEJBZjhFQkFNQ0JhQXdFd1lEVlIwbEJBd3dDZ1lJS3dZQkJRVUgKQXdJd0RRWUpLb1pJaHZjTkFRRUxCUUFEZ2dFQkFMMmhIUmVibEl2VHJTMFNmUVg1RG9ueVVhNy84aTg1endVWApSd3dqdzFuS0U0NDJKbWZWRGZ5b0hRYUM4Ti9MQkxyUXM0U0lqU1JYdmFHU1dSQnRnT1RRV21Db1laMXdSbjdwCndDTXZQTERJdHNWWm90SEZpUFl2b1lHWFFUSXA3YlROMmg1OEJaaEZ3d25nWUovT04zeG1rd29IN1IxYmVxWEYKWHF1TTluekhESk41VlZub1lQR09yRHMwWlg1RnNxNGtWVU0wVExNQm9qN1ZIRDhmU0E5RjRYNU4yMldsZnNPMAo4aksrRFJDWTAyaHBrYTZQQ0pQS0lNOEJaMUFSMG9ZakZxT0plcXpPTjBqcnpYWHh4S2pHVFVUb1BldVA5dCtCCjJOMVA1TnI4a2oxM0lrend5Q1NZclFVN09ZM3ltZmJobHkrcXZxaFVFa014MlQ1SkpmQT0KLS0tLS1FTkQgQ0VSVElGSUNBVEUtLS0tLQo=
|
client-certificate-data: LS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0tCk1JSUM4akNDQWRxZ0F3SUJBZ0lJQXhEdzk2RUY4SXN3RFFZSktvWklodmNOQVFFTEJRQXdGVEVUTUJFR0ExVUUKQXhNS2EzVmlaWEp1WlhSbGN6QWVGdzB4T1RBNU1qa3hOekF6TURsYUZ3MHlNREE1TWpneE56QXpNVEphTURReApGekFWQmdOVkJBb1REbk41YzNSbGJUcHRZWE4wWlhKek1Sa3dGd1lEVlFRREV4QnJkV0psY201bGRHVnpMV0ZrCmJXbHVNSUlCSWpBTkJna3Foa2lHOXcwQkFRRUZBQU9DQVE4QU1JSUJDZ0tDQVFFQXV6R0pZdlBaNkRvaTQyMUQKSzhXSmFaQ25OQWQycXo1cC8wNDJvRnpRUGJyQWd6RTJxWVZrek9MOHhBVmVSN1NONXdXb1RXRXlGOEVWN3JyLwo0K0hoSEdpcTVQbXF1SUZ5enpuNi9JWmM4alU5eEVmenZpa2NpckxmVTR2UlhKUXdWd2dBU05sMkFXQUloMmRECmRUcmpCQ2ZpS1dNSHlqMFJiSGFsc0J6T3BnVC9IVHYzR1F6blVRekZLdjJkajVWMU5rUy9ESGp5UlJKK0VMNlEKQlltR3NlZzVQNE5iQzllYnVpcG1NVEFxL0p1bU9vb2QrRmpMMm5acUw2Zkk2ZkJ0RjVPR2xwQ0IxWUo4ZnpDdApHUVFaN0hUSWJkYjJ0cDQzRlZPaHlRYlZjSHFUQTA0UEoxNSswV0F5bVVKVXo4WEE1NDRyL2J2NzRKY0pVUkZoCmFyWmlRd0lEQVFBQm95Y3dKVEFPQmdOVkhROEJBZjhFQkFNQ0JhQXdFd1lEVlIwbEJBd3dDZ1lJS3dZQkJRVUgKQXdJd0RRWUpLb1pJaHZjTkFRRUxCUUFEZ2dFQkFMMmhIUmVibEl2VHJTMFNmUVg1RG9ueVVhNy84aTg1endVWApSd3dqdzFuS0U0NDJKbWZWRGZ5b0hRYUM4Ti9MQkxyUXM0U0lqU1JYdmFHU1dSQnRnT1RRV21Db1laMXdSbjdwCndDTXZQTERJdHNWWm90SEZpUFl2b1lHWFFUSXA3YlROMmg1OEJaaEZ3d25nWUovT04zeG1rd29IN1IxYmVxWEYKWHF1TTluekhESk41VlZub1lQR09yRHMwWlg1RnNxNGtWVU0wVExNQm9qN1ZIRDhmU0E5RjRYNU4yMldsZnNPMAo4aksrRFJDWTAyaHBrYTZQQ0pQS0lNOEJaMUFSMG9ZakZxT0plcXpPTjBqcnpYWHh4S2pHVFVUb1BldVA5dCtCCjJOMVA1TnI4a2oxM0lrend5Q1NZclFVN09ZM3ltZmJobHkrcXZxaFVFa014MlQ1SkpmQT0KLS0tLS1FTkQgQ0VSVElGSUNBVEUtLS0tLQo=
|
||||||
|
7
pkg/config/testdata/authinfo-string.yaml
vendored
7
pkg/config/testdata/authinfo-string.yaml
vendored
@ -1 +1,6 @@
|
|||||||
{}
|
LocationOfOrigin: ""
|
||||||
|
client-certificate: dummy_certificate
|
||||||
|
client-key: dummy_key
|
||||||
|
password: dummy_password
|
||||||
|
token: dummy_token
|
||||||
|
username: dummy_username
|
||||||
|
@ -112,8 +112,8 @@ type Context struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
type AuthInfo struct {
|
type AuthInfo struct {
|
||||||
// Empty in purpose
|
// Kubeconfig AuthInfo Object
|
||||||
// Will implement Interface to Set/Get fields from kubeconfig as needed
|
kAuthInfo *kubeconfig.AuthInfo
|
||||||
}
|
}
|
||||||
|
|
||||||
// Manifests is a tuple of references to a Manifest (how do Identify, collect ,
|
// Manifests is a tuple of references to a Manifest (how do Identify, collect ,
|
||||||
|
Loading…
Reference in New Issue
Block a user