func getEnv(w http.ResponseWriter, r *http.Request, t auth.Token) error { var variables []string if r.Body != nil { defer r.Body.Close() err := json.NewDecoder(r.Body).Decode(&variables) if err != nil && err != io.EOF { return err } } appName := r.URL.Query().Get(":app") var u *auth.User var err error if !t.IsAppToken() { u, err = t.User() if err != nil { return err } rec.Log(u.Email, "get-env", "app="+appName, fmt.Sprintf("envs=%s", variables)) } app, err := getAppFromContext(appName, u, r) if err != nil { return err } return writeEnvVars(w, &app, variables...) }
func getEnv(w http.ResponseWriter, r *http.Request, t auth.Token) error { var variables []string if r.Body != nil { defer r.Body.Close() err := json.NewDecoder(r.Body).Decode(&variables) if err != nil && err != io.EOF { return err } } appName := r.URL.Query().Get(":app") var u *auth.User var err error a, err := getAppFromContext(appName, r) if err != nil { return err } if !t.IsAppToken() { u, err = t.User() if err != nil { return err } rec.Log(u.Email, "get-env", "app="+appName, fmt.Sprintf("envs=%s", variables)) allowed := permission.Check(t, permission.PermAppReadEnv, append(permission.Contexts(permission.CtxTeam, a.Teams), permission.Context(permission.CtxApp, a.Name), permission.Context(permission.CtxPool, a.Pool), )..., ) if !allowed { return permission.ErrUnauthorized } } return writeEnvVars(w, &a, variables...) }
func getEnv(w http.ResponseWriter, r *http.Request, t *auth.Token) error { var variables []string if r.Body != nil { defer r.Body.Close() err := json.NewDecoder(r.Body).Decode(&variables) if err != nil && err != io.EOF { return err } } appName := r.URL.Query().Get(":app") var u *auth.User = nil var err error if !t.IsAppToken() { u, err = t.User() if err != nil { return err } rec.Log(u.Email, "get-env", "app="+appName, fmt.Sprintf("envs=%s", variables)) } app, err := getApp(appName, u) if err != nil { return err } var result []map[string]interface{} w.Header().Set("Content-Type", "application/json") if len(variables) > 0 { for _, variable := range variables { if v, ok := app.Env[variable]; ok { item := map[string]interface{}{ "name": v.Name, "value": v.Value, "public": v.Public, } result = append(result, item) } } } else { for _, v := range app.Env { item := map[string]interface{}{ "name": v.Name, "value": v.Value, "public": v.Public, } result = append(result, item) } } return json.NewEncoder(w).Encode(result) }
// title: get envs // path: /apps/{app}/env // method: GET // produce: application/x-json-stream // responses: // 200: OK // 401: Unauthorized // 404: App not found func getEnv(w http.ResponseWriter, r *http.Request, t auth.Token) error { var variables []string if envs, ok := r.URL.Query()["env"]; ok { variables = envs } appName := r.URL.Query().Get(":app") a, err := getAppFromContext(appName, r) if err != nil { return err } if !t.IsAppToken() { allowed := permission.Check(t, permission.PermAppReadEnv, contextsForApp(&a)..., ) if !allowed { return permission.ErrUnauthorized } } return writeEnvVars(w, &a, variables...) }
func deploy(w http.ResponseWriter, r *http.Request, t auth.Token) error { var file multipart.File var err error if strings.HasPrefix(r.Header.Get("Content-Type"), "multipart/") { file, _, err = r.FormFile("file") if err != nil { return &errors.HTTP{ Code: http.StatusBadRequest, Message: err.Error(), } } } version := r.PostFormValue("version") archiveURL := r.PostFormValue("archive-url") if version == "" && archiveURL == "" && file == nil { return &errors.HTTP{ Code: http.StatusBadRequest, Message: "you must specify either the version, the archive-url or upload a file", } } if version != "" && archiveURL != "" { return &errors.HTTP{ Code: http.StatusBadRequest, Message: "you must specify either the version or the archive-url, but not both", } } commit := r.PostFormValue("commit") w.Header().Set("Content-Type", "text") appName := r.URL.Query().Get(":appname") var userName string var instance *app.App if t.IsAppToken() { if t.GetAppName() != appName && t.GetAppName() != app.InternalAppName { return &errors.HTTP{Code: http.StatusUnauthorized, Message: "invalid app token"} } instance, err = app.GetByName(appName) if err != nil { return &errors.HTTP{Code: http.StatusNotFound, Message: err.Error()} } userName = r.PostFormValue("user") } else { var user *auth.User var app app.App user, err = t.User() if err != nil { return err } app, err = getApp(appName, user, r) if err != nil { return err } instance = &app userName = t.GetUserName() } writer := io.NewKeepAliveWriter(w, 30*time.Second, "please wait...") defer writer.Stop() err = app.Deploy(app.DeployOptions{ App: instance, Version: version, Commit: commit, File: file, ArchiveURL: archiveURL, OutputStream: writer, User: userName, }) if err == nil { fmt.Fprintln(w, "\nOK") } return err }
func deploy(w http.ResponseWriter, r *http.Request, t auth.Token) error { var file multipart.File var err error if strings.HasPrefix(r.Header.Get("Content-Type"), "multipart/") { file, _, err = r.FormFile("file") if err != nil { return &errors.HTTP{ Code: http.StatusBadRequest, Message: err.Error(), } } } archiveURL := r.PostFormValue("archive-url") image := r.PostFormValue("image") if image == "" && archiveURL == "" && file == nil { return &errors.HTTP{ Code: http.StatusBadRequest, Message: "you must specify either the archive-url, a image url or upload a file.", } } commit := r.PostFormValue("commit") w.Header().Set("Content-Type", "text") appName := r.URL.Query().Get(":appname") origin := r.URL.Query().Get("origin") if image != "" { origin = "image" } if origin != "" { if !app.ValidateOrigin(origin) { return &errors.HTTP{ Code: http.StatusBadRequest, Message: "Invalid deployment origin", } } } var userName string if t.IsAppToken() { if t.GetAppName() != appName && t.GetAppName() != app.InternalAppName { return &errors.HTTP{Code: http.StatusUnauthorized, Message: "invalid app token"} } userName = r.PostFormValue("user") } else { userName = t.GetUserName() } instance, err := app.GetByName(appName) if err != nil { return &errors.HTTP{Code: http.StatusNotFound, Message: err.Error()} } if t.GetAppName() != app.InternalAppName { canDeploy := permission.Check(t, permission.PermAppDeploy, append(permission.Contexts(permission.CtxTeam, instance.Teams), permission.Context(permission.CtxApp, appName), permission.Context(permission.CtxPool, instance.Pool), )..., ) if !canDeploy { return &errors.HTTP{Code: http.StatusForbidden, Message: "User does not have access to this app"} } } writer := io.NewKeepAliveWriter(w, 30*time.Second, "please wait...") defer writer.Stop() var build bool buildString := r.URL.Query().Get("build") if buildString != "" { build, err = strconv.ParseBool(buildString) if err != nil { return &errors.HTTP{ Code: http.StatusBadRequest, Message: err.Error(), } } } err = app.Deploy(app.DeployOptions{ App: instance, Commit: commit, File: file, ArchiveURL: archiveURL, OutputStream: writer, User: userName, Image: image, Origin: origin, Build: build, }) if err == nil { fmt.Fprintln(w, "\nOK") } return err }
// title: app deploy // path: /apps/{appname}/deploy // method: POST // consume: application/x-www-form-urlencoded // responses: // 200: OK // 400: Invalid data // 403: Forbidden // 404: Not found func deploy(w http.ResponseWriter, r *http.Request, t auth.Token) (err error) { var file multipart.File var fileSize int64 if strings.HasPrefix(r.Header.Get("Content-Type"), "multipart/") { file, _, err = r.FormFile("file") if err != nil { return &tsuruErrors.HTTP{ Code: http.StatusBadRequest, Message: err.Error(), } } fileSize, err = file.Seek(0, os.SEEK_END) if err != nil { return errors.Wrap(err, "unable to find uploaded file size") } file.Seek(0, os.SEEK_SET) } archiveURL := r.FormValue("archive-url") image := r.FormValue("image") if image == "" && archiveURL == "" && file == nil { return &tsuruErrors.HTTP{ Code: http.StatusBadRequest, Message: "you must specify either the archive-url, a image url or upload a file.", } } commit := r.FormValue("commit") w.Header().Set("Content-Type", "text") appName := r.URL.Query().Get(":appname") origin := r.FormValue("origin") if image != "" { origin = "image" } if origin != "" { if !app.ValidateOrigin(origin) { return &tsuruErrors.HTTP{ Code: http.StatusBadRequest, Message: "Invalid deployment origin", } } } var userName string if t.IsAppToken() { if t.GetAppName() != appName && t.GetAppName() != app.InternalAppName { return &tsuruErrors.HTTP{Code: http.StatusUnauthorized, Message: "invalid app token"} } userName = r.FormValue("user") } else { commit = "" userName = t.GetUserName() } instance, err := app.GetByName(appName) if err != nil { return &tsuruErrors.HTTP{Code: http.StatusNotFound, Message: err.Error()} } var build bool buildString := r.FormValue("build") if buildString != "" { build, err = strconv.ParseBool(buildString) if err != nil { return &tsuruErrors.HTTP{ Code: http.StatusBadRequest, Message: err.Error(), } } } message := r.FormValue("message") if commit != "" && message == "" { var messages []string messages, err = repository.Manager().CommitMessages(instance.Name, commit, 1) if err != nil { return err } if len(messages) > 0 { message = messages[0] } } if origin == "" && commit != "" { origin = "git" } opts := app.DeployOptions{ App: instance, Commit: commit, FileSize: fileSize, File: file, ArchiveURL: archiveURL, User: userName, Image: image, Origin: origin, Build: build, Message: message, } opts.GetKind() if t.GetAppName() != app.InternalAppName { canDeploy := permission.Check(t, permSchemeForDeploy(opts), contextsForApp(instance)...) if !canDeploy { return &tsuruErrors.HTTP{Code: http.StatusForbidden, Message: "User does not have permission to do this action in this app"} } } var imageID string evt, err := event.New(&event.Opts{ Target: appTarget(appName), Kind: permission.PermAppDeploy, RawOwner: event.Owner{Type: event.OwnerTypeUser, Name: userName}, CustomData: opts, Allowed: event.Allowed(permission.PermAppReadEvents, contextsForApp(instance)...), AllowedCancel: event.Allowed(permission.PermAppUpdateEvents, contextsForApp(instance)...), Cancelable: true, }) if err != nil { return err } defer func() { evt.DoneCustomData(err, map[string]string{"image": imageID}) }() opts.Event = evt writer := io.NewKeepAliveWriter(w, 30*time.Second, "please wait...") defer writer.Stop() opts.OutputStream = writer imageID, err = app.Deploy(opts) if err == nil { fmt.Fprintln(w, "\nOK") } return err }