kubetsx 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/LICENSE +22 -0
- package/README.md +371 -0
- package/dist/components/index.d.ts +46 -0
- package/dist/components/index.d.ts.map +1 -0
- package/dist/components/index.js +155 -0
- package/dist/components/index.js.map +1 -0
- package/dist/index.d.ts +10 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +34 -0
- package/dist/index.js.map +1 -0
- package/dist/jsx-runtime.d.ts +33 -0
- package/dist/jsx-runtime.d.ts.map +1 -0
- package/dist/jsx-runtime.js +58 -0
- package/dist/jsx-runtime.js.map +1 -0
- package/dist/render.d.ts +12 -0
- package/dist/render.d.ts.map +1 -0
- package/dist/render.js +746 -0
- package/dist/render.js.map +1 -0
- package/dist/types.d.ts +339 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/types.js +5 -0
- package/dist/types.js.map +1 -0
- package/examples/basic.tsx +71 -0
- package/examples/full-stack.tsx +339 -0
- package/examples/tsconfig.json +21 -0
- package/package.json +57 -0
- package/src/components/index.ts +241 -0
- package/src/index.ts +123 -0
- package/src/jsx-runtime.ts +71 -0
- package/src/render.ts +862 -0
- package/src/types.ts +362 -0
- package/tsconfig.examples.json +18 -0
- package/tsconfig.json +22 -0
|
@@ -0,0 +1,339 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* 🎯 Kubetsx - Full Stack Example
|
|
3
|
+
*
|
|
4
|
+
* Complete production-ready deployment with:
|
|
5
|
+
* - Multiple microservices
|
|
6
|
+
* - Namespaces
|
|
7
|
+
* - ConfigMaps & Secrets
|
|
8
|
+
* - Autoscaling
|
|
9
|
+
* - RBAC
|
|
10
|
+
*
|
|
11
|
+
* @jsxImportSource ../dist
|
|
12
|
+
*/
|
|
13
|
+
|
|
14
|
+
import {
|
|
15
|
+
render,
|
|
16
|
+
Manifest,
|
|
17
|
+
Cluster,
|
|
18
|
+
Namespace,
|
|
19
|
+
Deployment,
|
|
20
|
+
Container,
|
|
21
|
+
Port,
|
|
22
|
+
Env,
|
|
23
|
+
SecretRef,
|
|
24
|
+
ConfigMapRef,
|
|
25
|
+
Resources,
|
|
26
|
+
Probe,
|
|
27
|
+
HttpProbe,
|
|
28
|
+
ExecProbe,
|
|
29
|
+
Service,
|
|
30
|
+
Ingress,
|
|
31
|
+
IngressHost,
|
|
32
|
+
Route,
|
|
33
|
+
ConfigMap,
|
|
34
|
+
Secret,
|
|
35
|
+
Pvc,
|
|
36
|
+
Hpa,
|
|
37
|
+
CronJob,
|
|
38
|
+
ServiceAccount,
|
|
39
|
+
Role,
|
|
40
|
+
RoleBinding,
|
|
41
|
+
Volume,
|
|
42
|
+
VolumeMount,
|
|
43
|
+
EmptyDir,
|
|
44
|
+
PvcVolume,
|
|
45
|
+
} from '../dist/index.js';
|
|
46
|
+
|
|
47
|
+
// ============================================================================
|
|
48
|
+
// Configuration
|
|
49
|
+
// ============================================================================
|
|
50
|
+
|
|
51
|
+
const VERSION = process.env.VERSION || 'latest';
|
|
52
|
+
const ENV = process.env.NODE_ENV || 'production';
|
|
53
|
+
const isProduction = ENV === 'production';
|
|
54
|
+
|
|
55
|
+
// Service definitions - just add to this array to deploy new services!
|
|
56
|
+
const services = [
|
|
57
|
+
{
|
|
58
|
+
name: 'api',
|
|
59
|
+
replicas: isProduction ? 5 : 1,
|
|
60
|
+
port: 3000,
|
|
61
|
+
host: 'api.mycompany.com',
|
|
62
|
+
memory: '512Mi',
|
|
63
|
+
cpu: '500m',
|
|
64
|
+
secrets: ['DATABASE_URL', 'REDIS_URL', 'JWT_SECRET'],
|
|
65
|
+
autoscale: { min: 3, max: 10, cpu: 70 },
|
|
66
|
+
},
|
|
67
|
+
{
|
|
68
|
+
name: 'auth',
|
|
69
|
+
replicas: isProduction ? 3 : 1,
|
|
70
|
+
port: 4000,
|
|
71
|
+
host: 'auth.mycompany.com',
|
|
72
|
+
memory: '256Mi',
|
|
73
|
+
cpu: '250m',
|
|
74
|
+
secrets: ['DATABASE_URL', 'OAUTH_CLIENT_SECRET', 'JWT_SECRET'],
|
|
75
|
+
autoscale: { min: 2, max: 5, cpu: 80 },
|
|
76
|
+
},
|
|
77
|
+
{
|
|
78
|
+
name: 'worker',
|
|
79
|
+
replicas: isProduction ? 3 : 1,
|
|
80
|
+
port: 5000,
|
|
81
|
+
memory: '1Gi',
|
|
82
|
+
cpu: '1',
|
|
83
|
+
secrets: ['DATABASE_URL', 'REDIS_URL', 'AWS_ACCESS_KEY', 'AWS_SECRET_KEY'],
|
|
84
|
+
// No autoscale for workers
|
|
85
|
+
},
|
|
86
|
+
];
|
|
87
|
+
|
|
88
|
+
// Cron jobs
|
|
89
|
+
const cronJobs = [
|
|
90
|
+
{ name: 'cleanup', schedule: '0 3 * * *', command: ['node', 'scripts/cleanup.js'] },
|
|
91
|
+
{ name: 'reports', schedule: '0 8 * * 1', command: ['node', 'scripts/weekly-report.js'] },
|
|
92
|
+
{ name: 'backups', schedule: '0 2 * * *', command: ['node', 'scripts/backup.js'] },
|
|
93
|
+
];
|
|
94
|
+
|
|
95
|
+
// ============================================================================
|
|
96
|
+
// Reusable Components
|
|
97
|
+
// ============================================================================
|
|
98
|
+
|
|
99
|
+
interface StandardContainerProps {
|
|
100
|
+
name: string;
|
|
101
|
+
port: number;
|
|
102
|
+
memory: string;
|
|
103
|
+
cpu: string;
|
|
104
|
+
secrets: string[];
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
const StandardContainer = ({ name, port, memory, cpu, secrets }: StandardContainerProps) => (
|
|
108
|
+
<Container name={name} image={`mycompany/${name}:${VERSION}`}>
|
|
109
|
+
<Port container={port} />
|
|
110
|
+
|
|
111
|
+
{/* Common env vars */}
|
|
112
|
+
<Env name="NODE_ENV" value={ENV} />
|
|
113
|
+
<Env name="SERVICE_NAME" value={name} />
|
|
114
|
+
<Env name="LOG_LEVEL">
|
|
115
|
+
<ConfigMapRef name="app-config" key="log_level" />
|
|
116
|
+
</Env>
|
|
117
|
+
|
|
118
|
+
{/* Service-specific secrets */}
|
|
119
|
+
{secrets.map(secret => (
|
|
120
|
+
<Env key={secret} name={secret}>
|
|
121
|
+
<SecretRef name="app-secrets" secretKey={secret.toLowerCase().replace(/_/g, '-')} />
|
|
122
|
+
</Env>
|
|
123
|
+
))}
|
|
124
|
+
|
|
125
|
+
<Resources
|
|
126
|
+
requestMemory={memory}
|
|
127
|
+
requestCpu={cpu}
|
|
128
|
+
limitMemory={memory}
|
|
129
|
+
limitCpu={cpu}
|
|
130
|
+
/>
|
|
131
|
+
|
|
132
|
+
<Probe type="liveness" delay={30} period={10}>
|
|
133
|
+
<HttpProbe path="/health" port={port} />
|
|
134
|
+
</Probe>
|
|
135
|
+
<Probe type="readiness" delay={5} period={5}>
|
|
136
|
+
<HttpProbe path="/ready" port={port} />
|
|
137
|
+
</Probe>
|
|
138
|
+
|
|
139
|
+
{/* Temp storage for logs */}
|
|
140
|
+
<VolumeMount name="tmp" mountPath="/tmp" />
|
|
141
|
+
</Container>
|
|
142
|
+
);
|
|
143
|
+
|
|
144
|
+
// ============================================================================
|
|
145
|
+
// Main Infrastructure
|
|
146
|
+
// ============================================================================
|
|
147
|
+
|
|
148
|
+
const ProductionStack = () => (
|
|
149
|
+
<Cluster name="production">
|
|
150
|
+
{/* ================================================================== */}
|
|
151
|
+
{/* Backend Namespace */}
|
|
152
|
+
{/* ================================================================== */}
|
|
153
|
+
<Namespace name="backend" labels={{ team: 'platform', env: ENV }}>
|
|
154
|
+
|
|
155
|
+
{/* Shared ConfigMap */}
|
|
156
|
+
<ConfigMap
|
|
157
|
+
name="app-config"
|
|
158
|
+
data={{
|
|
159
|
+
log_level: isProduction ? 'info' : 'debug',
|
|
160
|
+
feature_flags: JSON.stringify({ newUI: true, analytics: isProduction }),
|
|
161
|
+
}}
|
|
162
|
+
/>
|
|
163
|
+
|
|
164
|
+
{/* Shared Secret (in practice, use external secrets manager) */}
|
|
165
|
+
<Secret
|
|
166
|
+
name="app-secrets"
|
|
167
|
+
stringData={{
|
|
168
|
+
'database-url': '${DATABASE_URL}',
|
|
169
|
+
'redis-url': '${REDIS_URL}',
|
|
170
|
+
'jwt-secret': '${JWT_SECRET}',
|
|
171
|
+
'oauth-client-secret': '${OAUTH_CLIENT_SECRET}',
|
|
172
|
+
'aws-access-key': '${AWS_ACCESS_KEY}',
|
|
173
|
+
'aws-secret-key': '${AWS_SECRET_KEY}',
|
|
174
|
+
}}
|
|
175
|
+
/>
|
|
176
|
+
|
|
177
|
+
{/* Service Account with RBAC */}
|
|
178
|
+
<ServiceAccount name="backend-sa" />
|
|
179
|
+
<Role
|
|
180
|
+
name="backend-role"
|
|
181
|
+
rules={[
|
|
182
|
+
{ apiGroups: [''], resources: ['configmaps', 'secrets'], verbs: ['get', 'list', 'watch'] },
|
|
183
|
+
{ apiGroups: [''], resources: ['pods'], verbs: ['get', 'list'] },
|
|
184
|
+
]}
|
|
185
|
+
/>
|
|
186
|
+
<RoleBinding
|
|
187
|
+
name="backend-role-binding"
|
|
188
|
+
roleRef={{ kind: 'Role', name: 'backend-role' }}
|
|
189
|
+
subjects={[{ kind: 'ServiceAccount', name: 'backend-sa' }]}
|
|
190
|
+
/>
|
|
191
|
+
|
|
192
|
+
{/* Deploy all services using loop! */}
|
|
193
|
+
{services.map(svc => (
|
|
194
|
+
<Manifest key={svc.name}>
|
|
195
|
+
<Deployment
|
|
196
|
+
name={svc.name}
|
|
197
|
+
replicas={svc.replicas}
|
|
198
|
+
labels={{ app: svc.name, version: VERSION }}
|
|
199
|
+
>
|
|
200
|
+
<StandardContainer
|
|
201
|
+
name={svc.name}
|
|
202
|
+
port={svc.port}
|
|
203
|
+
memory={svc.memory}
|
|
204
|
+
cpu={svc.cpu}
|
|
205
|
+
secrets={svc.secrets}
|
|
206
|
+
/>
|
|
207
|
+
<Volume name="tmp">
|
|
208
|
+
<EmptyDir />
|
|
209
|
+
</Volume>
|
|
210
|
+
</Deployment>
|
|
211
|
+
|
|
212
|
+
<Service
|
|
213
|
+
name={svc.name}
|
|
214
|
+
port={80}
|
|
215
|
+
targetPort={svc.port}
|
|
216
|
+
selector={{ app: svc.name }}
|
|
217
|
+
/>
|
|
218
|
+
|
|
219
|
+
{/* HPA only for services with autoscale config */}
|
|
220
|
+
{svc.autoscale && (
|
|
221
|
+
<Hpa
|
|
222
|
+
name={`${svc.name}-hpa`}
|
|
223
|
+
target={svc.name}
|
|
224
|
+
minReplicas={svc.autoscale.min}
|
|
225
|
+
maxReplicas={svc.autoscale.max}
|
|
226
|
+
targetCpuUtilization={svc.autoscale.cpu}
|
|
227
|
+
/>
|
|
228
|
+
)}
|
|
229
|
+
</Manifest>
|
|
230
|
+
))}
|
|
231
|
+
|
|
232
|
+
{/* Ingress for public services */}
|
|
233
|
+
<Ingress name="backend-ingress" className="nginx" ssl>
|
|
234
|
+
{services
|
|
235
|
+
.filter(svc => svc.host)
|
|
236
|
+
.map(svc => (
|
|
237
|
+
<IngressHost key={svc.name} host={svc.host!}>
|
|
238
|
+
<Route path="/" service={svc.name} port={80} />
|
|
239
|
+
</IngressHost>
|
|
240
|
+
))
|
|
241
|
+
}
|
|
242
|
+
</Ingress>
|
|
243
|
+
|
|
244
|
+
{/* Cron Jobs */}
|
|
245
|
+
{cronJobs.map(job => (
|
|
246
|
+
<CronJob
|
|
247
|
+
key={job.name}
|
|
248
|
+
name={job.name}
|
|
249
|
+
schedule={job.schedule}
|
|
250
|
+
concurrencyPolicy="Forbid"
|
|
251
|
+
>
|
|
252
|
+
<Container
|
|
253
|
+
name={job.name}
|
|
254
|
+
image={`mycompany/jobs:${VERSION}`}
|
|
255
|
+
command={job.command}
|
|
256
|
+
>
|
|
257
|
+
<Env name="DATABASE_URL">
|
|
258
|
+
<SecretRef name="app-secrets" secretKey="database-url" />
|
|
259
|
+
</Env>
|
|
260
|
+
<Resources requestMemory="256Mi" requestCpu="100m" />
|
|
261
|
+
</Container>
|
|
262
|
+
</CronJob>
|
|
263
|
+
))}
|
|
264
|
+
</Namespace>
|
|
265
|
+
|
|
266
|
+
{/* ================================================================== */}
|
|
267
|
+
{/* Database Namespace */}
|
|
268
|
+
{/* ================================================================== */}
|
|
269
|
+
<Namespace name="databases" labels={{ team: 'platform', env: ENV }}>
|
|
270
|
+
|
|
271
|
+
{/* PostgreSQL PVC */}
|
|
272
|
+
<Pvc
|
|
273
|
+
name="postgres-data"
|
|
274
|
+
storage="100Gi"
|
|
275
|
+
accessModes={['ReadWriteOnce']}
|
|
276
|
+
storageClassName="ssd"
|
|
277
|
+
/>
|
|
278
|
+
|
|
279
|
+
{/* PostgreSQL Deployment */}
|
|
280
|
+
<Deployment name="postgres" replicas={1}>
|
|
281
|
+
<Container name="postgres" image="postgres:15-alpine">
|
|
282
|
+
<Port container={5432} />
|
|
283
|
+
<Env name="POSTGRES_PASSWORD">
|
|
284
|
+
<SecretRef name="postgres-secrets" key="password" />
|
|
285
|
+
</Env>
|
|
286
|
+
<Env name="POSTGRES_DB" value="myapp" />
|
|
287
|
+
<Resources
|
|
288
|
+
requestMemory="1Gi"
|
|
289
|
+
requestCpu="500m"
|
|
290
|
+
limitMemory="2Gi"
|
|
291
|
+
limitCpu="1"
|
|
292
|
+
/>
|
|
293
|
+
<Probe type="readiness" delay={5} period={10}>
|
|
294
|
+
<ExecProbe command={['pg_isready', '-U', 'postgres']} />
|
|
295
|
+
</Probe>
|
|
296
|
+
<VolumeMount name="data" mountPath="/var/lib/postgresql/data" />
|
|
297
|
+
</Container>
|
|
298
|
+
<Volume name="data">
|
|
299
|
+
<PvcVolume claimName="postgres-data" />
|
|
300
|
+
</Volume>
|
|
301
|
+
</Deployment>
|
|
302
|
+
|
|
303
|
+
<Service name="postgres" port={5432} targetPort={5432} type="ClusterIP" />
|
|
304
|
+
|
|
305
|
+
{/* Redis Deployment */}
|
|
306
|
+
<Deployment name="redis" replicas={1}>
|
|
307
|
+
<Container name="redis" image="redis:7-alpine">
|
|
308
|
+
<Port container={6379} />
|
|
309
|
+
<Resources
|
|
310
|
+
requestMemory="256Mi"
|
|
311
|
+
requestCpu="100m"
|
|
312
|
+
limitMemory="512Mi"
|
|
313
|
+
limitCpu="200m"
|
|
314
|
+
/>
|
|
315
|
+
<Probe type="readiness" delay={5}>
|
|
316
|
+
<ExecProbe command={['redis-cli', 'ping']} />
|
|
317
|
+
</Probe>
|
|
318
|
+
</Container>
|
|
319
|
+
</Deployment>
|
|
320
|
+
|
|
321
|
+
<Service name="redis" port={6379} targetPort={6379} type="ClusterIP" />
|
|
322
|
+
|
|
323
|
+
</Namespace>
|
|
324
|
+
</Cluster>
|
|
325
|
+
);
|
|
326
|
+
|
|
327
|
+
// ============================================================================
|
|
328
|
+
// Render Output
|
|
329
|
+
// ============================================================================
|
|
330
|
+
|
|
331
|
+
console.log('🎯 Kubetsx - Generating Kubernetes manifests...\n');
|
|
332
|
+
console.log(`Environment: ${ENV}`);
|
|
333
|
+
console.log(`Version: ${VERSION}`);
|
|
334
|
+
console.log(`Services: ${services.map(s => s.name).join(', ')}`);
|
|
335
|
+
console.log(`Cron Jobs: ${cronJobs.map(j => j.name).join(', ')}`);
|
|
336
|
+
console.log('\n---\n');
|
|
337
|
+
|
|
338
|
+
render(<ProductionStack />);
|
|
339
|
+
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
{
|
|
2
|
+
"compilerOptions": {
|
|
3
|
+
"target": "ES2022",
|
|
4
|
+
"module": "ESNext",
|
|
5
|
+
"moduleResolution": "bundler",
|
|
6
|
+
"lib": ["ES2022"],
|
|
7
|
+
"strict": true,
|
|
8
|
+
"esModuleInterop": true,
|
|
9
|
+
"skipLibCheck": true,
|
|
10
|
+
"forceConsistentCasingInFileNames": true,
|
|
11
|
+
"jsx": "react-jsx",
|
|
12
|
+
"jsxImportSource": "../dist",
|
|
13
|
+
"paths": {
|
|
14
|
+
"kubetsx": ["../dist/index.js"],
|
|
15
|
+
"kubetsx/*": ["../dist/*"]
|
|
16
|
+
},
|
|
17
|
+
"baseUrl": "."
|
|
18
|
+
},
|
|
19
|
+
"include": ["./**/*"]
|
|
20
|
+
}
|
|
21
|
+
|
package/package.json
ADDED
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "kubetsx",
|
|
3
|
+
"version": "0.1.0",
|
|
4
|
+
"description": "The Declarative Kubernetes Framework. Write K8s configs with JSX. Yes, really.",
|
|
5
|
+
"type": "module",
|
|
6
|
+
"main": "dist/index.js",
|
|
7
|
+
"types": "dist/index.d.ts",
|
|
8
|
+
"exports": {
|
|
9
|
+
".": {
|
|
10
|
+
"types": "./dist/index.d.ts",
|
|
11
|
+
"import": "./dist/index.js"
|
|
12
|
+
},
|
|
13
|
+
"./jsx-runtime": {
|
|
14
|
+
"types": "./dist/jsx-runtime.d.ts",
|
|
15
|
+
"import": "./dist/jsx-runtime.js"
|
|
16
|
+
}
|
|
17
|
+
},
|
|
18
|
+
"scripts": {
|
|
19
|
+
"build": "tsc",
|
|
20
|
+
"dev": "tsc --watch",
|
|
21
|
+
"example": "npm run build && node --experimental-strip-types examples/full-stack.tsx",
|
|
22
|
+
"example:basic": "npm run build && node --experimental-strip-types examples/basic.tsx",
|
|
23
|
+
"prepublishOnly": "npm run build"
|
|
24
|
+
},
|
|
25
|
+
"keywords": [
|
|
26
|
+
"kubernetes",
|
|
27
|
+
"k8s",
|
|
28
|
+
"jsx",
|
|
29
|
+
"tsx",
|
|
30
|
+
"yaml",
|
|
31
|
+
"declarative",
|
|
32
|
+
"infrastructure",
|
|
33
|
+
"config",
|
|
34
|
+
"devops"
|
|
35
|
+
],
|
|
36
|
+
"author": "malekabdelkader",
|
|
37
|
+
"license": "MIT",
|
|
38
|
+
"repository": {
|
|
39
|
+
"type": "git",
|
|
40
|
+
"url": "git+https://github.com/malekabdelkader/kubetsx.git"
|
|
41
|
+
},
|
|
42
|
+
"bugs": {
|
|
43
|
+
"url": "https://github.com/malekabdelkader/kubetsx/issues"
|
|
44
|
+
},
|
|
45
|
+
"homepage": "https://github.com/malekabdelkader/kubetsx#readme",
|
|
46
|
+
"devDependencies": {
|
|
47
|
+
"@types/node": "^22.0.0",
|
|
48
|
+
"typescript": "^5.7.0"
|
|
49
|
+
},
|
|
50
|
+
"dependencies": {
|
|
51
|
+
"yaml": "^2.7.0"
|
|
52
|
+
},
|
|
53
|
+
"engines": {
|
|
54
|
+
"node": ">=22.0.0"
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
|
|
@@ -0,0 +1,241 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* 🎯 Kubetsx - Component Definitions
|
|
3
|
+
*
|
|
4
|
+
* All Kubernetes resource components as JSX elements
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
import { h } from '../jsx-runtime.js';
|
|
8
|
+
import type {
|
|
9
|
+
KubexElement,
|
|
10
|
+
KubexNode,
|
|
11
|
+
ManifestProps,
|
|
12
|
+
ClusterProps,
|
|
13
|
+
NamespaceProps,
|
|
14
|
+
DeploymentProps,
|
|
15
|
+
ContainerProps,
|
|
16
|
+
PortProps,
|
|
17
|
+
EnvProps,
|
|
18
|
+
SecretRefProps,
|
|
19
|
+
ConfigMapRefProps,
|
|
20
|
+
ResourcesProps,
|
|
21
|
+
ProbeProps,
|
|
22
|
+
HttpProbeProps,
|
|
23
|
+
TcpProbeProps,
|
|
24
|
+
ExecProbeProps,
|
|
25
|
+
ServiceProps,
|
|
26
|
+
IngressProps,
|
|
27
|
+
IngressHostProps,
|
|
28
|
+
RouteProps,
|
|
29
|
+
ConfigMapProps,
|
|
30
|
+
SecretProps,
|
|
31
|
+
VolumeProps,
|
|
32
|
+
VolumeMountProps,
|
|
33
|
+
EmptyDirProps,
|
|
34
|
+
PvcVolumeProps,
|
|
35
|
+
ConfigMapVolumeProps,
|
|
36
|
+
SecretVolumeProps,
|
|
37
|
+
PvcProps,
|
|
38
|
+
HpaProps,
|
|
39
|
+
JobProps,
|
|
40
|
+
CronJobProps,
|
|
41
|
+
ServiceAccountProps,
|
|
42
|
+
RoleProps,
|
|
43
|
+
ClusterRoleProps,
|
|
44
|
+
RoleBindingProps,
|
|
45
|
+
ClusterRoleBindingProps,
|
|
46
|
+
} from '../types.js';
|
|
47
|
+
|
|
48
|
+
// Helper to get children array
|
|
49
|
+
function getChildren(children: KubexNode | undefined): KubexNode[] {
|
|
50
|
+
if (!children) return [];
|
|
51
|
+
return Array.isArray(children) ? children : [children];
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
// Cast helper
|
|
55
|
+
function toProps(props: object): Record<string, unknown> {
|
|
56
|
+
return props as Record<string, unknown>;
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
// ============================================================================
|
|
60
|
+
// Manifest (Fragment alternative - groups multiple resources)
|
|
61
|
+
// ============================================================================
|
|
62
|
+
|
|
63
|
+
export function Manifest(props: ManifestProps): KubexElement {
|
|
64
|
+
return h('Manifest', toProps(props), ...getChildren(props.children));
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
// ============================================================================
|
|
68
|
+
// Cluster & Namespace
|
|
69
|
+
// ============================================================================
|
|
70
|
+
|
|
71
|
+
export function Cluster(props: ClusterProps): KubexElement {
|
|
72
|
+
return h('Cluster', toProps(props), ...getChildren(props.children));
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
export function Namespace(props: NamespaceProps): KubexElement {
|
|
76
|
+
return h('Namespace', toProps(props), ...getChildren(props.children));
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
// ============================================================================
|
|
80
|
+
// Workloads
|
|
81
|
+
// ============================================================================
|
|
82
|
+
|
|
83
|
+
export function Deployment(props: DeploymentProps): KubexElement {
|
|
84
|
+
return h('Deployment', toProps(props), ...getChildren(props.children));
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
export function Container(props: ContainerProps & { children?: KubexNode }): KubexElement {
|
|
88
|
+
return h('Container', toProps(props), ...getChildren(props.children));
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
export function Job(props: JobProps): KubexElement {
|
|
92
|
+
return h('Job', toProps(props), ...getChildren(props.children));
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
export function CronJob(props: CronJobProps): KubexElement {
|
|
96
|
+
return h('CronJob', toProps(props), ...getChildren(props.children));
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
// ============================================================================
|
|
100
|
+
// Container Configuration
|
|
101
|
+
// ============================================================================
|
|
102
|
+
|
|
103
|
+
export function Port(props: PortProps): KubexElement {
|
|
104
|
+
return h('Port', toProps(props));
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
export function Env(props: EnvProps): KubexElement {
|
|
108
|
+
return h('Env', toProps(props), ...getChildren(props.children));
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
export function SecretRef(props: SecretRefProps): KubexElement {
|
|
112
|
+
return h('SecretRef', toProps(props));
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
export function ConfigMapRef(props: ConfigMapRefProps): KubexElement {
|
|
116
|
+
return h('ConfigMapRef', toProps(props));
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
export function Resources(props: ResourcesProps): KubexElement {
|
|
120
|
+
return h('Resources', toProps(props));
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
// ============================================================================
|
|
124
|
+
// Probes
|
|
125
|
+
// ============================================================================
|
|
126
|
+
|
|
127
|
+
export function Probe(props: ProbeProps): KubexElement {
|
|
128
|
+
return h('Probe', toProps(props), ...getChildren(props.children));
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
export function HttpProbe(props: HttpProbeProps): KubexElement {
|
|
132
|
+
return h('HttpProbe', toProps(props));
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
export function TcpProbe(props: TcpProbeProps): KubexElement {
|
|
136
|
+
return h('TcpProbe', toProps(props));
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
export function ExecProbe(props: ExecProbeProps): KubexElement {
|
|
140
|
+
return h('ExecProbe', toProps(props));
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
// ============================================================================
|
|
144
|
+
// Networking
|
|
145
|
+
// ============================================================================
|
|
146
|
+
|
|
147
|
+
export function Service(props: ServiceProps): KubexElement {
|
|
148
|
+
return h('Service', toProps(props));
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
export function Ingress(props: IngressProps & { host?: string }): KubexElement {
|
|
152
|
+
return h('Ingress', toProps(props), ...getChildren(props.children));
|
|
153
|
+
}
|
|
154
|
+
|
|
155
|
+
export function IngressHost(props: IngressHostProps): KubexElement {
|
|
156
|
+
return h('IngressHost', toProps(props), ...getChildren(props.children));
|
|
157
|
+
}
|
|
158
|
+
|
|
159
|
+
export function Route(props: RouteProps): KubexElement {
|
|
160
|
+
return h('Route', toProps(props));
|
|
161
|
+
}
|
|
162
|
+
|
|
163
|
+
// ============================================================================
|
|
164
|
+
// Configuration
|
|
165
|
+
// ============================================================================
|
|
166
|
+
|
|
167
|
+
export function ConfigMap(props: ConfigMapProps): KubexElement {
|
|
168
|
+
return h('ConfigMap', toProps(props));
|
|
169
|
+
}
|
|
170
|
+
|
|
171
|
+
export function Secret(props: SecretProps): KubexElement {
|
|
172
|
+
return h('Secret', toProps(props));
|
|
173
|
+
}
|
|
174
|
+
|
|
175
|
+
// ============================================================================
|
|
176
|
+
// Volumes
|
|
177
|
+
// ============================================================================
|
|
178
|
+
|
|
179
|
+
export function Volume(props: VolumeProps): KubexElement {
|
|
180
|
+
return h('Volume', toProps(props), ...getChildren(props.children));
|
|
181
|
+
}
|
|
182
|
+
|
|
183
|
+
export function VolumeMount(props: VolumeMountProps): KubexElement {
|
|
184
|
+
return h('VolumeMount', toProps(props));
|
|
185
|
+
}
|
|
186
|
+
|
|
187
|
+
export function EmptyDir(props: EmptyDirProps = {}): KubexElement {
|
|
188
|
+
return h('EmptyDir', toProps(props));
|
|
189
|
+
}
|
|
190
|
+
|
|
191
|
+
export function PvcVolume(props: PvcVolumeProps): KubexElement {
|
|
192
|
+
return h('PvcVolume', toProps(props));
|
|
193
|
+
}
|
|
194
|
+
|
|
195
|
+
export function ConfigMapVolume(props: ConfigMapVolumeProps): KubexElement {
|
|
196
|
+
return h('ConfigMapVolume', toProps(props));
|
|
197
|
+
}
|
|
198
|
+
|
|
199
|
+
export function SecretVolume(props: SecretVolumeProps): KubexElement {
|
|
200
|
+
return h('SecretVolume', toProps(props));
|
|
201
|
+
}
|
|
202
|
+
|
|
203
|
+
// ============================================================================
|
|
204
|
+
// Storage
|
|
205
|
+
// ============================================================================
|
|
206
|
+
|
|
207
|
+
export function Pvc(props: PvcProps): KubexElement {
|
|
208
|
+
return h('Pvc', toProps(props));
|
|
209
|
+
}
|
|
210
|
+
|
|
211
|
+
// ============================================================================
|
|
212
|
+
// Autoscaling
|
|
213
|
+
// ============================================================================
|
|
214
|
+
|
|
215
|
+
export function Hpa(props: HpaProps): KubexElement {
|
|
216
|
+
return h('Hpa', toProps(props));
|
|
217
|
+
}
|
|
218
|
+
|
|
219
|
+
// ============================================================================
|
|
220
|
+
// RBAC & Service Accounts
|
|
221
|
+
// ============================================================================
|
|
222
|
+
|
|
223
|
+
export function ServiceAccount(props: ServiceAccountProps): KubexElement {
|
|
224
|
+
return h('ServiceAccount', toProps(props));
|
|
225
|
+
}
|
|
226
|
+
|
|
227
|
+
export function Role(props: RoleProps): KubexElement {
|
|
228
|
+
return h('Role', toProps(props));
|
|
229
|
+
}
|
|
230
|
+
|
|
231
|
+
export function ClusterRole(props: ClusterRoleProps): KubexElement {
|
|
232
|
+
return h('ClusterRole', toProps(props));
|
|
233
|
+
}
|
|
234
|
+
|
|
235
|
+
export function RoleBinding(props: RoleBindingProps): KubexElement {
|
|
236
|
+
return h('RoleBinding', toProps(props));
|
|
237
|
+
}
|
|
238
|
+
|
|
239
|
+
export function ClusterRoleBinding(props: ClusterRoleBindingProps): KubexElement {
|
|
240
|
+
return h('ClusterRoleBinding', toProps(props));
|
|
241
|
+
}
|