func importK8s()

in cmd/hub/api/cluster.go [315:558]


func importK8s(importConfig ImportConfig, kind, name, environmentSelector, templateSelector string,
	autoCreateTemplate, createNewTemplate, waitAndTailDeployLogs, dryRun bool,
	pems io.Reader, clusterBearerToken,
	nativeRegion, nativeZone, nativeEndpoint, nativeClusterName,
	ingressIpOrHost, azureResourceGroup string,
	options ClusterOptions) error {

	environment, err := environmentBy(environmentSelector)
	if err != nil {
		return fmt.Errorf("Unable to retrieve Environment: %v", err)
	}
	cloudAccount, err := cloudAccountById(environment.CloudAccount, false)
	if err != nil {
		return fmt.Errorf("Unable to retrieve Cloud Account: %v", err)
	}
	err = verifyClusterCloudAccountKind(kind, cloudAccount)
	if err != nil {
		return err
	}
	name, fqdn, err := verifyClusterBaseDomain(name, cloudAccount)
	if err != nil {
		return err
	}

	ingressIp := ""
	ingressHost := ""

	if kind == "eks" {
		if nativeEndpoint == "" {
			cac, err := awsCloudAccountCredentials(cloudAccount.Id)
			if err != nil {
				return err
			}
			regions := make([]string, 0, 2)
			caRegion := cloudAccountRegion(cloudAccount)
			if caRegion != "" {
				if config.Debug {
					log.Printf("Cloud Account `%s` default region is `%s`", cloudAccount.Id, caRegion)
				}
				regions = append(regions, caRegion)
			}
			if config.AwsRegion != "" && !util.Contains(regions, config.AwsRegion) {
				regions = append(regions, config.AwsRegion)
			}
			for _, region := range regions {
				endpoint, ca, err := aws.DescribeEKSClusterWithStaticCredentials(region, nativeClusterName,
					cac.AccessKey, cac.SecretKey, cac.SessionToken)
				if err != nil {
					util.Warn("Unable to retrieve EKS cluster `%s` info in `%s` region: %v",
						nativeClusterName, region, err)
					continue
				}
				if endpoint != "" {
					if config.Verbose {
						log.Printf("Found EKS cluster `%s` in %s region with endpoint %s",
							nativeClusterName, region, endpoint)
					}
					if strings.HasPrefix(endpoint, "https://") && len(endpoint) > 8 {
						endpoint = endpoint[8:]
					}
					nativeEndpoint = endpoint
					if len(ca) > 0 {
						pems = bytes.NewReader(ca)
					}
					break
				}
			}
			if nativeEndpoint == "" {
				log.Fatal("EKS cluster endpoint (--eks-endpoint) must be provided")
			}
		}
	} else if kind == "hybrid" {
		if ingressIpOrHost == "" {
			parts := strings.Split(nativeEndpoint, ":")
			if len(parts) > 0 {
				ingressIpOrHost = parts[0]
			}
			if ingressIpOrHost == "" {
				log.Fatalf("Cannot determine ingress IP/hostname from API endpoint `%s`", nativeEndpoint)
			}
		}
		if net.ParseIP(ingressIpOrHost) != nil {
			ingressIp = ingressIpOrHost
		} else {
			ingressHost = ingressIpOrHost
		}
	}

	secrets, err := readImportSecrets(importConfig.SecretsOrder, pems)
	if err != nil {
		if !(kind == "openshift" && secrets != nil) { // OpenShift CA is optional
			return fmt.Errorf("Unable to read auth secrets: %v", err)
		}
	}
	hasCaCert := false
	for _, s := range secrets {
		if s.Name == "kubernetes.api.caCert" {
			hasCaCert = true
			break
		}
	}

	adapterTag := "adapter=" + kind
	if templateSelector == "" && autoCreateTemplate {
		templateSelector = fmt.Sprintf(importConfig.TemplateNameFormat, environment.Name)
	}

	var template *StackTemplate

	if templateSelector != "" && !createNewTemplate {
		template, err = templateBy(templateSelector)
		if err != nil && !strings.HasSuffix(err.Error(), " found") {
			return fmt.Errorf("Unable to retrieve adapter Template: %v", err)
		}
		if template != nil && !util.Contains(template.Tags, adapterTag) {
			util.Warn("Template `%s` [%s] contain no `%s` tag", template.Name, template.Id, adapterTag)
		}
	}

	if template == nil {
		if !autoCreateTemplate {
			return fmt.Errorf("No adapter Template found by `%s`", templateSelector)
		}

		asset := fmt.Sprintf("%s/%s-adapter-template.json.template", requestsBindata, kind)
		templateBytes, err := adapterTemplateFiles.ReadFile(asset)
		if err != nil {
			return fmt.Errorf("No %s embedded: %v", asset, err)
		}
		var templateRequest StackTemplateRequest
		err = json.Unmarshal(templateBytes, &templateRequest)
		if err != nil {
			return fmt.Errorf("Unable to unmarshall JSON into Template request: %v", err)
		}

		// TODO with createNewTemplate = true we can get a 400 HTTP
		// due to duplicate Template name which should be unique across organization
		templateRequest.Name = templateSelector // let use user-supplied selector as Template name, hope it's not id
		templateRequest.Tags = []string{adapterTag}
		templateRequest.TeamsPermissions = environment.TeamsPermissions // copy permissions from Environment
		templateRequest.ComponentsEnabled = clusterComponents(options)

		template, err = createTemplate(templateRequest)
		if err != nil {
			return fmt.Errorf("Unable to create adapter Template: %v", err)
		}
		err = initTemplate(template.Id)
		if err != nil {
			return fmt.Errorf("Unable to initialize adapter Template: %v", err)
		}
		if config.Verbose {
			log.Printf("Created %s adapter template `%s`", kind, template.Name)
		}
	}

	asset := fmt.Sprintf("%s/%s-adapter-instance.json.template", requestsBindata, kind)
	instanceBytes, err := adapterInstanceFiles.ReadFile(asset)
	if err != nil {
		return fmt.Errorf("No %s embedded: %v", asset, err)
	}
	var instanceRequest StackInstanceRequest
	err = json.Unmarshal(instanceBytes, &instanceRequest)
	if err != nil {
		return fmt.Errorf("Unable to unmarshall JSON into Stack Instance request: %v", err)
	}

	instanceRequest.Name = name
	instanceRequest.Tags = template.Tags
	instanceRequest.Environment = environment.Id
	instanceRequest.Template = template.Id
	parameters := make([]Parameter, 0, len(instanceRequest.Parameters))
	for _, p := range instanceRequest.Parameters {
		rm := false
		switch p.Name {
		case "dns.domain":
			p.Value = fqdn
		case "cloud.region":
			if nativeRegion != "" {
				p.Value = nativeRegion
			} else {
				rm = true
			}
		case "cloud.availabilityZone":
			if nativeZone != "" {
				p.Value = nativeZone
			} else {
				rm = true
			}
		case "kubernetes.api.endpoint":
			if nativeEndpoint != "" {
				p.Value = nativeEndpoint
			} else {
				rm = true
			}
		case "kubernetes.api.caCert":
			if !hasCaCert {
				rm = true
			}
		case "kubernetes.eks.cluster", "kubernetes.gke.cluster", "kubernetes.aks.cluster":
			p.Value = nativeClusterName
		case "component.ingress.staticIp":
			p.Value = ingressIp
		case "component.ingress.staticHost":
			p.Value = ingressHost
		case "cloud.azureResourceGroupName", "component.kubernetes.aks.resourceGroupName":
			if azureResourceGroup != "" {
				p.Value = azureResourceGroup
			} else {
				rm = true
			}
		}
		p = clusterOptions(p, options)
		if !rm {
			parameters = append(parameters, p)
		}
	}
	instanceRequest.Parameters = parameters

	instance, err := createStackInstance(instanceRequest)
	if err != nil {
		return fmt.Errorf("Unable to create adapter Stack Instance: %v", err)
	}

	if kind == "openshift" && clusterBearerToken != "" {
		secrets = append(secrets,
			Secret{"kubernetes.api.token", "bearerToken", map[string]string{"bearerToken": clusterBearerToken}})
	}
	for _, secret := range secrets {
		id, err := createSecret(stackInstancesResource, instance.Id, secret.Name, "", secret.Kind, secret.Values)
		if err != nil {
			return err
		}
		if config.Verbose {
			log.Printf("Created %s secret with id %s", secret.Name, id)
		}
	}

	_, err = commandStackInstance(instance.Id, "deploy", nil, waitAndTailDeployLogs, dryRun)
	if err != nil {
		return fmt.Errorf("Unable to deploy adapter Stack Instance: %v", err)
	}

	return nil
}