@suss/contract-terraform 0.8.0 → 0.10.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.d.cts CHANGED
@@ -1,4 +1,4 @@
1
- import { MessageBusTechnology, BehavioralSummary } from '@suss/behavioral-ir';
1
+ import { MessageBusTechnology, MetricValueShape, MetricAccumulation, BehavioralSummary } from '@suss/behavioral-ir';
2
2
 
3
3
  /**
4
4
  * What a pack says about the resources one Terraform provider declares.
@@ -20,6 +20,17 @@ interface StorageResource {
20
20
  storageSystem: string;
21
21
  /** How a caller reaches it, when that is not the store's own name. */
22
22
  transport?: string;
23
+ /**
24
+ * What the resource declares. The default, `"container"`, means the
25
+ * resource is the thing code addresses: code passes a bucket's name
26
+ * to `bucket()`, so the declared name and the accessed name meet.
27
+ * `"store"` means the resource only says the store exists. Code
28
+ * splits a Redis cluster into key namespaces, no attribute of the
29
+ * cluster lists them, so the summary gets no container name and
30
+ * claims no access. Any match on the cluster's own name would be a
31
+ * coincidence between a deployment name and a key prefix.
32
+ */
33
+ declares?: "container" | "store";
23
34
  /** The attribute that says what the resource is called once deployed. */
24
35
  nameAttribute?: string;
25
36
  /** Whether the fields it declares are every field an item has. */
@@ -55,11 +66,81 @@ interface MessageBusResource {
55
66
  messageBus: MessageBusTechnology;
56
67
  nameAttribute?: string;
57
68
  }
58
- type TerraformResource = StorageResource | MessageBusResource;
69
+ /**
70
+ * An attribute whose value the pack translates into one of suss's own
71
+ * words. The reader takes the value at `attribute` and looks it up in
72
+ * `means`; a value the pack did not list says nothing, the same as an
73
+ * attribute the configuration never set.
74
+ */
75
+ interface AttributeMeaning<T extends string> {
76
+ /** The attribute path whose value says which one it is. */
77
+ attribute: string;
78
+ /** What each value the provider can write there means. */
79
+ means: Record<string, T>;
80
+ }
81
+ /** A named series of measurements a resource declares. */
82
+ interface MetricResource {
83
+ kind: "metric";
84
+ /** Which system the series lives in: cloud-monitoring. */
85
+ metricSystem: string;
86
+ /** The attribute that says what the metric is called. */
87
+ nameAttribute: string;
88
+ /**
89
+ * How the deployed metric type is spelled, with `{name}` standing
90
+ * for the declared name. That string is what a resource reading the
91
+ * metric spells, so it is the identity the two sides share.
92
+ */
93
+ metricTypeTemplate: string;
94
+ /** Which attribute says whether one measurement is a number or a histogram. */
95
+ values?: AttributeMeaning<MetricValueShape>;
96
+ /** Which attribute says what a measurement covers. */
97
+ accumulates?: AttributeMeaning<MetricAccumulation>;
98
+ }
99
+ /**
100
+ * A resource that reads a metric another resource declares. One
101
+ * resource usually states several readings, each in its own block and
102
+ * each about its own metric, so each becomes a boundary of its own.
103
+ */
104
+ interface MetricReadingResource {
105
+ kind: "metric-reading";
106
+ metricSystem: string;
107
+ /** The blocks one reading is written inside, outermost first. */
108
+ readingBlocks: string[];
109
+ /** The attribute whose query says which metric the reading is about. */
110
+ queryAttribute: string;
111
+ /** The key inside that query whose value is the metric's type. */
112
+ queryIdentityKey: string;
113
+ /**
114
+ * The attribute whose presence means the reading compares the series
115
+ * against a value of this shape. A condition states a threshold, so
116
+ * the number it compares against is the attribute being set at all.
117
+ */
118
+ comparesTo?: {
119
+ attribute: string;
120
+ whenSet: MetricValueShape;
121
+ };
122
+ /** Which attribute says what the reading reduces each window to first. */
123
+ reducesTo?: AttributeMeaning<MetricValueShape>;
124
+ }
125
+ type TerraformResource = StorageResource | MessageBusResource | MetricResource | MetricReadingResource;
59
126
  /** One resource type, as one version range of one provider declares it. */
60
127
  interface TerraformResourcePattern {
61
128
  /** The resource type, spelled the way the provider spells it. */
62
129
  resource: string;
130
+ /**
131
+ * An attribute that decides whether the entry describes the resource
132
+ * at all. `aws_elasticache_cluster` deploys whichever engine its
133
+ * `engine` attribute picks, and only some engines are the store the
134
+ * entry describes. A value outside `equals`, or one built at deploy
135
+ * time, means the resource is not read, rather than read as
136
+ * something it may not be. `whenUnset` says what an absent attribute
137
+ * means; the default is not to read the resource.
138
+ */
139
+ appliesWhen?: {
140
+ attribute: string;
141
+ equals: string[];
142
+ whenUnset?: "read" | "skip";
143
+ };
63
144
  /**
64
145
  * Which provider versions this describes, as a semver range. A
65
146
  * configuration states its own constraint under `required_providers`,
@@ -81,6 +162,65 @@ interface TerraformPack {
81
162
  resources: TerraformResourcePattern[];
82
163
  }
83
164
 
165
+ /**
166
+ * A filter written as comparisons joined by AND and OR.
167
+ *
168
+ * Several cloud APIs take a selector as one string in this shape:
169
+ * `metric.type = "x" AND resource.type = "y"`, with quoted or bare
170
+ * values, parentheses, NOT, and terms written next to each other for
171
+ * AND. A resource that reads what another resource declares usually
172
+ * says which one inside such a string, so reading the string is how
173
+ * this reader finds out what a resource refers to.
174
+ *
175
+ * A pack says which key it wants. This file knows the grammar and no
176
+ * provider's key names. What comes back is a tree, since OR and NOT
177
+ * change what a term claims and only the caller can judge that.
178
+ */
179
+ /** One comparison, as the filter writes it. */
180
+ interface FilterTerm {
181
+ type: "term";
182
+ /**
183
+ * The left side, a dotted path such as `metric.type`. A segment the
184
+ * filter quotes, `metric.label."response_code"`, comes back without
185
+ * the quotes, so one key has one spelling.
186
+ */
187
+ key: string;
188
+ /** `=`, `!=`, `>`, `>=`, `<`, `<=`, or `:` for "has". */
189
+ operator: string;
190
+ /** The right side, with the quotes taken off a quoted value. */
191
+ value: string;
192
+ }
193
+ /** A call standing where a comparison would, with its arguments. */
194
+ interface FilterCall {
195
+ type: "call";
196
+ name: string;
197
+ arguments: string[];
198
+ }
199
+ type FilterQuery = FilterTerm | FilterCall | {
200
+ type: "junction";
201
+ operator: "and" | "or";
202
+ operands: FilterQuery[];
203
+ } | {
204
+ type: "negation";
205
+ operand: FilterQuery;
206
+ };
207
+ /** A filter nobody could read says why, rather than reading as empty. */
208
+ type FilterParse = {
209
+ ok: true;
210
+ query: FilterQuery;
211
+ } | {
212
+ ok: false;
213
+ reason: string;
214
+ };
215
+ /** Every value a key is compared to with `=`, anywhere in the tree. */
216
+ declare function filterValuesFor(query: FilterQuery, key: string): string[];
217
+ /** Every comparison in the tree, in the order the filter writes them. */
218
+ declare function filterTerms(query: FilterQuery): FilterTerm[];
219
+ /** Every call in the tree, for a caller that reads one of them. */
220
+ declare function filterCalls(query: FilterQuery): FilterCall[];
221
+ /** Read one filter string, or say what stopped the reading. */
222
+ declare function parseFilterQuery(source: string): FilterParse;
223
+
84
224
  /**
85
225
  * The boundaries a Terraform configuration declares.
86
226
  *
@@ -91,8 +231,10 @@ interface TerraformPack {
91
231
  * A name is usually built at deploy time, and Terraform interpolates
92
232
  * the same way CloudFormation does, so `"${local.environment}-orders"`
93
233
  * becomes the pattern `{local.environment}-orders` and pairs with code
94
- * that builds the same name from its own variable. The README says how
95
- * a block that HCL states once or many times is read.
234
+ * that builds the same name from its own variable. An interpolation
235
+ * that refers to another resource in the same configuration resolves
236
+ * instead, since that resource states the value. The README says how a
237
+ * block that HCL states once or many times is read.
96
238
  */
97
239
 
98
240
  interface TerraformReadOptions {
@@ -104,4 +246,4 @@ declare function terraformToSummaries(source: string, sourceFile: string, option
104
246
  /** Read one `.tf` file, or every one directly inside a directory. */
105
247
  declare function terraformFileToSummaries(target: string, options: TerraformReadOptions): BehavioralSummary[];
106
248
 
107
- export { type MessageBusResource, type StorageResource, type TerraformPack, type TerraformReadOptions, type TerraformResource, type TerraformResourcePattern, terraformFileToSummaries, terraformToSummaries };
249
+ export { type AttributeMeaning, type FilterCall, type FilterParse, type FilterQuery, type FilterTerm, type MessageBusResource, type MetricReadingResource, type MetricResource, type StorageResource, type TerraformPack, type TerraformReadOptions, type TerraformResource, type TerraformResourcePattern, filterCalls, filterTerms, filterValuesFor, parseFilterQuery, terraformFileToSummaries, terraformToSummaries };
package/dist/index.d.ts CHANGED
@@ -1,4 +1,4 @@
1
- import { MessageBusTechnology, BehavioralSummary } from '@suss/behavioral-ir';
1
+ import { MessageBusTechnology, MetricValueShape, MetricAccumulation, BehavioralSummary } from '@suss/behavioral-ir';
2
2
 
3
3
  /**
4
4
  * What a pack says about the resources one Terraform provider declares.
@@ -20,6 +20,17 @@ interface StorageResource {
20
20
  storageSystem: string;
21
21
  /** How a caller reaches it, when that is not the store's own name. */
22
22
  transport?: string;
23
+ /**
24
+ * What the resource declares. The default, `"container"`, means the
25
+ * resource is the thing code addresses: code passes a bucket's name
26
+ * to `bucket()`, so the declared name and the accessed name meet.
27
+ * `"store"` means the resource only says the store exists. Code
28
+ * splits a Redis cluster into key namespaces, no attribute of the
29
+ * cluster lists them, so the summary gets no container name and
30
+ * claims no access. Any match on the cluster's own name would be a
31
+ * coincidence between a deployment name and a key prefix.
32
+ */
33
+ declares?: "container" | "store";
23
34
  /** The attribute that says what the resource is called once deployed. */
24
35
  nameAttribute?: string;
25
36
  /** Whether the fields it declares are every field an item has. */
@@ -55,11 +66,81 @@ interface MessageBusResource {
55
66
  messageBus: MessageBusTechnology;
56
67
  nameAttribute?: string;
57
68
  }
58
- type TerraformResource = StorageResource | MessageBusResource;
69
+ /**
70
+ * An attribute whose value the pack translates into one of suss's own
71
+ * words. The reader takes the value at `attribute` and looks it up in
72
+ * `means`; a value the pack did not list says nothing, the same as an
73
+ * attribute the configuration never set.
74
+ */
75
+ interface AttributeMeaning<T extends string> {
76
+ /** The attribute path whose value says which one it is. */
77
+ attribute: string;
78
+ /** What each value the provider can write there means. */
79
+ means: Record<string, T>;
80
+ }
81
+ /** A named series of measurements a resource declares. */
82
+ interface MetricResource {
83
+ kind: "metric";
84
+ /** Which system the series lives in: cloud-monitoring. */
85
+ metricSystem: string;
86
+ /** The attribute that says what the metric is called. */
87
+ nameAttribute: string;
88
+ /**
89
+ * How the deployed metric type is spelled, with `{name}` standing
90
+ * for the declared name. That string is what a resource reading the
91
+ * metric spells, so it is the identity the two sides share.
92
+ */
93
+ metricTypeTemplate: string;
94
+ /** Which attribute says whether one measurement is a number or a histogram. */
95
+ values?: AttributeMeaning<MetricValueShape>;
96
+ /** Which attribute says what a measurement covers. */
97
+ accumulates?: AttributeMeaning<MetricAccumulation>;
98
+ }
99
+ /**
100
+ * A resource that reads a metric another resource declares. One
101
+ * resource usually states several readings, each in its own block and
102
+ * each about its own metric, so each becomes a boundary of its own.
103
+ */
104
+ interface MetricReadingResource {
105
+ kind: "metric-reading";
106
+ metricSystem: string;
107
+ /** The blocks one reading is written inside, outermost first. */
108
+ readingBlocks: string[];
109
+ /** The attribute whose query says which metric the reading is about. */
110
+ queryAttribute: string;
111
+ /** The key inside that query whose value is the metric's type. */
112
+ queryIdentityKey: string;
113
+ /**
114
+ * The attribute whose presence means the reading compares the series
115
+ * against a value of this shape. A condition states a threshold, so
116
+ * the number it compares against is the attribute being set at all.
117
+ */
118
+ comparesTo?: {
119
+ attribute: string;
120
+ whenSet: MetricValueShape;
121
+ };
122
+ /** Which attribute says what the reading reduces each window to first. */
123
+ reducesTo?: AttributeMeaning<MetricValueShape>;
124
+ }
125
+ type TerraformResource = StorageResource | MessageBusResource | MetricResource | MetricReadingResource;
59
126
  /** One resource type, as one version range of one provider declares it. */
60
127
  interface TerraformResourcePattern {
61
128
  /** The resource type, spelled the way the provider spells it. */
62
129
  resource: string;
130
+ /**
131
+ * An attribute that decides whether the entry describes the resource
132
+ * at all. `aws_elasticache_cluster` deploys whichever engine its
133
+ * `engine` attribute picks, and only some engines are the store the
134
+ * entry describes. A value outside `equals`, or one built at deploy
135
+ * time, means the resource is not read, rather than read as
136
+ * something it may not be. `whenUnset` says what an absent attribute
137
+ * means; the default is not to read the resource.
138
+ */
139
+ appliesWhen?: {
140
+ attribute: string;
141
+ equals: string[];
142
+ whenUnset?: "read" | "skip";
143
+ };
63
144
  /**
64
145
  * Which provider versions this describes, as a semver range. A
65
146
  * configuration states its own constraint under `required_providers`,
@@ -81,6 +162,65 @@ interface TerraformPack {
81
162
  resources: TerraformResourcePattern[];
82
163
  }
83
164
 
165
+ /**
166
+ * A filter written as comparisons joined by AND and OR.
167
+ *
168
+ * Several cloud APIs take a selector as one string in this shape:
169
+ * `metric.type = "x" AND resource.type = "y"`, with quoted or bare
170
+ * values, parentheses, NOT, and terms written next to each other for
171
+ * AND. A resource that reads what another resource declares usually
172
+ * says which one inside such a string, so reading the string is how
173
+ * this reader finds out what a resource refers to.
174
+ *
175
+ * A pack says which key it wants. This file knows the grammar and no
176
+ * provider's key names. What comes back is a tree, since OR and NOT
177
+ * change what a term claims and only the caller can judge that.
178
+ */
179
+ /** One comparison, as the filter writes it. */
180
+ interface FilterTerm {
181
+ type: "term";
182
+ /**
183
+ * The left side, a dotted path such as `metric.type`. A segment the
184
+ * filter quotes, `metric.label."response_code"`, comes back without
185
+ * the quotes, so one key has one spelling.
186
+ */
187
+ key: string;
188
+ /** `=`, `!=`, `>`, `>=`, `<`, `<=`, or `:` for "has". */
189
+ operator: string;
190
+ /** The right side, with the quotes taken off a quoted value. */
191
+ value: string;
192
+ }
193
+ /** A call standing where a comparison would, with its arguments. */
194
+ interface FilterCall {
195
+ type: "call";
196
+ name: string;
197
+ arguments: string[];
198
+ }
199
+ type FilterQuery = FilterTerm | FilterCall | {
200
+ type: "junction";
201
+ operator: "and" | "or";
202
+ operands: FilterQuery[];
203
+ } | {
204
+ type: "negation";
205
+ operand: FilterQuery;
206
+ };
207
+ /** A filter nobody could read says why, rather than reading as empty. */
208
+ type FilterParse = {
209
+ ok: true;
210
+ query: FilterQuery;
211
+ } | {
212
+ ok: false;
213
+ reason: string;
214
+ };
215
+ /** Every value a key is compared to with `=`, anywhere in the tree. */
216
+ declare function filterValuesFor(query: FilterQuery, key: string): string[];
217
+ /** Every comparison in the tree, in the order the filter writes them. */
218
+ declare function filterTerms(query: FilterQuery): FilterTerm[];
219
+ /** Every call in the tree, for a caller that reads one of them. */
220
+ declare function filterCalls(query: FilterQuery): FilterCall[];
221
+ /** Read one filter string, or say what stopped the reading. */
222
+ declare function parseFilterQuery(source: string): FilterParse;
223
+
84
224
  /**
85
225
  * The boundaries a Terraform configuration declares.
86
226
  *
@@ -91,8 +231,10 @@ interface TerraformPack {
91
231
  * A name is usually built at deploy time, and Terraform interpolates
92
232
  * the same way CloudFormation does, so `"${local.environment}-orders"`
93
233
  * becomes the pattern `{local.environment}-orders` and pairs with code
94
- * that builds the same name from its own variable. The README says how
95
- * a block that HCL states once or many times is read.
234
+ * that builds the same name from its own variable. An interpolation
235
+ * that refers to another resource in the same configuration resolves
236
+ * instead, since that resource states the value. The README says how a
237
+ * block that HCL states once or many times is read.
96
238
  */
97
239
 
98
240
  interface TerraformReadOptions {
@@ -104,4 +246,4 @@ declare function terraformToSummaries(source: string, sourceFile: string, option
104
246
  /** Read one `.tf` file, or every one directly inside a directory. */
105
247
  declare function terraformFileToSummaries(target: string, options: TerraformReadOptions): BehavioralSummary[];
106
248
 
107
- export { type MessageBusResource, type StorageResource, type TerraformPack, type TerraformReadOptions, type TerraformResource, type TerraformResourcePattern, terraformFileToSummaries, terraformToSummaries };
249
+ export { type AttributeMeaning, type FilterCall, type FilterParse, type FilterQuery, type FilterTerm, type MessageBusResource, type MetricReadingResource, type MetricResource, type StorageResource, type TerraformPack, type TerraformReadOptions, type TerraformResource, type TerraformResourcePattern, filterCalls, filterTerms, filterValuesFor, parseFilterQuery, terraformFileToSummaries, terraformToSummaries };