timonel 2.9.2 β 2.10.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/CHANGELOG.md +36 -0
- package/README.md +159 -18
- package/SECURITY.md +53 -7
- package/dist/cli.js +14 -4
- package/dist/index.d.ts +4 -2
- package/dist/index.js +3 -2
- package/dist/lib/helmChartWriter.js +5 -5
- package/dist/lib/rutter.js +10 -10
- package/dist/lib/templates/flexible-subchart.d.ts +27 -0
- package/dist/lib/templates/flexible-subchart.js +107 -0
- package/dist/lib/templates/umbrella-chart.d.ts +1 -0
- package/dist/lib/templates/umbrella-chart.js +120 -10
- package/dist/lib/types.d.ts +8 -1
- package/package.json +12 -12
package/CHANGELOG.md
CHANGED
|
@@ -1,3 +1,39 @@
|
|
|
1
|
+
# [2.10.0](https://github.com/KenkoGeek/timonel/compare/v2.9.2...v2.10.0) (2025-09-20)
|
|
2
|
+
|
|
3
|
+
### Bug Fixes
|
|
4
|
+
|
|
5
|
+
- **ci:** and beside or ([2901953](https://github.com/KenkoGeek/timonel/commit/2901953363ff81c03ad95e57fbf61129bffe4138))
|
|
6
|
+
- **ci:** change CodeQL build-mode to 'none' for JavaScript/TypeScript ([017ec93](https://github.com/KenkoGeek/timonel/commit/017ec930940780fca9e6f93e02372067f899675f))
|
|
7
|
+
- **ci:** clean up workflows and fix CodeQL configuration ([4c3ac55](https://github.com/KenkoGeek/timonel/commit/4c3ac55e04210d77ad694aef1fab261482a7f5e9))
|
|
8
|
+
- **ci:** correct CodeQL workflow configuration ([25813d3](https://github.com/KenkoGeek/timonel/commit/25813d3b4ce649da5fa3b1cf29f825369c17b196))
|
|
9
|
+
- **ci:** correct CodeQL workflow name in release.yaml ([cb38608](https://github.com/KenkoGeek/timonel/commit/cb3860881b527f5016dcdc891f848c22ea464868))
|
|
10
|
+
- **ci:** correct job dependencies and summary references ([d37cc9c](https://github.com/KenkoGeek/timonel/commit/d37cc9ccf05407f28b85bd7eeb5710b2460b72ef))
|
|
11
|
+
- **ci:** ensure real release on main branch ([c06a5f7](https://github.com/KenkoGeek/timonel/commit/c06a5f7f9d0d45261c95e677f04382e0e20de58d))
|
|
12
|
+
- **ci:** lint errors ([08fbb64](https://github.com/KenkoGeek/timonel/commit/08fbb645b3661a2bc4e6bf33b309ab88cd707fef))
|
|
13
|
+
- **ci:** remove explicit pnpm version from CodeQL workflow ([25a8a6c](https://github.com/KenkoGeek/timonel/commit/25a8a6cd9556ae614bb84bfcc147aadb17850f48))
|
|
14
|
+
- **ci:** remove explicit pnpm version from workflows ([b517e1e](https://github.com/KenkoGeek/timonel/commit/b517e1eb35b3ab57673428c7d80fa25d427bf046))
|
|
15
|
+
- **ci:** reorder pnpm setup before Node.js in CodeQL workflow ([904579c](https://github.com/KenkoGeek/timonel/commit/904579ca507ef2cad5f11887e35431e6a15a59f5))
|
|
16
|
+
- **ci:** resolve pnpm version conflict in workflows ([a2ee153](https://github.com/KenkoGeek/timonel/commit/a2ee153934c5710e58f8e5bd85da6ea70e1c8959))
|
|
17
|
+
- **ci:** simple but effective release ([a6b2014](https://github.com/KenkoGeek/timonel/commit/a6b201476903cedf8e1d1dd7bbf36c2f02fa750b))
|
|
18
|
+
- **ci:** simple but effective release, security.md updated ([6911d21](https://github.com/KenkoGeek/timonel/commit/6911d2131971787d8afce1123ed4969e0ae8e077))
|
|
19
|
+
- **ci:** use exact pnpm version 10.15.0 in workflows ([2634e7d](https://github.com/KenkoGeek/timonel/commit/2634e7d30b58dcea182605a52a1e34daca0cf6bb))
|
|
20
|
+
- **core:** correct TypeScript errors and improve version handling ([3945d8b](https://github.com/KenkoGeek/timonel/commit/3945d8b6e3f84141579e0a08b48bdfd480e64168))
|
|
21
|
+
- **core:** resolve issue [#114](https://github.com/KenkoGeek/timonel/issues/114) - invalid Helm template generation ([eac0bdb](https://github.com/KenkoGeek/timonel/commit/eac0bdbbe4946e0dcf29346b956451f4d1f4a016))
|
|
22
|
+
- **docs:** apply prettier formatting to README.md ([0ad15aa](https://github.com/KenkoGeek/timonel/commit/0ad15aa8add475268b6b7c9af9bdcd3b6a82bb80))
|
|
23
|
+
- **release:** align required checks with ruleset configuration ([1b4d1dd](https://github.com/KenkoGeek/timonel/commit/1b4d1dd245974f80d3fb00096d48dbaaa79419f1))
|
|
24
|
+
- **release:** update required checks in release workflow ([1811247](https://github.com/KenkoGeek/timonel/commit/1811247fa1562885b8bd43909bd2127e23de225d))
|
|
25
|
+
- resolve issue [#114](https://github.com/KenkoGeek/timonel/issues/114) - Helm template generation bug and enhance documentation ([#116](https://github.com/KenkoGeek/timonel/issues/116)) ([92782f8](https://github.com/KenkoGeek/timonel/commit/92782f840571e036cc235d1b7739b00d8ac8d56c))
|
|
26
|
+
- **umbrella:** remove unused \_subchartInstance variables ([73b3a8a](https://github.com/KenkoGeek/timonel/commit/73b3a8a99b30ef4576f60331f66b30164bd8213e))
|
|
27
|
+
|
|
28
|
+
### Features
|
|
29
|
+
|
|
30
|
+
- **ci:** optimize GitHub workflows with enhanced performance and reliability ([09d0470](https://github.com/KenkoGeek/timonel/commit/09d04700b011e8dc4ae3875c4a46d835b88bb13d)), closes [#114](https://github.com/KenkoGeek/timonel/issues/114)
|
|
31
|
+
- **core:** enhance ChartProps for better flexibility ([385f966](https://github.com/KenkoGeek/timonel/commit/385f96607c27a1dd58ff8e4ceb60d8a56ece8422))
|
|
32
|
+
|
|
33
|
+
### Reverts
|
|
34
|
+
|
|
35
|
+
- **ci:** restore original release workflow ([f2f9b27](https://github.com/KenkoGeek/timonel/commit/f2f9b27e1950e8c9496f0faf6b874c0be5ad02e9))
|
|
36
|
+
|
|
1
37
|
## [2.9.2](https://github.com/KenkoGeek/timonel/compare/v2.9.1...v2.9.2) (2025-09-19)
|
|
2
38
|
|
|
3
39
|
### Bug Fixes
|
package/README.md
CHANGED
|
@@ -10,39 +10,141 @@
|
|
|
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
|
|
14
|
-
using cdk8s. Define Kubernetes resources with classes and synthesize
|
|
15
|
-
`Chart.yaml`, `values.yaml`,
|
|
13
|
+
**Timonel** (Spanish for "helmsman") is a powerful TypeScript library that programmatically generates
|
|
14
|
+
Helm charts using cdk8s. Define Kubernetes resources with type-safe classes and synthesize complete
|
|
15
|
+
Helm charts with `Chart.yaml`, `values.yaml`, environment-specific values files, and `templates/`
|
|
16
|
+
directory.
|
|
17
|
+
|
|
18
|
+
> π **New in v2.9.2**: Enhanced umbrella chart support with flexible subchart templates, improved
|
|
19
|
+
> CLI version handling, and optimized GitHub workflows.
|
|
16
20
|
|
|
17
21
|
## β¨ Key Features
|
|
18
22
|
|
|
19
|
-
-
|
|
20
|
-
-
|
|
21
|
-
-
|
|
22
|
-
-
|
|
23
|
-
-
|
|
24
|
-
- **AWS**: EBS/EFS StorageClass, ALB Ingress, IRSA ServiceAccount
|
|
25
|
-
- **
|
|
26
|
-
- **
|
|
23
|
+
- **π Type-safe API** with strict TypeScript and cdk8s constructs
|
|
24
|
+
- **π§ Flexible resource creation** with built-in methods and `addManifest()` for custom resources
|
|
25
|
+
- **π Multi-environment support** with automatic values files generation
|
|
26
|
+
- **βοΈ Umbrella Charts** for managing multiple subcharts as a single unit
|
|
27
|
+
- **βοΈ Cloud integrations**:
|
|
28
|
+
- **AWS**: EBS/EFS StorageClass, ALB Ingress, IRSA ServiceAccount
|
|
29
|
+
- **Azure**: Azure Disk, Azure Files, AKS integrations
|
|
30
|
+
- **GCP**: GCE Persistent Disk, GKE integrations
|
|
31
|
+
- **π‘οΈ Security-first approach** with NetworkPolicies and best practices
|
|
32
|
+
- **β‘ Minimal CLI** (`tl`) for scaffolding and chart generation
|
|
33
|
+
- **π¦ Flexible subchart templates** supporting cdk8s, cdk8s-plus-33, and raw manifests
|
|
27
34
|
|
|
28
35
|
## π Quick Start
|
|
29
36
|
|
|
37
|
+
### Installation
|
|
38
|
+
|
|
30
39
|
```bash
|
|
31
40
|
# Install Timonel globally
|
|
32
41
|
npm install -g timonel
|
|
33
42
|
|
|
43
|
+
# Or use with pnpm
|
|
44
|
+
pnpm add -g timonel
|
|
45
|
+
|
|
46
|
+
# Verify installation
|
|
47
|
+
tl --version
|
|
48
|
+
```
|
|
49
|
+
|
|
50
|
+
### Basic Usage
|
|
51
|
+
|
|
52
|
+
```bash
|
|
34
53
|
# Create your first chart
|
|
35
54
|
tl init my-app
|
|
36
55
|
|
|
37
56
|
# Generate Helm chart
|
|
38
|
-
tl synth
|
|
57
|
+
tl synth my-app my-app-dist
|
|
39
58
|
|
|
40
59
|
# Use with Helm
|
|
41
|
-
helm install my-app
|
|
60
|
+
helm install my-app my-app-dist
|
|
61
|
+
```
|
|
62
|
+
|
|
63
|
+
### Umbrella Charts
|
|
64
|
+
|
|
65
|
+
```bash
|
|
66
|
+
# Create umbrella chart structure
|
|
67
|
+
tl umbrella init my-umbrella-app
|
|
68
|
+
|
|
69
|
+
# Add subcharts
|
|
70
|
+
tl umbrella add frontend
|
|
71
|
+
tl umbrella add backend
|
|
72
|
+
|
|
73
|
+
# Generate umbrella chart
|
|
74
|
+
tl umbrella synth
|
|
75
|
+
```
|
|
76
|
+
|
|
77
|
+
## π‘ Examples
|
|
78
|
+
|
|
79
|
+
### Simple Web Application
|
|
80
|
+
|
|
81
|
+
```typescript
|
|
82
|
+
import { Chart } from 'cdk8s';
|
|
83
|
+
import { Deployment, Service } from 'cdk8s-plus-33';
|
|
84
|
+
|
|
85
|
+
export class WebAppChart extends Chart {
|
|
86
|
+
constructor(scope: Chart, id: string) {
|
|
87
|
+
super(scope, id);
|
|
88
|
+
|
|
89
|
+
// Create deployment
|
|
90
|
+
new Deployment(this, 'web-deployment', {
|
|
91
|
+
containers: [
|
|
92
|
+
{
|
|
93
|
+
image: 'nginx:latest',
|
|
94
|
+
port: 80,
|
|
95
|
+
env: {
|
|
96
|
+
NGINX_PORT: '80',
|
|
97
|
+
},
|
|
98
|
+
},
|
|
99
|
+
],
|
|
100
|
+
});
|
|
101
|
+
|
|
102
|
+
// Create service
|
|
103
|
+
new Service(this, 'web-service', {
|
|
104
|
+
selector: { app: 'web' },
|
|
105
|
+
ports: [{ port: 80, targetPort: 80 }],
|
|
106
|
+
});
|
|
107
|
+
}
|
|
108
|
+
}
|
|
109
|
+
```
|
|
110
|
+
|
|
111
|
+
### Umbrella Chart with Multiple Services
|
|
112
|
+
|
|
113
|
+
```typescript
|
|
114
|
+
import { UmbrellaChartTemplate } from 'timonel';
|
|
115
|
+
|
|
116
|
+
const umbrellaConfig = {
|
|
117
|
+
name: 'my-umbrella-app',
|
|
118
|
+
version: '1.0.0',
|
|
119
|
+
subcharts: [
|
|
120
|
+
{
|
|
121
|
+
name: 'frontend',
|
|
122
|
+
version: '1.0.0',
|
|
123
|
+
chart: frontendChartFunction,
|
|
124
|
+
},
|
|
125
|
+
{
|
|
126
|
+
name: 'backend',
|
|
127
|
+
version: '1.0.0',
|
|
128
|
+
chart: backendChartFunction,
|
|
129
|
+
},
|
|
130
|
+
],
|
|
131
|
+
};
|
|
132
|
+
|
|
133
|
+
export const umbrella = new UmbrellaChartTemplate(umbrellaConfig);
|
|
42
134
|
```
|
|
43
135
|
|
|
44
136
|
## π Documentation
|
|
45
137
|
|
|
138
|
+
- **[API Reference](https://github.com/KenkoGeek/timonel/wiki/API-Reference)** - Complete API
|
|
139
|
+
documentation
|
|
140
|
+
- **[CLI Reference](https://github.com/KenkoGeek/timonel/wiki/CLI-Reference)** - Command-line
|
|
141
|
+
interface guide
|
|
142
|
+
- **[Examples](https://github.com/KenkoGeek/timonel/wiki/Examples)** - Real-world usage examples
|
|
143
|
+
- **[Best Practices](https://github.com/KenkoGeek/timonel/wiki/Best-Practices)** - Recommended
|
|
144
|
+
patterns and practices
|
|
145
|
+
- **[Contributing](https://github.com/KenkoGeek/timonel/wiki/Contributing)** - Development setup
|
|
146
|
+
and guidelines
|
|
147
|
+
|
|
46
148
|
## π§ Troubleshooting
|
|
47
149
|
|
|
48
150
|
### CDK8s Module Not Found Error
|
|
@@ -59,13 +161,13 @@ If you get `Error: Cannot find module 'cdk8s'` when running `tl umbrella synth`:
|
|
|
59
161
|
"version": "1.0.0",
|
|
60
162
|
"type": "module",
|
|
61
163
|
"dependencies": {
|
|
62
|
-
"cdk8s": "^2.70.
|
|
63
|
-
"cdk8s-plus-33": "^2.3.
|
|
164
|
+
"cdk8s": "^2.70.15",
|
|
165
|
+
"cdk8s-plus-33": "^2.3.6",
|
|
64
166
|
"constructs": "^10.4.2",
|
|
65
|
-
"timonel": "^2.9.
|
|
167
|
+
"timonel": "^2.9.2"
|
|
66
168
|
},
|
|
67
169
|
"devDependencies": {
|
|
68
|
-
"@types/node": "^24.
|
|
170
|
+
"@types/node": "^24.5.2",
|
|
69
171
|
"typescript": "^5.9.2"
|
|
70
172
|
}
|
|
71
173
|
}
|
|
@@ -78,6 +180,45 @@ npm install
|
|
|
78
180
|
tl umbrella synth # Now it works!
|
|
79
181
|
```
|
|
80
182
|
|
|
183
|
+
### Version Display Issues
|
|
184
|
+
|
|
185
|
+
If the CLI shows an incorrect version:
|
|
186
|
+
|
|
187
|
+
**Problem**: The CLI might be using cached or hardcoded version information.
|
|
188
|
+
|
|
189
|
+
**Solution**: Rebuild the project:
|
|
190
|
+
|
|
191
|
+
```bash
|
|
192
|
+
# In the Timonel project directory
|
|
193
|
+
pnpm build
|
|
194
|
+
tl --version # Should show correct version
|
|
195
|
+
```
|
|
196
|
+
|
|
197
|
+
### TypeScript Compilation Errors
|
|
198
|
+
|
|
199
|
+
If you encounter TypeScript errors when using umbrella charts:
|
|
200
|
+
|
|
201
|
+
**Problem**: Type mismatches in subchart configurations.
|
|
202
|
+
|
|
203
|
+
**Solution**: Ensure proper type casting for version and description fields:
|
|
204
|
+
|
|
205
|
+
```typescript
|
|
206
|
+
// β
Correct
|
|
207
|
+
const subchart = {
|
|
208
|
+
name: 'my-service',
|
|
209
|
+
version: '1.0.0' as string,
|
|
210
|
+
description: 'My service' as string,
|
|
211
|
+
chart: myChartFunction,
|
|
212
|
+
};
|
|
213
|
+
|
|
214
|
+
// β Incorrect
|
|
215
|
+
const subchart = {
|
|
216
|
+
name: 'my-service',
|
|
217
|
+
version: someUnknownValue, // This will cause TypeScript errors
|
|
218
|
+
chart: myChartFunction,
|
|
219
|
+
};
|
|
220
|
+
```
|
|
221
|
+
|
|
81
222
|
## π€ Contributing
|
|
82
223
|
|
|
83
224
|
See our [Contributing Guide](https://github.com/KenkoGeek/timonel/wiki/Contributing) for development
|
|
@@ -104,6 +245,6 @@ MIT
|
|
|
104
245
|
[maintained-badge]: https://img.shields.io/badge/maintained%20by-KenkoGeek-6C78AF?style=flat
|
|
105
246
|
[maintained-url]: https://github.com/kenkogeek/
|
|
106
247
|
[ci-badge]: https://github.com/KenkoGeek/timonel/actions/workflows/test.yaml/badge.svg?branch=main
|
|
107
|
-
[ci-url]: https://github.com/KenkoGeek/timonel/actions/workflows/
|
|
248
|
+
[ci-url]: https://github.com/KenkoGeek/timonel/actions/workflows/test.yaml
|
|
108
249
|
[codeql-badge]: https://github.com/KenkoGeek/timonel/actions/workflows/codeql.yaml/badge.svg
|
|
109
250
|
[codeql-url]: https://github.com/KenkoGeek/timonel/actions/workflows/codeql.yaml
|
package/SECURITY.md
CHANGED
|
@@ -14,24 +14,40 @@
|
|
|
14
14
|
- Steps to reproduce
|
|
15
15
|
- Potential impact assessment
|
|
16
16
|
- Suggested mitigation (if any)
|
|
17
|
+
- Affected versions
|
|
17
18
|
|
|
18
19
|
**Response timeline:**
|
|
19
20
|
|
|
20
21
|
- Initial response: 48 hours
|
|
21
22
|
- Triage completion: 5 business days
|
|
22
23
|
- Status updates: Every 10 business days
|
|
24
|
+
- Fix timeline: Depends on severity (Critical: 72h, High: 1 week, Medium: 2 weeks)
|
|
25
|
+
|
|
26
|
+
**Severity levels:**
|
|
27
|
+
|
|
28
|
+
- **Critical**: Remote code execution, privilege escalation, data breach
|
|
29
|
+
- **High**: Authentication bypass, significant data exposure
|
|
30
|
+
- **Medium**: Information disclosure, denial of service
|
|
31
|
+
- **Low**: Minor information leakage, cosmetic issues
|
|
23
32
|
|
|
24
33
|
## Supported Versions
|
|
25
34
|
|
|
26
35
|
We provide security updates for the following versions:
|
|
27
36
|
|
|
28
|
-
| Version | Supported |
|
|
29
|
-
| ------- | -------------- |
|
|
30
|
-
| 2.4.0+ | β
Current |
|
|
31
|
-
| 2.3.x | β
Supported |
|
|
32
|
-
| 2.0-2.2 | β οΈ Limited | Critical
|
|
33
|
-
| 1.x.x | β End of life |
|
|
34
|
-
| < 1.0 | β End of life |
|
|
37
|
+
| Version | Supported | Security Updates | End of Life |
|
|
38
|
+
| ------- | -------------- | ---------------- | ----------- |
|
|
39
|
+
| 2.4.0+ | β
Current | Full support | TBD |
|
|
40
|
+
| 2.3.x | β
Supported | Full support | TBD |
|
|
41
|
+
| 2.0-2.2 | β οΈ Limited | Critical only | 2024-12-31 |
|
|
42
|
+
| 1.x.x | β End of life | None | 2024-06-30 |
|
|
43
|
+
| < 1.0 | β End of life | None | 2024-01-01 |
|
|
44
|
+
|
|
45
|
+
**Update policy:**
|
|
46
|
+
|
|
47
|
+
- **Current versions**: All security updates within 48 hours
|
|
48
|
+
- **Supported versions**: Critical updates within 1 week
|
|
49
|
+
- **Limited versions**: Critical updates only, within 2 weeks
|
|
50
|
+
- **End of life**: No updates provided
|
|
35
51
|
|
|
36
52
|
## Development Security
|
|
37
53
|
|
|
@@ -57,6 +73,10 @@ We provide security updates for the following versions:
|
|
|
57
73
|
- **Multi-layer scanning**: ESLint security plugin + CodeQL + pnpm audit
|
|
58
74
|
- **Branch protection**: Required status checks and reviews
|
|
59
75
|
- **Secrets management**: No hardcoded credentials
|
|
76
|
+
- **Native dependencies**: Uses `workflow_run` for secure pipeline dependencies
|
|
77
|
+
- **Environment protection**: Production releases require manual approval
|
|
78
|
+
- **Automated security**: Security scans run on every PR and push
|
|
79
|
+
- **Dependency provenance**: NPM_CONFIG_PROVENANCE enabled for package integrity
|
|
60
80
|
|
|
61
81
|
### Security Features
|
|
62
82
|
|
|
@@ -77,3 +97,29 @@ We provide security updates for the following versions:
|
|
|
77
97
|
- **Values files**: Avoid hardcoded secrets in values
|
|
78
98
|
- **Network policies**: Use provided NetworkPolicy helpers
|
|
79
99
|
- **RBAC**: Apply principle of least privilege in Kubernetes
|
|
100
|
+
|
|
101
|
+
## Security Best Practices
|
|
102
|
+
|
|
103
|
+
### For Developers
|
|
104
|
+
|
|
105
|
+
- **Keep dependencies updated**: Run `pnpm audit` regularly
|
|
106
|
+
- **Review PRs carefully**: Check for security implications
|
|
107
|
+
- **Use security tools**: Enable IDE security plugins
|
|
108
|
+
- **Follow secure coding**: Avoid dangerous patterns (eval, innerHTML, etc.)
|
|
109
|
+
- **Test security features**: Verify input validation and sanitization
|
|
110
|
+
|
|
111
|
+
### For Users
|
|
112
|
+
|
|
113
|
+
- **Update regularly**: Always use the latest stable version
|
|
114
|
+
- **Review configurations**: Check generated Helm charts before deployment
|
|
115
|
+
- **Use secrets management**: Never hardcode credentials
|
|
116
|
+
- **Monitor deployments**: Watch for unusual behavior
|
|
117
|
+
- **Apply patches**: Install security updates promptly
|
|
118
|
+
|
|
119
|
+
## Security Tools Integration
|
|
120
|
+
|
|
121
|
+
- **GitHub Dependabot**: Automated dependency updates
|
|
122
|
+
- **CodeQL**: Static analysis for security vulnerabilities
|
|
123
|
+
- **ESLint Security**: Runtime security checks
|
|
124
|
+
- **pnpm audit**: Dependency vulnerability scanning
|
|
125
|
+
- **Semantic Release**: Automated versioning with security considerations
|
package/dist/cli.js
CHANGED
|
@@ -8,6 +8,16 @@ const __filename = fileURLToPath(import.meta.url);
|
|
|
8
8
|
const __dirname = path.dirname(__filename);
|
|
9
9
|
const UMBRELLA_CONFIG_FILE = 'umbrella.config.json';
|
|
10
10
|
const UMBRELLA_FILE_NAME = 'umbrella.ts';
|
|
11
|
+
function getVersion() {
|
|
12
|
+
try {
|
|
13
|
+
const packagePath = path.join(__dirname, '..', 'package.json');
|
|
14
|
+
const packageJson = JSON.parse(fs.readFileSync(packagePath, 'utf8'));
|
|
15
|
+
return packageJson.version || '0.1.0';
|
|
16
|
+
}
|
|
17
|
+
catch {
|
|
18
|
+
return '0.1.0';
|
|
19
|
+
}
|
|
20
|
+
}
|
|
11
21
|
function log(msg, silent = false) {
|
|
12
22
|
if (!silent) {
|
|
13
23
|
console.log(msg);
|
|
@@ -214,7 +224,7 @@ async function cmdUmbrellaInit(name, silent = false) {
|
|
|
214
224
|
fs.writeFileSync(umbrellaFile, generateUmbrellaChart(validName));
|
|
215
225
|
const config = {
|
|
216
226
|
name: validName,
|
|
217
|
-
version:
|
|
227
|
+
version: getVersion(),
|
|
218
228
|
description: `${validName} umbrella chart`,
|
|
219
229
|
subcharts: [],
|
|
220
230
|
};
|
|
@@ -315,7 +325,7 @@ async function cmdUmbrellaAdd(subchartPath, silent = false) {
|
|
|
315
325
|
fs.writeFileSync(chartFile, subchartContent);
|
|
316
326
|
config.subcharts.push({
|
|
317
327
|
name: subchartName,
|
|
318
|
-
version:
|
|
328
|
+
version: getVersion(),
|
|
319
329
|
path: `./charts/${validSubchartPath}/chart.ts`,
|
|
320
330
|
});
|
|
321
331
|
fs.writeFileSync(configFile, JSON.stringify(config, null, 2));
|
|
@@ -397,7 +407,7 @@ function parseFlags(args) {
|
|
|
397
407
|
case '--version':
|
|
398
408
|
case '-v':
|
|
399
409
|
if (!flags.silent) {
|
|
400
|
-
console.log(
|
|
410
|
+
console.log(`Timonel v${getVersion()}`);
|
|
401
411
|
}
|
|
402
412
|
process.exit(0);
|
|
403
413
|
break;
|
|
@@ -448,7 +458,7 @@ async function main() {
|
|
|
448
458
|
}
|
|
449
459
|
if (args.includes('--version') || args.includes('-v')) {
|
|
450
460
|
if (!isSilent) {
|
|
451
|
-
console.log(
|
|
461
|
+
console.log(`Timonel v${getVersion()}`);
|
|
452
462
|
}
|
|
453
463
|
process.exit(0);
|
|
454
464
|
}
|
package/dist/index.d.ts
CHANGED
|
@@ -3,9 +3,11 @@ export * from './lib/helmChartWriter.js';
|
|
|
3
3
|
export * from './lib/rutter.js';
|
|
4
4
|
export * from './lib/security.js';
|
|
5
5
|
export * from './lib/umbrella.js';
|
|
6
|
-
export { UmbrellaChartTemplate as UmbrellaChart } from './lib/templates/umbrella-chart.js';
|
|
7
|
-
export { Subchart } from './lib/templates/subchart.js';
|
|
8
6
|
export { BasicChart } from './lib/templates/basic-chart.js';
|
|
7
|
+
export { FlexibleSubchart, createFlexibleSubchart } from './lib/templates/flexible-subchart.js';
|
|
8
|
+
export { Subchart } from './lib/templates/subchart.js';
|
|
9
|
+
export { UmbrellaChartTemplate as UmbrellaChart } from './lib/templates/umbrella-chart.js';
|
|
10
|
+
export type { ChartProps, SubchartProps } from './lib/types.js';
|
|
9
11
|
export type { AWSALBIngressSpec, AWSEBSStorageClassSpec, AWSEFSStorageClassSpec, AWSIRSAServiceAccountSpec, } from './lib/resources/cloud/aws/awsResources.js';
|
|
10
12
|
export type { KarpenterDisruption, KarpenterDisruptionBudget, KarpenterEC2NodeClassSpec, KarpenterNodeClaimSpec, KarpenterNodePoolSpec, } from './lib/resources/cloud/aws/karpenterResources.js';
|
|
11
13
|
export { DEFAULT_TERMINATION_GRACE_PERIOD, isValidDisruptionBudget, isValidKubernetesDuration, KarpenterVersionUtils, } from './lib/resources/cloud/aws/karpenterResources.js';
|
package/dist/index.js
CHANGED
|
@@ -3,8 +3,9 @@ export * from './lib/helmChartWriter.js';
|
|
|
3
3
|
export * from './lib/rutter.js';
|
|
4
4
|
export * from './lib/security.js';
|
|
5
5
|
export * from './lib/umbrella.js';
|
|
6
|
-
export { UmbrellaChartTemplate as UmbrellaChart } from './lib/templates/umbrella-chart.js';
|
|
7
|
-
export { Subchart } from './lib/templates/subchart.js';
|
|
8
6
|
export { BasicChart } from './lib/templates/basic-chart.js';
|
|
7
|
+
export { FlexibleSubchart, createFlexibleSubchart } from './lib/templates/flexible-subchart.js';
|
|
8
|
+
export { Subchart } from './lib/templates/subchart.js';
|
|
9
|
+
export { UmbrellaChartTemplate as UmbrellaChart } from './lib/templates/umbrella-chart.js';
|
|
9
10
|
export { DEFAULT_TERMINATION_GRACE_PERIOD, isValidDisruptionBudget, isValidKubernetesDuration, KarpenterVersionUtils, } from './lib/resources/cloud/aws/karpenterResources.js';
|
|
10
11
|
export { AWS_HELPERS, createHelper, FILE_ACCESS_HELPERS, formatHelpers, generateHelpersTemplate, getDefaultHelpers, getHelpersByCategory, KUBERNETES_HELPERS, SPRIG_HELPERS, STANDARD_HELPERS, TEMPLATE_FUNCTION_HELPERS, } from './lib/utils/helmHelpers.js';
|
|
@@ -5,7 +5,7 @@ import { dumpHelmAwareYaml } from './utils/helmYamlSerializer.js';
|
|
|
5
5
|
export class HelmChartWriter {
|
|
6
6
|
static write(opts) {
|
|
7
7
|
const { outDir, meta, defaultValues = {}, envValues = {}, assets, helpersTpl, notesTpl, valuesSchema, } = opts;
|
|
8
|
-
console.log(
|
|
8
|
+
console.log(`Writing chart: ${meta.name} v${meta.version} to ${outDir}`);
|
|
9
9
|
const validatedOutDir = SecurityUtils.validatePath(outDir, process.cwd());
|
|
10
10
|
this.createDirectories(validatedOutDir);
|
|
11
11
|
this.writeChartYaml(validatedOutDir, meta);
|
|
@@ -15,7 +15,7 @@ export class HelmChartWriter {
|
|
|
15
15
|
this.writeNotes(validatedOutDir, notesTpl);
|
|
16
16
|
this.writeSchema(validatedOutDir, valuesSchema);
|
|
17
17
|
this.writeHelmIgnore(validatedOutDir);
|
|
18
|
-
console.log(
|
|
18
|
+
console.log(`Chart written successfully to ${validatedOutDir}`);
|
|
19
19
|
}
|
|
20
20
|
static createDirectories(outDir) {
|
|
21
21
|
fs.mkdirSync(path.join(outDir, 'templates'), { recursive: true });
|
|
@@ -111,7 +111,7 @@ function writeAssets(outDir, assets) {
|
|
|
111
111
|
for (const asset of assets) {
|
|
112
112
|
const sanitizedId = asset.id.replace(/[^a-zA-Z0-9-_]/g, '');
|
|
113
113
|
if (sanitizedId !== asset.id) {
|
|
114
|
-
console.error(
|
|
114
|
+
console.error(`Invalid asset ID detected: ${SecurityUtils.sanitizeLogMessage(asset.id)}`);
|
|
115
115
|
throw new Error(`Invalid asset ID: ${SecurityUtils.sanitizeLogMessage(asset.id)}`);
|
|
116
116
|
}
|
|
117
117
|
const targetDir = getTargetDirectory(asset.target);
|
|
@@ -124,7 +124,7 @@ function writeAssets(outDir, assets) {
|
|
|
124
124
|
}
|
|
125
125
|
}
|
|
126
126
|
catch (error) {
|
|
127
|
-
console.error(
|
|
127
|
+
console.error(`Failed to write asset ${asset.id}:`, error);
|
|
128
128
|
throw error;
|
|
129
129
|
}
|
|
130
130
|
}
|
|
@@ -134,7 +134,7 @@ function getTargetDirectory(target) {
|
|
|
134
134
|
}
|
|
135
135
|
function writeSingleAssetFile(outDir, targetDir, assetId, yaml) {
|
|
136
136
|
if (assetId === 'ingress' && yaml.includes('number:')) {
|
|
137
|
-
console.log('
|
|
137
|
+
console.log('Writing ingress file with number fields');
|
|
138
138
|
const numberLines = yaml.split('\n').filter((line) => line.includes('number:'));
|
|
139
139
|
console.log('Number lines:', numberLines);
|
|
140
140
|
}
|
package/dist/lib/rutter.js
CHANGED
|
@@ -2,14 +2,14 @@ import { ApiObject, App, Chart, Testing } from 'cdk8s';
|
|
|
2
2
|
import * as jsYaml from 'js-yaml';
|
|
3
3
|
import { include } from './helm.js';
|
|
4
4
|
import { HelmChartWriter } from './helmChartWriter.js';
|
|
5
|
-
import { dumpHelmAwareYaml } from './utils/helmYamlSerializer.js';
|
|
6
5
|
import { AWSResources } from './resources/cloud/aws/awsResources.js';
|
|
7
6
|
import { KarpenterResources } from './resources/cloud/aws/karpenterResources.js';
|
|
7
|
+
import { dumpHelmAwareYaml } from './utils/helmYamlSerializer.js';
|
|
8
8
|
import { generateHelpersTemplate } from './utils/helmHelpers.js';
|
|
9
9
|
export class Rutter {
|
|
10
10
|
constructor(props) {
|
|
11
11
|
this.assets = [];
|
|
12
|
-
console.log(
|
|
12
|
+
console.log(`Initializing chart: ${props.meta.name} v${props.meta.version}`);
|
|
13
13
|
this.defaultValues = props.defaultValues ?? {};
|
|
14
14
|
this.envValues = props.envValues ?? {};
|
|
15
15
|
this.meta = props.meta;
|
|
@@ -134,24 +134,24 @@ ${yamlContent.trim()}
|
|
|
134
134
|
}
|
|
135
135
|
validateManifestStructure(manifest) {
|
|
136
136
|
if (!manifest.apiVersion) {
|
|
137
|
-
console.error('
|
|
137
|
+
console.error('Validation failed: Missing apiVersion');
|
|
138
138
|
throw new Error('Manifest must have an apiVersion');
|
|
139
139
|
}
|
|
140
140
|
if (!manifest.kind) {
|
|
141
|
-
console.error('
|
|
141
|
+
console.error('Validation failed: Missing kind');
|
|
142
142
|
throw new Error('Manifest must have a kind');
|
|
143
143
|
}
|
|
144
144
|
if (!manifest.metadata) {
|
|
145
|
-
console.error('
|
|
145
|
+
console.error('Validation failed: Missing metadata');
|
|
146
146
|
throw new Error('Manifest must have metadata');
|
|
147
147
|
}
|
|
148
148
|
const metadata = manifest.metadata;
|
|
149
149
|
if (!metadata.name) {
|
|
150
|
-
console.error('
|
|
150
|
+
console.error('Validation failed: Missing metadata.name');
|
|
151
151
|
throw new Error('Manifest metadata must have a name');
|
|
152
152
|
}
|
|
153
153
|
if (typeof metadata.name !== 'string') {
|
|
154
|
-
console.error('
|
|
154
|
+
console.error('Validation failed: metadata.name must be a string');
|
|
155
155
|
throw new Error('Manifest metadata.name must be a string');
|
|
156
156
|
}
|
|
157
157
|
}
|
|
@@ -193,7 +193,7 @@ ${yamlContent.trim()}
|
|
|
193
193
|
const labels = o.metadata.labels;
|
|
194
194
|
const defaults = {
|
|
195
195
|
'helm.sh/chart': `{{ .Chart.Name }}-{{ .Chart.Version }}`,
|
|
196
|
-
'app.kubernetes.io/name':
|
|
196
|
+
'app.kubernetes.io/name': include(Rutter.HELPER_NAME),
|
|
197
197
|
'app.kubernetes.io/instance': '{{ .Release.Name }}',
|
|
198
198
|
'app.kubernetes.io/version': '{{ .Chart.Version }}',
|
|
199
199
|
'app.kubernetes.io/managed-by': '{{ .Release.Service }}',
|
|
@@ -399,7 +399,7 @@ ${yamlContent.trim()}
|
|
|
399
399
|
return processed;
|
|
400
400
|
}
|
|
401
401
|
write(outDir) {
|
|
402
|
-
console.log(
|
|
402
|
+
console.log(`Writing chart '${this.meta.name}' to: ${outDir}`);
|
|
403
403
|
let helpersContent;
|
|
404
404
|
if (this.props.helpersTpl) {
|
|
405
405
|
if (typeof this.props.helpersTpl === 'string') {
|
|
@@ -429,7 +429,7 @@ ${helper.template}
|
|
|
429
429
|
assets: synthAssets,
|
|
430
430
|
helpersTpl: helpersContent,
|
|
431
431
|
});
|
|
432
|
-
console.log(
|
|
432
|
+
console.log(`Chart '${this.meta.name}' written successfully`);
|
|
433
433
|
}
|
|
434
434
|
}
|
|
435
435
|
Rutter.HELPER_NAME = 'chart.name';
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import { Chart } from 'cdk8s';
|
|
2
|
+
export declare class FlexibleSubchart extends Chart {
|
|
3
|
+
private readonly config;
|
|
4
|
+
private _constructs;
|
|
5
|
+
private _manifests;
|
|
6
|
+
constructor(scope: Chart, id: string, config: {
|
|
7
|
+
name: string;
|
|
8
|
+
version?: string;
|
|
9
|
+
description?: string;
|
|
10
|
+
construct?: unknown;
|
|
11
|
+
manifest?: unknown;
|
|
12
|
+
[key: string]: unknown;
|
|
13
|
+
});
|
|
14
|
+
addConstruct(construct: unknown, id?: string): void;
|
|
15
|
+
addManifest(manifest: unknown, id?: string): void;
|
|
16
|
+
private configure;
|
|
17
|
+
writeHelmChart(outputDir: string): void;
|
|
18
|
+
private _generateManifestTemplate;
|
|
19
|
+
getConstructs(): unknown[];
|
|
20
|
+
getManifests(): unknown[];
|
|
21
|
+
}
|
|
22
|
+
export declare function createFlexibleSubchart(scope: Chart, id: string, config: {
|
|
23
|
+
name: string;
|
|
24
|
+
version?: string;
|
|
25
|
+
description?: string;
|
|
26
|
+
[key: string]: unknown;
|
|
27
|
+
}): FlexibleSubchart;
|
|
@@ -0,0 +1,107 @@
|
|
|
1
|
+
import { writeFileSync, mkdirSync, existsSync } from 'fs';
|
|
2
|
+
import { join } from 'path';
|
|
3
|
+
import { Chart } from 'cdk8s';
|
|
4
|
+
import { dumpHelmAwareYaml } from '../utils/helmYamlSerializer.js';
|
|
5
|
+
import { generateHelpersTemplate } from '../utils/helmHelpers.js';
|
|
6
|
+
export class FlexibleSubchart extends Chart {
|
|
7
|
+
constructor(scope, id, config) {
|
|
8
|
+
super(scope, id);
|
|
9
|
+
this.config = config;
|
|
10
|
+
this._constructs = [];
|
|
11
|
+
this._manifests = [];
|
|
12
|
+
this.configure();
|
|
13
|
+
}
|
|
14
|
+
addConstruct(construct, id) {
|
|
15
|
+
if (construct) {
|
|
16
|
+
this._constructs.push({ construct, id: id || `construct-${this._constructs.length}` });
|
|
17
|
+
}
|
|
18
|
+
}
|
|
19
|
+
addManifest(manifest, id) {
|
|
20
|
+
if (manifest) {
|
|
21
|
+
this._manifests.push({ manifest, id: id || `manifest-${this._manifests.length}` });
|
|
22
|
+
}
|
|
23
|
+
}
|
|
24
|
+
configure() {
|
|
25
|
+
if (this.config.construct) {
|
|
26
|
+
this.addConstruct(this.config.construct);
|
|
27
|
+
}
|
|
28
|
+
if (this.config.manifest) {
|
|
29
|
+
this.addManifest(this.config.manifest);
|
|
30
|
+
}
|
|
31
|
+
Object.entries(this.config).forEach(([key, value]) => {
|
|
32
|
+
if (key !== 'name' &&
|
|
33
|
+
key !== 'version' &&
|
|
34
|
+
key !== 'description' &&
|
|
35
|
+
key !== 'construct' &&
|
|
36
|
+
key !== 'manifest' &&
|
|
37
|
+
value) {
|
|
38
|
+
this.addConstruct(value, key);
|
|
39
|
+
}
|
|
40
|
+
});
|
|
41
|
+
}
|
|
42
|
+
writeHelmChart(outputDir) {
|
|
43
|
+
if (!existsSync(outputDir)) {
|
|
44
|
+
mkdirSync(outputDir, { recursive: true });
|
|
45
|
+
}
|
|
46
|
+
const subchartYaml = {
|
|
47
|
+
apiVersion: 'v2',
|
|
48
|
+
name: this.config.name,
|
|
49
|
+
description: this.config.description || `${this.config.name} subchart`,
|
|
50
|
+
type: 'application',
|
|
51
|
+
version: this.config.version || '1.0.0',
|
|
52
|
+
appVersion: this.config.version || '1.0.0',
|
|
53
|
+
};
|
|
54
|
+
writeFileSync(join(outputDir, 'Chart.yaml'), dumpHelmAwareYaml(subchartYaml));
|
|
55
|
+
const subchartValues = {
|
|
56
|
+
enabled: true,
|
|
57
|
+
...Object.fromEntries(Object.entries(this.config).filter(([key, value]) => key !== 'chart' && typeof value !== 'function' && value !== null && value !== undefined)),
|
|
58
|
+
};
|
|
59
|
+
writeFileSync(join(outputDir, 'values.yaml'), dumpHelmAwareYaml(subchartValues));
|
|
60
|
+
const templatesDir = join(outputDir, 'templates');
|
|
61
|
+
if (!existsSync(templatesDir)) {
|
|
62
|
+
mkdirSync(templatesDir, { recursive: true });
|
|
63
|
+
}
|
|
64
|
+
const helpersTpl = generateHelpersTemplate('aws', undefined, {
|
|
65
|
+
includeKubernetes: true,
|
|
66
|
+
includeSprig: true,
|
|
67
|
+
});
|
|
68
|
+
writeFileSync(join(templatesDir, '_helpers.tpl'), helpersTpl);
|
|
69
|
+
this._manifests.forEach((item) => {
|
|
70
|
+
if (item && typeof item === 'object' && 'manifest' in item && 'id' in item) {
|
|
71
|
+
const { manifest, id } = item;
|
|
72
|
+
if (manifest && typeof manifest === 'object') {
|
|
73
|
+
const templateContent = this._generateManifestTemplate(manifest, id);
|
|
74
|
+
writeFileSync(join(templatesDir, `${id}.yaml`), templateContent);
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
});
|
|
78
|
+
console.log(`Created flexible Helm chart for subchart: ${this.config.name}`);
|
|
79
|
+
}
|
|
80
|
+
_generateManifestTemplate(manifest, id) {
|
|
81
|
+
if (typeof manifest !== 'object' || manifest === null) {
|
|
82
|
+
return dumpHelmAwareYaml({});
|
|
83
|
+
}
|
|
84
|
+
const manifestObj = manifest;
|
|
85
|
+
const template = {
|
|
86
|
+
apiVersion: manifestObj.apiVersion || 'v1',
|
|
87
|
+
kind: manifestObj.kind || 'Manifest',
|
|
88
|
+
metadata: {
|
|
89
|
+
name: `{{ include "${id}.fullname" . }}`,
|
|
90
|
+
labels: `{{ include "${id}.labels" . }}`,
|
|
91
|
+
...(manifestObj.metadata || {}),
|
|
92
|
+
},
|
|
93
|
+
spec: manifestObj.spec || {},
|
|
94
|
+
...manifestObj,
|
|
95
|
+
};
|
|
96
|
+
return dumpHelmAwareYaml(template);
|
|
97
|
+
}
|
|
98
|
+
getConstructs() {
|
|
99
|
+
return this._constructs;
|
|
100
|
+
}
|
|
101
|
+
getManifests() {
|
|
102
|
+
return this._manifests;
|
|
103
|
+
}
|
|
104
|
+
}
|
|
105
|
+
export function createFlexibleSubchart(scope, id, config) {
|
|
106
|
+
return new FlexibleSubchart(scope, id, config);
|
|
107
|
+
}
|
|
@@ -3,6 +3,7 @@ import { join } from 'path';
|
|
|
3
3
|
import { Chart, ApiObject } from 'cdk8s';
|
|
4
4
|
import { dumpHelmAwareYaml } from '../utils/helmYamlSerializer.js';
|
|
5
5
|
import { generateHelpersTemplate } from '../utils/helmHelpers.js';
|
|
6
|
+
import { createFlexibleSubchart } from './flexible-subchart.js';
|
|
6
7
|
export function generateUmbrellaChart(name) {
|
|
7
8
|
return `import { App } from 'cdk8s';
|
|
8
9
|
import { UmbrellaChart } from 'timonel';
|
|
@@ -92,7 +93,87 @@ export class UmbrellaChartTemplate extends Chart {
|
|
|
92
93
|
},
|
|
93
94
|
});
|
|
94
95
|
}
|
|
95
|
-
_addSubchart(
|
|
96
|
+
_addSubchart(subchart, index) {
|
|
97
|
+
try {
|
|
98
|
+
let _subchartInstance;
|
|
99
|
+
const { name: _name, version: _version, description: _description, ...subchartProps } = subchart;
|
|
100
|
+
const flexibleSubchart = createFlexibleSubchart(this, `${subchart.name}-${index}`, {
|
|
101
|
+
name: subchart.name,
|
|
102
|
+
version: subchart.version || '1.0.0',
|
|
103
|
+
description: subchart.description || `${subchart.name} subchart`,
|
|
104
|
+
...subchartProps,
|
|
105
|
+
});
|
|
106
|
+
if (typeof subchart.chart === 'function') {
|
|
107
|
+
try {
|
|
108
|
+
const subchartInstance = subchart.chart(this, `${subchart.name}-${index}`);
|
|
109
|
+
if (subchartInstance.node.children) {
|
|
110
|
+
subchartInstance.node.children.forEach((child) => {
|
|
111
|
+
if (child instanceof Chart) {
|
|
112
|
+
flexibleSubchart.addConstruct(child);
|
|
113
|
+
}
|
|
114
|
+
});
|
|
115
|
+
}
|
|
116
|
+
}
|
|
117
|
+
catch {
|
|
118
|
+
const subchartInstance = subchart.chart();
|
|
119
|
+
if (subchartInstance.node.children) {
|
|
120
|
+
subchartInstance.node.children.forEach((child) => {
|
|
121
|
+
if (child instanceof Chart) {
|
|
122
|
+
flexibleSubchart.addConstruct(child);
|
|
123
|
+
}
|
|
124
|
+
});
|
|
125
|
+
}
|
|
126
|
+
}
|
|
127
|
+
}
|
|
128
|
+
else if (subchart.chart && typeof subchart.chart === 'object') {
|
|
129
|
+
if (subchart.chart.constructor && subchart.chart.constructor.name !== 'Object') {
|
|
130
|
+
flexibleSubchart.addConstruct(subchart.chart);
|
|
131
|
+
}
|
|
132
|
+
else {
|
|
133
|
+
flexibleSubchart.addManifest(subchart.chart);
|
|
134
|
+
}
|
|
135
|
+
}
|
|
136
|
+
console.log(`Added flexible subchart: ${subchart.name}`);
|
|
137
|
+
}
|
|
138
|
+
catch (_error) {
|
|
139
|
+
console.warn(`Failed to add subchart ${subchart.name}:`, _error);
|
|
140
|
+
const _fallbackSubchart = createFlexibleSubchart(this, `${subchart.name}-fallback-${index}`, {
|
|
141
|
+
name: subchart.name,
|
|
142
|
+
version: subchart.version || '1.0.0',
|
|
143
|
+
description: `${subchart.name} subchart (fallback)`,
|
|
144
|
+
});
|
|
145
|
+
console.log(`Created fallback subchart: ${subchart.name}`);
|
|
146
|
+
}
|
|
147
|
+
}
|
|
148
|
+
_createBasicSubchart(subchartName, subchartDir) {
|
|
149
|
+
const subchartYaml = {
|
|
150
|
+
apiVersion: 'v2',
|
|
151
|
+
name: subchartName,
|
|
152
|
+
description: `${subchartName} subchart`,
|
|
153
|
+
type: 'application',
|
|
154
|
+
version: '1.0.0',
|
|
155
|
+
appVersion: '1.0.0',
|
|
156
|
+
};
|
|
157
|
+
writeFileSync(join(subchartDir, 'Chart.yaml'), dumpHelmAwareYaml(subchartYaml));
|
|
158
|
+
const subchartValues = {
|
|
159
|
+
enabled: true,
|
|
160
|
+
replicas: 1,
|
|
161
|
+
image: {
|
|
162
|
+
repository: 'nginx',
|
|
163
|
+
tag: 'latest',
|
|
164
|
+
},
|
|
165
|
+
};
|
|
166
|
+
writeFileSync(join(subchartDir, 'values.yaml'), dumpHelmAwareYaml(subchartValues));
|
|
167
|
+
const templatesDir = join(subchartDir, 'templates');
|
|
168
|
+
if (!existsSync(templatesDir)) {
|
|
169
|
+
mkdirSync(templatesDir, { recursive: true });
|
|
170
|
+
}
|
|
171
|
+
const helpersTpl = generateHelpersTemplate('aws', undefined, {
|
|
172
|
+
includeKubernetes: true,
|
|
173
|
+
includeSprig: true,
|
|
174
|
+
});
|
|
175
|
+
writeFileSync(join(templatesDir, '_helpers.tpl'), helpersTpl);
|
|
176
|
+
console.log(`Created basic Helm chart structure for subchart: ${subchartName}`);
|
|
96
177
|
}
|
|
97
178
|
writeHelmChart(outputDir) {
|
|
98
179
|
if (!existsSync(outputDir)) {
|
|
@@ -133,21 +214,50 @@ export class UmbrellaChartTemplate extends Chart {
|
|
|
133
214
|
if (!existsSync(subchartDir)) {
|
|
134
215
|
mkdirSync(subchartDir, { recursive: true });
|
|
135
216
|
}
|
|
136
|
-
|
|
217
|
+
const { name: _name, version: _version, description: _description, ...subchartProps } = subchart;
|
|
218
|
+
const flexibleSubchart = createFlexibleSubchart(this, `${subchart.name}-chart`, {
|
|
219
|
+
name: subchart.name,
|
|
220
|
+
version: subchart.version || '1.0.0',
|
|
221
|
+
description: subchart.description || `${subchart.name} subchart`,
|
|
222
|
+
...subchartProps,
|
|
223
|
+
});
|
|
137
224
|
if (typeof subchart.chart === 'function') {
|
|
138
225
|
try {
|
|
139
|
-
|
|
226
|
+
const chartInstance = subchart.chart(this, `${subchart.name}-chart`);
|
|
227
|
+
if (chartInstance && typeof chartInstance.writeHelmChart === 'function') {
|
|
228
|
+
chartInstance.writeHelmChart(subchartDir);
|
|
229
|
+
}
|
|
230
|
+
else {
|
|
231
|
+
flexibleSubchart.writeHelmChart(subchartDir);
|
|
232
|
+
}
|
|
140
233
|
}
|
|
141
|
-
catch
|
|
142
|
-
|
|
143
|
-
|
|
234
|
+
catch {
|
|
235
|
+
try {
|
|
236
|
+
const chartInstance = subchart.chart();
|
|
237
|
+
if (chartInstance && typeof chartInstance.writeHelmChart === 'function') {
|
|
238
|
+
chartInstance.writeHelmChart(subchartDir);
|
|
239
|
+
}
|
|
240
|
+
else {
|
|
241
|
+
flexibleSubchart.writeHelmChart(subchartDir);
|
|
242
|
+
}
|
|
243
|
+
}
|
|
244
|
+
catch (fallbackError) {
|
|
245
|
+
console.warn(`Failed to create subchart ${subchart.name}:`, fallbackError);
|
|
246
|
+
flexibleSubchart.writeHelmChart(subchartDir);
|
|
247
|
+
}
|
|
144
248
|
}
|
|
145
249
|
}
|
|
146
|
-
else {
|
|
147
|
-
|
|
250
|
+
else if (subchart.chart && typeof subchart.chart === 'object') {
|
|
251
|
+
if (subchart.chart.constructor && subchart.chart.constructor.name !== 'Object') {
|
|
252
|
+
flexibleSubchart.addConstruct(subchart.chart);
|
|
253
|
+
}
|
|
254
|
+
else {
|
|
255
|
+
flexibleSubchart.addManifest(subchart.chart);
|
|
256
|
+
}
|
|
257
|
+
flexibleSubchart.writeHelmChart(subchartDir);
|
|
148
258
|
}
|
|
149
|
-
|
|
150
|
-
|
|
259
|
+
else {
|
|
260
|
+
flexibleSubchart.writeHelmChart(subchartDir);
|
|
151
261
|
}
|
|
152
262
|
});
|
|
153
263
|
const templatesDir = join(outputDir, 'templates');
|
package/dist/lib/types.d.ts
CHANGED
|
@@ -3,6 +3,9 @@ export interface ChartProps {
|
|
|
3
3
|
name: string;
|
|
4
4
|
version: string;
|
|
5
5
|
description: string;
|
|
6
|
+
namespace?: string;
|
|
7
|
+
labels?: Record<string, string>;
|
|
8
|
+
annotations?: Record<string, string>;
|
|
6
9
|
services?: Array<{
|
|
7
10
|
name: string;
|
|
8
11
|
port: number;
|
|
@@ -10,8 +13,12 @@ export interface ChartProps {
|
|
|
10
13
|
}>;
|
|
11
14
|
subcharts?: Array<{
|
|
12
15
|
name: string;
|
|
13
|
-
chart: Chart | (() => Chart);
|
|
16
|
+
chart: Chart | ((scope: Chart, id: string) => Chart) | unknown;
|
|
17
|
+
version?: string;
|
|
18
|
+
enabled?: boolean;
|
|
19
|
+
[key: string]: unknown;
|
|
14
20
|
}>;
|
|
21
|
+
[key: string]: unknown;
|
|
15
22
|
}
|
|
16
23
|
export interface SubchartProps {
|
|
17
24
|
name: string;
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "timonel",
|
|
3
3
|
"type": "module",
|
|
4
|
-
"version": "2.
|
|
4
|
+
"version": "2.10.0",
|
|
5
5
|
"description": "Timonel: programmatic Helm chart generator using cdk8s (TypeScript)",
|
|
6
6
|
"bin": {
|
|
7
7
|
"timonel": "dist/cli.js",
|
|
@@ -81,29 +81,29 @@
|
|
|
81
81
|
]
|
|
82
82
|
},
|
|
83
83
|
"dependencies": {
|
|
84
|
-
"cdk8s": "^2.70.
|
|
85
|
-
"cdk8s-plus-33": "^2.3.
|
|
84
|
+
"cdk8s": "^2.70.15",
|
|
85
|
+
"cdk8s-plus-33": "^2.3.6",
|
|
86
86
|
"constructs": "^10.4.2",
|
|
87
87
|
"handlebars": "^4.7.8",
|
|
88
88
|
"js-yaml": "^4.1.0",
|
|
89
|
-
"timonel": "^2.9.
|
|
89
|
+
"timonel": "^2.9.2",
|
|
90
90
|
"ts-node": "^10.9.2",
|
|
91
91
|
"yaml": "^2.8.1"
|
|
92
92
|
},
|
|
93
93
|
"devDependencies": {
|
|
94
94
|
"@commitlint/cli": "^19.8.1",
|
|
95
95
|
"@commitlint/config-conventional": "^19.8.1",
|
|
96
|
-
"@eslint/js": "^9.
|
|
96
|
+
"@eslint/js": "^9.36.0",
|
|
97
97
|
"@semantic-release/changelog": "^6.0.3",
|
|
98
98
|
"@semantic-release/exec": "^7.1.0",
|
|
99
99
|
"@semantic-release/git": "^10.0.1",
|
|
100
100
|
"@types/js-yaml": "^4.0.9",
|
|
101
|
-
"@types/node": "^24.
|
|
102
|
-
"@typescript-eslint/eslint-plugin": "^8.
|
|
103
|
-
"@typescript-eslint/parser": "^8.
|
|
104
|
-
"@vitest/coverage-v8": "^2.
|
|
101
|
+
"@types/node": "^24.5.2",
|
|
102
|
+
"@typescript-eslint/eslint-plugin": "^8.44.0",
|
|
103
|
+
"@typescript-eslint/parser": "^8.44.0",
|
|
104
|
+
"@vitest/coverage-v8": "^3.2.4",
|
|
105
105
|
"conventional-changelog-cli": "^5.0.0",
|
|
106
|
-
"eslint": "^9.
|
|
106
|
+
"eslint": "^9.36.0",
|
|
107
107
|
"eslint-config-prettier": "^10.1.8",
|
|
108
108
|
"eslint-import-resolver-typescript": "^4.4.4",
|
|
109
109
|
"eslint-plugin-import": "^2.32.0",
|
|
@@ -115,10 +115,10 @@
|
|
|
115
115
|
"markdownlint": "^0.38.0",
|
|
116
116
|
"markdownlint-cli": "^0.45.0",
|
|
117
117
|
"prettier": "^3.6.2",
|
|
118
|
-
"semantic-release": "^24.2.
|
|
118
|
+
"semantic-release": "^24.2.9",
|
|
119
119
|
"tsx": "^4.20.5",
|
|
120
120
|
"typescript": "^5.9.2",
|
|
121
|
-
"vitest": "^2.
|
|
121
|
+
"vitest": "^3.2.4"
|
|
122
122
|
},
|
|
123
123
|
"files": [
|
|
124
124
|
"dist",
|