func TestNewEmptyAuth(t *testing.T) { expectedConfig := *clientcmdapi.NewConfig() expectedConfig.AuthInfos["the-user-name"] = *clientcmdapi.NewAuthInfo() test := configCommandTest{ args: []string{"set-credentials", "the-user-name"}, startingConfig: *clientcmdapi.NewConfig(), expectedConfig: expectedConfig, } test.run(t) }
func TestNewEmptyCluster(t *testing.T) { expectedConfig := *clientcmdapi.NewConfig() expectedConfig.Clusters["new-cluster"] = *clientcmdapi.NewCluster() test := configCommandTest{ args: []string{"set-cluster", "new-cluster"}, startingConfig: *clientcmdapi.NewConfig(), expectedConfig: expectedConfig, } test.run(t) }
func TestNewEmptyContext(t *testing.T) { expectedConfig := *clientcmdapi.NewConfig() expectedConfig.Contexts["new-context"] = *clientcmdapi.NewContext() test := configCommandTest{ args: []string{"set-context", "new-context"}, startingConfig: *clientcmdapi.NewConfig(), expectedConfig: expectedConfig, } test.run(t) }
// Load starts by running the MigrationRules and then // takes the loading rules and returns a Config object based on following rules. // if the ExplicitPath, return the unmerged explicit file // Otherwise, return a merged config based on the Precedence slice // A missing ExplicitPath file produces an error. Empty filenames or other missing files are ignored. // Read errors or files with non-deserializable content produce errors. // The first file to set a particular map key wins and map key's value is never changed. // BUT, if you set a struct value that is NOT contained inside of map, the value WILL be changed. // This results in some odd looking logic to merge in one direction, merge in the other, and then merge the two. // It also means that if two files specify a "red-user", only values from the first file's red-user are used. Even // non-conflicting entries from the second file's "red-user" are discarded. // Relative paths inside of the .qingconfig files are resolved against the .qingconfig file's parent folder // and only absolute file paths are returned. func (rules *ClientConfigLoadingRules) Load() (*clientcmdapi.Config, error) { if err := rules.Migrate(); err != nil { return nil, err } errlist := []error{} qingConfigFiles := []string{} // Make sure a file we were explicitly told to use exists if len(rules.ExplicitPath) > 0 { if _, err := os.Stat(rules.ExplicitPath); os.IsNotExist(err) { return nil, err } qingConfigFiles = append(qingConfigFiles, rules.ExplicitPath) } else { qingConfigFiles = append(qingConfigFiles, rules.Precedence...) } // first merge all of our maps mapConfig := clientcmdapi.NewConfig() for _, file := range qingConfigFiles { if err := mergeConfigWithFile(mapConfig, file); err != nil { errlist = append(errlist, err) } if rules.ResolvePaths() { if err := ResolveLocalPaths(file, mapConfig); err != nil { errlist = append(errlist, err) } } } // merge all of the struct values in the reverse order so that priority is given correctly // errors are not added to the list the second time nonMapConfig := clientcmdapi.NewConfig() for i := len(qingConfigFiles) - 1; i >= 0; i-- { file := qingConfigFiles[i] mergeConfigWithFile(nonMapConfig, file) if rules.ResolvePaths() { ResolveLocalPaths(file, nonMapConfig) } } // since values are overwritten, but maps values are not, we can merge the non-map config on top of the map config and // get the values we expect. config := clientcmdapi.NewConfig() mergo.Merge(config, mapConfig) mergo.Merge(config, nonMapConfig) return config, errors.NewAggregate(errlist) }
func TestSetIntoNewConfig(t *testing.T) { expectedConfig := *clientcmdapi.NewConfig() context := clientcmdapi.NewContext() context.AuthInfo = "fake-user" expectedConfig.Contexts["new-context"] = *context test := configCommandTest{ args: []string{"set", "contexts.new-context.user", "fake-user"}, startingConfig: *clientcmdapi.NewConfig(), expectedConfig: expectedConfig, } test.run(t) }
func TestValidateEmptyConfig(t *testing.T) { config := clientcmdapi.NewConfig() test := configValidationTest{ config: config, } test.testConfig(t) }
func TestNewFactoryNoFlagBindings(t *testing.T) { clientConfig := clientcmd.NewDefaultClientConfig(*clientcmdapi.NewConfig(), &clientcmd.ConfigOverrides{}) factory := NewFactory(clientConfig) if factory.flags.HasFlags() { t.Errorf("Expected zero flags, but got %v", factory.flags) } }
func TestConfirmUsableEmptyConfig(t *testing.T) { config := clientcmdapi.NewConfig() test := configValidationTest{ config: config, expectedErrorSubstring: []string{"no context chosen"}, } test.testConfirmUsable("", t) }
func TestConfirmUsableMissingConfig(t *testing.T) { config := clientcmdapi.NewConfig() test := configValidationTest{ config: config, expectedErrorSubstring: []string{"context was not found for"}, } test.testConfirmUsable("not-here", t) }
func TestValidateMissingCurrentContextConfig(t *testing.T) { config := clientcmdapi.NewConfig() config.CurrentContext = "anything" test := configValidationTest{ config: config, expectedErrorSubstring: []string{"context was not found for specified "}, } test.testConfig(t) }
func TestValidateEmptyAuthInfo(t *testing.T) { config := clientcmdapi.NewConfig() config.AuthInfos["error"] = clientcmdapi.AuthInfo{} test := configValidationTest{ config: config, } test.testAuthInfo("error", t) test.testConfig(t) }
func TestValidateEmptyClusterInfo(t *testing.T) { config := clientcmdapi.NewConfig() config.Clusters["empty"] = clientcmdapi.Cluster{} test := configValidationTest{ config: config, expectedErrorSubstring: []string{"no server found for"}, } test.testCluster("empty", t) test.testConfig(t) }
func TestIsContextNotFound(t *testing.T) { config := clientcmdapi.NewConfig() config.CurrentContext = "anything" err := Validate(*config) if !IsContextNotFound(err) { t.Errorf("Expected context not found, but got %v", err) } if !IsConfigurationInvalid(err) { t.Errorf("Expected configuration invalid, but got %v", err) } }
// getConfigFromFileOrDie tries to read a qingconfig file and if it can't, it calls exit. One exception, missing files result in empty configs, not an exit func getConfigFromFileOrDie(filename string) *clientcmdapi.Config { config, err := clientcmd.LoadFromFile(filename) if err != nil && !os.IsNotExist(err) { glog.FatalDepth(1, err) } if config == nil { return clientcmdapi.NewConfig() } return config }
func TestValidateCleanClusterInfo(t *testing.T) { config := clientcmdapi.NewConfig() config.Clusters["clean"] = clientcmdapi.Cluster{ Server: "anything", } test := configValidationTest{ config: config, } test.testCluster("clean", t) test.testConfig(t) }
func TestValidateEmptyContext(t *testing.T) { config := clientcmdapi.NewConfig() config.CurrentContext = "anything" config.Contexts["anything"] = clientcmdapi.Context{} test := configValidationTest{ config: config, expectedErrorSubstring: []string{"user was not specified for context \"anything\"", "cluster was not specified for context \"anything\""}, } test.testContext("anything", t) test.testConfig(t) }
func TestValidateMissingReferencesConfig(t *testing.T) { config := clientcmdapi.NewConfig() config.CurrentContext = "anything" config.Contexts["anything"] = clientcmdapi.Context{Cluster: "missing", AuthInfo: "missing"} test := configValidationTest{ config: config, expectedErrorSubstring: []string{"user \"missing\" was not found for context \"anything\"", "cluster \"missing\" was not found for context \"anything\""}, } test.testContext("anything", t) test.testConfig(t) }
// Load takes a byte slice and deserializes the contents into Config object. // Encapsulates deserialization without assuming the source is a file. func Load(data []byte) (*clientcmdapi.Config, error) { config := clientcmdapi.NewConfig() // if there's no data in a file, return the default object instead of failing (DecodeInto reject empty input) if len(data) == 0 { return config, nil } if err := clientcmdlatest.Codec.DecodeInto(data, config); err != nil { return nil, err } return config, nil }
func TestValidateCleanTokenAuthInfo(t *testing.T) { config := clientcmdapi.NewConfig() config.AuthInfos["clean"] = clientcmdapi.AuthInfo{ Token: "any-value", } test := configValidationTest{ config: config, } test.testAuthInfo("clean", t) test.testConfig(t) }
func TestValidateMissingCAFileClusterInfo(t *testing.T) { config := clientcmdapi.NewConfig() config.Clusters["missing ca"] = clientcmdapi.Cluster{ Server: "anything", CertificateAuthority: "missing", } test := configValidationTest{ config: config, expectedErrorSubstring: []string{"unable to read certificate-authority"}, } test.testCluster("missing ca", t) test.testConfig(t) }
func TestValidateCertFilesNotFoundAuthInfo(t *testing.T) { config := clientcmdapi.NewConfig() config.AuthInfos["error"] = clientcmdapi.AuthInfo{ ClientCertificate: "missing", ClientKey: "missing", } test := configValidationTest{ config: config, expectedErrorSubstring: []string{"unable to read client-cert", "unable to read client-key"}, } test.testAuthInfo("error", t) test.testConfig(t) }
func TestValidateMultipleMethodsAuthInfo(t *testing.T) { config := clientcmdapi.NewConfig() config.AuthInfos["error"] = clientcmdapi.AuthInfo{ Token: "token", Username: "******", } test := configValidationTest{ config: config, expectedErrorSubstring: []string{"more than one authentication method", "token", "basicAuth"}, } test.testAuthInfo("error", t) test.testConfig(t) }
func TestValidateCleanWithCAClusterInfo(t *testing.T) { tempFile, _ := ioutil.TempFile("", "") defer os.Remove(tempFile.Name()) config := clientcmdapi.NewConfig() config.Clusters["clean"] = clientcmdapi.Cluster{ Server: "anything", CertificateAuthority: tempFile.Name(), } test := configValidationTest{ config: config, } test.testCluster("clean", t) test.testConfig(t) }
func (o *PathOptions) GetStartingConfig() (*clientcmdapi.Config, error) { // don't mutate the original loadingRules := *o.LoadingRules loadingRules.Precedence = o.GetLoadingPrecedence() clientConfig := clientcmd.NewNonInteractiveDeferredLoadingClientConfig(&loadingRules, &clientcmd.ConfigOverrides{}) rawConfig, err := clientConfig.RawConfig() if os.IsNotExist(err) { return clientcmdapi.NewConfig(), nil } if err != nil { return nil, err } return &rawConfig, nil }
func TestValidateCleanCertFilesAuthInfo(t *testing.T) { tempFile, _ := ioutil.TempFile("", "") defer os.Remove(tempFile.Name()) config := clientcmdapi.NewConfig() config.AuthInfos["clean"] = clientcmdapi.AuthInfo{ ClientCertificate: tempFile.Name(), ClientKey: tempFile.Name(), } test := configValidationTest{ config: config, } test.testAuthInfo("clean", t) test.testConfig(t) }
func TestValidateCertDataOverridesFiles(t *testing.T) { tempFile, _ := ioutil.TempFile("", "") defer os.Remove(tempFile.Name()) config := clientcmdapi.NewConfig() config.AuthInfos["clean"] = clientcmdapi.AuthInfo{ ClientCertificate: tempFile.Name(), ClientCertificateData: []byte("certdata"), ClientKey: tempFile.Name(), ClientKeyData: []byte("keydata"), } test := configValidationTest{ config: config, expectedErrorSubstring: []string{"client-cert-data and client-cert are both specified", "client-key-data and client-key are both specified"}, } test.testAuthInfo("clean", t) test.testConfig(t) }
func TestConfirmUsableBadInfoConfig(t *testing.T) { config := clientcmdapi.NewConfig() config.Clusters["missing ca"] = clientcmdapi.Cluster{ Server: "anything", CertificateAuthority: "missing", } config.AuthInfos["error"] = clientcmdapi.AuthInfo{ Username: "******", Token: "here", } config.Contexts["first"] = clientcmdapi.Context{ Cluster: "missing ca", AuthInfo: "error", } test := configValidationTest{ config: config, expectedErrorSubstring: []string{"unable to read certificate-authority"}, } test.testConfirmUsable("first", t) }
"github.com/qingyuancloud/QingYuan/pkg/api" "github.com/qingyuancloud/QingYuan/pkg/client" clientcmdapi "github.com/qingyuancloud/QingYuan/pkg/client/clientcmd/api" "github.com/qingyuancloud/QingYuan/pkg/clientauth" ) var ( // DefaultCluster is the cluster config used when no other config is specified // TODO: eventually apiserver should start on 443 and be secure by default DefaultCluster = clientcmdapi.Cluster{Server: "http://localhost:8080"} // EnvVarCluster allows overriding the DefaultCluster using an envvar for the server name EnvVarCluster = clientcmdapi.Cluster{Server: os.Getenv("QINGYUAN_MASTER")} DefaultClientConfig = DirectClientConfig{*clientcmdapi.NewConfig(), "", &ConfigOverrides{}, nil} ) // ClientConfig is used to make it easy to get an api server client type ClientConfig interface { // RawConfig returns the merged result of all overrides RawConfig() (clientcmdapi.Config, error) // ClientConfig returns a complete client config ClientConfig() (*client.Config, error) // Namespace returns the namespace resulting from the merged result of all overrides Namespace() (string, error) } // DirectClientConfig is a ClientConfig interface that is backed by a clientcmdapi.Config, options overrides, and an optional fallbackReader for auth information type DirectClientConfig struct { config clientcmdapi.Config