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 }