@pulumiverse/grafana 2.19.0 → 2.20.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,320 @@
1
+ import * as pulumi from "@pulumi/pulumi";
2
+ import * as inputs from "../types/input";
3
+ import * as outputs from "../types/output";
4
+ /**
5
+ * Manages Prometheus Rules configurations through Grafana Asserts API. Allows creation and management of custom Prometheus recording and alerting rules.
6
+ *
7
+ * ## Example Usage
8
+ *
9
+ * ```typescript
10
+ * import * as pulumi from "@pulumi/pulumi";
11
+ * import * as grafana from "@pulumiverse/grafana";
12
+ *
13
+ * // Basic recording rule for latency metrics
14
+ * const latencyMetrics = new grafana.assert.PromRuleFile("latency_metrics", {
15
+ * name: "custom-latency-metrics",
16
+ * active: true,
17
+ * groups: [{
18
+ * name: "latency_recording_rules",
19
+ * interval: "30s",
20
+ * rules: [
21
+ * {
22
+ * record: "custom:latency:p95",
23
+ * expr: "histogram_quantile(0.95, rate(http_request_duration_seconds_bucket[5m]))",
24
+ * labels: {
25
+ * source: "custom_instrumentation",
26
+ * severity: "info",
27
+ * },
28
+ * },
29
+ * {
30
+ * record: "custom:latency:p99",
31
+ * expr: "histogram_quantile(0.99, rate(http_request_duration_seconds_bucket[5m]))",
32
+ * labels: {
33
+ * source: "custom_instrumentation",
34
+ * severity: "info",
35
+ * },
36
+ * },
37
+ * ],
38
+ * }],
39
+ * });
40
+ * // Alert rules for high latency
41
+ * const latencyAlerts = new grafana.assert.PromRuleFile("latency_alerts", {
42
+ * name: "custom-latency-alerts",
43
+ * active: true,
44
+ * groups: [{
45
+ * name: "latency_alerting",
46
+ * interval: "30s",
47
+ * rules: [
48
+ * {
49
+ * alert: "HighLatency",
50
+ * expr: "histogram_quantile(0.99, rate(http_request_duration_seconds_bucket[5m])) > 0.5",
51
+ * duration: "5m",
52
+ * labels: {
53
+ * severity: "warning",
54
+ * category: "Latency",
55
+ * },
56
+ * annotations: {
57
+ * summary: "High latency detected",
58
+ * description: "P99 latency is above 500ms for 5 minutes",
59
+ * },
60
+ * },
61
+ * {
62
+ * alert: "VeryHighLatency",
63
+ * expr: "histogram_quantile(0.99, rate(http_request_duration_seconds_bucket[5m])) > 1.0",
64
+ * duration: "2m",
65
+ * labels: {
66
+ * severity: "critical",
67
+ * category: "Latency",
68
+ * },
69
+ * annotations: {
70
+ * summary: "Very high latency detected",
71
+ * description: "P99 latency is above 1 second",
72
+ * },
73
+ * },
74
+ * ],
75
+ * }],
76
+ * });
77
+ * // Comprehensive monitoring rules with multiple groups
78
+ * const comprehensiveMonitoring = new grafana.assert.PromRuleFile("comprehensive_monitoring", {
79
+ * name: "custom-comprehensive-monitoring",
80
+ * active: true,
81
+ * groups: [
82
+ * {
83
+ * name: "latency_monitoring",
84
+ * interval: "30s",
85
+ * rules: [
86
+ * {
87
+ * record: "custom:latency:p99",
88
+ * expr: "histogram_quantile(0.99, rate(http_request_duration_seconds_bucket[5m]))",
89
+ * labels: {
90
+ * source: "custom",
91
+ * },
92
+ * },
93
+ * {
94
+ * alert: "HighLatency",
95
+ * expr: "custom:latency:p99 > 0.5",
96
+ * duration: "5m",
97
+ * labels: {
98
+ * severity: "warning",
99
+ * },
100
+ * annotations: {
101
+ * summary: "High latency detected",
102
+ * },
103
+ * },
104
+ * ],
105
+ * },
106
+ * {
107
+ * name: "error_monitoring",
108
+ * interval: "1m",
109
+ * rules: [
110
+ * {
111
+ * record: "custom:error:rate",
112
+ * expr: "rate(http_requests_total{status=~\"5..\"}[5m])",
113
+ * labels: {
114
+ * source: "custom",
115
+ * },
116
+ * },
117
+ * {
118
+ * alert: "HighErrorRate",
119
+ * expr: "custom:error:rate > 0.1",
120
+ * duration: "10m",
121
+ * labels: {
122
+ * severity: "critical",
123
+ * category: "Errors",
124
+ * },
125
+ * annotations: {
126
+ * summary: "High error rate detected",
127
+ * description: "Error rate is above 10%",
128
+ * },
129
+ * },
130
+ * ],
131
+ * },
132
+ * {
133
+ * name: "throughput_monitoring",
134
+ * interval: "1m",
135
+ * rules: [
136
+ * {
137
+ * record: "custom:throughput:total",
138
+ * expr: "sum(rate(http_requests_total[5m]))",
139
+ * labels: {
140
+ * source: "custom",
141
+ * },
142
+ * },
143
+ * {
144
+ * alert: "LowThroughput",
145
+ * expr: "custom:throughput:total < 10",
146
+ * duration: "5m",
147
+ * labels: {
148
+ * severity: "warning",
149
+ * category: "Throughput",
150
+ * },
151
+ * annotations: {
152
+ * summary: "Low throughput detected",
153
+ * description: "Request throughput is below 10 requests/second",
154
+ * },
155
+ * },
156
+ * ],
157
+ * },
158
+ * ],
159
+ * });
160
+ * // Rules with conditional enablement
161
+ * const conditionalRules = new grafana.assert.PromRuleFile("conditional_rules", {
162
+ * name: "custom-conditional-rules",
163
+ * active: true,
164
+ * groups: [{
165
+ * name: "environment_specific_rules",
166
+ * interval: "30s",
167
+ * rules: [
168
+ * {
169
+ * alert: "TestAlert",
170
+ * expr: "up == 0",
171
+ * duration: "1m",
172
+ * labels: {
173
+ * severity: "info",
174
+ * },
175
+ * annotations: {
176
+ * summary: "Test alert that is disabled in production",
177
+ * },
178
+ * disableInGroups: ["production"],
179
+ * },
180
+ * {
181
+ * alert: "CriticalAlert",
182
+ * expr: "up == 0",
183
+ * duration: "30s",
184
+ * labels: {
185
+ * severity: "critical",
186
+ * },
187
+ * annotations: {
188
+ * summary: "Critical alert that fires in all environments",
189
+ * },
190
+ * },
191
+ * ],
192
+ * }],
193
+ * });
194
+ * // Inactive rules (for staging/testing)
195
+ * const stagingRules = new grafana.assert.PromRuleFile("staging_rules", {
196
+ * name: "custom-staging-rules",
197
+ * active: false,
198
+ * groups: [{
199
+ * name: "staging_tests",
200
+ * interval: "1m",
201
+ * rules: [{
202
+ * record: "staging:test:metric",
203
+ * expr: "up",
204
+ * labels: {
205
+ * environment: "staging",
206
+ * },
207
+ * }],
208
+ * }],
209
+ * });
210
+ * // SLO-based alerting
211
+ * const sloAlerts = new grafana.assert.PromRuleFile("slo_alerts", {
212
+ * name: "custom-slo-alerts",
213
+ * active: true,
214
+ * groups: [{
215
+ * name: "slo_monitoring",
216
+ * interval: "1m",
217
+ * rules: [
218
+ * {
219
+ * record: "custom:slo:availability",
220
+ * expr: "sum(rate(http_requests_total{status!~\"5..\"}[5m])) / sum(rate(http_requests_total[5m]))",
221
+ * labels: {
222
+ * slo_type: "availability",
223
+ * },
224
+ * },
225
+ * {
226
+ * alert: "SLOAvailabilityBreach",
227
+ * expr: "custom:slo:availability < 0.995",
228
+ * duration: "5m",
229
+ * labels: {
230
+ * severity: "critical",
231
+ * category: "SLO",
232
+ * },
233
+ * annotations: {
234
+ * summary: "SLO availability breach",
235
+ * description: "Availability is below 99.5% SLO target",
236
+ * runbook_url: "https://docs.example.com/runbooks/availability-breach",
237
+ * },
238
+ * },
239
+ * ],
240
+ * }],
241
+ * });
242
+ * ```
243
+ *
244
+ * ## Import
245
+ *
246
+ * ```sh
247
+ * $ pulumi import grafana:assert/promRuleFile:PromRuleFile name "{{ name }}"
248
+ * ```
249
+ */
250
+ export declare class PromRuleFile extends pulumi.CustomResource {
251
+ /**
252
+ * Get an existing PromRuleFile resource's state with the given name, ID, and optional extra
253
+ * properties used to qualify the lookup.
254
+ *
255
+ * @param name The _unique_ name of the resulting resource.
256
+ * @param id The _unique_ provider ID of the resource to lookup.
257
+ * @param state Any extra arguments used during the lookup.
258
+ * @param opts Optional settings to control the behavior of the CustomResource.
259
+ */
260
+ static get(name: string, id: pulumi.Input<pulumi.ID>, state?: PromRuleFileState, opts?: pulumi.CustomResourceOptions): PromRuleFile;
261
+ /**
262
+ * Returns true if the given object is an instance of PromRuleFile. This is designed to work even
263
+ * when multiple copies of the Pulumi SDK have been loaded into the same process.
264
+ */
265
+ static isInstance(obj: any): obj is PromRuleFile;
266
+ /**
267
+ * Whether the rules file is active. Inactive rules are not evaluated. Defaults to `true`.
268
+ */
269
+ readonly active: pulumi.Output<boolean | undefined>;
270
+ /**
271
+ * List of Prometheus rule groups. Each group contains one or more rules and can have its own evaluation interval.
272
+ */
273
+ readonly groups: pulumi.Output<outputs.assert.PromRuleFileGroup[]>;
274
+ /**
275
+ * The name of the Prometheus rules file. This will be stored with a .custom extension. Must follow naming validation rules (alphanumeric, hyphens, underscores).
276
+ */
277
+ readonly name: pulumi.Output<string>;
278
+ /**
279
+ * Create a PromRuleFile resource with the given unique name, arguments, and options.
280
+ *
281
+ * @param name The _unique_ name of the resource.
282
+ * @param args The arguments to use to populate this resource's properties.
283
+ * @param opts A bag of options that control this resource's behavior.
284
+ */
285
+ constructor(name: string, args: PromRuleFileArgs, opts?: pulumi.CustomResourceOptions);
286
+ }
287
+ /**
288
+ * Input properties used for looking up and filtering PromRuleFile resources.
289
+ */
290
+ export interface PromRuleFileState {
291
+ /**
292
+ * Whether the rules file is active. Inactive rules are not evaluated. Defaults to `true`.
293
+ */
294
+ active?: pulumi.Input<boolean>;
295
+ /**
296
+ * List of Prometheus rule groups. Each group contains one or more rules and can have its own evaluation interval.
297
+ */
298
+ groups?: pulumi.Input<pulumi.Input<inputs.assert.PromRuleFileGroup>[]>;
299
+ /**
300
+ * The name of the Prometheus rules file. This will be stored with a .custom extension. Must follow naming validation rules (alphanumeric, hyphens, underscores).
301
+ */
302
+ name?: pulumi.Input<string>;
303
+ }
304
+ /**
305
+ * The set of arguments for constructing a PromRuleFile resource.
306
+ */
307
+ export interface PromRuleFileArgs {
308
+ /**
309
+ * Whether the rules file is active. Inactive rules are not evaluated. Defaults to `true`.
310
+ */
311
+ active?: pulumi.Input<boolean>;
312
+ /**
313
+ * List of Prometheus rule groups. Each group contains one or more rules and can have its own evaluation interval.
314
+ */
315
+ groups: pulumi.Input<pulumi.Input<inputs.assert.PromRuleFileGroup>[]>;
316
+ /**
317
+ * The name of the Prometheus rules file. This will be stored with a .custom extension. Must follow naming validation rules (alphanumeric, hyphens, underscores).
318
+ */
319
+ name?: pulumi.Input<string>;
320
+ }
@@ -0,0 +1,302 @@
1
+ "use strict";
2
+ // *** WARNING: this file was generated by pulumi-language-nodejs. ***
3
+ // *** Do not edit by hand unless you're certain you know what you are doing! ***
4
+ Object.defineProperty(exports, "__esModule", { value: true });
5
+ exports.PromRuleFile = void 0;
6
+ const pulumi = require("@pulumi/pulumi");
7
+ const utilities = require("../utilities");
8
+ /**
9
+ * Manages Prometheus Rules configurations through Grafana Asserts API. Allows creation and management of custom Prometheus recording and alerting rules.
10
+ *
11
+ * ## Example Usage
12
+ *
13
+ * ```typescript
14
+ * import * as pulumi from "@pulumi/pulumi";
15
+ * import * as grafana from "@pulumiverse/grafana";
16
+ *
17
+ * // Basic recording rule for latency metrics
18
+ * const latencyMetrics = new grafana.assert.PromRuleFile("latency_metrics", {
19
+ * name: "custom-latency-metrics",
20
+ * active: true,
21
+ * groups: [{
22
+ * name: "latency_recording_rules",
23
+ * interval: "30s",
24
+ * rules: [
25
+ * {
26
+ * record: "custom:latency:p95",
27
+ * expr: "histogram_quantile(0.95, rate(http_request_duration_seconds_bucket[5m]))",
28
+ * labels: {
29
+ * source: "custom_instrumentation",
30
+ * severity: "info",
31
+ * },
32
+ * },
33
+ * {
34
+ * record: "custom:latency:p99",
35
+ * expr: "histogram_quantile(0.99, rate(http_request_duration_seconds_bucket[5m]))",
36
+ * labels: {
37
+ * source: "custom_instrumentation",
38
+ * severity: "info",
39
+ * },
40
+ * },
41
+ * ],
42
+ * }],
43
+ * });
44
+ * // Alert rules for high latency
45
+ * const latencyAlerts = new grafana.assert.PromRuleFile("latency_alerts", {
46
+ * name: "custom-latency-alerts",
47
+ * active: true,
48
+ * groups: [{
49
+ * name: "latency_alerting",
50
+ * interval: "30s",
51
+ * rules: [
52
+ * {
53
+ * alert: "HighLatency",
54
+ * expr: "histogram_quantile(0.99, rate(http_request_duration_seconds_bucket[5m])) > 0.5",
55
+ * duration: "5m",
56
+ * labels: {
57
+ * severity: "warning",
58
+ * category: "Latency",
59
+ * },
60
+ * annotations: {
61
+ * summary: "High latency detected",
62
+ * description: "P99 latency is above 500ms for 5 minutes",
63
+ * },
64
+ * },
65
+ * {
66
+ * alert: "VeryHighLatency",
67
+ * expr: "histogram_quantile(0.99, rate(http_request_duration_seconds_bucket[5m])) > 1.0",
68
+ * duration: "2m",
69
+ * labels: {
70
+ * severity: "critical",
71
+ * category: "Latency",
72
+ * },
73
+ * annotations: {
74
+ * summary: "Very high latency detected",
75
+ * description: "P99 latency is above 1 second",
76
+ * },
77
+ * },
78
+ * ],
79
+ * }],
80
+ * });
81
+ * // Comprehensive monitoring rules with multiple groups
82
+ * const comprehensiveMonitoring = new grafana.assert.PromRuleFile("comprehensive_monitoring", {
83
+ * name: "custom-comprehensive-monitoring",
84
+ * active: true,
85
+ * groups: [
86
+ * {
87
+ * name: "latency_monitoring",
88
+ * interval: "30s",
89
+ * rules: [
90
+ * {
91
+ * record: "custom:latency:p99",
92
+ * expr: "histogram_quantile(0.99, rate(http_request_duration_seconds_bucket[5m]))",
93
+ * labels: {
94
+ * source: "custom",
95
+ * },
96
+ * },
97
+ * {
98
+ * alert: "HighLatency",
99
+ * expr: "custom:latency:p99 > 0.5",
100
+ * duration: "5m",
101
+ * labels: {
102
+ * severity: "warning",
103
+ * },
104
+ * annotations: {
105
+ * summary: "High latency detected",
106
+ * },
107
+ * },
108
+ * ],
109
+ * },
110
+ * {
111
+ * name: "error_monitoring",
112
+ * interval: "1m",
113
+ * rules: [
114
+ * {
115
+ * record: "custom:error:rate",
116
+ * expr: "rate(http_requests_total{status=~\"5..\"}[5m])",
117
+ * labels: {
118
+ * source: "custom",
119
+ * },
120
+ * },
121
+ * {
122
+ * alert: "HighErrorRate",
123
+ * expr: "custom:error:rate > 0.1",
124
+ * duration: "10m",
125
+ * labels: {
126
+ * severity: "critical",
127
+ * category: "Errors",
128
+ * },
129
+ * annotations: {
130
+ * summary: "High error rate detected",
131
+ * description: "Error rate is above 10%",
132
+ * },
133
+ * },
134
+ * ],
135
+ * },
136
+ * {
137
+ * name: "throughput_monitoring",
138
+ * interval: "1m",
139
+ * rules: [
140
+ * {
141
+ * record: "custom:throughput:total",
142
+ * expr: "sum(rate(http_requests_total[5m]))",
143
+ * labels: {
144
+ * source: "custom",
145
+ * },
146
+ * },
147
+ * {
148
+ * alert: "LowThroughput",
149
+ * expr: "custom:throughput:total < 10",
150
+ * duration: "5m",
151
+ * labels: {
152
+ * severity: "warning",
153
+ * category: "Throughput",
154
+ * },
155
+ * annotations: {
156
+ * summary: "Low throughput detected",
157
+ * description: "Request throughput is below 10 requests/second",
158
+ * },
159
+ * },
160
+ * ],
161
+ * },
162
+ * ],
163
+ * });
164
+ * // Rules with conditional enablement
165
+ * const conditionalRules = new grafana.assert.PromRuleFile("conditional_rules", {
166
+ * name: "custom-conditional-rules",
167
+ * active: true,
168
+ * groups: [{
169
+ * name: "environment_specific_rules",
170
+ * interval: "30s",
171
+ * rules: [
172
+ * {
173
+ * alert: "TestAlert",
174
+ * expr: "up == 0",
175
+ * duration: "1m",
176
+ * labels: {
177
+ * severity: "info",
178
+ * },
179
+ * annotations: {
180
+ * summary: "Test alert that is disabled in production",
181
+ * },
182
+ * disableInGroups: ["production"],
183
+ * },
184
+ * {
185
+ * alert: "CriticalAlert",
186
+ * expr: "up == 0",
187
+ * duration: "30s",
188
+ * labels: {
189
+ * severity: "critical",
190
+ * },
191
+ * annotations: {
192
+ * summary: "Critical alert that fires in all environments",
193
+ * },
194
+ * },
195
+ * ],
196
+ * }],
197
+ * });
198
+ * // Inactive rules (for staging/testing)
199
+ * const stagingRules = new grafana.assert.PromRuleFile("staging_rules", {
200
+ * name: "custom-staging-rules",
201
+ * active: false,
202
+ * groups: [{
203
+ * name: "staging_tests",
204
+ * interval: "1m",
205
+ * rules: [{
206
+ * record: "staging:test:metric",
207
+ * expr: "up",
208
+ * labels: {
209
+ * environment: "staging",
210
+ * },
211
+ * }],
212
+ * }],
213
+ * });
214
+ * // SLO-based alerting
215
+ * const sloAlerts = new grafana.assert.PromRuleFile("slo_alerts", {
216
+ * name: "custom-slo-alerts",
217
+ * active: true,
218
+ * groups: [{
219
+ * name: "slo_monitoring",
220
+ * interval: "1m",
221
+ * rules: [
222
+ * {
223
+ * record: "custom:slo:availability",
224
+ * expr: "sum(rate(http_requests_total{status!~\"5..\"}[5m])) / sum(rate(http_requests_total[5m]))",
225
+ * labels: {
226
+ * slo_type: "availability",
227
+ * },
228
+ * },
229
+ * {
230
+ * alert: "SLOAvailabilityBreach",
231
+ * expr: "custom:slo:availability < 0.995",
232
+ * duration: "5m",
233
+ * labels: {
234
+ * severity: "critical",
235
+ * category: "SLO",
236
+ * },
237
+ * annotations: {
238
+ * summary: "SLO availability breach",
239
+ * description: "Availability is below 99.5% SLO target",
240
+ * runbook_url: "https://docs.example.com/runbooks/availability-breach",
241
+ * },
242
+ * },
243
+ * ],
244
+ * }],
245
+ * });
246
+ * ```
247
+ *
248
+ * ## Import
249
+ *
250
+ * ```sh
251
+ * $ pulumi import grafana:assert/promRuleFile:PromRuleFile name "{{ name }}"
252
+ * ```
253
+ */
254
+ class PromRuleFile extends pulumi.CustomResource {
255
+ /**
256
+ * Get an existing PromRuleFile resource's state with the given name, ID, and optional extra
257
+ * properties used to qualify the lookup.
258
+ *
259
+ * @param name The _unique_ name of the resulting resource.
260
+ * @param id The _unique_ provider ID of the resource to lookup.
261
+ * @param state Any extra arguments used during the lookup.
262
+ * @param opts Optional settings to control the behavior of the CustomResource.
263
+ */
264
+ static get(name, id, state, opts) {
265
+ return new PromRuleFile(name, state, { ...opts, id: id });
266
+ }
267
+ /**
268
+ * Returns true if the given object is an instance of PromRuleFile. This is designed to work even
269
+ * when multiple copies of the Pulumi SDK have been loaded into the same process.
270
+ */
271
+ static isInstance(obj) {
272
+ if (obj === undefined || obj === null) {
273
+ return false;
274
+ }
275
+ return obj['__pulumiType'] === PromRuleFile.__pulumiType;
276
+ }
277
+ constructor(name, argsOrState, opts) {
278
+ let resourceInputs = {};
279
+ opts = opts || {};
280
+ if (opts.id) {
281
+ const state = argsOrState;
282
+ resourceInputs["active"] = state?.active;
283
+ resourceInputs["groups"] = state?.groups;
284
+ resourceInputs["name"] = state?.name;
285
+ }
286
+ else {
287
+ const args = argsOrState;
288
+ if (args?.groups === undefined && !opts.urn) {
289
+ throw new Error("Missing required property 'groups'");
290
+ }
291
+ resourceInputs["active"] = args?.active;
292
+ resourceInputs["groups"] = args?.groups;
293
+ resourceInputs["name"] = args?.name;
294
+ }
295
+ opts = pulumi.mergeOptions(utilities.resourceOptsDefaults(), opts);
296
+ super(PromRuleFile.__pulumiType, name, resourceInputs, opts);
297
+ }
298
+ }
299
+ exports.PromRuleFile = PromRuleFile;
300
+ /** @internal */
301
+ PromRuleFile.__pulumiType = 'grafana:assert/promRuleFile:PromRuleFile';
302
+ //# sourceMappingURL=promRuleFile.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"promRuleFile.js","sourceRoot":"","sources":["../../assert/promRuleFile.ts"],"names":[],"mappings":";AAAA,sEAAsE;AACtE,iFAAiF;;;AAEjF,yCAAyC;AAGzC,0CAA0C;AAE1C;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAqPG;AACH,MAAa,YAAa,SAAQ,MAAM,CAAC,cAAc;IACnD;;;;;;;;OAQG;IACI,MAAM,CAAC,GAAG,CAAC,IAAY,EAAE,EAA2B,EAAE,KAAyB,EAAE,IAAmC;QACvH,OAAO,IAAI,YAAY,CAAC,IAAI,EAAO,KAAK,EAAE,EAAE,GAAG,IAAI,EAAE,EAAE,EAAE,EAAE,EAAE,CAAC,CAAC;IACnE,CAAC;IAKD;;;OAGG;IACI,MAAM,CAAC,UAAU,CAAC,GAAQ;QAC7B,IAAI,GAAG,KAAK,SAAS,IAAI,GAAG,KAAK,IAAI,EAAE;YACnC,OAAO,KAAK,CAAC;SAChB;QACD,OAAO,GAAG,CAAC,cAAc,CAAC,KAAK,YAAY,CAAC,YAAY,CAAC;IAC7D,CAAC;IAuBD,YAAY,IAAY,EAAE,WAAkD,EAAE,IAAmC;QAC7G,IAAI,cAAc,GAAkB,EAAE,CAAC;QACvC,IAAI,GAAG,IAAI,IAAI,EAAE,CAAC;QAClB,IAAI,IAAI,CAAC,EAAE,EAAE;YACT,MAAM,KAAK,GAAG,WAA4C,CAAC;YAC3D,cAAc,CAAC,QAAQ,CAAC,GAAG,KAAK,EAAE,MAAM,CAAC;YACzC,cAAc,CAAC,QAAQ,CAAC,GAAG,KAAK,EAAE,MAAM,CAAC;YACzC,cAAc,CAAC,MAAM,CAAC,GAAG,KAAK,EAAE,IAAI,CAAC;SACxC;aAAM;YACH,MAAM,IAAI,GAAG,WAA2C,CAAC;YACzD,IAAI,IAAI,EAAE,MAAM,KAAK,SAAS,IAAI,CAAC,IAAI,CAAC,GAAG,EAAE;gBACzC,MAAM,IAAI,KAAK,CAAC,oCAAoC,CAAC,CAAC;aACzD;YACD,cAAc,CAAC,QAAQ,CAAC,GAAG,IAAI,EAAE,MAAM,CAAC;YACxC,cAAc,CAAC,QAAQ,CAAC,GAAG,IAAI,EAAE,MAAM,CAAC;YACxC,cAAc,CAAC,MAAM,CAAC,GAAG,IAAI,EAAE,IAAI,CAAC;SACvC;QACD,IAAI,GAAG,MAAM,CAAC,YAAY,CAAC,SAAS,CAAC,oBAAoB,EAAE,EAAE,IAAI,CAAC,CAAC;QACnE,KAAK,CAAC,YAAY,CAAC,YAAY,EAAE,IAAI,EAAE,cAAc,EAAE,IAAI,CAAC,CAAC;IACjE,CAAC;;AApEL,oCAqEC;AAvDG,gBAAgB;AACO,yBAAY,GAAG,0CAA0C,CAAC"}