@hiiretail/gcp-infra-cli 0.74.0 → 0.75.2

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/README.md CHANGED
@@ -39,7 +39,7 @@ Changelog of key features is available in [CHANGELOG.md](./CHANGELOG.md)
39
39
 
40
40
  Development tools needed are:
41
41
 
42
- * Latest Node 12 LTS release
42
+ * Latest Node 16 LTS release
43
43
  * Docker
44
44
  * Pre-commit
45
45
 
@@ -1,7 +1,15 @@
1
1
  const yaml = require('js-yaml');
2
2
  const fs = require('fs');
3
3
 
4
- const appendNotIncludePull = async (inputs, subscriptionFilePath) => {
4
+ const addDLQ = async (yamlArray, env, dlqTopic) => {
5
+ if (env === 'prod') {
6
+ /* eslint-disable */
7
+ yamlArray[0].dead_letter_topic = dlqTopic;
8
+ /* eslint-enable */
9
+ }
10
+ };
11
+
12
+ const appendNotIncludePull = async (inputs, subscriptionFilePath, dlqTopic) => {
5
13
  const pullArray = [];
6
14
 
7
15
  pullArray.push(
@@ -12,11 +20,17 @@ const appendNotIncludePull = async (inputs, subscriptionFilePath) => {
12
20
  },
13
21
  );
14
22
 
23
+ await addDLQ(pullArray, inputs.env, dlqTopic);
15
24
  const yamlPullArray = yaml.dump(pullArray);
16
25
  fs.appendFileSync(subscriptionFilePath, `pull_subscriptions:\n${yamlPullArray}`);
17
26
  };
18
27
 
19
- const appendIncludePull = async (fileContent, originalContentYaml, subscriptionFilePath, input) => {
28
+ const appendIncludePull = async (
29
+ fileContent,
30
+ originalContentYaml,
31
+ subscriptionFilePath,
32
+ input,
33
+ dlqTopic) => {
20
34
  if (fileContent.includes('pull_subscriptions')) {
21
35
  const pullArray = Object.values(originalContentYaml.pull_subscriptions);
22
36
  const yamlPullArray = yaml.dump(pullArray);
@@ -33,6 +47,7 @@ const appendIncludePull = async (fileContent, originalContentYaml, subscriptionF
33
47
  },
34
48
  );
35
49
 
50
+ await addDLQ(newPullArray, input.env, dlqTopic);
36
51
  const finalYamlPullArray = yaml.dump(newPullArray);
37
52
  fs.appendFileSync(subscriptionFilePath, finalYamlPullArray);
38
53
 
@@ -43,7 +58,7 @@ const appendIncludePull = async (fileContent, originalContentYaml, subscriptionF
43
58
  }
44
59
  };
45
60
 
46
- const appendNotIncludePush = async (inputs, subscriptionFilePath) => {
61
+ const appendNotIncludePush = async (inputs, subscriptionFilePath, dlqTopic) => {
47
62
  const pushArray = [];
48
63
 
49
64
  pushArray.push(
@@ -56,11 +71,17 @@ const appendNotIncludePush = async (inputs, subscriptionFilePath) => {
56
71
  },
57
72
  );
58
73
 
74
+ await addDLQ(pushArray, inputs.env, dlqTopic);
59
75
  const yamlPushArray = yaml.dump(pushArray);
60
76
  fs.appendFileSync(subscriptionFilePath, `push_subscriptions:\n${yamlPushArray}`);
61
77
  };
62
78
 
63
- const appendIncludePush = async (fileContent, originalContentYaml, subscriptionFilePath, input) => {
79
+ const appendIncludePush = async (
80
+ fileContent,
81
+ originalContentYaml,
82
+ subscriptionFilePath,
83
+ input,
84
+ dlqTopic) => {
64
85
  if (fileContent.includes('push_subscriptions')) {
65
86
  const pushArray = Object.values(originalContentYaml.push_subscriptions);
66
87
  const yamlPushArray = yaml.dump(pushArray);
@@ -78,6 +99,7 @@ const appendIncludePush = async (fileContent, originalContentYaml, subscriptionF
78
99
  expiration_policy: '',
79
100
  },
80
101
  );
102
+ await addDLQ(newPushArray, input.env, dlqTopic);
81
103
  const yamlPushArray = yaml.dump(newPushArray);
82
104
  fs.appendFileSync(subscriptionFilePath, yamlPushArray);
83
105
 
@@ -4,7 +4,13 @@ const {
4
4
  appendNotIncludePull, appendIncludePull, appendNotIncludePush, appendIncludePush,
5
5
  } = require('./append');
6
6
 
7
- const handleSubscribers = async (env, answers, oidcEmail, pushEndpoint, subscriptionFilePath) => {
7
+ const handleSubscribers = async (
8
+ env,
9
+ answers,
10
+ oidcEmail,
11
+ pushEndpoint,
12
+ subscriptionFilePath,
13
+ dlqTopic) => {
8
14
  const {
9
15
  subscriberName,
10
16
  existingTopic,
@@ -22,22 +28,35 @@ const handleSubscribers = async (env, answers, oidcEmail, pushEndpoint, subscrip
22
28
  audience,
23
29
  oidcEmail,
24
30
  pushEndpoint,
31
+ dlqTopic,
25
32
  };
26
33
 
27
34
  if (pushOrPull === 'pull') {
28
35
  if (subscriptionFileContent.length === 0 || !subscriptionFileContent.includes('pull_subscriptions')) {
29
- await appendNotIncludePull(inputs, subscriptionFilePath);
36
+ await appendNotIncludePull(inputs, subscriptionFilePath, dlqTopic);
30
37
  } else {
31
38
  const originalContentYaml = yaml.load(subscriptionFileContent);
32
39
  const fileContent = subscriptionFileContent;
33
- await appendIncludePull(fileContent, originalContentYaml, subscriptionFilePath, inputs);
40
+ await appendIncludePull(
41
+ fileContent,
42
+ originalContentYaml,
43
+ subscriptionFilePath,
44
+ inputs,
45
+ dlqTopic,
46
+ );
34
47
  }
35
48
  } else if (subscriptionFileContent.length === 0 || !subscriptionFileContent.includes('push_subscriptions')) {
36
- await appendNotIncludePush(inputs, subscriptionFilePath);
49
+ await appendNotIncludePush(inputs, subscriptionFilePath, dlqTopic);
37
50
  } else {
38
51
  const originalContentYaml = yaml.load(subscriptionFileContent);
39
52
  const fileContent = subscriptionFileContent;
40
- await appendIncludePush(fileContent, originalContentYaml, subscriptionFilePath, inputs);
53
+ await appendIncludePush(
54
+ fileContent,
55
+ originalContentYaml,
56
+ subscriptionFilePath,
57
+ inputs,
58
+ dlqTopic,
59
+ );
41
60
  }
42
61
  };
43
62
 
@@ -170,6 +170,18 @@ module.exports = class extends BaseGenerator {
170
170
  externalSub,
171
171
  } = this.answers;
172
172
 
173
+ const dlqTopicName = `${getProjectId('prod').split('-')[0]}-common-dlq`;
174
+ let dlqTopic = `projects/${getProjectId('prod')}/topics/${dlqTopicName}`;
175
+
176
+ const dlqTopicDirPath = path.join(process.cwd(), 'infra', 'prod', 'pubsub', dlqTopicName);
177
+ this.fs.copyTpl(
178
+ this.templatePath('pubsub-dlq/terragrunt.hcl'),
179
+ this.destinationPath(`${dlqTopicDirPath}/terragrunt.hcl`),
180
+ {
181
+ ...this.answers,
182
+ },
183
+ );
184
+
173
185
  ['prod', 'staging'].forEach(async (env) => {
174
186
  if (createResource === 'topic') {
175
187
  const topicDirPath = path.join(process.cwd(), 'infra', env, 'pubsub', topicName);
@@ -182,6 +194,7 @@ module.exports = class extends BaseGenerator {
182
194
  env,
183
195
  topicName,
184
196
  subscriberName,
197
+ dlqTopic,
185
198
  },
186
199
  );
187
200
  });
@@ -212,6 +225,7 @@ module.exports = class extends BaseGenerator {
212
225
  audience,
213
226
  oidcEmail,
214
227
  pushEndpoint,
228
+ dlqTopic,
215
229
  },
216
230
  );
217
231
  }
@@ -228,7 +242,7 @@ module.exports = class extends BaseGenerator {
228
242
  );
229
243
  });
230
244
 
231
- await handleSubscribers(env, this.answers, oidcEmail, pushEndpoint, `${subscriptionDirPath}/subscribers.yaml`);
245
+ await handleSubscribers(env, this.answers, oidcEmail, pushEndpoint, `${subscriptionDirPath}/subscribers.yaml`, dlqTopic);
232
246
  }
233
247
  if (createResource === 'subscription' && externalSub === 'yes') {
234
248
  const externalDirPath = path.join(process.cwd(), 'infra', env, 'pubsub', existingTopic, clanName);
@@ -259,6 +273,7 @@ module.exports = class extends BaseGenerator {
259
273
  oidcEmail = `${oidcName}@${stagingProjectIdConsumer}.iam.gserviceaccount.com`;
260
274
  } else {
261
275
  oidcEmail = `${oidcName}@${prodProjectIdConsumer}.iam.gserviceaccount.com`;
276
+ dlqTopic = `projects/${prodProjectIdConsumer}/topics/${prodProjectIdConsumer.split('-')[0]}-common-dlq`;
262
277
  }
263
278
  if (!fs.existsSync(externalSubPath)) {
264
279
  fs.writeFileSync(externalSubPath, '');
@@ -273,11 +288,19 @@ module.exports = class extends BaseGenerator {
273
288
  audience,
274
289
  oidcEmail,
275
290
  pushEndpoint,
291
+ dlqTopic,
276
292
  },
277
293
  );
278
294
  }
279
295
 
280
- await handleSubscribers(env, this.answers, oidcEmail, pushEndpoint, externalSubPath);
296
+ await handleSubscribers(
297
+ env,
298
+ this.answers,
299
+ oidcEmail,
300
+ pushEndpoint,
301
+ externalSubPath,
302
+ dlqTopic,
303
+ );
281
304
  }
282
305
  });
283
306
 
@@ -1,9 +1,11 @@
1
1
  <% if (createResource == 'topic') { %><% } %><% if (createResource == 'subscription' && pushOrPull == 'push') { %>push_subscriptions:
2
2
  - name: "<%-existingTopic%>+<%-subscriberName%>"
3
- push_endpoint: "<%-pushEndpoint%>"
3
+ push_endpoint: "<%-pushEndpoint%>" <% if (env == 'prod') { %>
4
+ dead_letter_topic: "<%-dlqTopic%>" <% } %>
4
5
  oidc_service_account_email: "<%-oidcEmail%>"
5
6
  audience: "<%-audience%>"
6
7
  expiration_policy: ""<% } %><% if (createResource == 'subscription' && pushOrPull == 'pull') { %>pull_subscriptions:
7
8
  - name: "<%-existingTopic%>+<%-subscriberName%>"
8
- ack_deadline_seconds: "60"
9
+ ack_deadline_seconds: "60" <% if (env == 'prod') { %>
10
+ dead_letter_topic: "<%-dlqTopic%>" <% } %>
9
11
  expiration_policy: ""<% } %>
@@ -0,0 +1,41 @@
1
+ # Terragrunt will copy the Terraform configurations specified by the source parameter, along with any files in the
2
+ # working directory, into a temporary folder, and execute your Terraform commands in that folder.
3
+ terraform {
4
+ source = "git::https://github.com/terraform-google-modules/terraform-google-pubsub//?ref=v3.0.0"
5
+ }
6
+
7
+ # Include all settings from the root terragrunt.hcl file
8
+ include {
9
+ path = find_in_parent_folders("terragrunt_root.hcl")
10
+ }
11
+
12
+ locals {
13
+ project_vars = read_terragrunt_config(find_in_parent_folders("project.hcl"))
14
+ common_vars = read_terragrunt_config(find_in_parent_folders("common.hcl"))
15
+ }
16
+
17
+ # These are the variables we have to pass in to use the module specified in the terragrunt configuration above
18
+ inputs = merge (
19
+ local.project_vars.locals,
20
+ {
21
+ topic = "${local.common_vars.locals.clan_name}-common-dlq"
22
+ create_subscriptions = true
23
+ create_topic = true
24
+ push_subscriptions = [
25
+ {
26
+ name = "dlq-message-handler-subscription",
27
+ push_endpoint = "https://europe-west1-sre-prod-5462.cloudfunctions.net/dlq-message-handler",
28
+ audience = "https://europe-west1-sre-prod-5462.cloudfunctions.net/dlq-message-handler",
29
+ expiration_policy = "",
30
+ oidc_service_account_email = "pubsub-dlq-handler@${local.project_vars.locals.project_id}.iam.gserviceaccount.com",
31
+ },
32
+ ],
33
+ topic_labels = {
34
+ cc = local.common_vars.locals.cost_center
35
+ }
36
+ subscription_labels = {
37
+ cc = local.common_vars.locals.cost_center
38
+ }
39
+ grant_token_creator = false,
40
+ }
41
+ )
@@ -1,9 +1,11 @@
1
1
  <% if (pushOrPull == 'push') { %>push_subscriptions:
2
2
  - name: "<%-existingTopic%>+<%-subscriberName%>"
3
- push_endpoint: "<%-pushEndpoint%>"
3
+ push_endpoint: "<%-pushEndpoint%>" <% if (env == 'prod') { %>
4
+ dead_letter_topic: "<%-dlqTopic%>" <% } %>
4
5
  oidc_service_account_email: "<%-oidcEmail%>"
5
6
  audience: "<%-audience%>"
6
7
  expiration_policy: ""<% } %><% if (pushOrPull == 'pull') { %>pull_subscriptions:
7
8
  - name: "<%-existingTopic%>+<%-subscriberName%>"
8
- ack_deadline_seconds: "60"
9
+ ack_deadline_seconds: "60" <% if (env == 'prod') { %>
10
+ dead_letter_topic: "<%-dlqTopic%>" <% } %>
9
11
  expiration_policy: ""<% } %>
@@ -50,6 +50,11 @@ module.exports = class extends BaseGenerator {
50
50
  name: 'ddl',
51
51
  message: 'Please provide an optional list of DDL statements to run inside the newly created database. Leave empty to add them later.',
52
52
  },
53
+ {
54
+ type: 'input',
55
+ name: 'versionRetentionPeriod',
56
+ message: 'Please provide version retention period. Maximum value 7d, possible values include 84000s, 1h, 2d. Leave empty for default value 1h.',
57
+ },
53
58
  ];
54
59
 
55
60
  return this.prompt(prompts).then((props) => {
@@ -64,6 +69,7 @@ module.exports = class extends BaseGenerator {
64
69
  instanceAllocation,
65
70
  databaseName,
66
71
  ddl,
72
+ versionRetentionPeriod,
67
73
  } = this.answers;
68
74
 
69
75
  ['prod', 'staging'].forEach((env) => {
@@ -78,6 +84,7 @@ module.exports = class extends BaseGenerator {
78
84
  instanceAllocation,
79
85
  databaseName,
80
86
  ddl,
87
+ versionRetentionPeriod,
81
88
  },
82
89
  );
83
90
  });
@@ -17,4 +17,8 @@ locals {
17
17
  # The number of processing units allocated to this instance.
18
18
  # At most one of either num_nodes or processing_units can be present in terraform.
19
19
  processing_units = "<%-processingUnits%>" <% } %>
20
+ # The time frame it will be possible to restore the database to a point in time.
21
+ # Values from 1h up to max 7d
22
+ <% if (versionRetentionPeriod !== '') { %>
23
+ version_retention_period = "<%-versionRetentionPeriod%>" <% } %>
20
24
  }
@@ -1,7 +1,7 @@
1
1
  # Terragrunt will copy the Terraform configurations specified by the source parameter, along with any files in the
2
2
  # working directory, into a temporary folder, and execute your Terraform commands in that folder.
3
3
  terraform {
4
- source = "git::https://github.com/extenda/tf-module-gcp-spanner//?ref=v0.1.0"
4
+ source = "git::https://github.com/extenda/tf-module-gcp-spanner//?ref=v0.1.1"
5
5
  }
6
6
 
7
7
  # Include all settings from the root terragrunt.hcl file
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@hiiretail/gcp-infra-cli",
3
- "version": "0.74.0",
3
+ "version": "0.75.2",
4
4
  "description": "Infrastructure as code generator for GCP.",
5
5
  "main": "src/cli.js",
6
6
  "bin": {