timonel 2.1.0 → 2.2.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/README.md CHANGED
@@ -10,854 +10,88 @@
10
10
  [![TypeScript][ts-badge]][ts-url]
11
11
  [![Maintained by KenkoGeek][maintained-badge]][maintained-url]
12
12
 
13
- Timonel (Spanish for helmsman) is a TypeScript library to programmatically
14
- generate Helm charts using cdk8s. Define Kubernetes resources with classes and
15
- synthesize a full Helm chart with `Chart.yaml`, `values.yaml`, per‑environment
16
- values files, and `templates/`.
13
+ Timonel (Spanish for "helmsman") is a TypeScript library to programmatically generate Helm charts
14
+ using cdk8s. Define Kubernetes resources with classes and synthesize a full Helm chart with
15
+ `Chart.yaml`, `values.yaml`, per‑environment values files, and `templates/`.
17
16
 
18
- Key features:
17
+ ## ✨ Key Features
19
18
 
20
- - Type-safe API (strict TypeScript) with cdk8s constructs.
21
- - Helm templating helpers to embed `{{ .Values.* }}` where needed.
22
- - Simple multi-environment setup: `values.yaml`, `values-dev.yaml`, `values-prod.yaml`, etc.
23
- - **Umbrella Charts**: Manage multiple subcharts as a single deployable unit.
24
- - Minimal CLI (`tl`) to scaffold an example and synthesize the chart.
19
+ - **Type-safe API** with strict TypeScript and cdk8s constructs
20
+ - **Multi-environment support** with automatic values files generation
21
+ - **Umbrella Charts** for managing multiple subcharts as a single unit
22
+ - **Multi-cloud integrations** for AWS, Azure, and GCP
23
+ - **Security-first approach** with NetworkPolicies and best practices
24
+ - **Minimal CLI** (`tl`) for scaffolding and chart generation
25
25
 
26
- Advanced templating:
27
-
28
- - Programmatic Helm helpers: generate `templates/_helpers.tpl` and call helpers using `template()`/`include()`.
29
- - Umbrella chart support with automatic dependency management.
30
-
31
- ## Installation
32
-
33
- ### Using npm
26
+ ## 🚀 Quick Start
34
27
 
35
28
  ```bash
36
- npm install timonel
37
- ```
29
+ # Install Timonel globally
30
+ npm install -g timonel
38
31
 
39
- ### Development setup
32
+ # Create your first chart
33
+ tl init my-app
40
34
 
41
- Requirements: Node.js 20+ (Corepack enabled)
35
+ # Generate Helm chart
36
+ tl synth charts/my-app charts/my-app-dist
42
37
 
43
- ```bash
44
- corepack enable
45
- corepack prepare pnpm@latest --activate
46
- pnpm install
47
- pnpm run build
38
+ # Use with Helm
39
+ helm install my-app charts/my-app-dist
48
40
  ```
49
41
 
50
- ### Developer setup (git hooks)
51
-
52
- After installing dependencies, enable git hooks with Husky:
53
-
54
- ```bash
55
- pnpm dlx husky init || npx husky init
56
- ```
57
-
58
- This sets up pre-commit and commit-msg hooks to run lint-staged and commitlint.
59
- The pre-commit hook also runs Node-based Markdown linting (markdownlint)
60
- automatically.
61
-
62
- Markdown commands:
63
-
64
- - Lint: `pnpm run md:lint`
65
- - Fix: `pnpm run md:fix`
66
-
67
- ## Quick start
68
-
69
- <!-- markdownlint-disable MD029 -->
70
-
71
- 1. Create an example project
72
-
73
- ```bash
74
- tl init my-app-src
75
- ```
76
-
77
- This generates `charts/my-app-src/chart.ts` with a working example.
78
-
79
- 2. Synthesize Helm chart artifacts
80
-
81
- ```bash
82
- tl synth charts/my-app-src charts/my-app/
83
- ```
84
-
85
- Expected output:
86
-
87
- - `charts/my-app/Chart.yaml`
88
- - `charts/my-app/values.yaml`
89
- - `charts/my-app/values-dev.yaml`, `values-prod.yaml` (if defined)
90
- - `charts/my-app/templates/*.yaml`
91
-
92
- 3. Use with Helm
93
-
94
- ```bash
95
- helm template charts/my-app -f charts/my-app/values-dev.yaml
96
- helm install my-app charts/my-app -f charts/my-app/values-prod.yaml
97
- ```
42
+ ## 📚 Documentation
98
43
 
99
- Note: the output directory (`charts/my-app/` in this example) is overwritten if files
100
- exist. Use a clean folder or move old artifacts before running synth.
44
+ For comprehensive documentation, examples, and guides, visit our **[Wiki](https://github.com/KenkoGeek/timonel/wiki)**:
101
45
 
102
- ### Package the chart (tgz)
46
+ - **[Installation](https://github.com/KenkoGeek/timonel/wiki/Installation)** - Setup and requirements
47
+ - **[Quick Start](https://github.com/KenkoGeek/timonel/wiki/Quick-Start)** - Your first chart in 5 minutes
48
+ - **[Examples](https://github.com/KenkoGeek/timonel/wiki/Examples)** - Real-world deployment patterns
49
+ - **[Multi-Cloud Support](https://github.com/KenkoGeek/timonel/wiki/Multi-Cloud-Support)** - AWS,
50
+ Azure, GCP integrations
51
+ - **[CLI Reference](https://github.com/KenkoGeek/timonel/wiki/CLI-Commands)** - Complete command guide
103
52
 
104
- Requires Helm installed locally (`helm version`). Packages the chart directory into a
105
- `.tgz` that you can publish or attach to releases:
106
-
107
- ```bash
108
- tl package charts/my-app charts/
109
- # or set HELM_BIN if helm is not in PATH
110
- HELM_BIN=/usr/local/bin/helm tl package charts/my-app charts/
111
- ```
112
-
113
- ## Library API
53
+ ## 💡 Basic Example
114
54
 
115
55
  ```typescript
116
56
  import { Rutter } from 'timonel';
117
- import {
118
- valuesRef,
119
- helm,
120
- template,
121
- include,
122
- numberRef,
123
- boolRef,
124
- stringRef,
125
- floatRef,
126
- } from 'timonel';
57
+ import { valuesRef } from 'timonel';
127
58
 
128
59
  const rutter = new Rutter({
129
- meta: { name: 'my-app', version: '0.1.0', appVersion: '1.0.0' },
60
+ meta: { name: 'my-app', version: '0.1.0' },
130
61
  defaultValues: {
131
62
  image: { repository: 'nginx', tag: '1.27' },
132
63
  replicas: 2,
133
- service: { port: 80 },
134
64
  },
135
- envValues: { dev: { replicas: 1 }, prod: { replicas: 4 } },
136
- helpersTpl: [
137
- {
138
- name: 'timonel.fullname',
139
- body: `{{- printf "%s-%s" .Chart.Name .Release.Name | trunc 63 | trimSuffix "-" -}}`,
140
- },
141
- ],
142
- // Custom manifest naming options
143
- manifestName: 'my-app-resources', // Custom name for manifest files
144
- singleManifestFile: true, // Combine all resources into one file
65
+ envValues: {
66
+ dev: { replicas: 1 },
67
+ prod: { replicas: 5 },
68
+ },
145
69
  });
146
70
 
147
71
  rutter.addDeployment({
148
72
  name: 'my-app',
149
73
  image: `${valuesRef('image.repository')}:${valuesRef('image.tag')}`,
150
- replicas: 2,
74
+ replicas: Number(valuesRef('replicas')),
151
75
  containerPort: 80,
152
76
  });
153
77
 
154
78
  rutter.addService({ name: 'my-app', port: 80 });
155
79
 
156
- // Add auto-scaling with HPA and VPA
157
- rutter.addHorizontalPodAutoscaler({
158
- name: 'my-app-hpa',
159
- scaleTargetRef: { apiVersion: 'apps/v1', kind: 'Deployment', name: 'my-app' },
160
- minReplicas: 1,
161
- maxReplicas: 10,
162
- });
163
-
164
- rutter.addVerticalPodAutoscaler({
165
- name: 'my-app-vpa',
166
- targetRef: { apiVersion: 'apps/v1', kind: 'Deployment', name: 'my-app' },
167
- updatePolicy: { updateMode: 'Auto' },
168
- });
169
-
170
- rutter.addPodDisruptionBudget({
171
- name: 'my-app-pdb',
172
- minAvailable: 1,
173
- selector: { matchLabels: { app: 'my-app' } },
174
- });
175
-
176
- // Add one-time Job for database migration
177
- rutter.addJob({
178
- name: 'db-migration',
179
- image: 'migrate:latest',
180
- command: ['migrate'],
181
- args: ['up'],
182
- restartPolicy: 'OnFailure',
183
- backoffLimit: 3,
184
- activeDeadlineSeconds: 600,
185
- ttlSecondsAfterFinished: 86400,
186
- });
187
-
188
- // Add scheduled CronJob for backups
189
- rutter.addCronJob({
190
- name: 'backup-job',
191
- schedule: '0 2 * * *', // Daily at 2 AM
192
- image: 'backup:latest',
193
- command: ['backup.sh'],
194
- restartPolicy: 'OnFailure',
195
- concurrencyPolicy: 'Forbid',
196
- successfulJobsHistoryLimit: 3,
197
- failedJobsHistoryLimit: 1,
198
- });
199
-
200
- // Add IRSA ServiceAccount for AWS access
201
- rutter.addAWSIRSAServiceAccount({
202
- name: 'my-app-irsa',
203
- roleArn: 'arn:aws:iam::123456789012:role/MyAppRole',
204
- stsEndpointType: 'regional',
205
- tokenExpiration: 3600,
206
- });
207
-
208
- rutter.write('dist/charts/my-app');
209
- ```
210
-
211
- ### Custom Manifest Naming
212
-
213
- > **⚠️ Breaking Change Notice**: Starting from v1.1.0, template files no longer include
214
- > automatic numbering prefixes (0000-, 0001-, etc.). Files now use descriptive names
215
- > following Helm best practices. If your scripts or tools depend on numbered filenames,
216
- > please update them accordingly.
217
-
218
- Timonel provides flexible options for naming your Kubernetes manifest files:
219
-
220
- #### Single Manifest File
221
-
222
- ```typescript
223
- const rutter = new Rutter({
224
- meta: { name: 'my-app', version: '0.1.0' },
225
- manifestName: 'application',
226
- singleManifestFile: true, // All resources in one file
227
- });
228
-
229
- // Generates: templates/application.yaml
230
- ```
231
-
232
- #### Separate Files with Custom Names
233
-
234
- ```typescript
235
- const rutter = new Rutter({
236
- meta: { name: 'my-app', version: '0.1.0' },
237
- manifestName: 'my-app',
238
- singleManifestFile: false, // Each resource in its own file (default)
239
- });
240
-
241
- // Generates:
242
- // templates/my-app-deployment-web.yaml
243
- // templates/my-app-service-web.yaml
244
- // templates/my-app-configmap-config.yaml
245
- ```
246
-
247
- #### Default Behavior
248
-
249
- ```typescript
250
- const rutter = new Rutter({
251
- meta: { name: 'my-app', version: '0.1.0' },
252
- // No manifestName specified
253
- });
254
-
255
- // Generates:
256
- // templates/deployment-web.yaml
257
- // templates/service-web.yaml
258
- // templates/configmap-config.yaml
259
- ```
260
-
261
- ## Umbrella Charts
262
-
263
- Create umbrella charts that combine multiple subcharts into a single deployable unit:
264
-
265
- ```typescript
266
- import { createUmbrella, Rutter } from 'timonel';
267
-
268
- // Create individual subcharts
269
- const mysql = new Rutter({
270
- meta: { name: 'mysql', version: '0.1.0' },
271
- // MySQL configuration...
272
- });
273
-
274
- const wordpress = new Rutter({
275
- meta: { name: 'wordpress', version: '0.1.0' },
276
- // WordPress configuration...
277
- });
278
-
279
- // Combine into umbrella chart
280
- const umbrella = createUmbrella({
281
- meta: {
282
- name: 'wordpress-stack',
283
- version: '1.0.0',
284
- description: 'Complete WordPress stack with MySQL database',
285
- },
286
- subcharts: [
287
- { name: 'mysql', rutter: mysql },
288
- { name: 'wordpress', rutter: wordpress },
289
- ],
290
- defaultValues: {
291
- global: { storageClass: 'gp2' },
292
- mysql: { persistence: { size: '8Gi' } },
293
- wordpress: { service: { type: 'LoadBalancer' } },
294
- },
295
- envValues: {
296
- dev: { mysql: { persistence: { size: '5Gi' } } },
297
- prod: { mysql: { persistence: { size: '20Gi' } } },
298
- },
299
- });
300
-
301
- umbrella.write('dist/wordpress-stack');
302
- ```
303
-
304
- ### CLI for Umbrella Charts
305
-
306
- ```bash
307
- # Create umbrella structure
308
- tl umbrella init my-stack
309
-
310
- # Add subcharts
311
- tl umbrella add database
312
- tl umbrella add frontend
313
-
314
- # Generate umbrella chart
315
- tl umbrella synth ./dist
316
- ```
317
-
318
- ## Examples
319
-
320
- The `examples/` directory contains complete working examples:
321
-
322
- - **aws-game-2048**: Production-ready AWS 2048 game deployment showcasing AWS-specific features
323
- - AWS ALB Ingress with health checks and SSL support
324
- - HorizontalPodAutoscaler (HPA) for automatic scaling based on CPU utilization
325
- - PodDisruptionBudget (PDB) for high availability during updates
326
- - Multi-environment configuration (dev/staging/prod)
327
- - **wordpress**: WordPress with MySQL database setup (single chart)
328
- - **wordpress-umbrella**: WordPress stack using umbrella charts (MySQL + WordPress subcharts)
329
-
330
- Each example includes its own README with deployment instructions.
331
-
332
- ### Umbrella Chart Example
333
-
334
- See `examples/wordpress-umbrella/` for a complete umbrella chart implementation that
335
- separates MySQL and WordPress into individual subcharts with proper dependencies,
336
- shared values, and multi-environment support.
337
-
338
- - `valuesRef(path)`: returns a Helm placeholder string for `.Values.*`.
339
- - You can pass these strings directly into cdk8s constructs; they are preserved in the YAML.
340
- - `template(name, ctx='.')` and `include(name, ctx='.')`: inject calls to helpers defined in `_helpers.tpl`.
341
- - `numberRef(path)`, `boolRef(path)`: cast `.Values.*` to numeric/boolean using Sprig
342
- (`int`, `toBool`). Use for template strings, not direct numeric fields.
343
- - `stringRef(path)`, `floatRef(path)`: cast `.Values.*` to string/float using Sprig
344
- (`toString`, `float64`).
345
- - For numeric fields (ports, replicas), use literal values or template strings with proper casting.
346
-
347
- ## Multi-Cloud Support
348
-
349
- Timonel provides comprehensive cloud-specific helpers for major Kubernetes platforms:
350
-
351
- ### AWS Multi-Cloud Support
352
-
353
- Comprehensive AWS-specific helpers for EKS deployments:
354
-
355
- ### IRSA (IAM Roles for Service Accounts)
356
-
357
- Securely access AWS services from Kubernetes pods using IAM roles:
358
-
359
- ```typescript
360
- // Dedicated IRSA ServiceAccount
361
- rutter.addAWSIRSAServiceAccount({
362
- name: 'app-s3-access',
363
- roleArn: 'arn:aws:iam::123456789012:role/AppS3Role',
364
- audience: 'sts.amazonaws.com', // optional, defaults to sts.amazonaws.com
365
- stsEndpointType: 'regional', // recommended for better performance
366
- tokenExpiration: 3600, // optional, token lifetime in seconds
367
- });
368
-
369
- // General ServiceAccount with IRSA support
370
- rutter.addServiceAccount({
371
- name: 'my-app-sa',
372
- awsRoleArn: 'arn:aws:iam::123456789012:role/MyAppRole',
373
- awsStsEndpointType: 'regional',
374
- awsTokenExpiration: 7200,
375
- automountServiceAccountToken: true,
376
- });
80
+ export default function run(outDir: string) {
81
+ rutter.write(outDir);
82
+ }
377
83
  ```
378
84
 
379
- ### AWS Storage Classes
380
-
381
- ```typescript
382
- // EBS GP3 StorageClass
383
- rutter.addAWSEBSStorageClass({
384
- name: 'fast-ssd',
385
- volumeType: 'gp3',
386
- encrypted: true,
387
- iops: 3000,
388
- throughput: 125,
389
- });
390
-
391
- // EFS StorageClass for shared storage
392
- rutter.addAWSEFSStorageClass({
393
- name: 'shared-storage',
394
- reclaimPolicy: 'Retain',
395
- });
396
- ```
397
-
398
- ### AWS Load Balancer Controller
399
-
400
- ```typescript
401
- // ALB Ingress with health checks
402
- rutter.addAWSALBIngress({
403
- name: 'app-ingress',
404
- scheme: 'internet-facing',
405
- targetType: 'ip',
406
- healthCheckPath: '/health',
407
- certificateArn:
408
- 'arn:aws:acm:us-west-2:123456789012:certificate/12345678-1234-1234-1234-123456789012',
409
- rules: [
410
- {
411
- paths: [
412
- {
413
- path: '/',
414
- pathType: 'Prefix',
415
- backend: { service: { name: 'my-app', port: { number: 80 } } },
416
- },
417
- ],
418
- },
419
- ],
420
- });
421
- ```
422
-
423
- ### AWS Secrets Manager and Parameter Store
424
-
425
- Integrate with AWS Secrets Manager and Parameter Store using the Secrets Store CSI Driver:
426
-
427
- ```typescript
428
- // Secrets Manager integration
429
- rutter.addAWSSecretProviderClass({
430
- name: 'app-secrets',
431
- region: 'us-west-2',
432
- objects: [
433
- {
434
- objectName: 'prod/myapp/database',
435
- objectType: 'secretsmanager',
436
- objectAlias: 'db-credentials',
437
- },
438
- {
439
- objectName: 'prod/myapp/api-keys',
440
- objectType: 'secretsmanager',
441
- jmesPath: '["api_key", "secret_key"]', // Extract specific keys from JSON
442
- },
443
- ],
444
- });
445
-
446
- // Parameter Store integration
447
- rutter.addAWSSecretProviderClass({
448
- name: 'app-config',
449
- region: 'us-west-2',
450
- objects: [
451
- {
452
- objectName: '/myapp/config/debug-mode',
453
- objectType: 'ssmparameter',
454
- objectAlias: 'debug-flag',
455
- },
456
- {
457
- objectName: '/myapp/config/cache-ttl',
458
- objectType: 'ssmparameter',
459
- objectAlias: 'cache-timeout',
460
- },
461
- ],
462
- });
463
- ```
464
-
465
- ### Azure Multi-Cloud Support
466
-
467
- Azure-specific helpers for AKS deployments:
468
-
469
- #### Azure Disk Storage Classes
470
-
471
- ```typescript
472
- // Premium ZRS disk for production workloads
473
- rutter.addAzureDiskStorageClass({
474
- name: 'azure-premium-zrs',
475
- skuName: 'Premium_ZRS',
476
- fsType: 'ext4',
477
- cachingMode: 'ReadWrite',
478
- allowVolumeExpansion: true,
479
- volumeBindingMode: 'WaitForFirstConsumer',
480
- tags: {
481
- Environment: 'production',
482
- Application: 'database',
483
- },
484
- });
485
-
486
- // Standard SSD for cost-optimized workloads
487
- rutter.addAzureDiskStorageClass({
488
- name: 'azure-standard-ssd',
489
- skuName: 'StandardSSD_LRS',
490
- fsType: 'ext4',
491
- cachingMode: 'ReadOnly',
492
- });
493
-
494
- // Ultra SSD for high-performance workloads
495
- rutter.addAzureDiskStorageClass({
496
- name: 'azure-ultra-ssd',
497
- skuName: 'UltraSSD_LRS',
498
- fsType: 'ext4',
499
- cachingMode: 'None',
500
- diskIOPSReadWrite: 2000,
501
- diskMBpsReadWrite: 200,
502
- logicalSectorSize: 4096,
503
- });
504
- ```
505
-
506
- #### Azure Application Gateway Ingress Controller (AGIC)
507
-
508
- Comprehensive AGIC support for AKS deployments with advanced features:
509
-
510
- ```typescript
511
- // AGIC Ingress with SSL and health checks
512
- rutter.addAzureAGICIngress({
513
- name: 'app-ingress',
514
- rules: [
515
- {
516
- host: 'app.example.com',
517
- paths: [
518
- {
519
- path: '/',
520
- pathType: 'Prefix',
521
- backend: { service: { name: 'app-service', port: { number: 80 } } },
522
- },
523
- ],
524
- },
525
- ],
526
- sslRedirect: true,
527
- backendProtocol: 'https',
528
- healthProbePath: '/health',
529
- healthProbeInterval: 30,
530
- cookieBasedAffinity: true,
531
- requestTimeout: 60,
532
- appgwSslCertificate: 'my-ssl-cert',
533
- wafPolicyForPath:
534
- '/subscriptions/sub-id/resourceGroups/rg/providers/Microsoft.Network/applicationGatewayWebApplicationFirewallPolicies/waf-policy',
535
- });
536
-
537
- // Advanced AGIC features
538
- rutter.addAzureAGICIngress({
539
- name: 'advanced-ingress',
540
- rules: [
541
- /* rules */
542
- ],
543
- backendPathPrefix: '/api/v1',
544
- backendHostname: 'internal.example.com',
545
- usePrivateIp: true,
546
- overrideFrontendPort: 8080,
547
- connectionDraining: true,
548
- connectionDrainingTimeout: 60,
549
- hostnameExtension: ['api.example.com', 'admin.example.com'],
550
- appgwTrustedRootCertificate: ['root-cert-1', 'root-cert-2'],
551
- rewriteRuleSet: 'custom-rewrite-rules',
552
- rulePriority: 100,
553
- });
554
- ```
555
-
556
- ## Network Security with NetworkPolicies
557
-
558
- Timonel provides comprehensive NetworkPolicy helpers for implementing Zero Trust network security
559
- in Kubernetes:
560
-
561
- ### Zero Trust Network Security
562
-
563
- Implement defense-in-depth with deny-by-default policies:
564
-
565
- ```typescript
566
- // 1. Deny all traffic by default (recommended starting point)
567
- rutter.addDenyAllNetworkPolicy('default-deny-all');
568
-
569
- // 2. Allow specific traffic as needed
570
- rutter.addAllowFromPodsNetworkPolicy({
571
- name: 'allow-frontend-to-backend',
572
- targetPodSelector: { app: 'backend' },
573
- sourcePodSelector: { app: 'frontend' },
574
- ports: [{ protocol: 'TCP', port: 8080 }],
575
- });
576
- ```
577
-
578
- ### Advanced NetworkPolicy Examples
579
-
580
- #### Multi-tier Application Security
581
-
582
- ```typescript
583
- // Web tier - allow external traffic on port 80/443
584
- rutter.addNetworkPolicy({
585
- name: 'web-tier-policy',
586
- podSelector: { matchLabels: { tier: 'web' } },
587
- policyTypes: ['Ingress', 'Egress'],
588
- ingress: [
589
- {
590
- ports: [
591
- { protocol: 'TCP', port: 80 },
592
- { protocol: 'TCP', port: 443 },
593
- ],
594
- },
595
- ],
596
- egress: [
597
- // Allow access to app tier
598
- {
599
- to: [{ podSelector: { matchLabels: { tier: 'app' } } }],
600
- ports: [{ protocol: 'TCP', port: 8080 }],
601
- },
602
- // Allow DNS resolution
603
- {
604
- to: [{ namespaceSelector: { matchLabels: { name: 'kube-system' } } }],
605
- ports: [
606
- { protocol: 'UDP', port: 53 },
607
- { protocol: 'TCP', port: 53 },
608
- ],
609
- },
610
- ],
611
- });
612
-
613
- // App tier - only allow traffic from web tier
614
- rutter.addNetworkPolicy({
615
- name: 'app-tier-policy',
616
- podSelector: { matchLabels: { tier: 'app' } },
617
- policyTypes: ['Ingress', 'Egress'],
618
- ingress: [
619
- {
620
- from: [{ podSelector: { matchLabels: { tier: 'web' } } }],
621
- ports: [{ protocol: 'TCP', port: 8080 }],
622
- },
623
- ],
624
- egress: [
625
- // Allow access to database
626
- {
627
- to: [{ podSelector: { matchLabels: { tier: 'database' } } }],
628
- ports: [{ protocol: 'TCP', port: 5432 }],
629
- },
630
- // Allow external API calls (with CIDR restrictions)
631
- {
632
- to: [
633
- {
634
- ipBlock: {
635
- cidr: '0.0.0.0/0',
636
- except: ['10.0.0.0/8', '172.16.0.0/12', '192.168.0.0/16'],
637
- },
638
- },
639
- ],
640
- ports: [{ protocol: 'TCP', port: 443 }],
641
- },
642
- ],
643
- });
644
-
645
- // Database tier - most restrictive
646
- rutter.addNetworkPolicy({
647
- name: 'database-tier-policy',
648
- podSelector: { matchLabels: { tier: 'database' } },
649
- policyTypes: ['Ingress', 'Egress'],
650
- ingress: [
651
- {
652
- from: [{ podSelector: { matchLabels: { tier: 'app' } } }],
653
- ports: [{ protocol: 'TCP', port: 5432 }],
654
- },
655
- ],
656
- egress: [
657
- // Only allow DNS resolution
658
- {
659
- to: [{ namespaceSelector: { matchLabels: { name: 'kube-system' } } }],
660
- ports: [
661
- { protocol: 'UDP', port: 53 },
662
- { protocol: 'TCP', port: 53 },
663
- ],
664
- },
665
- ],
666
- });
667
- ```
668
-
669
- #### Cross-Namespace Communication
670
-
671
- ```typescript
672
- // Allow traffic from monitoring namespace
673
- rutter.addAllowFromNamespaceNetworkPolicy({
674
- name: 'allow-monitoring',
675
- targetPodSelector: { app: 'backend' },
676
- sourceNamespaceSelector: { name: 'monitoring' },
677
- ports: [{ protocol: 'TCP', port: 9090 }], // Prometheus metrics
678
- });
679
-
680
- // Allow traffic to shared services namespace
681
- rutter.addNetworkPolicy({
682
- name: 'allow-to-shared-services',
683
- podSelector: { matchLabels: { app: 'backend' } },
684
- policyTypes: ['Egress'],
685
- egress: [
686
- {
687
- to: [
688
- {
689
- namespaceSelector: { matchLabels: { name: 'shared-services' } },
690
- podSelector: { matchLabels: { app: 'redis' } },
691
- },
692
- ],
693
- ports: [{ protocol: 'TCP', port: 6379 }],
694
- },
695
- ],
696
- });
697
- ```
698
-
699
- ### Security Best Practices
700
-
701
- #### 1. Start with Deny-All Policies
702
-
703
- ```typescript
704
- // Always start with deny-all for maximum security
705
- rutter.addDenyAllNetworkPolicy('default-deny-all');
706
-
707
- // Then add specific allow rules
708
- rutter.addAllowFromPodsNetworkPolicy({
709
- name: 'allow-specific-communication',
710
- targetPodSelector: { app: 'api' },
711
- sourcePodSelector: { app: 'frontend' },
712
- ports: [{ protocol: 'TCP', port: 8080 }],
713
- });
714
- ```
715
-
716
- #### 2. Separate Ingress and Egress Policies
717
-
718
- ```typescript
719
- // Separate policies for better maintainability
720
- rutter.addDenyAllIngressNetworkPolicy('deny-all-ingress');
721
- rutter.addDenyAllEgressNetworkPolicy('deny-all-egress');
722
- ```
723
-
724
- #### 3. Use CIDR Blocks for External Access
725
-
726
- ```typescript
727
- // Restrict external access to specific IP ranges
728
- rutter.addNetworkPolicy({
729
- name: 'external-api-access',
730
- podSelector: { matchLabels: { app: 'backend' } },
731
- policyTypes: ['Egress'],
732
- egress: [
733
- {
734
- to: [
735
- {
736
- ipBlock: {
737
- cidr: '203.0.113.0/24', // Specific external service
738
- },
739
- },
740
- ],
741
- ports: [{ protocol: 'TCP', port: 443 }],
742
- },
743
- ],
744
- });
745
- ```
746
-
747
- #### 4. Include DNS Resolution
748
-
749
- ```typescript
750
- // Always allow DNS for name resolution
751
- const dnsEgressRule = {
752
- to: [{ namespaceSelector: { matchLabels: { name: 'kube-system' } } }],
753
- ports: [
754
- { protocol: 'UDP', port: 53 },
755
- { protocol: 'TCP', port: 53 },
756
- ],
757
- };
758
-
759
- rutter.addNetworkPolicy({
760
- name: 'app-with-dns',
761
- podSelector: { matchLabels: { app: 'backend' } },
762
- policyTypes: ['Egress'],
763
- egress: [dnsEgressRule /* other rules */],
764
- });
765
- ```
766
-
767
- ### Basic NetworkPolicy
768
-
769
- ```typescript
770
- // Custom NetworkPolicy with full control
771
- rutter.addNetworkPolicy({
772
- name: 'custom-policy',
773
- podSelector: { matchLabels: { app: 'backend' } },
774
- policyTypes: ['Ingress', 'Egress'],
775
- ingress: [
776
- {
777
- from: [{ podSelector: { matchLabels: { app: 'frontend' } } }],
778
- ports: [{ protocol: 'TCP', port: 8080 }],
779
- },
780
- ],
781
- egress: [
782
- {
783
- to: [{ podSelector: { matchLabels: { app: 'database' } } }],
784
- ports: [{ protocol: 'TCP', port: 5432 }],
785
- },
786
- ],
787
- });
788
- ```
789
-
790
- ## Multi-environment values
791
-
792
- Provide `envValues` in the `Rutter` constructor to automatically create
793
- `values-<env>.yaml` files. Each environment file overrides defaults from
794
- `values.yaml`.
795
-
796
- ## Security
797
-
798
- - ESLint security plugin with comprehensive vulnerability detection
799
- - Automated dependency scanning via Dependabot
800
- - Security audit in CI/CD pipeline
801
- - Provenance-enabled npm publishing
802
- - CodeQL analysis for code security
803
-
804
- ## Notes on cdk8s and Helm templates
805
-
806
- - cdk8s synthesizes Kubernetes manifests. Timonel wraps them into a Helm chart
807
- structure and allows Helm placeholders to appear in string fields (e.g.,
808
- `{{ .Values.image.tag }}`).
809
- - For advanced templating, Timonel can generate `_helpers.tpl`. Provide `helpersTpl`
810
- in `Rutter` as a string (verbatim) or as named helpers. Use `template()` or `include()`
811
- to reference them in your manifests.
812
-
813
- ## Roadmap
814
-
815
- - ✅ Auto-scaling helpers (HPA, VPA, PodDisruptionBudget)
816
- - ✅ AWS multi-cloud support (EBS, EFS, ALB, IRSA, Secrets Manager, Parameter Store)
817
- - ✅ Custom manifest naming and file organization
818
- - ✅ Azure multi-cloud support (Azure Disk StorageClass, AGIC)
819
- - ✅ Job and CronJob helpers for batch workloads
820
- - GCP multi-cloud support (GKE-specific helpers)
821
- - Richer CLI (resource generators, diff)
822
- - Template validation and testing utilities
823
-
824
- ## Contributing
825
-
826
- 1. Fork the repository
827
- 2. Create a feature branch: `git checkout -b feature/amazing-feature`
828
- 3. Make your changes following the existing code style
829
- 4. Run tests: `pnpm ci:check`
830
- 5. Update CHANGELOG.md following [Keep a Changelog](https://keepachangelog.com/) format
831
- 6. Commit using conventional commits: `git commit -m 'feat: add amazing feature'`
832
- 7. Push to the branch: `git push origin feature/amazing-feature`
833
- 8. Open a Pull Request using the provided template
834
-
835
- ## Troubleshooting
836
-
837
- ### Common Issues
838
-
839
- #### Error: chart.ts not found
840
-
841
- - Ensure you're running `tl synth` from the correct directory
842
- - Verify the chart.ts file exists in the specified path
843
-
844
- #### TypeScript compilation errors
845
-
846
- - Check Node.js version (requires 20+)
847
- - Run `pnpm install` to ensure dependencies are installed
848
- - Verify TypeScript configuration in tsconfig.json
849
-
850
- #### Helm template errors
85
+ ## 🤝 Contributing
851
86
 
852
- - Validate YAML syntax in generated templates
853
- - Check Helm values references match your values.yaml structure
854
- - Use `helm template --debug` for detailed error information
87
+ See our [Contributing Guide](https://github.com/KenkoGeek/timonel/wiki/Contributing) for development
88
+ setup and guidelines.
855
89
 
856
- ## License
90
+ ## 📄 License
857
91
 
858
92
  MIT
859
93
 
860
- <!-- Badges section -->
94
+ <!-- Badges -->
861
95
 
862
96
  [license-badge]: https://img.shields.io/badge/License-MIT-yellow.svg
863
97
  [license-url]: https://opensource.org/licenses/MIT