in images/controller/cmd/reservation_broker/reservation_broker.go [591:665]
func createApp(app broker.AppConfigSpec, appCtx *AppContext, user, username string) (int, string) {
statusCode := http.StatusOK
msg := ""
// Lock the reservation table so that users get an atomic reservation and they can't reserve multiple pods.
appCtx.Lock()
defer appCtx.Unlock()
if pod, ok := appCtx.ReservedPods[user]; ok {
msg = fmt.Sprintf("pod for %s: %s", user, pod.Name)
return statusCode, msg
}
if len(appCtx.AvailablePods) == 0 {
statusCode = http.StatusNotFound
msg = "No available instances at this time"
return statusCode, msg
}
// Generate session key
sessionKey := broker.MakeSessionKey()
// Assign user a pod and remove it from the list
pod := appCtx.AvailablePods[0]
appCtx.AvailablePods = appCtx.AvailablePods[1:]
pod.SessionKey = sessionKey
// Build the per-user manifest templates
destDir, err := buildUserBundle(app, appCtx, user, username, pod)
if err != nil {
log.Printf("failed to build user bundle for %s/%s: %v", app.Name, user, err)
statusCode = http.StatusInternalServerError
msg = "error creating app"
return statusCode, msg
}
// Determine the unique kinds of objects being applied and add them to a json patch that will add the list to an annotation.
// This is done because 'kubectl delete all' does not capture things like CRDs or VirtualService so object can get orphaned.
// See also: https://github.com/kubernetes/kubectl/issues/151
userObjects, err := broker.GetObjectTypes(destDir)
if err != nil {
log.Printf("failed to determine object types in bundle: %v", err)
statusCode = http.StatusInternalServerError
msg = "error creating app"
return statusCode, msg
}
pod.UserObjects = userObjects
// Update the pod for the user
if err := updatePodForUser(app, user, pod.SessionKey, pod.Name, pod.UserObjects); err != nil {
log.Printf("failed to update pod for user %s: %s: %v", user, pod.Name, err)
statusCode = http.StatusInternalServerError
msg = "error creating app"
return statusCode, msg
}
// Apply the per-user manifests
cmd := exec.Command("sh", "-o", "pipefail", "-c", fmt.Sprintf("kustomize build %s | kubectl apply -f -", destDir))
cmd.Dir = destDir
stdoutStderr, err := cmd.CombinedOutput()
if err != nil {
log.Printf("error applying per-user manifests for %s: %v\n%s", user, err, stdoutStderr)
statusCode = http.StatusInternalServerError
msg = "error creating app"
return statusCode, msg
}
log.Printf("assigned pod %s to user: %s", pod.Name, user)
// Reserve pod for user in map
appCtx.ReservedPods[user] = pod
msg = fmt.Sprintf("assigned pod: %s", pod.Name)
return statusCode, msg
}