Example #1
0
func (j *CreateKeysRequest) Execute(resp jobs.JobResponse) {
	failedKeys := []KeyFailure{}
	for i := range j.Keys {
		key := j.Keys[i]

		locator, err := key.Create()
		if err != nil {
			failedKeys = append(failedKeys, KeyFailure{i, &key, err})
			continue
		}

		for k := range j.Permissions {
			if err := j.Permissions[k].Create(locator); err != nil {
				failedKeys = append(failedKeys, KeyFailure{i, &key, err})
				continue
			}
		}
	}

	if len(failedKeys) > 0 {
		data := make([]KeyStructuredFailure, len(failedKeys))
		for i := range failedKeys {
			data[i] = KeyStructuredFailure{failedKeys[i].Index, failedKeys[i].Reason.Error()}
			log.Printf("Failure %d: %+v", failedKeys[i].Index, failedKeys[i].Reason)
		}
		resp.Failure(jobs.StructuredJobError{jobs.SimpleJobError{jobs.JobResponseError, "Not all keys were completed"}, data})
	} else {
		resp.Success(jobs.JobResponseOk)
	}
}
Example #2
0
func (j UpdateFrontendRequest) Execute(resp jobs.JobResponse) {
	// detach empty frontends
	for _, frontend := range j.Frontends {
		if frontend.BackendId == "" {
			frontend.Remove()
		}
	}

	errs := []backendError{}
	for _, backend := range j.Backends {
		if err := utils.WriteToPathExclusive(backend.Id.BackendPathFor(), 0554, backend); err != nil {
			errs = append(errs, backendError{backend.Id, err})
		}
	}
	if len(errs) != 0 {
		log.Printf("Unable to persist some backends: %+v", errs)
		resp.Failure(ErrBackendWriteFailed)
		return
	}
	resp.Success(jobs.JobResponseOk)
}
Example #3
0
func (h *HttpDispatcher) Dispatch(job RemoteExecutable, res jobs.JobResponse) error {
	reader, writer := io.Pipe()
	httpreq, errn := http.NewRequest(job.HttpMethod(), h.locator.BaseURL().String(), reader)
	if errn != nil {
		return errn
	}

	id := job.MarshalRequestIdentifier()
	if len(id) == 0 {
		id = jobs.NewRequestIdentifier()
	}

	query := &url.Values{}
	job.MarshalUrlQuery(query)

	req := httpreq
	req.Header.Set("X-Request-Id", id.String())
	req.Header.Set("If-Match", "api="+ApiVersion())
	req.Header.Set("Content-Type", "application/json")
	//TODO: introduce API version per job
	//TODO: content request signing for GETs
	req.URL.Path = job.HttpPath()
	req.URL.RawQuery = query.Encode()
	go func() {
		if err := job.MarshalHttpRequestBody(writer); err != nil {
			h.log.Printf("remote: Error when writing to http: %v", err)
			writer.CloseWithError(err)
		} else {
			writer.Close()
		}
	}()

	resp, err := h.client.Do(req)
	if err != nil {
		h.log.Printf("Failed: %v", err)
		return err
	}
	defer resp.Body.Close()

	isJson := resp.Header.Get("Content-Type") == "application/json"

	switch code := resp.StatusCode; {
	case code == 202:
		if isJson {
			return errors.New("Decoding of streaming JSON has not been implemented")
		}
		data, err := job.UnmarshalHttpResponse(resp.Header, nil, ResponseTable)
		if err != nil {
			return err
		}
		if pending, ok := data.(map[string]interface{}); ok {
			for k := range pending {
				res.WritePendingSuccess(k, pending[k])
			}
		}
		w := res.SuccessWithWrite(jobs.JobResponseOk, false, false)
		if _, err := io.Copy(w, resp.Body); err != nil {
			return err
		}
	case code == 204:
		data, err := job.UnmarshalHttpResponse(resp.Header, nil, ResponseTable)
		if err != nil {
			return err
		}
		if pending, ok := data.(map[string]interface{}); ok {
			for k := range pending {
				res.WritePendingSuccess(k, pending[k])
			}
		}
		res.Success(jobs.JobResponseOk)
	case code >= 200 && code < 300:
		if !isJson {
			return errors.New(fmt.Sprintf("remote: Response with %d status code had content type %s (should be application/json)", code, resp.Header.Get("Content-Type")))
		}
		data, err := job.UnmarshalHttpResponse(nil, resp.Body, ResponseJson)
		if err != nil {
			return err
		}
		res.SuccessWithData(jobs.JobResponseOk, data)
	default:
		if isJson {
			decoder := json.NewDecoder(resp.Body)
			data := httpFailureResponse{}
			if err := decoder.Decode(&data); err != nil {
				return err
			}
			res.Failure(jobs.SimpleJobError{jobs.JobResponseError, data.Message})
			return nil
		}
		io.Copy(os.Stderr, resp.Body)
		res.Failure(jobs.SimpleJobError{jobs.JobResponseError, "Unable to decode response."})
	}
	return nil
}