func createK8s()

in cmd/hub/api/cluster.go [124:292]


func createK8s(kind, name, environmentSelector, templateSelector string,
	autoCreateTemplate, createNewTemplate, waitAndTailDeployLogs, dryRun bool,
	nativeRegion, nativeZone, nativeClusterName,
	eksAdmin, 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
	}

	platformTag := "platform=" + kind
	if templateSelector == "" && autoCreateTemplate {
		templateSelector = fmt.Sprintf("%s in %s", strings.ToUpper(kind), environment.Name)
	}

	var template *StackTemplate

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

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

		asset := fmt.Sprintf("%s/%s-cluster-template.json.template", requestsBindata, kind)
		templateBytes, err := clusterTemplateFiles.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{platformTag}
		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 cluster Template: %v", err)
		}
		err = initTemplate(template.Id)
		if err != nil {
			return fmt.Errorf("Unable to initialize cluster Template: %v", err)
		}
		if config.Verbose {
			log.Printf("Created %s cluster template `%s`", kind, template.Name)
		}
	}

	asset := fmt.Sprintf("%s/%s-cluster-instance.json.template", requestsBindata, kind)
	instanceBytes, err := clusterInstanceFiles.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.name":
			p.Value = name
		case "dns.domain":
			p.Value = fqdn
		case "cloud.region":
			if nativeRegion != "" {
				p.Value = nativeRegion
			} else {
				rm = true
			}
		case "cloud.availabilityZone":
			if nativeZone != "" && !strings.Contains(nativeZone, ",") {
				p.Value = nativeZone
			} else {
				rm = true
			}
		case "cloud.availabilityZones":
			if nativeZone != "" && strings.Contains(nativeZone, ",") {
				p.Value = nativeZone
			} else {
				rm = true
			}
		case "component.kubernetes.eks.admin":
			p.Value = eksAdmin
		case "component.kubernetes.eks.cluster", "component.kubernetes.gke.cluster", "component.kubernetes.aks.cluster":
			p.Value = nativeClusterName
		case "cloud.azureResourceGroupName":
			if azureResourceGroup != "" {
				p.Value = azureResourceGroup
			} else {
				rm = true
			}
		case "component.kubernetes.worker.size", "component.kubernetes.gke.nodeMachineType": // TODO worker.instance.size
			p.Value = options.InstanceType
		case "component.kubernetes.worker.count", "component.kubernetes.gke.minNodeCount":
			p.Value = options.Count
		case "component.kubernetes.worker.maxCount", "component.kubernetes.gke.maxNodeCount":
			if options.MaxCount != 0 {
				p.Value = options.MaxCount
			} else {
				rm = true
			}
		case "component.kubernetes.worker.volume.size":
			if options.VolumeSize != 0 {
				p.Value = options.VolumeSize
			} else {
				rm = true
			}
		case "component.kubernetes.worker.spotPrice": // TODO worker.aws.spotPrice
			if options.SpotPrice > 0 {
				p.Value = options.SpotPrice
			}
		case "component.kubernetes.gke.preemptibleNodes": // TODO worker.gcp.preemptible.enabled
			p.Value = options.PreemptibleVMs
		}
		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 cluster Stack Instance: %v", err)
	}

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

	return nil
}