A host accepts an explicitly-empty declaration (hq 127) #29
@@ -1145,6 +1145,13 @@ type envelope struct {
|
|||||||
Version int `json:"declaration"`
|
Version int `json:"declaration"`
|
||||||
For string `json:"for,omitempty"`
|
For string `json:"for,omitempty"`
|
||||||
Adoption *Adoption `json:"adoption,omitempty"`
|
Adoption *Adoption `json:"adoption,omitempty"`
|
||||||
|
// OwnsNothing is the control plane saying, explicitly, that this node's declaration is empty
|
||||||
|
// on purpose — it owns nothing the mesh put there (novox/hq issue 127). Without it an empty
|
||||||
|
// resources list is refused as a likely mistake; with it the node applies the empty
|
||||||
|
// declaration and drops what it last held. The two are distinguished because a truncated or
|
||||||
|
// mis-composed body arrives as empty too, and a host that could not tell them apart would let
|
||||||
|
// a bug quietly strip a machine.
|
||||||
|
OwnsNothing bool `json:"owns_nothing,omitempty"`
|
||||||
Resources []json.RawMessage `json:"resources"`
|
Resources []json.RawMessage `json:"resources"`
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1165,7 +1172,7 @@ func parse(raw []byte, allowActions bool) (*Declaration, error) {
|
|||||||
d := &Declaration{Version: env.Version, For: env.For, Adoption: env.Adoption}
|
d := &Declaration{Version: env.Version, For: env.For, Adoption: env.Adoption}
|
||||||
var problems []string
|
var problems []string
|
||||||
|
|
||||||
if len(env.Resources) == 0 {
|
if len(env.Resources) == 0 && !env.OwnsNothing {
|
||||||
problems = append(problems, "no resources. An empty declaration is a mistake, not a "+
|
problems = append(problems, "no resources. An empty declaration is a mistake, not a "+
|
||||||
"machine with nothing on it — say so with an explicit empty list if that is meant")
|
"machine with nothing on it — say so with an explicit empty list if that is meant")
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -451,3 +451,16 @@ func TestAContainersResolverAndAddressAreAddressesOrRefused(t *testing.T) {
|
|||||||
t.Errorf("a well-formed resolver and address were refused: %v", p)
|
t.Errorf("a well-formed resolver and address were refused: %v", p)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestAnExplicitlyEmptyDeclarationIsAccepted(t *testing.T) {
|
||||||
|
// A deliberately-empty declaration (novox/hq issue 127) says owns_nothing, and is applied so
|
||||||
|
// the node drops what it last held — distinct from an accidental empty body, which is refused.
|
||||||
|
if _, err := Parse([]byte(`{"declaration":1,"owns_nothing":true,"resources":[]}`)); err != nil {
|
||||||
|
t.Fatalf("an explicitly-empty declaration must be accepted: %v", err)
|
||||||
|
}
|
||||||
|
// Without the marker, an empty declaration is still refused as a likely mistake.
|
||||||
|
_, err := Parse([]byte(`{"declaration":1,"resources":[]}`))
|
||||||
|
if err == nil || !strings.Contains(err.Error(), "no resources") {
|
||||||
|
t.Fatalf("an unmarked empty declaration must still be refused; got %v", err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user