Repository: digitalocean/doctl
Pull request #1316 (2022-11-22 20:39:16)

Adds subcommands to enable/disable a trigger
 - Adds subcommands to enable a disable a trigger.


Patch:
diff --git a/commands/triggers.go b/commands/triggers.go
index 3ea2a178..d236eb00 100644
--- a/commands/triggers.go
+++ b/commands/triggers.go
@@ -20,6 +20,7 @@ import (
 
 	"github.com/digitalocean/doctl"
 	"github.com/digitalocean/doctl/commands/displayers"
+	"github.com/digitalocean/doctl/do"
 	"github.com/spf13/cobra"
 )
 
@@ -42,6 +43,9 @@ when events from that source type occur.  Currently, only the ` + "`" + `schedul
 		Writer, aliasOpt("ls"), displayerType(&displayers.Triggers{}))
 	AddStringFlag(list, "function", "f", "", "list only triggers for the chosen function")
 
+	CmdBuilder(cmd, RunTriggerToggle(true), "enable <triggerName>", "Enable a trigger", "Use `doctl serverless triggers enable <triggerName>` to enable a trigger", Writer)
+	CmdBuilder(cmd, RunTriggerToggle(false), "disable <triggerName>", "Disable a trigger", "Use `doctl serverless triggers disable <triggerName>` to disable a trigger", Writer)
+
 	CmdBuilder(cmd, RunTriggersGet, "get <triggerName>", "Get the details for a trigger",
 		`Use `+"`"+`doctl serverless triggers get <triggerName>`+"`"+` for details about <triggerName>.`,
 		Writer)
@@ -80,6 +84,25 @@ func RunTriggersGet(c *CmdConfig) error {
 	return nil
 }
 
+// RunTriggerToggle provides the logic for 'doctl sls trig enabled/disabled'
+func RunTriggerToggle(isEnabled bool) func(*CmdConfig) error {
+	return func(c *CmdConfig) error {
+		err := ensureOneArg(c)
+
+		if err != nil {
+			return err
+		}
+
+		trigger, err := c.Serverless().UpdateTrigger(context.TODO(), c.Args[0], &do.UpdateTriggerRequest{IsEnabled: isEnabled})
+
+		if err != nil {
+			return err
+		}
+
+		return c.Display(&displayers.Triggers{List: []do.ServerlessTrigger{trigger}})
+	}
+}
+
 // cleanTriggers is the subroutine of undeploy that removes all the triggers of a namespace
 func cleanTriggers(c *CmdConfig) error {
 	sls := c.Serverless()
diff --git a/do/mocks/ServerlessService.go b/do/mocks/ServerlessService.go
index 749c9293..b46e975f 100644
--- a/do/mocks/ServerlessService.go
+++ b/do/mocks/ServerlessService.go
@@ -505,6 +505,21 @@ func (mr *MockServerlessServiceMockRecorder) Stream(arg0 interface{}) *gomock.Ca
 	return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "Stream", reflect.TypeOf((*MockServerlessService)(nil).Stream), arg0)
 }
 
+// UpdateTrigger mocks base method.
+func (m *MockServerlessService) UpdateTrigger(arg0 context.Context, arg1 string, arg2 *do.UpdateTriggerRequest) (do.ServerlessTrigger, error) {
+	m.ctrl.T.Helper()
+	ret := m.ctrl.Call(m, "UpdateTrigger", arg0, arg1, arg2)
+	ret0, _ := ret[0].(do.ServerlessTrigger)
+	ret1, _ := ret[1].(error)
+	return ret0, ret1
+}
+
+// UpdateTrigger indicates an expected call of UpdateTrigger.
+func (mr *MockServerlessServiceMockRecorder) UpdateTrigger(arg0, arg1, arg2 interface{}) *gomock.Call {
+	mr.mock.ctrl.T.Helper()
+	return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "UpdateTrigger", reflect.TypeOf((*MockServerlessService)(nil).UpdateTrigger), arg0, arg1, arg2)
+}
+
 // WriteCredentials mocks base method.
 func (m *MockServerlessService) WriteCredentials(arg0 do.ServerlessCredentials) error {
 	m.ctrl.T.Helper()
diff --git a/do/serverless.go b/do/serverless.go
index 65c55f2f..e9e16fab 100644
--- a/do/serverless.go
+++ b/do/serverless.go
@@ -176,13 +176,18 @@ type ServerlessTriggerGetResponse struct {
 	Trigger ServerlessTrigger `json:"Trigger,omitempty"`
 }
 
+type UpdateTriggerRequest struct {
+	IsEnabled        bool                     `json:"is_enabled"`
+	ScheduledDetails *TriggerScheduledDetails `json:"scheduled_details,omitempty"`
+}
+
 // ServerlessTrigger is the form used in list and get responses by the triggers API
 type ServerlessTrigger struct {
 	Namespace        string                   `json:"namespace,omitempty"`
 	Function         string                   `json:"function,omitempty"`
 	Type             string                   `json:"type,omitempty"`
 	Name             string                   `json:"name,omitempty"`
-	IsEnabled        bool                     `json:"is_enabled,omitempty"`
+	IsEnabled        bool                     `json:"is_enabled"`
 	CreatedAt        time.Time                `json:"created_at,omitempty"`
 	UpdatedAt        time.Time                `json:"updated_at,omitempty"`
 	ScheduledDetails *TriggerScheduledDetails `json:"scheduled_details,omitempty"`
@@ -214,6 +219,7 @@ type ServerlessService interface {
 	CleanNamespace() error
 	ListTriggers(context.Context, string) ([]ServerlessTrigger, error)
 	GetTrigger(context.Context, string) (ServerlessTrigger, error)
+	UpdateTrigger(context.Context, string, *UpdateTriggerRequest) (ServerlessTrigger, error)
 	DeleteTrigger(context.Context, string) error
 	WriteCredentials(ServerlessCredentials) error
 	ReadCredentials() (ServerlessCredentials, error)
@@ -1082,6 +1088,32 @@ func (s *serverlessService) GetTrigger(ctx context.Context, name string) (Server
 	return decoded.Trigger, nil
 }
 
+func (s *serverlessService) UpdateTrigger(ctx context.Context, trigger string, opts *UpdateTriggerRequest) (ServerlessTrigger, error) {
+	empty := ServerlessTrigger{}
+	err := s.CheckServerlessStatus()
+	if err != nil {
+		return empty, err
+	}
+	creds, err := s.ReadCredentials()
+	if err != nil {
+		return empty, err
+	}
+
+	path := fmt.Sprintf("v2/functions/namespaces/%s/triggers/%s", creds.Namespace, trigger)
+	req, err := s.client.NewRequest(ctx, http.MethodPut, path, opts)
+
+	if err != nil {
+		return empty, err
+	}
+
+	decoded := new(ServerlessTriggerGetResponse)
+	_, err = s.client.Do(ctx, req, decoded)
+	if err != nil {
+		return empty, err
+	}
+	return decoded.Trigger, nil
+}
+
 // Delete Trigger deletes a trigger from the namespace (used when undeploying triggers explicitly,
 // not part of a more general undeploy; when undeploying a function or the entire namespace we rely
 // on the deployer to delete associated triggers).


Test patch:
diff --git a/commands/triggers_test.go b/commands/triggers_test.go
index 059d6775..bfd1f164 100644
--- a/commands/triggers_test.go
+++ b/commands/triggers_test.go
@@ -28,7 +28,7 @@ import (
 func TestTriggersCommand(t *testing.T) {
 	cmd := Triggers()
 	assert.NotNil(t, cmd)
-	expected := []string{"get", "list"}
+	expected := []string{"get", "list", "enable", "disable"}
 
 	names := []string{}
 	for _, c := range cmd.Commands() {