github.com/skyscape-cloud-services/terraform@v0.9.2-0.20170609144644-7ece028a1747/builtin/providers/kubernetes/provider.go (about)

     1  package kubernetes
     2  
     3  import (
     4  	"bytes"
     5  	"fmt"
     6  	"log"
     7  	"os"
     8  
     9  	"github.com/hashicorp/terraform/helper/schema"
    10  	"github.com/hashicorp/terraform/terraform"
    11  	"github.com/mitchellh/go-homedir"
    12  	restclient "k8s.io/client-go/rest"
    13  	"k8s.io/client-go/tools/clientcmd"
    14  	clientcmdapi "k8s.io/client-go/tools/clientcmd/api"
    15  	kubernetes "k8s.io/kubernetes/pkg/client/clientset_generated/clientset"
    16  )
    17  
    18  func Provider() terraform.ResourceProvider {
    19  	return &schema.Provider{
    20  		Schema: map[string]*schema.Schema{
    21  			"host": {
    22  				Type:        schema.TypeString,
    23  				Optional:    true,
    24  				DefaultFunc: schema.EnvDefaultFunc("KUBE_HOST", ""),
    25  				Description: "The hostname (in form of URI) of Kubernetes master.",
    26  			},
    27  			"username": {
    28  				Type:        schema.TypeString,
    29  				Optional:    true,
    30  				DefaultFunc: schema.EnvDefaultFunc("KUBE_USER", ""),
    31  				Description: "The username to use for HTTP basic authentication when accessing the Kubernetes master endpoint.",
    32  			},
    33  			"password": {
    34  				Type:        schema.TypeString,
    35  				Optional:    true,
    36  				DefaultFunc: schema.EnvDefaultFunc("KUBE_PASSWORD", ""),
    37  				Description: "The password to use for HTTP basic authentication when accessing the Kubernetes master endpoint.",
    38  			},
    39  			"insecure": {
    40  				Type:        schema.TypeBool,
    41  				Optional:    true,
    42  				DefaultFunc: schema.EnvDefaultFunc("KUBE_INSECURE", false),
    43  				Description: "Whether server should be accessed without verifying the TLS certificate.",
    44  			},
    45  			"client_certificate": {
    46  				Type:        schema.TypeString,
    47  				Optional:    true,
    48  				DefaultFunc: schema.EnvDefaultFunc("KUBE_CLIENT_CERT_DATA", ""),
    49  				Description: "PEM-encoded client certificate for TLS authentication.",
    50  			},
    51  			"client_key": {
    52  				Type:        schema.TypeString,
    53  				Optional:    true,
    54  				DefaultFunc: schema.EnvDefaultFunc("KUBE_CLIENT_KEY_DATA", ""),
    55  				Description: "PEM-encoded client certificate key for TLS authentication.",
    56  			},
    57  			"cluster_ca_certificate": {
    58  				Type:        schema.TypeString,
    59  				Optional:    true,
    60  				DefaultFunc: schema.EnvDefaultFunc("KUBE_CLUSTER_CA_CERT_DATA", ""),
    61  				Description: "PEM-encoded root certificates bundle for TLS authentication.",
    62  			},
    63  			"config_path": {
    64  				Type:     schema.TypeString,
    65  				Optional: true,
    66  				DefaultFunc: schema.MultiEnvDefaultFunc(
    67  					[]string{
    68  						"KUBE_CONFIG",
    69  						"KUBECONFIG",
    70  					},
    71  					"~/.kube/config"),
    72  				Description: "Path to the kube config file, defaults to ~/.kube/config",
    73  			},
    74  			"config_context": {
    75  				Type:        schema.TypeString,
    76  				Optional:    true,
    77  				DefaultFunc: schema.EnvDefaultFunc("KUBE_CTX", ""),
    78  			},
    79  			"config_context_auth_info": {
    80  				Type:        schema.TypeString,
    81  				Optional:    true,
    82  				DefaultFunc: schema.EnvDefaultFunc("KUBE_CTX_AUTH_INFO", ""),
    83  				Description: "",
    84  			},
    85  			"config_context_cluster": {
    86  				Type:        schema.TypeString,
    87  				Optional:    true,
    88  				DefaultFunc: schema.EnvDefaultFunc("KUBE_CTX_CLUSTER", ""),
    89  				Description: "",
    90  			},
    91  		},
    92  
    93  		ResourcesMap: map[string]*schema.Resource{
    94  			"kubernetes_config_map":                resourceKubernetesConfigMap(),
    95  			"kubernetes_horizontal_pod_autoscaler": resourceKubernetesHorizontalPodAutoscaler(),
    96  			"kubernetes_limit_range":               resourceKubernetesLimitRange(),
    97  			"kubernetes_namespace":                 resourceKubernetesNamespace(),
    98  			"kubernetes_persistent_volume":         resourceKubernetesPersistentVolume(),
    99  			"kubernetes_persistent_volume_claim":   resourceKubernetesPersistentVolumeClaim(),
   100  			"kubernetes_pod":                       resourceKubernetesPod(),
   101  			"kubernetes_resource_quota":            resourceKubernetesResourceQuota(),
   102  			"kubernetes_secret":                    resourceKubernetesSecret(),
   103  			"kubernetes_service":                   resourceKubernetesService(),
   104  		},
   105  		ConfigureFunc: providerConfigure,
   106  	}
   107  }
   108  
   109  func providerConfigure(d *schema.ResourceData) (interface{}, error) {
   110  	// Config file loading
   111  	cfg, err := tryLoadingConfigFile(d)
   112  	if err != nil {
   113  		return nil, err
   114  	}
   115  	if cfg == nil {
   116  		cfg = &restclient.Config{}
   117  	}
   118  
   119  	// Overriding with static configuration
   120  	cfg.UserAgent = fmt.Sprintf("HashiCorp/1.0 Terraform/%s", terraform.VersionString())
   121  
   122  	if v, ok := d.GetOk("host"); ok {
   123  		cfg.Host = v.(string)
   124  	}
   125  	if v, ok := d.GetOk("username"); ok {
   126  		cfg.Username = v.(string)
   127  	}
   128  	if v, ok := d.GetOk("password"); ok {
   129  		cfg.Password = v.(string)
   130  	}
   131  	if v, ok := d.GetOk("insecure"); ok {
   132  		cfg.Insecure = v.(bool)
   133  	}
   134  	if v, ok := d.GetOk("cluster_ca_certificate"); ok {
   135  		cfg.CAData = bytes.NewBufferString(v.(string)).Bytes()
   136  	}
   137  	if v, ok := d.GetOk("client_certificate"); ok {
   138  		cfg.CertData = bytes.NewBufferString(v.(string)).Bytes()
   139  	}
   140  	if v, ok := d.GetOk("client_key"); ok {
   141  		cfg.KeyData = bytes.NewBufferString(v.(string)).Bytes()
   142  	}
   143  
   144  	k, err := kubernetes.NewForConfig(cfg)
   145  	if err != nil {
   146  		return nil, fmt.Errorf("Failed to configure: %s", err)
   147  	}
   148  
   149  	return k, nil
   150  }
   151  
   152  func tryLoadingConfigFile(d *schema.ResourceData) (*restclient.Config, error) {
   153  	path, err := homedir.Expand(d.Get("config_path").(string))
   154  	if err != nil {
   155  		return nil, err
   156  	}
   157  
   158  	loader := &clientcmd.ClientConfigLoadingRules{
   159  		ExplicitPath: path,
   160  	}
   161  
   162  	overrides := &clientcmd.ConfigOverrides{}
   163  	ctxSuffix := "; default context"
   164  
   165  	ctx, ctxOk := d.GetOk("config_context")
   166  	authInfo, authInfoOk := d.GetOk("config_context_auth_info")
   167  	cluster, clusterOk := d.GetOk("config_context_cluster")
   168  	if ctxOk || authInfoOk || clusterOk {
   169  		ctxSuffix = "; overriden context"
   170  		if ctxOk {
   171  			overrides.CurrentContext = ctx.(string)
   172  			ctxSuffix += fmt.Sprintf("; config ctx: %s", overrides.CurrentContext)
   173  			log.Printf("[DEBUG] Using custom current context: %q", overrides.CurrentContext)
   174  		}
   175  
   176  		overrides.Context = clientcmdapi.Context{}
   177  		if authInfoOk {
   178  			overrides.Context.AuthInfo = authInfo.(string)
   179  			ctxSuffix += fmt.Sprintf("; auth_info: %s", overrides.Context.AuthInfo)
   180  		}
   181  		if clusterOk {
   182  			overrides.Context.Cluster = cluster.(string)
   183  			ctxSuffix += fmt.Sprintf("; cluster: %s", overrides.Context.Cluster)
   184  		}
   185  		log.Printf("[DEBUG] Using overidden context: %#v", overrides.Context)
   186  	}
   187  
   188  	cc := clientcmd.NewNonInteractiveDeferredLoadingClientConfig(loader, overrides)
   189  	cfg, err := cc.ClientConfig()
   190  	if err != nil {
   191  		if pathErr, ok := err.(*os.PathError); ok && os.IsNotExist(pathErr.Err) {
   192  			log.Printf("[INFO] Unable to load config file as it doesn't exist at %q", path)
   193  			return nil, nil
   194  		}
   195  		return nil, fmt.Errorf("Failed to load config (%s%s): %s", path, ctxSuffix, err)
   196  	}
   197  
   198  	log.Printf("[INFO] Successfully loaded config file (%s%s)", path, ctxSuffix)
   199  	return cfg, nil
   200  }