zuplo 7.7.9 → 7.7.11
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/docs/ai-gateway/azure-ai.mdx +70 -14
- package/docs/ai-gateway/bedrock-mantle.mdx +5 -1
- package/docs/ai-gateway/integrations/claude-code.mdx +193 -22
- package/docs/ai-gateway/integrations/github-copilot.mdx +165 -0
- package/docs/ai-gateway/providers.mdx +9 -5
- package/docs/ai-gateway/universal-api.mdx +1 -1
- package/docs/ai-gateway/vertex-ai.mdx +6 -1
- package/docs/policies/ai-gateway-configuration-executor-v2-inbound/doc.md +21 -89
- package/docs/policies/ai-gateway-metering-v2-inbound/doc.md +156 -0
- package/docs/policies/ai-gateway-metering-v2-inbound/intro.md +4 -0
- package/docs/policies/ai-gateway-metering-v2-inbound/schema.json +12 -6
- package/docs/self-hosted/install.md +35 -1
- package/docs/self-hosted/overview.md +4 -4
- package/docs/self-hosted/troubleshooting.md +3 -2
- package/docs/self-hosted/upgrade.md +5 -5
- package/package.json +5 -5
- package/docs/self-hosted/verify.md +0 -279
|
@@ -355,34 +355,23 @@ have both actions, the `warn` value must be less than the `block` value. The
|
|
|
355
355
|
policy does not treat entries whose `budgetBy` is `app` as expression budget
|
|
356
356
|
rules.
|
|
357
357
|
|
|
358
|
-
###
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
| Custom context data | `context.custom.account.id` |
|
|
373
|
-
| Route data | `context.route.path` |
|
|
374
|
-
| Incoming request data | `context.incomingRequestProperties.country` |
|
|
375
|
-
| Request or context identity | `request.user.sub`, `context.requestId` |
|
|
376
|
-
| A key requiring brackets | `request.user.data["team-id"]` |
|
|
377
|
-
|
|
378
|
-
The `expression` field contains the complete expression. Do not wrap it in an
|
|
379
|
-
interpolation marker such as `${...}`. Expressions use values from the request
|
|
380
|
-
and context, including values set by earlier policies. Place policies that set
|
|
381
|
-
these values before Semantic Cache. You can change an expression in the
|
|
358
|
+
### Expressions
|
|
359
|
+
|
|
360
|
+
An expression selects one value from the request or its context, such as
|
|
361
|
+
`request.headers.get("x-user-id")` or `request.user.data["team-id"]`. Every
|
|
362
|
+
distinct value gets its own budget.
|
|
363
|
+
|
|
364
|
+
The expression grammar, the selectable properties, what a value must be, and
|
|
365
|
+
what happens when an expression does not resolve are documented once, on the
|
|
366
|
+
[AI Gateway Metering](/docs/policies/ai-gateway-metering-v2-inbound) policy
|
|
367
|
+
page. The same grammar applies here.
|
|
368
|
+
|
|
369
|
+
Two things are specific to application configuration. A policy that sets a value
|
|
370
|
+
an expression reads must run before Semantic Cache, which can answer without
|
|
371
|
+
reaching the rest of the chain. And you can change an expression in the
|
|
382
372
|
application configuration without rebuilding or redeploying the gateway.
|
|
383
373
|
|
|
384
|
-
|
|
385
|
-
the double quotes required by a bracket segment:
|
|
374
|
+
When writing raw JSON, escape the double quotes a bracket segment needs:
|
|
386
375
|
|
|
387
376
|
```json
|
|
388
377
|
{
|
|
@@ -390,58 +379,14 @@ the double quotes required by a bracket segment:
|
|
|
390
379
|
}
|
|
391
380
|
```
|
|
392
381
|
|
|
393
|
-
After a JSON parser decodes
|
|
382
|
+
After a JSON parser decodes that value the expression is
|
|
394
383
|
`request.user.data["team-id"]`; the backslashes are not part of its identity.
|
|
395
|
-
Code that
|
|
396
|
-
let its JSON serializer
|
|
384
|
+
Code that builds application configuration should create an ordinary string and
|
|
385
|
+
let its JSON serializer add the transport escaping.
|
|
397
386
|
|
|
398
|
-
|
|
399
|
-
|
|
400
|
-
|
|
401
|
-
```
|
|
402
|
-
|
|
403
|
-
Header expressions are terminal. Header names are case-insensitive; use
|
|
404
|
-
lowercase in stored expressions. The parser accepts the canonical
|
|
405
|
-
`request.headers.get("content-type")` form and the equivalent
|
|
406
|
-
`request.headers.content-type` and `request.headers["content-type"]` forms. The
|
|
407
|
-
canonical form keeps header access visually distinct from an ordinary object
|
|
408
|
-
property.
|
|
409
|
-
|
|
410
|
-
A dot property starts with an ASCII letter, `_`, or `$`, followed by those
|
|
411
|
-
characters, ASCII digits, or hyphens. Canonical rendering uses quoted brackets
|
|
412
|
-
for keys containing `$` or `-`, or any other non-identifier character. For
|
|
413
|
-
example, `context.custom.team-id` is accepted and its canonical form is
|
|
414
|
-
`context.custom["team-id"]`. Single- and double-quoted bracket properties are
|
|
415
|
-
accepted. Whitespace immediately inside brackets is accepted but is not
|
|
416
|
-
canonical.
|
|
417
|
-
|
|
418
|
-
The selectable data model is:
|
|
419
|
-
|
|
420
|
-
| Root | Selectable properties |
|
|
421
|
-
| --------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
|
422
|
-
| `request` | `url`, `method`, `headers`, `user.sub`, `user.data`, `query`, `searchParams`, `params`, and the scalar Fetch request metadata `bodyUsed`, `cache`, `credentials`, `destination`, `integrity`, `keepalive`, `mode`, `redirect`, `referrer`, and `referrerPolicy` |
|
|
423
|
-
| `context` | `contextId`, `requestId`, `custom`, `route`, and `incomingRequestProperties` |
|
|
424
|
-
|
|
425
|
-
Expressions cannot read the request body, call logging or policy methods, or
|
|
426
|
-
access properties outside this table.
|
|
427
|
-
|
|
428
|
-
Expressions have these limits:
|
|
429
|
-
|
|
430
|
-
- The expression is at most 1,024 UTF-8 bytes and contains well-formed Unicode.
|
|
431
|
-
- Quoted keys are non-empty and do not contain double quotes, backslashes,
|
|
432
|
-
control characters, U+2028, or U+2029. String escapes are not supported.
|
|
433
|
-
- Canonical expressions contain no syntax whitespace. Spaces inside a quoted key
|
|
434
|
-
are part of the key.
|
|
435
|
-
- Wildcards, recursive descent, filters, numeric bracket indexes, calls other
|
|
436
|
-
than the terminal header `.get("name")`, function arguments, and roots other
|
|
437
|
-
than `request` and `context` are not supported. For example,
|
|
438
|
-
`request.url.substring(5, 1)` is not a supported expression.
|
|
439
|
-
- Traversal reads own properties from plain objects and keys from declared Maps.
|
|
440
|
-
It does not traverse arrays, class instances, inherited properties, or the
|
|
441
|
-
property names `__proto__`, `constructor`, and `prototype`.
|
|
442
|
-
|
|
443
|
-
An authentication policy can populate `request.user`. A custom policy earlier in
|
|
444
|
-
the chain can derive a value and place it in a request header:
|
|
387
|
+
An expression selects one value and cannot combine several. To budget by a
|
|
388
|
+
composite value, compute it in a custom policy earlier in the chain and store it
|
|
389
|
+
somewhere an expression can read:
|
|
445
390
|
|
|
446
391
|
```ts
|
|
447
392
|
import { ZuploContext, ZuploRequest } from "@zuplo/runtime";
|
|
@@ -463,19 +408,6 @@ The corresponding expression is `request.headers.get("x-budget-customer")`.
|
|
|
463
408
|
Configuration code should create that ordinary string and pass the enclosing
|
|
464
409
|
object to `JSON.stringify`; the serializer adds the JSON transport escaping.
|
|
465
410
|
|
|
466
|
-
The expression chooses one value; it does not concatenate values, run
|
|
467
|
-
JavaScript, or evaluate conditions. Compute composite values in an earlier
|
|
468
|
-
policy and store the result in a supported request or context property.
|
|
469
|
-
|
|
470
|
-
The selected value must be a string or a safe integer. The runtime converts the
|
|
471
|
-
value to well-formed NFC Unicode and ignores it when it exceeds 256 UTF-8 bytes
|
|
472
|
-
or contains control characters, U+2028, or U+2029. A missing or invalid value
|
|
473
|
-
does not contribute to the rule for that request.
|
|
474
|
-
|
|
475
|
-
Use consistent spelling for each expression. Different spellings, such as single
|
|
476
|
-
quotes and double quotes, identify different budget rules even when they select
|
|
477
|
-
the same value.
|
|
478
|
-
|
|
479
411
|
Invalid budget rules and unsupported expressions are logged and skipped. Other
|
|
480
412
|
valid rules continue to apply.
|
|
481
413
|
|
|
@@ -68,6 +68,162 @@ value of its expression. An action of `"warn"` notifies without blocking. An
|
|
|
68
68
|
action of `"block"` activates the configured quota fallback or returns
|
|
69
69
|
`429 Too Many Requests` when usage reaches the value.
|
|
70
70
|
|
|
71
|
+
## Budget expressions
|
|
72
|
+
|
|
73
|
+
A rule with `"budgetBy": "expression"` gives every distinct value of its
|
|
74
|
+
expression its own budget. A daily cost budget of five dollars on
|
|
75
|
+
`request.headers.get("x-user-id")` gives each user five dollars a day, rather
|
|
76
|
+
than five dollars shared across all users.
|
|
77
|
+
|
|
78
|
+
An expression selects one value from the request or its context. It is a
|
|
79
|
+
selector, not code: there are no comparisons, arithmetic, string concatenation,
|
|
80
|
+
or method calls other than the header accessor below.
|
|
81
|
+
|
|
82
|
+
### Supported expressions
|
|
83
|
+
|
|
84
|
+
| Expression | Example | Selects |
|
|
85
|
+
| ------------------------------------------ | ------------------------------------------- | --------------------------------------------------------------- |
|
|
86
|
+
| `request.headers.get("<name>")` | `request.headers.get("x-user-id")` | One request header. Header names are case-insensitive. |
|
|
87
|
+
| `request.query.<name>` | `request.query.tenant` | One query-string parameter. |
|
|
88
|
+
| `request.searchParams.<name>` | `request.searchParams.tenant` | One query-string parameter. |
|
|
89
|
+
| `request.params.<name>` | `request.params.customerId` | One path parameter from the matched route. |
|
|
90
|
+
| `request.user.sub` | `request.user.sub` | The authenticated consumer's subject, such as the API key name. |
|
|
91
|
+
| `request.user.data.<property>` | `request.user.data.organizationId` | A property of the consumer's metadata, including nested ones. |
|
|
92
|
+
| `request.<property>` | `request.method` | A scalar request property. |
|
|
93
|
+
| `context.custom.<property>` | `context.custom.tenantId` | A value your own policies or handlers put on `context.custom`. |
|
|
94
|
+
| `context.route.<property>` | `context.route.path` | A property of the matched route, such as `path` or `label`. |
|
|
95
|
+
| `context.incomingRequestProperties.<name>` | `context.incomingRequestProperties.country` | A connection property, such as `country`, `city`, or `asn`. |
|
|
96
|
+
|
|
97
|
+
The selectable scalar request properties are `bodyUsed`, `cache`, `credentials`,
|
|
98
|
+
`destination`, `integrity`, `keepalive`, `method`, `mode`, `redirect`,
|
|
99
|
+
`referrer`, `referrerPolicy`, and `url`.
|
|
100
|
+
|
|
101
|
+
Use quoted brackets for any key that is not a plain identifier:
|
|
102
|
+
`request.query["team-id"]`, `context.custom["tenant.id"]`.
|
|
103
|
+
|
|
104
|
+
`context.incomingRequestProperties` exposes connection data only: `country`,
|
|
105
|
+
`city`, `region`, `regionCode`, `continent`, `colo`, `latitude`, `longitude`,
|
|
106
|
+
`postalCode`, `metroCode`, `timezone`, `ip`, `asn`, `asOrganization`, and
|
|
107
|
+
`httpProtocol`. Client-certificate and mTLS verification fields are not
|
|
108
|
+
selectable. To budget per client certificate, run the mTLS Authentication policy
|
|
109
|
+
first and select the metadata it attaches, such as
|
|
110
|
+
`request.user.data.mtlsAuth.sha256Fingerprint`.
|
|
111
|
+
|
|
112
|
+
An expression is limited to 1024 bytes and 32 property segments.
|
|
113
|
+
|
|
114
|
+
### Examples
|
|
115
|
+
|
|
116
|
+
Give every end user their own daily spend budget, keyed by a header your
|
|
117
|
+
application sends:
|
|
118
|
+
|
|
119
|
+
```json
|
|
120
|
+
{
|
|
121
|
+
"budgetBy": "expression",
|
|
122
|
+
"expression": "request.headers.get(\"x-user-id\")",
|
|
123
|
+
"meters": [
|
|
124
|
+
{ "meter": "cost", "period": "daily", "value": 5, "action": "block" }
|
|
125
|
+
]
|
|
126
|
+
}
|
|
127
|
+
```
|
|
128
|
+
|
|
129
|
+
Give every customer of yours their own monthly token budget, keyed by metadata
|
|
130
|
+
on the API key that made the request:
|
|
131
|
+
|
|
132
|
+
```json
|
|
133
|
+
{
|
|
134
|
+
"budgetBy": "expression",
|
|
135
|
+
"expression": "request.user.data.organizationId",
|
|
136
|
+
"meters": [
|
|
137
|
+
{
|
|
138
|
+
"meter": "tokens",
|
|
139
|
+
"period": "monthly",
|
|
140
|
+
"value": 8000000,
|
|
141
|
+
"action": "warn"
|
|
142
|
+
},
|
|
143
|
+
{
|
|
144
|
+
"meter": "tokens",
|
|
145
|
+
"period": "monthly",
|
|
146
|
+
"value": 10000000,
|
|
147
|
+
"action": "block"
|
|
148
|
+
}
|
|
149
|
+
]
|
|
150
|
+
}
|
|
151
|
+
```
|
|
152
|
+
|
|
153
|
+
Cap requests per tenant per hour, keyed by a path parameter on a route such as
|
|
154
|
+
`/tenants/:tenantId/chat`:
|
|
155
|
+
|
|
156
|
+
```json
|
|
157
|
+
{
|
|
158
|
+
"budgetBy": "expression",
|
|
159
|
+
"expression": "request.params.tenantId",
|
|
160
|
+
"meters": [
|
|
161
|
+
{
|
|
162
|
+
"meter": "requests",
|
|
163
|
+
"period": "hourly",
|
|
164
|
+
"value": 1000,
|
|
165
|
+
"action": "block"
|
|
166
|
+
}
|
|
167
|
+
]
|
|
168
|
+
}
|
|
169
|
+
```
|
|
170
|
+
|
|
171
|
+
### Values
|
|
172
|
+
|
|
173
|
+
An expression must resolve to a string or a safe integer. The runtime converts
|
|
174
|
+
the value to well-formed NFC Unicode, and ignores it when it exceeds 256 UTF-8
|
|
175
|
+
bytes or contains control characters, U+2028, or U+2029. Values are
|
|
176
|
+
case-sensitive, so `Acme` and `acme` get separate budgets, but two strings that
|
|
177
|
+
normalize to the same NFC text share one budget.
|
|
178
|
+
|
|
179
|
+
When an expression resolves to nothing, or to something else such as an object,
|
|
180
|
+
an array, or a fractional number, that rule does not count or block the request.
|
|
181
|
+
Other rules still apply. Pair a rule on a value you must enforce with a policy
|
|
182
|
+
that rejects requests missing it, such as API key authentication or request
|
|
183
|
+
validation.
|
|
184
|
+
|
|
185
|
+
### Not supported
|
|
186
|
+
|
|
187
|
+
| Not supported | Use instead |
|
|
188
|
+
| ---------------------------------------------------- | ------------------------------------------------------------------- |
|
|
189
|
+
| Request body values, such as `request.body.userId` | A header, a query parameter, a path parameter, or API key metadata. |
|
|
190
|
+
| Whole objects, such as `request.headers` | One value, such as `request.headers.get("x-user-id")`. |
|
|
191
|
+
| Comparisons, `&&`, ternaries, and literals | One selector per rule. An application can have up to five rules. |
|
|
192
|
+
| String methods, such as `.toLowerCase()` | The value as the client sends it. |
|
|
193
|
+
| Wildcards and multiple keys in one expression | One rule per value you want to budget. |
|
|
194
|
+
| Arrays, class instances, and inherited properties | A plain value the gateway or your own policy sets. |
|
|
195
|
+
| Per-request identifiers, such as `context.requestId` | A value shared by many requests, such as a user or tenant. |
|
|
196
|
+
|
|
197
|
+
An unsupported expression does not fail the request. The rule is skipped, and
|
|
198
|
+
the request is not budgeted by it.
|
|
199
|
+
|
|
200
|
+
### Keep the spelling stable
|
|
201
|
+
|
|
202
|
+
Each expression is stored exactly as you write it, and its budgets are tracked
|
|
203
|
+
under that exact text. `request.headers.get("x-user-id")` and
|
|
204
|
+
`request.headers["x-user-id"]` read the same header but keep separate budgets,
|
|
205
|
+
and editing a rule's expression starts its budgets over. Single quotes and
|
|
206
|
+
double quotes likewise identify different rules. Use the spellings in the table
|
|
207
|
+
above.
|
|
208
|
+
|
|
209
|
+
Several forms parse, so prefer the canonical one. A header is written
|
|
210
|
+
`request.headers.get("content-type")`, with a lowercase name; the equivalent
|
|
211
|
+
`request.headers.content-type` and `request.headers["content-type"]` are
|
|
212
|
+
accepted but keep separate budgets. A dot property starts with a letter, `_`, or
|
|
213
|
+
`$`; a key containing anything else takes quoted brackets, so
|
|
214
|
+
`context.custom.team-id` is canonically `context.custom["team-id"]`.
|
|
215
|
+
|
|
216
|
+
In raw JSON, escape the double quotes a bracket segment needs:
|
|
217
|
+
|
|
218
|
+
```json
|
|
219
|
+
{
|
|
220
|
+
"expression": "request.user.data[\"team-id\"]"
|
|
221
|
+
}
|
|
222
|
+
```
|
|
223
|
+
|
|
224
|
+
After a JSON parser decodes that value the expression is
|
|
225
|
+
`request.user.data["team-id"]`; the backslashes are not part of its identity.
|
|
226
|
+
|
|
71
227
|
## Team limits
|
|
72
228
|
|
|
73
229
|
Application budgets apply only to that application. Parent team and gateway
|
|
@@ -3,6 +3,10 @@ requests and enforces spend, token, and request budgets. When a limit is
|
|
|
3
3
|
exceeded, it uses the model selection's quota fallback when one is configured or
|
|
4
4
|
returns `429 Too Many Requests`.
|
|
5
5
|
|
|
6
|
+
A budget rule covers the whole application, or gives every distinct value of an
|
|
7
|
+
expression its own budget, such as one budget per user with
|
|
8
|
+
`request.headers.get("x-user-id")`.
|
|
9
|
+
|
|
6
10
|
Place it after Model Filtering and Fallback Model, and before policies such as
|
|
7
11
|
Semantic Cache that may answer without calling a provider. Metering fails open
|
|
8
12
|
by default when its service is unavailable; set `throwOnFailure` to `true` to
|
|
@@ -77,17 +77,19 @@
|
|
|
77
77
|
"properties": {
|
|
78
78
|
"budgetBy": {
|
|
79
79
|
"type": "string",
|
|
80
|
-
"enum": ["app", "expression"]
|
|
80
|
+
"enum": ["app", "expression"],
|
|
81
|
+
"description": "Budget the application as a whole (\"app\"), or give every distinct value of an expression its own budget (\"expression\")."
|
|
81
82
|
},
|
|
82
83
|
"expression": {
|
|
83
84
|
"type": "string",
|
|
84
85
|
"minLength": 1,
|
|
85
|
-
"description": "Required when budgetBy is \"expression\"; forbidden for \"app\". Each distinct value gets its own budget."
|
|
86
|
+
"description": "Required when budgetBy is \"expression\"; forbidden for \"app\". Each distinct value gets its own budget. Select one value from the request or its context: request.headers.get(\"x-user-id\"), request.query.tenant, request.params.customerId, request.user.sub, request.user.data.organizationId, request.method, request.url, context.custom.tenantId, context.route.path, or context.incomingRequestProperties.country. Comparisons, arithmetic, string methods, and request body values are not supported."
|
|
86
87
|
},
|
|
87
88
|
"meters": {
|
|
88
89
|
"type": "array",
|
|
89
90
|
"minItems": 1,
|
|
90
91
|
"maxItems": 24,
|
|
92
|
+
"description": "Thresholds this rule enforces. Add one entry per meter, period, and action you want.",
|
|
91
93
|
"items": {
|
|
92
94
|
"type": "object",
|
|
93
95
|
"additionalProperties": false,
|
|
@@ -95,19 +97,23 @@
|
|
|
95
97
|
"properties": {
|
|
96
98
|
"meter": {
|
|
97
99
|
"type": "string",
|
|
98
|
-
"enum": ["cost", "requests", "tokens"]
|
|
100
|
+
"enum": ["cost", "requests", "tokens"],
|
|
101
|
+
"description": "What to measure: US dollars spent (\"cost\"), requests made (\"requests\"), or tokens used (\"tokens\")."
|
|
99
102
|
},
|
|
100
103
|
"period": {
|
|
101
104
|
"type": "string",
|
|
102
|
-
"enum": ["hourly", "daily", "weekly", "monthly"]
|
|
105
|
+
"enum": ["hourly", "daily", "weekly", "monthly"],
|
|
106
|
+
"description": "How often usage resets."
|
|
103
107
|
},
|
|
104
108
|
"value": {
|
|
105
109
|
"type": "number",
|
|
106
|
-
"exclusiveMinimum": 0
|
|
110
|
+
"exclusiveMinimum": 0,
|
|
111
|
+
"description": "The threshold for this meter and period. Cost is in US dollars."
|
|
107
112
|
},
|
|
108
113
|
"action": {
|
|
109
114
|
"type": "string",
|
|
110
|
-
"enum": ["warn", "block"]
|
|
115
|
+
"enum": ["warn", "block"],
|
|
116
|
+
"description": "What happens at the threshold: \"warn\" notifies and lets the request through, \"block\" uses the configured quota fallback model or returns 429 Too Many Requests."
|
|
111
117
|
}
|
|
112
118
|
}
|
|
113
119
|
}
|
|
@@ -168,4 +168,38 @@ Certificates can't be issued until these records resolve. cert-manager checks
|
|
|
168
168
|
the challenge URL from inside the cluster before it contacts the certificate
|
|
169
169
|
authority.
|
|
170
170
|
|
|
171
|
-
|
|
171
|
+
## Verify your installation
|
|
172
|
+
|
|
173
|
+
Use the [Zuplo self-hosted doctor](https://github.com/zuplo/self-hosted-doctor)
|
|
174
|
+
to check the installation. Doctor is a CLI that reads your installation through
|
|
175
|
+
your kubeconfig and probes its DNS, TLS, and HTTP endpoints. It checks the Helm
|
|
176
|
+
release, the `Configuration` resource, Deployment health, ingress reachability,
|
|
177
|
+
certificate issuance, DNS records, the management API, and the builder
|
|
178
|
+
configuration. It reads the installation and doesn't change it.
|
|
179
|
+
|
|
180
|
+
Download the archive for your machine from the
|
|
181
|
+
[releases page](https://github.com/zuplo/self-hosted-doctor/releases), verify
|
|
182
|
+
its checksum, extract it, and run the full suite against your current kubeconfig
|
|
183
|
+
context:
|
|
184
|
+
|
|
185
|
+
```bash
|
|
186
|
+
./zuplo-self-hosted-doctor verify
|
|
187
|
+
```
|
|
188
|
+
|
|
189
|
+
Doctor exits `0` when no check failed, `1` when a check failed, and `3` when it
|
|
190
|
+
couldn't run. Each warning and failure names a diagnostic step and links to the
|
|
191
|
+
matching entry in [Troubleshooting](./troubleshooting.md).
|
|
192
|
+
|
|
193
|
+
To also check authenticated access to the management API, set `ZUPLO_API_KEY` in
|
|
194
|
+
your shell before running `verify`. Without a key, Doctor checks only that
|
|
195
|
+
unauthenticated requests are rejected.
|
|
196
|
+
|
|
197
|
+
The repository's README covers selecting individual checks, comparing a local
|
|
198
|
+
values file, private certificate authorities, and JSON output.
|
|
199
|
+
|
|
200
|
+
:::note
|
|
201
|
+
|
|
202
|
+
Doctor doesn't deploy a project. To confirm the full build-and-serve path, run
|
|
203
|
+
`npx zuplo deploy` against your account after Doctor passes.
|
|
204
|
+
|
|
205
|
+
:::
|
|
@@ -184,10 +184,10 @@ images, and the credentials to pull them.
|
|
|
184
184
|
## Get started
|
|
185
185
|
|
|
186
186
|
1. Review the [requirements](./requirements.md) and run the preflight checks.
|
|
187
|
-
2. [Install](./install.md) the Helm chart
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
187
|
+
2. [Install](./install.md) the Helm chart, then verify the installation with the
|
|
188
|
+
[Zuplo self-hosted doctor](https://github.com/zuplo/self-hosted-doctor) CLI.
|
|
189
|
+
3. [Upgrade](./upgrade.md) to later chart versions when needed.
|
|
190
|
+
4. Use [troubleshooting](./troubleshooting.md) to resolve installation and
|
|
191
191
|
deployment errors.
|
|
192
192
|
|
|
193
193
|
To discuss your specific requirements,
|
|
@@ -202,8 +202,9 @@ to HTTPS.
|
|
|
202
202
|
|
|
203
203
|
This redirect doesn't affect certificate issuance. cert-manager creates a
|
|
204
204
|
separate challenge Ingress that continues to serve on port 80. To test the
|
|
205
|
-
ingress, use a hostname with no Ingress
|
|
206
|
-
[
|
|
205
|
+
ingress, use a hostname with no Ingress. The
|
|
206
|
+
[Zuplo self-hosted doctor](https://github.com/zuplo/self-hosted-doctor) CLI does
|
|
207
|
+
this for you in its `ingress-reachable` check.
|
|
207
208
|
|
|
208
209
|
## Failed to deploy the environment but the cluster shows the build succeeding
|
|
209
210
|
|
|
@@ -41,13 +41,13 @@ installed with `helm plugin install https://github.com/databus23/helm-diff`.
|
|
|
41
41
|
|
|
42
42
|
## Verify the upgrade
|
|
43
43
|
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
44
|
+
Run the [Zuplo self-hosted doctor](https://github.com/zuplo/self-hosted-doctor)
|
|
45
|
+
CLI again and confirm the release history records the new revision. The gateway
|
|
46
|
+
deployments already in the cluster keep serving through the upgrade; they are
|
|
47
|
+
rebuilt only when you deploy them.
|
|
47
48
|
|
|
48
49
|
```bash
|
|
49
|
-
|
|
50
|
-
-n zuplo-system --timeout=5m
|
|
50
|
+
./zuplo-self-hosted-doctor verify
|
|
51
51
|
helm history zuplo -n zuplo
|
|
52
52
|
```
|
|
53
53
|
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "zuplo",
|
|
3
|
-
"version": "7.7.
|
|
3
|
+
"version": "7.7.11",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"description": "The official Zuplo CLI for local development and platform management",
|
|
6
6
|
"homepage": "https://zuplo.com/docs/cli/overview",
|
|
@@ -32,9 +32,9 @@
|
|
|
32
32
|
"zuplo": "zuplo.js"
|
|
33
33
|
},
|
|
34
34
|
"dependencies": {
|
|
35
|
-
"@zuplo/cli": "7.7.
|
|
36
|
-
"@zuplo/core": "7.7.
|
|
37
|
-
"@zuplo/runtime": "7.7.
|
|
38
|
-
"@zuplo/test": "7.7.
|
|
35
|
+
"@zuplo/cli": "7.7.11",
|
|
36
|
+
"@zuplo/core": "7.7.11",
|
|
37
|
+
"@zuplo/runtime": "7.7.11",
|
|
38
|
+
"@zuplo/test": "7.7.11"
|
|
39
39
|
}
|
|
40
40
|
}
|