container-superposition 0.1.1 → 0.1.4

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.
Files changed (178) hide show
  1. package/README.md +569 -8
  2. package/dist/scripts/init.js +436 -254
  3. package/dist/scripts/init.js.map +1 -1
  4. package/dist/tool/commands/doctor.d.ts +15 -0
  5. package/dist/tool/commands/doctor.d.ts.map +1 -0
  6. package/dist/tool/commands/doctor.js +862 -0
  7. package/dist/tool/commands/doctor.js.map +1 -0
  8. package/dist/tool/commands/explain.d.ts +13 -0
  9. package/dist/tool/commands/explain.d.ts.map +1 -0
  10. package/dist/tool/commands/explain.js +299 -0
  11. package/dist/tool/commands/explain.js.map +1 -0
  12. package/dist/tool/commands/list.d.ts +16 -0
  13. package/dist/tool/commands/list.d.ts.map +1 -0
  14. package/dist/tool/commands/list.js +121 -0
  15. package/dist/tool/commands/list.js.map +1 -0
  16. package/dist/tool/commands/plan.d.ts +67 -0
  17. package/dist/tool/commands/plan.d.ts.map +1 -0
  18. package/dist/tool/commands/plan.js +851 -0
  19. package/dist/tool/commands/plan.js.map +1 -0
  20. package/dist/tool/questionnaire/composer.d.ts +16 -2
  21. package/dist/tool/questionnaire/composer.d.ts.map +1 -1
  22. package/dist/tool/questionnaire/composer.js +411 -200
  23. package/dist/tool/questionnaire/composer.js.map +1 -1
  24. package/dist/tool/readme/markdown-parser.d.ts.map +1 -1
  25. package/dist/tool/readme/markdown-parser.js.map +1 -1
  26. package/dist/tool/readme/readme-generator.d.ts.map +1 -1
  27. package/dist/tool/readme/readme-generator.js +11 -6
  28. package/dist/tool/readme/readme-generator.js.map +1 -1
  29. package/dist/tool/schema/deployment-targets.d.ts +77 -0
  30. package/dist/tool/schema/deployment-targets.d.ts.map +1 -0
  31. package/dist/tool/schema/deployment-targets.js +91 -0
  32. package/dist/tool/schema/deployment-targets.js.map +1 -0
  33. package/dist/tool/schema/manifest-migrations.d.ts +51 -0
  34. package/dist/tool/schema/manifest-migrations.d.ts.map +1 -0
  35. package/dist/tool/schema/manifest-migrations.js +159 -0
  36. package/dist/tool/schema/manifest-migrations.js.map +1 -0
  37. package/dist/tool/schema/overlay-loader.d.ts +1 -1
  38. package/dist/tool/schema/overlay-loader.d.ts.map +1 -1
  39. package/dist/tool/schema/overlay-loader.js +42 -14
  40. package/dist/tool/schema/overlay-loader.js.map +1 -1
  41. package/dist/tool/schema/types.d.ts +62 -2
  42. package/dist/tool/schema/types.d.ts.map +1 -1
  43. package/dist/tool/utils/gitignore.d.ts +15 -0
  44. package/dist/tool/utils/gitignore.d.ts.map +1 -0
  45. package/dist/tool/utils/gitignore.js +41 -0
  46. package/dist/tool/utils/gitignore.js.map +1 -0
  47. package/dist/tool/utils/merge.d.ts +134 -0
  48. package/dist/tool/utils/merge.d.ts.map +1 -0
  49. package/dist/tool/utils/merge.js +277 -0
  50. package/dist/tool/utils/merge.js.map +1 -0
  51. package/dist/tool/utils/port-utils.d.ts +29 -0
  52. package/dist/tool/utils/port-utils.d.ts.map +1 -0
  53. package/dist/tool/utils/port-utils.js +128 -0
  54. package/dist/tool/utils/port-utils.js.map +1 -0
  55. package/dist/tool/utils/services-export.d.ts +14 -0
  56. package/dist/tool/utils/services-export.d.ts.map +1 -0
  57. package/dist/tool/utils/services-export.js +478 -0
  58. package/dist/tool/utils/services-export.js.map +1 -0
  59. package/dist/tool/utils/summary.d.ts +69 -0
  60. package/dist/tool/utils/summary.d.ts.map +1 -0
  61. package/dist/tool/utils/summary.js +260 -0
  62. package/dist/tool/utils/summary.js.map +1 -0
  63. package/dist/tool/utils/version.d.ts +9 -0
  64. package/dist/tool/utils/version.d.ts.map +1 -0
  65. package/dist/tool/utils/version.js +32 -0
  66. package/dist/tool/utils/version.js.map +1 -0
  67. package/docs/architecture.md +25 -21
  68. package/docs/deployment-targets.md +150 -0
  69. package/docs/discovery-commands.md +442 -0
  70. package/docs/merge-strategy.md +700 -0
  71. package/docs/minimal-and-editor.md +265 -0
  72. package/docs/overlay-imports.md +209 -0
  73. package/docs/overlay-manifest-refactoring.md +2 -2
  74. package/docs/overlay-metadata-archive.md +1 -1
  75. package/docs/overlays.md +139 -28
  76. package/docs/presets-architecture.md +3 -3
  77. package/docs/presets.md +1 -1
  78. package/docs/publishing.md +36 -35
  79. package/docs/team-workflow.md +540 -0
  80. package/overlays/.presets/data-engineering.yml +392 -0
  81. package/overlays/.presets/event-sourced-service.yml +262 -0
  82. package/overlays/.presets/frontend.yml +287 -0
  83. package/overlays/.presets/k8s-operator-dev.yml +462 -0
  84. package/overlays/{presets → .presets}/microservice.yml +32 -6
  85. package/overlays/.presets/web-api.yml +129 -0
  86. package/overlays/.registry/README.md +1 -1
  87. package/overlays/.registry/deployment-targets.yml +54 -0
  88. package/overlays/.shared/README.md +43 -0
  89. package/overlays/.shared/compose/common-healthchecks.yml +38 -0
  90. package/overlays/.shared/otel/instrumentation.env +20 -0
  91. package/overlays/.shared/otel/otel-base-config.yaml +30 -0
  92. package/overlays/.shared/vscode/recommended-extensions.json +14 -0
  93. package/overlays/README.md +1 -1
  94. package/overlays/cloudflared/README.md +190 -0
  95. package/overlays/cloudflared/devcontainer.patch.json +3 -0
  96. package/overlays/cloudflared/overlay.yml +15 -0
  97. package/overlays/cloudflared/setup.sh +49 -0
  98. package/overlays/cloudflared/verify.sh +21 -0
  99. package/overlays/codex/overlay.yml +1 -0
  100. package/overlays/direnv/README.md +6 -4
  101. package/overlays/direnv/setup.sh +0 -12
  102. package/overlays/duckdb/README.md +274 -0
  103. package/overlays/duckdb/devcontainer.patch.json +10 -0
  104. package/overlays/duckdb/overlay.yml +17 -0
  105. package/overlays/duckdb/setup.sh +45 -0
  106. package/overlays/duckdb/verify.sh +32 -0
  107. package/overlays/git-helpers/overlay.yml +1 -0
  108. package/overlays/grafana/README.md +5 -5
  109. package/overlays/grafana/dashboard-provider.yml +1 -1
  110. package/overlays/grafana/docker-compose.yml +2 -2
  111. package/overlays/grafana/overlay.yml +6 -1
  112. package/overlays/grpc-tools/README.md +242 -0
  113. package/overlays/grpc-tools/devcontainer.patch.json +14 -0
  114. package/overlays/grpc-tools/overlay.yml +14 -0
  115. package/overlays/grpc-tools/setup.sh +57 -0
  116. package/overlays/grpc-tools/verify.sh +47 -0
  117. package/overlays/jaeger/overlay.yml +16 -3
  118. package/overlays/jupyter/.env.example +6 -0
  119. package/overlays/jupyter/README.md +210 -0
  120. package/overlays/jupyter/devcontainer.patch.json +14 -0
  121. package/overlays/jupyter/docker-compose.yml +23 -0
  122. package/overlays/jupyter/overlay.yml +18 -0
  123. package/overlays/jupyter/verify.sh +35 -0
  124. package/overlays/keycloak/.env.example +5 -0
  125. package/overlays/keycloak/README.md +238 -0
  126. package/overlays/keycloak/devcontainer.patch.json +17 -0
  127. package/overlays/keycloak/docker-compose.yml +32 -0
  128. package/overlays/keycloak/overlay.yml +23 -0
  129. package/overlays/keycloak/verify.sh +54 -0
  130. package/overlays/kind/README.md +221 -0
  131. package/overlays/kind/devcontainer.patch.json +10 -0
  132. package/overlays/kind/overlay.yml +18 -0
  133. package/overlays/kind/setup.sh +43 -0
  134. package/overlays/kind/verify.sh +40 -0
  135. package/overlays/localstack/.env.example +6 -0
  136. package/overlays/localstack/README.md +188 -0
  137. package/overlays/localstack/devcontainer.patch.json +21 -0
  138. package/overlays/localstack/docker-compose.yml +25 -0
  139. package/overlays/localstack/overlay.yml +18 -0
  140. package/overlays/localstack/verify.sh +47 -0
  141. package/overlays/loki/overlay.yml +6 -1
  142. package/overlays/mailpit/.env.example +4 -0
  143. package/overlays/mailpit/README.md +191 -0
  144. package/overlays/mailpit/devcontainer.patch.json +20 -0
  145. package/overlays/mailpit/docker-compose.yml +17 -0
  146. package/overlays/mailpit/overlay.yml +26 -0
  147. package/overlays/mailpit/verify.sh +52 -0
  148. package/overlays/modern-cli-tools/overlay.yml +1 -0
  149. package/overlays/mongodb/overlay.yml +12 -2
  150. package/overlays/mysql/overlay.yml +12 -2
  151. package/overlays/nats/overlay.yml +12 -2
  152. package/overlays/ngrok/overlay.yml +2 -1
  153. package/overlays/openapi-tools/README.md +243 -0
  154. package/overlays/openapi-tools/devcontainer.patch.json +10 -0
  155. package/overlays/openapi-tools/overlay.yml +16 -0
  156. package/overlays/openapi-tools/setup.sh +45 -0
  157. package/overlays/openapi-tools/verify.sh +51 -0
  158. package/overlays/otel-collector/overlay.yml.example +26 -0
  159. package/overlays/postgres/overlay.yml +6 -1
  160. package/overlays/prometheus/overlay.yml +6 -1
  161. package/overlays/python/README.md +51 -35
  162. package/overlays/python/devcontainer.patch.json +7 -4
  163. package/overlays/python/setup.sh +50 -23
  164. package/overlays/python/verify.sh +29 -1
  165. package/overlays/rabbitmq/overlay.yml +12 -2
  166. package/overlays/redis/overlay.yml +6 -1
  167. package/overlays/tilt/README.md +259 -0
  168. package/overlays/tilt/devcontainer.patch.json +17 -0
  169. package/overlays/tilt/overlay.yml +19 -0
  170. package/overlays/tilt/setup.sh +25 -0
  171. package/overlays/tilt/verify.sh +24 -0
  172. package/package.json +8 -6
  173. package/tool/README.md +12 -16
  174. package/tool/schema/overlay-manifest.schema.json +64 -4
  175. package/tool/schema/superposition-manifest.schema.json +104 -0
  176. package/overlays/presets/web-api.yml +0 -109
  177. /package/overlays/{presets → .presets}/docs-site.yml +0 -0
  178. /package/overlays/{presets → .presets}/fullstack.yml +0 -0
@@ -0,0 +1,462 @@
1
+ # Kubernetes Operator Development Preset
2
+ # Go-based Kubernetes operator/controller development
3
+
4
+ id: k8s-operator-dev
5
+ name: Kubernetes Operator Development
6
+ description: Go-based operator development with kubectl and Helm
7
+ type: meta
8
+ category: preset
9
+ supports: [] # Works with both plain and compose
10
+ tags: [preset, kubernetes, operator, controller, k8s, crd, go]
11
+
12
+ # Overlays to select
13
+ selects:
14
+ # Always included
15
+ required:
16
+ - go
17
+ - kubectl-helm
18
+ - modern-cli-tools
19
+
20
+ # No user choices - operators are typically Go
21
+ userChoice: {}
22
+
23
+ # Glue configuration - integration helpers
24
+ glueConfig:
25
+ # Pre-configured environment variables
26
+ environment:
27
+ # Go environment
28
+ GOOS: 'linux'
29
+ GOARCH: 'amd64'
30
+ CGO_ENABLED: '0'
31
+
32
+ # Kubernetes configuration
33
+ KUBECONFIG: '/home/vscode/.kube/config'
34
+
35
+ # Operator SDK settings
36
+ OPERATOR_NAME: 'my-operator'
37
+ OPERATOR_NAMESPACE: 'default'
38
+
39
+ # Development cluster settings (for future kind/k3d overlay)
40
+ # KIND_CLUSTER_NAME: 'operator-dev'
41
+ # K3D_CLUSTER_NAME: 'operator-dev'
42
+
43
+ # Suggested port mappings
44
+ portMappings:
45
+ operator-metrics: 8080
46
+ operator-health: 8081
47
+
48
+ # README snippet to add to generated devcontainer
49
+ readme: |
50
+ ## Kubernetes Operator Development Stack
51
+
52
+ This devcontainer is configured for Kubernetes operator development:
53
+
54
+ ### Tools
55
+
56
+ - **Go**: Operator runtime and tooling
57
+ - **kubectl**: Kubernetes CLI
58
+ - **Helm**: Package manager for Kubernetes
59
+ - **Modern CLI Tools**: jq, yq, bat for manifest inspection
60
+
61
+ ### Operator Frameworks
62
+
63
+ This environment supports multiple operator frameworks:
64
+
65
+ #### Kubebuilder (Recommended)
66
+
67
+ ```bash
68
+ # Install Kubebuilder
69
+ curl -L -o kubebuilder "https://go.kubebuilder.io/dl/latest/$(go env GOOS)/$(go env GOARCH)"
70
+ chmod +x kubebuilder
71
+ sudo mv kubebuilder /usr/local/bin/
72
+
73
+ # Initialize new operator
74
+ mkdir my-operator && cd my-operator
75
+ kubebuilder init --domain example.com --repo github.com/myorg/my-operator
76
+
77
+ # Create API/Controller
78
+ kubebuilder create api --group apps --version v1alpha1 --kind MyResource
79
+ ```
80
+
81
+ #### Operator SDK
82
+
83
+ ```bash
84
+ # Install Operator SDK
85
+ export ARCH=$(case "$(uname -m)" in
86
+ x86_64) echo -n amd64 ;;
87
+ aarch64) echo -n arm64 ;;
88
+ *) echo -n "$(uname -m)" ;;
89
+ esac)
90
+ export OS=$(uname | awk '{print tolower($0)}')
91
+ export OPERATOR_SDK_DL_URL=https://github.com/operator-framework/operator-sdk/releases/latest/download
92
+ curl -LO ${OPERATOR_SDK_DL_URL}/operator-sdk_${OS}_${ARCH}
93
+ chmod +x operator-sdk_${OS}_${ARCH}
94
+ sudo mv operator-sdk_${OS}_${ARCH} /usr/local/bin/operator-sdk
95
+
96
+ # Create new operator
97
+ mkdir my-operator && cd my-operator
98
+ operator-sdk init --domain example.com --repo github.com/myorg/my-operator
99
+
100
+ # Create API
101
+ operator-sdk create api --group apps --version v1alpha1 --kind MyResource
102
+ ```
103
+
104
+ ### Quick Start (Kubebuilder)
105
+
106
+ #### 1. Scaffold Operator
107
+
108
+ ```bash
109
+ mkdir my-operator && cd my-operator
110
+ kubebuilder init --domain example.com --repo github.com/myorg/my-operator
111
+ kubebuilder create api --group apps --version v1alpha1 --kind MyApp --resource --controller
112
+ ```
113
+
114
+ This creates:
115
+ - `api/v1alpha1/myapp_types.go` - CRD definition
116
+ - `internal/controller/myapp_controller.go` - Reconciliation logic
117
+ - `config/` - Kubernetes manifests
118
+
119
+ #### 2. Define CRD
120
+
121
+ ```go
122
+ // api/v1alpha1/myapp_types.go
123
+ type MyAppSpec struct {
124
+ // +kubebuilder:validation:Minimum=1
125
+ Replicas int32 `json:"replicas"`
126
+
127
+ // +kubebuilder:validation:Required
128
+ Image string `json:"image"`
129
+ }
130
+
131
+ type MyAppStatus struct {
132
+ // Conditions represent the latest available observations
133
+ Conditions []metav1.Condition `json:"conditions,omitempty"`
134
+
135
+ // Ready replicas
136
+ ReadyReplicas int32 `json:"readyReplicas"`
137
+ }
138
+ ```
139
+
140
+ #### 3. Implement Controller
141
+
142
+ ```go
143
+ // internal/controller/myapp_controller.go
144
+ func (r *MyAppReconciler) Reconcile(ctx context.Context, req ctrl.Request) (ctrl.Result, error) {
145
+ log := log.FromContext(ctx)
146
+
147
+ // Fetch the MyApp instance
148
+ myApp := &appsv1alpha1.MyApp{}
149
+ err := r.Get(ctx, req.NamespacedName, myApp)
150
+ if err != nil {
151
+ return ctrl.Result{}, client.IgnoreNotFound(err)
152
+ }
153
+
154
+ // Reconciliation logic
155
+ // 1. Ensure Deployment exists
156
+ // 2. Update Deployment if spec changed
157
+ // 3. Update status
158
+
159
+ log.Info("Reconciled MyApp", "name", myApp.Name)
160
+ return ctrl.Result{}, nil
161
+ }
162
+ ```
163
+
164
+ #### 4. Test Locally
165
+
166
+ ```bash
167
+ # Generate manifests
168
+ make manifests
169
+
170
+ # Run tests
171
+ make test
172
+
173
+ # Run controller locally (no cluster needed initially)
174
+ make run
175
+ ```
176
+
177
+ ### Connecting to Kubernetes Cluster
178
+
179
+ This preset includes kubectl and Helm. You can connect to:
180
+
181
+ #### Remote Cluster
182
+
183
+ ```bash
184
+ # Set up kubeconfig
185
+ export KUBECONFIG=~/.kube/config
186
+
187
+ # Or copy config from local machine
188
+ cp /path/to/kubeconfig ~/.kube/config
189
+
190
+ # Verify connection
191
+ kubectl cluster-info
192
+ kubectl get nodes
193
+ ```
194
+
195
+ #### Future: Local Cluster (kind/k3d overlay)
196
+
197
+ When kind or k3d overlay is available:
198
+
199
+ ```bash
200
+ # kind
201
+ kind create cluster --name operator-dev
202
+
203
+ # k3d
204
+ k3d cluster create operator-dev
205
+ ```
206
+
207
+ ### Development Workflow
208
+
209
+ #### 1. Install CRDs
210
+
211
+ ```bash
212
+ make install
213
+ # This creates CustomResourceDefinition in cluster
214
+ ```
215
+
216
+ #### 2. Run Operator
217
+
218
+ ```bash
219
+ # Option A: Run locally (outside cluster)
220
+ make run
221
+
222
+ # Option B: Build and deploy to cluster
223
+ make docker-build docker-push IMG=myregistry/my-operator:v0.1.0
224
+ make deploy IMG=myregistry/my-operator:v0.1.0
225
+ ```
226
+
227
+ #### 3. Create Custom Resource
228
+
229
+ ```yaml
230
+ # config/samples/apps_v1alpha1_myapp.yaml
231
+ apiVersion: apps.example.com/v1alpha1
232
+ kind: MyApp
233
+ metadata:
234
+ name: myapp-sample
235
+ spec:
236
+ replicas: 3
237
+ image: nginx:latest
238
+ ```
239
+
240
+ ```bash
241
+ kubectl apply -f config/samples/apps_v1alpha1_myapp.yaml
242
+ ```
243
+
244
+ #### 4. Watch Reconciliation
245
+
246
+ ```bash
247
+ # Watch controller logs
248
+ kubectl logs -f -n <namespace> <operator-pod>
249
+
250
+ # Watch custom resource
251
+ kubectl get myapp -w
252
+
253
+ # Describe custom resource
254
+ kubectl describe myapp myapp-sample
255
+ ```
256
+
257
+ ### Testing Operators
258
+
259
+ #### Unit Tests
260
+
261
+ ```go
262
+ // internal/controller/myapp_controller_test.go
263
+ var _ = Describe("MyApp Controller", func() {
264
+ Context("When reconciling a resource", func() {
265
+ It("Should create a Deployment", func() {
266
+ // Test reconciliation logic
267
+ })
268
+ })
269
+ })
270
+ ```
271
+
272
+ Run tests:
273
+
274
+ ```bash
275
+ make test
276
+ ```
277
+
278
+ #### Integration Tests with envtest
279
+
280
+ ```go
281
+ var k8sClient client.Client
282
+ var testEnv *envtest.Environment
283
+
284
+ BeforeSuite(func() {
285
+ testEnv = &envtest.Environment{
286
+ CRDDirectoryPaths: []string{filepath.Join("..", "config", "crd", "bases")},
287
+ }
288
+ cfg, err := testEnv.Start()
289
+ Expect(err).NotTo(HaveOccurred())
290
+
291
+ k8sClient, err = client.New(cfg, client.Options{})
292
+ Expect(err).NotTo(HaveOccurred())
293
+ })
294
+ ```
295
+
296
+ ### Helm Chart for Operator
297
+
298
+ ```bash
299
+ # Create Helm chart
300
+ mkdir -p charts/my-operator
301
+ helm create charts/my-operator
302
+
303
+ # Package chart
304
+ helm package charts/my-operator
305
+
306
+ # Install from chart
307
+ helm install my-operator charts/my-operator
308
+ ```
309
+
310
+ ### RBAC Configuration
311
+
312
+ Operators need appropriate permissions:
313
+
314
+ ```yaml
315
+ # config/rbac/role.yaml
316
+ apiVersion: rbac.authorization.k8s.io/v1
317
+ kind: ClusterRole
318
+ metadata:
319
+ name: operator-role
320
+ rules:
321
+ - apiGroups: ["apps.example.com"]
322
+ resources: ["myapps"]
323
+ verbs: ["get", "list", "watch", "create", "update", "patch", "delete"]
324
+ - apiGroups: ["apps"]
325
+ resources: ["deployments"]
326
+ verbs: ["get", "list", "watch", "create", "update", "patch", "delete"]
327
+ ```
328
+
329
+ Kubebuilder generates RBAC with markers:
330
+
331
+ ```go
332
+ // +kubebuilder:rbac:groups=apps.example.com,resources=myapps,verbs=get;list;watch;create;update;patch;delete
333
+ // +kubebuilder:rbac:groups=apps,resources=deployments,verbs=get;list;watch;create;update;patch;delete
334
+ ```
335
+
336
+ ### Operator Patterns
337
+
338
+ #### Level-Based Reconciliation
339
+
340
+ ```go
341
+ func (r *MyAppReconciler) Reconcile(ctx context.Context, req ctrl.Request) (ctrl.Result, error) {
342
+ // Get desired state
343
+ myApp := &appsv1alpha1.MyApp{}
344
+ if err := r.Get(ctx, req.NamespacedName, myApp); err != nil {
345
+ return ctrl.Result{}, client.IgnoreNotFound(err)
346
+ }
347
+
348
+ // Get current state
349
+ deployment := &appsv1.Deployment{}
350
+ err := r.Get(ctx, types.NamespacedName{
351
+ Name: myApp.Name, Namespace: myApp.Namespace,
352
+ }, deployment)
353
+
354
+ if err != nil {
355
+ // Create if not exists
356
+ return r.createDeployment(ctx, myApp)
357
+ }
358
+
359
+ // Update if different
360
+ if deployment.Spec.Replicas != &myApp.Spec.Replicas {
361
+ return r.updateDeployment(ctx, myApp, deployment)
362
+ }
363
+
364
+ return ctrl.Result{}, nil
365
+ }
366
+ ```
367
+
368
+ #### Finalizers
369
+
370
+ ```go
371
+ const myFinalizerName = "myapp.example.com/finalizer"
372
+
373
+ func (r *MyAppReconciler) Reconcile(ctx context.Context, req ctrl.Request) (ctrl.Result, error) {
374
+ myApp := &appsv1alpha1.MyApp{}
375
+ if err := r.Get(ctx, req.NamespacedName, myApp); err != nil {
376
+ return ctrl.Result{}, client.IgnoreNotFound(err)
377
+ }
378
+
379
+ // Handle deletion
380
+ if myApp.DeletionTimestamp != nil {
381
+ if controllerutil.ContainsFinalizer(myApp, myFinalizerName) {
382
+ // Cleanup logic
383
+ if err := r.cleanup(ctx, myApp); err != nil {
384
+ return ctrl.Result{}, err
385
+ }
386
+
387
+ controllerutil.RemoveFinalizer(myApp, myFinalizerName)
388
+ return ctrl.Result{}, r.Update(ctx, myApp)
389
+ }
390
+ return ctrl.Result{}, nil
391
+ }
392
+
393
+ // Add finalizer if not present
394
+ if !controllerutil.ContainsFinalizer(myApp, myFinalizerName) {
395
+ controllerutil.AddFinalizer(myApp, myFinalizerName)
396
+ return ctrl.Result{}, r.Update(ctx, myApp)
397
+ }
398
+
399
+ // Normal reconciliation
400
+ return ctrl.Result{}, nil
401
+ }
402
+ ```
403
+
404
+ ### Debugging
405
+
406
+ ```bash
407
+ # Use kubectl to inspect resources
408
+ kubectl get myapp -o yaml
409
+ kubectl describe myapp myapp-sample
410
+
411
+ # Check events
412
+ kubectl get events --sort-by='.lastTimestamp'
413
+
414
+ # Debug with delve
415
+ dlv debug ./cmd/main.go
416
+ ```
417
+
418
+ ### Modern CLI Tools for K8s
419
+
420
+ ```bash
421
+ # Inspect manifests with yq
422
+ yq eval '.spec.replicas' config/samples/myapp.yaml
423
+
424
+ # Format YAML with bat
425
+ bat config/crd/bases/apps.example.com_myapps.yaml
426
+
427
+ # Search in manifests
428
+ rg 'kind: Deployment' config/
429
+
430
+ # Find manifest files
431
+ fd -e yaml config/
432
+ ```
433
+
434
+ ### Future Enhancements
435
+
436
+ When kind/k3d and tilt/skaffold overlays are available:
437
+
438
+ #### Local Kubernetes Cluster
439
+
440
+ - Fast inner development loop
441
+ - No external cluster dependencies
442
+ - Test CRD installations locally
443
+
444
+ #### Live Reload with Tilt/Skaffold
445
+
446
+ - Automatic rebuild on code changes
447
+ - Fast feedback cycle
448
+ - Port forwarding management
449
+ - Log aggregation
450
+
451
+ ### Next Steps
452
+
453
+ - Choose operator framework (Kubebuilder or Operator SDK)
454
+ - Design your Custom Resource Definition (CRD)
455
+ - Implement reconciliation logic
456
+ - Add unit and integration tests
457
+ - Configure RBAC permissions
458
+ - Create Helm chart for distribution
459
+ - Set up CI/CD for operator builds
460
+ - Document operator usage
461
+ - Implement metrics and monitoring
462
+ - Add webhooks for validation/mutation
@@ -26,11 +26,35 @@ selects:
26
26
  options: [dotnet, nodejs, python, go, java]
27
27
  defaultOption: nodejs
28
28
 
29
- messaging:
30
- id: messaging
31
- prompt: Select message broker
32
- options: [rabbitmq, redpanda, nats]
33
- defaultOption: rabbitmq
29
+ # Parameterized slots
30
+ parameters:
31
+ broker:
32
+ description: 'Message broker'
33
+ default: rabbitmq
34
+ options:
35
+ - id: rabbitmq
36
+ overlays: [rabbitmq]
37
+ description: 'RabbitMQ AMQP message broker'
38
+ - id: nats
39
+ overlays: [nats]
40
+ description: 'NATS lightweight messaging'
41
+ - id: redpanda
42
+ overlays: [redpanda]
43
+ description: 'Redpanda Kafka-compatible streaming'
44
+ - id: none
45
+ overlays: []
46
+ description: 'No message broker'
47
+
48
+ observability:
49
+ description: 'Observability stack level'
50
+ default: standard
51
+ options:
52
+ - id: standard
53
+ overlays: []
54
+ description: 'Standard (Jaeger + Prometheus + Grafana, already included)'
55
+ - id: full
56
+ overlays: [loki]
57
+ description: 'Full stack - adds Loki for log aggregation'
34
58
 
35
59
  # Glue configuration - integration helpers
36
60
  glueConfig:
@@ -66,11 +90,12 @@ glueConfig:
66
90
 
67
91
  ### Services
68
92
 
69
- - **Message Broker**: Async communication between services
93
+ - **Message Broker**: Async communication between services (RabbitMQ/NATS/Redpanda based on your choice)
70
94
  - **OpenTelemetry Collector**: Distributed tracing collection (ports 4317, 4318)
71
95
  - **Jaeger**: Distributed tracing UI (port 16686)
72
96
  - **Prometheus**: Metrics storage (port 9090)
73
97
  - **Grafana**: Unified observability dashboard (port 3000)
98
+ - **Loki** _(full observability only)_: Log aggregation (port 3100)
74
99
 
75
100
  ### Connection Strings
76
101
 
@@ -100,6 +125,7 @@ glueConfig:
100
125
  2. Publish/subscribe to messages via your chosen broker
101
126
  3. View distributed traces in Jaeger at http://localhost:16686
102
127
  4. Monitor metrics in Grafana at http://localhost:3000
128
+ 5. _(Full observability)_ Query logs in Loki via Grafana at http://localhost:3000
103
129
 
104
130
  ### Distributed Tracing
105
131
 
@@ -0,0 +1,129 @@
1
+ # Web API Stack Preset
2
+ # Complete environment for REST/GraphQL API development
3
+
4
+ id: web-api
5
+ name: Web API Stack
6
+ description: Complete REST/GraphQL API development environment with database, cache, and observability
7
+ type: meta
8
+ category: preset
9
+ supports: [compose] # Requires Docker Compose for services
10
+ tags: [preset, api, web, backend, observability]
11
+
12
+ # Overlays to select
13
+ selects:
14
+ # Always included
15
+ required: []
16
+
17
+ # User makes choices
18
+ userChoice:
19
+ language:
20
+ id: language
21
+ prompt: Select API language/framework
22
+ options: [dotnet, nodejs, python, go, java]
23
+ defaultOption: nodejs
24
+
25
+ # Parameterized slots - users can customize these without micro-managing individual overlays
26
+ parameters:
27
+ database:
28
+ description: 'Primary data store'
29
+ default: postgres
30
+ options:
31
+ - id: postgres
32
+ overlays: [postgres]
33
+ description: 'PostgreSQL relational database'
34
+ - id: mongodb
35
+ overlays: [mongodb]
36
+ description: 'MongoDB document database'
37
+ - id: mysql
38
+ overlays: [mysql]
39
+ description: 'MySQL relational database'
40
+ - id: none
41
+ overlays: []
42
+ description: 'No database (manage separately)'
43
+
44
+ cache:
45
+ description: 'In-memory cache'
46
+ default: redis
47
+ options:
48
+ - id: redis
49
+ overlays: [redis]
50
+ description: 'Redis cache and session store'
51
+ - id: none
52
+ overlays: []
53
+ description: 'No cache'
54
+
55
+ broker:
56
+ description: 'Message broker (optional)'
57
+ default: none
58
+ options:
59
+ - id: rabbitmq
60
+ overlays: [rabbitmq]
61
+ description: 'RabbitMQ AMQP message broker'
62
+ - id: nats
63
+ overlays: [nats]
64
+ description: 'NATS lightweight messaging'
65
+ - id: redpanda
66
+ overlays: [redpanda]
67
+ description: 'Redpanda Kafka-compatible streaming'
68
+ - id: none
69
+ overlays: []
70
+ description: 'No message broker'
71
+
72
+ observability:
73
+ description: 'Monitoring and observability stack'
74
+ default: standard
75
+ options:
76
+ - id: minimal
77
+ overlays: []
78
+ description: 'No observability tools'
79
+ - id: standard
80
+ overlays: [prometheus, grafana]
81
+ description: 'Metrics and dashboards'
82
+ - id: full
83
+ overlays: [otel-collector, prometheus, grafana, loki]
84
+ description: 'Full stack - metrics, logs, and traces'
85
+
86
+ # Glue configuration - integration helpers
87
+ glueConfig:
88
+ # Suggested port mappings (actual ports depend on chosen overlays)
89
+ portMappings:
90
+ api: 8000
91
+ grafana: 3000
92
+ prometheus: 9090
93
+
94
+ # README snippet to add to generated devcontainer
95
+ readme: |
96
+ ## Web API Stack
97
+
98
+ This devcontainer is configured for web API development. The exact services depend
99
+ on the parameters you chose (database, cache, broker, observability).
100
+
101
+ ### Connection Strings
102
+
103
+ Connection strings for each service are defined in `.devcontainer/.env.example`.
104
+ Copy that file to `.env` and adjust values as needed:
105
+
106
+ ```bash
107
+ cd .devcontainer
108
+ cp .env.example .env
109
+ ```
110
+
111
+ ### Quick Start
112
+
113
+ 1. Start your API (default suggested port: 8000)
114
+ 2. Access Grafana at http://localhost:3000 (admin/admin) — if observability was enabled
115
+ 3. View metrics in Prometheus at http://localhost:9090 — if observability was enabled
116
+
117
+ ### Health Checks
118
+
119
+ Verify all services are running:
120
+
121
+ ```bash
122
+ docker-compose ps
123
+ ```
124
+
125
+ ### Next Steps
126
+
127
+ - Configure your API to use the connection strings from `.env`
128
+ - Add OpenTelemetry SDK to your application (if full observability was selected)
129
+ - Create custom Grafana dashboards for your API metrics
@@ -11,4 +11,4 @@ These files are loaded during initialization to provide choices for base images
11
11
 
12
12
  ## Note
13
13
 
14
- Preset definitions are stored in `overlays/presets/*.yml`.
14
+ Preset definitions are stored in `overlays/.presets/*.yml`.
@@ -0,0 +1,54 @@
1
+ deployment_targets:
2
+ - id: local
3
+ name: Local Development
4
+ description: Running on local machine with Docker Desktop or Docker daemon
5
+ incompatibleOverlays: []
6
+ recommendations: {}
7
+ portForwarding:
8
+ defaultBehavior: notify
9
+ autoForward: false
10
+ constraints:
11
+ hasHostDocker: true
12
+ supportsPrivileged: true
13
+
14
+ - id: codespaces
15
+ name: GitHub Codespaces
16
+ description: Cloud-based development environment on GitHub
17
+ incompatibleOverlays:
18
+ - docker-sock
19
+ recommendations:
20
+ docker-sock:
21
+ - docker-in-docker
22
+ portForwarding:
23
+ defaultBehavior: notify
24
+ autoForward: true
25
+ constraints:
26
+ hasHostDocker: false
27
+ supportsPrivileged: true
28
+
29
+ - id: gitpod
30
+ name: Gitpod
31
+ description: Cloud development environment on Gitpod
32
+ incompatibleOverlays:
33
+ - docker-sock
34
+ recommendations:
35
+ docker-sock:
36
+ - docker-in-docker
37
+ portForwarding:
38
+ defaultBehavior: openBrowser
39
+ autoForward: true
40
+ constraints:
41
+ hasHostDocker: false
42
+ supportsPrivileged: true
43
+
44
+ - id: devpod
45
+ name: DevPod
46
+ description: Client-only development environments
47
+ incompatibleOverlays: []
48
+ recommendations: {}
49
+ portForwarding:
50
+ defaultBehavior: notify
51
+ autoForward: false
52
+ constraints:
53
+ hasHostDocker: true
54
+ supportsPrivileged: true