@r8s/recipes 0.1.0
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 +94 -0
- package/dist/app.d.ts.map +1 -0
- package/dist/app.js +120 -0
- package/dist/app.js.map +1 -0
- package/dist/auth/components.d.ts +163 -0
- package/dist/auth/components.d.ts.map +1 -0
- package/dist/auth/components.js +134 -0
- package/dist/auth/components.js.map +1 -0
- package/dist/auth/index.d.ts +2 -0
- package/dist/auth/index.d.ts.map +1 -0
- package/dist/auth/index.js +14 -0
- package/dist/auth/index.js.map +1 -0
- package/dist/auth.d.ts +92 -0
- package/dist/auth.d.ts.map +1 -0
- package/dist/auth.js +302 -0
- package/dist/auth.js.map +1 -0
- package/dist/backup.d.ts +45 -0
- package/dist/backup.d.ts.map +1 -0
- package/dist/backup.js +59 -0
- package/dist/backup.js.map +1 -0
- package/dist/cert-provider.d.ts +78 -0
- package/dist/cert-provider.d.ts.map +1 -0
- package/dist/cert-provider.js +71 -0
- package/dist/cert-provider.js.map +1 -0
- package/dist/database.d.ts +49 -0
- package/dist/database.d.ts.map +1 -0
- package/dist/database.js +212 -0
- package/dist/database.js.map +1 -0
- package/dist/dns-provider.d.ts +110 -0
- package/dist/dns-provider.d.ts.map +1 -0
- package/dist/dns-provider.js +121 -0
- package/dist/dns-provider.js.map +1 -0
- package/dist/endpoint-provider.d.ts +121 -0
- package/dist/endpoint-provider.d.ts.map +1 -0
- package/dist/endpoint-provider.js +79 -0
- package/dist/endpoint-provider.js.map +1 -0
- package/dist/endpoint.d.ts +43 -0
- package/dist/endpoint.d.ts.map +1 -0
- package/dist/endpoint.js +221 -0
- package/dist/endpoint.js.map +1 -0
- package/dist/index.d.ts +14 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +49 -0
- package/dist/index.js.map +1 -0
- package/dist/monitoring.d.ts +49 -0
- package/dist/monitoring.d.ts.map +1 -0
- package/dist/monitoring.js +128 -0
- package/dist/monitoring.js.map +1 -0
- package/dist/operators.d.ts +19 -0
- package/dist/operators.d.ts.map +1 -0
- package/dist/operators.js +30 -0
- package/dist/operators.js.map +1 -0
- package/dist/platform.d.ts +116 -0
- package/dist/platform.d.ts.map +1 -0
- package/dist/platform.js +121 -0
- package/dist/platform.js.map +1 -0
- package/dist/secret-provider.d.ts +119 -0
- package/dist/secret-provider.d.ts.map +1 -0
- package/dist/secret-provider.js +125 -0
- package/dist/secret-provider.js.map +1 -0
- package/dist/web-service.d.ts +87 -0
- package/dist/web-service.d.ts.map +1 -0
- package/dist/web-service.js +171 -0
- package/dist/web-service.js.map +1 -0
- package/package.json +48 -0
package/dist/database.js
ADDED
|
@@ -0,0 +1,212 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.Database = Database;
|
|
4
|
+
const core_1 = require("@r8s/core");
|
|
5
|
+
const defaults_1 = require("@r8s/core/defaults");
|
|
6
|
+
const operators_1 = require("./operators");
|
|
7
|
+
/**
|
|
8
|
+
* CloudNativePG PostgreSQL database.
|
|
9
|
+
*
|
|
10
|
+
* @title Database
|
|
11
|
+
* @category Data & Analytics
|
|
12
|
+
*
|
|
13
|
+
* Creates a dedicated 3-instance HA CloudNativePG cluster for this database.
|
|
14
|
+
* When wrapped in a `<Database>` component, child components receive the
|
|
15
|
+
* connection info via DatabaseContext automatically.
|
|
16
|
+
*
|
|
17
|
+
* Credentials are managed by the secrets backend configured on the Platform.
|
|
18
|
+
* Without a secrets backend, CNPG manages the bootstrap secret automatically.
|
|
19
|
+
*
|
|
20
|
+
* @example
|
|
21
|
+
* import { Database } from '@r8s/recipes'
|
|
22
|
+
*
|
|
23
|
+
* export default <Database name="app-db" storage="10Gi" />
|
|
24
|
+
*
|
|
25
|
+
* @example
|
|
26
|
+
* import { Platform, Database, WebService } from '@r8s/recipes'
|
|
27
|
+
*
|
|
28
|
+
* export default (
|
|
29
|
+
* <Platform secrets={{ backend: 'openbao' }}>
|
|
30
|
+
* <Database name="app-db" storage="10Gi">
|
|
31
|
+
* <WebService name="api" image="myapp/api:v1" />
|
|
32
|
+
* </Database>
|
|
33
|
+
* </Platform>
|
|
34
|
+
* )
|
|
35
|
+
*/
|
|
36
|
+
function Database(props) {
|
|
37
|
+
const { name, namespace: namespaceProp, storage = '10Gi', operatorVersion, password, children, } = props;
|
|
38
|
+
// Inherit namespace from <Platform> context if not explicitly set
|
|
39
|
+
const contextNamespace = (0, core_1.useContext)(defaults_1.Namespace);
|
|
40
|
+
const namespace = namespaceProp ?? (contextNamespace !== 'default' ? contextNamespace : undefined) ?? 'default';
|
|
41
|
+
const clusterConfig = (0, core_1.useContext)(defaults_1.ClusterContext);
|
|
42
|
+
const secretProvider = (0, core_1.useContext)(defaults_1.SecretContext);
|
|
43
|
+
const sharedOperators = (0, core_1.useContext)(defaults_1.OperatorContext);
|
|
44
|
+
const secretName = `${name}-db-credentials`;
|
|
45
|
+
const resources = [];
|
|
46
|
+
if (clusterConfig) {
|
|
47
|
+
// Shared cluster — reuse connection info from the surrounding Cluster
|
|
48
|
+
const connection = {
|
|
49
|
+
host: clusterConfig.host,
|
|
50
|
+
port: 5432,
|
|
51
|
+
database: name,
|
|
52
|
+
username: name,
|
|
53
|
+
passwordSecret: { name: secretName, key: 'password' },
|
|
54
|
+
passwordKey: 'password',
|
|
55
|
+
vendor: 'postgres',
|
|
56
|
+
};
|
|
57
|
+
resources.push(...createSecretResources(name, namespace, secretName, secretProvider, password, clusterConfig.host));
|
|
58
|
+
if (children) {
|
|
59
|
+
resources.push((0, core_1.jsx)(defaults_1.DatabaseContext.Provider, { value: connection, children }));
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
else {
|
|
63
|
+
// Dedicated cluster — create full CNPG cluster
|
|
64
|
+
const hasCNPG = sharedOperators.some((op) => op.name === 'cnpg');
|
|
65
|
+
const cluster = {
|
|
66
|
+
apiVersion: 'postgresql.cnpg.io/v1',
|
|
67
|
+
kind: 'Cluster',
|
|
68
|
+
metadata: { name, namespace },
|
|
69
|
+
spec: {
|
|
70
|
+
instances: 3,
|
|
71
|
+
storage: { size: storage },
|
|
72
|
+
bootstrap: {
|
|
73
|
+
initdb: {
|
|
74
|
+
database: name,
|
|
75
|
+
owner: name,
|
|
76
|
+
secret: { name: secretName },
|
|
77
|
+
},
|
|
78
|
+
},
|
|
79
|
+
monitoring: { enablePodMonitor: true },
|
|
80
|
+
},
|
|
81
|
+
};
|
|
82
|
+
const connection = {
|
|
83
|
+
host: `${name}-rw`,
|
|
84
|
+
port: 5432,
|
|
85
|
+
database: name,
|
|
86
|
+
username: name,
|
|
87
|
+
passwordSecret: { name: secretName, key: 'password' },
|
|
88
|
+
passwordKey: 'password',
|
|
89
|
+
vendor: 'postgres',
|
|
90
|
+
};
|
|
91
|
+
if (!hasCNPG) {
|
|
92
|
+
resources.push((0, core_1.declareOperator)((0, operators_1.cnpgOperator)(operatorVersion)));
|
|
93
|
+
}
|
|
94
|
+
resources.push((0, core_1.jsx)('Cluster', cluster));
|
|
95
|
+
// For dedicated clusters with a secrets backend, the backend manages
|
|
96
|
+
// credentials. For kubernetes backend, CNPG manages the bootstrap secret
|
|
97
|
+
// automatically — but we still validate that a password was provided
|
|
98
|
+
// when kubernetes backend is explicitly chosen.
|
|
99
|
+
if (secretProvider) {
|
|
100
|
+
resources.push(...createSecretResources(name, namespace, secretName, secretProvider, password, `${name}-rw`));
|
|
101
|
+
}
|
|
102
|
+
if (children) {
|
|
103
|
+
resources.push((0, core_1.jsx)(defaults_1.DatabaseContext.Provider, { value: connection, children }));
|
|
104
|
+
}
|
|
105
|
+
}
|
|
106
|
+
return resources;
|
|
107
|
+
}
|
|
108
|
+
/**
|
|
109
|
+
* Create the secret resources for a database based on the active secrets
|
|
110
|
+
* backend. Throws a descriptive error when a password is needed but not
|
|
111
|
+
* provided, or when the backend is not configured.
|
|
112
|
+
*/
|
|
113
|
+
function createSecretResources(name, namespace, secretName, secretProvider, password, host) {
|
|
114
|
+
const resources = [];
|
|
115
|
+
if (!secretProvider) {
|
|
116
|
+
if (!password) {
|
|
117
|
+
throw new Error(`Database "${name}" has no secrets backend configured and no password provided.\n` +
|
|
118
|
+
`\n` +
|
|
119
|
+
`Fix: either set a secrets backend on the Platform:\n` +
|
|
120
|
+
` <Platform secrets={{ backend: 'openbao' }}>\n` +
|
|
121
|
+
` <Database name="${name}" />\n` +
|
|
122
|
+
` </Platform>\n` +
|
|
123
|
+
`\n` +
|
|
124
|
+
`Or provide a password directly (not recommended for production):\n` +
|
|
125
|
+
` <Database name="${name}" password="..." />`);
|
|
126
|
+
}
|
|
127
|
+
resources.push((0, core_1.jsx)('Secret', {
|
|
128
|
+
apiVersion: 'v1',
|
|
129
|
+
kind: 'Secret',
|
|
130
|
+
metadata: { name: secretName, namespace },
|
|
131
|
+
stringData: {
|
|
132
|
+
password,
|
|
133
|
+
username: name,
|
|
134
|
+
uri: `postgresql://${name}:${password}@${host}:5432/${name}`,
|
|
135
|
+
},
|
|
136
|
+
}));
|
|
137
|
+
return resources;
|
|
138
|
+
}
|
|
139
|
+
switch (secretProvider.backend) {
|
|
140
|
+
case 'vault':
|
|
141
|
+
resources.push((0, core_1.jsx)('VaultStaticSecret', {
|
|
142
|
+
apiVersion: 'secrets.hashicorp.com/v1beta1',
|
|
143
|
+
kind: 'VaultStaticSecret',
|
|
144
|
+
metadata: { name: `${name}-db-secret`, namespace },
|
|
145
|
+
spec: {
|
|
146
|
+
vaultAuthRef: secretProvider.authRef,
|
|
147
|
+
mount: secretProvider.mount,
|
|
148
|
+
type: 'kv-v2',
|
|
149
|
+
path: `${secretProvider.path}/${name}`,
|
|
150
|
+
destination: { create: true, name: secretName },
|
|
151
|
+
},
|
|
152
|
+
}));
|
|
153
|
+
break;
|
|
154
|
+
case 'openbao':
|
|
155
|
+
resources.push((0, core_1.jsx)('OpenBaoStaticSecret', {
|
|
156
|
+
apiVersion: 'secrets.openbao.org/v1beta1',
|
|
157
|
+
kind: 'OpenBaoStaticSecret',
|
|
158
|
+
metadata: { name: `${name}-db-secret`, namespace },
|
|
159
|
+
spec: {
|
|
160
|
+
openbaoAuthRef: secretProvider.authRef,
|
|
161
|
+
mount: secretProvider.mount,
|
|
162
|
+
type: 'kv-v2',
|
|
163
|
+
path: `${secretProvider.path}/${name}`,
|
|
164
|
+
destination: { create: true, name: secretName },
|
|
165
|
+
},
|
|
166
|
+
}));
|
|
167
|
+
break;
|
|
168
|
+
case 'sealed-secrets':
|
|
169
|
+
// Sealed Secrets: the user provides a sealed secret that was encrypted
|
|
170
|
+
// with the cluster's public key. We reference it — we never see the
|
|
171
|
+
// plaintext. The user must pre-create the SealedSecret.
|
|
172
|
+
resources.push((0, core_1.jsx)('SealedSecret', {
|
|
173
|
+
apiVersion: 'bitnami.com/v1alpha1',
|
|
174
|
+
kind: 'SealedSecret',
|
|
175
|
+
metadata: { name: secretName, namespace },
|
|
176
|
+
spec: {
|
|
177
|
+
encryptedData: {
|
|
178
|
+
// Placeholder — the user replaces this with their sealed value
|
|
179
|
+
password: 'REPLACE_WITH_SEALED_VALUE',
|
|
180
|
+
},
|
|
181
|
+
},
|
|
182
|
+
}));
|
|
183
|
+
break;
|
|
184
|
+
case 'kubernetes':
|
|
185
|
+
if (!password) {
|
|
186
|
+
throw new Error(`Database "${name}" uses the 'kubernetes' secrets backend, which requires a password.\n` +
|
|
187
|
+
`\n` +
|
|
188
|
+
`The kubernetes backend stores credentials as plain Kubernetes Secrets.\n` +
|
|
189
|
+
`For production, use a managed backend instead:\n` +
|
|
190
|
+
` <Platform secrets={{ backend: 'openbao' }}>\n` +
|
|
191
|
+
`\n` +
|
|
192
|
+
`Or provide a password explicitly:\n` +
|
|
193
|
+
` <Database name="${name}" password="..." />`);
|
|
194
|
+
}
|
|
195
|
+
resources.push((0, core_1.jsx)('Secret', {
|
|
196
|
+
apiVersion: 'v1',
|
|
197
|
+
kind: 'Secret',
|
|
198
|
+
metadata: { name: secretName, namespace },
|
|
199
|
+
stringData: {
|
|
200
|
+
password,
|
|
201
|
+
username: name,
|
|
202
|
+
uri: `postgresql://${name}:${password}@${host}:5432/${name}`,
|
|
203
|
+
},
|
|
204
|
+
}));
|
|
205
|
+
break;
|
|
206
|
+
default:
|
|
207
|
+
throw new Error(`Database "${name}" has an unknown secrets backend "${secretProvider.backend}".\n` +
|
|
208
|
+
`Supported backends: 'openbao', 'vault', 'sealed-secrets', 'kubernetes'`);
|
|
209
|
+
}
|
|
210
|
+
return resources;
|
|
211
|
+
}
|
|
212
|
+
//# sourceMappingURL=database.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"database.js","sourceRoot":"","sources":["../src/database.tsx"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,110 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* ExternalDNS configuration component.
|
|
3
|
+
*
|
|
4
|
+
* Use as a value in DnsProvider when you need custom configuration:
|
|
5
|
+
* ```tsx
|
|
6
|
+
* <DnsProvider provider={<ExternalDns server="ns1.example.com" tsig={{ path: 'dns/tsig', key: 'secret' }} />}>
|
|
7
|
+
* ```
|
|
8
|
+
*/
|
|
9
|
+
export interface ExternalDnsProps {
|
|
10
|
+
/** DNS server for RFC 2136 updates (e.g., 'ns1.example.com') */
|
|
11
|
+
server?: string;
|
|
12
|
+
/** DNS zone name (e.g., 'example.com') */
|
|
13
|
+
zone?: string;
|
|
14
|
+
/** TSIG secret for secure updates */
|
|
15
|
+
tsig?: {
|
|
16
|
+
/** Vault/OpenBao path to the TSIG key */
|
|
17
|
+
path: string;
|
|
18
|
+
/** Key in the Vault/OpenBao secret */
|
|
19
|
+
key: string;
|
|
20
|
+
/** Kubernetes Secret name to create (default: 'external-dns-tsig') */
|
|
21
|
+
secretName?: string;
|
|
22
|
+
};
|
|
23
|
+
/** Cloud provider config (alternative to RFC 2136) */
|
|
24
|
+
cloud?: {
|
|
25
|
+
provider: 'aws' | 'google' | 'cloudflare';
|
|
26
|
+
/** Provider-specific options */
|
|
27
|
+
options?: Record<string, string>;
|
|
28
|
+
};
|
|
29
|
+
/**
|
|
30
|
+
* Explicit DNS targets (IPs or hostnames) for DNSEndpoint records.
|
|
31
|
+
* When set, Endpoint components create DNSEndpoint CRs with these targets.
|
|
32
|
+
* When omitted, Endpoints annotate Gateway/Ingress instead and let
|
|
33
|
+
* ExternalDNS discover hostnames via its gateway/ingress source.
|
|
34
|
+
*/
|
|
35
|
+
targets?: string[];
|
|
36
|
+
}
|
|
37
|
+
export declare function ExternalDns(props: ExternalDnsProps): DnsConfig;
|
|
38
|
+
/** DNS provider configuration */
|
|
39
|
+
export interface DnsConfig {
|
|
40
|
+
/** DNS provider type */
|
|
41
|
+
provider: 'external-dns';
|
|
42
|
+
/** Provider-specific settings */
|
|
43
|
+
settings: ExternalDnsProps;
|
|
44
|
+
}
|
|
45
|
+
/** Union of all DNS provider configurations */
|
|
46
|
+
export type DnsProviderValue = 'external-dns' | DnsConfig;
|
|
47
|
+
export declare const DnsContext: import("../../core/src/context").Context<DnsConfig | null>;
|
|
48
|
+
export interface DnsProviderProps {
|
|
49
|
+
/**
|
|
50
|
+
* DNS provider — string for simple cases, component for advanced config.
|
|
51
|
+
*
|
|
52
|
+
* @example
|
|
53
|
+
* // Simple string
|
|
54
|
+
* <DnsProvider provider="external-dns">
|
|
55
|
+
*
|
|
56
|
+
* @example
|
|
57
|
+
* // Advanced component
|
|
58
|
+
* <DnsProvider provider={<ExternalDns server="ns1.example.com" tsig={{ path: 'dns/tsig', key: 'secret' }} />}>
|
|
59
|
+
*/
|
|
60
|
+
provider: DnsProviderValue;
|
|
61
|
+
/** Child components */
|
|
62
|
+
children?: unknown;
|
|
63
|
+
}
|
|
64
|
+
/**
|
|
65
|
+
* DnsProvider — cluster-level DNS configuration.
|
|
66
|
+
*
|
|
67
|
+
* Sets up ExternalDNS with the specified provider and credentials.
|
|
68
|
+
* All Endpoint/App children automatically create DNS records.
|
|
69
|
+
*
|
|
70
|
+
* @example
|
|
71
|
+
* import { DnsProvider, SecretProvider, App } from '@r8s/recipes'
|
|
72
|
+
*
|
|
73
|
+
* export default (
|
|
74
|
+
* <SecretProvider provider="openbao">
|
|
75
|
+
* <DnsProvider provider="external-dns">
|
|
76
|
+
* <App name="api" image="myapp:v1" host="api.example.com" />
|
|
77
|
+
* </DnsProvider>
|
|
78
|
+
* </SecretProvider>
|
|
79
|
+
* )
|
|
80
|
+
*
|
|
81
|
+
* @example
|
|
82
|
+
* import { DnsProvider, ExternalDns, SecretProvider, App } from '@r8s/recipes'
|
|
83
|
+
*
|
|
84
|
+
* export default (
|
|
85
|
+
* <SecretProvider provider="openbao">
|
|
86
|
+
* <DnsProvider provider={
|
|
87
|
+
* <ExternalDns
|
|
88
|
+
* server="ns1.example.com"
|
|
89
|
+
* zone="example.com"
|
|
90
|
+
* tsig={{ path: 'dns/tsig', key: 'secret' }}
|
|
91
|
+
* />
|
|
92
|
+
* }>
|
|
93
|
+
* <App name="api" image="myapp:v1" host="api.example.com" />
|
|
94
|
+
* </DnsProvider>
|
|
95
|
+
* </SecretProvider>
|
|
96
|
+
* )
|
|
97
|
+
*
|
|
98
|
+
* @example
|
|
99
|
+
* import { DnsProvider, ExternalDns, App } from '@r8s/recipes'
|
|
100
|
+
*
|
|
101
|
+
* export default (
|
|
102
|
+
* <DnsProvider provider={
|
|
103
|
+
* <ExternalDns cloud={{ provider: 'google', options: { project: 'my-project' } }} />
|
|
104
|
+
* }>
|
|
105
|
+
* <App name="api" image="myapp:v1" host="api.example.com" />
|
|
106
|
+
* </DnsProvider>
|
|
107
|
+
* )
|
|
108
|
+
*/
|
|
109
|
+
export declare function DnsProvider(props: DnsProviderProps): import("@r8s/core").r8sElement;
|
|
110
|
+
//# sourceMappingURL=dns-provider.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"dns-provider.d.ts","sourceRoot":"","sources":["../src/dns-provider.tsx"],"names":[],"mappings":"AAKA;;;;;;;GAOG;AACH,MAAM,WAAW,gBAAgB;IAC/B,gEAAgE;IAChE,MAAM,CAAC,EAAE,MAAM,CAAA;IACf,0CAA0C;IAC1C,IAAI,CAAC,EAAE,MAAM,CAAA;IACb,qCAAqC;IACrC,IAAI,CAAC,EAAE;QACL,yCAAyC;QACzC,IAAI,EAAE,MAAM,CAAA;QACZ,sCAAsC;QACtC,GAAG,EAAE,MAAM,CAAA;QACX,sEAAsE;QACtE,UAAU,CAAC,EAAE,MAAM,CAAA;KACpB,CAAA;IACD,sDAAsD;IACtD,KAAK,CAAC,EAAE;QACN,QAAQ,EAAE,KAAK,GAAG,QAAQ,GAAG,YAAY,CAAA;QACzC,gCAAgC;QAChC,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAA;KACjC,CAAA;IACD;;;;;OAKG;IACH,OAAO,CAAC,EAAE,MAAM,EAAE,CAAA;CACnB;AAED,wBAAgB,WAAW,CAAC,KAAK,EAAE,gBAAgB,GAAG,SAAS,CAK9D;AAED,iCAAiC;AACjC,MAAM,WAAW,SAAS;IACxB,wBAAwB;IACxB,QAAQ,EAAE,cAAc,CAAA;IACxB,iCAAiC;IACjC,QAAQ,EAAE,gBAAgB,CAAA;CAC3B;AAED,+CAA+C;AAC/C,MAAM,MAAM,gBAAgB,GAAG,cAAc,GAAG,SAAS,CAAA;AAEzD,eAAO,MAAM,UAAU,4DAAwC,CAAA;AAE/D,MAAM,WAAW,gBAAgB;IAC/B;;;;;;;;;;OAUG;IACH,QAAQ,EAAE,gBAAgB,CAAA;IAC1B,uBAAuB;IACvB,QAAQ,CAAC,EAAE,OAAO,CAAA;CACnB;AAED;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA4CG;AACH,wBAAgB,WAAW,CAAC,KAAK,EAAE,gBAAgB,kCAqElD"}
|
|
@@ -0,0 +1,121 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.DnsContext = void 0;
|
|
4
|
+
exports.ExternalDns = ExternalDns;
|
|
5
|
+
exports.DnsProvider = DnsProvider;
|
|
6
|
+
const core_1 = require("@r8s/core");
|
|
7
|
+
const defaults_1 = require("@r8s/core/defaults");
|
|
8
|
+
const defaults_2 = require("@r8s/core/defaults");
|
|
9
|
+
const crds_1 = require("@r8s/crds");
|
|
10
|
+
function ExternalDns(props) {
|
|
11
|
+
return {
|
|
12
|
+
provider: 'external-dns',
|
|
13
|
+
settings: props,
|
|
14
|
+
};
|
|
15
|
+
}
|
|
16
|
+
exports.DnsContext = (0, defaults_1.createContext)(null);
|
|
17
|
+
/**
|
|
18
|
+
* DnsProvider — cluster-level DNS configuration.
|
|
19
|
+
*
|
|
20
|
+
* Sets up ExternalDNS with the specified provider and credentials.
|
|
21
|
+
* All Endpoint/App children automatically create DNS records.
|
|
22
|
+
*
|
|
23
|
+
* @example
|
|
24
|
+
* import { DnsProvider, SecretProvider, App } from '@r8s/recipes'
|
|
25
|
+
*
|
|
26
|
+
* export default (
|
|
27
|
+
* <SecretProvider provider="openbao">
|
|
28
|
+
* <DnsProvider provider="external-dns">
|
|
29
|
+
* <App name="api" image="myapp:v1" host="api.example.com" />
|
|
30
|
+
* </DnsProvider>
|
|
31
|
+
* </SecretProvider>
|
|
32
|
+
* )
|
|
33
|
+
*
|
|
34
|
+
* @example
|
|
35
|
+
* import { DnsProvider, ExternalDns, SecretProvider, App } from '@r8s/recipes'
|
|
36
|
+
*
|
|
37
|
+
* export default (
|
|
38
|
+
* <SecretProvider provider="openbao">
|
|
39
|
+
* <DnsProvider provider={
|
|
40
|
+
* <ExternalDns
|
|
41
|
+
* server="ns1.example.com"
|
|
42
|
+
* zone="example.com"
|
|
43
|
+
* tsig={{ path: 'dns/tsig', key: 'secret' }}
|
|
44
|
+
* />
|
|
45
|
+
* }>
|
|
46
|
+
* <App name="api" image="myapp:v1" host="api.example.com" />
|
|
47
|
+
* </DnsProvider>
|
|
48
|
+
* </SecretProvider>
|
|
49
|
+
* )
|
|
50
|
+
*
|
|
51
|
+
* @example
|
|
52
|
+
* import { DnsProvider, ExternalDns, App } from '@r8s/recipes'
|
|
53
|
+
*
|
|
54
|
+
* export default (
|
|
55
|
+
* <DnsProvider provider={
|
|
56
|
+
* <ExternalDns cloud={{ provider: 'google', options: { project: 'my-project' } }} />
|
|
57
|
+
* }>
|
|
58
|
+
* <App name="api" image="myapp:v1" host="api.example.com" />
|
|
59
|
+
* </DnsProvider>
|
|
60
|
+
* )
|
|
61
|
+
*/
|
|
62
|
+
function DnsProvider(props) {
|
|
63
|
+
const { provider, children } = props;
|
|
64
|
+
const sharedOperators = (0, core_1.useContext)(defaults_2.OperatorContext);
|
|
65
|
+
const secrets = (0, core_1.useContext)(defaults_2.SecretContext);
|
|
66
|
+
// Resolve provider config
|
|
67
|
+
let config;
|
|
68
|
+
if (typeof provider === 'string') {
|
|
69
|
+
config = { provider, settings: {} };
|
|
70
|
+
}
|
|
71
|
+
else if ('settings' in provider) {
|
|
72
|
+
config = provider;
|
|
73
|
+
}
|
|
74
|
+
else if (provider &&
|
|
75
|
+
typeof provider === 'object' &&
|
|
76
|
+
'type' in provider &&
|
|
77
|
+
provider.type === ExternalDns) {
|
|
78
|
+
// r8s JSX element — call the component with its props
|
|
79
|
+
config = ExternalDns(provider.props);
|
|
80
|
+
}
|
|
81
|
+
else {
|
|
82
|
+
config = { provider: 'external-dns', settings: provider };
|
|
83
|
+
}
|
|
84
|
+
const resources = [];
|
|
85
|
+
// Declare external-dns operator
|
|
86
|
+
const hasExternalDNS = sharedOperators.some((op) => op.name === 'external-dns');
|
|
87
|
+
if (!hasExternalDNS) {
|
|
88
|
+
resources.push((0, core_1.declareOperator)(crds_1.operators['external-dns']()));
|
|
89
|
+
}
|
|
90
|
+
// TSIG secret via VSO
|
|
91
|
+
if (config.settings.tsig) {
|
|
92
|
+
if (!secrets || (secrets.backend !== 'vault' && secrets.backend !== 'openbao')) {
|
|
93
|
+
throw new Error(`DnsProvider: tsig requires SecretProvider with backend 'vault' or 'openbao'. ` +
|
|
94
|
+
`Current: ${secrets?.backend ?? 'none'}. ` +
|
|
95
|
+
`Fix: wrap in <SecretProvider provider="openbao"> or remove tsig.`);
|
|
96
|
+
}
|
|
97
|
+
const secretName = config.settings.tsig.secretName ?? 'external-dns-tsig';
|
|
98
|
+
const mount = secrets.mount ?? 'secret';
|
|
99
|
+
const basePath = secrets.path ?? '';
|
|
100
|
+
const fullPath = basePath
|
|
101
|
+
? `${basePath}/${config.settings.tsig.path}`
|
|
102
|
+
: config.settings.tsig.path;
|
|
103
|
+
const SecretKind = secrets.backend === 'openbao' ? 'OpenBaoStaticSecret' : 'VaultStaticSecret';
|
|
104
|
+
resources.push((0, core_1.jsx)(SecretKind, {
|
|
105
|
+
apiVersion: 'secrets.hashicorp.com/v1alpha1',
|
|
106
|
+
kind: SecretKind,
|
|
107
|
+
metadata: { name: secretName, namespace: 'external-dns' },
|
|
108
|
+
spec: {
|
|
109
|
+
mount,
|
|
110
|
+
path: fullPath,
|
|
111
|
+
type: 'kv-v2',
|
|
112
|
+
destination: { name: secretName, create: true },
|
|
113
|
+
refreshAfter: '1h',
|
|
114
|
+
},
|
|
115
|
+
}));
|
|
116
|
+
}
|
|
117
|
+
return (0, core_1.jsx)(core_1.Fragment, {
|
|
118
|
+
children: [...resources, (0, core_1.jsx)(exports.DnsContext.Provider, { value: config, children })],
|
|
119
|
+
});
|
|
120
|
+
}
|
|
121
|
+
//# sourceMappingURL=dns-provider.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"dns-provider.js","sourceRoot":"","sources":["../src/dns-provider.tsx"],"names":[],"mappings":";;;AA0CA,kCAKC;AA6ED,kCAqEC;AAjMD,oCAAsE;AACtE,iDAAkD;AAClD,iDAAmE;AACnE,oCAAqC;AAuCrC,SAAgB,WAAW,CAAC,KAAuB;IACjD,OAAO;QACL,QAAQ,EAAE,cAAc;QACxB,QAAQ,EAAE,KAAK;KAChB,CAAA;AACH,CAAC;AAaY,QAAA,UAAU,GAAG,IAAA,wBAAa,EAAmB,IAAI,CAAC,CAAA;AAmB/D;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA4CG;AACH,SAAgB,WAAW,CAAC,KAAuB;IACjD,MAAM,EAAE,QAAQ,EAAE,QAAQ,EAAE,GAAG,KAAK,CAAA;IAEpC,MAAM,eAAe,GAAG,IAAA,iBAAU,EAAC,0BAAe,CAAC,CAAA;IACnD,MAAM,OAAO,GAAG,IAAA,iBAAU,EAAC,wBAAa,CAAC,CAAA;IAEzC,0BAA0B;IAC1B,IAAI,MAAiB,CAAA;IACrB,IAAI,OAAO,QAAQ,KAAK,QAAQ,EAAE,CAAC;QACjC,MAAM,GAAG,EAAE,QAAQ,EAAE,QAAQ,EAAE,EAAE,EAAE,CAAA;IACrC,CAAC;SAAM,IAAI,UAAU,IAAI,QAAQ,EAAE,CAAC;QAClC,MAAM,GAAG,QAAQ,CAAA;IACnB,CAAC;SAAM,IACL,QAAQ;QACR,OAAO,QAAQ,KAAK,QAAQ;QAC5B,MAAM,IAAI,QAAQ;QACjB,QAAgB,CAAC,IAAI,KAAK,WAAW,EACtC,CAAC;QACD,sDAAsD;QACtD,MAAM,GAAG,WAAW,CAAE,QAAgB,CAAC,KAAK,CAAC,CAAA;IAC/C,CAAC;SAAM,CAAC;QACN,MAAM,GAAG,EAAE,QAAQ,EAAE,cAAc,EAAE,QAAQ,EAAE,QAAQ,EAAE,CAAA;IAC3D,CAAC;IAED,MAAM,SAAS,GAA6B,EAAE,CAAA;IAE9C,gCAAgC;IAChC,MAAM,cAAc,GAAG,eAAe,CAAC,IAAI,CAAC,CAAC,EAAE,EAAE,EAAE,CAAC,EAAE,CAAC,IAAI,KAAK,cAAc,CAAC,CAAA;IAC/E,IAAI,CAAC,cAAc,EAAE,CAAC;QACpB,SAAS,CAAC,IAAI,CAAC,IAAA,sBAAe,EAAC,gBAAS,CAAC,cAAc,CAAC,EAAE,CAAC,CAAC,CAAA;IAC9D,CAAC;IAED,sBAAsB;IACtB,IAAI,MAAM,CAAC,QAAQ,CAAC,IAAI,EAAE,CAAC;QACzB,IAAI,CAAC,OAAO,IAAI,CAAC,OAAO,CAAC,OAAO,KAAK,OAAO,IAAI,OAAO,CAAC,OAAO,KAAK,SAAS,CAAC,EAAE,CAAC;YAC/E,MAAM,IAAI,KAAK,CACb,+EAA+E;gBAC7E,YAAY,OAAO,EAAE,OAAO,IAAI,MAAM,IAAI;gBAC1C,kEAAkE,CACrE,CAAA;QACH,CAAC;QAED,MAAM,UAAU,GAAG,MAAM,CAAC,QAAQ,CAAC,IAAI,CAAC,UAAU,IAAI,mBAAmB,CAAA;QACzE,MAAM,KAAK,GAAG,OAAO,CAAC,KAAK,IAAI,QAAQ,CAAA;QACvC,MAAM,QAAQ,GAAG,OAAO,CAAC,IAAI,IAAI,EAAE,CAAA;QACnC,MAAM,QAAQ,GAAG,QAAQ;YACvB,CAAC,CAAC,GAAG,QAAQ,IAAI,MAAM,CAAC,QAAQ,CAAC,IAAI,CAAC,IAAI,EAAE;YAC5C,CAAC,CAAC,MAAM,CAAC,QAAQ,CAAC,IAAI,CAAC,IAAI,CAAA;QAE7B,MAAM,UAAU,GAAG,OAAO,CAAC,OAAO,KAAK,SAAS,CAAC,CAAC,CAAC,qBAAqB,CAAC,CAAC,CAAC,mBAAmB,CAAA;QAC9F,SAAS,CAAC,IAAI,CACZ,IAAA,UAAG,EAAC,UAAU,EAAE;YACd,UAAU,EAAE,gCAAgC;YAC5C,IAAI,EAAE,UAAU;YAChB,QAAQ,EAAE,EAAE,IAAI,EAAE,UAAU,EAAE,SAAS,EAAE,cAAc,EAAE;YACzD,IAAI,EAAE;gBACJ,KAAK;gBACL,IAAI,EAAE,QAAQ;gBACd,IAAI,EAAE,OAAO;gBACb,WAAW,EAAE,EAAE,IAAI,EAAE,UAAU,EAAE,MAAM,EAAE,IAAI,EAAE;gBAC/C,YAAY,EAAE,IAAI;aACnB;SACF,CAAC,CACH,CAAA;IACH,CAAC;IAED,OAAO,IAAA,UAAG,EAAC,eAAQ,EAAE;QACnB,QAAQ,EAAE,CAAC,GAAG,SAAS,EAAE,IAAA,UAAG,EAAC,kBAAU,CAAC,QAAQ,EAAE,EAAE,KAAK,EAAE,MAAM,EAAE,QAAQ,EAAE,CAAC,CAAC;KAChF,CAAC,CAAA;AACJ,CAAC"}
|
|
@@ -0,0 +1,121 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Nginx Ingress configuration component.
|
|
3
|
+
*
|
|
4
|
+
* Use as a value in EndpointProvider when you need custom configuration:
|
|
5
|
+
* ```tsx
|
|
6
|
+
* <EndpointProvider provider={<Nginx className="nginx-internal" />}>
|
|
7
|
+
* ```
|
|
8
|
+
*/
|
|
9
|
+
export interface NginxProps {
|
|
10
|
+
/** Ingress class name (default: 'nginx') */
|
|
11
|
+
className?: string;
|
|
12
|
+
/** Default TLS configuration */
|
|
13
|
+
tls?: {
|
|
14
|
+
/** ClusterIssuer for cert-manager */
|
|
15
|
+
clusterIssuer?: string;
|
|
16
|
+
};
|
|
17
|
+
}
|
|
18
|
+
export declare function Nginx(props: NginxProps): EndpointConfig;
|
|
19
|
+
/**
|
|
20
|
+
* Envoy Gateway configuration component.
|
|
21
|
+
*
|
|
22
|
+
* Use as a value in EndpointProvider when you need custom configuration:
|
|
23
|
+
* ```tsx
|
|
24
|
+
* <EndpointProvider provider={<EnvoyGateway className="eg" tls={{ clusterIssuer: 'letsencrypt' }} />}>
|
|
25
|
+
* ```
|
|
26
|
+
*/
|
|
27
|
+
export interface EnvoyGatewayProps {
|
|
28
|
+
/** Gateway class name (default: 'eg') */
|
|
29
|
+
className?: string;
|
|
30
|
+
/** Default TLS configuration */
|
|
31
|
+
tls?: {
|
|
32
|
+
/** ClusterIssuer for cert-manager */
|
|
33
|
+
clusterIssuer?: string;
|
|
34
|
+
};
|
|
35
|
+
}
|
|
36
|
+
export declare function EnvoyGateway(props: EnvoyGatewayProps): EndpointConfig;
|
|
37
|
+
/** Endpoint provider configuration */
|
|
38
|
+
export interface EndpointConfig {
|
|
39
|
+
/** Routing implementation */
|
|
40
|
+
provider: 'nginx' | 'envoy-gateway';
|
|
41
|
+
/** Provider-specific settings */
|
|
42
|
+
settings?: {
|
|
43
|
+
/** Gateway class name (envoy-gateway only) */
|
|
44
|
+
gatewayClassName?: string;
|
|
45
|
+
/** Ingress class name (nginx only) */
|
|
46
|
+
ingressClassName?: string;
|
|
47
|
+
/** Default TLS configuration */
|
|
48
|
+
tls?: {
|
|
49
|
+
clusterIssuer?: string;
|
|
50
|
+
};
|
|
51
|
+
};
|
|
52
|
+
}
|
|
53
|
+
/** Union of all endpoint provider configurations */
|
|
54
|
+
export type EndpointProviderValue = 'nginx' | 'envoy-gateway' | EndpointConfig;
|
|
55
|
+
export declare const EndpointContext: import("../../core/src/context").Context<EndpointConfig>;
|
|
56
|
+
export interface EndpointProviderProps {
|
|
57
|
+
/**
|
|
58
|
+
* Endpoint provider — string for simple cases, component for advanced config.
|
|
59
|
+
*
|
|
60
|
+
* @example
|
|
61
|
+
* // Simple string provider
|
|
62
|
+
* import { EndpointProvider, App } from '@r8s/recipes'
|
|
63
|
+
*
|
|
64
|
+
* export default (
|
|
65
|
+
* <EndpointProvider provider="nginx">
|
|
66
|
+
* <App name="api" image="myapp:v1" host="api.example.com" />
|
|
67
|
+
* </EndpointProvider>
|
|
68
|
+
* )
|
|
69
|
+
*
|
|
70
|
+
* @example
|
|
71
|
+
* // Advanced component provider
|
|
72
|
+
* import { EndpointProvider, Nginx, App } from '@r8s/recipes'
|
|
73
|
+
*
|
|
74
|
+
* export default (
|
|
75
|
+
* <EndpointProvider provider={<Nginx className="nginx-internal" />}>
|
|
76
|
+
* <App name="api" image="myapp:v1" host="api.example.com" />
|
|
77
|
+
* </EndpointProvider>
|
|
78
|
+
* )
|
|
79
|
+
*/
|
|
80
|
+
provider: EndpointProviderValue;
|
|
81
|
+
/** Child components */
|
|
82
|
+
children?: unknown;
|
|
83
|
+
}
|
|
84
|
+
/**
|
|
85
|
+
* EndpointProvider — cluster-level routing configuration.
|
|
86
|
+
*
|
|
87
|
+
* Sets whether endpoints use nginx Ingress or Envoy Gateway (Gateway API).
|
|
88
|
+
* All Endpoint/App children read this context.
|
|
89
|
+
*
|
|
90
|
+
* @example
|
|
91
|
+
* // Simple string provider
|
|
92
|
+
* import { EndpointProvider, App } from '@r8s/recipes'
|
|
93
|
+
*
|
|
94
|
+
* export default (
|
|
95
|
+
* <EndpointProvider provider="nginx">
|
|
96
|
+
* <App name="api" image="myapp:v1" host="api.example.com" />
|
|
97
|
+
* </EndpointProvider>
|
|
98
|
+
* )
|
|
99
|
+
*
|
|
100
|
+
* @example
|
|
101
|
+
* // Nginx with custom class and TLS
|
|
102
|
+
* import { EndpointProvider, Nginx, App } from '@r8s/recipes'
|
|
103
|
+
*
|
|
104
|
+
* export default (
|
|
105
|
+
* <EndpointProvider provider={<Nginx className="nginx-internal" tls={{ clusterIssuer: 'letsencrypt' }} />}>
|
|
106
|
+
* <App name="api" image="myapp:v1" host="api.example.com" />
|
|
107
|
+
* </EndpointProvider>
|
|
108
|
+
* )
|
|
109
|
+
*
|
|
110
|
+
* @example
|
|
111
|
+
* // Envoy Gateway with TLS
|
|
112
|
+
* import { EndpointProvider, EnvoyGateway, App } from '@r8s/recipes'
|
|
113
|
+
*
|
|
114
|
+
* export default (
|
|
115
|
+
* <EndpointProvider provider={<EnvoyGateway className="eg" tls={{ clusterIssuer: 'letsencrypt-prod' }} />}>
|
|
116
|
+
* <App name="api" image="myapp:v1" host="api.example.com" />
|
|
117
|
+
* </EndpointProvider>
|
|
118
|
+
* )
|
|
119
|
+
*/
|
|
120
|
+
export declare function EndpointProvider(props: EndpointProviderProps): import("@r8s/core").r8sElement;
|
|
121
|
+
//# sourceMappingURL=endpoint-provider.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"endpoint-provider.d.ts","sourceRoot":"","sources":["../src/endpoint-provider.tsx"],"names":[],"mappings":"AAIA;;;;;;;GAOG;AACH,MAAM,WAAW,UAAU;IACzB,4CAA4C;IAC5C,SAAS,CAAC,EAAE,MAAM,CAAA;IAClB,gCAAgC;IAChC,GAAG,CAAC,EAAE;QACJ,qCAAqC;QACrC,aAAa,CAAC,EAAE,MAAM,CAAA;KACvB,CAAA;CACF;AAED,wBAAgB,KAAK,CAAC,KAAK,EAAE,UAAU,GAAG,cAAc,CAQvD;AAED;;;;;;;GAOG;AACH,MAAM,WAAW,iBAAiB;IAChC,yCAAyC;IACzC,SAAS,CAAC,EAAE,MAAM,CAAA;IAClB,gCAAgC;IAChC,GAAG,CAAC,EAAE;QACJ,qCAAqC;QACrC,aAAa,CAAC,EAAE,MAAM,CAAA;KACvB,CAAA;CACF;AAED,wBAAgB,YAAY,CAAC,KAAK,EAAE,iBAAiB,GAAG,cAAc,CAQrE;AAED,sCAAsC;AACtC,MAAM,WAAW,cAAc;IAC7B,6BAA6B;IAC7B,QAAQ,EAAE,OAAO,GAAG,eAAe,CAAA;IACnC,iCAAiC;IACjC,QAAQ,CAAC,EAAE;QACT,8CAA8C;QAC9C,gBAAgB,CAAC,EAAE,MAAM,CAAA;QACzB,sCAAsC;QACtC,gBAAgB,CAAC,EAAE,MAAM,CAAA;QACzB,gCAAgC;QAChC,GAAG,CAAC,EAAE;YACJ,aAAa,CAAC,EAAE,MAAM,CAAA;SACvB,CAAA;KACF,CAAA;CACF;AAED,oDAAoD;AACpD,MAAM,MAAM,qBAAqB,GAAG,OAAO,GAAG,eAAe,GAAG,cAAc,CAAA;AAE9E,eAAO,MAAM,eAAe,0DAAuD,CAAA;AAEnF,MAAM,WAAW,qBAAqB;IACpC;;;;;;;;;;;;;;;;;;;;;;OAsBG;IACH,QAAQ,EAAE,qBAAqB,CAAA;IAC/B,uBAAuB;IACvB,QAAQ,CAAC,EAAE,OAAO,CAAA;CACnB;AAED;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAmCG;AACH,wBAAgB,gBAAgB,CAAC,KAAK,EAAE,qBAAqB,kCAgB5D"}
|
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.EndpointContext = void 0;
|
|
4
|
+
exports.Nginx = Nginx;
|
|
5
|
+
exports.EnvoyGateway = EnvoyGateway;
|
|
6
|
+
exports.EndpointProvider = EndpointProvider;
|
|
7
|
+
const core_1 = require("@r8s/core");
|
|
8
|
+
const defaults_1 = require("@r8s/core/defaults");
|
|
9
|
+
const defaults_2 = require("@r8s/core/defaults");
|
|
10
|
+
function Nginx(props) {
|
|
11
|
+
return {
|
|
12
|
+
provider: 'nginx',
|
|
13
|
+
settings: {
|
|
14
|
+
ingressClassName: props.className ?? 'nginx',
|
|
15
|
+
tls: props.tls,
|
|
16
|
+
},
|
|
17
|
+
};
|
|
18
|
+
}
|
|
19
|
+
function EnvoyGateway(props) {
|
|
20
|
+
return {
|
|
21
|
+
provider: 'envoy-gateway',
|
|
22
|
+
settings: {
|
|
23
|
+
gatewayClassName: props.className ?? 'eg',
|
|
24
|
+
tls: props.tls,
|
|
25
|
+
},
|
|
26
|
+
};
|
|
27
|
+
}
|
|
28
|
+
exports.EndpointContext = (0, defaults_1.createContext)({ provider: 'nginx' });
|
|
29
|
+
/**
|
|
30
|
+
* EndpointProvider — cluster-level routing configuration.
|
|
31
|
+
*
|
|
32
|
+
* Sets whether endpoints use nginx Ingress or Envoy Gateway (Gateway API).
|
|
33
|
+
* All Endpoint/App children read this context.
|
|
34
|
+
*
|
|
35
|
+
* @example
|
|
36
|
+
* // Simple string provider
|
|
37
|
+
* import { EndpointProvider, App } from '@r8s/recipes'
|
|
38
|
+
*
|
|
39
|
+
* export default (
|
|
40
|
+
* <EndpointProvider provider="nginx">
|
|
41
|
+
* <App name="api" image="myapp:v1" host="api.example.com" />
|
|
42
|
+
* </EndpointProvider>
|
|
43
|
+
* )
|
|
44
|
+
*
|
|
45
|
+
* @example
|
|
46
|
+
* // Nginx with custom class and TLS
|
|
47
|
+
* import { EndpointProvider, Nginx, App } from '@r8s/recipes'
|
|
48
|
+
*
|
|
49
|
+
* export default (
|
|
50
|
+
* <EndpointProvider provider={<Nginx className="nginx-internal" tls={{ clusterIssuer: 'letsencrypt' }} />}>
|
|
51
|
+
* <App name="api" image="myapp:v1" host="api.example.com" />
|
|
52
|
+
* </EndpointProvider>
|
|
53
|
+
* )
|
|
54
|
+
*
|
|
55
|
+
* @example
|
|
56
|
+
* // Envoy Gateway with TLS
|
|
57
|
+
* import { EndpointProvider, EnvoyGateway, App } from '@r8s/recipes'
|
|
58
|
+
*
|
|
59
|
+
* export default (
|
|
60
|
+
* <EndpointProvider provider={<EnvoyGateway className="eg" tls={{ clusterIssuer: 'letsencrypt-prod' }} />}>
|
|
61
|
+
* <App name="api" image="myapp:v1" host="api.example.com" />
|
|
62
|
+
* </EndpointProvider>
|
|
63
|
+
* )
|
|
64
|
+
*/
|
|
65
|
+
function EndpointProvider(props) {
|
|
66
|
+
const { provider, children } = props;
|
|
67
|
+
// Resolve provider config
|
|
68
|
+
const config = typeof provider === 'string' ? { provider } : provider;
|
|
69
|
+
// Map to RoutingContext for backward compatibility
|
|
70
|
+
const routing = {
|
|
71
|
+
mode: config.provider === 'envoy-gateway' ? 'gateway' : 'ingress',
|
|
72
|
+
gatewayClassName: config.settings?.gatewayClassName ?? 'eg',
|
|
73
|
+
};
|
|
74
|
+
return (0, core_1.jsx)(defaults_2.RoutingContext.Provider, {
|
|
75
|
+
value: routing,
|
|
76
|
+
children: (0, core_1.jsx)(exports.EndpointContext.Provider, { value: config, children }),
|
|
77
|
+
});
|
|
78
|
+
}
|
|
79
|
+
//# sourceMappingURL=endpoint-provider.js.map
|