func SetupKubernetes()

in cmd/hub/kube/kubernetes.go [155:363]


func SetupKubernetes(params parameters.LockedParameters,
	provider string, outputs parameters.CapturedOutputs,
	context string, overwrite, keepPems bool) {

	kubectl := "kubectl"
	domain, _ := mayOutput(params, outputs, provider, stackDomainOutput)
	if domain == "" {
		util.Debug("Parameters from %s are not providing: %s", provider, stackDomainOutput) // try to get domain from environment
		name, val := getFirstEnviron("HUB_DOMAIN_NAME", "DOMAIN_NAME")
		if val != "" {
			util.Debug("Using %s from %s variable as %s", val, name, stackDomainOutput)
			domain = val
		} else {
			// Porting fuzzy logic here from extensions, for compatibility
			// When stack doesn't have a ingress domain.
			// In this case user will declare only a stack name
			util.Debug("Cannot find dns.domain from variables")
			util.Debug("Trying %s instead for stack that doesn't use ingress", stackNameOutput)
			stackName, _ := mayOutput(params, outputs, provider, stackNameOutput)
			if stackName != "" {
				domain = stackName
			} else {
				util.Debug("Trying environment variables")
				name, val = getFirstEnviron("HUB_STACK_NAME", "STACK_NAME")
				if val != "" {
					util.Debug("Using %s from %s variable as %s", val, name, stackNameOutput)
					domain = val
				} else {
					util.Warn("Giving up with domain name from %s", provider)
				}
			}
		}
	}
	if domain == "" {
		util.Errors("Unable to setup Kubeconfig: no domain name found")
		os.Exit(1)
		return
	}

	if context != "" {
		util.Debug("Using kube context: %s", context)
	}
	if context == "" {
		context = domain
	}

	flavor, _ := mayOutput(params, outputs, provider, kubernetesFlavorOutput)
	if flavor == "" {
		flavor = "k8s-aws"
	}

	eksClusterName := ""
	bearerToken := ""
	switch flavor {
	case "eks":
		eksClusterName = mustOutput(params, outputs, provider, kubernetesEksClusterOutput)
		bearerToken, _ = mayOutput(params, outputs, provider, kubernetesApiTokenOutput)
	case "openshift", "gke", "aks":
		bearerToken = mustOutput(params, outputs, provider, kubernetesApiTokenOutput)
	}

	configFilename, err := kubeconfigFilename()
	if err != nil {
		util.WarnOnce("Unable to setup Kubeconfig: %v", err)
		return
	}

	var configCmd string
	if config.SwitchKubeconfigContext {
		if config.Verbose {
			log.Printf("Changing Kubeconfig context to `%s`", context)
		}
		configCmd = "use-context"
	} else {
		if config.Verbose {
			log.Printf("Checking Kubeconfig context `%s`", context)
		}
		configCmd = "get-contexts"
	}

	outBytes, err := execOutput(kubectl, "config", configCmd, context)
	if err == nil {
		if !overwrite {
			// check CA cert match to
			// catch Kubeconfig leftovers from previous deployment to the same domain name
			if ca, exist := mayOutput(params, outputs, provider, kubernetesApiCaCertOutput); exist && ca != "" {
				warnClusterCaCertMismatch(configFilename, context, ca)
			}
			return
		}
	} else {
		out := string(outBytes)
		if !strings.Contains(out, "no context exists") && !strings.Contains(out, "not found") {
			util.MaybeFatalf("kubectl failed: %v", err)
		}
	}

	if config.Verbose {
		if provider != "" {
			log.Printf("Setting up Kubeconfig from `%s` outputs", provider)
			if config.Debug {
				parameters.PrintCapturedOutputsByComponent(outputs, provider)
			}
		} else {
			log.Printf("Setting up Kubeconfig from stack parameters")
		}
	}

	filenameBase := filepath.Join(filepath.Dir(configFilename), strings.Replace(domain, ".", "-", -1))
	caCertFile := filenameBase + kubernetesApiKeysFileSuf[kubernetesApiCaCertOutput]
	clientCertFile := filenameBase + kubernetesApiKeysFileSuf[kubernetesApiClientCertOutput]
	clientKeyFile := filenameBase + kubernetesApiKeysFileSuf[kubernetesApiClientKeyOutput]

	var caCert string
	caCertExist := true
	if flavor != "openshift" {
		caCert = mustOutput(params, outputs, provider, kubernetesApiCaCertOutput)
	} else {
		caCert, caCertExist = mayOutput(params, outputs, provider, kubernetesApiCaCertOutput)
	}
	var pemsWritten []string
	if caCertExist {
		writeFile(caCertFile, caCert)
		pemsWritten = append(pemsWritten, caCertFile)
	}
	if util.Contains([]string{"k8s-aws", "hybrid", "metal"}, flavor) {
		writeFile(clientCertFile,
			mustOutput(params, outputs, provider, kubernetesApiClientCertOutput))
		writeFile(clientKeyFile,
			mustOutput(params, outputs, provider, kubernetesApiClientKeyOutput))
		pemsWritten = append(pemsWritten, clientCertFile, clientKeyFile)
	}

	apiEndpoint := domain
	if endpoint, exist := mayOutput(params, outputs, provider, kubernetesApiEndpointOutput); exist && endpoint != "" {
		apiEndpoint = endpoint
	}

	clusterArgs := []string{"config", "set-cluster", domain, "--server=https://" + apiEndpoint}
	if caCertExist {
		clusterArgs = append(clusterArgs, "--embed-certs=true", "--certificate-authority="+caCertFile)
	}
	mustExec(kubectl, clusterArgs...)
	user := ""
	switch flavor {
	case "k8s-aws", "hybrid", "metal":
		user = "admin@" + domain
		mustExec(kubectl, "config", "set-credentials", user,
			"--embed-certs=true",
			"--client-key="+clientKeyFile,
			"--client-certificate="+clientCertFile)

	case "eks":
		user = "eks-" + eksClusterName
		if bearerToken != "" {
			mustExec(kubectl, "config", "set-credentials", user,
				"--token="+bearerToken)
			mustExec(kubectl, "config", "unset", fmt.Sprintf("users.%s.exec", user))
		} else {
			mustExec(kubectl, "config", "set-credentials", user,
				"--exec-api-version=client.authentication.k8s.io/v1alpha1",
				"--exec-command=aws-iam-authenticator",
				"--exec-arg=token",
				"--exec-arg=-i",
				"--exec-arg="+eksClusterName)
			mustExec(kubectl, "config", "unset", fmt.Sprintf("users.%s.token", user))
		}

	case "openshift", "gke", "aks":
		user = fmt.Sprintf("%s-%s", flavor, domain)
		mustExec(kubectl, "config", "set-credentials", user,
			"--token="+bearerToken)
	}
	mustExec(kubectl, "config", "set-context", context,
		"--cluster="+domain,
		"--user="+user,
		"--namespace=kube-system")
	switchContext := config.SwitchKubeconfigContext
	if os.Getenv("HUB_KUBECONFIG") != "" {
		kubeconfig := os.Getenv("HUB_KUBECONFIG")
		os.Setenv("KUBECONFIG", kubeconfig)
	}

	if !switchContext && os.Getenv("KUBECONFIG") != "" {
		// Hub CTL extensions expects a private Kubeconfig with current-context set
		outBytes, err := execOutput(kubectl, "config", "current-context")
		out := string(outBytes)
		if strings.Contains(out, "current-context is not set") {
			switchContext = true
		}
		if !switchContext && err != nil {
			if processErr, ok := err.(*exec.ExitError); ok && processErr.ExitCode() == 1 {
				switchContext = true
			}
		}
	}
	if switchContext {
		mustExec(kubectl, "config", "use-context", context)
	}
	if !keepPems {
		for _, filename := range pemsWritten {
			if err := os.Remove(filename); err != nil {
				util.WarnOnce("Unable to remove `%s`: %v", filename, err)
			} else if config.Debug {
				log.Printf("Removed `%s`", filename)
			}
		}
	}
}