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
}