120 lines
3.4 KiB
Go
120 lines
3.4 KiB
Go
package httpserver
|
|
|
|
import (
|
|
"encoding/json"
|
|
"fmt"
|
|
"net/http"
|
|
"strings"
|
|
"time"
|
|
|
|
"github.com/toki/oto/services/core/internal/cicdstate"
|
|
otopb "github.com/toki/oto/services/core/oto"
|
|
)
|
|
|
|
func jobToJSON(j *cicdstate.Job) map[string]interface{} {
|
|
out := map[string]interface{}{
|
|
"id": j.ID,
|
|
"name": j.Name,
|
|
"state": j.State,
|
|
"created_at": j.CreatedAt.Format(time.RFC3339),
|
|
"updated_at": j.UpdatedAt.Format(time.RFC3339),
|
|
"execution_id": j.ExecutionID,
|
|
}
|
|
if j.RunInput != nil {
|
|
out["run_request"] = runInputToJSON(j.RunInput)
|
|
}
|
|
return out
|
|
}
|
|
|
|
// validateRunInput enforces the remote claim contract: exactly one of
|
|
// pipeline_yaml or pipeline_yaml_path must be provided.
|
|
func validateRunInput(in *cicdstate.RunInput) error {
|
|
hasYAML := strings.TrimSpace(in.PipelineYAML) != ""
|
|
hasPath := strings.TrimSpace(in.PipelineYAMLPath) != ""
|
|
if hasYAML == hasPath {
|
|
return fmt.Errorf("run request must set exactly one of pipeline_yaml or pipeline_yaml_path")
|
|
}
|
|
return nil
|
|
}
|
|
|
|
// runRequestFromJSON converts an incoming otopb.RunRequest decoded from the job
|
|
// create body into a store-level RunInput. It returns nil when no run request
|
|
// was supplied, keeping job creation backward compatible.
|
|
func runRequestFromJSON(rr *otopb.RunRequest) *cicdstate.RunInput {
|
|
if rr == nil {
|
|
return nil
|
|
}
|
|
in := &cicdstate.RunInput{
|
|
PipelineYAMLPath: rr.GetPipelineYamlPath(),
|
|
PipelineYAML: rr.GetPipelineYaml(),
|
|
CommandTypes: append([]string(nil), rr.GetCommandTypes()...),
|
|
}
|
|
if len(rr.GetVariables()) > 0 {
|
|
in.Variables = make(map[string]string, len(rr.GetVariables()))
|
|
for k, v := range rr.GetVariables() {
|
|
in.Variables[k] = v
|
|
}
|
|
}
|
|
return in
|
|
}
|
|
|
|
// runRequestToProto builds the claim response RunRequest from the stored input,
|
|
// filling in the runner/job/execution identifiers resolved at claim time.
|
|
func runRequestToProto(in *cicdstate.RunInput, runnerID, jobID, execID string) *otopb.RunRequest {
|
|
if in == nil {
|
|
return nil
|
|
}
|
|
rr := &otopb.RunRequest{
|
|
RunnerId: runnerID,
|
|
JobId: jobID,
|
|
ExecutionId: execID,
|
|
PipelineYamlPath: in.PipelineYAMLPath,
|
|
PipelineYaml: in.PipelineYAML,
|
|
CommandTypes: append([]string(nil), in.CommandTypes...),
|
|
}
|
|
if len(in.Variables) > 0 {
|
|
rr.Variables = make(map[string]string, len(in.Variables))
|
|
for k, v := range in.Variables {
|
|
rr.Variables[k] = v
|
|
}
|
|
}
|
|
return rr
|
|
}
|
|
|
|
func runInputToJSON(in *cicdstate.RunInput) map[string]interface{} {
|
|
return map[string]interface{}{
|
|
"pipeline_yaml_path": in.PipelineYAMLPath,
|
|
"pipeline_yaml": in.PipelineYAML,
|
|
"variables": in.Variables,
|
|
"command_types": in.CommandTypes,
|
|
}
|
|
}
|
|
|
|
func execToJSON(e *cicdstate.Execution) map[string]interface{} {
|
|
return map[string]interface{}{
|
|
"id": e.ID,
|
|
"job_id": e.JobID,
|
|
"state": e.State,
|
|
"created_at": e.CreatedAt.Format(time.RFC3339),
|
|
"updated_at": e.UpdatedAt.Format(time.RFC3339),
|
|
"execution_id": e.ID,
|
|
}
|
|
}
|
|
|
|
func logsToJSON(logs []cicdstate.LogEntry) map[string]interface{} {
|
|
return map[string]interface{}{
|
|
"logs": logs,
|
|
}
|
|
}
|
|
|
|
func artifactsToJSON(artifacts []cicdstate.ArtifactEntry) map[string]interface{} {
|
|
return map[string]interface{}{
|
|
"artifacts": artifacts,
|
|
}
|
|
}
|
|
|
|
func writeResponse(w http.ResponseWriter, status int, data interface{}) {
|
|
w.Header().Set("Content-Type", "application/json")
|
|
w.WriteHeader(status)
|
|
_ = json.NewEncoder(w).Encode(data)
|
|
}
|