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.
- package/README.md +569 -8
- package/dist/scripts/init.js +436 -254
- package/dist/scripts/init.js.map +1 -1
- package/dist/tool/commands/doctor.d.ts +15 -0
- package/dist/tool/commands/doctor.d.ts.map +1 -0
- package/dist/tool/commands/doctor.js +862 -0
- package/dist/tool/commands/doctor.js.map +1 -0
- package/dist/tool/commands/explain.d.ts +13 -0
- package/dist/tool/commands/explain.d.ts.map +1 -0
- package/dist/tool/commands/explain.js +299 -0
- package/dist/tool/commands/explain.js.map +1 -0
- package/dist/tool/commands/list.d.ts +16 -0
- package/dist/tool/commands/list.d.ts.map +1 -0
- package/dist/tool/commands/list.js +121 -0
- package/dist/tool/commands/list.js.map +1 -0
- package/dist/tool/commands/plan.d.ts +67 -0
- package/dist/tool/commands/plan.d.ts.map +1 -0
- package/dist/tool/commands/plan.js +851 -0
- package/dist/tool/commands/plan.js.map +1 -0
- package/dist/tool/questionnaire/composer.d.ts +16 -2
- package/dist/tool/questionnaire/composer.d.ts.map +1 -1
- package/dist/tool/questionnaire/composer.js +411 -200
- package/dist/tool/questionnaire/composer.js.map +1 -1
- package/dist/tool/readme/markdown-parser.d.ts.map +1 -1
- package/dist/tool/readme/markdown-parser.js.map +1 -1
- package/dist/tool/readme/readme-generator.d.ts.map +1 -1
- package/dist/tool/readme/readme-generator.js +11 -6
- package/dist/tool/readme/readme-generator.js.map +1 -1
- package/dist/tool/schema/deployment-targets.d.ts +77 -0
- package/dist/tool/schema/deployment-targets.d.ts.map +1 -0
- package/dist/tool/schema/deployment-targets.js +91 -0
- package/dist/tool/schema/deployment-targets.js.map +1 -0
- package/dist/tool/schema/manifest-migrations.d.ts +51 -0
- package/dist/tool/schema/manifest-migrations.d.ts.map +1 -0
- package/dist/tool/schema/manifest-migrations.js +159 -0
- package/dist/tool/schema/manifest-migrations.js.map +1 -0
- package/dist/tool/schema/overlay-loader.d.ts +1 -1
- package/dist/tool/schema/overlay-loader.d.ts.map +1 -1
- package/dist/tool/schema/overlay-loader.js +42 -14
- package/dist/tool/schema/overlay-loader.js.map +1 -1
- package/dist/tool/schema/types.d.ts +62 -2
- package/dist/tool/schema/types.d.ts.map +1 -1
- package/dist/tool/utils/gitignore.d.ts +15 -0
- package/dist/tool/utils/gitignore.d.ts.map +1 -0
- package/dist/tool/utils/gitignore.js +41 -0
- package/dist/tool/utils/gitignore.js.map +1 -0
- package/dist/tool/utils/merge.d.ts +134 -0
- package/dist/tool/utils/merge.d.ts.map +1 -0
- package/dist/tool/utils/merge.js +277 -0
- package/dist/tool/utils/merge.js.map +1 -0
- package/dist/tool/utils/port-utils.d.ts +29 -0
- package/dist/tool/utils/port-utils.d.ts.map +1 -0
- package/dist/tool/utils/port-utils.js +128 -0
- package/dist/tool/utils/port-utils.js.map +1 -0
- package/dist/tool/utils/services-export.d.ts +14 -0
- package/dist/tool/utils/services-export.d.ts.map +1 -0
- package/dist/tool/utils/services-export.js +478 -0
- package/dist/tool/utils/services-export.js.map +1 -0
- package/dist/tool/utils/summary.d.ts +69 -0
- package/dist/tool/utils/summary.d.ts.map +1 -0
- package/dist/tool/utils/summary.js +260 -0
- package/dist/tool/utils/summary.js.map +1 -0
- package/dist/tool/utils/version.d.ts +9 -0
- package/dist/tool/utils/version.d.ts.map +1 -0
- package/dist/tool/utils/version.js +32 -0
- package/dist/tool/utils/version.js.map +1 -0
- package/docs/architecture.md +25 -21
- package/docs/deployment-targets.md +150 -0
- package/docs/discovery-commands.md +442 -0
- package/docs/merge-strategy.md +700 -0
- package/docs/minimal-and-editor.md +265 -0
- package/docs/overlay-imports.md +209 -0
- package/docs/overlay-manifest-refactoring.md +2 -2
- package/docs/overlay-metadata-archive.md +1 -1
- package/docs/overlays.md +139 -28
- package/docs/presets-architecture.md +3 -3
- package/docs/presets.md +1 -1
- package/docs/publishing.md +36 -35
- package/docs/team-workflow.md +540 -0
- package/overlays/.presets/data-engineering.yml +392 -0
- package/overlays/.presets/event-sourced-service.yml +262 -0
- package/overlays/.presets/frontend.yml +287 -0
- package/overlays/.presets/k8s-operator-dev.yml +462 -0
- package/overlays/{presets → .presets}/microservice.yml +32 -6
- package/overlays/.presets/web-api.yml +129 -0
- package/overlays/.registry/README.md +1 -1
- package/overlays/.registry/deployment-targets.yml +54 -0
- package/overlays/.shared/README.md +43 -0
- package/overlays/.shared/compose/common-healthchecks.yml +38 -0
- package/overlays/.shared/otel/instrumentation.env +20 -0
- package/overlays/.shared/otel/otel-base-config.yaml +30 -0
- package/overlays/.shared/vscode/recommended-extensions.json +14 -0
- package/overlays/README.md +1 -1
- package/overlays/cloudflared/README.md +190 -0
- package/overlays/cloudflared/devcontainer.patch.json +3 -0
- package/overlays/cloudflared/overlay.yml +15 -0
- package/overlays/cloudflared/setup.sh +49 -0
- package/overlays/cloudflared/verify.sh +21 -0
- package/overlays/codex/overlay.yml +1 -0
- package/overlays/direnv/README.md +6 -4
- package/overlays/direnv/setup.sh +0 -12
- package/overlays/duckdb/README.md +274 -0
- package/overlays/duckdb/devcontainer.patch.json +10 -0
- package/overlays/duckdb/overlay.yml +17 -0
- package/overlays/duckdb/setup.sh +45 -0
- package/overlays/duckdb/verify.sh +32 -0
- package/overlays/git-helpers/overlay.yml +1 -0
- package/overlays/grafana/README.md +5 -5
- package/overlays/grafana/dashboard-provider.yml +1 -1
- package/overlays/grafana/docker-compose.yml +2 -2
- package/overlays/grafana/overlay.yml +6 -1
- package/overlays/grpc-tools/README.md +242 -0
- package/overlays/grpc-tools/devcontainer.patch.json +14 -0
- package/overlays/grpc-tools/overlay.yml +14 -0
- package/overlays/grpc-tools/setup.sh +57 -0
- package/overlays/grpc-tools/verify.sh +47 -0
- package/overlays/jaeger/overlay.yml +16 -3
- package/overlays/jupyter/.env.example +6 -0
- package/overlays/jupyter/README.md +210 -0
- package/overlays/jupyter/devcontainer.patch.json +14 -0
- package/overlays/jupyter/docker-compose.yml +23 -0
- package/overlays/jupyter/overlay.yml +18 -0
- package/overlays/jupyter/verify.sh +35 -0
- package/overlays/keycloak/.env.example +5 -0
- package/overlays/keycloak/README.md +238 -0
- package/overlays/keycloak/devcontainer.patch.json +17 -0
- package/overlays/keycloak/docker-compose.yml +32 -0
- package/overlays/keycloak/overlay.yml +23 -0
- package/overlays/keycloak/verify.sh +54 -0
- package/overlays/kind/README.md +221 -0
- package/overlays/kind/devcontainer.patch.json +10 -0
- package/overlays/kind/overlay.yml +18 -0
- package/overlays/kind/setup.sh +43 -0
- package/overlays/kind/verify.sh +40 -0
- package/overlays/localstack/.env.example +6 -0
- package/overlays/localstack/README.md +188 -0
- package/overlays/localstack/devcontainer.patch.json +21 -0
- package/overlays/localstack/docker-compose.yml +25 -0
- package/overlays/localstack/overlay.yml +18 -0
- package/overlays/localstack/verify.sh +47 -0
- package/overlays/loki/overlay.yml +6 -1
- package/overlays/mailpit/.env.example +4 -0
- package/overlays/mailpit/README.md +191 -0
- package/overlays/mailpit/devcontainer.patch.json +20 -0
- package/overlays/mailpit/docker-compose.yml +17 -0
- package/overlays/mailpit/overlay.yml +26 -0
- package/overlays/mailpit/verify.sh +52 -0
- package/overlays/modern-cli-tools/overlay.yml +1 -0
- package/overlays/mongodb/overlay.yml +12 -2
- package/overlays/mysql/overlay.yml +12 -2
- package/overlays/nats/overlay.yml +12 -2
- package/overlays/ngrok/overlay.yml +2 -1
- package/overlays/openapi-tools/README.md +243 -0
- package/overlays/openapi-tools/devcontainer.patch.json +10 -0
- package/overlays/openapi-tools/overlay.yml +16 -0
- package/overlays/openapi-tools/setup.sh +45 -0
- package/overlays/openapi-tools/verify.sh +51 -0
- package/overlays/otel-collector/overlay.yml.example +26 -0
- package/overlays/postgres/overlay.yml +6 -1
- package/overlays/prometheus/overlay.yml +6 -1
- package/overlays/python/README.md +51 -35
- package/overlays/python/devcontainer.patch.json +7 -4
- package/overlays/python/setup.sh +50 -23
- package/overlays/python/verify.sh +29 -1
- package/overlays/rabbitmq/overlay.yml +12 -2
- package/overlays/redis/overlay.yml +6 -1
- package/overlays/tilt/README.md +259 -0
- package/overlays/tilt/devcontainer.patch.json +17 -0
- package/overlays/tilt/overlay.yml +19 -0
- package/overlays/tilt/setup.sh +25 -0
- package/overlays/tilt/verify.sh +24 -0
- package/package.json +8 -6
- package/tool/README.md +12 -16
- package/tool/schema/overlay-manifest.schema.json +64 -4
- package/tool/schema/superposition-manifest.schema.json +104 -0
- package/overlays/presets/web-api.yml +0 -109
- /package/overlays/{presets → .presets}/docs-site.yml +0 -0
- /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
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
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
|
|
@@ -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
|