示例#1
0
func reportHandler(w http.ResponseWriter, r *http.Request) {
	w.Header().Set("Content-Type", "application/json")

	protocolVersion := r.Header.Get("X-Ops-Reporting-Protocol-Version")
	if protocolVersion == "" {
		// try a param (makes working with webui easier)
		form, e := url.ParseQuery(r.URL.RawQuery)
		if e != nil {
			jsonErrorReport(w, r, e.Error(), http.StatusBadRequest)
			return
		}
		if p, f := form["protocol-version"]; f {
			if len(p) > 0 {
				protocolVersion = p[0]
			}
		}
	}
	// someday there may be other protocol versions
	if protocolVersion != "0.1.0" {
		jsonErrorReport(w, r, "Unsupported reporting protocol version", http.StatusNotFound)
		return
	}

	opUser, oerr := actor.GetReqUser(r.Header.Get("X-OPS-USERID"))
	if oerr != nil {
		jsonErrorReport(w, r, oerr.Error(), oerr.Status())
		return
	}

	// TODO: some params for time ranges exist and need to be handled
	// properly

	pathArray := splitPath(r.URL.Path)
	pathArrayLen := len(pathArray)
	reportResponse := make(map[string]interface{})

	switch r.Method {
	case "GET":
		// Making an informed guess that admin rights are needed
		// to see the node run reports
		r.ParseForm()
		var rows int
		var from, until time.Time
		var status string
		if fr, found := r.Form["rows"]; found {
			if len(fr) < 0 {
				jsonErrorReport(w, r, "invalid rows", http.StatusBadRequest)
				return
			}
			var err error
			rows, err = strconv.Atoi(fr[0])
			if err != nil {
				jsonErrorReport(w, r, err.Error(), http.StatusBadRequest)
				return
			}
		} else {
			// default is 10
			rows = 10
		}
		if ff, found := r.Form["from"]; found {
			if len(ff) < 0 {
				jsonErrorReport(w, r, "invalid from", http.StatusBadRequest)
				return
			}
			fromUnix, err := strconv.ParseInt(ff[0], 10, 64)
			if err != nil {
				jsonErrorReport(w, r, err.Error(), http.StatusBadRequest)
				return
			}
			from = time.Unix(fromUnix, 0)
		} else {
			from = time.Now().Add(-(time.Duration(24*90) * time.Hour))
		}
		if fu, found := r.Form["until"]; found {
			if len(fu) < 0 {
				jsonErrorReport(w, r, "invalid until", http.StatusBadRequest)
				return
			}
			untilUnix, err := strconv.ParseInt(fu[0], 10, 64)
			if err != nil {
				jsonErrorReport(w, r, err.Error(), http.StatusBadRequest)
				return
			}
			until = time.Unix(untilUnix, 0)
		} else {
			until = time.Now()
		}

		if st, found := r.Form["status"]; found {
			if len(st) < 0 {
				jsonErrorReport(w, r, "invalid status", http.StatusBadRequest)
				return
			}
			status = st[0]
			if status != "started" && status != "success" && status != "failure" {
				jsonErrorReport(w, r, "invalid status given", http.StatusBadRequest)
				return
			}
		}

		// If the end time is more than 90 days ahead of the
		// start time, give an error
		if from.Truncate(time.Hour).Sub(until.Truncate(time.Hour)) >= (time.Duration(24*90) * time.Hour) {
			msg := fmt.Sprintf("End time %s is too far ahead of start time %s (max 90 days)", until.String(), from.String())
			jsonErrorReport(w, r, msg, http.StatusNotAcceptable)
			return
		}

		if !opUser.IsAdmin() {
			jsonErrorReport(w, r, "You are not allowed to perform this action", http.StatusForbidden)
			return
		}
		if pathArrayLen < 3 || pathArrayLen > 4 {
			jsonErrorReport(w, r, "Bad request", http.StatusBadRequest)
			return
		}
		op := pathArray[1]
		if op == "nodes" && pathArrayLen == 4 {
			nodeName := pathArray[2]
			runs, nerr := report.GetNodeList(nodeName, from, until, rows, status)
			if nerr != nil {
				jsonErrorReport(w, r, nerr.Error(), http.StatusInternalServerError)
				return
			}
			reportResponse["run_history"] = runs
		} else if op == "org" {
			if pathArrayLen == 4 {
				runID := pathArray[3]
				run, err := report.Get(runID)
				if err != nil {
					jsonErrorReport(w, r, err.Error(), err.Status())
					return
				}
				reportResponse = formatRunShow(run)
			} else {
				runs, rerr := report.GetReportList(from, until, rows, status)
				if rerr != nil {
					jsonErrorReport(w, r, rerr.Error(), http.StatusInternalServerError)
					return
				}
				reportResponse["run_history"] = runs
			}
		} else {
			jsonErrorReport(w, r, "Bad request", http.StatusBadRequest)
			return
		}
	case "POST":
		// Can't use the usual parseObjJSON function here, since
		// the reporting "run_list" type is a string rather
		// than []interface{}.
		jsonReport := make(map[string]interface{})
		dec := json.NewDecoder(r.Body)
		if jerr := dec.Decode(&jsonReport); jerr != nil {
			jsonErrorReport(w, r, jerr.Error(), http.StatusBadRequest)
			return
		}

		if pathArrayLen < 4 || pathArrayLen > 5 {
			jsonErrorReport(w, r, "Bad request", http.StatusBadRequest)
			return
		}
		nodeName := pathArray[2]
		if pathArrayLen == 4 {
			rep, err := report.NewFromJSON(nodeName, jsonReport)
			if err != nil {
				jsonErrorReport(w, r, err.Error(), err.Status())
				return
			}
			// what's the expected response?
			serr := rep.Save()
			if serr != nil {
				jsonErrorReport(w, r, serr.Error(), http.StatusInternalServerError)
				return
			}
			reportResponse["run_detail"] = rep
		} else {
			runID := pathArray[4]
			rep, err := report.Get(runID)
			if err != nil {
				jsonErrorReport(w, r, err.Error(), err.Status())
				return
			}
			err = rep.UpdateFromJSON(jsonReport)
			if err != nil {
				jsonErrorReport(w, r, err.Error(), err.Status())
				return
			}
			serr := rep.Save()
			if serr != nil {
				jsonErrorReport(w, r, err.Error(), http.StatusInternalServerError)
				return
			}
			// .... and?
			reportResponse["run_detail"] = rep
		}
	default:
		jsonErrorReport(w, r, "Bad request", http.StatusBadRequest)
		return
	}

	enc := json.NewEncoder(w)
	if err := enc.Encode(&reportResponse); err != nil {
		jsonErrorReport(w, r, err.Error(), http.StatusInternalServerError)
	}
}
示例#2
0
func importAll(fileName string) error {
	fp, err := os.Open(fileName)
	if err != nil {
		return err
	}
	exportedData := &ExportData{}
	dec := json.NewDecoder(fp)
	if err := dec.Decode(&exportedData); err != nil {
		return err
	}

	// What versions of the exported data are supported?
	// At the moment it's only 1.0.

	if exportedData.MajorVersion == 1 && (exportedData.MinorVersion == 0 || exportedData.MinorVersion == 1) {
		logger.Infof("Importing data, version %d.%d created on %s", exportedData.MajorVersion, exportedData.MinorVersion, exportedData.CreatedTime)

		// load clients
		logger.Infof("Loading clients")
		for _, v := range exportedData.Data["client"] {
			c, err := client.NewFromJSON(v.(map[string]interface{}))
			if err != nil {
				return err
			}
			pkerr := c.SetPublicKey(v.(map[string]interface{})["public_key"])
			if pkerr != nil {
				return pkerr
			}
			gerr := c.Save()
			if gerr != nil {
				return gerr
			}
		}

		// load users
		logger.Infof("Loading users")
		for _, v := range exportedData.Data["user"] {
			pwhash, _ := v.(map[string]interface{})["password"].(string)
			v.(map[string]interface{})["password"] = ""
			u, err := user.NewFromJSON(v.(map[string]interface{}))
			if err != nil {
				return err
			}
			u.SetPasswdHash(pwhash)
			pkerr := u.SetPublicKey(v.(map[string]interface{})["public_key"])
			if pkerr != nil {
				return pkerr
			}
			gerr := u.Save()
			if gerr != nil {
				return gerr
			}
		}

		// load filestore
		logger.Infof("Loading filestore")
		for _, v := range exportedData.Data["filestore"] {
			fileData, err := base64.StdEncoding.DecodeString(v.(map[string]interface{})["Data"].(string))
			if err != nil {
				return err
			}
			fdBuf := bytes.NewBuffer(fileData)
			fdRc := ioutil.NopCloser(fdBuf)
			fs, err := filestore.New(v.(map[string]interface{})["Chksum"].(string), fdRc, int64(fdBuf.Len()))
			if err != nil {
				return err
			}
			if err = fs.Save(); err != nil {
				return err
			}
		}

		// load cookbooks
		logger.Infof("Loading cookbooks")
		for _, v := range exportedData.Data["cookbook"] {
			cb, err := cookbook.New(v.(map[string]interface{})["Name"].(string))
			if err != nil {
				return err
			}
			gerr := cb.Save()
			if gerr != nil {
				return gerr
			}
			for ver, cbvData := range v.(map[string]interface{})["Versions"].(map[string]interface{}) {
				cbvData, cerr := checkAttrs(cbvData.(map[string]interface{}))
				if cerr != nil {
					return cerr
				}
				_, cbverr := cb.NewVersion(ver, cbvData)
				if cbverr != nil {
					return cbverr
				}
			}
		}

		// load data bags
		logger.Infof("Loading data bags")
		for _, v := range exportedData.Data["data_bag"] {
			dbag, err := databag.New(v.(map[string]interface{})["Name"].(string))
			if err != nil {
				return err
			}
			gerr := dbag.Save()
			if gerr != nil {
				return gerr
			}
			for _, dbagData := range v.(map[string]interface{})["DataBagItems"].(map[string]interface{}) {
				_, dbierr := dbag.NewDBItem(dbagData.(map[string]interface{})["raw_data"].(map[string]interface{}))
				if dbierr != nil {
					return dbierr
				}
			}
			gerr = dbag.Save()
			if gerr != nil {
				return gerr
			}
		}
		// load environments
		logger.Infof("Loading environments")
		for _, v := range exportedData.Data["environment"] {
			envData, cerr := checkAttrs(v.(map[string]interface{}))
			if cerr != nil {
				return nil
			}
			if envData["name"].(string) != "_default" {
				e, err := environment.NewFromJSON(envData)
				if err != nil {
					return err
				}
				gerr := e.Save()
				if gerr != nil {
					return gerr
				}
			}
		}

		// load nodes
		logger.Infof("Loading nodes")
		for _, v := range exportedData.Data["node"] {
			nodeData, cerr := checkAttrs(v.(map[string]interface{}))
			if cerr != nil {
				return nil
			}
			n, err := node.NewFromJSON(nodeData)
			if err != nil {
				return err
			}
			gerr := n.Save()
			if gerr != nil {
				return gerr
			}
		}

		// load roles
		logger.Infof("Loading roles")
		for _, v := range exportedData.Data["role"] {
			roleData, cerr := checkAttrs(v.(map[string]interface{}))
			if cerr != nil {
				return nil
			}
			r, err := role.NewFromJSON(roleData)
			if err != nil {
				return err
			}
			gerr := r.Save()
			if gerr != nil {
				return gerr
			}
		}

		// load sandboxes
		logger.Infof("Loading sandboxes")
		for _, v := range exportedData.Data["sandbox"] {
			sbid, _ := v.(map[string]interface{})["Id"].(string)
			sbts, _ := v.(map[string]interface{})["CreationTime"].(string)
			sbcomplete, _ := v.(map[string]interface{})["Completed"].(bool)
			sbck, _ := v.(map[string]interface{})["Checksums"].([]interface{})
			sbTime, err := time.Parse(time.RFC3339, sbts)
			if err != nil {
				return err
			}
			sbChecksums := make([]string, len(sbck))
			for i, c := range sbck {
				sbChecksums[i] = c.(string)
			}
			sbox := &sandbox.Sandbox{ID: sbid, CreationTime: sbTime, Completed: sbcomplete, Checksums: sbChecksums}
			if err = sbox.Save(); err != nil {
				return err
			}
		}

		// load loginfos
		logger.Infof("Loading loginfo")
		for _, v := range exportedData.Data["loginfo"] {
			if err := loginfo.Import(v.(map[string]interface{})); err != nil {
				return err
			}
		}

		// load reports
		logger.Infof("Loading reports")
		for _, o := range exportedData.Data["report"] {
			// handle data exported from a bugged report export
			var nodeName string
			v := o.(map[string]interface{})
			if n, ok := v["node_name"]; ok {
				nodeName = n.(string)
			} else if n, ok := v["nodeName"]; ok {
				nodeName = n.(string)
			}
			v["action"] = "start"
			if st, ok := v["start_time"].(string); ok {
				t, err := time.Parse(time.RFC3339, st)
				if err != nil {
					return err
				}
				v["start_time"] = t.Format(report.ReportTimeFormat)
			}
			if et, ok := v["end_time"].(string); ok {
				t, err := time.Parse(time.RFC3339, et)
				if err != nil {
					return err
				}
				v["end_time"] = t.Format(report.ReportTimeFormat)
			}
			r, err := report.NewFromJSON(nodeName, v)
			if err != nil {
				return err
			}
			gerr := r.Save()
			if gerr != nil {
				return gerr
			}
			v["action"] = "end"
			if err := r.UpdateFromJSON(v); err != nil {
				return err
			}
			gerr = r.Save()
			if gerr != nil {
				return gerr
			}
		}

		if exportedData.MinorVersion == 1 {
			// import shovey jobs, run, and streams, and node
			// statuses
			logger.Infof("Loading node statuses...")
			for _, v := range exportedData.Data["node_status"] {
				ns := v.(map[string]interface{})
				err := node.ImportStatus(ns)
				if err != nil {
					return err
				}
			}
			logger.Infof("Loading shoveys...")
			for _, v := range exportedData.Data["shovey"] {
				s := v.(map[string]interface{})
				err := shovey.ImportShovey(s)
				if err != nil {
					return err
				}
			}
			logger.Infof("Loading shovey runs...")
			for _, v := range exportedData.Data["shovey_run"] {
				s := v.(map[string]interface{})
				err := shovey.ImportShoveyRun(s)
				if err != nil {
					return err
				}

			}
			logger.Infof("Loading shovey run streams...")
			for _, v := range exportedData.Data["shovey_run_stream"] {
				s := v.(map[string]interface{})
				err := shovey.ImportShoveyRunStream(s)
				if err != nil {
					return err
				}
			}
		}

	} else {
		err := fmt.Errorf("goiardi export data version %d.%d is not supported by this version of goiardi", exportedData.MajorVersion, exportedData.MinorVersion)
		return err
	}
	return nil
}