Clear a step's success only when it was started and failed, and say updated when it passes again (novox/hq issue 467)
A bundle that could not be fetched refused nothing; clearing for it would rerun every step on a node once the artifact store came back from an outage.
This commit is contained in:
@@ -3,6 +3,8 @@ package apply
|
||||
import (
|
||||
"context"
|
||||
"errors"
|
||||
"net/http"
|
||||
"net/http/httptest"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"strings"
|
||||
@@ -25,6 +27,7 @@ type aStepBed struct {
|
||||
dir, body, digest string
|
||||
starts int // how many times the step's unit was started
|
||||
refuse bool // whether the step fails when started
|
||||
storeGone bool // whether the bundle's store answers
|
||||
}
|
||||
|
||||
func newStepBed(t *testing.T) *aStepBed {
|
||||
@@ -33,7 +36,18 @@ func newStepBed(t *testing.T) *aStepBed {
|
||||
unitDir, daemonRoot = units, bundles
|
||||
t.Cleanup(func() { unitDir, daemonRoot = wasUnits, wasBundles })
|
||||
body, digest := anArchive(t, map[string]string{"check": "#!/bin/sh\n"})
|
||||
return &aStepBed{t: t, dir: t.TempDir(), body: serving(t, body), digest: digest}
|
||||
b := &aStepBed{t: t, dir: t.TempDir(), digest: digest}
|
||||
// The bundle's store, which can be made not to answer.
|
||||
server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, _ *http.Request) {
|
||||
if b.storeGone {
|
||||
http.NotFound(w, nil)
|
||||
return
|
||||
}
|
||||
_, _ = w.Write(body)
|
||||
}))
|
||||
t.Cleanup(server.Close)
|
||||
b.body = server.URL + "/check.tar.gz"
|
||||
return b
|
||||
}
|
||||
|
||||
func (b *aStepBed) run(ctx context.Context, name string, args ...string) (string, error) {
|
||||
@@ -195,3 +209,46 @@ func TestAContainerStepThatFailedRunsAgain(t *testing.T) {
|
||||
t.Errorf("apply 5: a step that passed ran again: err %v, runs %d (want 4)", err, runs)
|
||||
}
|
||||
}
|
||||
|
||||
func TestAStepWhoseBundleCouldNotBeFetchedIsNotRunAgainForIt(t *testing.T) {
|
||||
// A fetch that fails is a failure of the step, and gates its module, but the step was never started:
|
||||
// it did not refuse anything, and its last success stands. Cleared for it, every step on a machine
|
||||
// would run again once the artifact store came back from an outage.
|
||||
b := newStepBed(t)
|
||||
_, known, err := b.apply(store.State{}, "good")
|
||||
if err != nil || b.starts != 1 {
|
||||
t.Fatalf("apply 1: err %v, starts %d", err, b.starts)
|
||||
}
|
||||
b.storeGone = true
|
||||
report, known, err := b.apply(known, "good")
|
||||
if err == nil || !skippedIn(report, "mod.after") || b.starts != 1 {
|
||||
t.Fatalf("store gone: err %v, skipped %v, starts %d", err, skippedIn(report, "mod.after"), b.starts)
|
||||
}
|
||||
b.storeGone = false
|
||||
report, _, err = b.apply(known, "good")
|
||||
if err != nil || b.starts != 1 {
|
||||
t.Errorf("store back: err %v, a step that passed and was never started since ran again (started %d times, want 1)", err, b.starts)
|
||||
}
|
||||
for _, o := range report.Outcomes {
|
||||
if o.ID == "mod.check" && o.Action != "unchanged" {
|
||||
t.Errorf("store back: the step reports %s: %s", o.Action, o.Detail)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestAStepPassingAfterAFailureSaysItWasUpdated(t *testing.T) {
|
||||
b := newStepBed(t)
|
||||
_, known, _ := b.apply(store.State{}, "good")
|
||||
b.refuse = true
|
||||
_, known, _ = b.apply(known, "bad")
|
||||
b.refuse = false
|
||||
report, _, err := b.apply(known, "bad")
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
for _, o := range report.Outcomes {
|
||||
if o.ID == "mod.check" && o.Action != "updated" {
|
||||
t.Errorf("a step with a record that passed after failing says %s, want updated", o.Action)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user