@r8s/recipes 0.2.0 → 0.2.1
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/dist/app.d.ts.map +1 -1
- package/dist/app.js +1 -2
- package/dist/app.js.map +1 -1
- package/dist/auth.d.ts.map +1 -1
- package/dist/auth.js +48 -84
- package/dist/auth.js.map +1 -1
- package/dist/database.d.ts +17 -0
- package/dist/database.d.ts.map +1 -1
- package/dist/database.js +33 -36
- package/dist/database.js.map +1 -1
- package/dist/endpoint.d.ts +1 -1
- package/dist/endpoint.d.ts.map +1 -1
- package/dist/endpoint.js +20 -3
- package/dist/endpoint.js.map +1 -1
- package/dist/errors.d.ts +16 -0
- package/dist/errors.d.ts.map +1 -0
- package/dist/errors.js +19 -0
- package/dist/errors.js.map +1 -0
- package/dist/index.d.ts +4 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +11 -1
- package/dist/index.js.map +1 -1
- package/dist/operators.d.ts +16 -2
- package/dist/operators.d.ts.map +1 -1
- package/dist/operators.js +26 -0
- package/dist/operators.js.map +1 -1
- package/dist/secret-provider.d.ts +10 -1
- package/dist/secret-provider.d.ts.map +1 -1
- package/dist/secret-provider.js +74 -0
- package/dist/secret-provider.js.map +1 -1
- package/dist/static-secret.d.ts +107 -0
- package/dist/static-secret.d.ts.map +1 -0
- package/dist/static-secret.js +87 -0
- package/dist/static-secret.js.map +1 -0
- package/dist/web-service.d.ts +10 -2
- package/dist/web-service.d.ts.map +1 -1
- package/dist/web-service.js +52 -9
- package/dist/web-service.js.map +1 -1
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
// with good defaults. Named after what the user wants to achieve, not the
|
|
5
5
|
// underlying tools.
|
|
6
6
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
7
|
-
exports.vaultSecretsOperator = exports.nginxIngressOperator = exports.cnpgOperator = exports.CertManager = exports.CertContext = exports.CertProvider = exports.EnvoyGateway = exports.Nginx = exports.EndpointContext = exports.EndpointProvider = exports.ExternalDns = exports.DnsContext = exports.DnsProvider = exports.ManualSecrets = exports.SealedSecrets = exports.Vault = exports.OpenBao = exports.SecretProvider = exports.Backup = exports.Monitoring = exports.Auth = exports.WebService = exports.Endpoint = exports.Database = exports.App = exports.R8sCluster = exports.Platform = void 0;
|
|
7
|
+
exports.secretsRequiredError = exports.maybeOperator = exports.useOperators = exports.StaticSecret = exports.vaultSecretsOperator = exports.nginxIngressOperator = exports.cnpgOperator = exports.CertManager = exports.CertContext = exports.CertProvider = exports.EnvoyGateway = exports.Nginx = exports.EndpointContext = exports.EndpointProvider = exports.ExternalDns = exports.DnsContext = exports.DnsProvider = exports.canProvisionSecrets = exports.provisionerForSecretProvider = exports.ManualSecrets = exports.SealedSecrets = exports.Vault = exports.OpenBao = exports.SecretProvider = exports.Backup = exports.Monitoring = exports.Auth = exports.WebService = exports.Endpoint = exports.Database = exports.App = exports.R8sCluster = exports.Platform = void 0;
|
|
8
8
|
var platform_1 = require("./platform");
|
|
9
9
|
Object.defineProperty(exports, "Platform", { enumerable: true, get: function () { return platform_1.Platform; } });
|
|
10
10
|
var r8s_cluster_1 = require("./r8s-cluster");
|
|
@@ -30,6 +30,8 @@ Object.defineProperty(exports, "OpenBao", { enumerable: true, get: function () {
|
|
|
30
30
|
Object.defineProperty(exports, "Vault", { enumerable: true, get: function () { return secret_provider_1.Vault; } });
|
|
31
31
|
Object.defineProperty(exports, "SealedSecrets", { enumerable: true, get: function () { return secret_provider_1.SealedSecrets; } });
|
|
32
32
|
Object.defineProperty(exports, "ManualSecrets", { enumerable: true, get: function () { return secret_provider_1.ManualSecrets; } });
|
|
33
|
+
Object.defineProperty(exports, "provisionerForSecretProvider", { enumerable: true, get: function () { return secret_provider_1.provisionerForSecretProvider; } });
|
|
34
|
+
Object.defineProperty(exports, "canProvisionSecrets", { enumerable: true, get: function () { return secret_provider_1.canProvisionSecrets; } });
|
|
33
35
|
var dns_provider_1 = require("./dns-provider");
|
|
34
36
|
Object.defineProperty(exports, "DnsProvider", { enumerable: true, get: function () { return dns_provider_1.DnsProvider; } });
|
|
35
37
|
Object.defineProperty(exports, "DnsContext", { enumerable: true, get: function () { return dns_provider_1.DnsContext; } });
|
|
@@ -48,4 +50,12 @@ var operators_1 = require("./operators");
|
|
|
48
50
|
Object.defineProperty(exports, "cnpgOperator", { enumerable: true, get: function () { return operators_1.cnpgOperator; } });
|
|
49
51
|
Object.defineProperty(exports, "nginxIngressOperator", { enumerable: true, get: function () { return operators_1.nginxIngressOperator; } });
|
|
50
52
|
Object.defineProperty(exports, "vaultSecretsOperator", { enumerable: true, get: function () { return operators_1.vaultSecretsOperator; } });
|
|
53
|
+
var static_secret_1 = require("./static-secret");
|
|
54
|
+
Object.defineProperty(exports, "StaticSecret", { enumerable: true, get: function () { return static_secret_1.StaticSecret; } });
|
|
55
|
+
// Composition helpers — loose building blocks for packages
|
|
56
|
+
var operators_2 = require("./operators");
|
|
57
|
+
Object.defineProperty(exports, "useOperators", { enumerable: true, get: function () { return operators_2.useOperators; } });
|
|
58
|
+
Object.defineProperty(exports, "maybeOperator", { enumerable: true, get: function () { return operators_2.maybeOperator; } });
|
|
59
|
+
var errors_1 = require("./errors");
|
|
60
|
+
Object.defineProperty(exports, "secretsRequiredError", { enumerable: true, get: function () { return errors_1.secretsRequiredError; } });
|
|
51
61
|
//# sourceMappingURL=index.js.map
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";AAAA,wDAAwD;AACxD,4EAA4E;AAC5E,0EAA0E;AAC1E,oBAAoB;;;AAEpB,uCAA2E;AAAlE,oGAAA,QAAQ,OAAA;AACjB,6CAAgE;AAAvD,yGAAA,UAAU,OAAA;AACnB,6BAA0C;AAAjC,0FAAA,GAAG,OAAA;AACZ,uCAAyD;AAAhD,oGAAA,QAAQ,OAAA;AACjB,uCAAyD;AAAhD,oGAAA,QAAQ,OAAA;AACjB,6CAKsB;AAJpB,yGAAA,UAAU,OAAA;AAKZ,+BAA6C;AAApC,4FAAA,IAAI,OAAA;AACb,2CAA+D;AAAtD,wGAAA,UAAU,OAAA;AACnB,mCAAmD;AAA1C,gGAAA,MAAM,OAAA;AAEf,wEAAwE;AACxE,
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";AAAA,wDAAwD;AACxD,4EAA4E;AAC5E,0EAA0E;AAC1E,oBAAoB;;;AAEpB,uCAA2E;AAAlE,oGAAA,QAAQ,OAAA;AACjB,6CAAgE;AAAvD,yGAAA,UAAU,OAAA;AACnB,6BAA0C;AAAjC,0FAAA,GAAG,OAAA;AACZ,uCAAyD;AAAhD,oGAAA,QAAQ,OAAA;AACjB,uCAAyD;AAAhD,oGAAA,QAAQ,OAAA;AACjB,6CAKsB;AAJpB,yGAAA,UAAU,OAAA;AAKZ,+BAA6C;AAApC,4FAAA,IAAI,OAAA;AACb,2CAA+D;AAAtD,wGAAA,UAAU,OAAA;AACnB,mCAAmD;AAA1C,gGAAA,MAAM,OAAA;AAEf,wEAAwE;AACxE,qDAc0B;AAbxB,iHAAA,cAAc,OAAA;AAGd,0GAAA,OAAO,OAAA;AAEP,wGAAA,KAAK,OAAA;AAEL,gHAAA,aAAa,OAAA;AAEb,gHAAA,aAAa,OAAA;AAEb,+HAAA,4BAA4B,OAAA;AAC5B,sHAAA,mBAAmB,OAAA;AAErB,+CAQuB;AAPrB,2GAAA,WAAW,OAAA;AAIX,0GAAA,UAAU,OAAA;AACV,2GAAA,WAAW,OAAA;AAGb,yDAU4B;AAT1B,qHAAA,gBAAgB,OAAA;AAIhB,oHAAA,eAAe,OAAA;AACf,0GAAA,KAAK,OAAA;AAEL,iHAAA,YAAY,OAAA;AAGd,iDAQwB;AAPtB,6GAAA,YAAY,OAAA;AAIZ,4GAAA,WAAW,OAAA;AACX,4GAAA,WAAW,OAAA;AAIb,uDAAuD;AACvD,yCAAsF;AAA7E,yGAAA,YAAY,OAAA;AAAE,iHAAA,oBAAoB,OAAA;AAAE,iHAAA,oBAAoB,OAAA;AAEjE,iDAAsE;AAA7D,6GAAA,YAAY,OAAA;AAErB,2DAA2D;AAC3D,yCAAyD;AAAhD,yGAAA,YAAY,OAAA;AAAE,0GAAA,aAAa,OAAA;AACpC,mCAA4E;AAAnE,8GAAA,oBAAoB,OAAA"}
|
package/dist/operators.d.ts
CHANGED
|
@@ -1,5 +1,19 @@
|
|
|
1
|
+
import { declareOperator } from '@r8s/core';
|
|
2
|
+
import type { Operator } from '@r8s/k8s-types';
|
|
3
|
+
/**
|
|
4
|
+
* Read the operators already declared by the Platform tree. Packages call
|
|
5
|
+
* this once (unconditionally) and pass the result to maybeOperator() —
|
|
6
|
+
* no sharedOperators.some(...) boilerplate in every package.
|
|
7
|
+
*/
|
|
8
|
+
export declare function useOperators(): Operator[];
|
|
9
|
+
/**
|
|
10
|
+
* Declare an operator unless the Platform already provides it. Returns
|
|
11
|
+
* [] (nothing to add) or a one-element array — spread into resources:
|
|
12
|
+
* `resources_.push(...maybeOperator('redis-operator', shared))`
|
|
13
|
+
*/
|
|
14
|
+
export declare function maybeOperator(name: string, shared: Operator[], version?: string): ReturnType<typeof declareOperator>[];
|
|
1
15
|
/** CloudNativePG operator declaration */
|
|
2
|
-
export declare const cnpgOperator: (version?: string) =>
|
|
16
|
+
export declare const cnpgOperator: (version?: string) => Operator;
|
|
3
17
|
/** NGINX Ingress Controller operator declaration (not in operators.yaml — nginx-specific) */
|
|
4
18
|
export declare const nginxIngressOperator: (version?: string) => {
|
|
5
19
|
name: string;
|
|
@@ -15,5 +29,5 @@ export declare const nginxIngressOperator: (version?: string) => {
|
|
|
15
29
|
installCommand: string;
|
|
16
30
|
};
|
|
17
31
|
/** Vault Secrets Operator declaration */
|
|
18
|
-
export declare const vaultSecretsOperator: (version?: string) =>
|
|
32
|
+
export declare const vaultSecretsOperator: (version?: string) => Operator;
|
|
19
33
|
//# sourceMappingURL=operators.d.ts.map
|
package/dist/operators.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"operators.d.ts","sourceRoot":"","sources":["../src/operators.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"operators.d.ts","sourceRoot":"","sources":["../src/operators.ts"],"names":[],"mappings":"AAOA,OAAO,EAAc,eAAe,EAAE,MAAM,WAAW,CAAA;AAEvD,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,gBAAgB,CAAA;AAE9C;;;;GAIG;AACH,wBAAgB,YAAY,IAAI,QAAQ,EAAE,CAEzC;AAED;;;;GAIG;AACH,wBAAgB,aAAa,CAC3B,IAAI,EAAE,MAAM,EACZ,MAAM,EAAE,QAAQ,EAAE,EAClB,OAAO,CAAC,EAAE,MAAM,GACf,UAAU,CAAC,OAAO,eAAe,CAAC,EAAE,CAMtC;AAED,yCAAyC;AACzC,eAAO,MAAM,YAAY,gCAAoB,CAAA;AAE7C,6FAA6F;AAC7F,eAAO,MAAM,oBAAoB,GAAI,gBAAkB;;;;;;;;;;;;CAYrD,CAAA;AAEF,yCAAyC;AACzC,eAAO,MAAM,oBAAoB,gCAAsC,CAAA"}
|
package/dist/operators.js
CHANGED
|
@@ -1,6 +1,8 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.vaultSecretsOperator = exports.nginxIngressOperator = exports.cnpgOperator = void 0;
|
|
4
|
+
exports.useOperators = useOperators;
|
|
5
|
+
exports.maybeOperator = maybeOperator;
|
|
4
6
|
/**
|
|
5
7
|
* Operator declarations re-exported from @r8s/crds.
|
|
6
8
|
*
|
|
@@ -8,6 +10,30 @@ exports.vaultSecretsOperator = exports.nginxIngressOperator = exports.cnpgOperat
|
|
|
8
10
|
* exist for backwards compatibility with recipes that import from here.
|
|
9
11
|
*/
|
|
10
12
|
const crds_1 = require("@r8s/crds");
|
|
13
|
+
const core_1 = require("@r8s/core");
|
|
14
|
+
const defaults_1 = require("@r8s/core/defaults");
|
|
15
|
+
/**
|
|
16
|
+
* Read the operators already declared by the Platform tree. Packages call
|
|
17
|
+
* this once (unconditionally) and pass the result to maybeOperator() —
|
|
18
|
+
* no sharedOperators.some(...) boilerplate in every package.
|
|
19
|
+
*/
|
|
20
|
+
function useOperators() {
|
|
21
|
+
return (0, core_1.useContext)(defaults_1.OperatorContext);
|
|
22
|
+
}
|
|
23
|
+
/**
|
|
24
|
+
* Declare an operator unless the Platform already provides it. Returns
|
|
25
|
+
* [] (nothing to add) or a one-element array — spread into resources:
|
|
26
|
+
* `resources_.push(...maybeOperator('redis-operator', shared))`
|
|
27
|
+
*/
|
|
28
|
+
function maybeOperator(name, shared, version) {
|
|
29
|
+
if (shared.some((op) => op.name === name))
|
|
30
|
+
return [];
|
|
31
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
32
|
+
const factory = crds_1.operators[name];
|
|
33
|
+
if (!factory)
|
|
34
|
+
throw new Error(`Unknown operator '${name}' — check packages/crds/operators.yaml`);
|
|
35
|
+
return [(0, core_1.declareOperator)(factory(version))];
|
|
36
|
+
}
|
|
11
37
|
/** CloudNativePG operator declaration */
|
|
12
38
|
exports.cnpgOperator = crds_1.operators['cnpg'];
|
|
13
39
|
/** NGINX Ingress Controller operator declaration (not in operators.yaml — nginx-specific) */
|
package/dist/operators.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"operators.js","sourceRoot":"","sources":["../src/operators.ts"],"names":[],"mappings":";;;
|
|
1
|
+
{"version":3,"file":"operators.js","sourceRoot":"","sources":["../src/operators.ts"],"names":[],"mappings":";;;AAgBA,oCAEC;AAOD,sCAUC;AAnCD;;;;;GAKG;AACH,oCAAqC;AACrC,oCAAuD;AACvD,iDAAoD;AAGpD;;;;GAIG;AACH,SAAgB,YAAY;IAC1B,OAAO,IAAA,iBAAU,EAAC,0BAAe,CAAC,CAAA;AACpC,CAAC;AAED;;;;GAIG;AACH,SAAgB,aAAa,CAC3B,IAAY,EACZ,MAAkB,EAClB,OAAgB;IAEhB,IAAI,MAAM,CAAC,IAAI,CAAC,CAAC,EAAE,EAAE,EAAE,CAAC,EAAE,CAAC,IAAI,KAAK,IAAI,CAAC;QAAE,OAAO,EAAE,CAAA;IACpD,8DAA8D;IAC9D,MAAM,OAAO,GAAI,gBAAmE,CAAC,IAAI,CAAC,CAAA;IAC1F,IAAI,CAAC,OAAO;QAAE,MAAM,IAAI,KAAK,CAAC,qBAAqB,IAAI,wCAAwC,CAAC,CAAA;IAChG,OAAO,CAAC,IAAA,sBAAe,EAAC,OAAO,CAAC,OAAO,CAAU,CAAC,CAAC,CAAA;AACrD,CAAC;AAED,yCAAyC;AAC5B,QAAA,YAAY,GAAG,gBAAS,CAAC,MAAM,CAAC,CAAA;AAE7C,6FAA6F;AACtF,MAAM,oBAAoB,GAAG,CAAC,OAAO,GAAG,QAAQ,EAAE,EAAE,CAAC,CAAC;IAC3D,IAAI,EAAE,eAAe;IACrB,WAAW,EAAE,0BAA0B;IACvC,MAAM,EAAE;QACN,IAAI,EAAE,UAAmB;QACzB,GAAG,EAAE,0EAA0E,OAAO,2CAA2C;QACjI,OAAO;QACP,SAAS,EAAE,eAAe;KAC3B;IACD,OAAO;IACP,SAAS,EAAE,eAAe;IAC1B,cAAc,EAAE,yGAAyG,OAAO,2CAA2C;CAC5K,CAAC,CAAA;AAZW,QAAA,oBAAoB,wBAY/B;AAEF,yCAAyC;AAC5B,QAAA,oBAAoB,GAAG,gBAAS,CAAC,wBAAwB,CAAC,CAAA"}
|
|
@@ -1,4 +1,13 @@
|
|
|
1
|
-
import { type SecretProvider as SecretProviderConfig } from '@r8s/core/defaults';
|
|
1
|
+
import { type SecretProvider as SecretProviderConfig, type SecretProvisioner } from '@r8s/core/defaults';
|
|
2
|
+
/**
|
|
3
|
+
* Provisioner resolution — THE single identity-aware point in the platform.
|
|
4
|
+
* Everything downstream codes against the `provision()` capability; new
|
|
5
|
+
* backends plug in by carrying their own provisioner on the context value
|
|
6
|
+
* (or by being registered here — the orchestration point).
|
|
7
|
+
*/
|
|
8
|
+
export declare function provisionerForSecretProvider(provider: SecretProviderConfig | null | undefined): SecretProvisioner | undefined;
|
|
9
|
+
/** Can this provider provision secrets? (capability check, not identity) */
|
|
10
|
+
export declare function canProvisionSecrets(provider: SecretProviderConfig | null | undefined): provider is SecretProviderConfig;
|
|
2
11
|
/**
|
|
3
12
|
* OpenBao configuration component.
|
|
4
13
|
*
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"secret-provider.d.ts","sourceRoot":"","sources":["../src/secret-provider.tsx"],"names":[],"mappings":"AACA,OAAO,
|
|
1
|
+
{"version":3,"file":"secret-provider.d.ts","sourceRoot":"","sources":["../src/secret-provider.tsx"],"names":[],"mappings":"AACA,OAAO,EAEL,KAAK,cAAc,IAAI,oBAAoB,EAC3C,KAAK,iBAAiB,EAEvB,MAAM,oBAAoB,CAAA;AAI3B;;;;;GAKG;AACH,wBAAgB,4BAA4B,CAC1C,QAAQ,EAAE,oBAAoB,GAAG,IAAI,GAAG,SAAS,GAChD,iBAAiB,GAAG,SAAS,CAO/B;AAED,4EAA4E;AAC5E,wBAAgB,mBAAmB,CACjC,QAAQ,EAAE,oBAAoB,GAAG,IAAI,GAAG,SAAS,GAChD,QAAQ,IAAI,oBAAoB,CAElC;AA2DD;;;;;;;GAOG;AACH,MAAM,WAAW,YAAY;IAC3B,6CAA6C;IAC7C,KAAK,CAAC,EAAE,MAAM,CAAA;IACd,iEAAiE;IACjE,IAAI,CAAC,EAAE,MAAM,CAAA;IACb,wCAAwC;IACxC,OAAO,CAAC,EAAE,MAAM,CAAA;IAChB,8EAA8E;IAC9E,YAAY,CAAC,EAAE,MAAM,CAAA;CACtB;AAED,wBAAgB,OAAO,CAAC,KAAK,EAAE,YAAY,GAAG,oBAAoB,CAQjE;AAED;;GAEG;AACH,MAAM,WAAW,UAAU;IACzB,2CAA2C;IAC3C,KAAK,CAAC,EAAE,MAAM,CAAA;IACd,gCAAgC;IAChC,IAAI,CAAC,EAAE,MAAM,CAAA;IACb,sCAAsC;IACtC,OAAO,CAAC,EAAE,MAAM,CAAA;IAChB,8EAA8E;IAC9E,YAAY,CAAC,EAAE,MAAM,CAAA;CACtB;AAED,wBAAgB,KAAK,CAAC,KAAK,EAAE,UAAU,GAAG,oBAAoB,CAQ7D;AAED;;GAEG;AACH,MAAM,WAAW,kBAAkB;IACjC,8EAA8E;IAC9E,SAAS,CAAC,EAAE,MAAM,CAAA;CACnB;AAED,wBAAgB,aAAa,CAAC,KAAK,EAAE,kBAAkB,GAAG,oBAAoB,CAI7E;AAED;;;;;GAKG;AACH,MAAM,WAAW,kBAAkB;CAAG;AAEtC,wBAAgB,aAAa,CAAC,KAAK,EAAE,kBAAkB,GAAG,oBAAoB,CAI7E;AAED,kDAAkD;AAClD,MAAM,MAAM,mBAAmB,GAC7B,SAAS,GAAG,OAAO,GAAG,gBAAgB,GAAG,gBAAgB,GAAG,oBAAoB,CAAA;AAElF,MAAM,WAAW,mBAAmB;IAClC;;;;;;;;;;;;;;;;;;;;OAoBG;IACH,QAAQ,EAAE,mBAAmB,CAAA;IAC7B,uBAAuB;IACvB,QAAQ,CAAC,EAAE,OAAO,CAAA;CACnB;AAED;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAyCG;AACH,wBAAgB,cAAc,CAAC,KAAK,EAAE,mBAAmB,kCA0CxD"}
|
package/dist/secret-provider.js
CHANGED
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.provisionerForSecretProvider = provisionerForSecretProvider;
|
|
4
|
+
exports.canProvisionSecrets = canProvisionSecrets;
|
|
3
5
|
exports.OpenBao = OpenBao;
|
|
4
6
|
exports.Vault = Vault;
|
|
5
7
|
exports.SealedSecrets = SealedSecrets;
|
|
@@ -9,6 +11,78 @@ const core_1 = require("@r8s/core");
|
|
|
9
11
|
const defaults_1 = require("@r8s/core/defaults");
|
|
10
12
|
const defaults_2 = require("@r8s/core/defaults");
|
|
11
13
|
const crds_1 = require("@r8s/crds");
|
|
14
|
+
/**
|
|
15
|
+
* Provisioner resolution — THE single identity-aware point in the platform.
|
|
16
|
+
* Everything downstream codes against the `provision()` capability; new
|
|
17
|
+
* backends plug in by carrying their own provisioner on the context value
|
|
18
|
+
* (or by being registered here — the orchestration point).
|
|
19
|
+
*/
|
|
20
|
+
function provisionerForSecretProvider(provider) {
|
|
21
|
+
if (!provider)
|
|
22
|
+
return undefined;
|
|
23
|
+
if (typeof provider.provision === 'function')
|
|
24
|
+
return provider.provision;
|
|
25
|
+
if (provider.backend === 'vault' || provider.backend === 'openbao') {
|
|
26
|
+
return (req) => builtinProvisionStaticSecret(provider, req);
|
|
27
|
+
}
|
|
28
|
+
return undefined;
|
|
29
|
+
}
|
|
30
|
+
/** Can this provider provision secrets? (capability check, not identity) */
|
|
31
|
+
function canProvisionSecrets(provider) {
|
|
32
|
+
return provisionerForSecretProvider(provider) !== undefined;
|
|
33
|
+
}
|
|
34
|
+
/** Built-in Vault/OpenBao emission (VaultStaticSecret / OpenBaoStaticSecret) */
|
|
35
|
+
function builtinProvisionStaticSecret(provider, req) {
|
|
36
|
+
// Two modes: an EXHAUSTIVE bundle (keys/templates given — destination
|
|
37
|
+
// carries exactly those keys, excludeRaw) or a RAW SYNC (empty keys and
|
|
38
|
+
// no templates — destination passes the whole store entry through,
|
|
39
|
+
// legacy Database/operator-contract shape).
|
|
40
|
+
const exhaustive = Object.keys(req.keys).length > 0 || req.templates !== undefined;
|
|
41
|
+
const spec = {
|
|
42
|
+
...(provider.backend === 'vault'
|
|
43
|
+
? { vaultAuthRef: req.authRef ?? provider.authRef }
|
|
44
|
+
: { openbaoAuthRef: req.authRef ?? provider.authRef }),
|
|
45
|
+
mount: req.mount ?? provider.mount,
|
|
46
|
+
type: 'kv-v2',
|
|
47
|
+
path: req.path,
|
|
48
|
+
refreshAfter: req.refreshAfter ?? provider.refreshAfter ?? (exhaustive ? '1h' : undefined),
|
|
49
|
+
...(req.restartTargets && req.restartTargets.length > 0
|
|
50
|
+
? { rolloutRestartTargets: req.restartTargets }
|
|
51
|
+
: {}),
|
|
52
|
+
destination: exhaustive
|
|
53
|
+
? {
|
|
54
|
+
create: true,
|
|
55
|
+
name: req.secretName ?? req.name,
|
|
56
|
+
overwrite: true,
|
|
57
|
+
transformation: {
|
|
58
|
+
excludeRaw: true,
|
|
59
|
+
templates: {
|
|
60
|
+
...Object.fromEntries(Object.entries(req.keys).map(([dest, src]) => [
|
|
61
|
+
dest,
|
|
62
|
+
{ text: `{{ .Secrets.${src} }}` },
|
|
63
|
+
])),
|
|
64
|
+
// Raw passthrough templates (literals, composed templates) win
|
|
65
|
+
// over key-mapped entries on collision
|
|
66
|
+
...Object.fromEntries(Object.entries(req.templates ?? {}).map(([dest, tpl]) => [dest, { text: tpl }])),
|
|
67
|
+
},
|
|
68
|
+
},
|
|
69
|
+
}
|
|
70
|
+
: { create: true, name: req.secretName ?? req.name },
|
|
71
|
+
};
|
|
72
|
+
return provider.backend === 'vault'
|
|
73
|
+
? (0, core_1.jsx)('VaultStaticSecret', {
|
|
74
|
+
apiVersion: 'secrets.hashicorp.com/v1beta1',
|
|
75
|
+
kind: 'VaultStaticSecret',
|
|
76
|
+
metadata: { name: req.name, namespace: req.namespace },
|
|
77
|
+
spec,
|
|
78
|
+
})
|
|
79
|
+
: (0, core_1.jsx)('OpenBaoStaticSecret', {
|
|
80
|
+
apiVersion: 'secrets.openbao.org/v1beta1',
|
|
81
|
+
kind: 'OpenBaoStaticSecret',
|
|
82
|
+
metadata: { name: req.name, namespace: req.namespace },
|
|
83
|
+
spec,
|
|
84
|
+
});
|
|
85
|
+
}
|
|
12
86
|
function OpenBao(props) {
|
|
13
87
|
return {
|
|
14
88
|
backend: 'openbao',
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"secret-provider.js","sourceRoot":"","sources":["../src/secret-provider.tsx"],"names":[],"mappings":";;
|
|
1
|
+
{"version":3,"file":"secret-provider.js","sourceRoot":"","sources":["../src/secret-provider.tsx"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,107 @@
|
|
|
1
|
+
export interface StaticSecretProps {
|
|
2
|
+
/**
|
|
3
|
+
* Resource name (also the default for the provisioned Kubernetes
|
|
4
|
+
* Secret's name — override with secretName).
|
|
5
|
+
*/
|
|
6
|
+
name: string;
|
|
7
|
+
/** Kubernetes namespace (inherited from Platform context when omitted) */
|
|
8
|
+
namespace?: string;
|
|
9
|
+
/**
|
|
10
|
+
* Vault/OpenBao KV v2 path holding the source keys, e.g. 'outline/app'.
|
|
11
|
+
* Build it from the provider's base path when composing:
|
|
12
|
+
* `${secretProvider.path}/myapp/credentials`.
|
|
13
|
+
*/
|
|
14
|
+
path: string;
|
|
15
|
+
/**
|
|
16
|
+
* Destination→source key mapping. The destination carries env-case
|
|
17
|
+
* names consumed by the app; the vault/store keys stay snake_case:
|
|
18
|
+
* keys={{ SECRET_KEY: 'secret_key', UTILS_SECRET: 'utils_secret' }}
|
|
19
|
+
* A string array is shorthand for identity mappings ({ KEY: 'KEY' }).
|
|
20
|
+
*
|
|
21
|
+
* Rendered as destination.transformation.templates + excludeRaw —
|
|
22
|
+
* the destination holds ONLY these keys.
|
|
23
|
+
*/
|
|
24
|
+
keys: Record<string, string> | string[];
|
|
25
|
+
/**
|
|
26
|
+
* Raw Go-template passthrough merged AFTER the keys mapping — for
|
|
27
|
+
* advanced bundles needing literals or composed templates
|
|
28
|
+
* (e.g. `AWS_ENDPOINTS: 'https://s3.berget.cloud'`). Passthrough wins
|
|
29
|
+
* over key-mapped entries on collision.
|
|
30
|
+
*/
|
|
31
|
+
templates?: Record<string, string>;
|
|
32
|
+
/** Provisioned Kubernetes Secret name (defaults to name) */
|
|
33
|
+
secretName?: string;
|
|
34
|
+
/**
|
|
35
|
+
* Re-sync interval rendered as refreshAfter. Defaults to the provider's
|
|
36
|
+
* refreshAfter, else '1h'.
|
|
37
|
+
*/
|
|
38
|
+
refreshAfter?: string;
|
|
39
|
+
/**
|
|
40
|
+
* Workloads restarted after rotation (rolloutRestartTargets). Pass the
|
|
41
|
+
* workloads consuming these values so a rotation actually takes effect —
|
|
42
|
+
* pod env vars do not update in place.
|
|
43
|
+
*
|
|
44
|
+
* Deliberately has no default: some consumers read the Secret at use
|
|
45
|
+
* time (e.g. CNPG barman backup credentials are read when a backup
|
|
46
|
+
* runs, and the Cluster CRD is not a supported restart target), so an
|
|
47
|
+
* automatic restart is wrong for them.
|
|
48
|
+
*/
|
|
49
|
+
restart?: {
|
|
50
|
+
kind?: string;
|
|
51
|
+
name: string;
|
|
52
|
+
apiVersion?: string;
|
|
53
|
+
}[];
|
|
54
|
+
/**
|
|
55
|
+
* Auth reference override (defaults to the provider's authRef).
|
|
56
|
+
* Rendered as vaultAuthRef / openbaoAuthRef per backend.
|
|
57
|
+
*/
|
|
58
|
+
authRef?: string;
|
|
59
|
+
}
|
|
60
|
+
/**
|
|
61
|
+
* StaticSecret — provision a Kubernetes Secret from Vault/OpenBao,
|
|
62
|
+
* with rotation semantics that actually reach the workloads.
|
|
63
|
+
*
|
|
64
|
+
* Wraps VaultStaticSecret / OpenBaoStaticSecret with the platform's
|
|
65
|
+
* conventions baked in:
|
|
66
|
+
* - snake_case source keys templated to env-case destination keys
|
|
67
|
+
* (excludeRaw: only the declared keys land in the Secret)
|
|
68
|
+
* - destination create + overwrite (idempotent sync)
|
|
69
|
+
* - hourly refresh by default, inheriting the provider's refreshAfter
|
|
70
|
+
* - explicit, per-bundle restart semantics (app creds restart pods;
|
|
71
|
+
* backup creds read at use time never restart)
|
|
72
|
+
*
|
|
73
|
+
* Requires an active secrets backend (openbao or vault) — passive
|
|
74
|
+
* backends (manual-secrets, sealed-secrets) cannot provision: reference
|
|
75
|
+
* a pre-created Secret instead.
|
|
76
|
+
*
|
|
77
|
+
* @example
|
|
78
|
+
* import { Platform, StaticSecret } from '@r8s/recipes'
|
|
79
|
+
*
|
|
80
|
+
* export default (
|
|
81
|
+
* <Platform secrets={{ backend: 'openbao', mount: 'kv', path: 'apps' }}>
|
|
82
|
+
* <StaticSecret
|
|
83
|
+
* name="myapp-secrets"
|
|
84
|
+
* path="myapp/app"
|
|
85
|
+
* keys={{
|
|
86
|
+
* SECRET_KEY: 'secret_key',
|
|
87
|
+
* OIDC_CLIENT_ID: 'oidc_client_id',
|
|
88
|
+
* OIDC_CLIENT_SECRET: 'oidc_client_secret',
|
|
89
|
+
* }}
|
|
90
|
+
* restart={[{ kind: 'Deployment', name: 'myapp' }]}
|
|
91
|
+
* />
|
|
92
|
+
* </Platform>
|
|
93
|
+
* )
|
|
94
|
+
*
|
|
95
|
+
* @example
|
|
96
|
+
* import { Platform, StaticSecret } from '@r8s/recipes'
|
|
97
|
+
*
|
|
98
|
+
* // backup creds: read at use time — never restart workloads
|
|
99
|
+
* export default (
|
|
100
|
+
* <Platform secrets={{ backend: 'openbao', mount: 'kv', path: 'apps' }}>
|
|
101
|
+
* <StaticSecret name="myapp-backup-creds" path="rustfs/myapp"
|
|
102
|
+
* keys={['accesskey', 'secretkey']} />
|
|
103
|
+
* </Platform>
|
|
104
|
+
* )
|
|
105
|
+
*/
|
|
106
|
+
export declare function StaticSecret(props: StaticSecretProps): import("@r8s/core").r8sElement;
|
|
107
|
+
//# sourceMappingURL=static-secret.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"static-secret.d.ts","sourceRoot":"","sources":["../src/static-secret.tsx"],"names":[],"mappings":"AAIA,MAAM,WAAW,iBAAiB;IAChC;;;OAGG;IACH,IAAI,EAAE,MAAM,CAAA;IACZ,0EAA0E;IAC1E,SAAS,CAAC,EAAE,MAAM,CAAA;IAClB;;;;OAIG;IACH,IAAI,EAAE,MAAM,CAAA;IACZ;;;;;;;;OAQG;IACH,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,GAAG,MAAM,EAAE,CAAA;IACvC;;;;;OAKG;IACH,SAAS,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAA;IAClC,4DAA4D;IAC5D,UAAU,CAAC,EAAE,MAAM,CAAA;IACnB;;;OAGG;IACH,YAAY,CAAC,EAAE,MAAM,CAAA;IACrB;;;;;;;;;OASG;IACH,OAAO,CAAC,EAAE;QAAE,IAAI,CAAC,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,MAAM,CAAC;QAAC,UAAU,CAAC,EAAE,MAAM,CAAA;KAAE,EAAE,CAAA;IAChE;;;OAGG;IACH,OAAO,CAAC,EAAE,MAAM,CAAA;CACjB;AAED;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA6CG;AACH,wBAAgB,YAAY,CAAC,KAAK,EAAE,iBAAiB,kCAoDpD"}
|
|
@@ -0,0 +1,87 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.StaticSecret = StaticSecret;
|
|
4
|
+
const core_1 = require("@r8s/core");
|
|
5
|
+
const defaults_1 = require("@r8s/core/defaults");
|
|
6
|
+
const secret_provider_1 = require("./secret-provider");
|
|
7
|
+
/**
|
|
8
|
+
* StaticSecret — provision a Kubernetes Secret from Vault/OpenBao,
|
|
9
|
+
* with rotation semantics that actually reach the workloads.
|
|
10
|
+
*
|
|
11
|
+
* Wraps VaultStaticSecret / OpenBaoStaticSecret with the platform's
|
|
12
|
+
* conventions baked in:
|
|
13
|
+
* - snake_case source keys templated to env-case destination keys
|
|
14
|
+
* (excludeRaw: only the declared keys land in the Secret)
|
|
15
|
+
* - destination create + overwrite (idempotent sync)
|
|
16
|
+
* - hourly refresh by default, inheriting the provider's refreshAfter
|
|
17
|
+
* - explicit, per-bundle restart semantics (app creds restart pods;
|
|
18
|
+
* backup creds read at use time never restart)
|
|
19
|
+
*
|
|
20
|
+
* Requires an active secrets backend (openbao or vault) — passive
|
|
21
|
+
* backends (manual-secrets, sealed-secrets) cannot provision: reference
|
|
22
|
+
* a pre-created Secret instead.
|
|
23
|
+
*
|
|
24
|
+
* @example
|
|
25
|
+
* import { Platform, StaticSecret } from '@r8s/recipes'
|
|
26
|
+
*
|
|
27
|
+
* export default (
|
|
28
|
+
* <Platform secrets={{ backend: 'openbao', mount: 'kv', path: 'apps' }}>
|
|
29
|
+
* <StaticSecret
|
|
30
|
+
* name="myapp-secrets"
|
|
31
|
+
* path="myapp/app"
|
|
32
|
+
* keys={{
|
|
33
|
+
* SECRET_KEY: 'secret_key',
|
|
34
|
+
* OIDC_CLIENT_ID: 'oidc_client_id',
|
|
35
|
+
* OIDC_CLIENT_SECRET: 'oidc_client_secret',
|
|
36
|
+
* }}
|
|
37
|
+
* restart={[{ kind: 'Deployment', name: 'myapp' }]}
|
|
38
|
+
* />
|
|
39
|
+
* </Platform>
|
|
40
|
+
* )
|
|
41
|
+
*
|
|
42
|
+
* @example
|
|
43
|
+
* import { Platform, StaticSecret } from '@r8s/recipes'
|
|
44
|
+
*
|
|
45
|
+
* // backup creds: read at use time — never restart workloads
|
|
46
|
+
* export default (
|
|
47
|
+
* <Platform secrets={{ backend: 'openbao', mount: 'kv', path: 'apps' }}>
|
|
48
|
+
* <StaticSecret name="myapp-backup-creds" path="rustfs/myapp"
|
|
49
|
+
* keys={['accesskey', 'secretkey']} />
|
|
50
|
+
* </Platform>
|
|
51
|
+
* )
|
|
52
|
+
*/
|
|
53
|
+
function StaticSecret(props) {
|
|
54
|
+
const { name, namespace: namespaceProp, path, keys, templates, secretName, refreshAfter, restart, authRef, } = props;
|
|
55
|
+
const secretProvider = (0, core_1.useContext)(defaults_1.SecretContext);
|
|
56
|
+
const namespace = (0, defaults_1.useNamespace)(namespaceProp);
|
|
57
|
+
const provisioner = (0, secret_provider_1.provisionerForSecretProvider)(secretProvider);
|
|
58
|
+
if (!provisioner) {
|
|
59
|
+
throw new Error(`StaticSecret "${name}" requires a provisioning secrets backend (openbao, vault,\n` +
|
|
60
|
+
`or any provider carrying a provision() hook).\n` +
|
|
61
|
+
`\n` +
|
|
62
|
+
`Fix: configure a backend on the Platform:\n` +
|
|
63
|
+
` <Platform secrets={{ backend: 'openbao', mount: 'kv', path: 'apps' }}>\n` +
|
|
64
|
+
` <StaticSecret name="${name}" path="${path}" keys={...} />\n` +
|
|
65
|
+
` </Platform>\n` +
|
|
66
|
+
`\n` +
|
|
67
|
+
`On passive backends (manual-secrets, sealed-secrets, kubernetes), create the Secret\n` +
|
|
68
|
+
`out of band and reference it directly instead of rendering this component.`);
|
|
69
|
+
}
|
|
70
|
+
const mapping = Object.fromEntries((Array.isArray(keys) ? keys.map((k) => [k, k]) : Object.entries(keys)));
|
|
71
|
+
// Default missing fields (consistent with Database/WebService restart
|
|
72
|
+
// target conventions)
|
|
73
|
+
const restartTargets = restart?.map((t) => ({ kind: 'Deployment', ...t }));
|
|
74
|
+
const el = provisioner({
|
|
75
|
+
name,
|
|
76
|
+
namespace,
|
|
77
|
+
path,
|
|
78
|
+
keys: mapping,
|
|
79
|
+
templates,
|
|
80
|
+
secretName,
|
|
81
|
+
authRef,
|
|
82
|
+
refreshAfter,
|
|
83
|
+
restartTargets,
|
|
84
|
+
});
|
|
85
|
+
return Array.isArray(el) ? (0, core_1.jsx)(core_1.Fragment, { children: el }) : el;
|
|
86
|
+
}
|
|
87
|
+
//# sourceMappingURL=static-secret.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"static-secret.js","sourceRoot":"","sources":["../src/static-secret.tsx"],"names":[],"mappings":";;AA0GA,oCAoDC;AA9JD,oCAAqD;AACrD,iDAAgE;AAChE,uDAAgE;AA0DhE;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA6CG;AACH,SAAgB,YAAY,CAAC,KAAwB;IACnD,MAAM,EACJ,IAAI,EACJ,SAAS,EAAE,aAAa,EACxB,IAAI,EACJ,IAAI,EACJ,SAAS,EACT,UAAU,EACV,YAAY,EACZ,OAAO,EACP,OAAO,GACR,GAAG,KAAK,CAAA;IAET,MAAM,cAAc,GAAG,IAAA,iBAAU,EAAC,wBAAa,CAAC,CAAA;IAChD,MAAM,SAAS,GAAG,IAAA,uBAAY,EAAC,aAAa,CAAC,CAAA;IAC7C,MAAM,WAAW,GAAG,IAAA,8CAA4B,EAAC,cAAc,CAAC,CAAA;IAEhE,IAAI,CAAC,WAAW,EAAE,CAAC;QACjB,MAAM,IAAI,KAAK,CACb,iBAAiB,IAAI,8DAA8D;YACjF,iDAAiD;YACjD,IAAI;YACJ,6CAA6C;YAC7C,4EAA4E;YAC5E,2BAA2B,IAAI,WAAW,IAAI,mBAAmB;YACjE,iBAAiB;YACjB,IAAI;YACJ,uFAAuF;YACvF,4EAA4E,CAC/E,CAAA;IACH,CAAC;IAED,MAAM,OAAO,GAA2B,MAAM,CAAC,WAAW,CACxD,CAAC,KAAK,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,OAAO,CAAC,IAAI,CAAC,CAAuB,CAC7F,CAAA;IAED,sEAAsE;IACtE,sBAAsB;IACtB,MAAM,cAAc,GAAG,OAAO,EAAE,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,EAAE,IAAI,EAAE,YAAY,EAAE,GAAG,CAAC,EAAE,CAAC,CAAC,CAAA;IAE1E,MAAM,EAAE,GAAG,WAAW,CAAC;QACrB,IAAI;QACJ,SAAS;QACT,IAAI;QACJ,IAAI,EAAE,OAAO;QACb,SAAS;QACT,UAAU;QACV,OAAO;QACP,YAAY;QACZ,cAAc;KACf,CAAC,CAAA;IACF,OAAO,KAAK,CAAC,OAAO,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,IAAA,UAAG,EAAC,eAAQ,EAAE,EAAE,QAAQ,EAAE,EAAE,EAAE,CAAC,CAAC,CAAC,CAAE,EAA6B,CAAA;AAC7F,CAAC"}
|
package/dist/web-service.d.ts
CHANGED
|
@@ -100,7 +100,11 @@ export interface WebServiceProps {
|
|
|
100
100
|
tolerations?: Record<string, unknown>[];
|
|
101
101
|
/** Pod topologySpreadConstraints (spread replicas across nodes) */
|
|
102
102
|
topologySpreadConstraints?: Record<string, unknown>[];
|
|
103
|
-
/**
|
|
103
|
+
/**
|
|
104
|
+
* Deployment update strategy ('Recreate' for RWO-volume/migration apps).
|
|
105
|
+
* Default: 'Recreate' when the pod mounts a PVC volume and replicas=1
|
|
106
|
+
* (RollingUpdate would deadlock on the single-attach volume).
|
|
107
|
+
*/
|
|
104
108
|
strategy?: 'Recreate' | 'RollingUpdate' | {
|
|
105
109
|
type: string;
|
|
106
110
|
rollingUpdate?: {
|
|
@@ -130,7 +134,11 @@ export interface WebServiceProps {
|
|
|
130
134
|
} & Record<string, unknown>)[];
|
|
131
135
|
/** Container lifecycle hooks (e.g. { preStop: { exec: { command: [...] } } }) */
|
|
132
136
|
lifecycle?: Record<string, unknown>;
|
|
133
|
-
/**
|
|
137
|
+
/**
|
|
138
|
+
* Image pull policy. Default depends on the tag: floating tags
|
|
139
|
+
* (latest/main/master/dev/edge/head/nightly/canary) get 'Always', pinned
|
|
140
|
+
* tags and digests get 'IfNotPresent' (immutable — pointless to re-pull).
|
|
141
|
+
*/
|
|
134
142
|
imagePullPolicy?: 'Always' | 'IfNotPresent' | 'Never';
|
|
135
143
|
/** Names of Secrets used to pull private registry images */
|
|
136
144
|
imagePullSecrets?: string[];
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"web-service.d.ts","sourceRoot":"","sources":["../src/web-service.tsx"],"names":[],"mappings":"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
|
|
1
|
+
{"version":3,"file":"web-service.d.ts","sourceRoot":"","sources":["../src/web-service.tsx"],"names":[],"mappings":"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"}
|
package/dist/web-service.js
CHANGED
|
@@ -42,7 +42,7 @@ const operators_1 = require("./operators");
|
|
|
42
42
|
* )
|
|
43
43
|
*/
|
|
44
44
|
function WebService(props) {
|
|
45
|
-
const { name, namespace
|
|
45
|
+
const { name, namespace: namespaceProp, image, port = 3000, replicas = 2, probes, env = {}, secrets = {}, vault = {}, command, args, rawEnv = [], resources, securityContext, podSecurityContext, tolerations, topologySpreadConstraints, strategy, volumes, volumeMounts, initContainers, lifecycle, imagePullPolicy, imagePullSecrets, } = props;
|
|
46
46
|
const buildProbe = (spec, fallbackPath) => {
|
|
47
47
|
if (spec === null)
|
|
48
48
|
return undefined;
|
|
@@ -51,18 +51,57 @@ function WebService(props) {
|
|
|
51
51
|
const initialDelaySeconds = spec.initialDelaySeconds ?? 10;
|
|
52
52
|
const periodSeconds = spec.periodSeconds ?? 10;
|
|
53
53
|
if (spec.tcp) {
|
|
54
|
-
return {
|
|
54
|
+
return {
|
|
55
|
+
tcpSocket: { port: spec.port ?? port },
|
|
56
|
+
initialDelaySeconds,
|
|
57
|
+
periodSeconds,
|
|
58
|
+
// !== undefined (not truthy): an explicit 0 must surface as-is so
|
|
59
|
+
// Kubernetes validation fails loudly instead of silently reverting
|
|
60
|
+
// to the default
|
|
61
|
+
...(spec.failureThreshold !== undefined && { failureThreshold: spec.failureThreshold }),
|
|
62
|
+
};
|
|
55
63
|
}
|
|
56
64
|
return {
|
|
57
65
|
httpGet: { path: spec.path ?? fallbackPath, port: spec.port ?? port },
|
|
58
66
|
initialDelaySeconds,
|
|
59
67
|
periodSeconds,
|
|
60
|
-
...(spec.failureThreshold && { failureThreshold: spec.failureThreshold }),
|
|
68
|
+
...(spec.failureThreshold !== undefined && { failureThreshold: spec.failureThreshold }),
|
|
61
69
|
};
|
|
62
70
|
};
|
|
63
71
|
const livenessProbe = buildProbe(probes?.liveness, '/health');
|
|
64
72
|
const readinessProbe = buildProbe(probes?.readiness, '/ready');
|
|
65
73
|
const startupProbe = buildProbe(probes?.startup ?? null, '/health');
|
|
74
|
+
// --- Safe defaults derived from the image and storage shape -------------
|
|
75
|
+
// imagePullPolicy: a floating tag must be re-pulled (Always); a pinned tag
|
|
76
|
+
// (or digest) is immutable, so IfNotPresent avoids pointless pulls and
|
|
77
|
+
// makes deploys robust when a registry is slow/unreachable. Explicit prop
|
|
78
|
+
// always wins. Floating set covers the conventional mutables.
|
|
79
|
+
const imageLeaf = image.slice(image.lastIndexOf('/') + 1);
|
|
80
|
+
const imageTag = imageLeaf.includes('@')
|
|
81
|
+
? imageLeaf.slice(imageLeaf.indexOf('@') + 1)
|
|
82
|
+
: imageLeaf.includes(':')
|
|
83
|
+
? imageLeaf.slice(imageLeaf.indexOf(':') + 1)
|
|
84
|
+
: 'latest';
|
|
85
|
+
const FLOATING_TAGS = new Set([
|
|
86
|
+
'latest',
|
|
87
|
+
'main',
|
|
88
|
+
'master',
|
|
89
|
+
'dev',
|
|
90
|
+
'edge',
|
|
91
|
+
'head',
|
|
92
|
+
'nightly',
|
|
93
|
+
'canary',
|
|
94
|
+
]);
|
|
95
|
+
const pullPolicy = imagePullPolicy ??
|
|
96
|
+
(!imageLeaf.includes('@') && FLOATING_TAGS.has(imageTag.toLowerCase())
|
|
97
|
+
? 'Always'
|
|
98
|
+
: 'IfNotPresent');
|
|
99
|
+
// strategy: RollingUpdate + a ReadWriteOnce PVC + replicas=1 deadlocks
|
|
100
|
+
// (the new pod cannot attach the volume until the old releases it), and
|
|
101
|
+
// in-place DB-migration apps (n8n, outline) must not run two versions at
|
|
102
|
+
// once. Recreate is always safe at replicas=1 — there is already no HA.
|
|
103
|
+
const hasPvcVolume = (volumes ?? []).some((v) => 'persistentVolumeClaim' in v);
|
|
104
|
+
const derivedStrategy = strategy ?? (hasPvcVolume && replicas === 1 ? 'Recreate' : undefined);
|
|
66
105
|
const envVars = [];
|
|
67
106
|
const vaultResources = [];
|
|
68
107
|
// Secrets from Kubernetes Secrets — pushed before plain env vars so
|
|
@@ -89,6 +128,7 @@ function WebService(props) {
|
|
|
89
128
|
envVars.push({ name: key, value });
|
|
90
129
|
}
|
|
91
130
|
// Vault secrets — create VaultStaticSecret objects
|
|
131
|
+
const namespace = (0, defaults_1.useNamespace)(namespaceProp);
|
|
92
132
|
const platformSecrets = (0, core_1.useContext)(defaults_1.SecretContext);
|
|
93
133
|
for (const [envName, ref] of Object.entries(vault)) {
|
|
94
134
|
const secretName = `${name}-${envName.toLowerCase().replace(/_/g, '-')}-vault`;
|
|
@@ -166,8 +206,8 @@ function WebService(props) {
|
|
|
166
206
|
metadata: { name, namespace, labels: { app: name } },
|
|
167
207
|
spec: {
|
|
168
208
|
replicas,
|
|
169
|
-
...(
|
|
170
|
-
strategy: typeof
|
|
209
|
+
...(derivedStrategy && {
|
|
210
|
+
strategy: typeof derivedStrategy === 'string' ? { type: derivedStrategy } : derivedStrategy,
|
|
171
211
|
}),
|
|
172
212
|
selector: { matchLabels: { app: name } },
|
|
173
213
|
template: {
|
|
@@ -187,7 +227,7 @@ function WebService(props) {
|
|
|
187
227
|
{
|
|
188
228
|
name: 'app',
|
|
189
229
|
image,
|
|
190
|
-
imagePullPolicy,
|
|
230
|
+
imagePullPolicy: pullPolicy,
|
|
191
231
|
...(command && { command }),
|
|
192
232
|
...(args && { args }),
|
|
193
233
|
ports: [{ containerPort: port }],
|
|
@@ -215,11 +255,14 @@ function WebService(props) {
|
|
|
215
255
|
// Expose the app port directly (so consumers can reference it) while
|
|
216
256
|
// keeping 80 as a stable backward-compatible alias: existing
|
|
217
257
|
// Endpoints/default servicePort=80 users keep routing during
|
|
218
|
-
// migration to explicit servicePort
|
|
258
|
+
// migration to explicit servicePort.
|
|
259
|
+
// Port names are REQUIRED whenever a Service has more than one port —
|
|
260
|
+
// without them the API server rejects the resource (caught by Flux
|
|
261
|
+
// dry-run as "spec.ports[i].name: Required value").
|
|
219
262
|
ports: [
|
|
220
|
-
{ port, targetPort: port },
|
|
263
|
+
{ name: 'http', port, targetPort: port },
|
|
221
264
|
// eslint-disable-next-line -- 80 alias for legacy servicePort=80 consumers
|
|
222
|
-
...(port !== 80 ? [{ port: 80, targetPort: port }] : []),
|
|
265
|
+
...(port !== 80 ? [{ name: 'http-80', port: 80, targetPort: port }] : []),
|
|
223
266
|
],
|
|
224
267
|
},
|
|
225
268
|
};
|