diff --git a/internal/job/job.go b/internal/job/job.go index 62dc51093..88f7d7bc4 100644 --- a/internal/job/job.go +++ b/internal/job/job.go @@ -3,10 +3,12 @@ package job import ( "osbuild-composer/internal/pipeline" "osbuild-composer/internal/target" + + "github.com/google/uuid" ) type Job struct { - ComposeID string + ComposeID uuid.UUID Pipeline pipeline.Pipeline Targets []target.Target } diff --git a/internal/job/store.go b/internal/job/store.go index ac132f15a..9ade9aaf3 100644 --- a/internal/job/store.go +++ b/internal/job/store.go @@ -2,22 +2,24 @@ package job import ( "sync" + + "github.com/google/uuid" ) type Store struct { - jobs map[string]Job + jobs map[uuid.UUID]Job mu sync.RWMutex } func NewStore() *Store { var s Store - s.jobs = make(map[string]Job) + s.jobs = make(map[uuid.UUID]Job) return &s } -func (s *Store) AddJob(id string, job Job) bool { +func (s *Store) AddJob(id uuid.UUID, job Job) bool { s.mu.Lock() defer s.mu.Unlock() @@ -31,7 +33,7 @@ func (s *Store) AddJob(id string, job Job) bool { return true } -func (s *Store) UpdateJob(id string, job Job) bool { +func (s *Store) UpdateJob(id uuid.UUID, job Job) bool { s.mu.Lock() defer s.mu.Unlock() @@ -43,7 +45,7 @@ func (s *Store) UpdateJob(id string, job Job) bool { return true } -func (s *Store) DeleteJob(id string) { +func (s *Store) DeleteJob(id uuid.UUID) { s.mu.Lock() defer s.mu.Unlock() diff --git a/internal/jobqueue/api.go b/internal/jobqueue/api.go index 1dfec6062..4c83eb5f5 100644 --- a/internal/jobqueue/api.go +++ b/internal/jobqueue/api.go @@ -9,6 +9,7 @@ import ( "osbuild-composer/internal/pipeline" "osbuild-composer/internal/target" + "github.com/google/uuid" "github.com/julienschmidt/httprouter" ) @@ -77,7 +78,7 @@ func statusResponseError(writer http.ResponseWriter, code int, errors ...string) func (api *API) addJobHandler(writer http.ResponseWriter, request *http.Request, _ httprouter.Params) { type requestBody struct { - ID string `json:"id"` + ID uuid.UUID `json:"id"` } type replyBody struct { Pipeline pipeline.Pipeline `json:"pipeline"` @@ -123,14 +124,20 @@ func (api *API) updateJobHandler(writer http.ResponseWriter, request *http.Reque return } + id, err := uuid.Parse(params.ByName("id")) + if err != nil { + statusResponseError(writer, http.StatusBadRequest, "invalid job id: "+err.Error()) + return + } + var body requestBody - err := json.NewDecoder(request.Body).Decode(&body) + err = json.NewDecoder(request.Body).Decode(&body) if err != nil { statusResponseError(writer, http.StatusBadRequest, "invalid status: "+err.Error()) } else if body.Status == "running" { statusResponseOK(writer) } else if body.Status == "finished" { - api.jobStore.DeleteJob(params.ByName("id")) + api.jobStore.DeleteJob(id) statusResponseOK(writer) } else { statusResponseError(writer, http.StatusBadRequest, "invalid status: "+body.Status) diff --git a/internal/jobqueue/api_test.go b/internal/jobqueue/api_test.go index 36a008ccb..e5451a70f 100644 --- a/internal/jobqueue/api_test.go +++ b/internal/jobqueue/api_test.go @@ -14,6 +14,8 @@ import ( "osbuild-composer/internal/jobqueue" "osbuild-composer/internal/pipeline" "osbuild-composer/internal/target" + + "github.com/google/uuid" ) func testRoute(t *testing.T, api *jobqueue.API, method, path, body string, expectedStatus int, expectedJSON string) { @@ -64,7 +66,7 @@ func testRoute(t *testing.T, api *jobqueue.API, method, path, body string, expec } func TestBasic(t *testing.T) { - expected_job := `{"pipeline":{"assembler":{"name":"org.osbuild.tar","options":{"filename":"image.tar"}}},"targets":[{"name":"org.osbuild.local","options":{"location":"/var/lib/osbuild-composer/ffffffff-ffff–ffff-ffff-ffffffffffff"}}]}` + expected_job := `{"pipeline":{"assembler":{"name":"org.osbuild.tar","options":{"filename":"image.tar"}}},"targets":[{"name":"org.osbuild.local","options":{"location":"/var/lib/osbuild-composer/ffffffff-ffff-ffff-ffff-ffffffffffff"}}]}` var cases = []struct { Method string Path string @@ -77,8 +79,8 @@ func TestBasic(t *testing.T) { {"PATH", "/job-queue/v1/foo", ``, http.StatusNotFound, ``}, {"DELETE", "/job-queue/v1/foo", ``, http.StatusNotFound, ``}, - {"POST", "/job-queue/v1/jobs", `{"id":"ffffffff-ffff–ffff-ffff-ffffffffffff"}`, http.StatusOK, expected_job}, - {"POST", "/job-queue/v1/jobs", `{"id":"ffffffff-ffff–ffff-ffff-ffffffffffff"}`, http.StatusBadRequest, ``}, + {"POST", "/job-queue/v1/jobs", `{"id":"ffffffff-ffff-ffff-ffff-ffffffffffff"}`, http.StatusCreated, expected_job}, + {"POST", "/job-queue/v1/jobs", `{"id":"ffffffff-ffff-ffff-ffff-ffffffffffff"}`, http.StatusBadRequest, ``}, //{"PATCH", "/job-queue/v1/jobs/aaaaaaaa-aaaa-aaaa-aaaa-aaaaaaaaaaaa", `{"status":"finished"}`, http.StatusBadRequest, ``}, {"PATCH", "/job-queue/v1/jobs/ffffffff-ffff-ffff-ffff-ffffffffffff", `{"status":"running"}`, http.StatusOK, ``}, {"PATCH", "/job-queue/v1/jobs/ffffffff-ffff-ffff-ffff-ffffffffffff", `{"status":"running"}`, http.StatusOK, ``}, @@ -90,8 +92,9 @@ func TestBasic(t *testing.T) { jobChannel := make(chan job.Job, 100) api := jobqueue.New(nil, jobChannel) for _, c := range cases { + id, _ := uuid.Parse("ffffffff-ffff-ffff-ffff-ffffffffffff") jobChannel <- job.Job{ - ComposeID: "ffffffff-ffff–ffff-ffff-ffffffffffff", + ComposeID: id, Pipeline: pipeline.Pipeline{ Assembler: pipeline.Assembler{ Name: "org.osbuild.tar", @@ -103,7 +106,7 @@ func TestBasic(t *testing.T) { Targets: []target.Target{{ Name: "org.osbuild.local", Options: target.LocalOptions{ - Location: "/var/lib/osbuild-composer/ffffffff-ffff–ffff-ffff-ffffffffffff", + Location: "/var/lib/osbuild-composer/ffffffff-ffff-ffff-ffff-ffffffffffff", }}, }, } diff --git a/internal/weldr/api.go b/internal/weldr/api.go index 620b8d9c4..65144cdc1 100644 --- a/internal/weldr/api.go +++ b/internal/weldr/api.go @@ -8,6 +8,7 @@ import ( "strings" "time" + "github.com/google/uuid" "github.com/julienschmidt/httprouter" "osbuild-composer/internal/job" @@ -601,6 +602,10 @@ func (api *API) composeHandler(writer http.ResponseWriter, httpRequest *http.Req ComposeType string `json:"compose_type"` Branch string `json:"branch"` } + type ComposeReply struct { + BuildID uuid.UUID `json:"build_id"` + Status bool `json:"status"` + } contentType := httpRequest.Header["Content-Type"] if len(contentType) != 1 || contentType[0] != "application/json" { @@ -615,20 +620,23 @@ func (api *API) composeHandler(writer http.ResponseWriter, httpRequest *http.Req return } + reply := ComposeReply{ + BuildID: uuid.New(), + Status: true, + } + bp := blueprint{} changed := false found := api.store.getBlueprint(cr.BlueprintName, &bp, &changed) // TODO: what to do with changed? - uuid := "ffffffff-ffff–ffff-ffff-ffffffffffff" // TODO: generate - if found { api.pendingJobs <- job.Job{ - ComposeID: uuid, + ComposeID: reply.BuildID, Pipeline: bp.translateToPipeline(cr.ComposeType), Targets: []target.Target{{ Name: "org.osbuild.local", Options: target.LocalOptions{ - Location: "/var/lib/osbuild-composer/" + uuid, + Location: "/var/lib/osbuild-composer/" + reply.BuildID.String(), }}, }, } @@ -637,7 +645,7 @@ func (api *API) composeHandler(writer http.ResponseWriter, httpRequest *http.Req return } - statusResponseOK(writer) + json.NewEncoder(writer).Encode(reply) } func (api *API) composeTypesHandler(writer http.ResponseWriter, request *http.Request, _ httprouter.Params) { diff --git a/internal/weldr/api_test.go b/internal/weldr/api_test.go index 43ee6c2cf..bd08c4a73 100644 --- a/internal/weldr/api_test.go +++ b/internal/weldr/api_test.go @@ -152,7 +152,7 @@ func TestCompose(t *testing.T) { http.StatusBadRequest, `{"status":false,"errors":["blueprint does not exist"]}`) testRoute(t, api, "POST", "/api/v0/compose", `{"blueprint_name": "test","compose_type": "tar","branch": "master"}`, - http.StatusOK, `{"status":true}`) + http.StatusOK, `*`) job := <-jobChannel if job.Pipeline.Assembler.Name != "org.osbuild.tar" {