From 9ff2f852a0f28a4fa1ff7635737692956da5d79d Mon Sep 17 00:00:00 2001 From: ryank90 Date: Mon, 21 Sep 2026 13:06:54 +0100 Subject: [PATCH] feat(serverless): sync OpenAPI 0.6.0 and treat 402 as quota The control plane now returns paymentRequired with a shortfall, exposes effectiveMaxWorkers and log sort/cursors, and accepts 1|2|4|8 GPUs. Regenerate the client and map 402 so create, scale, activate, and resume print the credit gap instead of a server error. --- api/serverless/openapi.yaml | 138 ++++++++++++++-- internal/api/serverless/client.go | 95 +++++++++-- internal/api/serverless/errors.go | 7 +- internal/api/serverless/errors_test.go | 29 ++++ internal/api/serverless/gen/client.gen.go | 188 +++++++++++++++++++--- internal/api/serverless/logs.go | 14 +- 6 files changed, 422 insertions(+), 49 deletions(-) diff --git a/api/serverless/openapi.yaml b/api/serverless/openapi.yaml index d2ffedf..c13df8b 100644 --- a/api/serverless/openapi.yaml +++ b/api/serverless/openapi.yaml @@ -434,6 +434,8 @@ paths: $ref: '#/components/schemas/App' '401': $ref: '#/components/responses/Unauthorized' + '402': + $ref: '#/components/responses/PaymentRequired' '503': $ref: '#/components/responses/ServiceUnavailable' '403': @@ -545,6 +547,8 @@ paths: $ref: '#/components/schemas/App' '401': $ref: '#/components/responses/Unauthorized' + '402': + $ref: '#/components/responses/PaymentRequired' '503': $ref: '#/components/responses/ServiceUnavailable' '403': @@ -829,6 +833,8 @@ paths: $ref: '#/components/responses/BadRequest' '401': $ref: '#/components/responses/Unauthorized' + '402': + $ref: '#/components/responses/PaymentRequired' '503': $ref: '#/components/responses/ServiceUnavailable' '403': @@ -898,6 +904,8 @@ paths: $ref: '#/components/schemas/App' '401': $ref: '#/components/responses/Unauthorized' + '402': + $ref: '#/components/responses/PaymentRequired' '503': $ref: '#/components/responses/ServiceUnavailable' '403': @@ -906,6 +914,8 @@ paths: $ref: '#/components/responses/NotFound' '409': $ref: '#/components/responses/Conflict' + '422': + $ref: '#/components/responses/ValidationError' /v1/apps/{appId}/favourite: put: @@ -1317,7 +1327,7 @@ paths: terminal `stopped` rows until purged). Omitted `versionId` scopes the page to the app's `activeVersionId`. An app with no active version therefore answers an empty default page — not that it has no workers, only that - none are pinned. Optional `state` and `status` narrow the page further; + none are pinned. Optional `state`, `status` and `q` narrow the page further; a cursor must be replayed under the same filters it was issued with. operationId: listWorkers parameters: @@ -1353,6 +1363,18 @@ paths: required: false schema: $ref: '#/components/schemas/WorkerStatus' + - name: q + in: query + required: false + description: > + Case-insensitive literal substring match against `id`, `podName`, + `nodeName` and `versionId`. A worker matching any field is returned + within the selected version, state and status filters. Omit `q` to + disable search. Cursors must retain the same search term, ignoring case. + schema: + type: string + minLength: 1 + maxLength: 100 responses: '200': description: A page of workers @@ -2327,15 +2349,20 @@ paths: - Observability summary: Read one page of a named log query description: > - Returns one page of log entries, newest first, with an opaque cursor for the next - page when one exists. Query ids and their supported selectors are listed by the - insights catalogue. + Returns one page of log entries in the requested `sort` order, newest first by + default, with opaque cursors for the neighbouring pages when they exist. + `nextCursor` continues in the `sort` order and `prevCursor` goes back against it, + so a client can walk a window in either direction from either end. A cursor is only + valid for the `sort` it was issued under; reusing one under the other ordering + returns `400`. Query ids and their supported selectors are listed by the insights + catalogue. operationId: getLogEntries parameters: - $ref: '#/components/parameters/QueryId' - $ref: '#/components/parameters/MetricWindow' - $ref: '#/components/parameters/Limit' - $ref: '#/components/parameters/Cursor' + - $ref: '#/components/parameters/LogSort' - $ref: '#/components/parameters/SelectorDeployment' - $ref: '#/components/parameters/SelectorEndpoint' responses: @@ -2497,9 +2524,20 @@ components: name: cursor in: query required: false - description: Opaque pagination cursor returned as `nextCursor` by a previous call. + description: > + Opaque pagination cursor returned by a previous call, as `nextCursor` or, on the + operations that offer one, `prevCursor`. schema: type: string + LogSort: + name: sort + in: query + required: false + description: > + Ordering of a log page and the direction `nextCursor` moves in. Only + `getLogEntries` accepts it. + schema: + $ref: '#/components/schemas/LogSort' QueryId: name: queryId @@ -2686,6 +2724,18 @@ components: application/problem+json: schema: $ref: '#/components/schemas/ProblemDetails' + PaymentRequired: + description: > + The organization's credit cannot cover the capacity the request asks for. + The problem `type` is `insufficient-credit` when the available balance + is short, and `credit-suspended` when a refund took back credit already + spent and every allocation is refused until the balance is funded back. + Either way `shortfall` is the amount to add before retrying: the request + is unchanged by the refusal and succeeds as sent once the credit is there. + content: + application/problem+json: + schema: + $ref: '#/components/schemas/ProblemDetails' ServiceUnavailable: description: A required service is temporarily unavailable content: @@ -3038,6 +3088,15 @@ components: - name - activity - errorRate + LogSort: + type: string + description: > + Ordering of a log page. `newest` is the default: the first row is the + newest entry and `nextCursor` walks older. `oldest` reverses that. + default: newest + enum: + - newest + - oldest BuildStatus: type: string description: Build/validation lifecycle status. @@ -3463,6 +3522,30 @@ components: allOf: - $ref: '#/components/schemas/WorkerConfig' description: Live worker configuration. Updated via `PATCH /apps/{appId}`. + effectiveMaxWorkers: + type: integer + format: int32 + minimum: 0 + nullable: true + readOnly: true + description: > + The worker ceiling the last deploy actually applied, reduced where the + organization's credit balance did not back the whole range. The autoscaler + cannot grow past it. + + + It describes what was applied, not what is configured now, and the two can + differ. It is taken from the `maxWorkers` of the version that was deployed, + so deploying an older version applies that version's ceiling; and a later + `PATCH` of `configuration.maxWorkers` does not change it until the next + deploy. Read it beside `configuration.maxWorkers` rather than as a bound on + it. + + + `null` means nothing has been applied yet. It is recalculated on every + deploy. A committed credit top-up also recalculates a reduced ceiling and + restores the funded range automatically; KEDA then grows the workload from + queue demand without a customer redeploy. runtime: $ref: '#/components/schemas/AppRuntime' secrets: @@ -3722,7 +3805,10 @@ components: type: integer format: int32 default: 1 - description: One GPU per worker is currently supported. Historical apps may contain another value. + description: > + GPUs granted to one worker pod. Create and update accept only the group + sizes the cluster grants indivisibly, since a worker holds its GPUs as one + such group. Historical apps may contain another value. minWorkers: type: integer format: int32 @@ -3818,9 +3904,19 @@ components: gpusPerWorker: type: integer format: int32 - minimum: 0 + enum: [1, 2, 4, 8] + x-go-type: int32 default: 1 - description: Only 1 is currently supported. Any other value returns 422. + description: > + GPUs granted to one worker pod. A worker holds its GPUs as one group the + cluster grants indivisibly, so the count is one of the advertised group + sizes rather than any number in a range. The value must also be a group + size admitted by the cluster backing the chosen `gpuType`: a count above 1 + that cluster does not grant is rejected with a 422 naming + `/configuration/gpusPerWorker`, since the pod could never be scheduled. + A value above 1 requires an image built after the multi-GPU worker + entrypoint; older images serve a single rank while holding every granted + GPU. minWorkers: type: integer format: int32 @@ -3899,8 +3995,18 @@ components: gpusPerWorker: type: integer format: int32 - minimum: 0 - description: Only 1 is currently supported. Any other value returns 422. + enum: [1, 2, 4, 8] + x-go-type: int32 + description: > + GPUs granted to one worker pod. A worker holds its GPUs as one group the + cluster grants indivisibly, so the count is one of the advertised group + sizes rather than any number in a range. The value must also be a group + size admitted by the cluster backing the chosen `gpuType`: a count above 1 + that cluster does not grant is rejected with a 422 naming + `/configuration/gpusPerWorker`, since the pod could never be scheduled. + A value above 1 requires an image built after the multi-GPU worker + entrypoint; older images serve a single rank while holding every granted + GPU. minWorkers: type: integer format: int32 @@ -5164,6 +5270,13 @@ components: per offending request field. items: $ref: '#/components/schemas/ProblemError' + shortfall: + type: string + description: > + Extension member. Present on `402` credit refusals. The amount of + credit to add before retrying the same request. Units match the + platform credit display. + example: "12.50" ProblemError: type: object @@ -5316,6 +5429,11 @@ components: nextCursor: type: string description: Opaque; absent on the last page. + prevCursor: + type: string + description: > + Opaque; absent on the first page. Walks the opposite direction of + `nextCursor` under the same `sort`. LogEntry: type: object required: [time, body] diff --git a/internal/api/serverless/client.go b/internal/api/serverless/client.go index 4316152..f31e23e 100644 --- a/internal/api/serverless/client.go +++ b/internal/api/serverless/client.go @@ -128,6 +128,9 @@ const ( // Endpoint is an app HTTP endpoint. type Endpoint = gen.Endpoint +// EndpointRuntime is latest-window traffic for one endpoint. +type EndpointRuntime = gen.EndpointRuntime + // Version is a deployed application version. type Version = gen.Version @@ -321,6 +324,8 @@ func (c *Client) CreateApp(ctx context.Context, body AppCreate) (*App, error) { return nil, problemToError(resp.ApplicationproblemJSON400, http.StatusBadRequest) case http.StatusUnauthorized: return nil, problemToError(resp.ApplicationproblemJSON401, http.StatusUnauthorized) + case http.StatusPaymentRequired: + return nil, problemToError(resp.ApplicationproblemJSON402, http.StatusPaymentRequired) case http.StatusForbidden: return nil, problemToError(resp.ApplicationproblemJSON403, http.StatusForbidden) case http.StatusConflict: @@ -459,6 +464,8 @@ func (c *Client) UpdateApp(ctx context.Context, appID string, body AppUpdate) (* return nil, problemToError(resp.ApplicationproblemJSON400, http.StatusBadRequest) case http.StatusUnauthorized: return nil, problemToError(resp.ApplicationproblemJSON401, http.StatusUnauthorized) + case http.StatusPaymentRequired: + return nil, problemToError(resp.ApplicationproblemJSON402, http.StatusPaymentRequired) case http.StatusForbidden: return nil, problemToError(resp.ApplicationproblemJSON403, http.StatusForbidden) case http.StatusNotFound: @@ -509,10 +516,12 @@ func (c *Client) ResumeApp(ctx context.Context, appID string) (*App, error) { c.logResponse(ctx, resp.HTTPResponse, resp.Body) return acceptedApp("resume app", resp.StatusCode(), resp.JSON202, resp.Body, lifecycleProblems{ - Unauthorized: resp.ApplicationproblemJSON401, - Forbidden: resp.ApplicationproblemJSON403, - NotFound: resp.ApplicationproblemJSON404, - Conflict: resp.ApplicationproblemJSON409, + Unauthorized: resp.ApplicationproblemJSON401, + PaymentRequired: resp.ApplicationproblemJSON402, + Forbidden: resp.ApplicationproblemJSON403, + NotFound: resp.ApplicationproblemJSON404, + Conflict: resp.ApplicationproblemJSON409, + Unprocessable: resp.ApplicationproblemJSON422, }) } @@ -555,19 +564,23 @@ func (c *Client) DeployVersion(ctx context.Context, appID string, versionNumber c.logResponse(ctx, resp.HTTPResponse, resp.Body) return acceptedApp("deploy version", resp.StatusCode(), resp.JSON202, resp.Body, lifecycleProblems{ - Unauthorized: resp.ApplicationproblemJSON401, - Forbidden: resp.ApplicationproblemJSON403, - NotFound: resp.ApplicationproblemJSON404, - Conflict: resp.ApplicationproblemJSON409, + Unauthorized: resp.ApplicationproblemJSON401, + PaymentRequired: resp.ApplicationproblemJSON402, + Forbidden: resp.ApplicationproblemJSON403, + NotFound: resp.ApplicationproblemJSON404, + Conflict: resp.ApplicationproblemJSON409, + Unprocessable: resp.ApplicationproblemJSON422, }) } // lifecycleProblems are typed RFC 9457 bodies bound by the generated client. type lifecycleProblems struct { - Unauthorized *gen.ProblemDetails - Forbidden *gen.ProblemDetails - NotFound *gen.ProblemDetails - Conflict *gen.ProblemDetails + Unauthorized *gen.ProblemDetails + PaymentRequired *gen.ProblemDetails + Forbidden *gen.ProblemDetails + NotFound *gen.ProblemDetails + Conflict *gen.ProblemDetails + Unprocessable *gen.ProblemDetails } func acceptedApp(op string, status int, app *App, body []byte, problems lifecycleProblems) (*App, error) { @@ -579,6 +592,8 @@ func acceptedApp(op string, status int, app *App, body []byte, problems lifecycl return app, nil case http.StatusUnauthorized: return nil, problemToError(problems.Unauthorized, http.StatusUnauthorized) + case http.StatusPaymentRequired: + return nil, problemToError(problems.PaymentRequired, http.StatusPaymentRequired) case http.StatusForbidden: return nil, problemToError(problems.Forbidden, http.StatusForbidden) case http.StatusNotFound: @@ -588,6 +603,11 @@ func acceptedApp(op string, status int, app *App, body []byte, problems lifecycl return nil, problemToError(problems.Conflict, http.StatusConflict) } return nil, problemFromBody(body, status) + case http.StatusUnprocessableEntity: + if problems.Unprocessable != nil { + return nil, problemToError(problems.Unprocessable, http.StatusUnprocessableEntity) + } + return nil, problemFromBody(body, status) default: return nil, problemFromBody(body, status) } @@ -931,6 +951,57 @@ func (c *Client) ListAppEvents(ctx context.Context, appID string, params *ListAp } } +// ListAppErrorsParams filters the request-error page for an app. +type ListAppErrorsParams = gen.ListAppErrorsParams + +// ListAppErrorsParamsWindow is the closed set of time windows listAppErrors accepts. +type ListAppErrorsParamsWindow = gen.ListAppErrorsParamsWindow + +// ListAppErrorsParamsStatusClass filters listAppErrors by 4xx or 5xx. +type ListAppErrorsParamsStatusClass = gen.ListAppErrorsParamsStatusClass + +// ListAppErrors returns one page of failed inference requests for an app. +func (c *Client) ListAppErrors(ctx context.Context, appID string, params *ListAppErrorsParams) (Page[LogEntry], error) { + if c.apiKey == "" { + return Page[LogEntry]{}, transport.ErrNoAPIKey + } + + resp, err := c.inner.ListAppErrorsWithResponse(ctx, appID, params) + if err != nil { + return Page[LogEntry]{}, fmt.Errorf("list app errors: %w", err) + } + + c.logResponse(ctx, resp.HTTPResponse, resp.Body) + + switch resp.StatusCode() { + case http.StatusOK: + if resp.JSON200 == nil { + return pageOf[LogEntry](nil, nil), nil + } + return pageOf(&resp.JSON200.Data, resp.JSON200.NextCursor), nil + case http.StatusBadRequest: + return Page[LogEntry]{}, problemToError(resp.ApplicationproblemJSON400, http.StatusBadRequest) + case http.StatusUnauthorized: + return Page[LogEntry]{}, problemToError(resp.ApplicationproblemJSON401, http.StatusUnauthorized) + case http.StatusForbidden: + return Page[LogEntry]{}, problemToError(resp.ApplicationproblemJSON403, http.StatusForbidden) + case http.StatusNotFound: + return Page[LogEntry]{}, problemToError(resp.ApplicationproblemJSON404, http.StatusNotFound) + case http.StatusUnprocessableEntity: + return Page[LogEntry]{}, problemToError(resp.ApplicationproblemJSON422, http.StatusUnprocessableEntity) + case http.StatusTooManyRequests: + return Page[LogEntry]{}, problemToError(resp.ApplicationproblemJSON429, http.StatusTooManyRequests) + case http.StatusBadGateway: + return Page[LogEntry]{}, problemToError(resp.ApplicationproblemJSON502, http.StatusBadGateway) + case http.StatusServiceUnavailable: + return Page[LogEntry]{}, problemToError(resp.ApplicationproblemJSON503, http.StatusServiceUnavailable) + case http.StatusGatewayTimeout: + return Page[LogEntry]{}, problemToError(resp.ApplicationproblemJSON504, http.StatusGatewayTimeout) + default: + return Page[LogEntry]{}, problemFromBody(resp.Body, resp.StatusCode()) + } +} + // NewCodeAppSource builds an appSource for a code-based create or update. func NewCodeAppSource(src CodeSourceUpsert) (AppSourceUpsert, error) { var source gen.AppSourceUpsert_Source diff --git a/internal/api/serverless/errors.go b/internal/api/serverless/errors.go index 84c601b..c1d309e 100644 --- a/internal/api/serverless/errors.go +++ b/internal/api/serverless/errors.go @@ -29,6 +29,9 @@ func problemToError(p *gen.ProblemDetails, statusCode int) error { if extra := formatProblemErrors(p.Errors); extra != "" { msg = msg + "\n" + extra } + if p.Shortfall != nil && *p.Shortfall != "" { + msg = msg + "\n shortfall: " + *p.Shortfall + } } return transport.CreateRunwareError( rawCodeForStatus(statusCode), @@ -69,7 +72,7 @@ func problemFromBody(body []byte, statusCode int) error { } func isProblemDetails(p gen.ProblemDetails) bool { - return p.Title != "" || p.Type != "" || p.Status != 0 || (p.Detail != nil && *p.Detail != "") || (p.Errors != nil && len(*p.Errors) > 0) + return p.Title != "" || p.Type != "" || p.Status != 0 || (p.Detail != nil && *p.Detail != "") || (p.Errors != nil && len(*p.Errors) > 0) || (p.Shortfall != nil && *p.Shortfall != "") } // rawCodeForStatus maps an HTTP status to a raw error code string that @@ -86,6 +89,8 @@ func rawCodeForStatus(statusCode int) string { return "conflict" case http.StatusBadRequest, http.StatusUnprocessableEntity: return "validationFailed" + case http.StatusPaymentRequired: + return "paymentRequired" default: // Must be a key in transport.serverErrorCodes so DeriveCode returns // CodeServerError rather than CodeUnknown. diff --git a/internal/api/serverless/errors_test.go b/internal/api/serverless/errors_test.go index d02b207..98e4ff7 100644 --- a/internal/api/serverless/errors_test.go +++ b/internal/api/serverless/errors_test.go @@ -38,3 +38,32 @@ func TestProblemToError_IncludesValidationErrors(t *testing.T) { t.Errorf("missing field error: %q", re.Message) } } + +func TestProblemToError_PaymentRequiredIncludesShortfall(t *testing.T) { + detail := "Organization credit cannot cover the requested capacity" + shortfall := "12.50" + p := &gen.ProblemDetails{ + Title: "Payment Required", + Status: 402, + Detail: &detail, + Shortfall: &shortfall, + } + + err := problemToError(p, http.StatusPaymentRequired) + var re *transport.RunwareError + if !errors.As(err, &re) { + t.Fatalf("expected *transport.RunwareError, got %T: %v", err, err) + } + if re.Code != transport.CodeQuota { + t.Errorf("expected CodeQuota, got %v", re.Code) + } + if re.StatusCode != http.StatusPaymentRequired { + t.Errorf("status %d, want 402", re.StatusCode) + } + if !strings.Contains(re.Message, detail) { + t.Errorf("missing problem detail: %q", re.Message) + } + if !strings.Contains(re.Message, "shortfall: 12.50") { + t.Errorf("missing shortfall: %q", re.Message) + } +} diff --git a/internal/api/serverless/gen/client.gen.go b/internal/api/serverless/gen/client.gen.go index 09c7856..955be0a 100644 --- a/internal/api/serverless/gen/client.gen.go +++ b/internal/api/serverless/gen/client.gen.go @@ -238,6 +238,24 @@ func (e GpuAvailability) Valid() bool { } } +// Defines values for LogSort. +const ( + Newest LogSort = "newest" + Oldest LogSort = "oldest" +) + +// Valid indicates whether the value is a known member of the LogSort enum. +func (e LogSort) Valid() bool { + switch e { + case Newest: + return true + case Oldest: + return true + default: + return false + } +} + // Defines values for SecretType. const ( Generic SecretType = "generic" @@ -691,6 +709,13 @@ type App struct { Configuration WorkerConfig `json:"configuration"` CreatedAt time.Time `json:"createdAt"` + // EffectiveMaxWorkers The worker ceiling the last deploy actually applied, reduced where the organization's credit balance did not back the whole range. The autoscaler cannot grow past it. + // + // It describes what was applied, not what is configured now, and the two can differ. It is taken from the `maxWorkers` of the version that was deployed, so deploying an older version applies that version's ceiling; and a later `PATCH` of `configuration.maxWorkers` does not change it until the next deploy. Read it beside `configuration.maxWorkers` rather than as a bound on it. + // + // `null` means nothing has been applied yet. It is recalculated on every deploy. A committed credit top-up also recalculates a reduced ceiling and restores the funded range automatically; KEDA then grows the workload from queue demand without a customer redeploy. + EffectiveMaxWorkers *int32 `json:"effectiveMaxWorkers,omitempty"` + // EnvironmentVariables Plain-text environment variables for this app. Populated on single-app responses (get, update, stop, resume, delete, deploy, favourite). List of apps returns an empty array to avoid an N+1 per page row — use the `/environment-variables` endpoints to page the set. EnvironmentVariables []EnvironmentVariable `json:"environmentVariables"` @@ -1164,8 +1189,14 @@ type LogEntryPage struct { // NextCursor Opaque; absent on the last page. NextCursor *string `json:"nextCursor,omitempty"` + + // PrevCursor Opaque; absent on the first page. Walks the opposite direction of `nextCursor` under the same `sort`. + PrevCursor *string `json:"prevCursor,omitempty"` } +// LogSort Ordering of a log page. `newest` is the default: the first row is the newest entry and `nextCursor` walks older. `oldest` reverses that. +type LogSort string + // MetricSeries defines model for MetricSeries. type MetricSeries struct { Aggregation string `json:"aggregation"` @@ -1245,6 +1276,12 @@ type ProblemDetails struct { // RequestId Extension member. Correlation id for this request, echoed in the `X-Request-Id` response header; quote it when reporting problems. RequestId *string `json:"requestId,omitempty"` + // Shortfall Extension member. Present on `402` credit refusals. The amount of credit to add before retrying the same request. Units match the platform credit display. + // + // + // Example: 12.50 + Shortfall *string `json:"shortfall,omitempty"` + // Status HTTP status code generated for this occurrence. // // Example: 404 @@ -1749,7 +1786,7 @@ type WorkerConfig struct { // GpuType Preferred GPU type. Absent (or null) only on historical apps created before a GPU type was required. GpuType *GpuTypeId `json:"gpuType,omitempty"` - // GpusPerWorker One GPU per worker is currently supported. Historical apps may contain another value. + // GpusPerWorker GPUs granted to one worker pod. Create and update accept only the group sizes the cluster grants indivisibly, since a worker holds its GPUs as one such group. Historical apps may contain another value. GpusPerWorker int32 `json:"gpusPerWorker"` Id openapi_types.UUID `json:"id"` @@ -1783,7 +1820,7 @@ type WorkerConfigCreate struct { // GpuType GPU type the workers run on. Required: omitting it (or sending null) is a 422 before a build or deploy starts, because a GPU app with no type is unpinned and the deployer would render NVIDIA defaults. Must match an `id` returned by `GET /v1/gpu-types` that currently has admitted capacity. GpuType GpuTypeId `json:"gpuType"` - // GpusPerWorker Only 1 is currently supported. Any other value returns 422. + // GpusPerWorker GPUs granted to one worker pod. A worker holds its GPUs as one group the cluster grants indivisibly, so the count is one of the advertised group sizes rather than any number in a range. The value must also be a group size admitted by the cluster backing the chosen `gpuType`: a count above 1 that cluster does not grant is rejected with a 422 naming `/configuration/gpusPerWorker`, since the pod could never be scheduled. A value above 1 requires an image built after the multi-GPU worker entrypoint; older images serve a single rank while holding every granted GPU. GpusPerWorker *int32 `json:"gpusPerWorker,omitempty"` IdleTtlSecs int32 `json:"idleTtlSecs"` MaxWorkers int32 `json:"maxWorkers"` @@ -1806,7 +1843,7 @@ type WorkerConfigPatch struct { // GpuType Preferred GPU type. Omit to leave unchanged. Rejected with a 422 when no capacity is currently offered for the type (it does not appear in `GET /v1/gpu-types`). GpuType *GpuTypeId `json:"gpuType,omitempty"` - // GpusPerWorker Only 1 is currently supported. Any other value returns 422. + // GpusPerWorker GPUs granted to one worker pod. A worker holds its GPUs as one group the cluster grants indivisibly, so the count is one of the advertised group sizes rather than any number in a range. The value must also be a group size admitted by the cluster backing the chosen `gpuType`: a count above 1 that cluster does not grant is rejected with a 422 naming `/configuration/gpusPerWorker`, since the pod could never be scheduled. A value above 1 requires an image built after the multi-GPU worker entrypoint; older images serve a single rank while holding every granted GPU. GpusPerWorker *int32 `json:"gpusPerWorker,omitempty"` IdleTtlSecs *int32 `json:"idleTtlSecs,omitempty"` MaxWorkers *int32 `json:"maxWorkers,omitempty"` @@ -1889,6 +1926,9 @@ type InternalServerError = ProblemDetails // NotFound RFC 9457 problem details. Every error response from this API uses this schema with media type `application/problem+json`. `type` is a URI that identifies the problem class and dereferences to its documentation; clients should switch on `type` (not `status` or `detail`, which are not stable identifiers). Additional members beyond those below may appear. type NotFound = ProblemDetails +// PaymentRequired RFC 9457 problem details. Every error response from this API uses this schema with media type `application/problem+json`. `type` is a URI that identifies the problem class and dereferences to its documentation; clients should switch on `type` (not `status` or `detail`, which are not stable identifiers). Additional members beyond those below may appear. +type PaymentRequired = ProblemDetails + // ServiceUnavailable RFC 9457 problem details. Every error response from this API uses this schema with media type `application/problem+json`. `type` is a URI that identifies the problem class and dereferences to its documentation; clients should switch on `type` (not `status` or `detail`, which are not stable identifiers). Additional members beyond those below may appear. type ServiceUnavailable = ProblemDetails @@ -1909,7 +1949,7 @@ type ListAppsParams struct { // Limit Maximum number of items to return. Limit *Limit `form:"limit,omitempty" json:"limit,omitempty"` - // Cursor Opaque pagination cursor returned as `nextCursor` by a previous call. + // Cursor Opaque pagination cursor returned by a previous call, as `nextCursor` or, on the operations that offer one, `prevCursor`. Cursor *Cursor `form:"cursor,omitempty" json:"cursor,omitempty"` // Status Return only apps in this status. @@ -1928,7 +1968,7 @@ type ListBuildsParams struct { // Limit Maximum number of items to return. Limit *Limit `form:"limit,omitempty" json:"limit,omitempty"` - // Cursor Opaque pagination cursor returned as `nextCursor` by a previous call. + // Cursor Opaque pagination cursor returned by a previous call, as `nextCursor` or, on the operations that offer one, `prevCursor`. Cursor *Cursor `form:"cursor,omitempty" json:"cursor,omitempty"` } @@ -1937,7 +1977,7 @@ type ListEndpointsParams struct { // Limit Maximum number of items to return. Limit *Limit `form:"limit,omitempty" json:"limit,omitempty"` - // Cursor Opaque pagination cursor returned as `nextCursor` by a previous call. + // Cursor Opaque pagination cursor returned by a previous call, as `nextCursor` or, on the operations that offer one, `prevCursor`. Cursor *Cursor `form:"cursor,omitempty" json:"cursor,omitempty"` } @@ -1946,7 +1986,7 @@ type ListAppEnvironmentVariablesParams struct { // Limit Maximum number of items to return. Limit *Limit `form:"limit,omitempty" json:"limit,omitempty"` - // Cursor Opaque pagination cursor returned as `nextCursor` by a previous call. + // Cursor Opaque pagination cursor returned by a previous call, as `nextCursor` or, on the operations that offer one, `prevCursor`. Cursor *Cursor `form:"cursor,omitempty" json:"cursor,omitempty"` } @@ -1955,7 +1995,7 @@ type ListAppErrorsParams struct { // Limit Maximum number of items to return. Limit *Limit `form:"limit,omitempty" json:"limit,omitempty"` - // Cursor Opaque pagination cursor returned as `nextCursor` by a previous call. + // Cursor Opaque pagination cursor returned by a previous call, as `nextCursor` or, on the operations that offer one, `prevCursor`. Cursor *Cursor `form:"cursor,omitempty" json:"cursor,omitempty"` // Window The range to search. Same closed ladder as the metrics queries. Defaults to the last 24 hours. @@ -1976,7 +2016,7 @@ type ListAppEventsParams struct { // Limit Maximum number of items to return. Limit *Limit `form:"limit,omitempty" json:"limit,omitempty"` - // Cursor Opaque pagination cursor returned as `nextCursor` by a previous call. + // Cursor Opaque pagination cursor returned by a previous call, as `nextCursor` or, on the operations that offer one, `prevCursor`. Cursor *Cursor `form:"cursor,omitempty" json:"cursor,omitempty"` Type *AppEventType `form:"type,omitempty" json:"type,omitempty"` } @@ -1986,7 +2026,7 @@ type ListAppSecretsParams struct { // Limit Maximum number of items to return. Limit *Limit `form:"limit,omitempty" json:"limit,omitempty"` - // Cursor Opaque pagination cursor returned as `nextCursor` by a previous call. + // Cursor Opaque pagination cursor returned by a previous call, as `nextCursor` or, on the operations that offer one, `prevCursor`. Cursor *Cursor `form:"cursor,omitempty" json:"cursor,omitempty"` } @@ -1995,7 +2035,7 @@ type ListTasksParams struct { // Limit Maximum number of items to return. Limit *Limit `form:"limit,omitempty" json:"limit,omitempty"` - // Cursor Opaque pagination cursor returned as `nextCursor` by a previous call. + // Cursor Opaque pagination cursor returned by a previous call, as `nextCursor` or, on the operations that offer one, `prevCursor`. Cursor *Cursor `form:"cursor,omitempty" json:"cursor,omitempty"` Status *TaskStatus `form:"status,omitempty" json:"status,omitempty"` } @@ -2005,7 +2045,7 @@ type ListVersionsParams struct { // Limit Maximum number of items to return. Limit *Limit `form:"limit,omitempty" json:"limit,omitempty"` - // Cursor Opaque pagination cursor returned as `nextCursor` by a previous call. + // Cursor Opaque pagination cursor returned by a previous call, as `nextCursor` or, on the operations that offer one, `prevCursor`. Cursor *Cursor `form:"cursor,omitempty" json:"cursor,omitempty"` } @@ -2014,7 +2054,7 @@ type ListWorkersParams struct { // Limit Maximum number of items to return. Limit *Limit `form:"limit,omitempty" json:"limit,omitempty"` - // Cursor Opaque pagination cursor returned as `nextCursor` by a previous call. + // Cursor Opaque pagination cursor returned by a previous call, as `nextCursor` or, on the operations that offer one, `prevCursor`. Cursor *Cursor `form:"cursor,omitempty" json:"cursor,omitempty"` // VersionId Scope the page to one version. The default is the app's `activeVersionId`. When that field is unset the default page is empty: the app has no active version, not that it has no workers. Send `all` (any case) to include every version. An empty value is refused. A cursor must be replayed under the same version scope it was issued with. @@ -2025,6 +2065,9 @@ type ListWorkersParams struct { // A `state` of `live` with a `status` of `stopped` is a contradiction and is refused, because an empty page would read as "this app has never run". State *WorkerStateFilter `form:"state,omitempty" json:"state,omitempty"` Status *WorkerStatus `form:"status,omitempty" json:"status,omitempty"` + + // Q Case-insensitive literal substring match against `id`, `podName`, `nodeName` and `versionId`. A worker matching any field is returned within the selected version, state and status filters. Omit `q` to disable search. Cursors must retain the same search term, ignoring case. + Q *string `form:"q,omitempty" json:"q,omitempty"` } // GetLogEntriesParams defines parameters for GetLogEntries. @@ -2035,9 +2078,12 @@ type GetLogEntriesParams struct { // Limit Maximum number of items to return. Limit *Limit `form:"limit,omitempty" json:"limit,omitempty"` - // Cursor Opaque pagination cursor returned as `nextCursor` by a previous call. + // Cursor Opaque pagination cursor returned by a previous call, as `nextCursor` or, on the operations that offer one, `prevCursor`. Cursor *Cursor `form:"cursor,omitempty" json:"cursor,omitempty"` + // Sort Ordering of a log page and the direction `nextCursor` moves in. Only `getLogEntries` accepts it. + Sort *LogSort `form:"sort,omitempty" json:"sort,omitempty"` + // Deployment Narrow to one app. Deployment *SelectorDeployment `form:"deployment,omitempty" json:"deployment,omitempty"` @@ -2101,7 +2147,7 @@ type ListSecretsParams struct { // Limit Maximum number of items to return. Limit *Limit `form:"limit,omitempty" json:"limit,omitempty"` - // Cursor Opaque pagination cursor returned as `nextCursor` by a previous call. + // Cursor Opaque pagination cursor returned by a previous call, as `nextCursor` or, on the operations that offer one, `prevCursor`. Cursor *Cursor `form:"cursor,omitempty" json:"cursor,omitempty"` } @@ -2110,7 +2156,7 @@ type ListUsageEventsParams struct { // Limit Maximum number of items to return. Limit *Limit `form:"limit,omitempty" json:"limit,omitempty"` - // Cursor Opaque pagination cursor returned as `nextCursor` by a previous call. + // Cursor Opaque pagination cursor returned by a previous call, as `nextCursor` or, on the operations that offer one, `prevCursor`. Cursor *Cursor `form:"cursor,omitempty" json:"cursor,omitempty"` AppId *AppId `form:"appId,omitempty" json:"appId,omitempty"` @@ -2738,7 +2784,7 @@ type ClientInterface interface { // ListWorkers List workers // - // Returns a newest-first page of workers observed for the app (including terminal `stopped` rows until purged). Omitted `versionId` scopes the page to the app's `activeVersionId`. An app with no active version therefore answers an empty default page — not that it has no workers, only that none are pinned. Optional `state` and `status` narrow the page further; a cursor must be replayed under the same filters it was issued with. + // Returns a newest-first page of workers observed for the app (including terminal `stopped` rows until purged). Omitted `versionId` scopes the page to the app's `activeVersionId`. An app with no active version therefore answers an empty default page — not that it has no workers, only that none are pinned. Optional `state`, `status` and `q` narrow the page further; a cursor must be replayed under the same filters it was issued with. // // Corresponds with GET /v1/apps/{appId}/workers (the `ListWorkers` operationId). ListWorkers(ctx context.Context, appId AppId, params *ListWorkersParams, reqEditors ...RequestEditorFn) (*http.Response, error) @@ -2766,7 +2812,7 @@ type ClientInterface interface { // GetLogEntries Read one page of a named log query // - // Returns one page of log entries, newest first, with an opaque cursor for the next page when one exists. Query ids and their supported selectors are listed by the insights catalogue. + // Returns one page of log entries in the requested `sort` order, newest first by default, with opaque cursors for the neighbouring pages when they exist. `nextCursor` continues in the `sort` order and `prevCursor` goes back against it, so a client can walk a window in either direction from either end. A cursor is only valid for the `sort` it was issued under; reusing one under the other ordering returns `400`. Query ids and their supported selectors are listed by the insights catalogue. // // Corresponds with GET /v1/logs/queries/{queryId}/entries (the `GetLogEntries` operationId). GetLogEntries(ctx context.Context, queryId QueryId, params *GetLogEntriesParams, reqEditors ...RequestEditorFn) (*http.Response, error) @@ -3684,7 +3730,7 @@ func (c *Client) GetVersion(ctx context.Context, appId AppId, versionNumber int3 // ListWorkers List workers // -// Returns a newest-first page of workers observed for the app (including terminal `stopped` rows until purged). Omitted `versionId` scopes the page to the app's `activeVersionId`. An app with no active version therefore answers an empty default page — not that it has no workers, only that none are pinned. Optional `state` and `status` narrow the page further; a cursor must be replayed under the same filters it was issued with. +// Returns a newest-first page of workers observed for the app (including terminal `stopped` rows until purged). Omitted `versionId` scopes the page to the app's `activeVersionId`. An app with no active version therefore answers an empty default page — not that it has no workers, only that none are pinned. Optional `state`, `status` and `q` narrow the page further; a cursor must be replayed under the same filters it was issued with. // // Corresponds with GET /v1/apps/{appId}/workers (the `ListWorkers` operationId). func (c *Client) ListWorkers(ctx context.Context, appId AppId, params *ListWorkersParams, reqEditors ...RequestEditorFn) (*http.Response, error) { @@ -3752,7 +3798,7 @@ func (c *Client) GetGpuType(ctx context.Context, gpuTypeId GpuTypeId, reqEditors // GetLogEntries Read one page of a named log query // -// Returns one page of log entries, newest first, with an opaque cursor for the next page when one exists. Query ids and their supported selectors are listed by the insights catalogue. +// Returns one page of log entries in the requested `sort` order, newest first by default, with opaque cursors for the neighbouring pages when they exist. `nextCursor` continues in the `sort` order and `prevCursor` goes back against it, so a client can walk a window in either direction from either end. A cursor is only valid for the `sort` it was issued under; reusing one under the other ordering returns `400`. Query ids and their supported selectors are listed by the insights catalogue. // // Corresponds with GET /v1/logs/queries/{queryId}/entries (the `GetLogEntries` operationId). func (c *Client) GetLogEntries(ctx context.Context, queryId QueryId, params *GetLogEntriesParams, reqEditors ...RequestEditorFn) (*http.Response, error) { @@ -5852,6 +5898,18 @@ func NewListWorkersRequest(server string, appId AppId, params *ListWorkersParams } + if params.Q != nil { + + if queryFrag, err := runtime.StyleParamWithOptions("form", true, "q", *params.Q, runtime.StyleParamOptions{ParamLocation: runtime.ParamLocationQuery, Type: "string", Format: ""}); err != nil { + return nil, err + } else { + for _, qp := range strings.Split(queryFrag, "&") { + rawQueryFragments = append(rawQueryFragments, qp) + } + } + + } + if encoded := queryValues.Encode(); encoded != "" { rawQueryFragments = append(rawQueryFragments, encoded) } @@ -6035,6 +6093,18 @@ func NewGetLogEntriesRequest(server string, queryId QueryId, params *GetLogEntri } + if params.Sort != nil { + + if queryFrag, err := runtime.StyleParamWithOptions("form", true, "sort", *params.Sort, runtime.StyleParamOptions{ParamLocation: runtime.ParamLocationQuery, Type: "string", Format: ""}); err != nil { + return nil, err + } else { + for _, qp := range strings.Split(queryFrag, "&") { + rawQueryFragments = append(rawQueryFragments, qp) + } + } + + } + if params.Deployment != nil { if queryFrag, err := runtime.StyleParamWithOptions("form", true, "deployment", *params.Deployment, runtime.StyleParamOptions{ParamLocation: runtime.ParamLocationQuery, Type: "string", Format: ""}); err != nil { @@ -7391,7 +7461,7 @@ type ClientWithResponsesInterface interface { // ListWorkersWithResponse List workers // - // Returns a newest-first page of workers observed for the app (including terminal `stopped` rows until purged). Omitted `versionId` scopes the page to the app's `activeVersionId`. An app with no active version therefore answers an empty default page — not that it has no workers, only that none are pinned. Optional `state` and `status` narrow the page further; a cursor must be replayed under the same filters it was issued with. + // Returns a newest-first page of workers observed for the app (including terminal `stopped` rows until purged). Omitted `versionId` scopes the page to the app's `activeVersionId`. An app with no active version therefore answers an empty default page — not that it has no workers, only that none are pinned. Optional `state`, `status` and `q` narrow the page further; a cursor must be replayed under the same filters it was issued with. // // Returns a wrapper object for the known response body format(s). // @@ -7427,7 +7497,7 @@ type ClientWithResponsesInterface interface { // GetLogEntriesWithResponse Read one page of a named log query // - // Returns one page of log entries, newest first, with an opaque cursor for the next page when one exists. Query ids and their supported selectors are listed by the insights catalogue. + // Returns one page of log entries in the requested `sort` order, newest first by default, with opaque cursors for the neighbouring pages when they exist. `nextCursor` continues in the `sort` order and `prevCursor` goes back against it, so a client can walk a window in either direction from either end. A cursor is only valid for the `sort` it was issued under; reusing one under the other ordering returns `400`. Query ids and their supported selectors are listed by the insights catalogue. // // Returns a wrapper object for the known response body format(s). // @@ -7778,6 +7848,8 @@ type CreateAppResponse struct { ApplicationproblemJSON400 *BadRequest // ApplicationproblemJSON401 the response for an HTTP 401 `application/problem+json` response ApplicationproblemJSON401 *Unauthorized + // ApplicationproblemJSON402 the response for an HTTP 402 `application/problem+json` response + ApplicationproblemJSON402 *PaymentRequired // ApplicationproblemJSON403 the response for an HTTP 403 `application/problem+json` response ApplicationproblemJSON403 *Forbidden // ApplicationproblemJSON404 the response for an HTTP 404 `application/problem+json` response @@ -7805,6 +7877,11 @@ func (r CreateAppResponse) GetApplicationproblemJSON401() *Unauthorized { return r.ApplicationproblemJSON401 } +// GetApplicationproblemJSON402 returns the response for an HTTP 402 `application/problem+json` response +func (r CreateAppResponse) GetApplicationproblemJSON402() *PaymentRequired { + return r.ApplicationproblemJSON402 +} + // GetApplicationproblemJSON403 returns the response for an HTTP 403 `application/problem+json` response func (r CreateAppResponse) GetApplicationproblemJSON403() *Forbidden { return r.ApplicationproblemJSON403 @@ -8006,6 +8083,8 @@ type UpdateAppResponse struct { ApplicationproblemJSON400 *BadRequest // ApplicationproblemJSON401 the response for an HTTP 401 `application/problem+json` response ApplicationproblemJSON401 *Unauthorized + // ApplicationproblemJSON402 the response for an HTTP 402 `application/problem+json` response + ApplicationproblemJSON402 *PaymentRequired // ApplicationproblemJSON403 the response for an HTTP 403 `application/problem+json` response ApplicationproblemJSON403 *Forbidden // ApplicationproblemJSON404 the response for an HTTP 404 `application/problem+json` response @@ -8033,6 +8112,11 @@ func (r UpdateAppResponse) GetApplicationproblemJSON401() *Unauthorized { return r.ApplicationproblemJSON401 } +// GetApplicationproblemJSON402 returns the response for an HTTP 402 `application/problem+json` response +func (r UpdateAppResponse) GetApplicationproblemJSON402() *PaymentRequired { + return r.ApplicationproblemJSON402 +} + // GetApplicationproblemJSON403 returns the response for an HTTP 403 `application/problem+json` response func (r UpdateAppResponse) GetApplicationproblemJSON403() *Forbidden { return r.ApplicationproblemJSON403 @@ -8354,6 +8438,8 @@ type DeployVersionResponse struct { ApplicationproblemJSON400 *BadRequest // ApplicationproblemJSON401 the response for an HTTP 401 `application/problem+json` response ApplicationproblemJSON401 *Unauthorized + // ApplicationproblemJSON402 the response for an HTTP 402 `application/problem+json` response + ApplicationproblemJSON402 *PaymentRequired // ApplicationproblemJSON403 the response for an HTTP 403 `application/problem+json` response ApplicationproblemJSON403 *Forbidden // ApplicationproblemJSON404 the response for an HTTP 404 `application/problem+json` response @@ -8381,6 +8467,11 @@ func (r DeployVersionResponse) GetApplicationproblemJSON401() *Unauthorized { return r.ApplicationproblemJSON401 } +// GetApplicationproblemJSON402 returns the response for an HTTP 402 `application/problem+json` response +func (r DeployVersionResponse) GetApplicationproblemJSON402() *PaymentRequired { + return r.ApplicationproblemJSON402 +} + // GetApplicationproblemJSON403 returns the response for an HTTP 403 `application/problem+json` response func (r DeployVersionResponse) GetApplicationproblemJSON403() *Forbidden { return r.ApplicationproblemJSON403 @@ -9395,12 +9486,16 @@ type ResumeAppResponse struct { JSON202 *App // ApplicationproblemJSON401 the response for an HTTP 401 `application/problem+json` response ApplicationproblemJSON401 *Unauthorized + // ApplicationproblemJSON402 the response for an HTTP 402 `application/problem+json` response + ApplicationproblemJSON402 *PaymentRequired // ApplicationproblemJSON403 the response for an HTTP 403 `application/problem+json` response ApplicationproblemJSON403 *Forbidden // ApplicationproblemJSON404 the response for an HTTP 404 `application/problem+json` response ApplicationproblemJSON404 *NotFound // ApplicationproblemJSON409 the response for an HTTP 409 `application/problem+json` response ApplicationproblemJSON409 *Conflict + // ApplicationproblemJSON422 the response for an HTTP 422 `application/problem+json` response + ApplicationproblemJSON422 *ValidationError // ApplicationproblemJSON503 the response for an HTTP 503 `application/problem+json` response ApplicationproblemJSON503 *ServiceUnavailable } @@ -9415,6 +9510,11 @@ func (r ResumeAppResponse) GetApplicationproblemJSON401() *Unauthorized { return r.ApplicationproblemJSON401 } +// GetApplicationproblemJSON402 returns the response for an HTTP 402 `application/problem+json` response +func (r ResumeAppResponse) GetApplicationproblemJSON402() *PaymentRequired { + return r.ApplicationproblemJSON402 +} + // GetApplicationproblemJSON403 returns the response for an HTTP 403 `application/problem+json` response func (r ResumeAppResponse) GetApplicationproblemJSON403() *Forbidden { return r.ApplicationproblemJSON403 @@ -9430,6 +9530,11 @@ func (r ResumeAppResponse) GetApplicationproblemJSON409() *Conflict { return r.ApplicationproblemJSON409 } +// GetApplicationproblemJSON422 returns the response for an HTTP 422 `application/problem+json` response +func (r ResumeAppResponse) GetApplicationproblemJSON422() *ValidationError { + return r.ApplicationproblemJSON422 +} + // GetApplicationproblemJSON503 returns the response for an HTTP 503 `application/problem+json` response func (r ResumeAppResponse) GetApplicationproblemJSON503() *ServiceUnavailable { return r.ApplicationproblemJSON503 @@ -12573,7 +12678,7 @@ func (c *ClientWithResponses) GetVersionWithResponse(ctx context.Context, appId // ListWorkersWithResponse List workers // -// Returns a newest-first page of workers observed for the app (including terminal `stopped` rows until purged). Omitted `versionId` scopes the page to the app's `activeVersionId`. An app with no active version therefore answers an empty default page — not that it has no workers, only that none are pinned. Optional `state` and `status` narrow the page further; a cursor must be replayed under the same filters it was issued with. +// Returns a newest-first page of workers observed for the app (including terminal `stopped` rows until purged). Omitted `versionId` scopes the page to the app's `activeVersionId`. An app with no active version therefore answers an empty default page — not that it has no workers, only that none are pinned. Optional `state`, `status` and `q` narrow the page further; a cursor must be replayed under the same filters it was issued with. // // Returns a wrapper object for the known response body format(s). // @@ -12633,7 +12738,7 @@ func (c *ClientWithResponses) GetGpuTypeWithResponse(ctx context.Context, gpuTyp // GetLogEntriesWithResponse Read one page of a named log query // -// Returns one page of log entries, newest first, with an opaque cursor for the next page when one exists. Query ids and their supported selectors are listed by the insights catalogue. +// Returns one page of log entries in the requested `sort` order, newest first by default, with opaque cursors for the neighbouring pages when they exist. `nextCursor` continues in the `sort` order and `prevCursor` goes back against it, so a client can walk a window in either direction from either end. A cursor is only valid for the `sort` it was issued under; reusing one under the other ordering returns `400`. Query ids and their supported selectors are listed by the insights catalogue. // // Returns a wrapper object for the known response body format(s). // @@ -13088,6 +13193,13 @@ func ParseCreateAppResponse(rsp *http.Response) (*CreateAppResponse, error) { } response.ApplicationproblemJSON401 = &dest + case strings.Contains(rsp.Header.Get("Content-Type"), "json") && rsp.StatusCode == 402: + var dest PaymentRequired + if err := json.Unmarshal(bodyBytes, &dest); err != nil { + return nil, err + } + response.ApplicationproblemJSON402 = &dest + case strings.Contains(rsp.Header.Get("Content-Type"), "json") && rsp.StatusCode == 403: var dest Forbidden if err := json.Unmarshal(bodyBytes, &dest); err != nil { @@ -13271,6 +13383,13 @@ func ParseUpdateAppResponse(rsp *http.Response) (*UpdateAppResponse, error) { } response.ApplicationproblemJSON401 = &dest + case strings.Contains(rsp.Header.Get("Content-Type"), "json") && rsp.StatusCode == 402: + var dest PaymentRequired + if err := json.Unmarshal(bodyBytes, &dest); err != nil { + return nil, err + } + response.ApplicationproblemJSON402 = &dest + case strings.Contains(rsp.Header.Get("Content-Type"), "json") && rsp.StatusCode == 403: var dest Forbidden if err := json.Unmarshal(bodyBytes, &dest); err != nil { @@ -13554,6 +13673,13 @@ func ParseDeployVersionResponse(rsp *http.Response) (*DeployVersionResponse, err } response.ApplicationproblemJSON401 = &dest + case strings.Contains(rsp.Header.Get("Content-Type"), "json") && rsp.StatusCode == 402: + var dest PaymentRequired + if err := json.Unmarshal(bodyBytes, &dest); err != nil { + return nil, err + } + response.ApplicationproblemJSON402 = &dest + case strings.Contains(rsp.Header.Get("Content-Type"), "json") && rsp.StatusCode == 403: var dest Forbidden if err := json.Unmarshal(bodyBytes, &dest); err != nil { @@ -14399,6 +14525,13 @@ func ParseResumeAppResponse(rsp *http.Response) (*ResumeAppResponse, error) { } response.ApplicationproblemJSON401 = &dest + case strings.Contains(rsp.Header.Get("Content-Type"), "json") && rsp.StatusCode == 402: + var dest PaymentRequired + if err := json.Unmarshal(bodyBytes, &dest); err != nil { + return nil, err + } + response.ApplicationproblemJSON402 = &dest + case strings.Contains(rsp.Header.Get("Content-Type"), "json") && rsp.StatusCode == 403: var dest Forbidden if err := json.Unmarshal(bodyBytes, &dest); err != nil { @@ -14420,6 +14553,13 @@ func ParseResumeAppResponse(rsp *http.Response) (*ResumeAppResponse, error) { } response.ApplicationproblemJSON409 = &dest + case strings.Contains(rsp.Header.Get("Content-Type"), "json") && rsp.StatusCode == 422: + var dest ValidationError + if err := json.Unmarshal(bodyBytes, &dest); err != nil { + return nil, err + } + response.ApplicationproblemJSON422 = &dest + case strings.Contains(rsp.Header.Get("Content-Type"), "json") && rsp.StatusCode == 503: var dest ServiceUnavailable if err := json.Unmarshal(bodyBytes, &dest); err != nil { diff --git a/internal/api/serverless/logs.go b/internal/api/serverless/logs.go index 9598951..5ce2c6f 100644 --- a/internal/api/serverless/logs.go +++ b/internal/api/serverless/logs.go @@ -16,10 +16,20 @@ import ( // LogEntry is one application log line. type LogEntry = gen.LogEntry -// LogEntryPage is one page of log entries, newest first. +// LogEntryPage is one page of log entries in the requested sort order. type LogEntryPage = gen.LogEntryPage -// GetLogEntriesParams narrows a log page: window, page size, cursor, app and endpoint. +// LogSort is the ordering of a log page. +type LogSort = gen.LogSort + +const ( + // LogSortNewest lists newest first; nextCursor walks older. + LogSortNewest LogSort = gen.Newest + // LogSortOldest lists oldest first; nextCursor walks newer. + LogSortOldest LogSort = gen.Oldest +) + +// GetLogEntriesParams narrows a log page: window, page size, cursor, sort, app and endpoint. type GetLogEntriesParams = gen.GetLogEntriesParams // LogWindow is the closed set of time windows a log query accepts.