From a8dd681a8c1f70c9d6b4a4b9ed25c46fbc75db6f Mon Sep 17 00:00:00 2001 From: Leo Date: Tue, 3 Nov 2026 10:07:52 +0100 Subject: [PATCH 1/4] Add commands for several function schedules with their own variables Co-Authored-By: Claude Opus 5.5 --- internal/api/client.gen.go | 1230 ++++++++++++++--- internal/cmd/function_schedules.go | 299 ++++ internal/cmd/function_schedules_test.go | 242 ++++ internal/cmd/functions.go | 24 +- .../cmd/functionschedulesadd_flags.gen.go | 35 + .../cmd/functionschedulesupdate_flags.gen.go | 35 + scripts/gen-flags/parser.go | 26 +- scripts/gen-flags/types.go | 9 +- 8 files changed, 1681 insertions(+), 219 deletions(-) create mode 100644 internal/cmd/function_schedules.go create mode 100644 internal/cmd/function_schedules_test.go create mode 100644 internal/cmd/functionschedulesadd_flags.gen.go create mode 100644 internal/cmd/functionschedulesupdate_flags.gen.go diff --git a/internal/api/client.gen.go b/internal/api/client.gen.go index 0ad9d76..af4c5fe 100644 --- a/internal/api/client.gen.go +++ b/internal/api/client.gen.go @@ -2964,6 +2964,14 @@ type FunctionRuntimeHealthResponseSdkGeneration string // FunctionRuntimeHealthResponseStatus 'ok' when the runtime reported itself, 'degraded' when it is alive but too old to describe itself (its image predates this endpoint), 'unreachable' when it did not answer. type FunctionRuntimeHealthResponseStatus string +// FunctionSchedule defines model for FunctionSchedule. +type FunctionSchedule struct { + CreatedAt *string `json:"created_at,omitempty"` + Cron string `json:"cron"` + ScheduleId string `json:"schedule_id"` + Variables *map[string]interface{} `json:"variables,omitempty"` +} + // FunctionScheduleCreateRequest defines model for FunctionScheduleCreateRequest. type FunctionScheduleCreateRequest struct { // Cron AWS EventBridge schedule expression. Six space-separated fields, minutes first: `minutes hours day-of-month month day-of-week year`. This is neither five-field Unix crontab nor the seconds-first six-field dialect used by Quartz and cron-parser. Exactly one of day-of-month and day-of-week must be `?`, the other must be a real value. Schedules fire in UTC. Example: `0 12 ? * * *` runs daily at noon UTC. `rate(...)` expressions such as `rate(1 hour)` are accepted too. @@ -2973,6 +2981,17 @@ type FunctionScheduleCreateRequest struct { Variables *map[string]interface{} `json:"variables,omitempty"` } +// FunctionScheduleListResponse defines model for FunctionScheduleListResponse. +type FunctionScheduleListResponse struct { + PausedReason *string `json:"paused_reason,omitempty"` + + // Schedules The function's schedules, oldest first. + Schedules []FunctionSchedule `json:"schedules"` + + // State Applies to every schedule. Null when the function has none. + State *string `json:"state,omitempty"` +} + // FunctionSdkGeneration defines model for FunctionSdkGeneration. type FunctionSdkGeneration string @@ -6173,6 +6192,36 @@ type FunctionScheduleSetParams struct { XNotteSdkVersion *string `json:"x-notte-sdk-version,omitempty"` } +// FunctionSchedulesListParams defines parameters for FunctionSchedulesList. +type FunctionSchedulesListParams struct { + XNotteRequestOrigin *string `json:"x-notte-request-origin,omitempty"` + XNotteSdkVersion *string `json:"x-notte-sdk-version,omitempty"` +} + +// FunctionSchedulesAddParams defines parameters for FunctionSchedulesAdd. +type FunctionSchedulesAddParams struct { + XNotteRequestOrigin *string `json:"x-notte-request-origin,omitempty"` + XNotteSdkVersion *string `json:"x-notte-sdk-version,omitempty"` +} + +// FunctionSchedulesResumeParams defines parameters for FunctionSchedulesResume. +type FunctionSchedulesResumeParams struct { + XNotteRequestOrigin *string `json:"x-notte-request-origin,omitempty"` + XNotteSdkVersion *string `json:"x-notte-sdk-version,omitempty"` +} + +// FunctionSchedulesRemoveParams defines parameters for FunctionSchedulesRemove. +type FunctionSchedulesRemoveParams struct { + XNotteRequestOrigin *string `json:"x-notte-request-origin,omitempty"` + XNotteSdkVersion *string `json:"x-notte-sdk-version,omitempty"` +} + +// FunctionSchedulesUpdateParams defines parameters for FunctionSchedulesUpdate. +type FunctionSchedulesUpdateParams struct { + XNotteRequestOrigin *string `json:"x-notte-request-origin,omitempty"` + XNotteSdkVersion *string `json:"x-notte-sdk-version,omitempty"` +} + // MailboxListParams defines parameters for MailboxList. type MailboxListParams struct { XNotteRequestOrigin *string `json:"x-notte-request-origin,omitempty"` @@ -6794,6 +6843,12 @@ type PrepareRunPayloadUploadJSONRequestBody = RunPayloadUploadRequest // FunctionScheduleSetJSONRequestBody defines body for FunctionScheduleSet for application/json ContentType. type FunctionScheduleSetJSONRequestBody = FunctionScheduleCreateRequest +// FunctionSchedulesAddJSONRequestBody defines body for FunctionSchedulesAdd for application/json ContentType. +type FunctionSchedulesAddJSONRequestBody = FunctionScheduleCreateRequest + +// FunctionSchedulesUpdateJSONRequestBody defines body for FunctionSchedulesUpdate for application/json ContentType. +type FunctionSchedulesUpdateJSONRequestBody = FunctionScheduleCreateRequest + // MailboxConnectTokenJSONRequestBody defines body for MailboxConnectToken for application/json ContentType. type MailboxConnectTokenJSONRequestBody = MailboxConnectRequest @@ -14950,6 +15005,25 @@ type ClientInterface interface { FunctionScheduleSet(ctx context.Context, functionId string, params *FunctionScheduleSetParams, body FunctionScheduleSetJSONRequestBody, reqEditors ...RequestEditorFn) (*http.Response, error) + // FunctionSchedulesList request + FunctionSchedulesList(ctx context.Context, functionId string, params *FunctionSchedulesListParams, reqEditors ...RequestEditorFn) (*http.Response, error) + + // FunctionSchedulesAddWithBody request with any body + FunctionSchedulesAddWithBody(ctx context.Context, functionId string, params *FunctionSchedulesAddParams, contentType string, body io.Reader, reqEditors ...RequestEditorFn) (*http.Response, error) + + FunctionSchedulesAdd(ctx context.Context, functionId string, params *FunctionSchedulesAddParams, body FunctionSchedulesAddJSONRequestBody, reqEditors ...RequestEditorFn) (*http.Response, error) + + // FunctionSchedulesResume request + FunctionSchedulesResume(ctx context.Context, functionId string, params *FunctionSchedulesResumeParams, reqEditors ...RequestEditorFn) (*http.Response, error) + + // FunctionSchedulesRemove request + FunctionSchedulesRemove(ctx context.Context, functionId string, scheduleId string, params *FunctionSchedulesRemoveParams, reqEditors ...RequestEditorFn) (*http.Response, error) + + // FunctionSchedulesUpdateWithBody request with any body + FunctionSchedulesUpdateWithBody(ctx context.Context, functionId string, scheduleId string, params *FunctionSchedulesUpdateParams, contentType string, body io.Reader, reqEditors ...RequestEditorFn) (*http.Response, error) + + FunctionSchedulesUpdate(ctx context.Context, functionId string, scheduleId string, params *FunctionSchedulesUpdateParams, body FunctionSchedulesUpdateJSONRequestBody, reqEditors ...RequestEditorFn) (*http.Response, error) + // HealthCheck request HealthCheck(ctx context.Context, reqEditors ...RequestEditorFn) (*http.Response, error) @@ -16174,6 +16248,90 @@ func (c *Client) FunctionScheduleSet(ctx context.Context, functionId string, par return c.Client.Do(req) } +func (c *Client) FunctionSchedulesList(ctx context.Context, functionId string, params *FunctionSchedulesListParams, reqEditors ...RequestEditorFn) (*http.Response, error) { + req, err := NewFunctionSchedulesListRequest(c.Server, functionId, params) + if err != nil { + return nil, err + } + req = req.WithContext(ctx) + if err := c.applyEditors(ctx, req, reqEditors); err != nil { + return nil, err + } + return c.Client.Do(req) +} + +func (c *Client) FunctionSchedulesAddWithBody(ctx context.Context, functionId string, params *FunctionSchedulesAddParams, contentType string, body io.Reader, reqEditors ...RequestEditorFn) (*http.Response, error) { + req, err := NewFunctionSchedulesAddRequestWithBody(c.Server, functionId, params, contentType, body) + if err != nil { + return nil, err + } + req = req.WithContext(ctx) + if err := c.applyEditors(ctx, req, reqEditors); err != nil { + return nil, err + } + return c.Client.Do(req) +} + +func (c *Client) FunctionSchedulesAdd(ctx context.Context, functionId string, params *FunctionSchedulesAddParams, body FunctionSchedulesAddJSONRequestBody, reqEditors ...RequestEditorFn) (*http.Response, error) { + req, err := NewFunctionSchedulesAddRequest(c.Server, functionId, params, body) + if err != nil { + return nil, err + } + req = req.WithContext(ctx) + if err := c.applyEditors(ctx, req, reqEditors); err != nil { + return nil, err + } + return c.Client.Do(req) +} + +func (c *Client) FunctionSchedulesResume(ctx context.Context, functionId string, params *FunctionSchedulesResumeParams, reqEditors ...RequestEditorFn) (*http.Response, error) { + req, err := NewFunctionSchedulesResumeRequest(c.Server, functionId, params) + if err != nil { + return nil, err + } + req = req.WithContext(ctx) + if err := c.applyEditors(ctx, req, reqEditors); err != nil { + return nil, err + } + return c.Client.Do(req) +} + +func (c *Client) FunctionSchedulesRemove(ctx context.Context, functionId string, scheduleId string, params *FunctionSchedulesRemoveParams, reqEditors ...RequestEditorFn) (*http.Response, error) { + req, err := NewFunctionSchedulesRemoveRequest(c.Server, functionId, scheduleId, params) + if err != nil { + return nil, err + } + req = req.WithContext(ctx) + if err := c.applyEditors(ctx, req, reqEditors); err != nil { + return nil, err + } + return c.Client.Do(req) +} + +func (c *Client) FunctionSchedulesUpdateWithBody(ctx context.Context, functionId string, scheduleId string, params *FunctionSchedulesUpdateParams, contentType string, body io.Reader, reqEditors ...RequestEditorFn) (*http.Response, error) { + req, err := NewFunctionSchedulesUpdateRequestWithBody(c.Server, functionId, scheduleId, params, contentType, body) + if err != nil { + return nil, err + } + req = req.WithContext(ctx) + if err := c.applyEditors(ctx, req, reqEditors); err != nil { + return nil, err + } + return c.Client.Do(req) +} + +func (c *Client) FunctionSchedulesUpdate(ctx context.Context, functionId string, scheduleId string, params *FunctionSchedulesUpdateParams, body FunctionSchedulesUpdateJSONRequestBody, reqEditors ...RequestEditorFn) (*http.Response, error) { + req, err := NewFunctionSchedulesUpdateRequest(c.Server, functionId, scheduleId, params, body) + if err != nil { + return nil, err + } + req = req.WithContext(ctx) + if err := c.applyEditors(ctx, req, reqEditors); err != nil { + return nil, err + } + return c.Client.Do(req) +} + func (c *Client) HealthCheck(ctx context.Context, reqEditors ...RequestEditorFn) (*http.Response, error) { req, err := NewHealthCheckRequest(c.Server) if err != nil { @@ -23664,16 +23822,23 @@ func NewFunctionScheduleSetRequestWithBody(server string, functionId string, par return req, nil } -// NewHealthCheckRequest generates requests for HealthCheck -func NewHealthCheckRequest(server string) (*http.Request, error) { +// NewFunctionSchedulesListRequest generates requests for FunctionSchedulesList +func NewFunctionSchedulesListRequest(server string, functionId string, params *FunctionSchedulesListParams) (*http.Request, error) { var err error + var pathParam0 string + + pathParam0, err = runtime.StyleParamWithLocation("simple", false, "function_id", runtime.ParamLocationPath, functionId) + if err != nil { + return nil, err + } + serverURL, err := url.Parse(server) if err != nil { return nil, err } - operationPath := fmt.Sprintf("/health") + operationPath := fmt.Sprintf("/functions/%s/schedules", pathParam0) if operationPath[0] == '/' { operationPath = "." + operationPath } @@ -23688,19 +23853,63 @@ func NewHealthCheckRequest(server string) (*http.Request, error) { return nil, err } + if params != nil { + + if params.XNotteRequestOrigin != nil { + var headerParam0 string + + headerParam0, err = runtime.StyleParamWithLocation("simple", false, "x-notte-request-origin", runtime.ParamLocationHeader, *params.XNotteRequestOrigin) + if err != nil { + return nil, err + } + + req.Header.Set("x-notte-request-origin", headerParam0) + } + + if params.XNotteSdkVersion != nil { + var headerParam1 string + + headerParam1, err = runtime.StyleParamWithLocation("simple", false, "x-notte-sdk-version", runtime.ParamLocationHeader, *params.XNotteSdkVersion) + if err != nil { + return nil, err + } + + req.Header.Set("x-notte-sdk-version", headerParam1) + } + + } + return req, nil } -// NewMailboxListRequest generates requests for MailboxList -func NewMailboxListRequest(server string, params *MailboxListParams) (*http.Request, error) { +// NewFunctionSchedulesAddRequest calls the generic FunctionSchedulesAdd builder with application/json body +func NewFunctionSchedulesAddRequest(server string, functionId string, params *FunctionSchedulesAddParams, body FunctionSchedulesAddJSONRequestBody) (*http.Request, error) { + var bodyReader io.Reader + buf, err := json.Marshal(body) + if err != nil { + return nil, err + } + bodyReader = bytes.NewReader(buf) + return NewFunctionSchedulesAddRequestWithBody(server, functionId, params, "application/json", bodyReader) +} + +// NewFunctionSchedulesAddRequestWithBody generates requests for FunctionSchedulesAdd with any type of body +func NewFunctionSchedulesAddRequestWithBody(server string, functionId string, params *FunctionSchedulesAddParams, contentType string, body io.Reader) (*http.Request, error) { var err error + var pathParam0 string + + pathParam0, err = runtime.StyleParamWithLocation("simple", false, "function_id", runtime.ParamLocationPath, functionId) + if err != nil { + return nil, err + } + serverURL, err := url.Parse(server) if err != nil { return nil, err } - operationPath := fmt.Sprintf("/mailboxes") + operationPath := fmt.Sprintf("/functions/%s/schedules", pathParam0) if operationPath[0] == '/' { operationPath = "." + operationPath } @@ -23710,11 +23919,13 @@ func NewMailboxListRequest(server string, params *MailboxListParams) (*http.Requ return nil, err } - req, err := http.NewRequest("GET", queryURL.String(), nil) + req, err := http.NewRequest("POST", queryURL.String(), body) if err != nil { return nil, err } + req.Header.Add("Content-Type", contentType) + if params != nil { if params.XNotteRequestOrigin != nil { @@ -23744,27 +23955,23 @@ func NewMailboxListRequest(server string, params *MailboxListParams) (*http.Requ return req, nil } -// NewMailboxConnectTokenRequest calls the generic MailboxConnectToken builder with application/json body -func NewMailboxConnectTokenRequest(server string, params *MailboxConnectTokenParams, body MailboxConnectTokenJSONRequestBody) (*http.Request, error) { - var bodyReader io.Reader - buf, err := json.Marshal(body) +// NewFunctionSchedulesResumeRequest generates requests for FunctionSchedulesResume +func NewFunctionSchedulesResumeRequest(server string, functionId string, params *FunctionSchedulesResumeParams) (*http.Request, error) { + var err error + + var pathParam0 string + + pathParam0, err = runtime.StyleParamWithLocation("simple", false, "function_id", runtime.ParamLocationPath, functionId) if err != nil { return nil, err } - bodyReader = bytes.NewReader(buf) - return NewMailboxConnectTokenRequestWithBody(server, params, "application/json", bodyReader) -} - -// NewMailboxConnectTokenRequestWithBody generates requests for MailboxConnectToken with any type of body -func NewMailboxConnectTokenRequestWithBody(server string, params *MailboxConnectTokenParams, contentType string, body io.Reader) (*http.Request, error) { - var err error serverURL, err := url.Parse(server) if err != nil { return nil, err } - operationPath := fmt.Sprintf("/mailboxes/connect-token") + operationPath := fmt.Sprintf("/functions/%s/schedules/resume", pathParam0) if operationPath[0] == '/' { operationPath = "." + operationPath } @@ -23774,13 +23981,11 @@ func NewMailboxConnectTokenRequestWithBody(server string, params *MailboxConnect return nil, err } - req, err := http.NewRequest("POST", queryURL.String(), body) + req, err := http.NewRequest("POST", queryURL.String(), nil) if err != nil { return nil, err } - req.Header.Add("Content-Type", contentType) - if params != nil { if params.XNotteRequestOrigin != nil { @@ -23810,27 +24015,30 @@ func NewMailboxConnectTokenRequestWithBody(server string, params *MailboxConnect return req, nil } -// NewMailboxSyncRequest calls the generic MailboxSync builder with application/json body -func NewMailboxSyncRequest(server string, params *MailboxSyncParams, body MailboxSyncJSONRequestBody) (*http.Request, error) { - var bodyReader io.Reader - buf, err := json.Marshal(body) +// NewFunctionSchedulesRemoveRequest generates requests for FunctionSchedulesRemove +func NewFunctionSchedulesRemoveRequest(server string, functionId string, scheduleId string, params *FunctionSchedulesRemoveParams) (*http.Request, error) { + var err error + + var pathParam0 string + + pathParam0, err = runtime.StyleParamWithLocation("simple", false, "function_id", runtime.ParamLocationPath, functionId) if err != nil { return nil, err } - bodyReader = bytes.NewReader(buf) - return NewMailboxSyncRequestWithBody(server, params, "application/json", bodyReader) -} -// NewMailboxSyncRequestWithBody generates requests for MailboxSync with any type of body -func NewMailboxSyncRequestWithBody(server string, params *MailboxSyncParams, contentType string, body io.Reader) (*http.Request, error) { - var err error + var pathParam1 string + + pathParam1, err = runtime.StyleParamWithLocation("simple", false, "schedule_id", runtime.ParamLocationPath, scheduleId) + if err != nil { + return nil, err + } serverURL, err := url.Parse(server) if err != nil { return nil, err } - operationPath := fmt.Sprintf("/mailboxes/sync") + operationPath := fmt.Sprintf("/functions/%s/schedules/%s", pathParam0, pathParam1) if operationPath[0] == '/' { operationPath = "." + operationPath } @@ -23840,13 +24048,11 @@ func NewMailboxSyncRequestWithBody(server string, params *MailboxSyncParams, con return nil, err } - req, err := http.NewRequest("POST", queryURL.String(), body) + req, err := http.NewRequest("DELETE", queryURL.String(), nil) if err != nil { return nil, err } - req.Header.Add("Content-Type", contentType) - if params != nil { if params.XNotteRequestOrigin != nil { @@ -23876,13 +24082,31 @@ func NewMailboxSyncRequestWithBody(server string, params *MailboxSyncParams, con return req, nil } -// NewMailboxDeleteRequest generates requests for MailboxDelete -func NewMailboxDeleteRequest(server string, mailboxId string, params *MailboxDeleteParams) (*http.Request, error) { +// NewFunctionSchedulesUpdateRequest calls the generic FunctionSchedulesUpdate builder with application/json body +func NewFunctionSchedulesUpdateRequest(server string, functionId string, scheduleId string, params *FunctionSchedulesUpdateParams, body FunctionSchedulesUpdateJSONRequestBody) (*http.Request, error) { + var bodyReader io.Reader + buf, err := json.Marshal(body) + if err != nil { + return nil, err + } + bodyReader = bytes.NewReader(buf) + return NewFunctionSchedulesUpdateRequestWithBody(server, functionId, scheduleId, params, "application/json", bodyReader) +} + +// NewFunctionSchedulesUpdateRequestWithBody generates requests for FunctionSchedulesUpdate with any type of body +func NewFunctionSchedulesUpdateRequestWithBody(server string, functionId string, scheduleId string, params *FunctionSchedulesUpdateParams, contentType string, body io.Reader) (*http.Request, error) { var err error var pathParam0 string - pathParam0, err = runtime.StyleParamWithLocation("simple", false, "mailbox_id", runtime.ParamLocationPath, mailboxId) + pathParam0, err = runtime.StyleParamWithLocation("simple", false, "function_id", runtime.ParamLocationPath, functionId) + if err != nil { + return nil, err + } + + var pathParam1 string + + pathParam1, err = runtime.StyleParamWithLocation("simple", false, "schedule_id", runtime.ParamLocationPath, scheduleId) if err != nil { return nil, err } @@ -23892,7 +24116,7 @@ func NewMailboxDeleteRequest(server string, mailboxId string, params *MailboxDel return nil, err } - operationPath := fmt.Sprintf("/mailboxes/%s", pathParam0) + operationPath := fmt.Sprintf("/functions/%s/schedules/%s", pathParam0, pathParam1) if operationPath[0] == '/' { operationPath = "." + operationPath } @@ -23902,11 +24126,13 @@ func NewMailboxDeleteRequest(server string, mailboxId string, params *MailboxDel return nil, err } - req, err := http.NewRequest("DELETE", queryURL.String(), nil) + req, err := http.NewRequest("PATCH", queryURL.String(), body) if err != nil { return nil, err } + req.Header.Add("Content-Type", contentType) + if params != nil { if params.XNotteRequestOrigin != nil { @@ -23936,23 +24162,295 @@ func NewMailboxDeleteRequest(server string, mailboxId string, params *MailboxDel return req, nil } -// NewMailboxGetRequest generates requests for MailboxGet -func NewMailboxGetRequest(server string, mailboxId string, params *MailboxGetParams) (*http.Request, error) { +// NewHealthCheckRequest generates requests for HealthCheck +func NewHealthCheckRequest(server string) (*http.Request, error) { var err error - var pathParam0 string + serverURL, err := url.Parse(server) + if err != nil { + return nil, err + } - pathParam0, err = runtime.StyleParamWithLocation("simple", false, "mailbox_id", runtime.ParamLocationPath, mailboxId) + operationPath := fmt.Sprintf("/health") + if operationPath[0] == '/' { + operationPath = "." + operationPath + } + + queryURL, err := serverURL.Parse(operationPath) + if err != nil { + return nil, err + } + + req, err := http.NewRequest("GET", queryURL.String(), nil) if err != nil { return nil, err } + return req, nil +} + +// NewMailboxListRequest generates requests for MailboxList +func NewMailboxListRequest(server string, params *MailboxListParams) (*http.Request, error) { + var err error + serverURL, err := url.Parse(server) if err != nil { return nil, err } - operationPath := fmt.Sprintf("/mailboxes/%s", pathParam0) + operationPath := fmt.Sprintf("/mailboxes") + if operationPath[0] == '/' { + operationPath = "." + operationPath + } + + queryURL, err := serverURL.Parse(operationPath) + if err != nil { + return nil, err + } + + req, err := http.NewRequest("GET", queryURL.String(), nil) + if err != nil { + return nil, err + } + + if params != nil { + + if params.XNotteRequestOrigin != nil { + var headerParam0 string + + headerParam0, err = runtime.StyleParamWithLocation("simple", false, "x-notte-request-origin", runtime.ParamLocationHeader, *params.XNotteRequestOrigin) + if err != nil { + return nil, err + } + + req.Header.Set("x-notte-request-origin", headerParam0) + } + + if params.XNotteSdkVersion != nil { + var headerParam1 string + + headerParam1, err = runtime.StyleParamWithLocation("simple", false, "x-notte-sdk-version", runtime.ParamLocationHeader, *params.XNotteSdkVersion) + if err != nil { + return nil, err + } + + req.Header.Set("x-notte-sdk-version", headerParam1) + } + + } + + return req, nil +} + +// NewMailboxConnectTokenRequest calls the generic MailboxConnectToken builder with application/json body +func NewMailboxConnectTokenRequest(server string, params *MailboxConnectTokenParams, body MailboxConnectTokenJSONRequestBody) (*http.Request, error) { + var bodyReader io.Reader + buf, err := json.Marshal(body) + if err != nil { + return nil, err + } + bodyReader = bytes.NewReader(buf) + return NewMailboxConnectTokenRequestWithBody(server, params, "application/json", bodyReader) +} + +// NewMailboxConnectTokenRequestWithBody generates requests for MailboxConnectToken with any type of body +func NewMailboxConnectTokenRequestWithBody(server string, params *MailboxConnectTokenParams, contentType string, body io.Reader) (*http.Request, error) { + var err error + + serverURL, err := url.Parse(server) + if err != nil { + return nil, err + } + + operationPath := fmt.Sprintf("/mailboxes/connect-token") + if operationPath[0] == '/' { + operationPath = "." + operationPath + } + + queryURL, err := serverURL.Parse(operationPath) + if err != nil { + return nil, err + } + + req, err := http.NewRequest("POST", queryURL.String(), body) + if err != nil { + return nil, err + } + + req.Header.Add("Content-Type", contentType) + + if params != nil { + + if params.XNotteRequestOrigin != nil { + var headerParam0 string + + headerParam0, err = runtime.StyleParamWithLocation("simple", false, "x-notte-request-origin", runtime.ParamLocationHeader, *params.XNotteRequestOrigin) + if err != nil { + return nil, err + } + + req.Header.Set("x-notte-request-origin", headerParam0) + } + + if params.XNotteSdkVersion != nil { + var headerParam1 string + + headerParam1, err = runtime.StyleParamWithLocation("simple", false, "x-notte-sdk-version", runtime.ParamLocationHeader, *params.XNotteSdkVersion) + if err != nil { + return nil, err + } + + req.Header.Set("x-notte-sdk-version", headerParam1) + } + + } + + return req, nil +} + +// NewMailboxSyncRequest calls the generic MailboxSync builder with application/json body +func NewMailboxSyncRequest(server string, params *MailboxSyncParams, body MailboxSyncJSONRequestBody) (*http.Request, error) { + var bodyReader io.Reader + buf, err := json.Marshal(body) + if err != nil { + return nil, err + } + bodyReader = bytes.NewReader(buf) + return NewMailboxSyncRequestWithBody(server, params, "application/json", bodyReader) +} + +// NewMailboxSyncRequestWithBody generates requests for MailboxSync with any type of body +func NewMailboxSyncRequestWithBody(server string, params *MailboxSyncParams, contentType string, body io.Reader) (*http.Request, error) { + var err error + + serverURL, err := url.Parse(server) + if err != nil { + return nil, err + } + + operationPath := fmt.Sprintf("/mailboxes/sync") + if operationPath[0] == '/' { + operationPath = "." + operationPath + } + + queryURL, err := serverURL.Parse(operationPath) + if err != nil { + return nil, err + } + + req, err := http.NewRequest("POST", queryURL.String(), body) + if err != nil { + return nil, err + } + + req.Header.Add("Content-Type", contentType) + + if params != nil { + + if params.XNotteRequestOrigin != nil { + var headerParam0 string + + headerParam0, err = runtime.StyleParamWithLocation("simple", false, "x-notte-request-origin", runtime.ParamLocationHeader, *params.XNotteRequestOrigin) + if err != nil { + return nil, err + } + + req.Header.Set("x-notte-request-origin", headerParam0) + } + + if params.XNotteSdkVersion != nil { + var headerParam1 string + + headerParam1, err = runtime.StyleParamWithLocation("simple", false, "x-notte-sdk-version", runtime.ParamLocationHeader, *params.XNotteSdkVersion) + if err != nil { + return nil, err + } + + req.Header.Set("x-notte-sdk-version", headerParam1) + } + + } + + return req, nil +} + +// NewMailboxDeleteRequest generates requests for MailboxDelete +func NewMailboxDeleteRequest(server string, mailboxId string, params *MailboxDeleteParams) (*http.Request, error) { + var err error + + var pathParam0 string + + pathParam0, err = runtime.StyleParamWithLocation("simple", false, "mailbox_id", runtime.ParamLocationPath, mailboxId) + if err != nil { + return nil, err + } + + serverURL, err := url.Parse(server) + if err != nil { + return nil, err + } + + operationPath := fmt.Sprintf("/mailboxes/%s", pathParam0) + if operationPath[0] == '/' { + operationPath = "." + operationPath + } + + queryURL, err := serverURL.Parse(operationPath) + if err != nil { + return nil, err + } + + req, err := http.NewRequest("DELETE", queryURL.String(), nil) + if err != nil { + return nil, err + } + + if params != nil { + + if params.XNotteRequestOrigin != nil { + var headerParam0 string + + headerParam0, err = runtime.StyleParamWithLocation("simple", false, "x-notte-request-origin", runtime.ParamLocationHeader, *params.XNotteRequestOrigin) + if err != nil { + return nil, err + } + + req.Header.Set("x-notte-request-origin", headerParam0) + } + + if params.XNotteSdkVersion != nil { + var headerParam1 string + + headerParam1, err = runtime.StyleParamWithLocation("simple", false, "x-notte-sdk-version", runtime.ParamLocationHeader, *params.XNotteSdkVersion) + if err != nil { + return nil, err + } + + req.Header.Set("x-notte-sdk-version", headerParam1) + } + + } + + return req, nil +} + +// NewMailboxGetRequest generates requests for MailboxGet +func NewMailboxGetRequest(server string, mailboxId string, params *MailboxGetParams) (*http.Request, error) { + var err error + + var pathParam0 string + + pathParam0, err = runtime.StyleParamWithLocation("simple", false, "mailbox_id", runtime.ParamLocationPath, mailboxId) + if err != nil { + return nil, err + } + + serverURL, err := url.Parse(server) + if err != nil { + return nil, err + } + + operationPath := fmt.Sprintf("/mailboxes/%s", pathParam0) if operationPath[0] == '/' { operationPath = "." + operationPath } @@ -29464,6 +29962,25 @@ type ClientWithResponsesInterface interface { FunctionScheduleSetWithResponse(ctx context.Context, functionId string, params *FunctionScheduleSetParams, body FunctionScheduleSetJSONRequestBody, reqEditors ...RequestEditorFn) (*FunctionScheduleSetResult, error) + // FunctionSchedulesListWithResponse request + FunctionSchedulesListWithResponse(ctx context.Context, functionId string, params *FunctionSchedulesListParams, reqEditors ...RequestEditorFn) (*FunctionSchedulesListResult, error) + + // FunctionSchedulesAddWithBodyWithResponse request with any body + FunctionSchedulesAddWithBodyWithResponse(ctx context.Context, functionId string, params *FunctionSchedulesAddParams, contentType string, body io.Reader, reqEditors ...RequestEditorFn) (*FunctionSchedulesAddResult, error) + + FunctionSchedulesAddWithResponse(ctx context.Context, functionId string, params *FunctionSchedulesAddParams, body FunctionSchedulesAddJSONRequestBody, reqEditors ...RequestEditorFn) (*FunctionSchedulesAddResult, error) + + // FunctionSchedulesResumeWithResponse request + FunctionSchedulesResumeWithResponse(ctx context.Context, functionId string, params *FunctionSchedulesResumeParams, reqEditors ...RequestEditorFn) (*FunctionSchedulesResumeResult, error) + + // FunctionSchedulesRemoveWithResponse request + FunctionSchedulesRemoveWithResponse(ctx context.Context, functionId string, scheduleId string, params *FunctionSchedulesRemoveParams, reqEditors ...RequestEditorFn) (*FunctionSchedulesRemoveResult, error) + + // FunctionSchedulesUpdateWithBodyWithResponse request with any body + FunctionSchedulesUpdateWithBodyWithResponse(ctx context.Context, functionId string, scheduleId string, params *FunctionSchedulesUpdateParams, contentType string, body io.Reader, reqEditors ...RequestEditorFn) (*FunctionSchedulesUpdateResult, error) + + FunctionSchedulesUpdateWithResponse(ctx context.Context, functionId string, scheduleId string, params *FunctionSchedulesUpdateParams, body FunctionSchedulesUpdateJSONRequestBody, reqEditors ...RequestEditorFn) (*FunctionSchedulesUpdateResult, error) + // HealthCheckWithResponse request HealthCheckWithResponse(ctx context.Context, reqEditors ...RequestEditorFn) (*HealthCheckResult, error) @@ -31096,6 +31613,121 @@ func (r FunctionScheduleSetResult) StatusCode() int { return 0 } +type FunctionSchedulesListResult struct { + Body []byte + HTTPResponse *http.Response + JSON200 *FunctionScheduleListResponse + JSON422 *HTTPValidationError +} + +// Status returns HTTPResponse.Status +func (r FunctionSchedulesListResult) Status() string { + if r.HTTPResponse != nil { + return r.HTTPResponse.Status + } + return http.StatusText(0) +} + +// StatusCode returns HTTPResponse.StatusCode +func (r FunctionSchedulesListResult) StatusCode() int { + if r.HTTPResponse != nil { + return r.HTTPResponse.StatusCode + } + return 0 +} + +type FunctionSchedulesAddResult struct { + Body []byte + HTTPResponse *http.Response + JSON200 *FunctionSchedule + JSON422 *HTTPValidationError +} + +// Status returns HTTPResponse.Status +func (r FunctionSchedulesAddResult) Status() string { + if r.HTTPResponse != nil { + return r.HTTPResponse.Status + } + return http.StatusText(0) +} + +// StatusCode returns HTTPResponse.StatusCode +func (r FunctionSchedulesAddResult) StatusCode() int { + if r.HTTPResponse != nil { + return r.HTTPResponse.StatusCode + } + return 0 +} + +type FunctionSchedulesResumeResult struct { + Body []byte + HTTPResponse *http.Response + JSON200 *FunctionScheduleListResponse + JSON422 *HTTPValidationError +} + +// Status returns HTTPResponse.Status +func (r FunctionSchedulesResumeResult) Status() string { + if r.HTTPResponse != nil { + return r.HTTPResponse.Status + } + return http.StatusText(0) +} + +// StatusCode returns HTTPResponse.StatusCode +func (r FunctionSchedulesResumeResult) StatusCode() int { + if r.HTTPResponse != nil { + return r.HTTPResponse.StatusCode + } + return 0 +} + +type FunctionSchedulesRemoveResult struct { + Body []byte + HTTPResponse *http.Response + JSON200 *ScheduleDeleteResponse + JSON422 *HTTPValidationError +} + +// Status returns HTTPResponse.Status +func (r FunctionSchedulesRemoveResult) Status() string { + if r.HTTPResponse != nil { + return r.HTTPResponse.Status + } + return http.StatusText(0) +} + +// StatusCode returns HTTPResponse.StatusCode +func (r FunctionSchedulesRemoveResult) StatusCode() int { + if r.HTTPResponse != nil { + return r.HTTPResponse.StatusCode + } + return 0 +} + +type FunctionSchedulesUpdateResult struct { + Body []byte + HTTPResponse *http.Response + JSON200 *FunctionSchedule + JSON422 *HTTPValidationError +} + +// Status returns HTTPResponse.Status +func (r FunctionSchedulesUpdateResult) Status() string { + if r.HTTPResponse != nil { + return r.HTTPResponse.Status + } + return http.StatusText(0) +} + +// StatusCode returns HTTPResponse.StatusCode +func (r FunctionSchedulesUpdateResult) StatusCode() int { + if r.HTTPResponse != nil { + return r.HTTPResponse.StatusCode + } + return 0 +} + type HealthCheckResult struct { Body []byte HTTPResponse *http.Response @@ -33466,6 +34098,67 @@ func (c *ClientWithResponses) FunctionScheduleSetWithResponse(ctx context.Contex return ParseFunctionScheduleSetResult(rsp) } +// FunctionSchedulesListWithResponse request returning *FunctionSchedulesListResult +func (c *ClientWithResponses) FunctionSchedulesListWithResponse(ctx context.Context, functionId string, params *FunctionSchedulesListParams, reqEditors ...RequestEditorFn) (*FunctionSchedulesListResult, error) { + rsp, err := c.FunctionSchedulesList(ctx, functionId, params, reqEditors...) + if err != nil { + return nil, err + } + return ParseFunctionSchedulesListResult(rsp) +} + +// FunctionSchedulesAddWithBodyWithResponse request with arbitrary body returning *FunctionSchedulesAddResult +func (c *ClientWithResponses) FunctionSchedulesAddWithBodyWithResponse(ctx context.Context, functionId string, params *FunctionSchedulesAddParams, contentType string, body io.Reader, reqEditors ...RequestEditorFn) (*FunctionSchedulesAddResult, error) { + rsp, err := c.FunctionSchedulesAddWithBody(ctx, functionId, params, contentType, body, reqEditors...) + if err != nil { + return nil, err + } + return ParseFunctionSchedulesAddResult(rsp) +} + +func (c *ClientWithResponses) FunctionSchedulesAddWithResponse(ctx context.Context, functionId string, params *FunctionSchedulesAddParams, body FunctionSchedulesAddJSONRequestBody, reqEditors ...RequestEditorFn) (*FunctionSchedulesAddResult, error) { + rsp, err := c.FunctionSchedulesAdd(ctx, functionId, params, body, reqEditors...) + if err != nil { + return nil, err + } + return ParseFunctionSchedulesAddResult(rsp) +} + +// FunctionSchedulesResumeWithResponse request returning *FunctionSchedulesResumeResult +func (c *ClientWithResponses) FunctionSchedulesResumeWithResponse(ctx context.Context, functionId string, params *FunctionSchedulesResumeParams, reqEditors ...RequestEditorFn) (*FunctionSchedulesResumeResult, error) { + rsp, err := c.FunctionSchedulesResume(ctx, functionId, params, reqEditors...) + if err != nil { + return nil, err + } + return ParseFunctionSchedulesResumeResult(rsp) +} + +// FunctionSchedulesRemoveWithResponse request returning *FunctionSchedulesRemoveResult +func (c *ClientWithResponses) FunctionSchedulesRemoveWithResponse(ctx context.Context, functionId string, scheduleId string, params *FunctionSchedulesRemoveParams, reqEditors ...RequestEditorFn) (*FunctionSchedulesRemoveResult, error) { + rsp, err := c.FunctionSchedulesRemove(ctx, functionId, scheduleId, params, reqEditors...) + if err != nil { + return nil, err + } + return ParseFunctionSchedulesRemoveResult(rsp) +} + +// FunctionSchedulesUpdateWithBodyWithResponse request with arbitrary body returning *FunctionSchedulesUpdateResult +func (c *ClientWithResponses) FunctionSchedulesUpdateWithBodyWithResponse(ctx context.Context, functionId string, scheduleId string, params *FunctionSchedulesUpdateParams, contentType string, body io.Reader, reqEditors ...RequestEditorFn) (*FunctionSchedulesUpdateResult, error) { + rsp, err := c.FunctionSchedulesUpdateWithBody(ctx, functionId, scheduleId, params, contentType, body, reqEditors...) + if err != nil { + return nil, err + } + return ParseFunctionSchedulesUpdateResult(rsp) +} + +func (c *ClientWithResponses) FunctionSchedulesUpdateWithResponse(ctx context.Context, functionId string, scheduleId string, params *FunctionSchedulesUpdateParams, body FunctionSchedulesUpdateJSONRequestBody, reqEditors ...RequestEditorFn) (*FunctionSchedulesUpdateResult, error) { + rsp, err := c.FunctionSchedulesUpdate(ctx, functionId, scheduleId, params, body, reqEditors...) + if err != nil { + return nil, err + } + return ParseFunctionSchedulesUpdateResult(rsp) +} + // HealthCheckWithResponse request returning *HealthCheckResult func (c *ClientWithResponses) HealthCheckWithResponse(ctx context.Context, reqEditors ...RequestEditorFn) (*HealthCheckResult, error) { rsp, err := c.HealthCheck(ctx, reqEditors...) @@ -35165,22 +35858,187 @@ func ParseChangesResult(rsp *http.Response) (*ChangesResult, error) { return response, nil } -// ParseRetrieveChangeResult parses an HTTP response from a RetrieveChangeWithResponse call -func ParseRetrieveChangeResult(rsp *http.Response) (*RetrieveChangeResult, error) { +// ParseRetrieveChangeResult parses an HTTP response from a RetrieveChangeWithResponse call +func ParseRetrieveChangeResult(rsp *http.Response) (*RetrieveChangeResult, error) { + bodyBytes, err := io.ReadAll(rsp.Body) + defer func() { _ = rsp.Body.Close() }() + if err != nil { + return nil, err + } + + response := &RetrieveChangeResult{ + Body: bodyBytes, + HTTPResponse: rsp, + } + + switch { + case strings.Contains(rsp.Header.Get("Content-Type"), "json") && rsp.StatusCode == 200: + var dest map[string]interface{} + if err := json.Unmarshal(bodyBytes, &dest); err != nil { + return nil, err + } + response.JSON200 = &dest + + case strings.Contains(rsp.Header.Get("Content-Type"), "json") && rsp.StatusCode == 422: + var dest HTTPValidationError + if err := json.Unmarshal(bodyBytes, &dest); err != nil { + return nil, err + } + response.JSON422 = &dest + + } + + return response, nil +} + +// ParseRunNowResult parses an HTTP response from a RunNowWithResponse call +func ParseRunNowResult(rsp *http.Response) (*RunNowResult, error) { + bodyBytes, err := io.ReadAll(rsp.Body) + defer func() { _ = rsp.Body.Close() }() + if err != nil { + return nil, err + } + + response := &RunNowResult{ + Body: bodyBytes, + HTTPResponse: rsp, + } + + switch { + case strings.Contains(rsp.Header.Get("Content-Type"), "json") && rsp.StatusCode == 202: + var dest map[string]interface{} + if err := json.Unmarshal(bodyBytes, &dest); err != nil { + return nil, err + } + response.JSON202 = &dest + + case strings.Contains(rsp.Header.Get("Content-Type"), "json") && rsp.StatusCode == 422: + var dest HTTPValidationError + if err := json.Unmarshal(bodyBytes, &dest); err != nil { + return nil, err + } + response.JSON422 = &dest + + } + + return response, nil +} + +// ParseRunsResult parses an HTTP response from a RunsWithResponse call +func ParseRunsResult(rsp *http.Response) (*RunsResult, error) { + bodyBytes, err := io.ReadAll(rsp.Body) + defer func() { _ = rsp.Body.Close() }() + if err != nil { + return nil, err + } + + response := &RunsResult{ + Body: bodyBytes, + HTTPResponse: rsp, + } + + switch { + case strings.Contains(rsp.Header.Get("Content-Type"), "json") && rsp.StatusCode == 200: + var dest map[string]interface{} + if err := json.Unmarshal(bodyBytes, &dest); err != nil { + return nil, err + } + response.JSON200 = &dest + + case strings.Contains(rsp.Header.Get("Content-Type"), "json") && rsp.StatusCode == 422: + var dest HTTPValidationError + if err := json.Unmarshal(bodyBytes, &dest); err != nil { + return nil, err + } + response.JSON422 = &dest + + } + + return response, nil +} + +// ParseRetrieveRunResult parses an HTTP response from a RetrieveRunWithResponse call +func ParseRetrieveRunResult(rsp *http.Response) (*RetrieveRunResult, error) { + bodyBytes, err := io.ReadAll(rsp.Body) + defer func() { _ = rsp.Body.Close() }() + if err != nil { + return nil, err + } + + response := &RetrieveRunResult{ + Body: bodyBytes, + HTTPResponse: rsp, + } + + switch { + case strings.Contains(rsp.Header.Get("Content-Type"), "json") && rsp.StatusCode == 200: + var dest map[string]interface{} + if err := json.Unmarshal(bodyBytes, &dest); err != nil { + return nil, err + } + response.JSON200 = &dest + + case strings.Contains(rsp.Header.Get("Content-Type"), "json") && rsp.StatusCode == 422: + var dest HTTPValidationError + if err := json.Unmarshal(bodyBytes, &dest); err != nil { + return nil, err + } + response.JSON422 = &dest + + } + + return response, nil +} + +// ParseRotateSecretResult parses an HTTP response from a RotateSecretWithResponse call +func ParseRotateSecretResult(rsp *http.Response) (*RotateSecretResult, error) { + bodyBytes, err := io.ReadAll(rsp.Body) + defer func() { _ = rsp.Body.Close() }() + if err != nil { + return nil, err + } + + response := &RotateSecretResult{ + Body: bodyBytes, + HTTPResponse: rsp, + } + + switch { + case strings.Contains(rsp.Header.Get("Content-Type"), "json") && rsp.StatusCode == 200: + var dest map[string]interface{} + if err := json.Unmarshal(bodyBytes, &dest); err != nil { + return nil, err + } + response.JSON200 = &dest + + case strings.Contains(rsp.Header.Get("Content-Type"), "json") && rsp.StatusCode == 422: + var dest HTTPValidationError + if err := json.Unmarshal(bodyBytes, &dest); err != nil { + return nil, err + } + response.JSON422 = &dest + + } + + return response, nil +} + +// ParseNewsSearchResult parses an HTTP response from a NewsSearchWithResponse call +func ParseNewsSearchResult(rsp *http.Response) (*NewsSearchResult, error) { bodyBytes, err := io.ReadAll(rsp.Body) defer func() { _ = rsp.Body.Close() }() if err != nil { return nil, err } - response := &RetrieveChangeResult{ + response := &NewsSearchResult{ Body: bodyBytes, HTTPResponse: rsp, } switch { case strings.Contains(rsp.Header.Get("Content-Type"), "json") && rsp.StatusCode == 200: - var dest map[string]interface{} + var dest NewsSearchResponse if err := json.Unmarshal(bodyBytes, &dest); err != nil { return nil, err } @@ -35198,26 +36056,26 @@ func ParseRetrieveChangeResult(rsp *http.Response) (*RetrieveChangeResult, error return response, nil } -// ParseRunNowResult parses an HTTP response from a RunNowWithResponse call -func ParseRunNowResult(rsp *http.Response) (*RunNowResult, error) { +// ParsePeopleEnrichResult parses an HTTP response from a PeopleEnrichWithResponse call +func ParsePeopleEnrichResult(rsp *http.Response) (*PeopleEnrichResult, error) { bodyBytes, err := io.ReadAll(rsp.Body) defer func() { _ = rsp.Body.Close() }() if err != nil { return nil, err } - response := &RunNowResult{ + response := &PeopleEnrichResult{ Body: bodyBytes, HTTPResponse: rsp, } switch { - case strings.Contains(rsp.Header.Get("Content-Type"), "json") && rsp.StatusCode == 202: - var dest map[string]interface{} + case strings.Contains(rsp.Header.Get("Content-Type"), "json") && rsp.StatusCode == 200: + var dest PeopleEnrichResponse if err := json.Unmarshal(bodyBytes, &dest); err != nil { return nil, err } - response.JSON202 = &dest + response.JSON200 = &dest case strings.Contains(rsp.Header.Get("Content-Type"), "json") && rsp.StatusCode == 422: var dest HTTPValidationError @@ -35231,22 +36089,22 @@ func ParseRunNowResult(rsp *http.Response) (*RunNowResult, error) { return response, nil } -// ParseRunsResult parses an HTTP response from a RunsWithResponse call -func ParseRunsResult(rsp *http.Response) (*RunsResult, error) { +// ParseExtractProductEndpointResult parses an HTTP response from a ExtractProductEndpointWithResponse call +func ParseExtractProductEndpointResult(rsp *http.Response) (*ExtractProductEndpointResult, error) { bodyBytes, err := io.ReadAll(rsp.Body) defer func() { _ = rsp.Body.Close() }() if err != nil { return nil, err } - response := &RunsResult{ + response := &ExtractProductEndpointResult{ Body: bodyBytes, HTTPResponse: rsp, } switch { case strings.Contains(rsp.Header.Get("Content-Type"), "json") && rsp.StatusCode == 200: - var dest map[string]interface{} + var dest ProductOutput if err := json.Unmarshal(bodyBytes, &dest); err != nil { return nil, err } @@ -35264,22 +36122,22 @@ func ParseRunsResult(rsp *http.Response) (*RunsResult, error) { return response, nil } -// ParseRetrieveRunResult parses an HTTP response from a RetrieveRunWithResponse call -func ParseRetrieveRunResult(rsp *http.Response) (*RetrieveRunResult, error) { +// ParseFetchSpecializedDataResult parses an HTTP response from a FetchSpecializedDataWithResponse call +func ParseFetchSpecializedDataResult(rsp *http.Response) (*FetchSpecializedDataResult, error) { bodyBytes, err := io.ReadAll(rsp.Body) defer func() { _ = rsp.Body.Close() }() if err != nil { return nil, err } - response := &RetrieveRunResult{ + response := &FetchSpecializedDataResult{ Body: bodyBytes, HTTPResponse: rsp, } switch { case strings.Contains(rsp.Header.Get("Content-Type"), "json") && rsp.StatusCode == 200: - var dest map[string]interface{} + var dest ScrapeResponse if err := json.Unmarshal(bodyBytes, &dest); err != nil { return nil, err } @@ -35297,22 +36155,22 @@ func ParseRetrieveRunResult(rsp *http.Response) (*RetrieveRunResult, error) { return response, nil } -// ParseRotateSecretResult parses an HTTP response from a RotateSecretWithResponse call -func ParseRotateSecretResult(rsp *http.Response) (*RotateSecretResult, error) { +// ParseStyleguideEndpointResult parses an HTTP response from a StyleguideEndpointWithResponse call +func ParseStyleguideEndpointResult(rsp *http.Response) (*StyleguideEndpointResult, error) { bodyBytes, err := io.ReadAll(rsp.Body) defer func() { _ = rsp.Body.Close() }() if err != nil { return nil, err } - response := &RotateSecretResult{ + response := &StyleguideEndpointResult{ Body: bodyBytes, HTTPResponse: rsp, } switch { case strings.Contains(rsp.Header.Get("Content-Type"), "json") && rsp.StatusCode == 200: - var dest map[string]interface{} + var dest StyleguideResponse if err := json.Unmarshal(bodyBytes, &dest); err != nil { return nil, err } @@ -35330,22 +36188,22 @@ func ParseRotateSecretResult(rsp *http.Response) (*RotateSecretResult, error) { return response, nil } -// ParseNewsSearchResult parses an HTTP response from a NewsSearchWithResponse call -func ParseNewsSearchResult(rsp *http.Response) (*NewsSearchResult, error) { +// ParseDeliveriesResult parses an HTTP response from a DeliveriesWithResponse call +func ParseDeliveriesResult(rsp *http.Response) (*DeliveriesResult, error) { bodyBytes, err := io.ReadAll(rsp.Body) defer func() { _ = rsp.Body.Close() }() if err != nil { return nil, err } - response := &NewsSearchResult{ + response := &DeliveriesResult{ Body: bodyBytes, HTTPResponse: rsp, } switch { case strings.Contains(rsp.Header.Get("Content-Type"), "json") && rsp.StatusCode == 200: - var dest NewsSearchResponse + var dest map[string]interface{} if err := json.Unmarshal(bodyBytes, &dest); err != nil { return nil, err } @@ -35363,22 +36221,22 @@ func ParseNewsSearchResult(rsp *http.Response) (*NewsSearchResult, error) { return response, nil } -// ParsePeopleEnrichResult parses an HTTP response from a PeopleEnrichWithResponse call -func ParsePeopleEnrichResult(rsp *http.Response) (*PeopleEnrichResult, error) { +// ParseRetrieveDeliveryResult parses an HTTP response from a RetrieveDeliveryWithResponse call +func ParseRetrieveDeliveryResult(rsp *http.Response) (*RetrieveDeliveryResult, error) { bodyBytes, err := io.ReadAll(rsp.Body) defer func() { _ = rsp.Body.Close() }() if err != nil { return nil, err } - response := &PeopleEnrichResult{ + response := &RetrieveDeliveryResult{ Body: bodyBytes, HTTPResponse: rsp, } switch { case strings.Contains(rsp.Header.Get("Content-Type"), "json") && rsp.StatusCode == 200: - var dest PeopleEnrichResponse + var dest map[string]interface{} if err := json.Unmarshal(bodyBytes, &dest); err != nil { return nil, err } @@ -35396,22 +36254,22 @@ func ParsePeopleEnrichResult(rsp *http.Response) (*PeopleEnrichResult, error) { return response, nil } -// ParseExtractProductEndpointResult parses an HTTP response from a ExtractProductEndpointWithResponse call -func ParseExtractProductEndpointResult(rsp *http.Response) (*ExtractProductEndpointResult, error) { +// ParseAttemptsResult parses an HTTP response from a AttemptsWithResponse call +func ParseAttemptsResult(rsp *http.Response) (*AttemptsResult, error) { bodyBytes, err := io.ReadAll(rsp.Body) defer func() { _ = rsp.Body.Close() }() if err != nil { return nil, err } - response := &ExtractProductEndpointResult{ + response := &AttemptsResult{ Body: bodyBytes, HTTPResponse: rsp, } switch { case strings.Contains(rsp.Header.Get("Content-Type"), "json") && rsp.StatusCode == 200: - var dest ProductOutput + var dest map[string]interface{} if err := json.Unmarshal(bodyBytes, &dest); err != nil { return nil, err } @@ -35429,26 +36287,26 @@ func ParseExtractProductEndpointResult(rsp *http.Response) (*ExtractProductEndpo return response, nil } -// ParseFetchSpecializedDataResult parses an HTTP response from a FetchSpecializedDataWithResponse call -func ParseFetchSpecializedDataResult(rsp *http.Response) (*FetchSpecializedDataResult, error) { +// ParseRetryResult parses an HTTP response from a RetryWithResponse call +func ParseRetryResult(rsp *http.Response) (*RetryResult, error) { bodyBytes, err := io.ReadAll(rsp.Body) defer func() { _ = rsp.Body.Close() }() if err != nil { return nil, err } - response := &FetchSpecializedDataResult{ + response := &RetryResult{ Body: bodyBytes, HTTPResponse: rsp, } switch { - case strings.Contains(rsp.Header.Get("Content-Type"), "json") && rsp.StatusCode == 200: - var dest ScrapeResponse + case strings.Contains(rsp.Header.Get("Content-Type"), "json") && rsp.StatusCode == 202: + var dest map[string]interface{} if err := json.Unmarshal(bodyBytes, &dest); err != nil { return nil, err } - response.JSON200 = &dest + response.JSON202 = &dest case strings.Contains(rsp.Header.Get("Content-Type"), "json") && rsp.StatusCode == 422: var dest HTTPValidationError @@ -35462,22 +36320,22 @@ func ParseFetchSpecializedDataResult(rsp *http.Response) (*FetchSpecializedDataR return response, nil } -// ParseStyleguideEndpointResult parses an HTTP response from a StyleguideEndpointWithResponse call -func ParseStyleguideEndpointResult(rsp *http.Response) (*StyleguideEndpointResult, error) { +// ParseYoutubeEndpointResult parses an HTTP response from a YoutubeEndpointWithResponse call +func ParseYoutubeEndpointResult(rsp *http.Response) (*YoutubeEndpointResult, error) { bodyBytes, err := io.ReadAll(rsp.Body) defer func() { _ = rsp.Body.Close() }() if err != nil { return nil, err } - response := &StyleguideEndpointResult{ + response := &YoutubeEndpointResult{ Body: bodyBytes, HTTPResponse: rsp, } switch { case strings.Contains(rsp.Header.Get("Content-Type"), "json") && rsp.StatusCode == 200: - var dest StyleguideResponse + var dest YouTubeResult if err := json.Unmarshal(bodyBytes, &dest); err != nil { return nil, err } @@ -35495,22 +36353,22 @@ func ParseStyleguideEndpointResult(rsp *http.Response) (*StyleguideEndpointResul return response, nil } -// ParseDeliveriesResult parses an HTTP response from a DeliveriesWithResponse call -func ParseDeliveriesResult(rsp *http.Response) (*DeliveriesResult, error) { +// ParseListFunctionsResult parses an HTTP response from a ListFunctionsWithResponse call +func ParseListFunctionsResult(rsp *http.Response) (*ListFunctionsResult, error) { bodyBytes, err := io.ReadAll(rsp.Body) defer func() { _ = rsp.Body.Close() }() if err != nil { return nil, err } - response := &DeliveriesResult{ + response := &ListFunctionsResult{ Body: bodyBytes, HTTPResponse: rsp, } switch { case strings.Contains(rsp.Header.Get("Content-Type"), "json") && rsp.StatusCode == 200: - var dest map[string]interface{} + var dest PaginatedResponseFunctionListItemResponse if err := json.Unmarshal(bodyBytes, &dest); err != nil { return nil, err } @@ -35528,22 +36386,22 @@ func ParseDeliveriesResult(rsp *http.Response) (*DeliveriesResult, error) { return response, nil } -// ParseRetrieveDeliveryResult parses an HTTP response from a RetrieveDeliveryWithResponse call -func ParseRetrieveDeliveryResult(rsp *http.Response) (*RetrieveDeliveryResult, error) { +// ParseFunctionCreateResult parses an HTTP response from a FunctionCreateWithResponse call +func ParseFunctionCreateResult(rsp *http.Response) (*FunctionCreateResult, error) { bodyBytes, err := io.ReadAll(rsp.Body) defer func() { _ = rsp.Body.Close() }() if err != nil { return nil, err } - response := &RetrieveDeliveryResult{ + response := &FunctionCreateResult{ Body: bodyBytes, HTTPResponse: rsp, } switch { case strings.Contains(rsp.Header.Get("Content-Type"), "json") && rsp.StatusCode == 200: - var dest map[string]interface{} + var dest FunctionResponse if err := json.Unmarshal(bodyBytes, &dest); err != nil { return nil, err } @@ -35561,22 +36419,22 @@ func ParseRetrieveDeliveryResult(rsp *http.Response) (*RetrieveDeliveryResult, e return response, nil } -// ParseAttemptsResult parses an HTTP response from a AttemptsWithResponse call -func ParseAttemptsResult(rsp *http.Response) (*AttemptsResult, error) { +// ParseFunctionRuntimeHealthResult parses an HTTP response from a FunctionRuntimeHealthWithResponse call +func ParseFunctionRuntimeHealthResult(rsp *http.Response) (*FunctionRuntimeHealthResult, error) { bodyBytes, err := io.ReadAll(rsp.Body) defer func() { _ = rsp.Body.Close() }() if err != nil { return nil, err } - response := &AttemptsResult{ + response := &FunctionRuntimeHealthResult{ Body: bodyBytes, HTTPResponse: rsp, } switch { case strings.Contains(rsp.Header.Get("Content-Type"), "json") && rsp.StatusCode == 200: - var dest map[string]interface{} + var dest FunctionRuntimeHealthResponse if err := json.Unmarshal(bodyBytes, &dest); err != nil { return nil, err } @@ -35594,26 +36452,26 @@ func ParseAttemptsResult(rsp *http.Response) (*AttemptsResult, error) { return response, nil } -// ParseRetryResult parses an HTTP response from a RetryWithResponse call -func ParseRetryResult(rsp *http.Response) (*RetryResult, error) { +// ParseFunctionDeleteResult parses an HTTP response from a FunctionDeleteWithResponse call +func ParseFunctionDeleteResult(rsp *http.Response) (*FunctionDeleteResult, error) { bodyBytes, err := io.ReadAll(rsp.Body) defer func() { _ = rsp.Body.Close() }() if err != nil { return nil, err } - response := &RetryResult{ + response := &FunctionDeleteResult{ Body: bodyBytes, HTTPResponse: rsp, } switch { - case strings.Contains(rsp.Header.Get("Content-Type"), "json") && rsp.StatusCode == 202: - var dest map[string]interface{} + case strings.Contains(rsp.Header.Get("Content-Type"), "json") && rsp.StatusCode == 200: + var dest DeleteFunctionResponse if err := json.Unmarshal(bodyBytes, &dest); err != nil { return nil, err } - response.JSON202 = &dest + response.JSON200 = &dest case strings.Contains(rsp.Header.Get("Content-Type"), "json") && rsp.StatusCode == 422: var dest HTTPValidationError @@ -35627,22 +36485,22 @@ func ParseRetryResult(rsp *http.Response) (*RetryResult, error) { return response, nil } -// ParseYoutubeEndpointResult parses an HTTP response from a YoutubeEndpointWithResponse call -func ParseYoutubeEndpointResult(rsp *http.Response) (*YoutubeEndpointResult, error) { +// ParseFunctionDownloadUrlResult parses an HTTP response from a FunctionDownloadUrlWithResponse call +func ParseFunctionDownloadUrlResult(rsp *http.Response) (*FunctionDownloadUrlResult, error) { bodyBytes, err := io.ReadAll(rsp.Body) defer func() { _ = rsp.Body.Close() }() if err != nil { return nil, err } - response := &YoutubeEndpointResult{ + response := &FunctionDownloadUrlResult{ Body: bodyBytes, HTTPResponse: rsp, } switch { case strings.Contains(rsp.Header.Get("Content-Type"), "json") && rsp.StatusCode == 200: - var dest YouTubeResult + var dest FunctionWithLinkResponse if err := json.Unmarshal(bodyBytes, &dest); err != nil { return nil, err } @@ -35660,22 +36518,22 @@ func ParseYoutubeEndpointResult(rsp *http.Response) (*YoutubeEndpointResult, err return response, nil } -// ParseListFunctionsResult parses an HTTP response from a ListFunctionsWithResponse call -func ParseListFunctionsResult(rsp *http.Response) (*ListFunctionsResult, error) { +// ParseFunctionMetadataUpdateResult parses an HTTP response from a FunctionMetadataUpdateWithResponse call +func ParseFunctionMetadataUpdateResult(rsp *http.Response) (*FunctionMetadataUpdateResult, error) { bodyBytes, err := io.ReadAll(rsp.Body) defer func() { _ = rsp.Body.Close() }() if err != nil { return nil, err } - response := &ListFunctionsResult{ + response := &FunctionMetadataUpdateResult{ Body: bodyBytes, HTTPResponse: rsp, } switch { case strings.Contains(rsp.Header.Get("Content-Type"), "json") && rsp.StatusCode == 200: - var dest PaginatedResponseFunctionListItemResponse + var dest FunctionResponse if err := json.Unmarshal(bodyBytes, &dest); err != nil { return nil, err } @@ -35693,15 +36551,15 @@ func ParseListFunctionsResult(rsp *http.Response) (*ListFunctionsResult, error) return response, nil } -// ParseFunctionCreateResult parses an HTTP response from a FunctionCreateWithResponse call -func ParseFunctionCreateResult(rsp *http.Response) (*FunctionCreateResult, error) { +// ParseFunctionUpdateResult parses an HTTP response from a FunctionUpdateWithResponse call +func ParseFunctionUpdateResult(rsp *http.Response) (*FunctionUpdateResult, error) { bodyBytes, err := io.ReadAll(rsp.Body) defer func() { _ = rsp.Body.Close() }() if err != nil { return nil, err } - response := &FunctionCreateResult{ + response := &FunctionUpdateResult{ Body: bodyBytes, HTTPResponse: rsp, } @@ -35726,22 +36584,22 @@ func ParseFunctionCreateResult(rsp *http.Response) (*FunctionCreateResult, error return response, nil } -// ParseFunctionRuntimeHealthResult parses an HTTP response from a FunctionRuntimeHealthWithResponse call -func ParseFunctionRuntimeHealthResult(rsp *http.Response) (*FunctionRuntimeHealthResult, error) { +// ParseFunctionForkResult parses an HTTP response from a FunctionForkWithResponse call +func ParseFunctionForkResult(rsp *http.Response) (*FunctionForkResult, error) { bodyBytes, err := io.ReadAll(rsp.Body) defer func() { _ = rsp.Body.Close() }() if err != nil { return nil, err } - response := &FunctionRuntimeHealthResult{ + response := &FunctionForkResult{ Body: bodyBytes, HTTPResponse: rsp, } switch { case strings.Contains(rsp.Header.Get("Content-Type"), "json") && rsp.StatusCode == 200: - var dest FunctionRuntimeHealthResponse + var dest FunctionResponse if err := json.Unmarshal(bodyBytes, &dest); err != nil { return nil, err } @@ -35759,22 +36617,22 @@ func ParseFunctionRuntimeHealthResult(rsp *http.Response) (*FunctionRuntimeHealt return response, nil } -// ParseFunctionDeleteResult parses an HTTP response from a FunctionDeleteWithResponse call -func ParseFunctionDeleteResult(rsp *http.Response) (*FunctionDeleteResult, error) { +// ParseFunctionRollbackResult parses an HTTP response from a FunctionRollbackWithResponse call +func ParseFunctionRollbackResult(rsp *http.Response) (*FunctionRollbackResult, error) { bodyBytes, err := io.ReadAll(rsp.Body) defer func() { _ = rsp.Body.Close() }() if err != nil { return nil, err } - response := &FunctionDeleteResult{ + response := &FunctionRollbackResult{ Body: bodyBytes, HTTPResponse: rsp, } switch { case strings.Contains(rsp.Header.Get("Content-Type"), "json") && rsp.StatusCode == 200: - var dest DeleteFunctionResponse + var dest FunctionResponse if err := json.Unmarshal(bodyBytes, &dest); err != nil { return nil, err } @@ -35792,22 +36650,22 @@ func ParseFunctionDeleteResult(rsp *http.Response) (*FunctionDeleteResult, error return response, nil } -// ParseFunctionDownloadUrlResult parses an HTTP response from a FunctionDownloadUrlWithResponse call -func ParseFunctionDownloadUrlResult(rsp *http.Response) (*FunctionDownloadUrlResult, error) { +// ParseFunctionConditionalRollbackResult parses an HTTP response from a FunctionConditionalRollbackWithResponse call +func ParseFunctionConditionalRollbackResult(rsp *http.Response) (*FunctionConditionalRollbackResult, error) { bodyBytes, err := io.ReadAll(rsp.Body) defer func() { _ = rsp.Body.Close() }() if err != nil { return nil, err } - response := &FunctionDownloadUrlResult{ + response := &FunctionConditionalRollbackResult{ Body: bodyBytes, HTTPResponse: rsp, } switch { case strings.Contains(rsp.Header.Get("Content-Type"), "json") && rsp.StatusCode == 200: - var dest FunctionWithLinkResponse + var dest FunctionResponse if err := json.Unmarshal(bodyBytes, &dest); err != nil { return nil, err } @@ -35825,22 +36683,22 @@ func ParseFunctionDownloadUrlResult(rsp *http.Response) (*FunctionDownloadUrlRes return response, nil } -// ParseFunctionMetadataUpdateResult parses an HTTP response from a FunctionMetadataUpdateWithResponse call -func ParseFunctionMetadataUpdateResult(rsp *http.Response) (*FunctionMetadataUpdateResult, error) { +// ParseListFunctionRunsByFunctionIdResult parses an HTTP response from a ListFunctionRunsByFunctionIdWithResponse call +func ParseListFunctionRunsByFunctionIdResult(rsp *http.Response) (*ListFunctionRunsByFunctionIdResult, error) { bodyBytes, err := io.ReadAll(rsp.Body) defer func() { _ = rsp.Body.Close() }() if err != nil { return nil, err } - response := &FunctionMetadataUpdateResult{ + response := &ListFunctionRunsByFunctionIdResult{ Body: bodyBytes, HTTPResponse: rsp, } switch { case strings.Contains(rsp.Header.Get("Content-Type"), "json") && rsp.StatusCode == 200: - var dest FunctionResponse + var dest PaginatedResponseFunctionRunListItemResponse if err := json.Unmarshal(bodyBytes, &dest); err != nil { return nil, err } @@ -35858,22 +36716,22 @@ func ParseFunctionMetadataUpdateResult(rsp *http.Response) (*FunctionMetadataUpd return response, nil } -// ParseFunctionUpdateResult parses an HTTP response from a FunctionUpdateWithResponse call -func ParseFunctionUpdateResult(rsp *http.Response) (*FunctionUpdateResult, error) { +// ParseFunctionRunStartResult parses an HTTP response from a FunctionRunStartWithResponse call +func ParseFunctionRunStartResult(rsp *http.Response) (*FunctionRunStartResult, error) { bodyBytes, err := io.ReadAll(rsp.Body) defer func() { _ = rsp.Body.Close() }() if err != nil { return nil, err } - response := &FunctionUpdateResult{ + response := &FunctionRunStartResult{ Body: bodyBytes, HTTPResponse: rsp, } switch { case strings.Contains(rsp.Header.Get("Content-Type"), "json") && rsp.StatusCode == 200: - var dest FunctionResponse + var dest interface{} if err := json.Unmarshal(bodyBytes, &dest); err != nil { return nil, err } @@ -35891,22 +36749,22 @@ func ParseFunctionUpdateResult(rsp *http.Response) (*FunctionUpdateResult, error return response, nil } -// ParseFunctionForkResult parses an HTTP response from a FunctionForkWithResponse call -func ParseFunctionForkResult(rsp *http.Response) (*FunctionForkResult, error) { +// ParseFunctionRunStopResult parses an HTTP response from a FunctionRunStopWithResponse call +func ParseFunctionRunStopResult(rsp *http.Response) (*FunctionRunStopResult, error) { bodyBytes, err := io.ReadAll(rsp.Body) defer func() { _ = rsp.Body.Close() }() if err != nil { return nil, err } - response := &FunctionForkResult{ + response := &FunctionRunStopResult{ Body: bodyBytes, HTTPResponse: rsp, } switch { case strings.Contains(rsp.Header.Get("Content-Type"), "json") && rsp.StatusCode == 200: - var dest FunctionResponse + var dest UpdateFunctionRunResponse if err := json.Unmarshal(bodyBytes, &dest); err != nil { return nil, err } @@ -35924,22 +36782,22 @@ func ParseFunctionForkResult(rsp *http.Response) (*FunctionForkResult, error) { return response, nil } -// ParseFunctionRollbackResult parses an HTTP response from a FunctionRollbackWithResponse call -func ParseFunctionRollbackResult(rsp *http.Response) (*FunctionRollbackResult, error) { +// ParseFunctionRunGetMetadataResult parses an HTTP response from a FunctionRunGetMetadataWithResponse call +func ParseFunctionRunGetMetadataResult(rsp *http.Response) (*FunctionRunGetMetadataResult, error) { bodyBytes, err := io.ReadAll(rsp.Body) defer func() { _ = rsp.Body.Close() }() if err != nil { return nil, err } - response := &FunctionRollbackResult{ + response := &FunctionRunGetMetadataResult{ Body: bodyBytes, HTTPResponse: rsp, } switch { case strings.Contains(rsp.Header.Get("Content-Type"), "json") && rsp.StatusCode == 200: - var dest FunctionResponse + var dest GetFunctionRunResponse if err := json.Unmarshal(bodyBytes, &dest); err != nil { return nil, err } @@ -35957,22 +36815,22 @@ func ParseFunctionRollbackResult(rsp *http.Response) (*FunctionRollbackResult, e return response, nil } -// ParseFunctionConditionalRollbackResult parses an HTTP response from a FunctionConditionalRollbackWithResponse call -func ParseFunctionConditionalRollbackResult(rsp *http.Response) (*FunctionConditionalRollbackResult, error) { +// ParseFunctionRunUpdateMetadataResult parses an HTTP response from a FunctionRunUpdateMetadataWithResponse call +func ParseFunctionRunUpdateMetadataResult(rsp *http.Response) (*FunctionRunUpdateMetadataResult, error) { bodyBytes, err := io.ReadAll(rsp.Body) defer func() { _ = rsp.Body.Close() }() if err != nil { return nil, err } - response := &FunctionConditionalRollbackResult{ + response := &FunctionRunUpdateMetadataResult{ Body: bodyBytes, HTTPResponse: rsp, } switch { case strings.Contains(rsp.Header.Get("Content-Type"), "json") && rsp.StatusCode == 200: - var dest FunctionResponse + var dest UpdateFunctionRunResponse if err := json.Unmarshal(bodyBytes, &dest); err != nil { return nil, err } @@ -35990,22 +36848,22 @@ func ParseFunctionConditionalRollbackResult(rsp *http.Response) (*FunctionCondit return response, nil } -// ParseListFunctionRunsByFunctionIdResult parses an HTTP response from a ListFunctionRunsByFunctionIdWithResponse call -func ParseListFunctionRunsByFunctionIdResult(rsp *http.Response) (*ListFunctionRunsByFunctionIdResult, error) { +// ParseDownloadRunPayloadResult parses an HTTP response from a DownloadRunPayloadWithResponse call +func ParseDownloadRunPayloadResult(rsp *http.Response) (*DownloadRunPayloadResult, error) { bodyBytes, err := io.ReadAll(rsp.Body) defer func() { _ = rsp.Body.Close() }() if err != nil { return nil, err } - response := &ListFunctionRunsByFunctionIdResult{ + response := &DownloadRunPayloadResult{ Body: bodyBytes, HTTPResponse: rsp, } switch { case strings.Contains(rsp.Header.Get("Content-Type"), "json") && rsp.StatusCode == 200: - var dest PaginatedResponseFunctionRunListItemResponse + var dest interface{} if err := json.Unmarshal(bodyBytes, &dest); err != nil { return nil, err } @@ -36023,22 +36881,22 @@ func ParseListFunctionRunsByFunctionIdResult(rsp *http.Response) (*ListFunctionR return response, nil } -// ParseFunctionRunStartResult parses an HTTP response from a FunctionRunStartWithResponse call -func ParseFunctionRunStartResult(rsp *http.Response) (*FunctionRunStartResult, error) { +// ParsePrepareRunPayloadUploadResult parses an HTTP response from a PrepareRunPayloadUploadWithResponse call +func ParsePrepareRunPayloadUploadResult(rsp *http.Response) (*PrepareRunPayloadUploadResult, error) { bodyBytes, err := io.ReadAll(rsp.Body) defer func() { _ = rsp.Body.Close() }() if err != nil { return nil, err } - response := &FunctionRunStartResult{ + response := &PrepareRunPayloadUploadResult{ Body: bodyBytes, HTTPResponse: rsp, } switch { case strings.Contains(rsp.Header.Get("Content-Type"), "json") && rsp.StatusCode == 200: - var dest interface{} + var dest RunPayloadUploadResponse if err := json.Unmarshal(bodyBytes, &dest); err != nil { return nil, err } @@ -36056,22 +36914,22 @@ func ParseFunctionRunStartResult(rsp *http.Response) (*FunctionRunStartResult, e return response, nil } -// ParseFunctionRunStopResult parses an HTTP response from a FunctionRunStopWithResponse call -func ParseFunctionRunStopResult(rsp *http.Response) (*FunctionRunStopResult, error) { +// ParseFunctionScheduleDeleteResult parses an HTTP response from a FunctionScheduleDeleteWithResponse call +func ParseFunctionScheduleDeleteResult(rsp *http.Response) (*FunctionScheduleDeleteResult, error) { bodyBytes, err := io.ReadAll(rsp.Body) defer func() { _ = rsp.Body.Close() }() if err != nil { return nil, err } - response := &FunctionRunStopResult{ + response := &FunctionScheduleDeleteResult{ Body: bodyBytes, HTTPResponse: rsp, } switch { case strings.Contains(rsp.Header.Get("Content-Type"), "json") && rsp.StatusCode == 200: - var dest UpdateFunctionRunResponse + var dest ScheduleDeleteResponse if err := json.Unmarshal(bodyBytes, &dest); err != nil { return nil, err } @@ -36089,22 +36947,22 @@ func ParseFunctionRunStopResult(rsp *http.Response) (*FunctionRunStopResult, err return response, nil } -// ParseFunctionRunGetMetadataResult parses an HTTP response from a FunctionRunGetMetadataWithResponse call -func ParseFunctionRunGetMetadataResult(rsp *http.Response) (*FunctionRunGetMetadataResult, error) { +// ParseFunctionScheduleSetResult parses an HTTP response from a FunctionScheduleSetWithResponse call +func ParseFunctionScheduleSetResult(rsp *http.Response) (*FunctionScheduleSetResult, error) { bodyBytes, err := io.ReadAll(rsp.Body) defer func() { _ = rsp.Body.Close() }() if err != nil { return nil, err } - response := &FunctionRunGetMetadataResult{ + response := &FunctionScheduleSetResult{ Body: bodyBytes, HTTPResponse: rsp, } switch { case strings.Contains(rsp.Header.Get("Content-Type"), "json") && rsp.StatusCode == 200: - var dest GetFunctionRunResponse + var dest ScheduleResponse if err := json.Unmarshal(bodyBytes, &dest); err != nil { return nil, err } @@ -36122,22 +36980,22 @@ func ParseFunctionRunGetMetadataResult(rsp *http.Response) (*FunctionRunGetMetad return response, nil } -// ParseFunctionRunUpdateMetadataResult parses an HTTP response from a FunctionRunUpdateMetadataWithResponse call -func ParseFunctionRunUpdateMetadataResult(rsp *http.Response) (*FunctionRunUpdateMetadataResult, error) { +// ParseFunctionSchedulesListResult parses an HTTP response from a FunctionSchedulesListWithResponse call +func ParseFunctionSchedulesListResult(rsp *http.Response) (*FunctionSchedulesListResult, error) { bodyBytes, err := io.ReadAll(rsp.Body) defer func() { _ = rsp.Body.Close() }() if err != nil { return nil, err } - response := &FunctionRunUpdateMetadataResult{ + response := &FunctionSchedulesListResult{ Body: bodyBytes, HTTPResponse: rsp, } switch { case strings.Contains(rsp.Header.Get("Content-Type"), "json") && rsp.StatusCode == 200: - var dest UpdateFunctionRunResponse + var dest FunctionScheduleListResponse if err := json.Unmarshal(bodyBytes, &dest); err != nil { return nil, err } @@ -36155,22 +37013,22 @@ func ParseFunctionRunUpdateMetadataResult(rsp *http.Response) (*FunctionRunUpdat return response, nil } -// ParseDownloadRunPayloadResult parses an HTTP response from a DownloadRunPayloadWithResponse call -func ParseDownloadRunPayloadResult(rsp *http.Response) (*DownloadRunPayloadResult, error) { +// ParseFunctionSchedulesAddResult parses an HTTP response from a FunctionSchedulesAddWithResponse call +func ParseFunctionSchedulesAddResult(rsp *http.Response) (*FunctionSchedulesAddResult, error) { bodyBytes, err := io.ReadAll(rsp.Body) defer func() { _ = rsp.Body.Close() }() if err != nil { return nil, err } - response := &DownloadRunPayloadResult{ + response := &FunctionSchedulesAddResult{ Body: bodyBytes, HTTPResponse: rsp, } switch { case strings.Contains(rsp.Header.Get("Content-Type"), "json") && rsp.StatusCode == 200: - var dest interface{} + var dest FunctionSchedule if err := json.Unmarshal(bodyBytes, &dest); err != nil { return nil, err } @@ -36188,22 +37046,22 @@ func ParseDownloadRunPayloadResult(rsp *http.Response) (*DownloadRunPayloadResul return response, nil } -// ParsePrepareRunPayloadUploadResult parses an HTTP response from a PrepareRunPayloadUploadWithResponse call -func ParsePrepareRunPayloadUploadResult(rsp *http.Response) (*PrepareRunPayloadUploadResult, error) { +// ParseFunctionSchedulesResumeResult parses an HTTP response from a FunctionSchedulesResumeWithResponse call +func ParseFunctionSchedulesResumeResult(rsp *http.Response) (*FunctionSchedulesResumeResult, error) { bodyBytes, err := io.ReadAll(rsp.Body) defer func() { _ = rsp.Body.Close() }() if err != nil { return nil, err } - response := &PrepareRunPayloadUploadResult{ + response := &FunctionSchedulesResumeResult{ Body: bodyBytes, HTTPResponse: rsp, } switch { case strings.Contains(rsp.Header.Get("Content-Type"), "json") && rsp.StatusCode == 200: - var dest RunPayloadUploadResponse + var dest FunctionScheduleListResponse if err := json.Unmarshal(bodyBytes, &dest); err != nil { return nil, err } @@ -36221,15 +37079,15 @@ func ParsePrepareRunPayloadUploadResult(rsp *http.Response) (*PrepareRunPayloadU return response, nil } -// ParseFunctionScheduleDeleteResult parses an HTTP response from a FunctionScheduleDeleteWithResponse call -func ParseFunctionScheduleDeleteResult(rsp *http.Response) (*FunctionScheduleDeleteResult, error) { +// ParseFunctionSchedulesRemoveResult parses an HTTP response from a FunctionSchedulesRemoveWithResponse call +func ParseFunctionSchedulesRemoveResult(rsp *http.Response) (*FunctionSchedulesRemoveResult, error) { bodyBytes, err := io.ReadAll(rsp.Body) defer func() { _ = rsp.Body.Close() }() if err != nil { return nil, err } - response := &FunctionScheduleDeleteResult{ + response := &FunctionSchedulesRemoveResult{ Body: bodyBytes, HTTPResponse: rsp, } @@ -36254,22 +37112,22 @@ func ParseFunctionScheduleDeleteResult(rsp *http.Response) (*FunctionScheduleDel return response, nil } -// ParseFunctionScheduleSetResult parses an HTTP response from a FunctionScheduleSetWithResponse call -func ParseFunctionScheduleSetResult(rsp *http.Response) (*FunctionScheduleSetResult, error) { +// ParseFunctionSchedulesUpdateResult parses an HTTP response from a FunctionSchedulesUpdateWithResponse call +func ParseFunctionSchedulesUpdateResult(rsp *http.Response) (*FunctionSchedulesUpdateResult, error) { bodyBytes, err := io.ReadAll(rsp.Body) defer func() { _ = rsp.Body.Close() }() if err != nil { return nil, err } - response := &FunctionScheduleSetResult{ + response := &FunctionSchedulesUpdateResult{ Body: bodyBytes, HTTPResponse: rsp, } switch { case strings.Contains(rsp.Header.Get("Content-Type"), "json") && rsp.StatusCode == 200: - var dest ScheduleResponse + var dest FunctionSchedule if err := json.Unmarshal(bodyBytes, &dest); err != nil { return nil, err } diff --git a/internal/cmd/function_schedules.go b/internal/cmd/function_schedules.go new file mode 100644 index 0000000..8e2bd23 --- /dev/null +++ b/internal/cmd/function_schedules.go @@ -0,0 +1,299 @@ +package cmd + +import ( + "context" + "encoding/json" + "errors" + "fmt" + "strings" + + "github.com/spf13/cobra" + + "github.com/nottelabs/notte-cli/internal/api" +) + +var ( + functionScheduleVariables []string // Variables as key=value pairs + functionScheduleVariablesJSON string // Variables as JSON string +) + +var functionSchedulesCmd = &cobra.Command{ + Use: "schedules", + Short: "Manage the function's schedules, each with its own variables", + Long: `A function can run on several schedules, each passing its own variables to +its runs. Pausing applies to all of them: "resume" restarts a paused function's +schedules without changing them. + +"notte functions schedule" replaces every schedule with one, and +"notte functions unschedule" removes them all.`, +} + +var functionSchedulesListCmd = &cobra.Command{ + Use: "list", + Short: "List the function's schedules", + Args: cobra.NoArgs, + RunE: runFunctionSchedulesList, +} + +var functionSchedulesAddCmd = &cobra.Command{ + Use: "add", + Short: "Add a schedule to the function", + Args: cobra.NoArgs, + Example: ` # Every weekday at 9:00 UTC, for Paris + notte functions schedules add --cron "0 9 ? * MON-FRI *" --var city=paris + + # Every day at 18:00 UTC, with JSON variables + notte functions schedules add --cron "0 18 ? * * *" --vars '{"city": "tokyo", "limit": 5}'`, + RunE: runFunctionSchedulesAdd, +} + +var functionSchedulesUpdateCmd = &cobra.Command{ + Use: "update ", + Short: "Change a schedule's cron expression or variables", + Long: `Change a schedule's cron expression or variables. What is not given keeps its +current value: --cron alone keeps the variables, and --var or --vars alone keeps +the cron expression. Given variables replace all of the schedule's variables.`, + Args: cobra.ExactArgs(1), + RunE: runFunctionSchedulesUpdate, +} + +var functionSchedulesRemoveCmd = &cobra.Command{ + Use: "remove ", + Aliases: []string{"rm"}, + Short: "Remove one schedule from the function", + Args: cobra.ExactArgs(1), + RunE: runFunctionSchedulesRemove, +} + +var functionSchedulesResumeCmd = &cobra.Command{ + Use: "resume", + Short: "Resume the function's paused schedules without changing them", + Args: cobra.NoArgs, + RunE: runFunctionSchedulesResume, +} + +func init() { + functionsCmd.AddCommand(functionSchedulesCmd) + for _, c := range []*cobra.Command{ + functionSchedulesListCmd, functionSchedulesAddCmd, functionSchedulesUpdateCmd, + functionSchedulesRemoveCmd, functionSchedulesResumeCmd, + } { + functionSchedulesCmd.AddCommand(c) + c.Flags().StringVar(&functionID, "function-id", "", "Function ID (uses current function if not specified)") + } + + RegisterFunctionSchedulesAddFlags(functionSchedulesAddCmd) + _ = functionSchedulesAddCmd.MarkFlagRequired("cron") + RegisterFunctionSchedulesUpdateFlags(functionSchedulesUpdateCmd) + for _, c := range []*cobra.Command{functionSchedulesAddCmd, functionSchedulesUpdateCmd} { + c.Flags().StringArrayVar(&functionScheduleVariables, "var", []string{}, "Variable as key=value pair (can be used multiple times)") + c.Flags().StringVar(&functionScheduleVariablesJSON, "vars", "", "Variables as JSON object string") + } +} + +// parseVariables reads --vars (a JSON object), then --var key=value pairs, +// which override it. +func parseVariables(variablesJSON string, pairs []string) (map[string]interface{}, error) { + variables := make(map[string]interface{}) + if variablesJSON != "" { + if err := json.Unmarshal([]byte(variablesJSON), &variables); err != nil { + return nil, fmt.Errorf("failed to parse --vars JSON: %w", err) + } + } + if variables == nil { + return nil, errors.New("--vars must be a JSON object") + } + for _, kv := range pairs { + parts := strings.SplitN(kv, "=", 2) + if len(parts) != 2 { + return nil, fmt.Errorf("invalid variable format %q: expected key=value", kv) + } + variables[parts[0]] = parts[1] + } + return variables, nil +} + +func scheduleVariablesGiven(cmd *cobra.Command) bool { + return cmd.Flags().Changed("var") || cmd.Flags().Changed("vars") +} + +func listFunctionSchedules(ctx context.Context, client *api.NotteClient) (*api.FunctionScheduleListResponse, error) { + resp, err := client.Client().FunctionSchedulesListWithResponse(ctx, functionID, &api.FunctionSchedulesListParams{}) + if err != nil { + return nil, fmt.Errorf("API request failed: %w", err) + } + if err := HandleAPIResponse(resp.HTTPResponse, resp.Body); err != nil { + return nil, err + } + if resp.JSON200 == nil { + return &api.FunctionScheduleListResponse{}, nil + } + return resp.JSON200, nil +} + +func runFunctionSchedulesList(cmd *cobra.Command, args []string) error { + if err := RequireFunctionID(); err != nil { + return err + } + client, err := GetClient() + if err != nil { + return err + } + ctx, cancel := GetContextWithTimeout(cmd.Context()) + defer cancel() + + list, err := listFunctionSchedules(ctx, client) + if err != nil { + return err + } + if printed, err := PrintListOrEmpty(list.Schedules, "No schedules found."); err != nil { + return err + } else if printed { + return nil + } + return GetFormatter().Print(list) +} + +func runFunctionSchedulesAdd(cmd *cobra.Command, args []string) error { + if err := RequireFunctionID(); err != nil { + return err + } + body, err := BuildFunctionSchedulesAddRequest(cmd) + if err != nil { + return err + } + // `variables` is required by the API; no variables is an empty object. + variables, err := parseVariables(functionScheduleVariablesJSON, functionScheduleVariables) + if err != nil { + return err + } + body.Variables = &variables + + client, err := GetClient() + if err != nil { + return err + } + ctx, cancel := GetContextWithTimeout(cmd.Context()) + defer cancel() + + resp, err := client.Client().FunctionSchedulesAddWithResponse(ctx, functionID, &api.FunctionSchedulesAddParams{}, *body) + if err != nil { + return fmt.Errorf("API request failed: %w", err) + } + if err := HandleAPIResponse(resp.HTTPResponse, resp.Body); err != nil { + return err + } + return GetFormatter().Print(resp.JSON200) +} + +func runFunctionSchedulesUpdate(cmd *cobra.Command, args []string) error { + if err := RequireFunctionID(); err != nil { + return err + } + scheduleID := args[0] + if !cmd.Flags().Changed("cron") && !scheduleVariablesGiven(cmd) { + return errors.New("nothing to update: pass --cron, --var or --vars") + } + body, err := BuildFunctionSchedulesUpdateRequest(cmd) + if err != nil { + return err + } + + client, err := GetClient() + if err != nil { + return err + } + ctx, cancel := GetContextWithTimeout(cmd.Context()) + defer cancel() + + // The API replaces both the cron expression and the variables: fill in + // the current value of whichever was not given. + if !cmd.Flags().Changed("cron") || !scheduleVariablesGiven(cmd) { + list, err := listFunctionSchedules(ctx, client) + if err != nil { + return err + } + var current *api.FunctionSchedule + for i := range list.Schedules { + if list.Schedules[i].ScheduleId == scheduleID { + current = &list.Schedules[i] + } + } + if current == nil { + return fmt.Errorf("schedule %s not found on function %s", scheduleID, functionID) + } + if !cmd.Flags().Changed("cron") { + body.Cron = current.Cron + } + if !scheduleVariablesGiven(cmd) { + body.Variables = current.Variables + } + } + if scheduleVariablesGiven(cmd) { + variables, err := parseVariables(functionScheduleVariablesJSON, functionScheduleVariables) + if err != nil { + return err + } + body.Variables = &variables + } + if body.Variables == nil { + empty := make(map[string]interface{}) + body.Variables = &empty + } + + resp, err := client.Client().FunctionSchedulesUpdateWithResponse(ctx, functionID, scheduleID, &api.FunctionSchedulesUpdateParams{}, *body) + if err != nil { + return fmt.Errorf("API request failed: %w", err) + } + if err := HandleAPIResponse(resp.HTTPResponse, resp.Body); err != nil { + return err + } + return GetFormatter().Print(resp.JSON200) +} + +func runFunctionSchedulesRemove(cmd *cobra.Command, args []string) error { + if err := RequireFunctionID(); err != nil { + return err + } + scheduleID := args[0] + client, err := GetClient() + if err != nil { + return err + } + ctx, cancel := GetContextWithTimeout(cmd.Context()) + defer cancel() + + resp, err := client.Client().FunctionSchedulesRemoveWithResponse(ctx, functionID, scheduleID, &api.FunctionSchedulesRemoveParams{}) + if err != nil { + return fmt.Errorf("API request failed: %w", err) + } + if err := HandleAPIResponse(resp.HTTPResponse, resp.Body); err != nil { + return err + } + return PrintResult(fmt.Sprintf("Schedule %s removed from function %s.", scheduleID, functionID), map[string]any{ + "id": functionID, + "schedule_id": scheduleID, + "status": "removed", + }) +} + +func runFunctionSchedulesResume(cmd *cobra.Command, args []string) error { + if err := RequireFunctionID(); err != nil { + return err + } + client, err := GetClient() + if err != nil { + return err + } + ctx, cancel := GetContextWithTimeout(cmd.Context()) + defer cancel() + + resp, err := client.Client().FunctionSchedulesResumeWithResponse(ctx, functionID, &api.FunctionSchedulesResumeParams{}) + if err != nil { + return fmt.Errorf("API request failed: %w", err) + } + if err := HandleAPIResponse(resp.HTTPResponse, resp.Body); err != nil { + return err + } + return GetFormatter().Print(resp.JSON200) +} diff --git a/internal/cmd/function_schedules_test.go b/internal/cmd/function_schedules_test.go new file mode 100644 index 0000000..e2d1cd3 --- /dev/null +++ b/internal/cmd/function_schedules_test.go @@ -0,0 +1,242 @@ +package cmd + +import ( + "context" + "encoding/json" + "strings" + "testing" + + "github.com/spf13/cobra" + + "github.com/nottelabs/notte-cli/internal/testutil" +) + +const schedulesListJSON = `{"schedules":[` + + `{"schedule_id":"` + functionIDTest + `","cron":"0 9 ? * MON-FRI *","variables":{"city":"paris"}},` + + `{"schedule_id":"s2","cron":"0 17 ? * MON-FRI *","variables":{"city":"tokyo","limit":5}}` + + `],"state":"enabled","paused_reason":null}` + +// scheduleCommand is a command with the flags of add or update, set from flags. +func scheduleCommand(t *testing.T, register func(*cobra.Command), flags map[string][]string) *cobra.Command { + t.Helper() + origVars, origJSON := functionScheduleVariables, functionScheduleVariablesJSON + origAdd, origUpdate := FunctionSchedulesAddCron, FunctionSchedulesUpdateCron + functionScheduleVariables, functionScheduleVariablesJSON = []string{}, "" + t.Cleanup(func() { + functionScheduleVariables, functionScheduleVariablesJSON = origVars, origJSON + FunctionSchedulesAddCron, FunctionSchedulesUpdateCron = origAdd, origUpdate + }) + cmd := &cobra.Command{} + cmd.SetContext(context.Background()) + register(cmd) + cmd.Flags().StringArrayVar(&functionScheduleVariables, "var", []string{}, "") + cmd.Flags().StringVar(&functionScheduleVariablesJSON, "vars", "", "") + for name, values := range flags { + for _, v := range values { + if err := cmd.Flags().Set(name, v); err != nil { + t.Fatal(err) + } + } + } + return cmd +} + +func sentBody(t *testing.T, server *testutil.MockServer, path, method string) map[string]any { + t.Helper() + for _, r := range server.Requests(path) { + if r.Method == method { + var body map[string]any + if err := json.Unmarshal([]byte(r.Body), &body); err != nil { + t.Fatalf("request body %q: %v", r.Body, err) + } + return body + } + } + t.Fatalf("no %s %s request", method, path) + return nil +} + +func TestRunFunctionSchedulesAddSendsCronAndVariables(t *testing.T) { + server := setupFunctionTest(t) + path := "/functions/" + functionIDTest + "/schedules" + server.AddResponse(path, 200, `{"schedule_id":"s3","cron":"0 6 1 * ? *","variables":{"city":"berlin","limit":"3"}}`) + cmd := scheduleCommand(t, RegisterFunctionSchedulesAddFlags, map[string][]string{ + "cron": {"0 6 1 * ? *"}, "vars": {`{"city": "rome", "limit": 3}`}, "var": {"city=berlin"}, + }) + + stdout, _ := testutil.CaptureOutput(func() { + if err := runFunctionSchedulesAdd(cmd, nil); err != nil { + t.Fatalf("unexpected error: %v", err) + } + }) + + body := sentBody(t, server, path, "POST") + want := map[string]any{"cron": "0 6 1 * ? *", "variables": map[string]any{"city": "berlin", "limit": float64(3)}} + if got, _ := json.Marshal(body); string(got) != mustJSON(t, want) { + t.Errorf("body = %s, want %s", got, mustJSON(t, want)) + } + if !strings.Contains(stdout, "s3") { + t.Errorf("expected the new schedule in the output, got %q", stdout) + } +} + +func TestRunFunctionSchedulesAddWithoutVariablesSendsAnEmptyObject(t *testing.T) { + server := setupFunctionTest(t) + path := "/functions/" + functionIDTest + "/schedules" + server.AddResponse(path, 200, `{"schedule_id":"s3","cron":"rate(1 hour)","variables":{}}`) + cmd := scheduleCommand(t, RegisterFunctionSchedulesAddFlags, map[string][]string{"cron": {"rate(1 hour)"}}) + + _, _ = testutil.CaptureOutput(func() { + if err := runFunctionSchedulesAdd(cmd, nil); err != nil { + t.Fatalf("unexpected error: %v", err) + } + }) + + if got := sentBody(t, server, path, "POST")["variables"]; got == nil || len(got.(map[string]any)) != 0 { + t.Errorf("variables = %v, want {}", got) + } +} + +func TestRunFunctionSchedulesUpdateKeepsWhatIsNotGiven(t *testing.T) { + cases := []struct { + name string + flags map[string][]string + want map[string]any + }{ + {"cron only", map[string][]string{"cron": {"0 18 ? * MON-FRI *"}}, + map[string]any{"cron": "0 18 ? * MON-FRI *", "variables": map[string]any{"city": "tokyo", "limit": float64(5)}}}, + {"variables only", map[string][]string{"var": {"city=osaka"}}, + map[string]any{"cron": "0 17 ? * MON-FRI *", "variables": map[string]any{"city": "osaka"}}}, + {"both", map[string][]string{"cron": {"0 1 ? * * *"}, "vars": {`{"city": "kyoto"}`}}, + map[string]any{"cron": "0 1 ? * * *", "variables": map[string]any{"city": "kyoto"}}}, + } + for _, c := range cases { + t.Run(c.name, func(t *testing.T) { + server := setupFunctionTest(t) + server.AddResponse("/functions/"+functionIDTest+"/schedules", 200, schedulesListJSON) + path := "/functions/" + functionIDTest + "/schedules/s2" + server.AddResponse(path, 200, `{"schedule_id":"s2","cron":"0 18 ? * MON-FRI *","variables":{}}`) + cmd := scheduleCommand(t, RegisterFunctionSchedulesUpdateFlags, c.flags) + + _, _ = testutil.CaptureOutput(func() { + if err := runFunctionSchedulesUpdate(cmd, []string{"s2"}); err != nil { + t.Fatalf("unexpected error: %v", err) + } + }) + + body := sentBody(t, server, path, "PATCH") + if got, _ := json.Marshal(body); string(got) != mustJSON(t, c.want) { + t.Errorf("body = %s, want %s", got, mustJSON(t, c.want)) + } + }) + } +} + +func TestRunFunctionSchedulesUpdateRejectsNoChange(t *testing.T) { + setupFunctionTest(t) + cmd := scheduleCommand(t, RegisterFunctionSchedulesUpdateFlags, nil) + err := runFunctionSchedulesUpdate(cmd, []string{"s2"}) + if err == nil || !strings.Contains(err.Error(), "nothing to update") { + t.Fatalf("err = %v, want nothing to update", err) + } +} + +func TestRunFunctionSchedulesUpdateUnknownSchedule(t *testing.T) { + server := setupFunctionTest(t) + server.AddResponse("/functions/"+functionIDTest+"/schedules", 200, schedulesListJSON) + cmd := scheduleCommand(t, RegisterFunctionSchedulesUpdateFlags, map[string][]string{"cron": {"0 1 ? * * *"}}) + err := runFunctionSchedulesUpdate(cmd, []string{"missing"}) + if err == nil || !strings.Contains(err.Error(), "schedule missing not found") { + t.Fatalf("err = %v, want not found", err) + } +} + +func TestRunFunctionSchedulesRemove(t *testing.T) { + server := setupFunctionTest(t) + path := "/functions/" + functionIDTest + "/schedules/s2" + server.AddResponse(path, 200, `{"status":"DELETED"}`) + origFormat := outputFormat + outputFormat = "text" + t.Cleanup(func() { outputFormat = origFormat }) + cmd := &cobra.Command{} + cmd.SetContext(context.Background()) + + stdout, _ := testutil.CaptureOutput(func() { + if err := runFunctionSchedulesRemove(cmd, []string{"s2"}); err != nil { + t.Fatalf("unexpected error: %v", err) + } + }) + + if reqs := server.Requests(path); len(reqs) != 1 || reqs[0].Method != "DELETE" { + t.Fatalf("requests = %+v, want one DELETE", reqs) + } + if !strings.Contains(stdout, "Schedule s2 removed") { + t.Errorf("expected removal message, got %q", stdout) + } +} + +func TestRunFunctionSchedulesResume(t *testing.T) { + server := setupFunctionTest(t) + path := "/functions/" + functionIDTest + "/schedules/resume" + server.AddResponse(path, 200, schedulesListJSON) + cmd := &cobra.Command{} + cmd.SetContext(context.Background()) + + stdout, _ := testutil.CaptureOutput(func() { + if err := runFunctionSchedulesResume(cmd, nil); err != nil { + t.Fatalf("unexpected error: %v", err) + } + }) + + if reqs := server.Requests(path); len(reqs) != 1 || reqs[0].Method != "POST" { + t.Fatalf("requests = %+v, want one POST", reqs) + } + if !strings.Contains(stdout, "enabled") { + t.Errorf("expected the resumed state in the output, got %q", stdout) + } +} + +func TestRunFunctionSchedulesListEmpty(t *testing.T) { + server := setupFunctionTest(t) + server.AddResponse("/functions/"+functionIDTest+"/schedules", 200, `{"schedules":[],"state":null,"paused_reason":null}`) + origFormat := outputFormat + outputFormat = "text" + t.Cleanup(func() { outputFormat = origFormat }) + cmd := &cobra.Command{} + cmd.SetContext(context.Background()) + + stdout, _ := testutil.CaptureOutput(func() { + if err := runFunctionSchedulesList(cmd, nil); err != nil { + t.Fatalf("unexpected error: %v", err) + } + }) + + if !strings.Contains(stdout, "No schedules found.") { + t.Errorf("expected the empty message, got %q", stdout) + } +} + +func TestParseVariablesRejectsBadInput(t *testing.T) { + for _, c := range []struct { + json string + pairs []string + want string + }{ + {`[1]`, nil, "failed to parse --vars JSON"}, + {`null`, nil, "--vars must be a JSON object"}, + {"", []string{"novalue"}, "expected key=value"}, + } { + if _, err := parseVariables(c.json, c.pairs); err == nil || !strings.Contains(err.Error(), c.want) { + t.Errorf("parseVariables(%q, %v) = %v, want %q", c.json, c.pairs, err, c.want) + } + } +} + +func mustJSON(t *testing.T, v any) string { + t.Helper() + b, err := json.Marshal(v) + if err != nil { + t.Fatal(err) + } + return string(b) +} diff --git a/internal/cmd/functions.go b/internal/cmd/functions.go index 6d4e69c..0945649 100644 --- a/internal/cmd/functions.go +++ b/internal/cmd/functions.go @@ -770,26 +770,10 @@ func runFunctionRun(cmd *cobra.Command, args []string) error { return err } - // Parse variables - variables := make(map[string]interface{}) - - // First, parse JSON variables if provided - if functionRunVariablesJSON != "" { - if err := json.Unmarshal([]byte(functionRunVariablesJSON), &variables); err != nil { - return fmt.Errorf("failed to parse --vars JSON: %w", err) - } - } - if variables == nil { - return errors.New("--vars must be a JSON object") - } - - // Then, parse key=value pairs (these override JSON if there's a conflict) - for _, kv := range functionRunVariables { - parts := strings.SplitN(kv, "=", 2) - if len(parts) != 2 { - return fmt.Errorf("invalid variable format %q: expected key=value", kv) - } - variables[parts[0]] = parts[1] + // key=value pairs override the JSON variables if there's a conflict + variables, err := parseVariables(functionRunVariablesJSON, functionRunVariables) + if err != nil { + return err } if functionRunRuntime != "" { diff --git a/internal/cmd/functionschedulesadd_flags.gen.go b/internal/cmd/functionschedulesadd_flags.gen.go new file mode 100644 index 0000000..2eade4e --- /dev/null +++ b/internal/cmd/functionschedulesadd_flags.gen.go @@ -0,0 +1,35 @@ +// Code generated by gen-flags DO NOT EDIT. +package cmd + +import ( + "fmt" + + "github.com/spf13/cobra" + + "github.com/nottelabs/notte-cli/internal/api" +) + +// FunctionSchedulesAdd command flags +var ( + // AWS EventBridge schedule expression. Six space-separated fields, minutes first: `minutes hours day-of-month month day-of-week year`. This is neither five-field Unix crontab nor the seconds-first six-field dialect used by Quartz and cron-parser. Exactly one of day-of-month and day-of-week must be `?`, the other must be a real value. Schedules fire in UTC. Example: `0 12 ? * * *` runs daily at noon UTC. `rate(...)` expressions such as `rate(1 hour)` are accepted too. + FunctionSchedulesAddCron string +) + +// RegisterFunctionSchedulesAddFlags registers all flags for FunctionSchedulesAdd command +func RegisterFunctionSchedulesAddFlags(cmd *cobra.Command) { + cmd.Flags().StringVar(&FunctionSchedulesAddCron, "cron", "", "AWS EventBridge schedule expression. Six space-separated fields, minutes first: `minutes hours day-of-month month day-of-week year`. This is neither five-field Unix crontab nor the seconds-first six-field dialect used by Quartz and cron-parser. Exactly one of day-of-month and day-of-week must be `?`, the other must be a real value. Schedules fire in UTC. Example: `0 12 ? * * *` runs daily at noon UTC. `rate(...)` expressions such as `rate(1 hour)` are accepted too.") +} + +// BuildFunctionSchedulesAddRequest builds the API request from CLI flags +func BuildFunctionSchedulesAddRequest(cmd *cobra.Command) (*api.FunctionScheduleCreateRequest, error) { + body := &api.FunctionScheduleCreateRequest{} + + if cmd.Flags().Changed("cron") { + if FunctionSchedulesAddCron == "" { + return nil, fmt.Errorf("--cron cannot be empty") + } + body.Cron = FunctionSchedulesAddCron + } + + return body, nil +} diff --git a/internal/cmd/functionschedulesupdate_flags.gen.go b/internal/cmd/functionschedulesupdate_flags.gen.go new file mode 100644 index 0000000..b17a5c8 --- /dev/null +++ b/internal/cmd/functionschedulesupdate_flags.gen.go @@ -0,0 +1,35 @@ +// Code generated by gen-flags DO NOT EDIT. +package cmd + +import ( + "fmt" + + "github.com/spf13/cobra" + + "github.com/nottelabs/notte-cli/internal/api" +) + +// FunctionSchedulesUpdate command flags +var ( + // AWS EventBridge schedule expression. Six space-separated fields, minutes first: `minutes hours day-of-month month day-of-week year`. This is neither five-field Unix crontab nor the seconds-first six-field dialect used by Quartz and cron-parser. Exactly one of day-of-month and day-of-week must be `?`, the other must be a real value. Schedules fire in UTC. Example: `0 12 ? * * *` runs daily at noon UTC. `rate(...)` expressions such as `rate(1 hour)` are accepted too. + FunctionSchedulesUpdateCron string +) + +// RegisterFunctionSchedulesUpdateFlags registers all flags for FunctionSchedulesUpdate command +func RegisterFunctionSchedulesUpdateFlags(cmd *cobra.Command) { + cmd.Flags().StringVar(&FunctionSchedulesUpdateCron, "cron", "", "AWS EventBridge schedule expression. Six space-separated fields, minutes first: `minutes hours day-of-month month day-of-week year`. This is neither five-field Unix crontab nor the seconds-first six-field dialect used by Quartz and cron-parser. Exactly one of day-of-month and day-of-week must be `?`, the other must be a real value. Schedules fire in UTC. Example: `0 12 ? * * *` runs daily at noon UTC. `rate(...)` expressions such as `rate(1 hour)` are accepted too.") +} + +// BuildFunctionSchedulesUpdateRequest builds the API request from CLI flags +func BuildFunctionSchedulesUpdateRequest(cmd *cobra.Command) (*api.FunctionScheduleCreateRequest, error) { + body := &api.FunctionScheduleCreateRequest{} + + if cmd.Flags().Changed("cron") { + if FunctionSchedulesUpdateCron == "" { + return nil, fmt.Errorf("--cron cannot be empty") + } + body.Cron = FunctionSchedulesUpdateCron + } + + return body, nil +} diff --git a/scripts/gen-flags/parser.go b/scripts/gen-flags/parser.go index 0f1ae17..c45756d 100644 --- a/scripts/gen-flags/parser.go +++ b/scripts/gen-flags/parser.go @@ -96,18 +96,20 @@ type endpoint struct { // /scrape, /scrape_from_html and /vaults/{vault_id}/card were removed rather // than repaired. var endpointMap = map[endpoint]string{ - {"POST", "/sessions/start"}: "SessionStart", - {"POST", "/personas/create"}: "PersonaCreate", - {"PATCH", "/personas/{persona_id}"}: "PersonaUpdate", - {"POST", "/profiles/create"}: "ProfileCreate", - {"POST", "/vaults/create"}: "VaultCreate", - {"PATCH", "/vaults/{vault_id}"}: "VaultUpdate", - {"POST", "/vaults/{vault_id}/credentials"}: "VaultCredentialsAdd", - {"POST", "/functions"}: "FunctionCreate", - {"POST", "/functions/{function_id}"}: "FunctionUpdate", - {"PATCH", "/functions/{function_id}"}: "FunctionConfigure", - {"POST", "/functions/{function_id}/rollback"}: "FunctionRollback", - {"POST", "/functions/{function_id}/schedule"}: "FunctionScheduleSet", + {"POST", "/sessions/start"}: "SessionStart", + {"POST", "/personas/create"}: "PersonaCreate", + {"PATCH", "/personas/{persona_id}"}: "PersonaUpdate", + {"POST", "/profiles/create"}: "ProfileCreate", + {"POST", "/vaults/create"}: "VaultCreate", + {"PATCH", "/vaults/{vault_id}"}: "VaultUpdate", + {"POST", "/vaults/{vault_id}/credentials"}: "VaultCredentialsAdd", + {"POST", "/functions"}: "FunctionCreate", + {"POST", "/functions/{function_id}"}: "FunctionUpdate", + {"PATCH", "/functions/{function_id}"}: "FunctionConfigure", + {"POST", "/functions/{function_id}/rollback"}: "FunctionRollback", + {"POST", "/functions/{function_id}/schedule"}: "FunctionScheduleSet", + {"POST", "/functions/{function_id}/schedules"}: "FunctionSchedulesAdd", + {"PATCH", "/functions/{function_id}/schedules/{schedule_id}"}: "FunctionSchedulesUpdate", } // methods is the set of operations inspected, in a fixed order so a spec that diff --git a/scripts/gen-flags/types.go b/scripts/gen-flags/types.go index 64ce6cf..72a6209 100644 --- a/scripts/gen-flags/types.go +++ b/scripts/gen-flags/types.go @@ -54,11 +54,18 @@ var SkippedFields = map[string]bool{ // schema and is a free-form object, which no flag can express, so // runFunctionSchedule hard-codes an empty map after calling the generated // builder. Skipping it here keeps that endpoint generating cleanly instead of -// reporting the same unsupported field on every run. +// reporting the same unsupported field on every run. The schedules commands +// take the same body and read variables from --var and --vars instead. var CommandSkippedFields = map[string]map[string]bool{ "FunctionScheduleSet": { "variables": true, }, + "FunctionSchedulesAdd": { + "variables": true, + }, + "FunctionSchedulesUpdate": { + "variables": true, + }, } // JSONDocumentFields contains field names carrying a JSON document rather than From f9b8bf850428307f48cafbc210d3ac4d401feec8 Mon Sep 17 00:00:00 2001 From: Leo Date: Tue, 3 Nov 2026 11:51:14 +0100 Subject: [PATCH 2/4] Warn after an update when schedules no longer match the function's inputs Co-Authored-By: Claude Opus 5.5 --- internal/cmd/function_schedules.go | 59 +++++++++++++++++++ internal/cmd/function_schedules_test.go | 78 +++++++++++++++++++++++++ internal/cmd/functions.go | 3 + 3 files changed, 140 insertions(+) diff --git a/internal/cmd/function_schedules.go b/internal/cmd/function_schedules.go index 8e2bd23..36cdeb9 100644 --- a/internal/cmd/function_schedules.go +++ b/internal/cmd/function_schedules.go @@ -5,6 +5,8 @@ import ( "encoding/json" "errors" "fmt" + "os" + "sort" "strings" "github.com/spf13/cobra" @@ -297,3 +299,60 @@ func runFunctionSchedulesResume(cmd *cobra.Command, args []string) error { } return GetFormatter().Print(resp.JSON200) } + +// scheduleInputProblem is how a schedule's inputs disagree with the function's +// variables: required ones it does not set, and ones the function no longer +// takes. The API applies the same rule when a schedule is saved, not when the +// function changes, so either fails every run of an older schedule. +func scheduleInputProblem(values *map[string]interface{}, variables *[]api.ParameterInfo) (missing, unused []string) { + set := map[string]interface{}{} + if values != nil { + set = *values + } + declared := map[string]bool{} + if variables != nil { + for _, v := range *variables { + declared[v.Name] = true + if _, ok := set[v.Name]; !ok && v.Default == nil { + missing = append(missing, v.Name) + } + } + } + for name := range set { + if !declared[name] { + unused = append(unused, name) + } + } + sort.Strings(unused) + return missing, unused +} + +// warnAboutScheduleInputs prints, on stderr, the schedules whose inputs no +// longer fit the function's variables after an update. The update itself +// succeeded: when the schedules cannot be read there is nothing to print. +func warnAboutScheduleInputs(ctx context.Context, client *api.NotteClient, variables *[]api.ParameterInfo) { + list, err := listFunctionSchedules(ctx, client) + if err != nil { + return + } + var lines []string + for _, s := range list.Schedules { + missing, unused := scheduleInputProblem(s.Variables, variables) + var parts []string + if len(missing) > 0 { + parts = append(parts, "missing required "+strings.Join(missing, ", ")) + } + if len(unused) > 0 { + parts = append(parts, "no longer takes "+strings.Join(unused, ", ")) + } + if len(parts) > 0 { + lines = append(lines, fmt.Sprintf(" %s (%s): %s", s.ScheduleId, s.Cron, strings.Join(parts, "; "))) + } + } + if len(lines) == 0 { + return + } + _, _ = fmt.Fprintf(os.Stderr, "Warning: %d of the function's schedules no longer match its inputs, so their runs fail:\n%s\n"+ + "Fix them with: notte functions schedules update --function-id %s --var name=value\n", + len(lines), strings.Join(lines, "\n"), functionID) +} diff --git a/internal/cmd/function_schedules_test.go b/internal/cmd/function_schedules_test.go index e2d1cd3..3b7d716 100644 --- a/internal/cmd/function_schedules_test.go +++ b/internal/cmd/function_schedules_test.go @@ -3,6 +3,7 @@ package cmd import ( "context" "encoding/json" + "os" "strings" "testing" @@ -240,3 +241,80 @@ func mustJSON(t *testing.T, v any) string { } return string(b) } + +func TestRunFunctionUpdateWarnsAboutSchedulesItBreaks(t *testing.T) { + server := setupFunctionTest(t) + updated := `{"function_id":"` + functionIDTest + `","latest_version":"2","status":"active","created_at":"2020-01-01T00:00:00Z","updated_at":"2020-01-01T00:00:00Z","versions":["1","2"],` + + `"variables":[{"name":"city","default":null},{"name":"limit","default":"10"}]}` + server.AddResponse("/functions/"+functionIDTest, 200, updated) + // s2 still sets `zip`; the new version also needs `city`, which the + // first schedule has. A schedule without inputs misses `city`. + server.AddResponse("/functions/"+functionIDTest+"/schedules", 200, `{"schedules":[`+ + `{"schedule_id":"`+functionIDTest+`","cron":"0 9 ? * * *","variables":{"city":"paris"}},`+ + `{"schedule_id":"s2","cron":"0 17 ? * * *","variables":{"city":"tokyo","zip":"100"}},`+ + `{"schedule_id":"s3","cron":"0 1 ? * * *"}`+ + `],"state":"enabled"}`) + + tmpFile, err := os.CreateTemp("", "function-update-*.py") + if err != nil { + t.Fatal(err) + } + _ = tmpFile.Close() + t.Cleanup(func() { _ = os.Remove(tmpFile.Name()) }) + origFile := FunctionUpdateFile + FunctionUpdateFile = tmpFile.Name() + t.Cleanup(func() { FunctionUpdateFile = origFile }) + origFormat := outputFormat + outputFormat = "json" + t.Cleanup(func() { outputFormat = origFormat }) + cmd := &cobra.Command{} + cmd.SetContext(context.Background()) + + stdout, stderr := testutil.CaptureOutput(func() { + if err := runFunctionUpdate(cmd, nil); err != nil { + t.Fatalf("unexpected error: %v", err) + } + }) + + if !strings.Contains(stdout, `"latest_version"`) || strings.Contains(stdout, "Warning") { + t.Errorf("stdout should be the function only, got %q", stdout) + } + for _, want := range []string{ + "2 of the function's schedules no longer match its inputs", + "s2 (0 17 ? * * *): no longer takes zip", + "s3 (0 1 ? * * *): missing required city", + } { + if !strings.Contains(stderr, want) { + t.Errorf("stderr missing %q, got %q", want, stderr) + } + } + if strings.Contains(stderr, functionIDTest+" (0 9") { + t.Errorf("the matching schedule should not be listed: %q", stderr) + } +} + +func TestRunFunctionUpdateSaysNothingWhenSchedulesCannotBeRead(t *testing.T) { + server := setupFunctionTest(t) + server.AddResponse("/functions/"+functionIDTest, 200, functionJSON()) + tmpFile, err := os.CreateTemp("", "function-update-*.py") + if err != nil { + t.Fatal(err) + } + _ = tmpFile.Close() + t.Cleanup(func() { _ = os.Remove(tmpFile.Name()) }) + origFile := FunctionUpdateFile + FunctionUpdateFile = tmpFile.Name() + t.Cleanup(func() { FunctionUpdateFile = origFile }) + cmd := &cobra.Command{} + cmd.SetContext(context.Background()) + + _, stderr := testutil.CaptureOutput(func() { + if err := runFunctionUpdate(cmd, nil); err != nil { + t.Fatalf("unexpected error: %v", err) + } + }) + + if strings.Contains(stderr, "Warning") { + t.Errorf("expected no warning, got %q", stderr) + } +} diff --git a/internal/cmd/functions.go b/internal/cmd/functions.go index 0945649..a3cf93b 100644 --- a/internal/cmd/functions.go +++ b/internal/cmd/functions.go @@ -568,6 +568,9 @@ func runFunctionUpdate(cmd *cobra.Command, args []string) error { return err } + if resp.JSON200 != nil { + warnAboutScheduleInputs(ctx, client, resp.JSON200.Variables) + } return GetFormatter().Print(resp.JSON200) } From f4750e83570cbbef3c59d59fb8fea4adc927a7f4 Mon Sep 17 00:00:00 2001 From: Leo Date: Tue, 3 Nov 2026 12:38:14 +0100 Subject: [PATCH 3/4] Format the schedule command tests Co-Authored-By: Claude Opus 5.5 --- internal/cmd/function_schedules_test.go | 21 +++++++++++++++------ 1 file changed, 15 insertions(+), 6 deletions(-) diff --git a/internal/cmd/function_schedules_test.go b/internal/cmd/function_schedules_test.go index 3b7d716..9fff908 100644 --- a/internal/cmd/function_schedules_test.go +++ b/internal/cmd/function_schedules_test.go @@ -104,12 +104,21 @@ func TestRunFunctionSchedulesUpdateKeepsWhatIsNotGiven(t *testing.T) { flags map[string][]string want map[string]any }{ - {"cron only", map[string][]string{"cron": {"0 18 ? * MON-FRI *"}}, - map[string]any{"cron": "0 18 ? * MON-FRI *", "variables": map[string]any{"city": "tokyo", "limit": float64(5)}}}, - {"variables only", map[string][]string{"var": {"city=osaka"}}, - map[string]any{"cron": "0 17 ? * MON-FRI *", "variables": map[string]any{"city": "osaka"}}}, - {"both", map[string][]string{"cron": {"0 1 ? * * *"}, "vars": {`{"city": "kyoto"}`}}, - map[string]any{"cron": "0 1 ? * * *", "variables": map[string]any{"city": "kyoto"}}}, + { + "cron only", + map[string][]string{"cron": {"0 18 ? * MON-FRI *"}}, + map[string]any{"cron": "0 18 ? * MON-FRI *", "variables": map[string]any{"city": "tokyo", "limit": float64(5)}}, + }, + { + "variables only", + map[string][]string{"var": {"city=osaka"}}, + map[string]any{"cron": "0 17 ? * MON-FRI *", "variables": map[string]any{"city": "osaka"}}, + }, + { + "both", + map[string][]string{"cron": {"0 1 ? * * *"}, "vars": {`{"city": "kyoto"}`}}, + map[string]any{"cron": "0 1 ? * * *", "variables": map[string]any{"city": "kyoto"}}, + }, } for _, c := range cases { t.Run(c.name, func(t *testing.T) { From 2637e7a2f32784d54471b7f01725c4d5ba6fafa6 Mon Sep 17 00:00:00 2001 From: Leo Date: Tue, 3 Nov 2026 13:39:05 +0100 Subject: [PATCH 4/4] Keep schedule numbers exact on update and one JSON shape for list Co-Authored-By: Claude Opus 5.5 --- internal/cmd/function_schedules.go | 23 +++++++++--- internal/cmd/function_schedules_test.go | 49 +++++++++++++++++++++++++ 2 files changed, 66 insertions(+), 6 deletions(-) diff --git a/internal/cmd/function_schedules.go b/internal/cmd/function_schedules.go index 36cdeb9..313ed96 100644 --- a/internal/cmd/function_schedules.go +++ b/internal/cmd/function_schedules.go @@ -1,6 +1,7 @@ package cmd import ( + "bytes" "context" "encoding/json" "errors" @@ -119,6 +120,9 @@ func scheduleVariablesGiven(cmd *cobra.Command) bool { return cmd.Flags().Changed("var") || cmd.Flags().Changed("vars") } +// listFunctionSchedules reads the function's schedules with their variables' +// numbers kept as sent (json.Number), so one written back is unchanged: the +// generated decoder reads them as float64, which rounds integers above 2^53. func listFunctionSchedules(ctx context.Context, client *api.NotteClient) (*api.FunctionScheduleListResponse, error) { resp, err := client.Client().FunctionSchedulesListWithResponse(ctx, functionID, &api.FunctionSchedulesListParams{}) if err != nil { @@ -127,10 +131,16 @@ func listFunctionSchedules(ctx context.Context, client *api.NotteClient) (*api.F if err := HandleAPIResponse(resp.HTTPResponse, resp.Body); err != nil { return nil, err } - if resp.JSON200 == nil { - return &api.FunctionScheduleListResponse{}, nil + list := &api.FunctionScheduleListResponse{} + if len(resp.Body) == 0 { + return list, nil } - return resp.JSON200, nil + decoder := json.NewDecoder(bytes.NewReader(resp.Body)) + decoder.UseNumber() + if err := decoder.Decode(list); err != nil { + return nil, fmt.Errorf("failed to parse schedules: %w", err) + } + return list, nil } func runFunctionSchedulesList(cmd *cobra.Command, args []string) error { @@ -148,9 +158,10 @@ func runFunctionSchedulesList(cmd *cobra.Command, args []string) error { if err != nil { return err } - if printed, err := PrintListOrEmpty(list.Schedules, "No schedules found."); err != nil { - return err - } else if printed { + // JSON output is the whole response whether or not there are schedules, + // so `.schedules` and `.state` stay readable once the last one is removed. + if !IsJSONOutput() && len(list.Schedules) == 0 { + PrintInfo("No schedules found.") return nil } return GetFormatter().Print(list) diff --git a/internal/cmd/function_schedules_test.go b/internal/cmd/function_schedules_test.go index 9fff908..8002192 100644 --- a/internal/cmd/function_schedules_test.go +++ b/internal/cmd/function_schedules_test.go @@ -142,6 +142,31 @@ func TestRunFunctionSchedulesUpdateKeepsWhatIsNotGiven(t *testing.T) { } } +func TestRunFunctionSchedulesUpdateKeepsLargeIntegersExact(t *testing.T) { + server := setupFunctionTest(t) + server.AddResponse("/functions/"+functionIDTest+"/schedules", 200, + `{"schedules":[{"schedule_id":"s2","cron":"0 17 ? * * *","variables":{"id":9007199254740993,"ratio":0.1}}],"state":"enabled"}`) + path := "/functions/" + functionIDTest + "/schedules/s2" + server.AddResponse(path, 200, `{"schedule_id":"s2","cron":"0 18 ? * * *","variables":{}}`) + cmd := scheduleCommand(t, RegisterFunctionSchedulesUpdateFlags, map[string][]string{"cron": {"0 18 ? * * *"}}) + + _, _ = testutil.CaptureOutput(func() { + if err := runFunctionSchedulesUpdate(cmd, []string{"s2"}); err != nil { + t.Fatalf("unexpected error: %v", err) + } + }) + + var sent string + for _, r := range server.Requests(path) { + if r.Method == "PATCH" { + sent = r.Body + } + } + if !strings.Contains(sent, `"id":9007199254740993`) || !strings.Contains(sent, `"ratio":0.1`) { + t.Errorf("variables changed on a cron-only update: %s", sent) + } +} + func TestRunFunctionSchedulesUpdateRejectsNoChange(t *testing.T) { setupFunctionTest(t) cmd := scheduleCommand(t, RegisterFunctionSchedulesUpdateFlags, nil) @@ -206,6 +231,30 @@ func TestRunFunctionSchedulesResume(t *testing.T) { } } +func TestRunFunctionSchedulesListEmptyJSONKeepsTheResponseShape(t *testing.T) { + server := setupFunctionTest(t) + server.AddResponse("/functions/"+functionIDTest+"/schedules", 200, `{"schedules":[],"state":null,"paused_reason":null}`) + origFormat := outputFormat + outputFormat = "json" + t.Cleanup(func() { outputFormat = origFormat }) + cmd := &cobra.Command{} + cmd.SetContext(context.Background()) + + stdout, _ := testutil.CaptureOutput(func() { + if err := runFunctionSchedulesList(cmd, nil); err != nil { + t.Fatalf("unexpected error: %v", err) + } + }) + + var out map[string]any + if err := json.Unmarshal([]byte(stdout), &out); err != nil { + t.Fatalf("stdout is not a JSON object: %q", stdout) + } + if schedules, ok := out["schedules"].([]any); !ok || len(schedules) != 0 { + t.Errorf("schedules = %v, want []", out["schedules"]) + } +} + func TestRunFunctionSchedulesListEmpty(t *testing.T) { server := setupFunctionTest(t) server.AddResponse("/functions/"+functionIDTest+"/schedules", 200, `{"schedules":[],"state":null,"paused_reason":null}`)