func (api *Api) AddPerm(w rest.ResponseWriter, r *rest.Request) { // Check credentials login := r.PathParam("login") guid := r.PathParam("GUID") // Only admin is allowed if login != "admin" { rest.Error(w, "Not allowed", 400) return } session := Session{} var errl error if session, errl = api.CheckLogin(login, guid); errl != nil { rest.Error(w, errl.Error(), 401) return } defer api.TouchSession(guid) // Can't add if it exists already permData := Perm{} if err := r.DecodeJsonPayload(&permData); err != nil { rest.Error(w, "Invalid data format received.", 400) return } else if permData.UserId == 0 { rest.Error(w, "Incorrect data format received.", 400) return } perm := Perm{} mutex.Lock() if !api.db.Find(&perm, "env_id = ? and user_id = ?", permData.EnvId, permData.UserId).RecordNotFound() { mutex.Unlock() rest.Error(w, "Record exists.", 400) return } mutex.Unlock() // Add perm mutex.Lock() if err := api.db.Save(&permData).Error; err != nil { mutex.Unlock() rest.Error(w, err.Error(), 400) return } mutex.Unlock() text := fmt.Sprintf("Added new environment permission. PermID = '%d'.", permData.Id) api.LogActivity(session.Id, text) w.WriteJson(permData) }
func (api *Api) AddEnvCap(w rest.ResponseWriter, r *rest.Request) { // Check credentials login := r.PathParam("login") guid := r.PathParam("GUID") // Only admin is allowed if login != "admin" { rest.Error(w, "Not allowed", 400) return } session := Session{} var errl error if session, errl = api.CheckLogin(login, guid); errl != nil { rest.Error(w, errl.Error(), 401) return } defer api.TouchSession(guid) // Can't add if it exists already EnvCapData := EnvCap{} if err := r.DecodeJsonPayload(&EnvCapData); err != nil { rest.Error(w, "Invalid data format received.", 400) return } else if len(EnvCapData.Code) == 0 || len(EnvCapData.Desc) == 0 { rest.Error(w, "A required field is empty.", 400) return } EnvCap := EnvCap{} mutex.Lock() if !api.db.Find(&EnvCap, "code = ?", EnvCapData.Code).RecordNotFound() { mutex.Unlock() rest.Error(w, "Record exists.", 400) return } mutex.Unlock() // Add EnvCap mutex.Lock() if err := api.db.Save(&EnvCapData).Error; err != nil { mutex.Unlock() rest.Error(w, err.Error(), 400) return } mutex.Unlock() text := fmt.Sprintf("Added new EnvCap, '%s'.", EnvCapData.Code) api.LogActivity(session.Id, text) w.WriteJson(EnvCapData) }
func (api *Api) AddRepo(w rest.ResponseWriter, r *rest.Request) { // Check credentials login := r.PathParam("login") guid := r.PathParam("GUID") // Only admin is allowed if login != "admin" { rest.Error(w, "Not allowed", 400) return } session := Session{} var errl error if session, errl = api.CheckLogin(login, guid); errl != nil { rest.Error(w, errl.Error(), 401) return } defer api.TouchSession(guid) // Can't add if it exists already repoData := Repo{} if err := r.DecodeJsonPayload(&repoData); err != nil { rest.Error(w, "Invalid data format received.", 400) return } else if len(repoData.Url) == 0 { rest.Error(w, "Incorrect data format received.", 400) return } repo := Repo{} mutex.Lock() if !api.db.Find(&repo, "Url = ?", repoData.Url). RecordNotFound() { mutex.Unlock() rest.Error(w, "Record exists.", 400) return } mutex.Unlock() // Add repo mutex.Lock() if err := api.db.Save(&repoData).Error; err != nil { mutex.Unlock() rest.Error(w, err.Error(), 400) return } mutex.Unlock() api.LogActivity(session.Id, "Added new repo '"+repoData.Url+"'.") w.WriteJson(repoData) }
func (api *Api) AddJob(w rest.ResponseWriter, r *rest.Request) { // Decode json post data into JobIn struct logit(fmt.Sprintf("Connection from %s", r.RemoteAddr)) job := JobIn{} if err := r.DecodeJsonPayload(&job); err != nil { rest.Error(w, "Invalid data format received.", 400) return } else if job.JobID == 0 { rest.Error(w, "Incorrect data format received.", 400) return } // Check the password matches if job.Key != config.WorkerKey { rest.Error(w, "Invalid key", 400) return } // Add the job to the job list api.AppendJob(job) if api.Guid() == "" { api.loginmutex.Lock() if err := api.Login(); err != nil { // Can't send this error to the Manager so must return it here logit(fmt.Sprintf("Error: %s", err.Error())) rest.Error(w, err.Error(), 400) api.loginmutex.Unlock() return } api.loginmutex.Unlock() } if err := api.sendStatus(job, JobOut{ Status: STATUS_NOTSTARTED, StatusReason: "About to start job", StatusPercent: 0, Errors: 0, }); err != nil { logit(fmt.Sprintf("Error: %s", err.Error())) } w.WriteJson(job) //a := fmt.Sprintf("%#v",job) //logit(a) go api.execCmd(job) }
func (api *Api) AddOutputLine(w rest.ResponseWriter, r *rest.Request) { login := r.PathParam("login") guid := r.PathParam("GUID") // Admin is not allowed if login == "admin" { rest.Error(w, "Not allowed", 400) return } // Check credentials //session := Session{} var errl error if _, errl = api.CheckLoginNoExpiry(login, guid); errl != nil { rest.Error(w, errl.Error(), 401) return } //defer api.TouchSession( guid ) outputLineData := OutputLine{} if err := r.DecodeJsonPayload(&outputLineData); err != nil { rest.Error(w, "Invalid data format received.", 400) return } else if outputLineData.JobId == 0 { rest.Error(w, "Incorrect data format received.", 400) return } // Add OutputLine mutex.Lock() if err := api.db.Save(&outputLineData).Error; err != nil { mutex.Unlock() rest.Error(w, err.Error(), 400) return } mutex.Unlock() //text := "" //fmt.Sprintf( text,"%d",outputLineData.JobId ) //api.LogActivity( session.Id, "Started outputLine logging for job '"+ // text+"'." ) w.WriteJson("Success") }
func (api *Api) DeleteJob(w rest.ResponseWriter, r *rest.Request) { // Decode json post data into JobIn struct logit(fmt.Sprintf("Connection from %s", r.RemoteAddr)) job := JobIn{} if err := r.DecodeJsonPayload(&job); err != nil { rest.Error(w, "Invalid data format received.", 400) return } else if job.JobID == 0 { rest.Error(w, "Incorrect data format received.", 400) return } // Check the password matches if job.Key != config.WorkerKey { rest.Error(w, "Invalid key", 400) return } oldjob, err := api.FindJob(job.JobID) if err != nil { rest.Error(w, "Job not found", 400) return } // So status can be updated correctly api.SetUserCancel(oldjob.JobID) // Kill the whole process group (-pid) syscall.Kill(int(oldjob.Pid)*-1, syscall.SIGKILL) // RemoveJob is done if the Wait fails in execCmd (exec.go) // And wait will fail 'cos we just killed it. // //api.RemoveJob( oldjob.JobID ) w.WriteJson(job) }
func (api *Api) UpdateEnvCap(w rest.ResponseWriter, r *rest.Request) { // Check credentials login := r.PathParam("login") guid := r.PathParam("GUID") // Only admin is allowed if login != "admin" { rest.Error(w, "Not allowed", 400) return } session := Session{} var errl error if session, errl = api.CheckLogin(login, guid); errl != nil { rest.Error(w, errl.Error(), 401) return } defer api.TouchSession(guid) // Ensure user exists id := r.PathParam("id") // Check that the id string is a number if _, err := strconv.Atoi(id); err != nil { rest.Error(w, "Invalid id.", 400) return } // Load data from db, then ... EnvCap := EnvCap{} mutex.Lock() if api.db.Find(&EnvCap, id).RecordNotFound() { mutex.Unlock() //rest.Error(w, err.Error(), 400) rest.Error(w, "Record not found.", 400) return } mutex.Unlock() // ... overwrite any sent fields if err := r.DecodeJsonPayload(&EnvCap); err != nil { //rest.Error(w, err.Error(), 400) rest.Error(w, "Invalid data format received.", 400) return } // Force the use of the path id over an id in the payload Id, _ := strconv.Atoi(id) EnvCap.Id = int64(Id) mutex.Lock() if err := api.db.Save(&EnvCap).Error; err != nil { mutex.Unlock() rest.Error(w, err.Error(), 400) return } mutex.Unlock() text := fmt.Sprintf("Updated EnvCap, '%s'.", EnvCap.Code) api.LogActivity(session.Id, text) w.WriteJson("Success") }
// UpdateUser processes "PUT /users" queries. // func (api *Api) UpdateUser(w rest.ResponseWriter, r *rest.Request) { // Check credentials login := r.PathParam("login") guid := r.PathParam("GUID") // Only admin is allowed if login != "admin" { rest.Error(w, "Not allowed", 400) return } session := Session{} var errl error if session, errl = api.CheckLogin(login, guid); errl != nil { rest.Error(w, errl.Error(), 401) return } defer api.TouchSession(guid) // Ensure user exists id := r.PathParam("id") // Check that the id string is a number if _, err := strconv.Atoi(id); err != nil { rest.Error(w, "Invalid id.", 400) return } // Load data from db, then ... user := User{} mutex.Lock() if api.db.Find(&user, id).RecordNotFound() { mutex.Unlock() //rest.Error(w, err.Error(), 400) rest.Error(w, "Record not found.", 400) return } mutex.Unlock() // FIXME: DecodeJsonPayload(&somethingelse) then // merge with 'user' manually. This will remove // the 'password can't begin with $' limitation. // ... overwrite any sent fields if err := r.DecodeJsonPayload(&user); err != nil { //rest.Error(w, err.Error(), 400) rest.Error(w, "Invalid data format received.", 400) return } // Add user if !strings.HasPrefix(user.Passhash, "$") { c := &Crypt{} c.Pass = []byte(user.Passhash) c.Crypt() user.Passhash = string(c.Hash) } // Force the use of the path id over an id in the payload Id, _ := strconv.Atoi(id) user.Id = int64(Id) mutex.Lock() if err := api.db.Save(&user).Error; err != nil { mutex.Unlock() rest.Error(w, err.Error(), 400) return } mutex.Unlock() api.LogActivity(session.Id, "Updated user details for '"+user.Login+"'.") w.WriteJson(user) }
// AddUser processes "POST /users" queries. // func (api *Api) AddUser(w rest.ResponseWriter, r *rest.Request) { // Check credentials login := r.PathParam("login") guid := r.PathParam("GUID") // Only admin is allowed if login != "admin" { rest.Error(w, "Not allowed", 400) return } session := Session{} var errl error if session, errl = api.CheckLogin(login, guid); errl != nil { rest.Error(w, errl.Error(), 401) return } defer api.TouchSession(guid) // Can't add if it exists already userData := User{} if err := r.DecodeJsonPayload(&userData); err != nil { rest.Error(w, "Invalid data format received.", 400) return } else if len(userData.Login) == 0 { rest.Error(w, "Incorrect data format received.", 400) return } user := User{} mutex.Lock() if !api.db.Find(&user, "login = ?", userData.Login).RecordNotFound() { mutex.Unlock() rest.Error(w, "Record exists.", 400) return } mutex.Unlock() // Add user if len(userData.Passhash) == 0 { rest.Error(w, "Empty password not allowed.", 400) return } c := &Crypt{} c.Pass = []byte(userData.Passhash) c.Crypt() userData.Passhash = string(c.Hash) mutex.Lock() if err := api.db.Save(&userData).Error; err != nil { mutex.Unlock() rest.Error(w, err.Error(), 400) return } mutex.Unlock() api.LogActivity(session.Id, "Added new user '"+userData.Login+"'.") w.WriteJson(userData) }
func (api *Api) UpdateScript(w rest.ResponseWriter, r *rest.Request) { // Check credentials login := r.PathParam("login") guid := r.PathParam("GUID") // Only admin is allowed if login != "admin" { rest.Error(w, "Not allowed", 400) return } session := Session{} var errl error if session, errl = api.CheckLogin(login, guid); errl != nil { rest.Error(w, errl.Error(), 401) return } defer api.TouchSession(guid) // Ensure user exists id := r.PathParam("id") // Check that the id string is a number if _, err := strconv.Atoi(id); err != nil { rest.Error(w, "Invalid id.", 400) return } // Load data from db, then ... script := Script{} mutex.Lock() if api.db.Find(&script, id).RecordNotFound() { mutex.Unlock() //rest.Error(w, err.Error(), 400) rest.Error(w, "Record not found.", 400) return } mutex.Unlock() // ... overwrite any sent fields if err := r.DecodeJsonPayload(&script); err != nil { //rest.Error(w, err.Error(), 400) rest.Error(w, "Invalid data format received.", 400) return } script_srch := Script{} mutex.Lock() if !api.db.Find(&script_srch, "name = ? and id != ?", script.Name, script.Id).RecordNotFound() { mutex.Unlock() rest.Error(w, "Record exists.", 400) return } mutex.Unlock() // Work out type: // Write to disk then use unix 'file -b' (brief) if len(script.Source) > 0 { if err := ioutil.WriteFile(os.TempDir()+"/obdi_scriptcheck", script.Source, 0644); err != nil { script.Type = "Write file failed. Type of script unknown. (" + err.Error() + ")" } else { runCmd := exec.Command("file", "-b", os.TempDir()+"/obdi_scriptcheck") output, err := runCmd.Output() if err != nil { script.Type = "Unix 'file' failed. Type of script unknown." + " (" + err.Error() + ")" } else { script.Type = string(output) } } } // Force the use of the path id over an id in the payload Id, _ := strconv.Atoi(id) script.Id = int64(Id) mutex.Lock() if err := api.db.Save(&script).Error; err != nil { mutex.Unlock() rest.Error(w, err.Error(), 400) return } mutex.Unlock() api.LogActivity(session.Id, "Updated data centre details for '"+script.Name+"'.") w.WriteJson(script) }
func (api *Api) AddScript(w rest.ResponseWriter, r *rest.Request) { // Check credentials login := r.PathParam("login") guid := r.PathParam("GUID") // Only admin is allowed if login != "admin" { rest.Error(w, "Not allowed", 400) return } session := Session{} var errl error if session, errl = api.CheckLogin(login, guid); errl != nil { rest.Error(w, errl.Error(), 401) return } defer api.TouchSession(guid) // Can't add if it exists already scriptData := Script{} if err := r.DecodeJsonPayload(&scriptData); err != nil { rest.Error(w, "Invalid data format received.", 400) return } else if len(scriptData.Source) == 0 { rest.Error(w, "Incorrect data format received.", 400) return } script := Script{} mutex.Lock() if !api.db.Find(&script, "name = ?", scriptData.Name).RecordNotFound() { mutex.Unlock() rest.Error(w, "Record exists.", 400) return } mutex.Unlock() // Work out type: // Write to disk then use unix 'file -b' (brief) if err := ioutil.WriteFile(os.TempDir()+"/obdi_scriptcheck", scriptData.Source, 0644); err != nil { scriptData.Type = "Unknown type of script" } else { runCmd := exec.Command("file", "-b", os.TempDir()+"/obdi_scriptcheck") output, err := runCmd.Output() if err != nil { scriptData.Type = "Unknown type of script" } else { scriptData.Type = string(output) } } // Add script mutex.Lock() if err := api.db.Save(&scriptData).Error; err != nil { mutex.Unlock() rest.Error(w, err.Error(), 400) return } mutex.Unlock() // Try to start the script text := fmt.Sprintf("Added new script, %s.", scriptData.Name) api.LogActivity(session.Id, text) scriptData.Source = []byte{} w.WriteJson(scriptData) }
func (api *Api) AddPlugin(w rest.ResponseWriter, r *rest.Request) { // Check credentials login := r.PathParam("login") guid := r.PathParam("GUID") // Only admin is allowed if login != "admin" { rest.Error(w, "Not allowed", 400) return } session := Session{} var errl error if session, errl = api.CheckLogin(login, guid); errl != nil { rest.Error(w, errl.Error(), 401) return } defer api.TouchSession(guid) // Can't add if it exists already pluginData := Plugin{} if err := r.DecodeJsonPayload(&pluginData); err != nil { rest.Error(w, "Invalid data format received.", 400) return } else if len(pluginData.Name) == 0 { rest.Error(w, "Incorrect data format received.", 400) return } plugin := Plugin{} mutex.Lock() if !api.db.Find(&plugin, "name = ?", pluginData.Name). RecordNotFound() { mutex.Unlock() rest.Error(w, "Record exists.", 400) return } mutex.Unlock() // Make sure parent exists mutex.Lock() if len(pluginData.Parent) > 0 && api.db.Find(&plugin, "name = ?", pluginData.Parent).RecordNotFound() { mutex.Unlock() rest.Error(w, "Parent not found.", 400) return } mutex.Unlock() // Add plugin mutex.Lock() if err := api.db.Save(&pluginData).Error; err != nil { mutex.Unlock() rest.Error(w, err.Error(), 400) return } mutex.Unlock() api.LogActivity(session.Id, "Added new plugin '"+pluginData.Name+"'.") w.WriteJson(pluginData) }
func (api *Api) UpdatePlugin(w rest.ResponseWriter, r *rest.Request) { // Check credentials login := r.PathParam("login") guid := r.PathParam("GUID") // Only admin is allowed if login != "admin" { rest.Error(w, "Not allowed", 400) return } session := Session{} var errl error if session, errl = api.CheckLogin(login, guid); errl != nil { rest.Error(w, errl.Error(), 401) return } defer api.TouchSession(guid) // Ensure user exists id := r.PathParam("id") // Check that the id string is a number if _, err := strconv.Atoi(id); err != nil { rest.Error(w, "Invalid id.", 400) return } // Load data from db, then ... plugin := Plugin{} mutex.Lock() if api.db.Find(&plugin, id).RecordNotFound() { mutex.Unlock() //rest.Error(w, err.Error(), 400) rest.Error(w, "Record not found.", 400) return } mutex.Unlock() // ... overwrite any sent fields if err := r.DecodeJsonPayload(&plugin); err != nil { //rest.Error(w, err.Error(), 400) rest.Error(w, "Invalid data format received.", 400) return } // Force the use of the path id over an id in the payload Id, _ := strconv.Atoi(id) plugin.Id = int64(Id) // Make sure parent exists pluginSrch := Plugin{} mutex.Lock() if len(plugin.Parent) > 0 && api.db.Find(&pluginSrch, "name = ?", plugin.Parent).RecordNotFound() { mutex.Unlock() rest.Error(w, "Parent not found.", 400) return } mutex.Unlock() if pluginSrch.Id == plugin.Id { rest.Error(w, "Cannot be a parent of itself.", 400) return } mutex.Lock() if err := api.db.Save(&plugin).Error; err != nil { mutex.Unlock() rest.Error(w, err.Error(), 400) return } mutex.Unlock() api.LogActivity(session.Id, "Updated plugin details for '"+plugin.Name+"'.") w.WriteJson("Success") }
// DoLogin processes "POST /login" queries. // // Checks login name and passhash stored in database. // If correct then 200 header and GUID are sent. // any previous sessions for that user are closed. // new session entry is made in session table. // If not correct then 400 header with error message. // func (api *Api) DoLogin(w rest.ResponseWriter, r *rest.Request) { // Get the Login and Password userData := struct{ Login, Password string }{} if err := r.DecodeJsonPayload(&userData); err != nil { rest.Error(w, "Invalid data format received.", 400) return } else if len(userData.Login) == 0 || len(userData.Password) == 0 { rest.Error(w, "Incorrect data format received.", 400) return } //fmt.Printf( "\n%#v\n", userData ) // Get passhash for login from database user := User{} mutex.Lock() if api.db.Where(User{Login: userData.Login}). First(&user).RecordNotFound() { rest.Error(w, "User or password error.", 400) mutex.Unlock() return } mutex.Unlock() // Check password against hash c := &Crypt{} c.Pass = []byte(userData.Password) c.Hash = []byte(user.Passhash) if err := c.Check(); err != nil { rest.Error(w, "User or password error.", 400) return } // The user's password matches. // Delete old session(s) and create a new one. guid := NewGUID() session := Session{} for { session = Session{} mutex.Lock() if api.db.Where(Session{UserId: user.Id}). First(&session).RecordNotFound() { session = Session{ Guid: guid, UserId: user.Id, } if err := api.db.Save(&session).Error; err != nil { rest.Error(w, err.Error(), 400) mutex.Unlock() return } mutex.Unlock() break } else { if err := api.db.Delete(&session).Error; err != nil { rest.Error(w, err.Error(), 400) mutex.Unlock() return } } mutex.Unlock() } logit("User '" + user.Login + "' logged in") api.LogActivity(session.Id, "User '"+user.Login+"' logged in.") w.WriteJson(struct{ GUID string }{guid}) }
func (api *Api) AddDcCapMap(w rest.ResponseWriter, r *rest.Request) { // Check credentials login := r.PathParam("login") guid := r.PathParam("GUID") // Only admin is allowed if login != "admin" { rest.Error(w, "Not allowed", 400) return } session := Session{} var errl error if session, errl = api.CheckLogin(login, guid); errl != nil { rest.Error(w, errl.Error(), 401) return } defer api.TouchSession(guid) // Can't add if it exists already dcCapMapData := DcCapMap{} if err := r.DecodeJsonPayload(&dcCapMapData); err != nil { rest.Error(w, "Invalid data format received.", 400) return } else if dcCapMapData.DcId == 0 || dcCapMapData.DcCapId == 0 { rest.Error(w, "A required field is empty.", 400) return } dcCapMap := DcCapMap{} mutex.Lock() if !api.db.Find(&dcCapMap, "dc_id = ? and dc_cap_id = ?", dcCapMapData.DcId, dcCapMapData.DcCapId).RecordNotFound() { mutex.Unlock() rest.Error(w, "Record exists.", 400) return } mutex.Unlock() // Check that DcId and DcCapId exist dc := Dc{} mutex.Lock() if api.db.Find(&dc, dcCapMapData.DcId).RecordNotFound() { mutex.Unlock() rest.Error(w, "Invalid data centre id.", 400) return } mutex.Unlock() dcCap := DcCap{} mutex.Lock() if api.db.Find(&dcCap, dcCapMapData.DcCapId).RecordNotFound() { mutex.Unlock() rest.Error(w, "Invalid data centre capability id.", 400) return } mutex.Unlock() // Add DcCapMap mutex.Lock() if err := api.db.Save(&dcCapMapData).Error; err != nil { mutex.Unlock() rest.Error(w, err.Error(), 400) return } mutex.Unlock() text := fmt.Sprintf("Added new DcCapMap, '%d'.", dcCapMapData.Id) api.LogActivity(session.Id, text) w.WriteJson(dcCapMapData) }
func (api *Api) AddEnv(w rest.ResponseWriter, r *rest.Request) { // Check credentials login := r.PathParam("login") guid := r.PathParam("GUID") // Only admin is allowed if login != "admin" { rest.Error(w, "Not allowed", 400) return } session := Session{} var errl error if session, errl = api.CheckLogin(login, guid); errl != nil { rest.Error(w, errl.Error(), 401) return } defer api.TouchSession(guid) // Can't add if it exists already envData := Env{} if err := r.DecodeJsonPayload(&envData); err != nil { rest.Error(w, "Invalid data format received.", 400) return } else if len(envData.SysName) == 0 { rest.Error(w, "Incorrect data format received.", 400) return } env := Env{} mutex.Lock() if !api.db.Find(&env, "sys_name = ? and dc_id = ?", envData.SysName, envData.DcId).RecordNotFound() { mutex.Unlock() rest.Error(w, "Record exists.", 400) return } mutex.Unlock() // Add env mutex.Lock() if err := api.db.Save(&envData).Error; err != nil { mutex.Unlock() rest.Error(w, err.Error(), 400) return } mutex.Unlock() dc := Dc{} mutex.Lock() api.db.First(&dc, envData.DcId) mutex.Unlock() text := fmt.Sprintf("Added new environment '%s->%s'.", dc.SysName, envData.SysName) api.LogActivity(session.Id, text) w.WriteJson(envData) }
func (api *Api) UpdateJob(w rest.ResponseWriter, r *rest.Request) { // Check credentials login := r.PathParam("login") guid := r.PathParam("GUID") // Admin is not allowed if login == "admin" { rest.Error(w, "Not allowed", 400) return } session := Session{} var errl error if session, errl = api.CheckLogin(login, guid); errl != nil { rest.Error(w, errl.Error(), 401) return } defer api.TouchSession(guid) // Ensure user exists id := r.PathParam("id") // Check that the id string is a number if _, err := strconv.Atoi(id); err != nil { rest.Error(w, "Invalid id.", 400) return } // Load data from db, then ... job := Job{} mutex.Lock() if api.db.Find(&job, id).RecordNotFound() { mutex.Unlock() //rest.Error(w, err.Error(), 400) rest.Error(w, "Job ID not found.", 400) return } mutex.Unlock() // ... overwrite any sent fields if err := r.DecodeJsonPayload(&job); err != nil { //rest.Error(w, err.Error(), 400) rest.Error(w, "Invalid data format received.", 400) return } // Force the use of the path id over an id in the payload Id, _ := strconv.Atoi(id) job.Id = int64(Id) mutex.Lock() if err := api.db.Save(&job).Error; err != nil { mutex.Unlock() rest.Error(w, err.Error(), 400) return } mutex.Unlock() api.LogActivity(session.Id, fmt.Sprintf("Updated job details for jobId %d.", job.Id)) w.WriteJson(job) }
func (api *Api) AddJob(w rest.ResponseWriter, r *rest.Request) { // This function will return successfully in all cases, after // the sanity checks. Errors are saved in to the job here, or by // the worker. // // TODO: Delete jobs (and output_lines) over N days old here // logit(fmt.Sprintf("Connection from %s", r.RemoteAddr)) // Check credentials login := r.PathParam("login") guid := r.PathParam("GUID") // Admin is not allowed if login == "admin" { rest.Error(w, "Not allowed", 400) return } session := Session{} var errl error if session, errl = api.CheckLogin(login, guid); errl != nil { rest.Error(w, errl.Error(), 401) return } defer api.TouchSession(guid) // Can't add if it exists already jobData := Job{} if err := r.DecodeJsonPayload(&jobData); err != nil { rest.Error(w, "Invalid data format received.", 400) return } else if jobData.ScriptId == 0 { rest.Error(w, "Incorrect data format received.", 400) return } jobData.UserLogin = login // Sanity checks if jobData.ScriptId == 0 { txt := "Script ID must be specified" rest.Error(w, txt, 400) return } if jobData.EnvId == 0 { txt := "Environment ID must be specified" rest.Error(w, txt, 400) return } // Add job to DB saveJob := func() { mutex.Lock() if err := api.db.Save(&jobData).Error; err != nil { mutex.Unlock() rest.Error(w, err.Error(), 400) return } mutex.Unlock() } saveJob() // Get the associated environment data env := Env{} mutex.Lock() api.db.Model(&jobData).Related(&env) mutex.Unlock() // We need WorkerUrl and WorkerKey if env.WorkerUrl == "" || env.WorkerKey == "" { txt := "WorkerUrl or WorkerKey not set for this environment" jobData.Status = STATUS_ERROR jobData.StatusReason = txt saveJob() w.WriteJson(jobData) return } // Send the job to the worker script := Script{} saveJob() mutex.Lock() if err := api.db.Find(&script, jobData.ScriptId); err.Error != nil { mutex.Unlock() txt := fmt.Sprintf("Script ID %d not found ('%s')", jobData.ScriptId, err.Error.Error()) jobData.Status = STATUS_ERROR jobData.StatusReason = txt saveJob() w.WriteJson(jobData) //rest.Error(w, txt, 400) return } mutex.Unlock() // Jobsend definition type Jobsend struct { ScriptSource []byte ScriptName string Args string EnvVars string //NotifURL string JobID int64 Key string Type int64 // 1 - user job, 2 - system job } // Jobsend data data := Jobsend{ ScriptSource: script.Source, ScriptName: script.Name, JobID: jobData.Id, Key: env.WorkerKey, Args: jobData.Args, EnvVars: jobData.EnvVars, Type: jobData.Type, } // Encode jsondata, err := json.Marshal(data) if err != nil { txt := fmt.Sprintf("Error sending job to worker, JSON Encode:", err.Error()) jobData.Status = STATUS_ERROR jobData.StatusReason = txt saveJob() w.WriteJson(jobData) //rest.Error(w, txt, 400) return } // POST to worker resp, err := POST(jsondata, env.WorkerUrl, "jobs") //fmt.Printf("%+v", jsondata) if err != nil { txt := "Could not send job to worker. ('" + err.Error() + "')" jobData.Status = STATUS_ERROR jobData.StatusReason = txt saveJob() w.WriteJson(jobData) //rest.Error(w, txt, 400) return } defer resp.Body.Close() text := fmt.Sprintf("Added new job, %d.", jobData.Id) api.LogActivity(session.Id, text) w.WriteJson(jobData) }