@@ -35,8 +35,10 @@ func Provider() *schema.Provider {
3535 DefaultFunc : schema .EnvDefaultFunc ("KUBE_HOST" , nil ),
3636 Description : "The hostname (in form of URI) of Kubernetes master." ,
3737 ConflictsWith : []string {"config_path" , "config_paths" },
38- //AtLeastOneOf: []string{"token", "exec", "username", "password", "client_certificate", "client_key"},
3938 ValidateDiagFunc : validation .ToDiagFunc (validation .IsURLWithHTTPorHTTPS ),
39+ // TODO: enable this when AtLeastOneOf works with optional attributes.
40+ // Currently, it will require at least one of the following keys to be set, even if 'host' isn't set.
41+ // AtLeastOneOf: []string{"token", "exec", "username", "password", "client_certificate", "client_key"},
4042 },
4143 "username" : {
4244 Type : schema .TypeString ,
@@ -82,6 +84,7 @@ func Provider() *schema.Provider {
8284 DefaultFunc : schema .EnvDefaultFunc ("KUBE_CLUSTER_CA_CERT_DATA" , nil ),
8385 Description : "PEM-encoded root certificates bundle for TLS authentication." ,
8486 ConflictsWith : []string {"config_path" , "config_paths" , "insecure" },
87+ // TODO: enable this when AtLeastOneOf works with optional attributes.
8588 //AtLeastOneOf: []string{"token", "exec", "client_certificate", "client_key"},
8689 },
8790 "config_paths" : {
@@ -342,135 +345,134 @@ func providerConfigure(ctx context.Context, d *schema.ResourceData, terraformVer
342345 return m , diag.Diagnostics {}
343346}
344347
348+ func initializeConfiguration (d * schema.ResourceData ) (* restclient.Config , error ) {
349+ overrides := & clientcmd.ConfigOverrides {}
350+ loader := & clientcmd.ClientConfigLoadingRules {
351+ WarnIfAllMissing : true ,
352+ }
353+
354+ configPaths := []string {}
355+
356+ if v , ok := d .Get ("config_path" ).(string ); ok && v != "" {
357+ configPaths = []string {v }
358+ } else if v , ok := d .Get ("config_paths" ).([]interface {}); ok && len (v ) > 0 {
359+ for _ , p := range v {
360+ configPaths = append (configPaths , p .(string ))
361+ }
362+ } else if v := os .Getenv ("KUBE_CONFIG_PATHS" ); v != "" {
363+ // NOTE we have to do this here because the schema
364+ // does not yet allow you to set a default for a TypeList
365+ configPaths = filepath .SplitList (v )
366+ }
367+
368+ if len (configPaths ) > 0 {
369+ expandedPaths := []string {}
370+ for _ , p := range configPaths {
371+ path , err := homedir .Expand (p )
372+ if err != nil {
373+ return nil , err
374+ }
375+ if _ , err := os .Stat (path ); err != nil {
376+ return nil , fmt .Errorf ("could not open kubeconfig %q: %v" , p , err )
377+ }
378+
379+ log .Printf ("[DEBUG] Using kubeconfig: %s" , path )
380+ expandedPaths = append (expandedPaths , path )
381+ }
382+
383+ if len (expandedPaths ) == 1 {
384+ loader .ExplicitPath = expandedPaths [0 ]
385+ } else {
386+ loader .Precedence = expandedPaths
387+ }
388+
389+ ctxSuffix := "; default context"
390+
391+ kubectx , ctxOk := d .GetOk ("config_context" )
392+ authInfo , authInfoOk := d .GetOk ("config_context_auth_info" )
393+ cluster , clusterOk := d .GetOk ("config_context_cluster" )
394+ if ctxOk || authInfoOk || clusterOk {
395+ ctxSuffix = "; overridden context"
396+ if ctxOk {
397+ overrides .CurrentContext = kubectx .(string )
398+ ctxSuffix += fmt .Sprintf ("; config ctx: %s" , overrides .CurrentContext )
399+ log .Printf ("[DEBUG] Using custom current context: %q" , overrides .CurrentContext )
400+ }
401+
402+ overrides .Context = clientcmdapi.Context {}
403+ if authInfoOk {
404+ overrides .Context .AuthInfo = authInfo .(string )
405+ ctxSuffix += fmt .Sprintf ("; auth_info: %s" , overrides .Context .AuthInfo )
406+ }
407+ if clusterOk {
408+ overrides .Context .Cluster = cluster .(string )
409+ ctxSuffix += fmt .Sprintf ("; cluster: %s" , overrides .Context .Cluster )
410+ }
411+ log .Printf ("[DEBUG] Using overidden context: %#v" , overrides .Context )
412+ }
413+ }
414+
415+ // Overriding with static configuration
416+ if v , ok := d .GetOk ("insecure" ); ok && v != "" {
417+ overrides .ClusterInfo .InsecureSkipTLSVerify = v .(bool )
418+ }
419+ if v , ok := d .GetOk ("cluster_ca_certificate" ); ok && v != "" {
420+ overrides .ClusterInfo .CertificateAuthorityData = bytes .NewBufferString (v .(string )).Bytes ()
421+ }
422+ if v , ok := d .GetOk ("client_certificate" ); ok && v != "" {
423+ overrides .AuthInfo .ClientCertificateData = bytes .NewBufferString (v .(string )).Bytes ()
424+ }
425+ if v , ok := d .GetOk ("host" ); ok && v != "" {
426+ // Server has to be the complete address of the kubernetes cluster (scheme://hostname:port), not just the hostname,
427+ // because `overrides` are processed too late to be taken into account by `defaultServerUrlFor()`.
428+ // This basically replicates what defaultServerUrlFor() does with config but for overrides,
429+ // see https://github.com/kubernetes/client-go/blob/v12.0.0/rest/url_utils.go#L85-L87
430+ hasCA := len (overrides .ClusterInfo .CertificateAuthorityData ) != 0
431+ hasCert := len (overrides .AuthInfo .ClientCertificateData ) != 0
432+ defaultTLS := hasCA || hasCert || overrides .ClusterInfo .InsecureSkipTLSVerify
433+ host , _ , err := restclient .DefaultServerURL (v .(string ), "" , apimachineryschema.GroupVersion {}, defaultTLS )
434+ if err != nil {
435+ return nil , fmt .Errorf ("Failed to parse host: %s" , err )
436+ }
437+
438+ overrides .ClusterInfo .Server = host .String ()
439+ }
440+ if v , ok := d .GetOk ("username" ); ok && v != "" {
441+ overrides .AuthInfo .Username = v .(string )
442+ }
443+ if v , ok := d .GetOk ("password" ); ok && v != "" {
444+ overrides .AuthInfo .Password = v .(string )
445+ }
446+ if v , ok := d .GetOk ("client_key" ); ok && v != "" {
447+ overrides .AuthInfo .ClientKeyData = bytes .NewBufferString (v .(string )).Bytes ()
448+ }
449+ if v , ok := d .GetOk ("token" ); ok && v != "" {
450+ overrides .AuthInfo .Token = v .(string )
451+ }
452+
453+ if v , ok := d .GetOk ("exec" ); ok {
454+ exec := & clientcmdapi.ExecConfig {}
455+ if spec , ok := v .([]interface {})[0 ].(map [string ]interface {}); ok {
456+ exec .APIVersion = spec ["api_version" ].(string )
457+ exec .Command = spec ["command" ].(string )
458+ exec .Args = expandStringSlice (spec ["args" ].([]interface {}))
459+ for kk , vv := range spec ["env" ].(map [string ]interface {}) {
460+ exec .Env = append (exec .Env , clientcmdapi.ExecEnvVar {Name : kk , Value : vv .(string )})
461+ }
462+ } else {
463+ return nil , fmt .Errorf ("Failed to parse exec" )
464+ }
465+ overrides .AuthInfo .Exec = exec
466+ }
467+
468+ cc := clientcmd .NewNonInteractiveDeferredLoadingClientConfig (loader , overrides )
469+ cfg , err := cc .ClientConfig ()
470+ if err != nil {
471+ log .Printf ("[WARN] Invalid provider configuration was supplied. Provider operations likely to fail: %v" , err )
472+ return nil , nil
473+ }
345474
346- func initializeConfiguration (d * schema.ResourceData ) (* restclient.Config , error ) {
347- overrides := & clientcmd.ConfigOverrides {}
348- loader := & clientcmd.ClientConfigLoadingRules {
349- WarnIfAllMissing : true ,
350- }
351-
352- configPaths := []string {}
353-
354- if v , ok := d .Get ("config_path" ).(string ); ok && v != "" {
355- configPaths = []string {v }
356- } else if v , ok := d .Get ("config_paths" ).([]interface {}); ok && len (v ) > 0 {
357- for _ , p := range v {
358- configPaths = append (configPaths , p .(string ))
359- }
360- } else if v := os .Getenv ("KUBE_CONFIG_PATHS" ); v != "" {
361- // NOTE we have to do this here because the schema
362- // does not yet allow you to set a default for a TypeList
363- configPaths = filepath .SplitList (v )
364- }
365-
366- if len (configPaths ) > 0 {
367- expandedPaths := []string {}
368- for _ , p := range configPaths {
369- path , err := homedir .Expand (p )
370- if err != nil {
371- return nil , err
372- }
373- if _ , err := os .Stat (path ); err != nil {
374- return nil , fmt .Errorf ("could not open kubeconfig %q: %v" , p , err )
375- }
376-
377- log .Printf ("[DEBUG] Using kubeconfig: %s" , path )
378- expandedPaths = append (expandedPaths , path )
379- }
380-
381- if len (expandedPaths ) == 1 {
382- loader .ExplicitPath = expandedPaths [0 ]
383- } else {
384- loader .Precedence = expandedPaths
385- }
386-
387- ctxSuffix := "; default context"
388-
389- kubectx , ctxOk := d .GetOk ("config_context" )
390- authInfo , authInfoOk := d .GetOk ("config_context_auth_info" )
391- cluster , clusterOk := d .GetOk ("config_context_cluster" )
392- if ctxOk || authInfoOk || clusterOk {
393- ctxSuffix = "; overridden context"
394- if ctxOk {
395- overrides .CurrentContext = kubectx .(string )
396- ctxSuffix += fmt .Sprintf ("; config ctx: %s" , overrides .CurrentContext )
397- log .Printf ("[DEBUG] Using custom current context: %q" , overrides .CurrentContext )
398- }
399-
400- overrides .Context = clientcmdapi.Context {}
401- if authInfoOk {
402- overrides .Context .AuthInfo = authInfo .(string )
403- ctxSuffix += fmt .Sprintf ("; auth_info: %s" , overrides .Context .AuthInfo )
404- }
405- if clusterOk {
406- overrides .Context .Cluster = cluster .(string )
407- ctxSuffix += fmt .Sprintf ("; cluster: %s" , overrides .Context .Cluster )
408- }
409- log .Printf ("[DEBUG] Using overidden context: %#v" , overrides .Context )
410- }
411- }
412-
413- // Overriding with static configuration
414- if v , ok := d .GetOk ("insecure" ); ok && v != "" {
415- overrides .ClusterInfo .InsecureSkipTLSVerify = v .(bool )
416- }
417- if v , ok := d .GetOk ("cluster_ca_certificate" ); ok && v != "" {
418- overrides .ClusterInfo .CertificateAuthorityData = bytes .NewBufferString (v .(string )).Bytes ()
419- }
420- if v , ok := d .GetOk ("client_certificate" ); ok && v != "" {
421- overrides .AuthInfo .ClientCertificateData = bytes .NewBufferString (v .(string )).Bytes ()
422- }
423- if v , ok := d .GetOk ("host" ); ok && v != "" {
424- // Server has to be the complete address of the kubernetes cluster (scheme://hostname:port), not just the hostname,
425- // because `overrides` are processed too late to be taken into account by `defaultServerUrlFor()`.
426- // This basically replicates what defaultServerUrlFor() does with config but for overrides,
427- // see https://github.com/kubernetes/client-go/blob/v12.0.0/rest/url_utils.go#L85-L87
428- hasCA := len (overrides .ClusterInfo .CertificateAuthorityData ) != 0
429- hasCert := len (overrides .AuthInfo .ClientCertificateData ) != 0
430- defaultTLS := hasCA || hasCert || overrides .ClusterInfo .InsecureSkipTLSVerify
431- host , _ , err := restclient .DefaultServerURL (v .(string ), "" , apimachineryschema.GroupVersion {}, defaultTLS )
432- if err != nil {
433- return nil , fmt .Errorf ("Failed to parse host: %s" , err )
434- }
435-
436- overrides .ClusterInfo .Server = host .String ()
437- }
438- if v , ok := d .GetOk ("username" ); ok && v != "" {
439- overrides .AuthInfo .Username = v .(string )
440- }
441- if v , ok := d .GetOk ("password" ); ok && v != "" {
442- overrides .AuthInfo .Password = v .(string )
443- }
444- if v , ok := d .GetOk ("client_key" ); ok && v != "" {
445- overrides .AuthInfo .ClientKeyData = bytes .NewBufferString (v .(string )).Bytes ()
446- }
447- if v , ok := d .GetOk ("token" ); ok && v != "" {
448- overrides .AuthInfo .Token = v .(string )
449- }
450-
451- if v , ok := d .GetOk ("exec" ); ok {
452- exec := & clientcmdapi.ExecConfig {}
453- if spec , ok := v .([]interface {})[0 ].(map [string ]interface {}); ok {
454- exec .APIVersion = spec ["api_version" ].(string )
455- exec .Command = spec ["command" ].(string )
456- exec .Args = expandStringSlice (spec ["args" ].([]interface {}))
457- for kk , vv := range spec ["env" ].(map [string ]interface {}) {
458- exec .Env = append (exec .Env , clientcmdapi.ExecEnvVar {Name : kk , Value : vv .(string )})
459- }
460- } else {
461- return nil , fmt .Errorf ("Failed to parse exec" )
462- }
463- overrides .AuthInfo .Exec = exec
464- }
465-
466- cc := clientcmd .NewNonInteractiveDeferredLoadingClientConfig (loader , overrides )
467- cfg , err := cc .ClientConfig ()
468- if err != nil {
469- log .Printf ("[WARN] Invalid provider configuration was supplied. Provider operations likely to fail: %v" , err )
470- return nil , nil
471- }
472-
473- return cfg , nil
475+ return cfg , nil
474476}
475477
476478var useadmissionregistrationv1beta1 * bool
0 commit comments