From ae194c147024466f729cbcc2bf035d224fe3a198 Mon Sep 17 00:00:00 2001 From: "J. David Lowe" Date: Fri, 4 Jun 2021 08:15:34 -0700 Subject: [PATCH] etcdserver: don't activate alarm w/missing AlarmType Narrowly prevent etcd from crashing when given a bad ACTIVATE payload, e.g.: $ curl -d "{\"action\":\"ACTIVATE\"}" ${ETCD}/v3/maintenance/alarm curl: (52) Empty reply from server --- server/etcdserver/apply.go | 5 ++++- tests/e2e/v3_curl_test.go | 15 +++++++++++++++ 2 files changed, 19 insertions(+), 1 deletion(-) diff --git a/server/etcdserver/apply.go b/server/etcdserver/apply.go index cf281d1a9c7..5a77ef37734 100644 --- a/server/etcdserver/apply.go +++ b/server/etcdserver/apply.go @@ -721,6 +721,9 @@ func (a *applierV3backend) Alarm(ar *pb.AlarmRequest) (*pb.AlarmResponse, error) case pb.AlarmRequest_GET: resp.Alarms = a.s.alarmStore.Get(ar.Alarm) case pb.AlarmRequest_ACTIVATE: + if ar.Alarm == pb.AlarmType_NONE { + break + } m := a.s.alarmStore.Activate(types.ID(ar.MemberID), ar.Alarm) if m == nil { break @@ -738,7 +741,7 @@ func (a *applierV3backend) Alarm(ar *pb.AlarmRequest) (*pb.AlarmResponse, error) case pb.AlarmType_NOSPACE: a.s.applyV3 = newApplierV3Capped(a) default: - lg.Warn("unimplemented alarm activation", zap.String("alarm", fmt.Sprintf("%+v", m))) + lg.Panic("unimplemented alarm activation", zap.String("alarm", fmt.Sprintf("%+v", m))) } case pb.AlarmRequest_DEACTIVATE: m := a.s.alarmStore.Deactivate(types.ID(ar.MemberID), ar.Alarm) diff --git a/tests/e2e/v3_curl_test.go b/tests/e2e/v3_curl_test.go index ecc94888d14..7c697115057 100644 --- a/tests/e2e/v3_curl_test.go +++ b/tests/e2e/v3_curl_test.go @@ -366,6 +366,21 @@ func testV3CurlResignMissiongLeaderKey(cx ctlCtx) { } } +func TestV3CurlMaintenanceAlarmMissiongAlarm(t *testing.T) { + for _, p := range apiPrefix { + testCtl(t, testV3CurlMaintenanceAlarmMissiongAlarm, withApiPrefix(p), withCfg(*newConfigNoTLS())) + } +} + +func testV3CurlMaintenanceAlarmMissiongAlarm(cx ctlCtx) { + if err := cURLPost(cx.epc, cURLReq{ + endpoint: path.Join(cx.apiPrefix, "/maintenance/alarm"), + value: `{"action": "ACTIVATE"}`, + }); err != nil { + cx.t.Fatalf("failed post maintenance alarm (%s) (%v)", cx.apiPrefix, err) + } +} + // to manually decode; JSON marshals integer fields with // string types, so can't unmarshal with epb.CampaignResponse type campaignResponse struct {