From cac4b14bec765e75c774074c5d95245ee152260c Mon Sep 17 00:00:00 2001 From: Davi DeBarros Date: Thu, 3 Nov 2022 18:20:05 -0400 Subject: [PATCH 1/4] Adds support for the functions APIs --- godo.go | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/godo.go b/godo.go index c77332c6..1dc38e5e 100644 --- a/godo.go +++ b/godo.go @@ -81,6 +81,7 @@ type Client struct { VPCs VPCsService OneClick OneClickService Monitoring MonitoringService + Functions FunctionsService // Optional function called after every successful request made to the DO APIs onRequestCompleted RequestCompletionCallback @@ -248,7 +249,7 @@ func NewClient(httpClient *http.Client) *Client { c.VPCs = &VPCsServiceOp{client: c} c.OneClick = &OneClickServiceOp{client: c} c.Monitoring = &MonitoringServiceOp{client: c} - + c.Functions = &FunctionsServiceOp{client: c} c.headers = make(map[string]string) return c From 12deb03827e3ccb598be87fb8f5785ddf2c62139 Mon Sep 17 00:00:00 2001 From: Davi DeBarros Date: Thu, 3 Nov 2022 18:20:39 -0400 Subject: [PATCH 2/4] Adds tests --- functions.go | 235 +++++++++++++++++++++++++ functions_test.go | 436 ++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 671 insertions(+) create mode 100644 functions.go create mode 100644 functions_test.go diff --git a/functions.go b/functions.go new file mode 100644 index 00000000..6c146c6c --- /dev/null +++ b/functions.go @@ -0,0 +1,235 @@ +package godo + +import ( + "context" + "fmt" + "net/http" + "time" +) + +const ( + functionsBasePath = "/v2/functions/namespaces" + functionsNamespacePath = functionsBasePath + "/%s" + functionsTriggerBasePath = functionsNamespacePath + "/triggers" +) + +type FunctionsService interface { + Namespaces(context.Context) ([]FunctionsNamespace, *Response, error) + Namespace(context.Context, string) (*FunctionsNamespace, *Response, error) + CreateNamespace(context.Context, *FunctionsNamespaceCreateOptions) (*FunctionsNamespace, *Response, error) + DeleteNamespace(context.Context, string) (*Response, error) + + Triggers(context.Context, string) ([]FunctionsTrigger, *Response, error) + Trigger(context.Context, string, string) (*FunctionsTrigger, *Response, error) + CreateTrigger(context.Context, string, *FunctionsTriggerCreateOptions) (*FunctionsTrigger, *Response, error) + UpdateTrigger(context.Context, string, string, *FunctionsTriggerUpdateOptions) (*FunctionsTrigger, *Response, error) + DeleteTrigger(context.Context, string, string) (*Response, error) +} + +type FunctionsServiceOp struct { + client *Client +} + +var _ FunctionsService = &FunctionsServiceOp{} + +type namespacesRoot struct { + Namespaces []FunctionsNamespace `json:"namespaces,omitempty"` +} + +type namespaceRoot struct { + Namespace *FunctionsNamespace `json:"namespace,omitempty"` +} + +type FunctionsNamespace struct { + ApiHost string `json:"api_host,omitempty"` + Namespace string `json:"namespace,omitempty"` + CreatedAt time.Time `json:"created_at,omitempty"` + UpdatedAt time.Time `json:"updated_at,omitempty"` + Label string `json:"label,omitempty"` + Region string `json:"region,omitempty"` + UUID string `json:"uuid,omitempty"` + Key string `json:"key,omitempty"` +} + +type FunctionsNamespaceCreateOptions struct { + Label string `json:"label"` + Region string `json:"region"` +} + +type triggersRoot struct { + Triggers []FunctionsTrigger `json:"triggers,omitempty"` +} + +type triggerRoot struct { + Trigger *FunctionsTrigger `json:"trigger,omitempty"` +} + +type FunctionsTrigger 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"` + CreatedAt time.Time `json:"created_at,omitempty"` + UpdatedAt time.Time `json:"updated_at,omitempty"` + ScheduledDetails *TriggerScheduledDetails `json:"scheduled_details,omitempty"` + ScheduledRuns *TriggerScheduledRuns `json:"scheduled_runs,omitempty"` +} + +type TriggerScheduledDetails struct { + Cron string `json:"cron,omitempty"` + Body map[string]interface{} `json:"body,omitempty"` +} + +type TriggerScheduledRuns struct { + LastRunAt time.Time `json:"last_run_at,omitempty"` + NextRunAt time.Time `json:"next_run_at,omitempty"` +} + +type FunctionsTriggerCreateOptions struct { + Name string `json:"name"` + Type string `json:"type"` + Function string `json:"function"` + IsEnabled bool `json:"is_enabled,omitempty"` + ScheduledDetails *TriggerScheduledDetails `json:"scheduled_details,omitempty"` +} + +type FunctionsTriggerUpdateOptions struct { + IsEnabled bool `json:"is_enabled,omitempty"` + ScheduledDetails *TriggerScheduledDetails `json:"scheduled_details,omitempty"` +} + +// Gets a list of namespaces +func (s *FunctionsServiceOp) Namespaces(ctx context.Context) ([]FunctionsNamespace, *Response, error) { + req, err := s.client.NewRequest(ctx, http.MethodGet, functionsBasePath, nil) + if err != nil { + return nil, nil, err + } + nsRoot := new(namespacesRoot) + resp, err := s.client.Do(ctx, req, nsRoot) + if err != nil { + return nil, resp, err + } + return nsRoot.Namespaces, resp, nil +} + +// Gets a single namespace +func (s *FunctionsServiceOp) Namespace(ctx context.Context, namespace string) (*FunctionsNamespace, *Response, error) { + path := fmt.Sprintf(functionsNamespacePath, namespace) + + req, err := s.client.NewRequest(ctx, http.MethodGet, path, nil) + if err != nil { + return nil, nil, err + } + nsRoot := new(namespaceRoot) + resp, err := s.client.Do(ctx, req, nsRoot) + if err != nil { + return nil, resp, err + } + return nsRoot.Namespace, resp, nil +} + +// Creates a namespace +func (s *FunctionsServiceOp) CreateNamespace(ctx context.Context, opts *FunctionsNamespaceCreateOptions) (*FunctionsNamespace, *Response, error) { + req, err := s.client.NewRequest(ctx, http.MethodPost, functionsBasePath, opts) + if err != nil { + return nil, nil, err + } + nsRoot := new(namespaceRoot) + resp, err := s.client.Do(ctx, req, nsRoot) + if err != nil { + return nil, resp, err + } + return nsRoot.Namespace, resp, nil +} + +// Delete a namespace +func (s *FunctionsServiceOp) DeleteNamespace(ctx context.Context, namespace string) (*Response, error) { + path := fmt.Sprintf(functionsNamespacePath, namespace) + + req, err := s.client.NewRequest(ctx, http.MethodDelete, path, nil) + if err != nil { + return nil, err + } + + resp, err := s.client.Do(ctx, req, nil) + if err != nil { + return resp, err + } + return resp, nil +} + +// Gets a list of triggers +func (s *FunctionsServiceOp) Triggers(ctx context.Context, namespace string) ([]FunctionsTrigger, *Response, error) { + path := fmt.Sprintf(functionsTriggerBasePath, namespace) + req, err := s.client.NewRequest(ctx, http.MethodGet, path, nil) + if err != nil { + return nil, nil, err + } + root := new(triggersRoot) + resp, err := s.client.Do(ctx, req, root) + if err != nil { + return nil, resp, err + } + return root.Triggers, resp, nil +} + +// Gets a single trigger +func (s *FunctionsServiceOp) Trigger(ctx context.Context, namespace string, trigger string) (*FunctionsTrigger, *Response, error) { + path := fmt.Sprintf(functionsTriggerBasePath+"/%s", namespace, trigger) + req, err := s.client.NewRequest(ctx, http.MethodGet, path, nil) + if err != nil { + return nil, nil, err + } + root := new(triggerRoot) + resp, err := s.client.Do(ctx, req, root) + if err != nil { + return nil, resp, err + } + return root.Trigger, resp, nil +} + +// Creates a trigger +func (s *FunctionsServiceOp) CreateTrigger(ctx context.Context, namespace string, opts *FunctionsTriggerCreateOptions) (*FunctionsTrigger, *Response, error) { + path := fmt.Sprintf(functionsTriggerBasePath, namespace) + req, err := s.client.NewRequest(ctx, http.MethodPost, path, opts) + if err != nil { + return nil, nil, err + } + root := new(triggerRoot) + resp, err := s.client.Do(ctx, req, root) + if err != nil { + return nil, resp, err + } + return root.Trigger, resp, nil +} + +// Update a trigger +func (s *FunctionsServiceOp) UpdateTrigger(ctx context.Context, namespace string, trigger string, opts *FunctionsTriggerUpdateOptions) (*FunctionsTrigger, *Response, error) { + path := fmt.Sprintf(functionsTriggerBasePath+"/%s", namespace, trigger) + req, err := s.client.NewRequest(ctx, http.MethodPut, path, opts) + if err != nil { + return nil, nil, err + } + root := new(triggerRoot) + resp, err := s.client.Do(ctx, req, root) + if err != nil { + return nil, resp, err + } + return root.Trigger, resp, nil +} + +// Delete a trigger +func (s *FunctionsServiceOp) DeleteTrigger(ctx context.Context, namespace string, trigger string) (*Response, error) { + path := fmt.Sprintf(functionsTriggerBasePath+"/%s", namespace, trigger) + req, err := s.client.NewRequest(ctx, http.MethodDelete, path, nil) + if err != nil { + return nil, err + } + + resp, err := s.client.Do(ctx, req, nil) + if err != nil { + return resp, err + } + return resp, nil +} diff --git a/functions_test.go b/functions_test.go new file mode 100644 index 00000000..b7a29fbc --- /dev/null +++ b/functions_test.go @@ -0,0 +1,436 @@ +package godo + +import ( + "fmt" + "net/http" + "testing" + "time" + + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" +) + +func TestFunctions_ListNamespaces(t *testing.T) { + setup() + defer teardown() + + mux.HandleFunc("/v2/functions/namespaces", func(w http.ResponseWriter, r *http.Request) { + testMethod(t, r, http.MethodGet) + fmt.Fprint(w, `{ + "namespaces": [ + { + "api_host": "https://faas.do.com", + "namespace": "123-abc", + "created_at": "2022-06-16T12:09:13Z", + "updated_at": "2022-06-16T12:09:13Z", + "label": "my-namespace-1", + "region": "nyc1", + "uuid": "", + "key": "" + }, + { + "api_host": "https://faas.do.com", + "namespace": "456-abc", + "created_at": "2022-11-02T18:33:44Z", + "updated_at": "2022-11-02T18:33:44Z", + "label": "my-namespace-2", + "region": "nyc3", + "uuid": "", + "key": "" + } + ] + }`) + }) + + namespaces, _, err := client.Functions.Namespaces(ctx) + require.NoError(t, err) + + expectedNamespaces := []FunctionsNamespace{ + { + ApiHost: "https://faas.do.com", + Namespace: "123-abc", + CreatedAt: time.Date(2022, 6, 16, 12, 9, 13, 0, time.UTC), + UpdatedAt: time.Date(2022, 6, 16, 12, 9, 13, 0, time.UTC), + Label: "my-namespace-1", + Region: "nyc1", + UUID: "", + Key: "", + }, + { + ApiHost: "https://faas.do.com", + Namespace: "456-abc", + CreatedAt: time.Date(2022, 11, 2, 18, 33, 44, 0, time.UTC), + UpdatedAt: time.Date(2022, 11, 2, 18, 33, 44, 0, time.UTC), + Label: "my-namespace-2", + Region: "nyc3", + UUID: "", + Key: "", + }, + } + assert.Equal(t, expectedNamespaces, namespaces) +} + +func TestFunctions_GetNamespace(t *testing.T) { + setup() + defer teardown() + + mux.HandleFunc("/v2/functions/namespaces/123-abc", func(w http.ResponseWriter, r *http.Request) { + testMethod(t, r, http.MethodGet) + fmt.Fprint(w, `{ + "namespace": { + "api_host": "https://faas.do.com", + "namespace": "123-abc", + "created_at": "2022-06-16T12:09:13Z", + "updated_at": "2022-06-16T12:09:13Z", + "label": "my-namespace-1", + "region": "nyc1", + "uuid": "123-456", + "key": "abc-123" + } + }`) + }) + + namespace, _, err := client.Functions.Namespace(ctx, "123-abc") + require.NoError(t, err) + + expectedNamespace := &FunctionsNamespace{ + ApiHost: "https://faas.do.com", + Namespace: "123-abc", + CreatedAt: time.Date(2022, 6, 16, 12, 9, 13, 0, time.UTC), + UpdatedAt: time.Date(2022, 6, 16, 12, 9, 13, 0, time.UTC), + Label: "my-namespace-1", + Region: "nyc1", + UUID: "123-456", + Key: "abc-123", + } + assert.Equal(t, expectedNamespace, namespace) +} + +func TestFunctions_CreateNamespace(t *testing.T) { + setup() + defer teardown() + + mux.HandleFunc("/v2/functions/namespaces", func(w http.ResponseWriter, r *http.Request) { + testMethod(t, r, http.MethodPost) + fmt.Fprint(w, `{ + "namespace": { + "api_host": "https://faas.do.com", + "namespace": "123-abc", + "created_at": "2022-06-16T12:09:13Z", + "updated_at": "2022-06-16T12:09:13Z", + "label": "my-namespace-1", + "region": "nyc1", + "uuid": "123-456", + "key": "abc-123" + } + }`) + }) + + opts := FunctionsNamespaceCreateOptions{Label: "my-namespace-1", Region: "nyc1"} + namespace, _, err := client.Functions.CreateNamespace(ctx, &opts) + require.NoError(t, err) + + expectedNamespace := &FunctionsNamespace{ + ApiHost: "https://faas.do.com", + Namespace: "123-abc", + CreatedAt: time.Date(2022, 6, 16, 12, 9, 13, 0, time.UTC), + UpdatedAt: time.Date(2022, 6, 16, 12, 9, 13, 0, time.UTC), + Label: "my-namespace-1", + Region: "nyc1", + UUID: "123-456", + Key: "abc-123", + } + assert.Equal(t, expectedNamespace, namespace) +} + +func TestFunctions_DeleteNamespace(t *testing.T) { + setup() + defer teardown() + + mux.HandleFunc("/v2/functions/namespaces/123-abc", func(w http.ResponseWriter, r *http.Request) { + testMethod(t, r, http.MethodDelete) + }) + + _, err := client.Functions.DeleteNamespace(ctx, "123-abc") + + assert.NoError(t, err) +} + +func TestFunctions_ListTriggers(t *testing.T) { + setup() + defer teardown() + + mux.HandleFunc("/v2/functions/namespaces/123-456/triggers", func(w http.ResponseWriter, r *http.Request) { + testMethod(t, r, http.MethodGet) + fmt.Fprint(w, `{ + "triggers": [ + { + "name": "trigger", + "namespace": "123-456", + "function": "my_func", + "type": "SCHEDULED", + "is_enabled": true, + "created_at": "2022-10-05T13:46:59Z", + "updated_at": "2022-10-17T18:41:30Z", + "scheduled_details": { + "cron": "* * * * *", + "body": { + "foo": "bar" + } + }, + "scheduled_runs": { + "next_run_at": "2022-11-03T17:03:02Z" + } + }, + { + "name": "trigger1", + "namespace": "123-456", + "function": "sample/hello", + "type": "SCHEDULED", + "is_enabled": true, + "created_at": "2022-10-14T20:29:43Z", + "updated_at": "2022-10-14T20:29:43Z", + "scheduled_details": { + "cron": "* * * * *", + "body": {} + }, + "scheduled_runs": { + "last_run_at": "2022-11-03T17:02:43Z", + "next_run_at": "2022-11-03T17:02:47Z" + } + } + ] + }`) + }) + + triggers, _, err := client.Functions.Triggers(ctx, "123-456") + require.NoError(t, err) + + expectedTriggers := []FunctionsTrigger{ + { + Name: "trigger", + Namespace: "123-456", + Function: "my_func", + Type: "SCHEDULED", + IsEnabled: true, + CreatedAt: time.Date(2022, 10, 5, 13, 46, 59, 0, time.UTC), + UpdatedAt: time.Date(2022, 10, 17, 18, 41, 30, 0, time.UTC), + ScheduledDetails: &TriggerScheduledDetails{ + Cron: "* * * * *", + Body: map[string]interface{}{ + "foo": "bar", + }, + }, + ScheduledRuns: &TriggerScheduledRuns{ + NextRunAt: time.Date(2022, 11, 3, 17, 3, 2, 0, time.UTC), + }, + }, + { + Name: "trigger1", + Namespace: "123-456", + Function: "sample/hello", + Type: "SCHEDULED", + IsEnabled: true, + CreatedAt: time.Date(2022, 10, 14, 20, 29, 43, 0, time.UTC), + UpdatedAt: time.Date(2022, 10, 14, 20, 29, 43, 0, time.UTC), + ScheduledDetails: &TriggerScheduledDetails{ + Cron: "* * * * *", + Body: map[string]interface{}{}, + }, + ScheduledRuns: &TriggerScheduledRuns{ + LastRunAt: time.Date(2022, 11, 03, 17, 02, 43, 0, time.UTC), + NextRunAt: time.Date(2022, 11, 03, 17, 02, 47, 0, time.UTC), + }, + }, + } + assert.Equal(t, expectedTriggers, triggers) +} + +func TestFunctions_GetTrigger(t *testing.T) { + setup() + defer teardown() + + mux.HandleFunc("/v2/functions/namespaces/123-456/triggers/my-trigger", func(w http.ResponseWriter, r *http.Request) { + testMethod(t, r, http.MethodGet) + fmt.Fprint(w, `{ + "trigger": { + "name": "my-trigger", + "namespace": "123-456", + "function": "my_func", + "type": "SCHEDULED", + "is_enabled": true, + "created_at": "2022-10-05T13:46:59Z", + "updated_at": "2022-10-17T18:41:30Z", + "scheduled_details": { + "cron": "* * * * *", + "body": { + "foo": "bar" + } + }, + "scheduled_runs": { + "next_run_at": "2022-11-03T17:03:02Z" + } + } + }`) + }) + + trigger, _, err := client.Functions.Trigger(ctx, "123-456", "my-trigger") + require.NoError(t, err) + + expectedTrigger := &FunctionsTrigger{ + Name: "my-trigger", + Namespace: "123-456", + Function: "my_func", + Type: "SCHEDULED", + IsEnabled: true, + CreatedAt: time.Date(2022, 10, 5, 13, 46, 59, 0, time.UTC), + UpdatedAt: time.Date(2022, 10, 17, 18, 41, 30, 0, time.UTC), + ScheduledDetails: &TriggerScheduledDetails{ + Cron: "* * * * *", + Body: map[string]interface{}{ + "foo": "bar", + }, + }, + ScheduledRuns: &TriggerScheduledRuns{ + NextRunAt: time.Date(2022, 11, 3, 17, 3, 2, 0, time.UTC), + }, + } + + assert.Equal(t, expectedTrigger, trigger) +} + +func TestFunctions_CreateTrigger(t *testing.T) { + setup() + defer teardown() + + mux.HandleFunc("/v2/functions/namespaces/123-456/triggers", func(w http.ResponseWriter, r *http.Request) { + testMethod(t, r, http.MethodPost) + fmt.Fprint(w, `{ + "trigger": { + "name": "my-new-trigger", + "namespace": "123-456", + "function": "my_func", + "type": "SCHEDULED", + "is_enabled": true, + "created_at": "2022-10-05T13:46:59Z", + "updated_at": "2022-10-17T18:41:30Z", + "scheduled_details": { + "cron": "* * * * *", + "body": { + "foo": "bar" + } + }, + "scheduled_runs": { + "next_run_at": "2022-11-03T17:03:02Z" + } + } + }`) + }) + + opts := FunctionsTriggerCreateOptions{ + Name: "my-new-trigger", + Function: "my_func", + Type: "SCHEDULED", + IsEnabled: true, + ScheduledDetails: &TriggerScheduledDetails{ + Cron: "* * * * *", + Body: map[string]interface{}{ + "foo": "bar", + }, + }, + } + + trigger, _, err := client.Functions.CreateTrigger(ctx, "123-456", &opts) + require.NoError(t, err) + + expectedTrigger := &FunctionsTrigger{ + Name: "my-new-trigger", + Namespace: "123-456", + Function: "my_func", + Type: "SCHEDULED", + IsEnabled: true, + CreatedAt: time.Date(2022, 10, 5, 13, 46, 59, 0, time.UTC), + UpdatedAt: time.Date(2022, 10, 17, 18, 41, 30, 0, time.UTC), + ScheduledDetails: &TriggerScheduledDetails{ + Cron: "* * * * *", + Body: map[string]interface{}{ + "foo": "bar", + }, + }, + ScheduledRuns: &TriggerScheduledRuns{ + NextRunAt: time.Date(2022, 11, 3, 17, 3, 2, 0, time.UTC), + }, + } + + assert.Equal(t, expectedTrigger, trigger) +} + +func TestFunctions_UpdateTrigger(t *testing.T) { + setup() + defer teardown() + + mux.HandleFunc("/v2/functions/namespaces/123-456/triggers/my-trigger", func(w http.ResponseWriter, r *http.Request) { + testMethod(t, r, http.MethodPut) + fmt.Fprint(w, `{ + "trigger": { + "name": "my-trigger", + "namespace": "123-456", + "function": "my_func", + "type": "SCHEDULED", + "is_enabled": false, + "created_at": "2022-10-05T13:46:59Z", + "updated_at": "2022-10-17T18:41:30Z", + "scheduled_details": { + "cron": "* * * * *", + "body": { + "foo": "bar" + } + }, + "scheduled_runs": { + "next_run_at": "2022-11-03T17:03:02Z" + } + } + }`) + }) + + opts := FunctionsTriggerUpdateOptions{ + IsEnabled: false, + } + + trigger, _, err := client.Functions.UpdateTrigger(ctx, "123-456", "my-trigger", &opts) + require.NoError(t, err) + + expectedTrigger := &FunctionsTrigger{ + Name: "my-trigger", + Namespace: "123-456", + Function: "my_func", + Type: "SCHEDULED", + IsEnabled: false, + CreatedAt: time.Date(2022, 10, 5, 13, 46, 59, 0, time.UTC), + UpdatedAt: time.Date(2022, 10, 17, 18, 41, 30, 0, time.UTC), + ScheduledDetails: &TriggerScheduledDetails{ + Cron: "* * * * *", + Body: map[string]interface{}{ + "foo": "bar", + }, + }, + ScheduledRuns: &TriggerScheduledRuns{ + NextRunAt: time.Date(2022, 11, 3, 17, 3, 2, 0, time.UTC), + }, + } + + assert.Equal(t, expectedTrigger, trigger) +} + +func TestFunctions_DeleteTrigger(t *testing.T) { + setup() + defer teardown() + + mux.HandleFunc("/v2/functions/namespaces/123-abc/triggers/my-trigger", func(w http.ResponseWriter, r *http.Request) { + testMethod(t, r, http.MethodDelete) + }) + + _, err := client.Functions.DeleteTrigger(ctx, "123-abc", "my-trigger") + + assert.NoError(t, err) +} From ccb159589798711f420fa1eacdde3aac2b8ad1a7 Mon Sep 17 00:00:00 2001 From: Davi DeBarros Date: Fri, 4 Nov 2022 14:59:25 -0400 Subject: [PATCH 3/4] Removes reference to trigger API --- functions.go | 129 +-------------------- functions_test.go | 279 ---------------------------------------------- 2 files changed, 2 insertions(+), 406 deletions(-) diff --git a/functions.go b/functions.go index 6c146c6c..26bbaa07 100644 --- a/functions.go +++ b/functions.go @@ -8,9 +8,8 @@ import ( ) const ( - functionsBasePath = "/v2/functions/namespaces" - functionsNamespacePath = functionsBasePath + "/%s" - functionsTriggerBasePath = functionsNamespacePath + "/triggers" + functionsBasePath = "/v2/functions/namespaces" + functionsNamespacePath = functionsBasePath + "/%s" ) type FunctionsService interface { @@ -18,12 +17,6 @@ type FunctionsService interface { Namespace(context.Context, string) (*FunctionsNamespace, *Response, error) CreateNamespace(context.Context, *FunctionsNamespaceCreateOptions) (*FunctionsNamespace, *Response, error) DeleteNamespace(context.Context, string) (*Response, error) - - Triggers(context.Context, string) ([]FunctionsTrigger, *Response, error) - Trigger(context.Context, string, string) (*FunctionsTrigger, *Response, error) - CreateTrigger(context.Context, string, *FunctionsTriggerCreateOptions) (*FunctionsTrigger, *Response, error) - UpdateTrigger(context.Context, string, string, *FunctionsTriggerUpdateOptions) (*FunctionsTrigger, *Response, error) - DeleteTrigger(context.Context, string, string) (*Response, error) } type FunctionsServiceOp struct { @@ -56,49 +49,6 @@ type FunctionsNamespaceCreateOptions struct { Region string `json:"region"` } -type triggersRoot struct { - Triggers []FunctionsTrigger `json:"triggers,omitempty"` -} - -type triggerRoot struct { - Trigger *FunctionsTrigger `json:"trigger,omitempty"` -} - -type FunctionsTrigger 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"` - CreatedAt time.Time `json:"created_at,omitempty"` - UpdatedAt time.Time `json:"updated_at,omitempty"` - ScheduledDetails *TriggerScheduledDetails `json:"scheduled_details,omitempty"` - ScheduledRuns *TriggerScheduledRuns `json:"scheduled_runs,omitempty"` -} - -type TriggerScheduledDetails struct { - Cron string `json:"cron,omitempty"` - Body map[string]interface{} `json:"body,omitempty"` -} - -type TriggerScheduledRuns struct { - LastRunAt time.Time `json:"last_run_at,omitempty"` - NextRunAt time.Time `json:"next_run_at,omitempty"` -} - -type FunctionsTriggerCreateOptions struct { - Name string `json:"name"` - Type string `json:"type"` - Function string `json:"function"` - IsEnabled bool `json:"is_enabled,omitempty"` - ScheduledDetails *TriggerScheduledDetails `json:"scheduled_details,omitempty"` -} - -type FunctionsTriggerUpdateOptions struct { - IsEnabled bool `json:"is_enabled,omitempty"` - ScheduledDetails *TriggerScheduledDetails `json:"scheduled_details,omitempty"` -} - // Gets a list of namespaces func (s *FunctionsServiceOp) Namespaces(ctx context.Context) ([]FunctionsNamespace, *Response, error) { req, err := s.client.NewRequest(ctx, http.MethodGet, functionsBasePath, nil) @@ -158,78 +108,3 @@ func (s *FunctionsServiceOp) DeleteNamespace(ctx context.Context, namespace stri } return resp, nil } - -// Gets a list of triggers -func (s *FunctionsServiceOp) Triggers(ctx context.Context, namespace string) ([]FunctionsTrigger, *Response, error) { - path := fmt.Sprintf(functionsTriggerBasePath, namespace) - req, err := s.client.NewRequest(ctx, http.MethodGet, path, nil) - if err != nil { - return nil, nil, err - } - root := new(triggersRoot) - resp, err := s.client.Do(ctx, req, root) - if err != nil { - return nil, resp, err - } - return root.Triggers, resp, nil -} - -// Gets a single trigger -func (s *FunctionsServiceOp) Trigger(ctx context.Context, namespace string, trigger string) (*FunctionsTrigger, *Response, error) { - path := fmt.Sprintf(functionsTriggerBasePath+"/%s", namespace, trigger) - req, err := s.client.NewRequest(ctx, http.MethodGet, path, nil) - if err != nil { - return nil, nil, err - } - root := new(triggerRoot) - resp, err := s.client.Do(ctx, req, root) - if err != nil { - return nil, resp, err - } - return root.Trigger, resp, nil -} - -// Creates a trigger -func (s *FunctionsServiceOp) CreateTrigger(ctx context.Context, namespace string, opts *FunctionsTriggerCreateOptions) (*FunctionsTrigger, *Response, error) { - path := fmt.Sprintf(functionsTriggerBasePath, namespace) - req, err := s.client.NewRequest(ctx, http.MethodPost, path, opts) - if err != nil { - return nil, nil, err - } - root := new(triggerRoot) - resp, err := s.client.Do(ctx, req, root) - if err != nil { - return nil, resp, err - } - return root.Trigger, resp, nil -} - -// Update a trigger -func (s *FunctionsServiceOp) UpdateTrigger(ctx context.Context, namespace string, trigger string, opts *FunctionsTriggerUpdateOptions) (*FunctionsTrigger, *Response, error) { - path := fmt.Sprintf(functionsTriggerBasePath+"/%s", namespace, trigger) - req, err := s.client.NewRequest(ctx, http.MethodPut, path, opts) - if err != nil { - return nil, nil, err - } - root := new(triggerRoot) - resp, err := s.client.Do(ctx, req, root) - if err != nil { - return nil, resp, err - } - return root.Trigger, resp, nil -} - -// Delete a trigger -func (s *FunctionsServiceOp) DeleteTrigger(ctx context.Context, namespace string, trigger string) (*Response, error) { - path := fmt.Sprintf(functionsTriggerBasePath+"/%s", namespace, trigger) - req, err := s.client.NewRequest(ctx, http.MethodDelete, path, nil) - if err != nil { - return nil, err - } - - resp, err := s.client.Do(ctx, req, nil) - if err != nil { - return resp, err - } - return resp, nil -} diff --git a/functions_test.go b/functions_test.go index b7a29fbc..e9967148 100644 --- a/functions_test.go +++ b/functions_test.go @@ -155,282 +155,3 @@ func TestFunctions_DeleteNamespace(t *testing.T) { assert.NoError(t, err) } - -func TestFunctions_ListTriggers(t *testing.T) { - setup() - defer teardown() - - mux.HandleFunc("/v2/functions/namespaces/123-456/triggers", func(w http.ResponseWriter, r *http.Request) { - testMethod(t, r, http.MethodGet) - fmt.Fprint(w, `{ - "triggers": [ - { - "name": "trigger", - "namespace": "123-456", - "function": "my_func", - "type": "SCHEDULED", - "is_enabled": true, - "created_at": "2022-10-05T13:46:59Z", - "updated_at": "2022-10-17T18:41:30Z", - "scheduled_details": { - "cron": "* * * * *", - "body": { - "foo": "bar" - } - }, - "scheduled_runs": { - "next_run_at": "2022-11-03T17:03:02Z" - } - }, - { - "name": "trigger1", - "namespace": "123-456", - "function": "sample/hello", - "type": "SCHEDULED", - "is_enabled": true, - "created_at": "2022-10-14T20:29:43Z", - "updated_at": "2022-10-14T20:29:43Z", - "scheduled_details": { - "cron": "* * * * *", - "body": {} - }, - "scheduled_runs": { - "last_run_at": "2022-11-03T17:02:43Z", - "next_run_at": "2022-11-03T17:02:47Z" - } - } - ] - }`) - }) - - triggers, _, err := client.Functions.Triggers(ctx, "123-456") - require.NoError(t, err) - - expectedTriggers := []FunctionsTrigger{ - { - Name: "trigger", - Namespace: "123-456", - Function: "my_func", - Type: "SCHEDULED", - IsEnabled: true, - CreatedAt: time.Date(2022, 10, 5, 13, 46, 59, 0, time.UTC), - UpdatedAt: time.Date(2022, 10, 17, 18, 41, 30, 0, time.UTC), - ScheduledDetails: &TriggerScheduledDetails{ - Cron: "* * * * *", - Body: map[string]interface{}{ - "foo": "bar", - }, - }, - ScheduledRuns: &TriggerScheduledRuns{ - NextRunAt: time.Date(2022, 11, 3, 17, 3, 2, 0, time.UTC), - }, - }, - { - Name: "trigger1", - Namespace: "123-456", - Function: "sample/hello", - Type: "SCHEDULED", - IsEnabled: true, - CreatedAt: time.Date(2022, 10, 14, 20, 29, 43, 0, time.UTC), - UpdatedAt: time.Date(2022, 10, 14, 20, 29, 43, 0, time.UTC), - ScheduledDetails: &TriggerScheduledDetails{ - Cron: "* * * * *", - Body: map[string]interface{}{}, - }, - ScheduledRuns: &TriggerScheduledRuns{ - LastRunAt: time.Date(2022, 11, 03, 17, 02, 43, 0, time.UTC), - NextRunAt: time.Date(2022, 11, 03, 17, 02, 47, 0, time.UTC), - }, - }, - } - assert.Equal(t, expectedTriggers, triggers) -} - -func TestFunctions_GetTrigger(t *testing.T) { - setup() - defer teardown() - - mux.HandleFunc("/v2/functions/namespaces/123-456/triggers/my-trigger", func(w http.ResponseWriter, r *http.Request) { - testMethod(t, r, http.MethodGet) - fmt.Fprint(w, `{ - "trigger": { - "name": "my-trigger", - "namespace": "123-456", - "function": "my_func", - "type": "SCHEDULED", - "is_enabled": true, - "created_at": "2022-10-05T13:46:59Z", - "updated_at": "2022-10-17T18:41:30Z", - "scheduled_details": { - "cron": "* * * * *", - "body": { - "foo": "bar" - } - }, - "scheduled_runs": { - "next_run_at": "2022-11-03T17:03:02Z" - } - } - }`) - }) - - trigger, _, err := client.Functions.Trigger(ctx, "123-456", "my-trigger") - require.NoError(t, err) - - expectedTrigger := &FunctionsTrigger{ - Name: "my-trigger", - Namespace: "123-456", - Function: "my_func", - Type: "SCHEDULED", - IsEnabled: true, - CreatedAt: time.Date(2022, 10, 5, 13, 46, 59, 0, time.UTC), - UpdatedAt: time.Date(2022, 10, 17, 18, 41, 30, 0, time.UTC), - ScheduledDetails: &TriggerScheduledDetails{ - Cron: "* * * * *", - Body: map[string]interface{}{ - "foo": "bar", - }, - }, - ScheduledRuns: &TriggerScheduledRuns{ - NextRunAt: time.Date(2022, 11, 3, 17, 3, 2, 0, time.UTC), - }, - } - - assert.Equal(t, expectedTrigger, trigger) -} - -func TestFunctions_CreateTrigger(t *testing.T) { - setup() - defer teardown() - - mux.HandleFunc("/v2/functions/namespaces/123-456/triggers", func(w http.ResponseWriter, r *http.Request) { - testMethod(t, r, http.MethodPost) - fmt.Fprint(w, `{ - "trigger": { - "name": "my-new-trigger", - "namespace": "123-456", - "function": "my_func", - "type": "SCHEDULED", - "is_enabled": true, - "created_at": "2022-10-05T13:46:59Z", - "updated_at": "2022-10-17T18:41:30Z", - "scheduled_details": { - "cron": "* * * * *", - "body": { - "foo": "bar" - } - }, - "scheduled_runs": { - "next_run_at": "2022-11-03T17:03:02Z" - } - } - }`) - }) - - opts := FunctionsTriggerCreateOptions{ - Name: "my-new-trigger", - Function: "my_func", - Type: "SCHEDULED", - IsEnabled: true, - ScheduledDetails: &TriggerScheduledDetails{ - Cron: "* * * * *", - Body: map[string]interface{}{ - "foo": "bar", - }, - }, - } - - trigger, _, err := client.Functions.CreateTrigger(ctx, "123-456", &opts) - require.NoError(t, err) - - expectedTrigger := &FunctionsTrigger{ - Name: "my-new-trigger", - Namespace: "123-456", - Function: "my_func", - Type: "SCHEDULED", - IsEnabled: true, - CreatedAt: time.Date(2022, 10, 5, 13, 46, 59, 0, time.UTC), - UpdatedAt: time.Date(2022, 10, 17, 18, 41, 30, 0, time.UTC), - ScheduledDetails: &TriggerScheduledDetails{ - Cron: "* * * * *", - Body: map[string]interface{}{ - "foo": "bar", - }, - }, - ScheduledRuns: &TriggerScheduledRuns{ - NextRunAt: time.Date(2022, 11, 3, 17, 3, 2, 0, time.UTC), - }, - } - - assert.Equal(t, expectedTrigger, trigger) -} - -func TestFunctions_UpdateTrigger(t *testing.T) { - setup() - defer teardown() - - mux.HandleFunc("/v2/functions/namespaces/123-456/triggers/my-trigger", func(w http.ResponseWriter, r *http.Request) { - testMethod(t, r, http.MethodPut) - fmt.Fprint(w, `{ - "trigger": { - "name": "my-trigger", - "namespace": "123-456", - "function": "my_func", - "type": "SCHEDULED", - "is_enabled": false, - "created_at": "2022-10-05T13:46:59Z", - "updated_at": "2022-10-17T18:41:30Z", - "scheduled_details": { - "cron": "* * * * *", - "body": { - "foo": "bar" - } - }, - "scheduled_runs": { - "next_run_at": "2022-11-03T17:03:02Z" - } - } - }`) - }) - - opts := FunctionsTriggerUpdateOptions{ - IsEnabled: false, - } - - trigger, _, err := client.Functions.UpdateTrigger(ctx, "123-456", "my-trigger", &opts) - require.NoError(t, err) - - expectedTrigger := &FunctionsTrigger{ - Name: "my-trigger", - Namespace: "123-456", - Function: "my_func", - Type: "SCHEDULED", - IsEnabled: false, - CreatedAt: time.Date(2022, 10, 5, 13, 46, 59, 0, time.UTC), - UpdatedAt: time.Date(2022, 10, 17, 18, 41, 30, 0, time.UTC), - ScheduledDetails: &TriggerScheduledDetails{ - Cron: "* * * * *", - Body: map[string]interface{}{ - "foo": "bar", - }, - }, - ScheduledRuns: &TriggerScheduledRuns{ - NextRunAt: time.Date(2022, 11, 3, 17, 3, 2, 0, time.UTC), - }, - } - - assert.Equal(t, expectedTrigger, trigger) -} - -func TestFunctions_DeleteTrigger(t *testing.T) { - setup() - defer teardown() - - mux.HandleFunc("/v2/functions/namespaces/123-abc/triggers/my-trigger", func(w http.ResponseWriter, r *http.Request) { - testMethod(t, r, http.MethodDelete) - }) - - _, err := client.Functions.DeleteTrigger(ctx, "123-abc", "my-trigger") - - assert.NoError(t, err) -} From 75e9c1b4d9a34785b6714d36d59a9a5047235b62 Mon Sep 17 00:00:00 2001 From: Davi DeBarros Date: Mon, 7 Nov 2022 14:22:34 -0500 Subject: [PATCH 4/4] updates from PR suggestion --- functions.go | 14 +++++++------- functions_test.go | 6 +++--- 2 files changed, 10 insertions(+), 10 deletions(-) diff --git a/functions.go b/functions.go index 26bbaa07..b3829367 100644 --- a/functions.go +++ b/functions.go @@ -13,9 +13,9 @@ const ( ) type FunctionsService interface { - Namespaces(context.Context) ([]FunctionsNamespace, *Response, error) - Namespace(context.Context, string) (*FunctionsNamespace, *Response, error) - CreateNamespace(context.Context, *FunctionsNamespaceCreateOptions) (*FunctionsNamespace, *Response, error) + ListNamespaces(context.Context) ([]FunctionsNamespace, *Response, error) + GetNamespace(context.Context, string) (*FunctionsNamespace, *Response, error) + CreateNamespace(context.Context, *FunctionsNamespaceCreateRequest) (*FunctionsNamespace, *Response, error) DeleteNamespace(context.Context, string) (*Response, error) } @@ -44,13 +44,13 @@ type FunctionsNamespace struct { Key string `json:"key,omitempty"` } -type FunctionsNamespaceCreateOptions struct { +type FunctionsNamespaceCreateRequest struct { Label string `json:"label"` Region string `json:"region"` } // Gets a list of namespaces -func (s *FunctionsServiceOp) Namespaces(ctx context.Context) ([]FunctionsNamespace, *Response, error) { +func (s *FunctionsServiceOp) ListNamespaces(ctx context.Context) ([]FunctionsNamespace, *Response, error) { req, err := s.client.NewRequest(ctx, http.MethodGet, functionsBasePath, nil) if err != nil { return nil, nil, err @@ -64,7 +64,7 @@ func (s *FunctionsServiceOp) Namespaces(ctx context.Context) ([]FunctionsNamespa } // Gets a single namespace -func (s *FunctionsServiceOp) Namespace(ctx context.Context, namespace string) (*FunctionsNamespace, *Response, error) { +func (s *FunctionsServiceOp) GetNamespace(ctx context.Context, namespace string) (*FunctionsNamespace, *Response, error) { path := fmt.Sprintf(functionsNamespacePath, namespace) req, err := s.client.NewRequest(ctx, http.MethodGet, path, nil) @@ -80,7 +80,7 @@ func (s *FunctionsServiceOp) Namespace(ctx context.Context, namespace string) (* } // Creates a namespace -func (s *FunctionsServiceOp) CreateNamespace(ctx context.Context, opts *FunctionsNamespaceCreateOptions) (*FunctionsNamespace, *Response, error) { +func (s *FunctionsServiceOp) CreateNamespace(ctx context.Context, opts *FunctionsNamespaceCreateRequest) (*FunctionsNamespace, *Response, error) { req, err := s.client.NewRequest(ctx, http.MethodPost, functionsBasePath, opts) if err != nil { return nil, nil, err diff --git a/functions_test.go b/functions_test.go index e9967148..3662cb2d 100644 --- a/functions_test.go +++ b/functions_test.go @@ -42,7 +42,7 @@ func TestFunctions_ListNamespaces(t *testing.T) { }`) }) - namespaces, _, err := client.Functions.Namespaces(ctx) + namespaces, _, err := client.Functions.ListNamespaces(ctx) require.NoError(t, err) expectedNamespaces := []FunctionsNamespace{ @@ -90,7 +90,7 @@ func TestFunctions_GetNamespace(t *testing.T) { }`) }) - namespace, _, err := client.Functions.Namespace(ctx, "123-abc") + namespace, _, err := client.Functions.GetNamespace(ctx, "123-abc") require.NoError(t, err) expectedNamespace := &FunctionsNamespace{ @@ -126,7 +126,7 @@ func TestFunctions_CreateNamespace(t *testing.T) { }`) }) - opts := FunctionsNamespaceCreateOptions{Label: "my-namespace-1", Region: "nyc1"} + opts := FunctionsNamespaceCreateRequest{Label: "my-namespace-1", Region: "nyc1"} namespace, _, err := client.Functions.CreateNamespace(ctx, &opts) require.NoError(t, err)