mirror of https://github.com/status-im/consul.git
consul: Adding flag to support future incompatible commands. Future self will thank me.
This commit is contained in:
parent
27a820d611
commit
35744c7210
|
@ -75,7 +75,18 @@ func (c *consulFSM) State() *StateStore {
|
|||
|
||||
func (c *consulFSM) Apply(log *raft.Log) interface{} {
|
||||
buf := log.Data
|
||||
switch structs.MessageType(buf[0]) {
|
||||
msgType := structs.MessageType(buf[0])
|
||||
|
||||
// Check if this message type should be ignored when unknown. This is
|
||||
// used so that new commands can be added with developer control if older
|
||||
// versions can safely ignore the command, or if they should crash.
|
||||
ignoreUnknown := false
|
||||
if msgType&structs.IgnoreUnknownTypeFlag == structs.IgnoreUnknownTypeFlag {
|
||||
msgType &= ^structs.IgnoreUnknownTypeFlag
|
||||
ignoreUnknown = true
|
||||
}
|
||||
|
||||
switch msgType {
|
||||
case structs.RegisterRequestType:
|
||||
return c.decodeRegister(buf[1:], log.Index)
|
||||
case structs.DeregisterRequestType:
|
||||
|
@ -89,7 +100,12 @@ func (c *consulFSM) Apply(log *raft.Log) interface{} {
|
|||
case structs.TombstoneRequestType:
|
||||
return c.applyTombstoneOperation(buf[1:], log.Index)
|
||||
default:
|
||||
panic(fmt.Errorf("failed to apply request: %#v", buf))
|
||||
if ignoreUnknown {
|
||||
c.logger.Printf("[WARN] consul.fsm: ignoring unknown message type (%d), upgrade to newer version", msgType)
|
||||
return nil
|
||||
} else {
|
||||
panic(fmt.Errorf("failed to apply request: %#v", buf))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -1059,3 +1059,33 @@ func TestFSM_TombstoneReap(t *testing.T) {
|
|||
t.Fatalf("bad: %v", res)
|
||||
}
|
||||
}
|
||||
|
||||
func TestFSM_IgnoreUnknown(t *testing.T) {
|
||||
path, err := ioutil.TempDir("", "fsm")
|
||||
if err != nil {
|
||||
t.Fatalf("err: %v", err)
|
||||
}
|
||||
defer os.RemoveAll(path)
|
||||
fsm, err := NewFSM(nil, path, os.Stderr)
|
||||
if err != nil {
|
||||
t.Fatalf("err: %v", err)
|
||||
}
|
||||
defer fsm.Close()
|
||||
|
||||
// Create a new reap request
|
||||
type UnknownRequest struct {
|
||||
Foo string
|
||||
}
|
||||
req := UnknownRequest{Foo: "bar"}
|
||||
msgType := structs.IgnoreUnknownTypeFlag | 64
|
||||
buf, err := structs.Encode(msgType, req)
|
||||
if err != nil {
|
||||
t.Fatalf("err: %v", err)
|
||||
}
|
||||
|
||||
// Apply should work, even though not supported
|
||||
resp := fsm.Apply(makeLog(buf))
|
||||
if err, ok := resp.(error); ok {
|
||||
t.Fatalf("resp: %v", err)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -26,6 +26,15 @@ const (
|
|||
TombstoneRequestType
|
||||
)
|
||||
|
||||
const (
|
||||
// IgnoreUnknownTypeFlag is set along with a MessageType
|
||||
// to indicate that the message type can be safely ignored
|
||||
// if it is not recognized. This is for future proofing, so
|
||||
// that new commands can be added in a way that won't cause
|
||||
// old servers to crash when the FSM attempts to process them.
|
||||
IgnoreUnknownTypeFlag MessageType = 128
|
||||
)
|
||||
|
||||
const (
|
||||
// HealthAny is special, and is used as a wild card,
|
||||
// not as a specific state.
|
||||
|
|
Loading…
Reference in New Issue