@highstate/common 0.14.2 → 0.16.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.
Files changed (91) hide show
  1. package/dist/{chunk-WFWXDYUX.js → chunk-X5BK6JSN.js} +877 -194
  2. package/dist/chunk-X5BK6JSN.js.map +1 -0
  3. package/dist/highstate.manifest.json +12 -2
  4. package/dist/index.js +1 -1
  5. package/dist/units/databases/etcd-patch/index.js +20 -0
  6. package/dist/units/databases/etcd-patch/index.js.map +1 -0
  7. package/dist/units/databases/existing-etcd/index.js +14 -0
  8. package/dist/units/databases/existing-etcd/index.js.map +1 -0
  9. package/dist/units/databases/existing-mariadb/index.js +2 -2
  10. package/dist/units/databases/existing-mariadb/index.js.map +1 -1
  11. package/dist/units/databases/existing-mongodb/index.js +2 -2
  12. package/dist/units/databases/existing-mongodb/index.js.map +1 -1
  13. package/dist/units/databases/existing-postgresql/index.js +2 -2
  14. package/dist/units/databases/existing-postgresql/index.js.map +1 -1
  15. package/dist/units/databases/existing-redis/index.js +2 -2
  16. package/dist/units/databases/existing-redis/index.js.map +1 -1
  17. package/dist/units/databases/existing-s3/index.js +18 -0
  18. package/dist/units/databases/existing-s3/index.js.map +1 -0
  19. package/dist/units/databases/mariadb-patch/index.js +24 -0
  20. package/dist/units/databases/mariadb-patch/index.js.map +1 -0
  21. package/dist/units/databases/mongodb-patch/index.js +24 -0
  22. package/dist/units/databases/mongodb-patch/index.js.map +1 -0
  23. package/dist/units/databases/postgresql-patch/index.js +24 -0
  24. package/dist/units/databases/postgresql-patch/index.js.map +1 -0
  25. package/dist/units/databases/redis-patch/index.js +27 -0
  26. package/dist/units/databases/redis-patch/index.js.map +1 -0
  27. package/dist/units/databases/s3-patch/index.js +25 -0
  28. package/dist/units/databases/s3-patch/index.js.map +1 -0
  29. package/dist/units/dns/record-set/index.js +14 -20
  30. package/dist/units/dns/record-set/index.js.map +1 -1
  31. package/dist/units/existing-server/index.js +3 -4
  32. package/dist/units/existing-server/index.js.map +1 -1
  33. package/dist/units/network/address-space/index.js +20 -0
  34. package/dist/units/network/address-space/index.js.map +1 -0
  35. package/dist/units/network/endpoint-filter/index.js +15 -0
  36. package/dist/units/network/endpoint-filter/index.js.map +1 -0
  37. package/dist/units/network/l3-endpoint/index.js +2 -2
  38. package/dist/units/network/l3-endpoint/index.js.map +1 -1
  39. package/dist/units/network/l4-endpoint/index.js +2 -2
  40. package/dist/units/network/l4-endpoint/index.js.map +1 -1
  41. package/dist/units/network/l7-endpoint/index.js +12 -0
  42. package/dist/units/network/l7-endpoint/index.js.map +1 -0
  43. package/dist/units/script/index.js +1 -1
  44. package/dist/units/server-patch/index.js +9 -12
  45. package/dist/units/server-patch/index.js.map +1 -1
  46. package/dist/units/ssh/key-pair/index.js +1 -1
  47. package/package.json +64 -10
  48. package/src/shared/command.ts +1 -1
  49. package/src/shared/dns.ts +11 -93
  50. package/src/shared/files.ts +3 -3
  51. package/src/shared/impl-ref.ts +4 -0
  52. package/src/shared/index.ts +2 -0
  53. package/src/shared/network/address-space.spec.ts +114 -0
  54. package/src/shared/network/address-space.ts +364 -0
  55. package/src/shared/network/address.spec.ts +109 -0
  56. package/src/shared/network/address.ts +119 -0
  57. package/src/shared/network/endpoints.spec.ts +249 -0
  58. package/src/shared/network/endpoints.ts +608 -0
  59. package/src/shared/network/index.ts +4 -0
  60. package/src/shared/network/ip.ts +236 -0
  61. package/src/shared/network/subnet.spec.ts +62 -0
  62. package/src/shared/network/subnet.ts +137 -0
  63. package/src/shared/ssh.ts +1 -1
  64. package/src/shared/tls.ts +21 -5
  65. package/src/shared/utils.ts +93 -0
  66. package/src/units/databases/etcd-patch/index.ts +23 -0
  67. package/src/units/databases/existing-etcd/index.ts +11 -0
  68. package/src/units/databases/existing-mariadb/index.ts +1 -1
  69. package/src/units/databases/existing-mongodb/index.ts +1 -1
  70. package/src/units/databases/existing-postgresql/index.ts +1 -1
  71. package/src/units/databases/existing-redis/index.ts +1 -1
  72. package/src/units/databases/existing-s3/index.ts +1 -1
  73. package/src/units/databases/mariadb-patch/index.ts +27 -0
  74. package/src/units/databases/mongodb-patch/index.ts +27 -0
  75. package/src/units/databases/postgresql-patch/index.ts +27 -0
  76. package/src/units/databases/redis-patch/index.ts +32 -0
  77. package/src/units/databases/s3-patch/index.ts +28 -0
  78. package/src/units/dns/record-set/index.ts +15 -20
  79. package/src/units/existing-server/index.ts +3 -4
  80. package/src/units/network/address-space/index.ts +20 -0
  81. package/src/units/network/endpoint-filter/index.ts +5 -5
  82. package/src/units/network/l3-endpoint/index.ts +2 -2
  83. package/src/units/network/l4-endpoint/index.ts +2 -2
  84. package/src/units/network/l7-endpoint/index.ts +2 -2
  85. package/src/units/remote-file/index.ts +12 -5
  86. package/src/units/server-patch/index.ts +10 -13
  87. package/dist/chunk-WFWXDYUX.js.map +0 -1
  88. package/dist/units/server-dns/index.js +0 -26
  89. package/dist/units/server-dns/index.js.map +0 -1
  90. package/src/shared/network.ts +0 -413
  91. package/src/units/server-dns/index.ts +0 -26
@@ -1,413 +0,0 @@
1
- import type { ArrayPatchMode, network } from "@highstate/library"
2
- import { type Input, toPromise } from "@highstate/pulumi"
3
- import { uniqueBy } from "remeda"
4
-
5
- /**
6
- * The L3 or L4 endpoint for some service.
7
- *
8
- * The format is: `[protocol://]endpoint[:port]`
9
- */
10
- export type InputL34Endpoint = network.L34Endpoint | string
11
-
12
- /**
13
- * The L3 endpoint for some service.
14
- */
15
- export type InputL3Endpoint = network.L3Endpoint | string
16
-
17
- /**
18
- * The L4 endpoint for some service.
19
- */
20
- export type InputL4Endpoint = network.L4Endpoint | string
21
-
22
- /**
23
- * The L7 endpoint for some service.
24
- *
25
- * The format is: `appProtocol://endpoint[:port][/resource]`
26
- */
27
- export type InputL7Endpoint = network.L7Endpoint | string
28
-
29
- /**
30
- * Stringifies a L3 endpoint object into a string.
31
- *
32
- * @param l3Endpoint The L3 endpoint object to stringify.
33
- * @returns The string representation of the L3 endpoint.
34
- */
35
- export function l3EndpointToString(l3Endpoint: network.L3Endpoint): string {
36
- switch (l3Endpoint.type) {
37
- case "ipv4":
38
- return l3Endpoint.address
39
- case "ipv6":
40
- return l3Endpoint.address
41
- case "hostname":
42
- return l3Endpoint.hostname
43
- }
44
- }
45
-
46
- /**
47
- * Stringifies a L4 endpoint object into a string.
48
- *
49
- * @param l4Endpoint The L4 endpoint object to stringify.
50
- * @returns The string representation of the L4 endpoint.
51
- */
52
- export function l4EndpointToString(l4Endpoint: network.L4Endpoint): string {
53
- if (l4Endpoint.type === "ipv6") {
54
- return `[${l4Endpoint.address}]:${l4Endpoint.port}`
55
- }
56
-
57
- return `${l3EndpointToString(l4Endpoint)}:${l4Endpoint.port}`
58
- }
59
-
60
- /**
61
- * Stringifies a L4 endpoint object into a string with protocol.
62
- *
63
- * @param l4Endpoint The L4 endpoint object to stringify.
64
- * @returns The string representation of the L4 endpoint with protocol.
65
- */
66
- export function l4EndpointWithProtocolToString(l4Endpoint: network.L4Endpoint): string {
67
- const protocol = `${l4Endpoint.protocol}://`
68
-
69
- return `${protocol}${l4EndpointToString(l4Endpoint)}`
70
- }
71
-
72
- /**
73
- * Stringifies a L7 endpoint object into a string.
74
- *
75
- * The format is: `appProtocol://endpoint[:port][/resource]`
76
- * @param l7Endpoint The L7 endpoint object to stringify.
77
- * @returns The string representation of the L7 endpoint.
78
- */
79
- export function l7EndpointToString(l7Endpoint: network.L7Endpoint): string {
80
- const protocol = `${l7Endpoint.appProtocol}://`
81
-
82
- let endpoint = l4EndpointToString(l7Endpoint)
83
-
84
- if (l7Endpoint.resource) {
85
- endpoint += `/${l7Endpoint.resource}`
86
- }
87
-
88
- return `${protocol}${endpoint}`
89
- }
90
-
91
- /**
92
- * Stringifies a L3 or L4 endpoint object into a string.
93
- *
94
- * @param l34Endpoint The L3 or L4 endpoint object to stringify.
95
- * @returns The string representation of the L3 or L4 endpoint.
96
- */
97
- export function l34EndpointToString(l34Endpoint: network.L34Endpoint): string {
98
- if (l34Endpoint.port) {
99
- return l4EndpointToString(l34Endpoint)
100
- }
101
-
102
- return l3EndpointToString(l34Endpoint)
103
- }
104
-
105
- const L34_ENDPOINT_RE =
106
- /^(?:(?<protocol>[a-z]+):\/\/)?(?:(?:\[?(?<ipv6>[0-9A-Fa-f:]+)\]?)|(?<ipv4>(?:\d{1,3}\.){3}\d{1,3})|(?<hostname>[a-zA-Z0-9-*]+(?:\.[a-zA-Z0-9-*]+)*))(?::(?<port>\d{1,5}))?$/
107
-
108
- const L7_ENDPOINT_RE =
109
- /^(?<appProtocol>[a-z]+):\/\/(?:(?:\[?(?<ipv6>[0-9A-Fa-f:]+)\]?)|(?<ipv4>(?:\d{1,3}\.){3}\d{1,3})|(?<hostname>[a-zA-Z0-9-*]+(?:\.[a-zA-Z0-9-*]+)*))(?::(?<port>\d{1,5}))?(?:\/(?<resource>.*))?$/
110
-
111
- /**
112
- * Parses a L3 or L4 endpoint from a string.
113
- *
114
- * The format is `[protocol://]endpoint[:port]`.
115
- *
116
- * @param l34Endpoint The L3 or L4 endpoint string to parse.
117
- * @returns The parsed L3 or L4 endpoint object.
118
- */
119
- export function parseL34Endpoint(l34Endpoint: InputL34Endpoint): network.L34Endpoint {
120
- if (typeof l34Endpoint === "object") {
121
- return l34Endpoint
122
- }
123
-
124
- const match = l34Endpoint.match(L34_ENDPOINT_RE)
125
- if (!match) {
126
- throw new Error(`Invalid L3/L4 endpoint: "${l34Endpoint}"`)
127
- }
128
-
129
- const { protocol, ipv6, ipv4, hostname, port } = match.groups!
130
-
131
- if (protocol && protocol !== "tcp" && protocol !== "udp") {
132
- throw new Error(`Invalid L4 endpoint protocol: "${protocol}"`)
133
- }
134
-
135
- let visibility: network.EndpointVisibility = "public"
136
-
137
- if (ipv4 && IPV4_PRIVATE_REGEX.test(ipv4)) {
138
- visibility = "external"
139
- } else if (ipv6 && IPV6_PRIVATE_REGEX.test(ipv6)) {
140
- visibility = "external"
141
- }
142
-
143
- const fallbackProtocol = port ? "tcp" : undefined
144
-
145
- return {
146
- type: ipv6 ? "ipv6" : ipv4 ? "ipv4" : "hostname",
147
- visibility,
148
- address: ipv6 || ipv4,
149
- hostname: hostname,
150
- port: port ? parseInt(port, 10) : undefined,
151
- protocol: protocol ? (protocol as network.L4Protocol) : fallbackProtocol,
152
- } as network.L34Endpoint
153
- }
154
-
155
- /**
156
- * Parses a L3 endpoint from a string.
157
- *
158
- * The same as `parseL34Endpoint`, but only for L3 endpoints and will throw an error if the endpoint contains a port.
159
- *
160
- * @param l3Endpoint The L3 endpoint string to parse.
161
- * @returns The parsed L3 endpoint object.
162
- */
163
- export function parseL3Endpoint(l3Endpoint: InputL3Endpoint): network.L3Endpoint {
164
- if (typeof l3Endpoint === "object") {
165
- return l3Endpoint
166
- }
167
-
168
- const parsed = parseL34Endpoint(l3Endpoint)
169
-
170
- if (parsed.port) {
171
- throw new Error(`Port cannot be specified in L3 endpoint: "${l3Endpoint}"`)
172
- }
173
-
174
- return parsed
175
- }
176
-
177
- /**
178
- * Parses a L4 endpoint from a string.
179
- *
180
- * The same as `parseL34Endpoint`, but only for L4 endpoints and will throw an error if the endpoint does not contain a port.
181
- */
182
- export function parseL4Endpoint(l4Endpoint: InputL4Endpoint): network.L4Endpoint {
183
- if (typeof l4Endpoint === "object") {
184
- return l4Endpoint
185
- }
186
-
187
- const parsed = parseL34Endpoint(l4Endpoint)
188
-
189
- if (!parsed.port) {
190
- throw new Error(`No port found in L4 endpoint: "${l4Endpoint}"`)
191
- }
192
-
193
- return parsed
194
- }
195
-
196
- const IPV4_PRIVATE_REGEX =
197
- /^(?:10|127)(?:\.\d{1,3}){3}$|^(?:172\.1[6-9]|172\.2[0-9]|172\.3[0-1])(?:\.\d{1,3}){2}$|^(?:192\.168)(?:\.\d{1,3}){2}$/
198
-
199
- const IPV6_PRIVATE_REGEX =
200
- /^(?:fc|fd)(?:[0-9a-f]{2}){0,2}::(?:[0-9a-f]{1,4}:){7}[0-9a-f]{1,4}$|^::(?:ffff:(?:10|127)(?:\.\d{1,3}){3}|(?:172\.1[6-9]|172\.2[0-9]|172\.3[0-1])(?:\.\d{1,3}){2}|(?:192\.168)(?:\.\d{1,3}){2})$/
201
-
202
- /**
203
- * Helper function to get the input L3 endpoint from the raw endpoint or input endpoint.
204
- *
205
- * If neither is provided, an error is thrown.
206
- *
207
- * @param rawEndpoint The raw endpoint string to parse.
208
- * @param inputEndpoint The input endpoint object to use if the raw endpoint is not provided.
209
- * @returns The parsed L3 endpoint object.
210
- */
211
- export async function requireInputL3Endpoint(
212
- rawEndpoint: string | undefined,
213
- inputEndpoint: Input<network.L3Endpoint> | undefined,
214
- ): Promise<network.L3Endpoint> {
215
- if (rawEndpoint) {
216
- return parseL3Endpoint(rawEndpoint)
217
- }
218
-
219
- if (inputEndpoint) {
220
- return toPromise(inputEndpoint)
221
- }
222
-
223
- throw new Error("No endpoint provided")
224
- }
225
-
226
- /**
227
- * Helper function to get the input L4 endpoint from the raw endpoint or input endpoint.
228
- *
229
- * If neither is provided, an error is thrown.
230
- *
231
- * @param rawEndpoint The raw endpoint string to parse.
232
- * @param inputEndpoint The input endpoint object to use if the raw endpoint is not provided.
233
- * @returns The parsed L4 endpoint object.
234
- */
235
- export async function requireInputL4Endpoint(
236
- rawEndpoint: string | undefined,
237
- inputEndpoint: Input<network.L4Endpoint> | undefined,
238
- ): Promise<network.L4Endpoint> {
239
- if (rawEndpoint) {
240
- return parseL4Endpoint(rawEndpoint)
241
- }
242
-
243
- if (inputEndpoint) {
244
- return toPromise(inputEndpoint)
245
- }
246
-
247
- throw new Error("No endpoint provided")
248
- }
249
-
250
- /**
251
- * Converts L3 endpoint to L4 endpoint by adding a port and protocol.
252
- *
253
- * @param l3Endpoint The L3 endpoint to convert.
254
- * @param port The port to add to the L3 endpoint.
255
- * @param protocol The protocol to add to the L3 endpoint. Defaults to "tcp".
256
- * @returns The L4 endpoint with the port and protocol added.
257
- */
258
- export function l3EndpointToL4(
259
- l3Endpoint: InputL3Endpoint,
260
- port: number,
261
- protocol: network.L4Protocol = "tcp",
262
- ): network.L4Endpoint {
263
- return {
264
- ...parseL3Endpoint(l3Endpoint),
265
- port,
266
- protocol,
267
- }
268
- }
269
-
270
- /**
271
- * Filters the endpoints based on the given filter.
272
- *
273
- * @param endpoints The list of endpoints to filter.
274
- * @param filter The filter to apply. If not provided, the endpoints will be filtered by the most accessible type: `public` > `external` > `internal`.
275
- * @param types The list of endpoint types to filter by. If provided, only endpoints of these types will be returned.
276
- *
277
- * @returns The filtered list of endpoints.
278
- */
279
- export function filterEndpoints<
280
- TEndpoint extends network.L34Endpoint,
281
- TType extends network.L34Endpoint["type"],
282
- >(
283
- endpoints: TEndpoint[],
284
- filter?: network.EndpointFilter,
285
- types?: TType[],
286
- ): (TEndpoint & { type: TType })[] {
287
- if (filter?.length) {
288
- endpoints = endpoints.filter(endpoint => filter.includes(endpoint.visibility))
289
- } else if (endpoints.some(endpoint => endpoint.visibility === "public")) {
290
- endpoints = endpoints.filter(endpoint => endpoint.visibility === "public")
291
- } else if (endpoints.some(endpoint => endpoint.visibility === "external")) {
292
- endpoints = endpoints.filter(endpoint => endpoint.visibility === "external")
293
- }
294
-
295
- if (types?.length) {
296
- endpoints = endpoints.filter(endpoint => types.includes(endpoint.type as TType))
297
- }
298
-
299
- return endpoints as (TEndpoint & { type: TType })[]
300
- }
301
-
302
- /**
303
- * Converts a L3 endpoint to CIDR notation.
304
- *
305
- * If the endpoint is a hostname, an error is thrown.
306
- *
307
- * @param l3Endpoint The L3 endpoint to convert.
308
- * @returns The CIDR notation of the L3 endpoint.
309
- */
310
- export function l3EndpointToCidr(l3Endpoint: network.L3Endpoint): string {
311
- switch (l3Endpoint.type) {
312
- case "ipv4":
313
- return `${l3Endpoint.address}/32`
314
- case "ipv6":
315
- return `${l3Endpoint.address}/128`
316
- case "hostname":
317
- throw new Error("Cannot convert hostname to CIDR")
318
- }
319
- }
320
-
321
- const udpAppProtocols = ["dns", "dhcp"]
322
-
323
- /**
324
- * Parses a L7 endpoint from a string.
325
- *
326
- * The format is: `appProtocol://endpoint[:port][/resource]`
327
- *
328
- * @param l7Endpoint The L7 endpoint string to parse.
329
- * @returns The parsed L7 endpoint object.
330
- */
331
- export function parseL7Endpoint(l7Endpoint: InputL7Endpoint): network.L7Endpoint {
332
- if (typeof l7Endpoint === "object") {
333
- return l7Endpoint
334
- }
335
-
336
- const match = l7Endpoint.match(L7_ENDPOINT_RE)
337
- if (!match) {
338
- throw new Error(`Invalid L7 endpoint: "${l7Endpoint}"`)
339
- }
340
-
341
- const { appProtocol, ipv6, ipv4, hostname, port, resource } = match.groups!
342
-
343
- let visibility: network.EndpointVisibility = "public"
344
-
345
- if (ipv4 && IPV4_PRIVATE_REGEX.test(ipv4)) {
346
- visibility = "external"
347
- } else if (ipv6 && IPV6_PRIVATE_REGEX.test(ipv6)) {
348
- visibility = "external"
349
- }
350
-
351
- return {
352
- type: ipv6 ? "ipv6" : ipv4 ? "ipv4" : "hostname",
353
- visibility,
354
- address: ipv6 || ipv4,
355
- hostname: hostname,
356
-
357
- // Default port for L7 endpoints (TODO: add more specific defaults for common protocols)
358
- port: port ? parseInt(port, 10) : 443,
359
-
360
- // L7 endpoints typically use TCP, but can also use UDP for specific protocols
361
- protocol: udpAppProtocols.includes(appProtocol) ? "udp" : "tcp",
362
-
363
- appProtocol,
364
- resource: resource || "",
365
- } as network.L7Endpoint
366
- }
367
-
368
- /**
369
- * Updates the endpoints based on the given mode.
370
- *
371
- * @param currentEndpoints The current endpoints to update.
372
- * @param endpoints The new endpoints to add in string format.
373
- * @param inputEndpoints The input endpoints to add in object format.
374
- * @param mode The mode to use when updating the endpoints. Can be "replace" or "prepend". Defaults to "prepend".
375
- * @returns The updated list of endpoints with duplicates removed.
376
- */
377
- export async function updateEndpoints<TEndpoints extends network.L34Endpoint>(
378
- currentEndpoints: Input<TEndpoints[]>,
379
- endpoints: string[] | undefined,
380
- inputEndpoints: Input<TEndpoints[]> | undefined,
381
- mode: ArrayPatchMode = "prepend",
382
- ): Promise<TEndpoints[]> {
383
- const resolvedCurrentEndpoints = await toPromise(currentEndpoints)
384
- const newEndpoints = await parseEndpoints(endpoints, inputEndpoints)
385
-
386
- if (mode === "replace") {
387
- return newEndpoints as TEndpoints[]
388
- }
389
-
390
- return uniqueBy(
391
- [...newEndpoints, ...resolvedCurrentEndpoints],
392
- l34EndpointToString,
393
- ) as TEndpoints[]
394
- }
395
-
396
- /**
397
- * Parses a list of endpoints from strings and input objects.
398
- *
399
- * @param endpoints The list of endpoint strings to parse.
400
- * @param inputEndpoints The list of input endpoint objects to use.
401
- * @returns The parsed list of endpoint objects with duplicates removed.
402
- */
403
- export async function parseEndpoints<TEndpoints extends network.L34Endpoint>(
404
- endpoints: string[] | undefined,
405
- inputEndpoints: Input<TEndpoints[]> | undefined,
406
- ): Promise<TEndpoints[]> {
407
- const resolvedInputEndpoints = await toPromise(inputEndpoints)
408
-
409
- return uniqueBy(
410
- [...(endpoints?.map(parseL34Endpoint) ?? []), ...(resolvedInputEndpoints ?? [])],
411
- l34EndpointToString,
412
- ) as TEndpoints[]
413
- }
@@ -1,26 +0,0 @@
1
- import { common } from "@highstate/library"
2
- import { forUnit } from "@highstate/pulumi"
3
- import { l3EndpointToString, updateEndpointsWithFqdn } from "../../shared"
4
-
5
- const { args, inputs, outputs } = forUnit(common.serverDns)
6
-
7
- const { endpoints } = await updateEndpointsWithFqdn(
8
- inputs.server.endpoints,
9
- args.fqdn,
10
- args.endpointFilter,
11
- args.patchMode,
12
- inputs.dnsProviders,
13
- )
14
-
15
- export default outputs({
16
- server: inputs.server.apply(server => ({
17
- ...server,
18
- endpoints,
19
- })),
20
-
21
- endpoints,
22
-
23
- $statusFields: {
24
- endpoints: endpoints.map(l3EndpointToString),
25
- },
26
- })