@hiiretail/gcp-infra-cli 0.74.0 → 0.75.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.
@@ -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: ""<% } %>
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.0",
4
4
  "description": "Infrastructure as code generator for GCP.",
5
5
  "main": "src/cli.js",
6
6
  "bin": {