Say a mark-only provider's retirement as mark only
A provider that cannot disable keeps the consumer reachable until a person deletes it (hq ADR 0230); the listing and the approval say so instead of claiming access was disabled.
This commit is contained in:
@@ -195,7 +195,10 @@ func answerRetirement(ctx context.Context, conn *nats.Conn, p providerInstance,
|
|||||||
if answer.Error != "" {
|
if answer.Error != "" {
|
||||||
return fmt.Errorf("%s on %s refused: %s", p.Module, p.Node, answer.Error)
|
return fmt.Errorf("%s on %s refused: %s", p.Module, p.Node, answer.Error)
|
||||||
}
|
}
|
||||||
if approve {
|
if approve && state.RetiresBy == "mark-only" {
|
||||||
|
fmt.Printf("%s on %s marked %s retired, MARK ONLY: this provider cannot disable a consumer, so they keep "+
|
||||||
|
"their access until `cleanup delete`; `cleanup list` shows them\n", p.Module, p.Node, strings.Join(names, ", "))
|
||||||
|
} else if approve {
|
||||||
fmt.Printf("%s on %s retired %s: access disabled, data kept; `cleanup list` shows them\n", p.Module, p.Node,
|
fmt.Printf("%s on %s retired %s: access disabled, data kept; `cleanup list` shows them\n", p.Module, p.Node,
|
||||||
strings.Join(names, ", "))
|
strings.Join(names, ", "))
|
||||||
} else {
|
} else {
|
||||||
@@ -280,6 +283,8 @@ type retiredRow struct {
|
|||||||
AgeDays int `json:"age-days"`
|
AgeDays int `json:"age-days"`
|
||||||
SizeBytes *int64 `json:"size-bytes,omitempty"`
|
SizeBytes *int64 `json:"size-bytes,omitempty"`
|
||||||
Why string `json:"why,omitempty"`
|
Why string `json:"why,omitempty"`
|
||||||
|
// Access is "kept" for a consumer of a mark-only provider: retired on record, still reachable.
|
||||||
|
Access string `json:"access,omitempty"`
|
||||||
}
|
}
|
||||||
|
|
||||||
// retiredListing is every provider's retired consumers, and the providers that could not say.
|
// retiredListing is every provider's retired consumers, and the providers that could not say.
|
||||||
@@ -311,7 +316,7 @@ func retiredOf(ctx context.Context, conn *nats.Conn, instances []providerInstanc
|
|||||||
}
|
}
|
||||||
for _, c := range state.Retired {
|
for _, c := range state.Retired {
|
||||||
row := retiredRow{Node: p.Node, Module: p.Module, Consumer: c.Consumer, ConsumerNode: c.Node, Kind: c.Kind,
|
row := retiredRow{Node: p.Node, Module: p.Module, Consumer: c.Consumer, ConsumerNode: c.Node, Kind: c.Kind,
|
||||||
RetiredAt: c.RetiredAt, AgeDays: -1, SizeBytes: c.SizeBytes, Why: c.Why}
|
RetiredAt: c.RetiredAt, AgeDays: -1, SizeBytes: c.SizeBytes, Why: c.Why, Access: c.Access}
|
||||||
if at := retiredAt(c); !at.IsZero() {
|
if at := retiredAt(c); !at.IsZero() {
|
||||||
row.AgeDays = int(now.Sub(at).Hours() / 24)
|
row.AgeDays = int(now.Sub(at).Hours() / 24)
|
||||||
}
|
}
|
||||||
@@ -338,6 +343,9 @@ func printRetired(l retiredListing, asJSON bool) error {
|
|||||||
if r.Kind != "" && r.Kind != "consumer" {
|
if r.Kind != "" && r.Kind != "consumer" {
|
||||||
kind = " [" + r.Kind + "]"
|
kind = " [" + r.Kind + "]"
|
||||||
}
|
}
|
||||||
|
if r.Access == "kept" {
|
||||||
|
kind += " [MARK ONLY: access kept until deleted]"
|
||||||
|
}
|
||||||
fmt.Printf("%s on %s: %s%s — retired %s, %s, %s\n %s\n", r.Module, r.Node, r.Consumer, kind, age,
|
fmt.Printf("%s on %s: %s%s — retired %s, %s, %s\n %s\n", r.Module, r.Node, r.Consumer, kind, age,
|
||||||
sizeWords(r.SizeBytes), r.RetiredAt, orWhy("", r.Why))
|
sizeWords(r.SizeBytes), r.RetiredAt, orWhy("", r.Why))
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -458,3 +458,26 @@ func TestTheRetireAndCleanupVerbsComposeTheirCommandLines(t *testing.T) {
|
|||||||
t.Error("the generic verb would let a retirement or a deletion through without a why")
|
t.Error("the generic verb would let a retirement or a deletion through without a why")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// A mark-only provider's retired consumer keeps its access; the listing and the approval say so
|
||||||
|
// rather than claiming it was disabled (ADR 0230).
|
||||||
|
func TestNatsAMarkOnlyRetirementIsSaidAsSuch(t *testing.T) {
|
||||||
|
conn := onATestBus(t)
|
||||||
|
fake := &fakeProvider{}
|
||||||
|
kept := retiredDaysAgo("ledger", 3)
|
||||||
|
kept.Access = "kept"
|
||||||
|
fake.state.Retired = []link.RetiredConsumer{kept}
|
||||||
|
fake.state.RetiresBy = "mark-only"
|
||||||
|
fake.state.Waiting = &link.RetirementWaiting{Consumers: []link.RetiredConsumer{{Consumer: "a"}, {Consumer: "b"}}, Held: 2}
|
||||||
|
fake.serve(t, conn, "vault-mark", "anchor")
|
||||||
|
p := providerInstance{Node: "anchor", Module: "vault-mark"}
|
||||||
|
listing := retiredOf(t.Context(), conn, []providerInstance{p}, time.Now())
|
||||||
|
said := printed(t, func() error { return printRetired(listing, false) })
|
||||||
|
if !strings.Contains(said, "MARK ONLY") || listing.Retired[0].Access != "kept" {
|
||||||
|
t.Fatalf("%s %+v", said, listing)
|
||||||
|
}
|
||||||
|
said = printed(t, func() error { return answerRetirement(t.Context(), conn, p, true, whyFlags(t, "gone")) })
|
||||||
|
if !strings.Contains(said, "MARK ONLY") || strings.Contains(said, "access disabled") {
|
||||||
|
t.Fatal(said)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
@@ -49,6 +49,9 @@ type RetiredConsumer struct {
|
|||||||
SizeBytes *int64 `json:"size_bytes,omitempty"`
|
SizeBytes *int64 `json:"size_bytes,omitempty"`
|
||||||
// Kind is "consumer", or a backend's own word for something set aside ("set-aside-database").
|
// Kind is "consumer", or a backend's own word for something set aside ("set-aside-database").
|
||||||
Kind string `json:"kind,omitempty"`
|
Kind string `json:"kind,omitempty"`
|
||||||
|
// Access is "disabled" when the provider disabled it, "kept" for a mark-only provider whose consumer
|
||||||
|
// keeps its access until a person deletes it (ADR 0230); absent is disabled.
|
||||||
|
Access string `json:"access,omitempty"`
|
||||||
}
|
}
|
||||||
|
|
||||||
// Retirement is one provider's word about consumers the mesh stopped asking for.
|
// Retirement is one provider's word about consumers the mesh stopped asking for.
|
||||||
@@ -234,6 +237,10 @@ type RetirementState struct {
|
|||||||
Node string `json:"node"`
|
Node string `json:"node"`
|
||||||
Held []string `json:"held"`
|
Held []string `json:"held"`
|
||||||
StablePasses int `json:"stable_passes"`
|
StablePasses int `json:"stable_passes"`
|
||||||
|
// StableForSeconds is how long the same unasked set must hold as well (ADR 0230: ten minutes).
|
||||||
|
StableForSeconds int `json:"stable_for_seconds,omitempty"`
|
||||||
|
// RetiresBy is "disable", or "mark-only" for a provider that cannot disable a consumer.
|
||||||
|
RetiresBy string `json:"retires_by,omitempty"`
|
||||||
Bound string `json:"bound"`
|
Bound string `json:"bound"`
|
||||||
Waiting *RetirementWaiting `json:"waiting"`
|
Waiting *RetirementWaiting `json:"waiting"`
|
||||||
Rejected *RetirementRejected `json:"rejected"`
|
Rejected *RetirementRejected `json:"rejected"`
|
||||||
|
|||||||
Reference in New Issue
Block a user