@highstate/restic 0.9.8 → 0.9.10

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.
@@ -2,9 +2,10 @@ import "../chunk-G3PMV62Z.js";
2
2
 
3
3
  // src/repo/index.ts
4
4
  import { restic } from "@highstate/library";
5
- import { forUnit, getOrCreateSecret } from "@highstate/pulumi";
6
- import { generatePassword } from "@highstate/common";
7
- var { args, secrets, outputs } = forUnit(restic.repo);
5
+ import { forUnit, toPromise } from "@highstate/pulumi";
6
+ import { l34EndpointToString, parseL34Endpoint } from "@highstate/common";
7
+ import { uniqueBy } from "remeda";
8
+ var { args, inputs, secrets, outputs } = forUnit(restic.repo);
8
9
  var remoteName = secrets.rcloneConfig.apply((config) => {
9
10
  const remoteNames = Array.from(config.matchAll(/(?<=\[).+?(?=\])/g));
10
11
  if (remoteNames.length === 0) {
@@ -15,20 +16,30 @@ var remoteName = secrets.rcloneConfig.apply((config) => {
15
16
  }
16
17
  return remoteNames[0][0];
17
18
  });
18
- var password = getOrCreateSecret(secrets, "password", generatePassword);
19
- var basePath = args.basePath?.replace(/\/$/, "") ?? "backups";
19
+ var { remoteL3Endpoints, remoteL4Endpoints } = await toPromise(inputs);
20
+ var remoteEndpoints = uniqueBy(
21
+ [
22
+ //
23
+ ...args.remoteEndpoints.map(parseL34Endpoint),
24
+ ...remoteL3Endpoints,
25
+ ...remoteL4Endpoints
26
+ ],
27
+ l34EndpointToString
28
+ );
20
29
  var repo_default = outputs({
21
30
  repo: {
22
- password,
23
31
  type: "rclone",
32
+ pathPattern: args.pathPattern,
24
33
  rcloneConfig: secrets.rcloneConfig,
25
34
  remoteName,
26
- remoteEndpoints: args.remoteDomains ?? [],
27
- basePath
35
+ remoteEndpoints
28
36
  },
29
37
  $status: {
30
38
  remoteName,
31
- basePath
39
+ remoteEndpoints: {
40
+ value: remoteEndpoints.map(l34EndpointToString),
41
+ complementaryTo: "remoteEndpoints"
42
+ }
32
43
  }
33
44
  });
34
45
  export {
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/repo/index.ts"],"sourcesContent":["import { restic } from \"@highstate/library\"\nimport { forUnit, getOrCreateSecret } from \"@highstate/pulumi\"\nimport { generatePassword } from \"@highstate/common\"\n\nconst { args, secrets, outputs } = forUnit(restic.repo)\n\nconst remoteName = secrets.rcloneConfig.apply(config => {\n const remoteNames = Array.from(config.matchAll(/(?<=\\[).+?(?=\\])/g))\n\n if (remoteNames.length === 0) {\n throw new Error(\"No remotes found in rclone config\")\n }\n\n if (remoteNames.length > 1) {\n throw new Error(\"Multiple remotes found in rclone config\")\n }\n\n return remoteNames[0][0]\n})\n\nconst password = getOrCreateSecret(secrets, \"password\", generatePassword)\nconst basePath = args.basePath?.replace(/\\/$/, \"\") ?? \"backups\"\n\nexport default outputs({\n repo: {\n password,\n type: \"rclone\",\n rcloneConfig: secrets.rcloneConfig,\n remoteName,\n remoteEndpoints: args.remoteDomains ?? [],\n basePath,\n },\n $status: {\n remoteName,\n basePath,\n },\n})\n"],"mappings":";;;AAAA,SAAS,cAAc;AACvB,SAAS,SAAS,yBAAyB;AAC3C,SAAS,wBAAwB;AAEjC,IAAM,EAAE,MAAM,SAAS,QAAQ,IAAI,QAAQ,OAAO,IAAI;AAEtD,IAAM,aAAa,QAAQ,aAAa,MAAM,YAAU;AACtD,QAAM,cAAc,MAAM,KAAK,OAAO,SAAS,mBAAmB,CAAC;AAEnE,MAAI,YAAY,WAAW,GAAG;AAC5B,UAAM,IAAI,MAAM,mCAAmC;AAAA,EACrD;AAEA,MAAI,YAAY,SAAS,GAAG;AAC1B,UAAM,IAAI,MAAM,yCAAyC;AAAA,EAC3D;AAEA,SAAO,YAAY,CAAC,EAAE,CAAC;AACzB,CAAC;AAED,IAAM,WAAW,kBAAkB,SAAS,YAAY,gBAAgB;AACxE,IAAM,WAAW,KAAK,UAAU,QAAQ,OAAO,EAAE,KAAK;AAEtD,IAAO,eAAQ,QAAQ;AAAA,EACrB,MAAM;AAAA,IACJ;AAAA,IACA,MAAM;AAAA,IACN,cAAc,QAAQ;AAAA,IACtB;AAAA,IACA,iBAAiB,KAAK,iBAAiB,CAAC;AAAA,IACxC;AAAA,EACF;AAAA,EACA,SAAS;AAAA,IACP;AAAA,IACA;AAAA,EACF;AACF,CAAC;","names":[]}
1
+ {"version":3,"sources":["../../src/repo/index.ts"],"sourcesContent":["import { restic } from \"@highstate/library\"\nimport { forUnit, toPromise } from \"@highstate/pulumi\"\nimport { l34EndpointToString, parseL34Endpoint } from \"@highstate/common\"\nimport { uniqueBy } from \"remeda\"\n\nconst { args, inputs, secrets, outputs } = forUnit(restic.repo)\n\nconst remoteName = secrets.rcloneConfig.apply(config => {\n const remoteNames = Array.from(config.matchAll(/(?<=\\[).+?(?=\\])/g))\n\n if (remoteNames.length === 0) {\n throw new Error(\"No remotes found in rclone config\")\n }\n\n if (remoteNames.length > 1) {\n throw new Error(\"Multiple remotes found in rclone config\")\n }\n\n return remoteNames[0][0]\n})\n\nconst { remoteL3Endpoints, remoteL4Endpoints } = await toPromise(inputs)\n\nconst remoteEndpoints = uniqueBy(\n [\n //\n ...args.remoteEndpoints.map(parseL34Endpoint),\n ...remoteL3Endpoints,\n ...remoteL4Endpoints,\n ],\n l34EndpointToString,\n)\n\nexport default outputs({\n repo: {\n type: \"rclone\",\n pathPattern: args.pathPattern,\n rcloneConfig: secrets.rcloneConfig,\n remoteName,\n remoteEndpoints,\n },\n\n $status: {\n remoteName,\n\n remoteEndpoints: {\n value: remoteEndpoints.map(l34EndpointToString),\n complementaryTo: \"remoteEndpoints\",\n },\n },\n})\n"],"mappings":";;;AAAA,SAAS,cAAc;AACvB,SAAS,SAAS,iBAAiB;AACnC,SAAS,qBAAqB,wBAAwB;AACtD,SAAS,gBAAgB;AAEzB,IAAM,EAAE,MAAM,QAAQ,SAAS,QAAQ,IAAI,QAAQ,OAAO,IAAI;AAE9D,IAAM,aAAa,QAAQ,aAAa,MAAM,YAAU;AACtD,QAAM,cAAc,MAAM,KAAK,OAAO,SAAS,mBAAmB,CAAC;AAEnE,MAAI,YAAY,WAAW,GAAG;AAC5B,UAAM,IAAI,MAAM,mCAAmC;AAAA,EACrD;AAEA,MAAI,YAAY,SAAS,GAAG;AAC1B,UAAM,IAAI,MAAM,yCAAyC;AAAA,EAC3D;AAEA,SAAO,YAAY,CAAC,EAAE,CAAC;AACzB,CAAC;AAED,IAAM,EAAE,mBAAmB,kBAAkB,IAAI,MAAM,UAAU,MAAM;AAEvE,IAAM,kBAAkB;AAAA,EACtB;AAAA;AAAA,IAEE,GAAG,KAAK,gBAAgB,IAAI,gBAAgB;AAAA,IAC5C,GAAG;AAAA,IACH,GAAG;AAAA,EACL;AAAA,EACA;AACF;AAEA,IAAO,eAAQ,QAAQ;AAAA,EACrB,MAAM;AAAA,IACJ,MAAM;AAAA,IACN,aAAa,KAAK;AAAA,IAClB,cAAc,QAAQ;AAAA,IACtB;AAAA,IACA;AAAA,EACF;AAAA,EAEA,SAAS;AAAA,IACP;AAAA,IAEA,iBAAiB;AAAA,MACf,OAAO,gBAAgB,IAAI,mBAAmB;AAAA,MAC9C,iBAAiB;AAAA,IACnB;AAAA,EACF;AACF,CAAC;","names":[]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@highstate/restic",
3
- "version": "0.9.8",
3
+ "version": "0.9.10",
4
4
  "type": "module",
5
5
  "files": [
6
6
  "dist",
@@ -20,14 +20,15 @@
20
20
  "build": "highstate build"
21
21
  },
22
22
  "dependencies": {
23
- "@highstate/common": "^0.9.8",
24
- "@highstate/k8s": "^0.9.8",
25
- "@highstate/library": "^0.9.8",
26
- "@highstate/pulumi": "^0.9.8",
27
- "@pulumi/kubernetes": "^4.18.0"
23
+ "@highstate/common": "^0.9.10",
24
+ "@highstate/k8s": "^0.9.10",
25
+ "@highstate/library": "^0.9.10",
26
+ "@highstate/pulumi": "^0.9.10",
27
+ "@pulumi/kubernetes": "^4.18.0",
28
+ "remeda": "^2.21.0"
28
29
  },
29
30
  "devDependencies": {
30
- "@highstate/cli": "^0.9.8"
31
+ "@highstate/cli": "^0.9.10"
31
32
  },
32
- "gitHead": "036db4d9937ff30edf15f143482c5702e5b7a7fb"
33
+ "gitHead": "aacf8837fdf40f2bb2f83d4c11b35a358e26ec33"
33
34
  }
package/src/job-pair.ts CHANGED
@@ -1,12 +1,12 @@
1
1
  import type { k8s, restic } from "@highstate/library"
2
2
  import type { InputL34Endpoint } from "@highstate/common"
3
- import { batch, core } from "@pulumi/kubernetes"
3
+ import { batch } from "@pulumi/kubernetes"
4
4
  import {
5
5
  createScriptContainer,
6
6
  CronJob,
7
7
  Job,
8
- mapMetadata,
9
8
  ScriptBundle,
9
+ Secret,
10
10
  type CommonArgs,
11
11
  type Container,
12
12
  type ScriptDistribution,
@@ -15,6 +15,7 @@ import {
15
15
  } from "@highstate/k8s"
16
16
  import {
17
17
  ComponentResource,
18
+ getUnitInstanceName,
18
19
  normalize,
19
20
  output,
20
21
  Output,
@@ -38,6 +39,11 @@ export type BackupJobPairArgs = CommonArgs & {
38
39
  */
39
40
  resticRepo: Input<restic.Repo>
40
41
 
42
+ /**
43
+ * The password used to encrypt the backups.
44
+ */
45
+ backupPassword: Input<string>
46
+
41
47
  /**
42
48
  * The extra script environment to pass to the backup and restore scripts.
43
49
  */
@@ -99,7 +105,7 @@ export class BackupJobPair extends ComponentResource {
99
105
  /**
100
106
  * The credentials used to access the repository and encrypt the backups.
101
107
  */
102
- readonly credentials: Output<core.v1.Secret>
108
+ readonly credentials: Output<Secret>
103
109
 
104
110
  /**
105
111
  * The script bundle used by the backup and restore jobs.
@@ -124,13 +130,14 @@ export class BackupJobPair extends ComponentResource {
124
130
  super("highstate:restic:BackupJobPair", name, args, opts)
125
131
 
126
132
  this.credentials = output(args).apply(args => {
127
- return new core.v1.Secret(
133
+ return Secret.create(
128
134
  `${name}-backup-credentials`,
129
135
  {
130
- metadata: mapMetadata(args, `${name}-backup-credentials`),
136
+ namespace: args.namespace,
137
+ cluster: args.cluster,
131
138
 
132
139
  stringData: {
133
- password: args.resticRepo.password,
140
+ password: args.backupPassword,
134
141
  "rclone.conf": args.resticRepo.rcloneConfig,
135
142
  },
136
143
  },
@@ -139,6 +146,11 @@ export class BackupJobPair extends ComponentResource {
139
146
  })
140
147
 
141
148
  const environment = output(args).apply(args => {
149
+ const repositoryPath = args.resticRepo.pathPattern
150
+ .replace(/\$clusterName/g, args.cluster.name)
151
+ .replace(/\$appName/g, name)
152
+ .replace(/\$unitName/g, getUnitInstanceName())
153
+
142
154
  return {
143
155
  alpine: {
144
156
  packages: ["rclone"],
@@ -165,7 +177,7 @@ export class BackupJobPair extends ComponentResource {
165
177
  },
166
178
 
167
179
  environment: {
168
- RESTIC_REPOSITORY: `rclone:${args.resticRepo.remoteName}:${args.resticRepo.basePath}/${args.cluster.name}/${name}`,
180
+ RESTIC_REPOSITORY: `rclone:${args.resticRepo.remoteName}:${repositoryPath}`,
169
181
  RESTIC_PASSWORD_FILE: "/credentials/password",
170
182
  RESTIC_HOSTNAME: "default",
171
183
  RCLONE_CONFIG: "/credentials/rclone.conf",
@@ -224,6 +236,8 @@ export class BackupJobPair extends ComponentResource {
224
236
  main: "restore.sh",
225
237
  bundle: this.scriptBundle,
226
238
  }),
239
+
240
+ backoffLimit: 2,
227
241
  },
228
242
  { ...opts, parent: this },
229
243
  )
@@ -248,12 +262,7 @@ export class BackupJobPair extends ComponentResource {
248
262
 
249
263
  jobTemplate: {
250
264
  spec: {
251
- backoffLimit: 1,
252
- template: {
253
- spec: {
254
- restartPolicy: "Never",
255
- },
256
- },
265
+ backoffLimit: 2,
257
266
  },
258
267
  },
259
268
  },
package/src/repo/index.ts CHANGED
@@ -1,8 +1,9 @@
1
1
  import { restic } from "@highstate/library"
2
- import { forUnit, getOrCreateSecret } from "@highstate/pulumi"
3
- import { generatePassword } from "@highstate/common"
2
+ import { forUnit, toPromise } from "@highstate/pulumi"
3
+ import { l34EndpointToString, parseL34Endpoint } from "@highstate/common"
4
+ import { uniqueBy } from "remeda"
4
5
 
5
- const { args, secrets, outputs } = forUnit(restic.repo)
6
+ const { args, inputs, secrets, outputs } = forUnit(restic.repo)
6
7
 
7
8
  const remoteName = secrets.rcloneConfig.apply(config => {
8
9
  const remoteNames = Array.from(config.matchAll(/(?<=\[).+?(?=\])/g))
@@ -18,20 +19,33 @@ const remoteName = secrets.rcloneConfig.apply(config => {
18
19
  return remoteNames[0][0]
19
20
  })
20
21
 
21
- const password = getOrCreateSecret(secrets, "password", generatePassword)
22
- const basePath = args.basePath?.replace(/\/$/, "") ?? "backups"
22
+ const { remoteL3Endpoints, remoteL4Endpoints } = await toPromise(inputs)
23
+
24
+ const remoteEndpoints = uniqueBy(
25
+ [
26
+ //
27
+ ...args.remoteEndpoints.map(parseL34Endpoint),
28
+ ...remoteL3Endpoints,
29
+ ...remoteL4Endpoints,
30
+ ],
31
+ l34EndpointToString,
32
+ )
23
33
 
24
34
  export default outputs({
25
35
  repo: {
26
- password,
27
36
  type: "rclone",
37
+ pathPattern: args.pathPattern,
28
38
  rcloneConfig: secrets.rcloneConfig,
29
39
  remoteName,
30
- remoteEndpoints: args.remoteDomains ?? [],
31
- basePath,
40
+ remoteEndpoints,
32
41
  },
42
+
33
43
  $status: {
34
44
  remoteName,
35
- basePath,
45
+
46
+ remoteEndpoints: {
47
+ value: remoteEndpoints.map(l34EndpointToString),
48
+ complementaryTo: "remoteEndpoints",
49
+ },
36
50
  },
37
51
  })