feat: add Docker Swarm support (MODE=swarm) #4
@@ -56,7 +56,12 @@ func (h *Handlers) Update(w http.ResponseWriter, r *http.Request) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
jobs, err := h.finder.FindJobs(r.Context(), req.Image)
|
requestedImage := req.Image
|
||||||
|
if req.Tag != "" {
|
||||||
|
requestedImage = req.Image + ":" + req.Tag
|
||||||
|
}
|
||||||
|
|
||||||
|
jobs, err := h.finder.FindJobs(r.Context(), requestedImage)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
writeJSONError(w, http.StatusInternalServerError, "discovery failed: "+err.Error())
|
writeJSONError(w, http.StatusInternalServerError, "discovery failed: "+err.Error())
|
||||||
return
|
return
|
||||||
|
|||||||
@@ -21,9 +21,21 @@ import (
|
|||||||
type fakeFinder struct {
|
type fakeFinder struct {
|
||||||
jobs []discovery.Job
|
jobs []discovery.Job
|
||||||
err error
|
err error
|
||||||
|
|
||||||
|
// gotImage records the image argument passed to FindJobs, for
|
||||||
|
// assertions on the exact reference the handler built.
|
||||||
|
gotImage string
|
||||||
|
// swarmShaped, when true, makes FindJobs return a Job whose Image
|
||||||
|
// field carries the received image argument, simulating
|
||||||
|
// discovery.SwarmDiscovery.FindJobs.
|
||||||
|
swarmShaped bool
|
||||||
}
|
}
|
||||||
|
|
||||||
func (f *fakeFinder) FindJobs(_ context.Context, _ string) ([]discovery.Job, error) {
|
func (f *fakeFinder) FindJobs(_ context.Context, image string) ([]discovery.Job, error) {
|
||||||
|
f.gotImage = image
|
||||||
|
if f.swarmShaped {
|
||||||
|
return []discovery.Job{{Service: "myapp_web", ServiceID: "svc1", Image: image}}, f.err
|
||||||
|
}
|
||||||
return f.jobs, f.err
|
return f.jobs, f.err
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -157,6 +169,42 @@ func TestHealthz_503WhenDockerDown(t *testing.T) {
|
|||||||
require.Equal(t, http.StatusServiceUnavailable, w.Code)
|
require.Equal(t, http.StatusServiceUnavailable, w.Code)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestUpdate_FindJobsCalledWithTaggedImage(t *testing.T) {
|
||||||
|
finder := &fakeFinder{}
|
||||||
|
h := api.NewHandlers(finder, &fakeSubmitter{}, &fakePinger{}, "v0.0.0", "abc", "now", nil)
|
||||||
|
body, _ := json.Marshal(api.UpdateRequest{Image: "registry.example.com/myapp", Tag: "v2"})
|
||||||
|
req := httptest.NewRequest(http.MethodPost, "/update", bytes.NewReader(body))
|
||||||
|
w := httptest.NewRecorder()
|
||||||
|
h.Update(w, req)
|
||||||
|
require.Equal(t, "registry.example.com/myapp:v2", finder.gotImage)
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestUpdate_FindJobsCalledWithBareImageWhenNoTag(t *testing.T) {
|
||||||
|
finder := &fakeFinder{}
|
||||||
|
h := api.NewHandlers(finder, &fakeSubmitter{}, &fakePinger{}, "v0.0.0", "abc", "now", nil)
|
||||||
|
body, _ := json.Marshal(api.UpdateRequest{Image: "registry.example.com/myapp"})
|
||||||
|
req := httptest.NewRequest(http.MethodPost, "/update", bytes.NewReader(body))
|
||||||
|
w := httptest.NewRecorder()
|
||||||
|
h.Update(w, req)
|
||||||
|
require.Equal(t, "registry.example.com/myapp", finder.gotImage)
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestUpdate_SwarmModeThreadsTagThroughDiscovery(t *testing.T) {
|
||||||
|
finder := &fakeFinder{swarmShaped: true}
|
||||||
|
h := api.NewHandlers(finder, &fakeSubmitter{}, &fakePinger{}, "v0.0.0", "abc", "now", nil)
|
||||||
|
body, _ := json.Marshal(api.UpdateRequest{Image: "registry.example.com/myapp", Tag: "v2"})
|
||||||
|
req := httptest.NewRequest(http.MethodPost, "/update", bytes.NewReader(body))
|
||||||
|
w := httptest.NewRecorder()
|
||||||
|
h.Update(w, req)
|
||||||
|
require.Equal(t, http.StatusOK, w.Code)
|
||||||
|
// The fake Finder's returned Job.Image (as SwarmDiscovery would build
|
||||||
|
// it) reflects the image argument it received from the handler.
|
||||||
|
// Asserting on the captured argument proves the full request ->
|
||||||
|
// discovery flow carries the tag through to what would reach the
|
||||||
|
// SwarmExecutor.
|
||||||
|
require.Equal(t, "registry.example.com/myapp:v2", finder.gotImage)
|
||||||
|
}
|
||||||
|
|
||||||
func TestVersion(t *testing.T) {
|
func TestVersion(t *testing.T) {
|
||||||
h := api.NewHandlers(&fakeFinder{}, &fakeSubmitter{}, &fakePinger{}, "v1.2.3", "abcdef", "2026-05-22T00:00:00Z", nil)
|
h := api.NewHandlers(&fakeFinder{}, &fakeSubmitter{}, &fakePinger{}, "v1.2.3", "abcdef", "2026-05-22T00:00:00Z", nil)
|
||||||
req := httptest.NewRequest(http.MethodGet, "/version", nil)
|
req := httptest.NewRequest(http.MethodGet, "/version", nil)
|
||||||
|
|||||||
Reference in New Issue
Block a user