@bluedynamics/cdk8s-monitoring 0.0.1

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 (47) hide show
  1. package/CLAUDE.md +76 -0
  2. package/LICENSE +202 -0
  3. package/README.md +87 -0
  4. package/examples/synth.ts +17 -0
  5. package/lib/constructs/alloy.d.ts +29 -0
  6. package/lib/constructs/alloy.js +214 -0
  7. package/lib/constructs/grafana-password-secret.d.ts +57 -0
  8. package/lib/constructs/grafana-password-secret.js +99 -0
  9. package/lib/constructs/loki-s3-bucket.d.ts +24 -0
  10. package/lib/constructs/loki-s3-bucket.js +147 -0
  11. package/lib/constructs/loki-s3-credentials.d.ts +27 -0
  12. package/lib/constructs/loki-s3-credentials.js +71 -0
  13. package/lib/constructs/loki.d.ts +30 -0
  14. package/lib/constructs/loki.js +185 -0
  15. package/lib/constructs/namespace.d.ts +13 -0
  16. package/lib/constructs/namespace.js +34 -0
  17. package/lib/constructs/priority-class.d.ts +12 -0
  18. package/lib/constructs/priority-class.js +38 -0
  19. package/lib/constructs/prometheus-stack.d.ts +30 -0
  20. package/lib/constructs/prometheus-stack.js +477 -0
  21. package/lib/constructs/thanos-compactor.d.ts +35 -0
  22. package/lib/constructs/thanos-compactor.js +198 -0
  23. package/lib/constructs/thanos-query.d.ts +30 -0
  24. package/lib/constructs/thanos-query.js +205 -0
  25. package/lib/constructs/thanos-s3-bucket.d.ts +24 -0
  26. package/lib/constructs/thanos-s3-bucket.js +147 -0
  27. package/lib/constructs/thanos-s3-credentials.d.ts +27 -0
  28. package/lib/constructs/thanos-s3-credentials.js +93 -0
  29. package/lib/constructs/thanos-store.d.ts +30 -0
  30. package/lib/constructs/thanos-store.js +239 -0
  31. package/lib/default-config.d.ts +12 -0
  32. package/lib/default-config.js +77 -0
  33. package/lib/imports/external-secrets.io.d.ts +39243 -0
  34. package/lib/imports/external-secrets.io.js +23112 -0
  35. package/lib/imports/generators.external-secrets.io.d.ts +7831 -0
  36. package/lib/imports/generators.external-secrets.io.js +4895 -0
  37. package/lib/imports/k8s.d.ts +24537 -0
  38. package/lib/imports/k8s.js +18268 -0
  39. package/lib/imports/s3.aws.upbound.io.d.ts +2882 -0
  40. package/lib/imports/s3.aws.upbound.io.js +1828 -0
  41. package/lib/index.d.ts +17 -0
  42. package/lib/index.js +38 -0
  43. package/lib/monitoring-chart.d.ts +39 -0
  44. package/lib/monitoring-chart.js +127 -0
  45. package/lib/types.d.ts +142 -0
  46. package/lib/types.js +3 -0
  47. package/package.json +117 -0
@@ -0,0 +1,198 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.ThanosCompactorConstruct = void 0;
4
+ const constructs_1 = require("constructs");
5
+ const k8s_1 = require("../imports/k8s");
6
+ /**
7
+ * Creates Thanos Compactor StatefulSet and Service.
8
+ *
9
+ * Thanos Compactor performs:
10
+ * - Downsampling: Creates 5-minute and 1-hour resolution data from raw blocks
11
+ * - Compaction: Merges small blocks into larger ones for better query performance
12
+ * - Retention enforcement: Deletes blocks older than configured retention
13
+ *
14
+ * Retention Strategy:
15
+ * - Raw (15s resolution): 30 days
16
+ * - 5-minute resolution: 180 days (6 months)
17
+ * - 1-hour resolution: 730 days (2 years)
18
+ *
19
+ * Components:
20
+ * - StatefulSet (1 replica - singleton, 20Gi PVC for working directory)
21
+ * - HTTP Service (for metrics and debugging)
22
+ *
23
+ * Prerequisites:
24
+ * - Namespace exists
25
+ * - PriorityClass 'high-priority' exists
26
+ * - Longhorn storage class available
27
+ * - Thanos S3 secret exists (thanos-objstore-config)
28
+ * - S3 bucket contains Prometheus data blocks
29
+ *
30
+ * Sync Wave: 3 (compaction - can run alongside Store Gateway)
31
+ */
32
+ class ThanosCompactorConstruct extends constructs_1.Construct {
33
+ constructor(scope, id, props) {
34
+ super(scope, id);
35
+ const { namespace, config } = props;
36
+ // Create StatefulSet
37
+ // Wave 3: Compaction - after S3 bucket and credentials are ready
38
+ new k8s_1.KubeStatefulSet(this, 'statefulset', {
39
+ metadata: {
40
+ name: 'thanos-compactor',
41
+ namespace: namespace,
42
+ labels: {
43
+ 'app.kubernetes.io/name': 'thanos-compactor',
44
+ 'app.kubernetes.io/component': 'compactor',
45
+ 'app.kubernetes.io/managed-by': 'cdk8s',
46
+ 'app.kubernetes.io/part-of': 'monitoring',
47
+ },
48
+ annotations: {
49
+ 'argocd.argoproj.io/sync-wave': '3',
50
+ },
51
+ },
52
+ spec: {
53
+ serviceName: 'thanos-compactor',
54
+ replicas: 1, // Singleton - only one compactor should run
55
+ selector: {
56
+ matchLabels: {
57
+ 'app.kubernetes.io/name': 'thanos-compactor',
58
+ },
59
+ },
60
+ template: {
61
+ metadata: {
62
+ labels: {
63
+ 'app.kubernetes.io/name': 'thanos-compactor',
64
+ 'app.kubernetes.io/component': 'compactor',
65
+ },
66
+ },
67
+ spec: {
68
+ // No arch nodeSelector: Thanos images are multi-arch; let the
69
+ // scheduler place this on any worker (legacy ARM64 pin removed).
70
+ // Fix volume permissions for Thanos user (UID 10001)
71
+ securityContext: {
72
+ fsGroup: 10001,
73
+ runAsUser: 10001,
74
+ runAsNonRoot: true,
75
+ },
76
+ containers: [
77
+ {
78
+ name: 'thanos-compactor',
79
+ image: `quay.io/thanos/thanos:${config.versions.thanos}`,
80
+ args: [
81
+ 'compact',
82
+ '--log.level=info',
83
+ '--data-dir=/var/thanos/compactor',
84
+ '--objstore.config-file=/etc/thanos/objstore.yml',
85
+ '--wait', // Wait for other compactors to finish (prevents conflicts)
86
+ // Downsampling configuration
87
+ `--retention.resolution-raw=${config.retention.prometheusS3Raw}d`, // Keep raw data for 30 days
88
+ `--retention.resolution-5m=${config.retention.prometheusS35m}d`, // Keep 5m data for 180 days (6 months)
89
+ `--retention.resolution-1h=${config.retention.prometheusS31h}d`, // Keep 1h data for 730 days (2 years)
90
+ // Compaction configuration
91
+ '--compact.concurrency=1',
92
+ '--delete-delay=48h', // Wait 48h before deleting blocks (safety margin)
93
+ ],
94
+ ports: [
95
+ {
96
+ name: 'http',
97
+ containerPort: 10902,
98
+ },
99
+ ],
100
+ volumeMounts: [
101
+ {
102
+ name: 'objstore-config',
103
+ mountPath: '/etc/thanos',
104
+ readOnly: true,
105
+ },
106
+ {
107
+ name: 'data',
108
+ mountPath: '/var/thanos/compactor',
109
+ },
110
+ ],
111
+ livenessProbe: {
112
+ httpGet: {
113
+ path: '/-/healthy',
114
+ port: k8s_1.IntOrString.fromString('http'),
115
+ },
116
+ initialDelaySeconds: 30,
117
+ periodSeconds: 30,
118
+ },
119
+ readinessProbe: {
120
+ httpGet: {
121
+ path: '/-/ready',
122
+ port: k8s_1.IntOrString.fromString('http'),
123
+ },
124
+ initialDelaySeconds: 30,
125
+ periodSeconds: 5,
126
+ },
127
+ resources: {
128
+ requests: {
129
+ cpu: k8s_1.Quantity.fromString(config.resources.thanosCompactor.requests.cpu),
130
+ memory: k8s_1.Quantity.fromString(config.resources.thanosCompactor.requests.memory),
131
+ },
132
+ limits: {
133
+ cpu: k8s_1.Quantity.fromString(config.resources.thanosCompactor.limits.cpu),
134
+ memory: k8s_1.Quantity.fromString(config.resources.thanosCompactor.limits.memory),
135
+ },
136
+ },
137
+ },
138
+ ],
139
+ volumes: [
140
+ {
141
+ name: 'objstore-config',
142
+ secret: {
143
+ secretName: 'thanos-objstore-config',
144
+ },
145
+ },
146
+ ],
147
+ priorityClassName: 'high-priority',
148
+ },
149
+ },
150
+ volumeClaimTemplates: [
151
+ {
152
+ metadata: {
153
+ name: 'data',
154
+ },
155
+ spec: {
156
+ accessModes: ['ReadWriteOnce'],
157
+ storageClassName: 'longhorn',
158
+ resources: {
159
+ requests: {
160
+ storage: k8s_1.Quantity.fromString(config.storage.thanosCompactor), // Working directory for compaction operations
161
+ },
162
+ },
163
+ },
164
+ },
165
+ ],
166
+ },
167
+ });
168
+ // Create HTTP Service (for metrics/debugging)
169
+ new k8s_1.KubeService(this, 'service', {
170
+ metadata: {
171
+ name: 'thanos-compactor',
172
+ namespace: namespace,
173
+ labels: {
174
+ 'app.kubernetes.io/name': 'thanos-compactor',
175
+ 'app.kubernetes.io/managed-by': 'cdk8s',
176
+ },
177
+ annotations: {
178
+ 'argocd.argoproj.io/sync-wave': '3',
179
+ },
180
+ },
181
+ spec: {
182
+ ports: [
183
+ {
184
+ name: 'http',
185
+ port: 10902,
186
+ targetPort: 'http',
187
+ protocol: 'TCP',
188
+ },
189
+ ],
190
+ selector: {
191
+ 'app.kubernetes.io/name': 'thanos-compactor',
192
+ },
193
+ },
194
+ });
195
+ }
196
+ }
197
+ exports.ThanosCompactorConstruct = ThanosCompactorConstruct;
198
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoidGhhbm9zLWNvbXBhY3Rvci5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uL3NyYy9jb25zdHJ1Y3RzL3RoYW5vcy1jb21wYWN0b3IudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6Ijs7O0FBQUEsMkNBQXVDO0FBQ3ZDLHdDQUFxRjtBQVFyRjs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7OztHQXlCRztBQUNILE1BQWEsd0JBQXlCLFNBQVEsc0JBQVM7SUFDckQsWUFBWSxLQUFnQixFQUFFLEVBQVUsRUFBRSxLQUEyQjtRQUNuRSxLQUFLLENBQUMsS0FBSyxFQUFFLEVBQUUsQ0FBQyxDQUFDO1FBRWpCLE1BQU0sRUFBRSxTQUFTLEVBQUUsTUFBTSxFQUFFLEdBQUcsS0FBSyxDQUFDO1FBRXBDLHFCQUFxQjtRQUNyQixpRUFBaUU7UUFDakUsSUFBSSxxQkFBZSxDQUFDLElBQUksRUFBRSxhQUFhLEVBQUU7WUFDdkMsUUFBUSxFQUFFO2dCQUNSLElBQUksRUFBRSxrQkFBa0I7Z0JBQ3hCLFNBQVMsRUFBRSxTQUFTO2dCQUNwQixNQUFNLEVBQUU7b0JBQ04sd0JBQXdCLEVBQUUsa0JBQWtCO29CQUM1Qyw2QkFBNkIsRUFBRSxXQUFXO29CQUMxQyw4QkFBOEIsRUFBRSxPQUFPO29CQUN2QywyQkFBMkIsRUFBRSxZQUFZO2lCQUMxQztnQkFDRCxXQUFXLEVBQUU7b0JBQ1gsOEJBQThCLEVBQUUsR0FBRztpQkFDcEM7YUFDRjtZQUNELElBQUksRUFBRTtnQkFDSixXQUFXLEVBQUUsa0JBQWtCO2dCQUMvQixRQUFRLEVBQUUsQ0FBQyxFQUFFLDRDQUE0QztnQkFDekQsUUFBUSxFQUFFO29CQUNSLFdBQVcsRUFBRTt3QkFDWCx3QkFBd0IsRUFBRSxrQkFBa0I7cUJBQzdDO2lCQUNGO2dCQUNELFFBQVEsRUFBRTtvQkFDUixRQUFRLEVBQUU7d0JBQ1IsTUFBTSxFQUFFOzRCQUNOLHdCQUF3QixFQUFFLGtCQUFrQjs0QkFDNUMsNkJBQTZCLEVBQUUsV0FBVzt5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Q0osV0FBVyxFQUFFLENBQUMsZUFBZSxDQUFDOzRCQUM5QixnQkFBZ0IsRUFBRSxVQUFVOzRCQUM1QixTQUFTLEVBQUU7Z0NBQ1QsUUFBUSxFQUFFO29DQUNSLE9BQU8sRUFBRSxjQUFRLENBQUMsVUFBVSxDQUFDLE1BQU0sQ0FBQyxPQUFPLENBQUMsZUFBZSxDQUFDLEVBQUUsOENBQThDO2lDQUM3Rzs2QkFDRjt5QkFDRjtxQkFDRjtpQkFDRjthQUNGO1NBQ0YsQ0FBQyxDQUFDO1FBRUgsOENBQThDO1FBQzlDLElBQUksaUJBQVcsQ0FBQyxJQUFJLEVBQUUsU0FBUyxFQUFFO1lBQy9CLFFBQVEsRUFBRTtnQkFDUixJQUFJLEVBQUUsa0JBQWtCO2dCQUN4QixTQUFTLEVBQUUsU0FBUztnQkFDcEIsTUFBTSxFQUFFO29CQUNOLHdCQUF3QixFQUFFLGtCQUFrQjtvQkFDNUMsOEJBQThCLEVBQUUsT0FBTztpQkFDeEM7Z0JBQ0QsV0FBVyxFQUFFO29CQUNYLDhCQUE4QixFQUFFLEdBQUc7aUJBQ3BDO2FBQ0Y7WUFDRCxJQUFJLEVBQUU7Z0JBQ0osS0FBSyxFQUFFO29CQUNMO3dCQUNFLElBQUksRUFBRSxNQUFNO3dCQUNaLElBQUksRUFBRSxLQUFLO3dCQUNYLFVBQVUsRUFBRSxNQUFhO3dCQUN6QixRQUFRLEVBQUUsS0FBSztxQkFDaEI7aUJBQ0Y7Z0JBQ0QsUUFBUSxFQUFFO29CQUNSLHdCQUF3QixFQUFFLGtCQUFrQjtpQkFDN0M7YUFDRjtTQUNGLENBQUMsQ0FBQztJQUNMLENBQUM7Q0FDRjtBQTNLRCw0REEyS0MiLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQgeyBDb25zdHJ1Y3QgfSBmcm9tICdjb25zdHJ1Y3RzJztcbmltcG9ydCB7IEt1YmVTdGF0ZWZ1bFNldCwgS3ViZVNlcnZpY2UsIFF1YW50aXR5LCBJbnRPclN0cmluZyB9IGZyb20gJy4uL2ltcG9ydHMvazhzJztcbmltcG9ydCB7IE1vbml0b3JpbmdDb25maWcgfSBmcm9tICcuLi90eXBlcyc7XG5cbmV4cG9ydCBpbnRlcmZhY2UgVGhhbm9zQ29tcGFjdG9yUHJvcHMge1xuICBuYW1lc3BhY2U6IHN0cmluZztcbiAgY29uZmlnOiBNb25pdG9yaW5nQ29uZmlnO1xufVxuXG4vKipcbiAqIENyZWF0ZXMgVGhhbm9zIENvbXBhY3RvciBTdGF0ZWZ1bFNldCBhbmQgU2VydmljZS5cbiAqXG4gKiBUaGFub3MgQ29tcGFjdG9yIHBlcmZvcm1zOlxuICogLSBEb3duc2FtcGxpbmc6IENyZWF0ZXMgNS1taW51dGUgYW5kIDEtaG91ciByZXNvbHV0aW9uIGRhdGEgZnJvbSByYXcgYmxvY2tzXG4gKiAtIENvbXBhY3Rpb246IE1lcmdlcyBzbWFsbCBibG9ja3MgaW50byBsYXJnZXIgb25lcyBmb3IgYmV0dGVyIHF1ZXJ5IHBlcmZvcm1hbmNlXG4gKiAtIFJldGVudGlvbiBlbmZvcmNlbWVudDogRGVsZXRlcyBibG9ja3Mgb2xkZXIgdGhhbiBjb25maWd1cmVkIHJldGVudGlvblxuICpcbiAqIFJldGVudGlvbiBTdHJhdGVneTpcbiAqIC0gUmF3ICgxNXMgcmVzb2x1dGlvbik6IDMwIGRheXNcbiAqIC0gNS1taW51dGUgcmVzb2x1dGlvbjogMTgwIGRheXMgKDYgbW9udGhzKVxuICogLSAxLWhvdXIgcmVzb2x1dGlvbjogNzMwIGRheXMgKDIgeWVhcnMpXG4gKlxuICogQ29tcG9uZW50czpcbiAqIC0gU3RhdGVmdWxTZXQgKDEgcmVwbGljYSAtIHNpbmdsZXRvbiwgMjBHaSBQVkMgZm9yIHdvcmtpbmcgZGlyZWN0b3J5KVxuICogLSBIVFRQIFNlcnZpY2UgKGZvciBtZXRyaWNzIGFuZCBkZWJ1Z2dpbmcpXG4gKlxuICogUHJlcmVxdWlzaXRlczpcbiAqIC0gTmFtZXNwYWNlIGV4aXN0c1xuICogLSBQcmlvcml0eUNsYXNzICdoaWdoLXByaW9yaXR5JyBleGlzdHNcbiAqIC0gTG9uZ2hvcm4gc3RvcmFnZSBjbGFzcyBhdmFpbGFibGVcbiAqIC0gVGhhbm9zIFMzIHNlY3JldCBleGlzdHMgKHRoYW5vcy1vYmpzdG9yZS1jb25maWcpXG4gKiAtIFMzIGJ1Y2tldCBjb250YWlucyBQcm9tZXRoZXVzIGRhdGEgYmxvY2tzXG4gKlxuICogU3luYyBXYXZlOiAzIChjb21wYWN0aW9uIC0gY2FuIHJ1biBhbG9uZ3NpZGUgU3RvcmUgR2F0ZXdheSlcbiAqL1xuZXhwb3J0IGNsYXNzIFRoYW5vc0NvbXBhY3RvckNvbnN0cnVjdCBleHRlbmRzIENvbnN0cnVjdCB7XG4gIGNvbnN0cnVjdG9yKHNjb3BlOiBDb25zdHJ1Y3QsIGlkOiBzdHJpbmcsIHByb3BzOiBUaGFub3NDb21wYWN0b3JQcm9wcykge1xuICAgIHN1cGVyKHNjb3BlLCBpZCk7XG5cbiAgICBjb25zdCB7IG5hbWVzcGFjZSwgY29uZmlnIH0gPSBwcm9wcztcblxuICAgIC8vIENyZWF0ZSBTdGF0ZWZ1bFNldFxuICAgIC8vIFdhdmUgMzogQ29tcGFjdGlvbiAtIGFmdGVyIFMzIGJ1Y2tldCBhbmQgY3JlZGVudGlhbHMgYXJlIHJlYWR5XG4gICAgbmV3IEt1YmVTdGF0ZWZ1bFNldCh0aGlzLCAnc3RhdGVmdWxzZXQnLCB7XG4gICAgICBtZXRhZGF0YToge1xuICAgICAgICBuYW1lOiAndGhhbm9zLWNvbXBhY3RvcicsXG4gICAgICAgIG5hbWVzcGFjZTogbmFtZXNwYWNlLFxuICAgICAgICBsYWJlbHM6IHtcbiAgICAgICAgICAnYXBwLmt1YmVybmV0ZXMuaW8vbmFtZSc6ICd0aGFub3MtY29tcGFjdG9yJyxcbiAgICAgICAgICAnYXBwLmt1YmVybmV0ZXMuaW8vY29tcG9uZW50JzogJ2NvbXBhY3RvcicsXG4gICAgICAgICAgJ2FwcC5rdWJlcm5ldGVzLmlvL21hbmFnZWQtYnknOiAnY2RrOHMnLFxuICAgICAgICAgICdhcHAua3ViZXJuZXRlcy5pby9wYXJ0LW9mJzogJ21vbml0b3JpbmcnLFxuICAgICAgICB9LFxuICAgICAgICBhbm5vdGF0aW9uczoge1xuICAgICAgICAgICdhcmdvY2QuYXJnb3Byb2ouaW8vc3luYy13YXZlJzogJzMnLFxuICAgICAgICB9LFxuICAgICAgfSxcbiAgICAgIHNwZWM6IHtcbiAgICAgICAgc2VydmljZU5hbWU6ICd0aGFub3MtY29tcGFjdG9yJyxcbiAgICAgICAgcmVwbGljYXM6IDEsIC8vIFNpbmdsZXRvbiAtIG9ubHkgb25lIGNvbXBhY3RvciBzaG91bGQgcnVuXG4gICAgICAgIHNlbGVjdG9yOiB7XG4gICAgICAgICAgbWF0Y2hMYWJlbHM6IHtcbiAgICAgICAgICAgICdhcHAua3ViZXJuZXRlcy5pby9uYW1lJzogJ3RoYW5vcy1jb21wYWN0b3InLFxuICAgICAgICAgIH0sXG4gICAgICAgIH0sXG4gICAgICAgIHRlbXBsYXRlOiB7XG4gICAgICAgICAgbWV0YWRhdGE6IHtcbiAgICAgICAgICAgIGxhYmVsczoge1xuICAgICAgICAgICAgICAnYXBwLmt1YmVybmV0ZXMuaW8vbmFtZSc6ICd0aGFub3MtY29tcGFjdG9yJyxcbiAgICAgICAgICAgICAgJ2FwcC5rdWJlcm5ldGVzLmlvL2NvbXBvbmVudCc6ICdjb21wYWN0b3InLFxuICAgICAgICAgICAgfSxcbiAgICAgICAgICB9LFxuICAgICAgICAgIHNwZWM6IHtcbiAgICAgICAgICAgIC8vIE5vIGFyY2ggbm9kZVNlbGVjdG9yOiBUaGFub3MgaW1hZ2VzIGFyZSBtdWx0aS1hcmNoOyBsZXQgdGhlXG4gICAgICAgICAgICAvLyBzY2hlZHVsZXIgcGxhY2UgdGhpcyBvbiBhbnkgd29ya2VyIChsZWdhY3kgQVJNNjQgcGluIHJlbW92ZWQpLlxuXG4gICAgICAgICAgICAvLyBGaXggdm9sdW1lIHBlcm1pc3Npb25zIGZvciBUaGFub3MgdXNlciAoVUlEIDEwMDAxKVxuICAgICAgICAgICAgc2VjdXJpdHlDb250ZXh0OiB7XG4gICAgICAgICAgICAgIGZzR3JvdXA6IDEwMDAxLFxuICAgICAgICAgICAgICBydW5Bc1VzZXI6IDEwMDAxLFxuICAgICAgICAgICAgICBydW5Bc05vblJvb3Q6IHRydWUsXG4gICAgICAgICAgICB9LFxuXG4gICAgICAgICAgICBjb250YWluZXJzOiBbXG4gICAgICAgICAgICAgIHtcbiAgICAgICAgICAgICAgICBuYW1lOiAndGhhbm9zLWNvbXBhY3RvcicsXG4gICAgICAgICAgICAgICAgaW1hZ2U6IGBxdWF5LmlvL3RoYW5vcy90aGFub3M6JHtjb25maWcudmVyc2lvbnMudGhhbm9zfWAsXG4gICAgICAgICAgICAgICAgYXJnczogW1xuICAgICAgICAgICAgICAgICAgJ2NvbXBhY3QnLFxuICAgICAgICAgICAgICAgICAgJy0tbG9nLmxldmVsPWluZm8nLFxuICAgICAgICAgICAgICAgICAgJy0tZGF0YS1kaXI9L3Zhci90aGFub3MvY29tcGFjdG9yJyxcbiAgICAgICAgICAgICAgICAgICctLW9ianN0b3JlLmNvbmZpZy1maWxlPS9ldGMvdGhhbm9zL29ianN0b3JlLnltbCcsXG4gICAgICAgICAgICAgICAgICAnLS13YWl0JywgLy8gV2FpdCBmb3Igb3RoZXIgY29tcGFjdG9ycyB0byBmaW5pc2ggKHByZXZlbnRzIGNvbmZsaWN0cylcbiAgICAgICAgICAgICAgICAgIC8vIERvd25zYW1wbGluZyBjb25maWd1cmF0aW9uXG4gICAgICAgICAgICAgICAgICBgLS1yZXRlbnRpb24ucmVzb2x1dGlvbi1yYXc9JHtjb25maWcucmV0ZW50aW9uLnByb21ldGhldXNTM1Jhd31kYCwgLy8gS2VlcCByYXcgZGF0YSBmb3IgMzAgZGF5c1xuICAgICAgICAgICAgICAgICAgYC0tcmV0ZW50aW9uLnJlc29sdXRpb24tNW09JHtjb25maWcucmV0ZW50aW9uLnByb21ldGhldXNTMzVtfWRgLCAvLyBLZWVwIDVtIGRhdGEgZm9yIDE4MCBkYXlzICg2IG1vbnRocylcbiAgICAgICAgICAgICAgICAgIGAtLXJldGVudGlvbi5yZXNvbHV0aW9uLTFoPSR7Y29uZmlnLnJldGVudGlvbi5wcm9tZXRoZXVzUzMxaH1kYCwgLy8gS2VlcCAxaCBkYXRhIGZvciA3MzAgZGF5cyAoMiB5ZWFycylcbiAgICAgICAgICAgICAgICAgIC8vIENvbXBhY3Rpb24gY29uZmlndXJhdGlvblxuICAgICAgICAgICAgICAgICAgJy0tY29tcGFjdC5jb25jdXJyZW5jeT0xJyxcbiAgICAgICAgICAgICAgICAgICctLWRlbGV0ZS1kZWxheT00OGgnLCAvLyBXYWl0IDQ4aCBiZWZvcmUgZGVsZXRpbmcgYmxvY2tzIChzYWZldHkgbWFyZ2luKVxuICAgICAgICAgICAgICAgIF0sXG4gICAgICAgICAgICAgICAgcG9ydHM6IFtcbiAgICAgICAgICAgICAgICAgIHtcbiAgICAgICAgICAgICAgICAgICAgbmFtZTogJ2h0dHAnLFxuICAgICAgICAgICAgICAgICAgICBjb250YWluZXJQb3J0OiAxMDkwMixcbiAgICAgICAgICAgICAgICAgIH0sXG4gICAgICAgICAgICAgICAgXSxcbiAgICAgICAgICAgICAgICB2b2x1bWVNb3VudHM6IFtcbiAgICAgICAgICAgICAgICAgIHtcbiAgICAgICAgICAgICAgICAgICAgbmFtZTogJ29ianN0b3JlLWNvbmZpZycsXG4gICAgICAgICAgICAgICAgICAgIG1vdW50UGF0aDogJy9ldGMvdGhhbm9zJyxcbiAgICAgICAgICAgICAgICAgICAgcmVhZE9ubHk6IHRydWUsXG4gICAgICAgICAgICAgICAgICB9LFxuICAgICAgICAgICAgICAgICAge1xuICAgICAgICAgICAgICAgICAgICBuYW1lOiAnZGF0YScsXG4gICAgICAgICAgICAgICAgICAgIG1vdW50UGF0aDogJy92YXIvdGhhbm9zL2NvbXBhY3RvcicsXG4gICAgICAgICAgICAgICAgICB9LFxuICAgICAgICAgICAgICAgIF0sXG4gICAgICAgICAgICAgICAgbGl2ZW5lc3NQcm9iZToge1xuICAgICAgICAgICAgICAgICAgaHR0cEdldDoge1xuICAgICAgICAgICAgICAgICAgICBwYXRoOiAnLy0vaGVhbHRoeScsXG4gICAgICAgICAgICAgICAgICAgIHBvcnQ6IEludE9yU3RyaW5nLmZyb21TdHJpbmcoJ2h0dHAnKSxcbiAgICAgICAgICAgICAgICAgIH0sXG4gICAgICAgICAgICAgICAgICBpbml0aWFsRGVsYXlTZWNvbmRzOiAzMCxcbiAgICAgICAgICAgICAgICAgIHBlcmlvZFNlY29uZHM6IDMwLFxuICAgICAgICAgICAgICAgIH0sXG4gICAgICAgICAgICAgICAgcmVhZGluZXNzUHJvYmU6IHtcbiAgICAgICAgICAgICAgICAgIGh0dHBHZXQ6IHtcbiAgICAgICAgICAgICAgICAgICAgcGF0aDogJy8tL3JlYWR5JyxcbiAgICAgICAgICAgICAgICAgICAgcG9ydDogSW50T3JTdHJpbmcuZnJvbVN0cmluZygnaHR0cCcpLFxuICAgICAgICAgICAgICAgICAgfSxcbiAgICAgICAgICAgICAgICAgIGluaXRpYWxEZWxheVNlY29uZHM6IDMwLFxuICAgICAgICAgICAgICAgICAgcGVyaW9kU2Vjb25kczogNSxcbiAgICAgICAgICAgICAgICB9LFxuICAgICAgICAgICAgICAgIHJlc291cmNlczoge1xuICAgICAgICAgICAgICAgICAgcmVxdWVzdHM6IHtcbiAgICAgICAgICAgICAgICAgICAgY3B1OiBRdWFudGl0eS5mcm9tU3RyaW5nKGNvbmZpZy5yZXNvdXJjZXMudGhhbm9zQ29tcGFjdG9yLnJlcXVlc3RzLmNwdSksXG4gICAgICAgICAgICAgICAgICAgIG1lbW9yeTogUXVhbnRpdHkuZnJvbVN0cmluZyhjb25maWcucmVzb3VyY2VzLnRoYW5vc0NvbXBhY3Rvci5yZXF1ZXN0cy5tZW1vcnkpLFxuICAgICAgICAgICAgICAgICAgfSxcbiAgICAgICAgICAgICAgICAgIGxpbWl0czoge1xuICAgICAgICAgICAgICAgICAgICBjcHU6IFF1YW50aXR5LmZyb21TdHJpbmcoY29uZmlnLnJlc291cmNlcy50aGFub3NDb21wYWN0b3IubGltaXRzLmNwdSksXG4gICAgICAgICAgICAgICAgICAgIG1lbW9yeTogUXVhbnRpdHkuZnJvbVN0cmluZyhjb25maWcucmVzb3VyY2VzLnRoYW5vc0NvbXBhY3Rvci5saW1pdHMubWVtb3J5KSxcbiAgICAgICAgICAgICAgICAgIH0sXG4gICAgICAgICAgICAgICAgfSxcbiAgICAgICAgICAgICAgfSxcbiAgICAgICAgICAgIF0sXG5cbiAgICAgICAgICAgIHZvbHVtZXM6IFtcbiAgICAgICAgICAgICAge1xuICAgICAgICAgICAgICAgIG5hbWU6ICdvYmpzdG9yZS1jb25maWcnLFxuICAgICAgICAgICAgICAgIHNlY3JldDoge1xuICAgICAgICAgICAgICAgICAgc2VjcmV0TmFtZTogJ3RoYW5vcy1vYmpzdG9yZS1jb25maWcnLFxuICAgICAgICAgICAgICAgIH0sXG4gICAgICAgICAgICAgIH0sXG4gICAgICAgICAgICBdLFxuXG4gICAgICAgICAgICBwcmlvcml0eUNsYXNzTmFtZTogJ2hpZ2gtcHJpb3JpdHknLFxuICAgICAgICAgIH0sXG4gICAgICAgIH0sXG4gICAgICAgIHZvbHVtZUNsYWltVGVtcGxhdGVzOiBbXG4gICAgICAgICAge1xuICAgICAgICAgICAgbWV0YWRhdGE6IHtcbiAgICAgICAgICAgICAgbmFtZTogJ2RhdGEnLFxuICAgICAgICAgICAgfSxcbiAgICAgICAgICAgIHNwZWM6IHtcbiAgICAgICAgICAgICAgYWNjZXNzTW9kZXM6IFsnUmVhZFdyaXRlT25jZSddLFxuICAgICAgICAgICAgICBzdG9yYWdlQ2xhc3NOYW1lOiAnbG9uZ2hvcm4nLFxuICAgICAgICAgICAgICByZXNvdXJjZXM6IHtcbiAgICAgICAgICAgICAgICByZXF1ZXN0czoge1xuICAgICAgICAgICAgICAgICAgc3RvcmFnZTogUXVhbnRpdHkuZnJvbVN0cmluZyhjb25maWcuc3RvcmFnZS50aGFub3NDb21wYWN0b3IpLCAvLyBXb3JraW5nIGRpcmVjdG9yeSBmb3IgY29tcGFjdGlvbiBvcGVyYXRpb25zXG4gICAgICAgICAgICAgICAgfSxcbiAgICAgICAgICAgICAgfSxcbiAgICAgICAgICAgIH0sXG4gICAgICAgICAgfSxcbiAgICAgICAgXSxcbiAgICAgIH0sXG4gICAgfSk7XG5cbiAgICAvLyBDcmVhdGUgSFRUUCBTZXJ2aWNlIChmb3IgbWV0cmljcy9kZWJ1Z2dpbmcpXG4gICAgbmV3IEt1YmVTZXJ2aWNlKHRoaXMsICdzZXJ2aWNlJywge1xuICAgICAgbWV0YWRhdGE6IHtcbiAgICAgICAgbmFtZTogJ3RoYW5vcy1jb21wYWN0b3InLFxuICAgICAgICBuYW1lc3BhY2U6IG5hbWVzcGFjZSxcbiAgICAgICAgbGFiZWxzOiB7XG4gICAgICAgICAgJ2FwcC5rdWJlcm5ldGVzLmlvL25hbWUnOiAndGhhbm9zLWNvbXBhY3RvcicsXG4gICAgICAgICAgJ2FwcC5rdWJlcm5ldGVzLmlvL21hbmFnZWQtYnknOiAnY2RrOHMnLFxuICAgICAgICB9LFxuICAgICAgICBhbm5vdGF0aW9uczoge1xuICAgICAgICAgICdhcmdvY2QuYXJnb3Byb2ouaW8vc3luYy13YXZlJzogJzMnLFxuICAgICAgICB9LFxuICAgICAgfSxcbiAgICAgIHNwZWM6IHtcbiAgICAgICAgcG9ydHM6IFtcbiAgICAgICAgICB7XG4gICAgICAgICAgICBuYW1lOiAnaHR0cCcsXG4gICAgICAgICAgICBwb3J0OiAxMDkwMixcbiAgICAgICAgICAgIHRhcmdldFBvcnQ6ICdodHRwJyBhcyBhbnksXG4gICAgICAgICAgICBwcm90b2NvbDogJ1RDUCcsXG4gICAgICAgICAgfSxcbiAgICAgICAgXSxcbiAgICAgICAgc2VsZWN0b3I6IHtcbiAgICAgICAgICAnYXBwLmt1YmVybmV0ZXMuaW8vbmFtZSc6ICd0aGFub3MtY29tcGFjdG9yJyxcbiAgICAgICAgfSxcbiAgICAgIH0sXG4gICAgfSk7XG4gIH1cbn1cbiJdfQ==
@@ -0,0 +1,30 @@
1
+ import { Construct } from 'constructs';
2
+ import { MonitoringConfig } from '../types';
3
+ export interface ThanosQueryProps {
4
+ namespace: string;
5
+ config: MonitoringConfig;
6
+ }
7
+ /**
8
+ * Creates Thanos Query Deployment and Services.
9
+ *
10
+ * Thanos Query provides a unified query interface for:
11
+ * - Local Prometheus data (3-day retention)
12
+ * - Historical S3 data (via Thanos Store Gateway)
13
+ * - Automatic deduplication across Prometheus replicas
14
+ *
15
+ * Components:
16
+ * - Deployment (2 replicas with anti-affinity)
17
+ * - HTTP Service (port 9090 for Grafana queries)
18
+ * - gRPC Service (headless, for future Query Frontend)
19
+ *
20
+ * Prerequisites:
21
+ * - Namespace exists
22
+ * - PriorityClass 'high-priority' exists
23
+ * - Prometheus with Thanos sidecar running
24
+ * - Thanos Store Gateway running
25
+ *
26
+ * Sync Wave: 3 (query layer - after Prometheus and Store)
27
+ */
28
+ export declare class ThanosQueryConstruct extends Construct {
29
+ constructor(scope: Construct, id: string, props: ThanosQueryProps);
30
+ }
@@ -0,0 +1,205 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.ThanosQueryConstruct = void 0;
4
+ const constructs_1 = require("constructs");
5
+ const k8s_1 = require("../imports/k8s");
6
+ /**
7
+ * Creates Thanos Query Deployment and Services.
8
+ *
9
+ * Thanos Query provides a unified query interface for:
10
+ * - Local Prometheus data (3-day retention)
11
+ * - Historical S3 data (via Thanos Store Gateway)
12
+ * - Automatic deduplication across Prometheus replicas
13
+ *
14
+ * Components:
15
+ * - Deployment (2 replicas with anti-affinity)
16
+ * - HTTP Service (port 9090 for Grafana queries)
17
+ * - gRPC Service (headless, for future Query Frontend)
18
+ *
19
+ * Prerequisites:
20
+ * - Namespace exists
21
+ * - PriorityClass 'high-priority' exists
22
+ * - Prometheus with Thanos sidecar running
23
+ * - Thanos Store Gateway running
24
+ *
25
+ * Sync Wave: 3 (query layer - after Prometheus and Store)
26
+ */
27
+ class ThanosQueryConstruct extends constructs_1.Construct {
28
+ constructor(scope, id, props) {
29
+ super(scope, id);
30
+ const { namespace, config } = props;
31
+ // Create Deployment
32
+ // Wave 3: Query Layer - after Prometheus and Store are ready
33
+ new k8s_1.KubeDeployment(this, 'deployment', {
34
+ metadata: {
35
+ name: 'thanos-query',
36
+ namespace: namespace,
37
+ labels: {
38
+ 'app.kubernetes.io/name': 'thanos-query',
39
+ 'app.kubernetes.io/component': 'query',
40
+ 'app.kubernetes.io/managed-by': 'cdk8s',
41
+ 'app.kubernetes.io/part-of': 'monitoring',
42
+ },
43
+ annotations: {
44
+ 'argocd.argoproj.io/sync-wave': '3',
45
+ },
46
+ },
47
+ spec: {
48
+ replicas: config.replicas.thanosQuery,
49
+ selector: {
50
+ matchLabels: {
51
+ 'app.kubernetes.io/name': 'thanos-query',
52
+ },
53
+ },
54
+ template: {
55
+ metadata: {
56
+ labels: {
57
+ 'app.kubernetes.io/name': 'thanos-query',
58
+ 'app.kubernetes.io/component': 'query',
59
+ },
60
+ },
61
+ spec: {
62
+ // No arch nodeSelector: Thanos images are multi-arch; let the
63
+ // scheduler place these on any worker (legacy ARM64 pin removed).
64
+ // Spread replicas across different nodes for HA
65
+ affinity: {
66
+ podAntiAffinity: {
67
+ preferredDuringSchedulingIgnoredDuringExecution: [
68
+ {
69
+ weight: 100,
70
+ podAffinityTerm: {
71
+ labelSelector: {
72
+ matchLabels: {
73
+ 'app.kubernetes.io/name': 'thanos-query',
74
+ },
75
+ },
76
+ topologyKey: 'kubernetes.io/hostname',
77
+ },
78
+ },
79
+ ],
80
+ },
81
+ },
82
+ containers: [
83
+ {
84
+ name: 'thanos-query',
85
+ image: `quay.io/thanos/thanos:${config.versions.thanos}`,
86
+ args: [
87
+ 'query',
88
+ '--log.level=info',
89
+ '--query.replica-label=replica',
90
+ '--query.replica-label=prometheus_replica',
91
+ // Connect to Prometheus sidecars via gRPC.
92
+ // The sidecar gRPC port is exposed by the operator's thanos
93
+ // discovery service (thanosService.enabled=true), NOT by
94
+ // prometheus-operated (which only exposes http-web:9090).
95
+ `--endpoint=dnssrv+_grpc._tcp.kube-prometheus-stack-thanos-discovery.${namespace}.svc.cluster.local`,
96
+ // Connect to Thanos Store Gateway
97
+ `--endpoint=dnssrv+_grpc._tcp.thanos-store-grpc.${namespace}.svc.cluster.local`,
98
+ ],
99
+ ports: [
100
+ {
101
+ name: 'http',
102
+ containerPort: 10902,
103
+ },
104
+ {
105
+ name: 'grpc',
106
+ containerPort: 10901,
107
+ },
108
+ ],
109
+ livenessProbe: {
110
+ httpGet: {
111
+ path: '/-/healthy',
112
+ port: k8s_1.IntOrString.fromNumber(10902), // HTTP port (named 'http' in ports list)
113
+ },
114
+ initialDelaySeconds: 10,
115
+ periodSeconds: 30,
116
+ },
117
+ readinessProbe: {
118
+ httpGet: {
119
+ path: '/-/ready',
120
+ port: k8s_1.IntOrString.fromNumber(10902), // HTTP port (named 'http' in ports list)
121
+ },
122
+ initialDelaySeconds: 15,
123
+ periodSeconds: 5,
124
+ },
125
+ resources: {
126
+ requests: {
127
+ cpu: k8s_1.Quantity.fromString(config.resources.thanosQuery.requests.cpu),
128
+ memory: k8s_1.Quantity.fromString(config.resources.thanosQuery.requests.memory),
129
+ },
130
+ limits: {
131
+ cpu: k8s_1.Quantity.fromString(config.resources.thanosQuery.limits.cpu),
132
+ memory: k8s_1.Quantity.fromString(config.resources.thanosQuery.limits.memory),
133
+ },
134
+ },
135
+ },
136
+ ],
137
+ priorityClassName: 'high-priority',
138
+ },
139
+ },
140
+ },
141
+ });
142
+ // Create HTTP Service (for Grafana)
143
+ new k8s_1.KubeService(this, 'service-http', {
144
+ metadata: {
145
+ name: 'thanos-query',
146
+ namespace: namespace,
147
+ labels: {
148
+ 'app.kubernetes.io/name': 'thanos-query',
149
+ 'app.kubernetes.io/managed-by': 'cdk8s',
150
+ },
151
+ annotations: {
152
+ 'argocd.argoproj.io/sync-wave': '3',
153
+ },
154
+ },
155
+ spec: {
156
+ ports: [
157
+ {
158
+ name: 'http',
159
+ port: 9090,
160
+ // Container http port is 10902. A bare string is dropped by cdk8s
161
+ // (targetPort expects IntOrString), which silently defaulted
162
+ // targetPort to 9090 and made the Service refuse connections.
163
+ targetPort: k8s_1.IntOrString.fromString('http'),
164
+ protocol: 'TCP',
165
+ },
166
+ ],
167
+ selector: {
168
+ 'app.kubernetes.io/name': 'thanos-query',
169
+ },
170
+ sessionAffinity: 'ClientIP',
171
+ },
172
+ });
173
+ // Create gRPC Service (headless, for future Query Frontend)
174
+ new k8s_1.KubeService(this, 'service-grpc', {
175
+ metadata: {
176
+ name: 'thanos-query-grpc',
177
+ namespace: namespace,
178
+ labels: {
179
+ 'app.kubernetes.io/name': 'thanos-query',
180
+ 'app.kubernetes.io/managed-by': 'cdk8s',
181
+ },
182
+ annotations: {
183
+ 'argocd.argoproj.io/sync-wave': '3',
184
+ },
185
+ },
186
+ spec: {
187
+ type: 'ClusterIP',
188
+ clusterIp: 'None', // Headless service for DNS-based discovery
189
+ ports: [
190
+ {
191
+ name: 'grpc',
192
+ port: 10901,
193
+ targetPort: k8s_1.IntOrString.fromString('grpc'),
194
+ protocol: 'TCP',
195
+ },
196
+ ],
197
+ selector: {
198
+ 'app.kubernetes.io/name': 'thanos-query',
199
+ },
200
+ },
201
+ });
202
+ }
203
+ }
204
+ exports.ThanosQueryConstruct = ThanosQueryConstruct;
205
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoidGhhbm9zLXF1ZXJ5LmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vc3JjL2NvbnN0cnVjdHMvdGhhbm9zLXF1ZXJ5LnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7OztBQUFBLDJDQUF1QztBQUN2Qyx3Q0FBb0Y7QUFRcEY7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7O0dBb0JHO0FBQ0gsTUFBYSxvQkFBcUIsU0FBUSxzQkFBUztJQUNqRCxZQUFZLEtBQWdCLEVBQUUsRUFBVSxFQUFFLEtBQXVCO1FBQy9ELEtBQUssQ0FBQyxLQUFLLEVBQUUsRUFBRSxDQUFDLENBQUM7UUFFakIsTUFBTSxFQUFFLFNBQVMsRUFBRSxNQUFNLEVBQUUsR0FBRyxLQUFLLENBQUM7UUFFcEMsb0JBQW9CO1FBQ3BCLDZEQUE2RDtRQUM3RCxJQUFJLG9CQUFjLENBQUMsSUFBSSxFQUFFLFlBQVksRUFBRTtZQUNyQyxRQUFRLEVBQUU7Z0JBQ1IsSUFBSSxFQUFFLGNBQWM7Z0JBQ3BCLFNBQVMsRUFBRSxTQUFTO2dCQUNwQixNQUFNLEVBQUU7b0JBQ04sd0JBQXdCLEVBQUUsY0FBYztvQkFDeEMsNkJBQTZCLEVBQUUsT0FBTztvQkFDdEMsOEJBQThCLEVBQUUsT0FBTztvQkFDdkMsMkJBQTJCLEVBQUUsWUFBWTtpQkFDMUM7Z0JBQ0QsV0FBVyxFQUFFO29CQUNYLDhCQUE4QixFQUFFLEdBQUc7aUJBQ3BDO2FBQ0Y7WUFDRCxJQUFJLEVBQUU7Z0JBQ0osUUFBUSxFQUFFLE1BQU0sQ0FBQyxRQUFRLENBQUMsV0FBVztnQkFDckMsUUFBUSxFQUFFO29CQUNSLFdBQVcsRUFBRTt3QkFDWCx3QkFBd0IsRUFBRSxjQUFjO3FCQUN6QztpQkFDRjtnQkFDRCxRQUFRLEVBQUU7b0JBQ1IsUUFBUSxFQUFFO3dCQUNSLE1BQU0sRUFBRTs0QkFDTix3QkFBd0IsRUFBRSxjQUFjOzRCQUN4Qyw2QkFBNkIsRUFBRSxPQUFPO3lCQUN2QztxQkFDRjtvQkFDRCxJQUFJLEVBQUU7d0JBQ0osOERB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LElBQUksRUFBRSxJQUFJO3dCQUNWLGtFQUFrRTt3QkFDbEUsNkRBQTZEO3dCQUM3RCw4REFBOEQ7d0JBQzlELFVBQVUsRUFBRSxpQkFBVyxDQUFDLFVBQVUsQ0FBQyxNQUFNLENBQUM7d0JBQzFDLFFBQVEsRUFBRSxLQUFLO3FCQUNoQjtpQkFDRjtnQkFDRCxRQUFRLEVBQUU7b0JBQ1Isd0JBQXdCLEVBQUUsY0FBYztpQkFDekM7Z0JBQ0QsZUFBZSxFQUFFLFVBQVU7YUFDNUI7U0FDRixDQUFDLENBQUM7UUFFSCw0REFBNEQ7UUFDNUQsSUFBSSxpQkFBVyxDQUFDLElBQUksRUFBRSxjQUFjLEVBQUU7WUFDcEMsUUFBUSxFQUFFO2dCQUNSLElBQUksRUFBRSxtQkFBbUI7Z0JBQ3pCLFNBQVMsRUFBRSxTQUFTO2dCQUNwQixNQUFNLEVBQUU7b0JBQ04sd0JBQXdCLEVBQUUsY0FBYztvQkFDeEMsOEJBQThCLEVBQUUsT0FBTztpQkFDeEM7Z0JBQ0QsV0FBVyxFQUFFO29CQUNYLDhCQUE4QixFQUFFLEdBQUc7aUJBQ3BDO2FBQ0Y7WUFDRCxJQUFJLEVBQUU7Z0JBQ0osSUFBSSxFQUFFLFdBQVc7Z0JBQ2pCLFNBQVMsRUFBRSxNQUFNLEVBQUUsMkNBQTJDO2dCQUM5RCxLQUFLLEVBQUU7b0JBQ0w7d0JBQ0UsSUFBSSxFQUFFLE1BQU07d0JBQ1osSUFBSSxFQUFFLEtBQUs7d0JBQ1gsVUFBVSxFQUFFLGlCQUFXLENBQUMsVUFBVSxDQUFDLE1BQU0sQ0FBQzt3QkFDMUMsUUFBUSxFQUFFLEtBQUs7cUJBQ2hCO2lCQUNGO2dCQUNELFFBQVEsRUFBRTtvQkFDUix3QkFBd0IsRUFBRSxjQUFjO2lCQUN6QzthQUNGO1NBQ0YsQ0FBQyxDQUFDO0lBQ0wsQ0FBQztDQUNGO0FBdkxELG9EQXVMQyIsInNvdXJjZXNDb250ZW50IjpbImltcG9ydCB7IENvbnN0cnVjdCB9IGZyb20gJ2NvbnN0cnVjdHMnO1xuaW1wb3J0IHsgS3ViZURlcGxveW1lbnQsIEt1YmVTZXJ2aWNlLCBRdWFudGl0eSwgSW50T3JTdHJpbmcgfSBmcm9tICcuLi9pbXBvcnRzL2s4cyc7XG5pbXBvcnQgeyBNb25pdG9yaW5nQ29uZmlnIH0gZnJvbSAnLi4vdHlwZXMnO1xuXG5leHBvcnQgaW50ZXJmYWNlIFRoYW5vc1F1ZXJ5UHJvcHMge1xuICBuYW1lc3BhY2U6IHN0cmluZztcbiAgY29uZmlnOiBNb25pdG9yaW5nQ29uZmlnO1xufVxuXG4vKipcbiAqIENyZWF0ZXMgVGhhbm9zIFF1ZXJ5IERlcGxveW1lbnQgYW5kIFNlcnZpY2VzLlxuICpcbiAqIFRoYW5vcyBRdWVyeSBwcm92aWRlcyBhIHVuaWZpZWQgcXVlcnkgaW50ZXJmYWNlIGZvcjpcbiAqIC0gTG9jYWwgUHJvbWV0aGV1cyBkYXRhICgzLWRheSByZXRlbnRpb24pXG4gKiAtIEhpc3RvcmljYWwgUzMgZGF0YSAodmlhIFRoYW5vcyBTdG9yZSBHYXRld2F5KVxuICogLSBBdXRvbWF0aWMgZGVkdXBsaWNhdGlvbiBhY3Jvc3MgUHJvbWV0aGV1cyByZXBsaWNhc1xuICpcbiAqIENvbXBvbmVudHM6XG4gKiAtIERlcGxveW1lbnQgKDIgcmVwbGljYXMgd2l0aCBhbnRpLWFmZmluaXR5KVxuICogLSBIVFRQIFNlcnZpY2UgKHBvcnQgOTA5MCBmb3IgR3JhZmFuYSBxdWVyaWVzKVxuICogLSBnUlBDIFNlcnZpY2UgKGhlYWRsZXNzLCBmb3IgZnV0dXJlIFF1ZXJ5IEZyb250ZW5kKVxuICpcbiAqIFByZXJlcXVpc2l0ZXM6XG4gKiAtIE5hbWVzcGFjZSBleGlzdHNcbiAqIC0gUHJpb3JpdHlDbGFzcyAnaGlnaC1wcmlvcml0eScgZXhpc3RzXG4gKiAtIFByb21ldGhldXMgd2l0aCBUaGFub3Mgc2lkZWNhciBydW5uaW5nXG4gKiAtIFRoYW5vcyBTdG9yZSBHYXRld2F5IHJ1bm5pbmdcbiAqXG4gKiBTeW5jIFdhdmU6IDMgKHF1ZXJ5IGxheWVyIC0gYWZ0ZXIgUHJvbWV0aGV1cyBhbmQgU3RvcmUpXG4gKi9cbmV4cG9ydCBjbGFzcyBUaGFub3NRdWVyeUNvbnN0cnVjdCBleHRlbmRzIENvbnN0cnVjdCB7XG4gIGNvbnN0cnVjdG9yKHNjb3BlOiBDb25zdHJ1Y3QsIGlkOiBzdHJpbmcsIHByb3BzOiBUaGFub3NRdWVyeVByb3BzKSB7XG4gICAgc3VwZXIoc2NvcGUsIGlkKTtcblxuICAgIGNvbnN0IHsgbmFtZXNwYWNlLCBjb25maWcgfSA9IHByb3BzO1xuXG4gICAgLy8gQ3JlYXRlIERlcGxveW1lbnRcbiAgICAvLyBXYXZlIDM6IFF1ZXJ5IExheWVyIC0gYWZ0ZXIgUHJvbWV0aGV1cyBhbmQgU3RvcmUgYXJlIHJlYWR5XG4gICAgbmV3IEt1YmVEZXBsb3ltZW50KHRoaXMsICdkZXBsb3ltZW50Jywge1xuICAgICAgbWV0YWRhdGE6IHtcbiAgICAgICAgbmFtZTogJ3RoYW5vcy1xdWVyeScsXG4gICAgICAgIG5hbWVzcGFjZTogbmFtZXNwYWNlLFxuICAgICAgICBsYWJlbHM6IHtcbiAgICAgICAgICAnYXBwLmt1YmVybmV0ZXMuaW8vbmFtZSc6ICd0aGFub3MtcXVlcnknLFxuICAgICAgICAgICdhcHAua3ViZXJuZXRlcy5pby9jb21wb25lbnQnOiAncXVlcnknLFxuICAgICAgICAgICdhcHAua3ViZXJuZXRlcy5pby9tYW5hZ2VkLWJ5JzogJ2NkazhzJyxcbiAgICAgICAgICAnYXBwLmt1YmVybmV0ZXMuaW8vcGFydC1vZic6ICdtb25pdG9yaW5nJyxcbiAgICAgICAgfSxcbiAgICAgICAgYW5ub3RhdGlvbnM6IHtcbiAgICAgICAgICAnYXJnb2NkLmFyZ29wcm9qLmlvL3N5bmMtd2F2ZSc6ICczJyxcbiAgICAgICAgfSxcbiAgICAgIH0sXG4gICAgICBzcGVjOiB7XG4gICAgICAgIHJlcGxpY2FzOiBjb25maWcucmVwbGljYXMudGhhbm9zUXVlcnksXG4gICAgICAgIHNlbGVjdG9yOiB7XG4gICAgICAgICAgbWF0Y2hMYWJlbHM6IHtcbiAgICAgICAgICAgICdhcHAua3ViZXJuZXRlcy5pby9uYW1lJzogJ3RoYW5vcy1xdWVyeScsXG4gICAgICAgICAgfSxcbiAgICAgICAgfSxcbiAgICAgICAgdGVtcGxhdGU6IHtcbiAgICAgICAgICBtZXRhZGF0YToge1xuICAgICAgICAgICAgbGFiZWxzOiB7XG4gICAgICAgICAgICAgICdhcHAua3ViZXJuZXRlcy5pby9uYW1lJzogJ3RoYW5vcy1xdWVyeScsXG4gICAgICAgICAgICAgICdhcHAua3ViZXJuZXRlcy5pby9jb21wb25lbnQnOiAncXVlcnknLFxuICAgICAgICAgICAgfSxcbiAgICAgICAgICB9LFxuICAgICAgICAgIHNwZWM6IHtcbiAgICAgICAgICAgIC8vIE5vIGFyY2ggbm9kZVNlbGVjdG9yOiBUaGFub3MgaW1hZ2VzIGFyZSBtdWx0aS1hcmNoOyBsZXQgdGhlXG4gICAgICAgICAgICAvLyBzY2hlZHVsZXIgcGxhY2UgdGhlc2Ugb24gYW55IHdvcmtlciAobGVnYWN5IEFSTTY0IHBpbiByZW1vdmVkKS5cblxuICAgICAgICAgICAgLy8gU3ByZWFkIHJlcGxpY2FzIGFjcm9zcyBkaWZmZXJlbnQgbm9kZXMgZm9yIEhBXG4gICAgICAgICAgICBhZmZpbml0eToge1xuICAgICAgICAgICAgICBwb2RBbnRpQWZmaW5pdHk6IHtcbiAgICAgICAgICAgICAgICBwcmVmZXJyZWREdXJpbmdTY2hlZHVsaW5nSWdub3JlZER1cmluZ0V4ZWN1dGlvbjogW1xuICAgICAgICAgICAgICAgICAge1xuICAgICAgICAgICAgICAgICAgICB3ZWlnaHQ6IDEwMCxcbiAgICAgICAgICAgICAgICAgICAgcG9kQWZmaW5pdHlUZXJtOiB7XG4gICAgICAgICAgICAgICAgICAgICAgbGFiZWxTZWxlY3Rvcjoge1xuICAgICAgICAgICAgICAgICAgICAgICAgbWF0Y2hMYWJlbHM6IHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgJ2FwcC5rdWJlcm5ldGVzLmlvL25hbWUnOiAndGhhbm9zLXF1ZXJ5JyxcbiAgICAgICAgICAgICAgICAgICAgICAgIH0sXG4gICAgICAgICAgICAgICAgICAgICAgfSxcbiAgICAgICAgICAgICAgICAgICAgICB0b3BvbG9neUtleTogJ2t1YmVybmV0ZXMuaW8vaG9zdG5hbWUnLFxuICAgICAgICAgICAgICAgICAgICB9LFxuICAgICAgICAgICAgICAgICAgfSxcbiAgICAgICAgICAgICAgICBdLFxuICAgICAgICAgICAgICB9LFxuICAgICAgICAgICAgfSxcblxuICAgICAgICAgICAgY29udGFpbmVyczogW1xuICAgICAgICAgICAgICB7XG4gICAgICAgICAgICAgICAgbmFtZTogJ3RoYW5vcy1xdWVyeScsXG4gICAgICAgICAgICAgICAgaW1hZ2U6IGBxdWF5LmlvL3RoYW5vcy90aGFub3M6JHtjb25maWcudmVyc2lvbnMudGhhbm9zfWAsXG4gICAgICAgICAgICAgICAgYXJnczogW1xuICAgICAgICAgICAgICAgICAgJ3F1ZXJ5JyxcbiAgICAgICAgICAgICAgICAgICctLWxvZy5sZXZlbD1pbmZvJyxcbiAgICAgICAgICAgICAgICAgICctLXF1ZXJ5LnJlcGxpY2EtbGFiZWw9cmVwbGljYScsXG4gICAgICAgICAgICAgICAgICAnLS1xdWVyeS5yZXBsaWNhLWxhYmVsPXByb21ldGhldXNfcmVwbGljYScsXG4gICAgICAgICAgICAgICAgICAvLyBDb25uZWN0IHRvIFByb21ldGhldXMgc2lkZWNhcnMgdmlhIGdSUEMuXG4gICAgICAgICAgICAgICAgICAvLyBUaGUgc2lkZWNhciBnUlBDIHBvcnQgaXMgZXhwb3NlZCBieSB0aGUgb3BlcmF0b3IncyB0aGFub3NcbiAgICAgICAgICAgICAgICAgIC8vIGRpc2NvdmVyeSBzZXJ2aWNlICh0aGFub3NTZXJ2aWNlLmVuYWJsZWQ9dHJ1ZSksIE5PVCBieVxuICAgICAgICAgICAgICAgICAgLy8gcHJvbWV0aGV1cy1vcGVyYXRlZCAod2hpY2ggb25seSBleHBvc2VzIGh0dHAtd2ViOjkwOTApLlxuICAgICAgICAgICAgICAgICAgYC0tZW5kcG9pbnQ9ZG5zc3J2K19ncnBjLl90Y3Aua3ViZS1wcm9tZXRoZXVzLXN0YWNrLXRoYW5vcy1kaXNjb3ZlcnkuJHtuYW1lc3BhY2V9LnN2Yy5jbHVzdGVyLmxvY2FsYCxcbiAgICAgICAgICAgICAgICAgIC8vIENvbm5lY3QgdG8gVGhhbm9zIFN0b3JlIEdhdGV3YXlcbiAgICAgICAgICAgICAgICAgIGAtLWVuZHBvaW50PWRuc3NyditfZ3JwYy5fdGNwLnRoYW5vcy1zdG9yZS1ncnBjLiR7bmFtZXNwYWNlfS5zdmMuY2x1c3Rlci5sb2NhbGAsXG4gICAgICAgICAgICAgICAgXSxcbiAgICAgICAgICAgICAgICBwb3J0czogW1xuICAgICAgICAgICAgICAgICAge1xuICAgICAgICAgICAgICAgICAgICBuYW1lOiAnaHR0cCcsXG4gICAgICAgICAgICAgICAgICAgIGNvbnRhaW5lclBvcnQ6IDEwOTAyLFxuICAgICAgICAgICAgICAgICAgfSxcbiAgICAgICAgICAgICAgICAgIHtcbiAgICAgICAgICAgICAgICAgICAgbmFtZTogJ2dycGMnLFxuICAgICAgICAgICAgICAgICAgICBjb250YWluZXJQb3J0OiAxMDkwMSxcbiAgICAgICAgICAgICAgICAgIH0sXG4gICAgICAgICAgICAgICAgXSxcbiAgICAgICAgICAgICAgICBsaXZlbmVzc1Byb2JlOiB7XG4gICAgICAgICAgICAgICAgICBodHRwR2V0OiB7XG4gICAgICAgICAgICAgICAgICAgIHBhdGg6ICcvLS9oZWFsdGh5JyxcbiAgICAgICAgICAgICAgICAgICAgcG9ydDogSW50T3JTdHJpbmcuZnJvbU51bWJlcigxMDkwMiksIC8vIEhUVFAgcG9ydCAobmFtZWQgJ2h0dHAnIGluIHBvcnRzIGxpc3QpXG4gICAgICAgICAgICAgICAgICB9LFxuICAgICAgICAgICAgICAgICAgaW5pdGlhbERlbGF5U2Vjb25kczogMTAsXG4gICAgICAgICAgICAgICAgICBwZXJpb2RTZWNvbmRzOiAzMCxcbiAgICAgICAgICAgICAgICB9LFxuICAgICAgICAgICAgICAgIHJlYWRpbmVzc1Byb2JlOiB7XG4gICAgICAgICAgICAgICAgICBodHRwR2V0OiB7XG4gICAgICAgICAgICAgICAgICAgIHBhdGg6ICcvLS9yZWFkeScsXG4gICAgICAgICAgICAgICAgICAgIHBvcnQ6IEludE9yU3RyaW5nLmZyb21OdW1iZXIoMTA5MDIpLCAvLyBIVFRQIHBvcnQgKG5hbWVkICdodHRwJyBpbiBwb3J0cyBsaXN0KVxuICAgICAgICAgICAgICAgICAgfSxcbiAgICAgICAgICAgICAgICAgIGluaXRpYWxEZWxheVNlY29uZHM6IDE1LFxuICAgICAgICAgICAgICAgICAgcGVyaW9kU2Vjb25kczogNSxcbiAgICAgICAgICAgICAgICB9LFxuICAgICAgICAgICAgICAgIHJlc291cmNlczoge1xuICAgICAgICAgICAgICAgICAgcmVxdWVzdHM6IHtcbiAgICAgICAgICAgICAgICAgICAgY3B1OiBRdWFudGl0eS5mcm9tU3RyaW5nKGNvbmZpZy5yZXNvdXJjZXMudGhhbm9zUXVlcnkucmVxdWVzdHMuY3B1KSxcbiAgICAgICAgICAgICAgICAgICAgbWVtb3J5OiBRdWFudGl0eS5mcm9tU3RyaW5nKGNvbmZpZy5yZXNvdXJjZXMudGhhbm9zUXVlcnkucmVxdWVzdHMubWVtb3J5KSxcbiAgICAgICAgICAgICAgICAgIH0sXG4gICAgICAgICAgICAgICAgICBsaW1pdHM6IHtcbiAgICAgICAgICAgICAgICAgICAgY3B1OiBRdWFudGl0eS5mcm9tU3RyaW5nKGNvbmZpZy5yZXNvdXJjZXMudGhhbm9zUXVlcnkubGltaXRzLmNwdSksXG4gICAgICAgICAgICAgICAgICAgIG1lbW9yeTogUXVhbnRpdHkuZnJvbVN0cmluZyhjb25maWcucmVzb3VyY2VzLnRoYW5vc1F1ZXJ5LmxpbWl0cy5tZW1vcnkpLFxuICAgICAgICAgICAgICAgICAgfSxcbiAgICAgICAgICAgICAgICB9LFxuICAgICAgICAgICAgICB9LFxuICAgICAgICAgICAgXSxcblxuICAgICAgICAgICAgcHJpb3JpdHlDbGFzc05hbWU6ICdoaWdoLXByaW9yaXR5JyxcbiAgICAgICAgICB9LFxuICAgICAgICB9LFxuICAgICAgfSxcbiAgICB9KTtcblxuICAgIC8vIENyZWF0ZSBIVFRQIFNlcnZpY2UgKGZvciBHcmFmYW5hKVxuICAgIG5ldyBLdWJlU2VydmljZSh0aGlzLCAnc2VydmljZS1odHRwJywge1xuICAgICAgbWV0YWRhdGE6IHtcbiAgICAgICAgbmFtZTogJ3RoYW5vcy1xdWVyeScsXG4gICAgICAgIG5hbWVzcGFjZTogbmFtZXNwYWNlLFxuICAgICAgICBsYWJlbHM6IHtcbiAgICAgICAgICAnYXBwLmt1YmVybmV0ZXMuaW8vbmFtZSc6ICd0aGFub3MtcXVlcnknLFxuICAgICAgICAgICdhcHAua3ViZXJuZXRlcy5pby9tYW5hZ2VkLWJ5JzogJ2NkazhzJyxcbiAgICAgICAgfSxcbiAgICAgICAgYW5ub3RhdGlvbnM6IHtcbiAgICAgICAgICAnYXJnb2NkLmFyZ29wcm9qLmlvL3N5bmMtd2F2ZSc6ICczJyxcbiAgICAgICAgfSxcbiAgICAgIH0sXG4gICAgICBzcGVjOiB7XG4gICAgICAgIHBvcnRzOiBbXG4gICAgICAgICAge1xuICAgICAgICAgICAgbmFtZTogJ2h0dHAnLFxuICAgICAgICAgICAgcG9ydDogOTA5MCxcbiAgICAgICAgICAgIC8vIENvbnRhaW5lciBodHRwIHBvcnQgaXMgMTA5MDIuIEEgYmFyZSBzdHJpbmcgaXMgZHJvcHBlZCBieSBjZGs4c1xuICAgICAgICAgICAgLy8gKHRhcmdldFBvcnQgZXhwZWN0cyBJbnRPclN0cmluZyksIHdoaWNoIHNpbGVudGx5IGRlZmF1bHRlZFxuICAgICAgICAgICAgLy8gdGFyZ2V0UG9ydCB0byA5MDkwIGFuZCBtYWRlIHRoZSBTZXJ2aWNlIHJlZnVzZSBjb25uZWN0aW9ucy5cbiAgICAgICAgICAgIHRhcmdldFBvcnQ6IEludE9yU3RyaW5nLmZyb21TdHJpbmcoJ2h0dHAnKSxcbiAgICAgICAgICAgIHByb3RvY29sOiAnVENQJyxcbiAgICAgICAgICB9LFxuICAgICAgICBdLFxuICAgICAgICBzZWxlY3Rvcjoge1xuICAgICAgICAgICdhcHAua3ViZXJuZXRlcy5pby9uYW1lJzogJ3RoYW5vcy1xdWVyeScsXG4gICAgICAgIH0sXG4gICAgICAgIHNlc3Npb25BZmZpbml0eTogJ0NsaWVudElQJyxcbiAgICAgIH0sXG4gICAgfSk7XG5cbiAgICAvLyBDcmVhdGUgZ1JQQyBTZXJ2aWNlIChoZWFkbGVzcywgZm9yIGZ1dHVyZSBRdWVyeSBGcm9udGVuZClcbiAgICBuZXcgS3ViZVNlcnZpY2UodGhpcywgJ3NlcnZpY2UtZ3JwYycsIHtcbiAgICAgIG1ldGFkYXRhOiB7XG4gICAgICAgIG5hbWU6ICd0aGFub3MtcXVlcnktZ3JwYycsXG4gICAgICAgIG5hbWVzcGFjZTogbmFtZXNwYWNlLFxuICAgICAgICBsYWJlbHM6IHtcbiAgICAgICAgICAnYXBwLmt1YmVybmV0ZXMuaW8vbmFtZSc6ICd0aGFub3MtcXVlcnknLFxuICAgICAgICAgICdhcHAua3ViZXJuZXRlcy5pby9tYW5hZ2VkLWJ5JzogJ2NkazhzJyxcbiAgICAgICAgfSxcbiAgICAgICAgYW5ub3RhdGlvbnM6IHtcbiAgICAgICAgICAnYXJnb2NkLmFyZ29wcm9qLmlvL3N5bmMtd2F2ZSc6ICczJyxcbiAgICAgICAgfSxcbiAgICAgIH0sXG4gICAgICBzcGVjOiB7XG4gICAgICAgIHR5cGU6ICdDbHVzdGVySVAnLFxuICAgICAgICBjbHVzdGVySXA6ICdOb25lJywgLy8gSGVhZGxlc3Mgc2VydmljZSBmb3IgRE5TLWJhc2VkIGRpc2NvdmVyeVxuICAgICAgICBwb3J0czogW1xuICAgICAgICAgIHtcbiAgICAgICAgICAgIG5hbWU6ICdncnBjJyxcbiAgICAgICAgICAgIHBvcnQ6IDEwOTAxLFxuICAgICAgICAgICAgdGFyZ2V0UG9ydDogSW50T3JTdHJpbmcuZnJvbVN0cmluZygnZ3JwYycpLFxuICAgICAgICAgICAgcHJvdG9jb2w6ICdUQ1AnLFxuICAgICAgICAgIH0sXG4gICAgICAgIF0sXG4gICAgICAgIHNlbGVjdG9yOiB7XG4gICAgICAgICAgJ2FwcC5rdWJlcm5ldGVzLmlvL25hbWUnOiAndGhhbm9zLXF1ZXJ5JyxcbiAgICAgICAgfSxcbiAgICAgIH0sXG4gICAgfSk7XG4gIH1cbn1cbiJdfQ==
@@ -0,0 +1,24 @@
1
+ import { Construct } from 'constructs';
2
+ import { MonitoringConfig } from '../types';
3
+ export interface ThanosS3BucketProps {
4
+ config: MonitoringConfig;
5
+ }
6
+ /**
7
+ * Creates Crossplane Bucket resources for Thanos long-term metrics storage.
8
+ *
9
+ * This construct generates:
10
+ * - S3 Bucket (via Crossplane Upbound provider-aws-s3)
11
+ * - BucketVersioning (for recovery)
12
+ * - BucketLifecycleConfiguration (2-year retention)
13
+ *
14
+ * Prerequisites:
15
+ * - Crossplane operator installed
16
+ * - Upbound provider-aws-s3 installed
17
+ * - ProviderConfig 'hetzner-s3' configured (points to Hetzner S3)
18
+ * - Hetzner S3 credentials secret exists in crossplane-system
19
+ *
20
+ * Sync Wave: 1 (external dependencies - must exist before pods access S3)
21
+ */
22
+ export declare class ThanosS3BucketConstruct extends Construct {
23
+ constructor(scope: Construct, id: string, props: ThanosS3BucketProps);
24
+ }