2017-10-06 20:26:14 +00:00
/ *
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 clientcmd
import (
"io/ioutil"
"os"
"strings"
"testing"
utilerrors "k8s.io/apimachinery/pkg/util/errors"
clientcmdapi "k8s.io/client-go/tools/clientcmd/api"
)
func TestConfirmUsableBadInfoButOkConfig ( t * testing . T ) {
config := clientcmdapi . NewConfig ( )
config . Clusters [ "missing ca" ] = & clientcmdapi . Cluster {
Server : "anything" ,
CertificateAuthority : "missing" ,
}
config . AuthInfos [ "error" ] = & clientcmdapi . AuthInfo {
Username : "anything" ,
Token : "here" ,
}
config . Contexts [ "dirty" ] = & clientcmdapi . Context {
Cluster : "missing ca" ,
AuthInfo : "error" ,
}
config . Clusters [ "clean" ] = & clientcmdapi . Cluster {
Server : "anything" ,
}
config . AuthInfos [ "clean" ] = & clientcmdapi . AuthInfo {
Token : "here" ,
}
config . Contexts [ "clean" ] = & clientcmdapi . Context {
Cluster : "clean" ,
AuthInfo : "clean" ,
}
badValidation := configValidationTest {
config : config ,
expectedErrorSubstring : [ ] string { "unable to read certificate-authority" } ,
}
okTest := configValidationTest {
config : config ,
}
okTest . testConfirmUsable ( "clean" , t )
badValidation . testConfig ( t )
}
2018-03-23 16:35:19 +00:00
2017-10-06 20:26:14 +00:00
func TestConfirmUsableBadInfoConfig ( t * testing . T ) {
config := clientcmdapi . NewConfig ( )
config . Clusters [ "missing ca" ] = & clientcmdapi . Cluster {
Server : "anything" ,
CertificateAuthority : "missing" ,
}
config . AuthInfos [ "error" ] = & clientcmdapi . AuthInfo {
Username : "anything" ,
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 )
}
2018-03-23 16:35:19 +00:00
2017-10-06 20:26:14 +00:00
func TestConfirmUsableEmptyConfig ( t * testing . T ) {
config := clientcmdapi . NewConfig ( )
test := configValidationTest {
config : config ,
expectedErrorSubstring : [ ] string { "invalid configuration: no configuration has been provided" } ,
}
test . testConfirmUsable ( "" , t )
}
2018-03-23 16:35:19 +00:00
2017-10-06 20:26:14 +00:00
func TestConfirmUsableMissingConfig ( t * testing . T ) {
config := clientcmdapi . NewConfig ( )
test := configValidationTest {
config : config ,
expectedErrorSubstring : [ ] string { "invalid configuration: no configuration has been provided" } ,
}
test . testConfirmUsable ( "not-here" , t )
}
2018-03-23 16:35:19 +00:00
2017-10-06 20:26:14 +00:00
func TestValidateEmptyConfig ( t * testing . T ) {
config := clientcmdapi . NewConfig ( )
test := configValidationTest {
config : config ,
expectedErrorSubstring : [ ] string { "invalid configuration: no configuration has been provided" } ,
}
test . testConfig ( t )
}
2018-03-23 16:35:19 +00:00
2017-10-06 20:26:14 +00:00
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 )
}
2018-03-23 16:35:19 +00:00
2017-10-06 20:26:14 +00:00
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 )
}
}
func TestIsEmptyConfig ( t * testing . T ) {
config := clientcmdapi . NewConfig ( )
err := Validate ( * config )
if ! IsEmptyConfig ( err ) {
t . Errorf ( "Expected context not found, but got %v" , err )
}
if ! IsConfigurationInvalid ( err ) {
t . Errorf ( "Expected configuration invalid, but got %v" , err )
}
}
func TestIsConfigurationInvalid ( t * testing . T ) {
if newErrConfigurationInvalid ( [ ] error { } ) != nil {
t . Errorf ( "unexpected error" )
}
if newErrConfigurationInvalid ( [ ] error { ErrNoContext } ) == ErrNoContext {
t . Errorf ( "unexpected error" )
}
if newErrConfigurationInvalid ( [ ] error { ErrNoContext , ErrNoContext } ) == nil {
t . Errorf ( "unexpected error" )
}
if ! IsConfigurationInvalid ( newErrConfigurationInvalid ( [ ] error { ErrNoContext , ErrNoContext } ) ) {
t . Errorf ( "unexpected error" )
}
}
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 )
}
2018-03-23 16:35:19 +00:00
2017-10-06 20:26:14 +00:00
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 )
}
2018-03-23 16:35:19 +00:00
func TestValidateEmptyContextName ( t * testing . T ) {
config := clientcmdapi . NewConfig ( )
config . CurrentContext = "anything"
config . Contexts [ "" ] = & clientcmdapi . Context { Cluster : "missing" , AuthInfo : "missing" }
test := configValidationTest {
config : config ,
expectedErrorSubstring : [ ] string { "empty context name" , "is not allowed" } ,
}
test . testContext ( "" , t )
test . testConfig ( t )
}
2017-10-06 20:26:14 +00:00
func TestValidateEmptyClusterInfo ( t * testing . T ) {
config := clientcmdapi . NewConfig ( )
config . Clusters [ "empty" ] = clientcmdapi . NewCluster ( )
test := configValidationTest {
config : config ,
expectedErrorSubstring : [ ] string { "cluster has no server defined" } ,
}
test . testCluster ( "empty" , t )
test . testConfig ( t )
}
func TestValidateClusterInfoErrEmptyCluster ( t * testing . T ) {
cluster := clientcmdapi . NewCluster ( )
errs := validateClusterInfo ( "" , * cluster )
if len ( errs ) != 1 {
t . Fatalf ( "unexpected errors: %v" , errs )
}
if errs [ 0 ] != ErrEmptyCluster {
t . Errorf ( "unexpected error: %v" , errs [ 0 ] )
}
}
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 )
}
2018-03-23 16:35:19 +00:00
2017-10-06 20:26:14 +00:00
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 )
}
2018-03-23 16:35:19 +00:00
2017-10-06 20:26:14 +00:00
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 TestValidateEmptyAuthInfo ( t * testing . T ) {
config := clientcmdapi . NewConfig ( )
config . AuthInfos [ "error" ] = & clientcmdapi . AuthInfo { }
test := configValidationTest {
config : config ,
}
test . testAuthInfo ( "error" , t )
test . testConfig ( t )
}
2018-03-23 16:35:19 +00:00
2017-10-06 20:26:14 +00:00
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 )
}
2018-03-23 16:35:19 +00:00
2017-10-06 20:26:14 +00:00
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 )
}
2018-03-23 16:35:19 +00:00
2017-10-06 20:26:14 +00:00
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 )
}
2018-03-23 16:35:19 +00:00
2017-10-06 20:26:14 +00:00
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 TestValidateMultipleMethodsAuthInfo ( t * testing . T ) {
config := clientcmdapi . NewConfig ( )
config . AuthInfos [ "error" ] = & clientcmdapi . AuthInfo {
Token : "token" ,
Username : "username" ,
}
test := configValidationTest {
config : config ,
expectedErrorSubstring : [ ] string { "more than one authentication method" , "token" , "basicAuth" } ,
}
test . testAuthInfo ( "error" , t )
test . testConfig ( t )
}
2018-03-23 16:35:19 +00:00
func TestValidateAuthInfoExec ( t * testing . T ) {
config := clientcmdapi . NewConfig ( )
config . AuthInfos [ "user" ] = & clientcmdapi . AuthInfo {
Exec : & clientcmdapi . ExecConfig {
Command : "/bin/example" ,
APIVersion : "clientauthentication.k8s.io/v1alpha1" ,
Args : [ ] string { "hello" , "world" } ,
Env : [ ] clientcmdapi . ExecEnvVar {
{ Name : "foo" , Value : "bar" } ,
} ,
} ,
}
test := configValidationTest {
config : config ,
}
test . testAuthInfo ( "user" , t )
test . testConfig ( t )
}
func TestValidateAuthInfoExecNoVersion ( t * testing . T ) {
config := clientcmdapi . NewConfig ( )
config . AuthInfos [ "user" ] = & clientcmdapi . AuthInfo {
Exec : & clientcmdapi . ExecConfig {
Command : "/bin/example" ,
} ,
}
test := configValidationTest {
config : config ,
expectedErrorSubstring : [ ] string {
"apiVersion must be specified for user to use exec authentication plugin" ,
} ,
}
test . testAuthInfo ( "user" , t )
test . testConfig ( t )
}
func TestValidateAuthInfoExecNoCommand ( t * testing . T ) {
config := clientcmdapi . NewConfig ( )
config . AuthInfos [ "user" ] = & clientcmdapi . AuthInfo {
Exec : & clientcmdapi . ExecConfig {
APIVersion : "clientauthentication.k8s.io/v1alpha1" ,
} ,
}
test := configValidationTest {
config : config ,
expectedErrorSubstring : [ ] string {
"command must be specified for user to use exec authentication plugin" ,
} ,
}
test . testAuthInfo ( "user" , t )
test . testConfig ( t )
}
func TestValidateAuthInfoExecWithAuthProvider ( t * testing . T ) {
config := clientcmdapi . NewConfig ( )
config . AuthInfos [ "user" ] = & clientcmdapi . AuthInfo {
AuthProvider : & clientcmdapi . AuthProviderConfig {
Name : "oidc" ,
} ,
Exec : & clientcmdapi . ExecConfig {
Command : "/bin/example" ,
APIVersion : "clientauthentication.k8s.io/v1alpha1" ,
} ,
}
test := configValidationTest {
config : config ,
expectedErrorSubstring : [ ] string {
"authProvider cannot be provided in combination with an exec plugin for user" ,
} ,
}
test . testAuthInfo ( "user" , t )
test . testConfig ( t )
}
func TestValidateAuthInfoExecInvalidEnv ( t * testing . T ) {
config := clientcmdapi . NewConfig ( )
config . AuthInfos [ "user" ] = & clientcmdapi . AuthInfo {
Exec : & clientcmdapi . ExecConfig {
Command : "/bin/example" ,
APIVersion : "clientauthentication.k8s.io/v1alpha1" ,
Env : [ ] clientcmdapi . ExecEnvVar {
{ Name : "foo" } , // No value
} ,
} ,
}
test := configValidationTest {
config : config ,
expectedErrorSubstring : [ ] string {
"env variable foo value must be specified for user to use exec authentication plugin" ,
} ,
}
test . testAuthInfo ( "user" , t )
test . testConfig ( t )
}
2017-10-06 20:26:14 +00:00
type configValidationTest struct {
config * clientcmdapi . Config
expectedErrorSubstring [ ] string
}
func ( c configValidationTest ) testContext ( contextName string , t * testing . T ) {
errs := validateContext ( contextName , * c . config . Contexts [ contextName ] , * c . config )
if len ( c . expectedErrorSubstring ) != 0 {
if len ( errs ) == 0 {
t . Errorf ( "Expected error containing: %v" , c . expectedErrorSubstring )
}
for _ , curr := range c . expectedErrorSubstring {
if len ( errs ) != 0 && ! strings . Contains ( utilerrors . NewAggregate ( errs ) . Error ( ) , curr ) {
t . Errorf ( "Expected error containing: %v, but got %v" , c . expectedErrorSubstring , utilerrors . NewAggregate ( errs ) )
}
}
} else {
if len ( errs ) != 0 {
t . Errorf ( "Unexpected error: %v" , utilerrors . NewAggregate ( errs ) )
}
}
}
2018-03-23 16:35:19 +00:00
2017-10-06 20:26:14 +00:00
func ( c configValidationTest ) testConfirmUsable ( contextName string , t * testing . T ) {
err := ConfirmUsable ( * c . config , contextName )
if len ( c . expectedErrorSubstring ) != 0 {
if err == nil {
t . Errorf ( "Expected error containing: %v" , c . expectedErrorSubstring )
} else {
for _ , curr := range c . expectedErrorSubstring {
if err != nil && ! strings . Contains ( err . Error ( ) , curr ) {
t . Errorf ( "Expected error containing: %v, but got %v" , c . expectedErrorSubstring , err )
}
}
}
} else {
if err != nil {
t . Errorf ( "Unexpected error: %v" , err )
}
}
}
2018-03-23 16:35:19 +00:00
2017-10-06 20:26:14 +00:00
func ( c configValidationTest ) testConfig ( t * testing . T ) {
err := Validate ( * c . config )
if len ( c . expectedErrorSubstring ) != 0 {
if err == nil {
t . Errorf ( "Expected error containing: %v" , c . expectedErrorSubstring )
} else {
for _ , curr := range c . expectedErrorSubstring {
if err != nil && ! strings . Contains ( err . Error ( ) , curr ) {
t . Errorf ( "Expected error containing: %v, but got %v" , c . expectedErrorSubstring , err )
}
}
if ! IsConfigurationInvalid ( err ) {
t . Errorf ( "all errors should be configuration invalid: %v" , err )
}
}
} else {
if err != nil {
t . Errorf ( "Unexpected error: %v" , err )
}
}
}
2018-03-23 16:35:19 +00:00
2017-10-06 20:26:14 +00:00
func ( c configValidationTest ) testCluster ( clusterName string , t * testing . T ) {
errs := validateClusterInfo ( clusterName , * c . config . Clusters [ clusterName ] )
if len ( c . expectedErrorSubstring ) != 0 {
if len ( errs ) == 0 {
t . Errorf ( "Expected error containing: %v" , c . expectedErrorSubstring )
}
for _ , curr := range c . expectedErrorSubstring {
if len ( errs ) != 0 && ! strings . Contains ( utilerrors . NewAggregate ( errs ) . Error ( ) , curr ) {
t . Errorf ( "Expected error containing: %v, but got %v" , c . expectedErrorSubstring , utilerrors . NewAggregate ( errs ) )
}
}
} else {
if len ( errs ) != 0 {
t . Errorf ( "Unexpected error: %v" , utilerrors . NewAggregate ( errs ) )
}
}
}
func ( c configValidationTest ) testAuthInfo ( authInfoName string , t * testing . T ) {
errs := validateAuthInfo ( authInfoName , * c . config . AuthInfos [ authInfoName ] )
if len ( c . expectedErrorSubstring ) != 0 {
if len ( errs ) == 0 {
t . Errorf ( "Expected error containing: %v" , c . expectedErrorSubstring )
}
for _ , curr := range c . expectedErrorSubstring {
if len ( errs ) != 0 && ! strings . Contains ( utilerrors . NewAggregate ( errs ) . Error ( ) , curr ) {
t . Errorf ( "Expected error containing: %v, but got %v" , c . expectedErrorSubstring , utilerrors . NewAggregate ( errs ) )
}
}
} else {
if len ( errs ) != 0 {
t . Errorf ( "Unexpected error: %v" , utilerrors . NewAggregate ( errs ) )
}
}
}