diff --git a/api/status/status.go b/api/status/status.go index 53d361e3..7fe91114 100644 --- a/api/status/status.go +++ b/api/status/status.go @@ -65,6 +65,8 @@ const ( NodeUnderMaintenance // InvalidArgument is a local Code value for INVALID_ARGUMENT status. InvalidArgument + // ResourceExhausted is a local Code value for RESOURCE_EXHAUSTED status. + ResourceExhausted ) const ( diff --git a/client/status/common.go b/client/status/common.go index 486bc72a..65c4ba31 100644 --- a/client/status/common.go +++ b/client/status/common.go @@ -296,3 +296,62 @@ func (x *InvalidArgument) SetMessage(v string) { func (x InvalidArgument) Message() string { return x.v2.Message() } + +// ResourceExhausted is a failure status indicating that +// the operation cannot be performed due to a lack of resources. +// Instances provide Status and StatusV2 interfaces. +type ResourceExhausted struct { + v2 status.Status +} + +const defaultResourceExhaustedMsg = "resource exhausted" + +// Error implements the error interface. +func (x *ResourceExhausted) Error() string { + msg := x.v2.Message() + if msg == "" { + msg = defaultResourceExhaustedMsg + } + + return errMessageStatusV2( + globalizeCodeV2(status.ResourceExhausted, status.GlobalizeCommonFail), + msg, + ) +} + +// implements local interface defined in FromStatusV2 func. +func (x *ResourceExhausted) fromStatusV2(st *status.Status) { + x.v2 = *st +} + +// ToStatusV2 implements StatusV2 interface method. +// If the value was returned by FromStatusV2, returns the source message. +// Otherwise, returns message with +// - code: RESOURCE_EXHAUSTED; +// - string message: written message via SetMessage or +// "resource exhausted" as a default message; +// - details: empty. +func (x ResourceExhausted) ToStatusV2() *status.Status { + x.v2.SetCode(globalizeCodeV2(status.ResourceExhausted, status.GlobalizeCommonFail)) + if x.v2.Message() == "" { + x.v2.SetMessage(defaultResourceExhaustedMsg) + } + + return &x.v2 +} + +// SetMessage writes invalid argument failure message. +// Message should be used for debug purposes only. +// +// See also Message. +func (x *ResourceExhausted) SetMessage(v string) { + x.v2.SetMessage(v) +} + +// Message returns status message. Zero status returns empty message. +// Message should be used for debug purposes only. +// +// See also SetMessage. +func (x ResourceExhausted) Message() string { + return x.v2.Message() +} diff --git a/client/status/common_test.go b/client/status/common_test.go index e55883e4..0c3d2d5d 100644 --- a/client/status/common_test.go +++ b/client/status/common_test.go @@ -167,3 +167,42 @@ func TestInvalidArgument(t *testing.T) { require.Equal(t, msg, stV2.Message()) }) } + +func TestResourceExhausted(t *testing.T) { + t.Run("default", func(t *testing.T) { + var st apistatus.ResourceExhausted + + require.Empty(t, st.Message()) + }) + + t.Run("custom message", func(t *testing.T) { + var st apistatus.ResourceExhausted + msg := "some message" + + st.SetMessage(msg) + + stV2 := st.ToStatusV2() + + require.Equal(t, msg, st.Message()) + require.Equal(t, msg, stV2.Message()) + }) + + t.Run("empty to V2", func(t *testing.T) { + var st apistatus.ResourceExhausted + + stV2 := st.ToStatusV2() + + require.Equal(t, "resource exhausted", stV2.Message()) + }) + + t.Run("non-empty to V2", func(t *testing.T) { + var st apistatus.ResourceExhausted + msg := "some other msg" + + st.SetMessage(msg) + + stV2 := st.ToStatusV2() + + require.Equal(t, msg, stV2.Message()) + }) +} diff --git a/client/status/v2.go b/client/status/v2.go index 95dfb8a4..6ee3d84a 100644 --- a/client/status/v2.go +++ b/client/status/v2.go @@ -80,6 +80,8 @@ func FromStatusV2(st *status.Status) Status { decoder = new(NodeUnderMaintenance) case status.InvalidArgument: decoder = new(InvalidArgument) + case status.ResourceExhausted: + decoder = new(ResourceExhausted) } case object.LocalizeFailStatus(&code): switch code {