Skip to content

Commit d6156c5

Browse files
committed
wip
1 parent 3267ed8 commit d6156c5

File tree

1 file changed

+131
-129
lines changed

1 file changed

+131
-129
lines changed

kubernetes/provider.go

Lines changed: 131 additions & 129 deletions
Original file line numberDiff line numberDiff line change
@@ -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

476478
var useadmissionregistrationv1beta1 *bool

0 commit comments

Comments
 (0)