@hiiretail/gcp-infra-cli 0.68.0 → 0.70.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.
@@ -0,0 +1,4 @@
1
+ {
2
+ "name": "Runbook documentation",
3
+ "description": "Create a Runbook template"
4
+ }
@@ -0,0 +1,42 @@
1
+ const path = require('path');
2
+ const chalk = require('chalk');
3
+ const BaseGenerator = require('../../../src/BaseGenerator');
4
+ const { required } = require('../../../src/validators');
5
+
6
+ module.exports = class extends BaseGenerator {
7
+ prompting() {
8
+ const prompts = [
9
+ {
10
+ type: 'input',
11
+ name: 'system',
12
+ message: 'Name of the software system',
13
+ validate: required,
14
+ },
15
+ ];
16
+
17
+ return this.prompt(prompts).then((props) => {
18
+ this.answers = props;
19
+ });
20
+ }
21
+
22
+ writing() {
23
+ const { system } = this.answers;
24
+ const filename = this.kebabCase(system.toLowerCase());
25
+
26
+ this.copyDir(
27
+ 'docs',
28
+ this.destinationPath(path.join('docs', filename)),
29
+ {
30
+ ...this.answers,
31
+ c4System: system.replace(/\s/g, ''),
32
+ },
33
+ );
34
+ }
35
+
36
+ end() {
37
+ this.log(`
38
+ ${chalk.green('Your Runbook documentation template have now been created.')}
39
+ Next, push this change in a feature branch and open a pull request.
40
+ `);
41
+ }
42
+ };
@@ -0,0 +1,50 @@
1
+ # Runbook for <%-system%>
2
+
3
+ ## General
4
+
5
+ Describe in short what the purpose of the solution is.
6
+
7
+ ## Architecture
8
+
9
+ Include C4 diagrams or links to the Software Guidebook.
10
+
11
+ ## Business Continuity and Disaster Recovery Plan
12
+
13
+ Link to the Business Continuity and Disaster Recovery Plan documentation.
14
+
15
+ ## Services
16
+
17
+ A short description of what the purpose of each service is. Links to the log files of all the services that are included in the solution.
18
+
19
+ ## Dashboard
20
+
21
+ Links to one or multiple dashboards.
22
+
23
+ ## Service Level Objectives
24
+
25
+ What are the SLOs?
26
+
27
+ ## Alerts
28
+
29
+ What are the alerts that has been setup, where is alert sent to and what are the steps to mitigate the issue?
30
+
31
+ ## Health Checks
32
+
33
+ Links to the configured uptime checks that has been setup in GCP.
34
+
35
+ ## How do I..?
36
+
37
+ Good to know things. Such as `How do I check the price for a specific item?`
38
+
39
+ ## Known Issues
40
+
41
+ Are there any known issues? If yes, what is the workaround to solve them?
42
+
43
+ ## Contact & Escalation Matrix
44
+
45
+ If the team is unable to resolve the issue, who is the first in line to contact?
46
+
47
+ | # | Name | Role | E-Mail | Phone number |
48
+ | --- | --- | --- | --- | --- |
49
+ | 1 | Mr X | My Role | mr.x@x.com | 1234567 |
50
+ | 2 | Mr Y | My Role | mr.y@y.com | 7654321 |
@@ -7,24 +7,103 @@ module.exports = class extends BaseGenerator {
7
7
  prompting() {
8
8
  const prompts = [
9
9
  {
10
+ type: 'list',
11
+ name: 'resourceType',
12
+ message: 'Select type of resource you want to create',
13
+ default: 'datasets',
14
+ choices: ['scheduledQueries', 'datasets'],
15
+ },
16
+ {
17
+ when: (response) => response.resourceType === 'scheduledQueries',
18
+ type: 'input',
19
+ name: 'queryName',
20
+ message: 'Please provide the name for the transfer config',
21
+ validate: required,
22
+ },
23
+ {
24
+ when: (response) => response.resourceType === 'scheduledQueries',
25
+ type: 'input',
26
+ name: 'dataSourceId',
27
+ message: 'Please provide the data source id. Cannot be changed once the transfer config is created.',
28
+ validate: required,
29
+ },
30
+ {
31
+ when: (response) => response.resourceType === 'scheduledQueries',
32
+ type: 'input',
33
+ name: 'destinationDatasetId',
34
+ message: 'Please provide the BigQuery target dataset id. Leave empty to specify later',
35
+ },
36
+ {
37
+ when: (response) => response.resourceType === 'scheduledQueries',
38
+ type: 'input',
39
+ name: 'schedule',
40
+ message: 'Please provide the data transfer schedule. Format here: https://cloud.google.com/appengine/docs/flexible/python/scheduling-jobs-with-cron-yaml#the_schedule_format',
41
+ validate: required,
42
+ },
43
+ {
44
+ when: (response) => response.resourceType === 'scheduledQueries',
45
+ type: 'input',
46
+ name: 'notificationPubsubTopic',
47
+ message: 'Please provide Pub/Sub topic full name where notifications will be sent after transfer finish. Leave empty to specify later',
48
+ },
49
+ {
50
+ when: (response) => response.resourceType === 'scheduledQueries',
51
+ type: 'input',
52
+ name: 'dataRefreshWindow',
53
+ message: 'Please provide the number of days to look back to automatically refresh the data. Leave empty to specify later',
54
+ },
55
+ {
56
+ when: (response) => response.resourceType === 'scheduledQueries',
57
+ type: 'list',
58
+ name: 'enableFailureEmail',
59
+ message: 'Select if you want to enable notifications to be sent to the email address of the user who owns this transfer config if the run fails',
60
+ default: 'false',
61
+ choices: ['false', 'true'],
62
+ },
63
+ {
64
+ when: (response) => response.resourceType === 'scheduledQueries',
65
+ type: 'input',
66
+ name: 'dataPathTemplate',
67
+ message: 'Please provide the Cloud Storage URI that contains your files to be transferred',
68
+ validate: required,
69
+ },
70
+ {
71
+ when: (response) => response.resourceType === 'scheduledQueries',
72
+ type: 'input',
73
+ name: 'destinationTableTemplate',
74
+ message: 'Please provide the name of your destination table',
75
+ validate: required,
76
+ },
77
+ {
78
+ when: (response) => response.resourceType === 'scheduledQueries',
79
+ type: 'input',
80
+ name: 'fileFormat',
81
+ message: 'Please provide the type of files you want to transfe. Supported values CSV, JSON, AVRO, PARQUET, or ORC',
82
+ validate: required,
83
+ },
84
+ {
85
+ when: (response) => response.resourceType === 'datasets',
10
86
  type: 'input',
11
87
  name: 'datasetId',
12
88
  message: 'Please provide the dataset ID (must be alphanumeric, plus underscores)',
13
89
  validate: required,
14
90
  },
15
91
  {
92
+ when: (response) => response.resourceType === 'datasets',
16
93
  type: 'input',
17
94
  name: 'datasetName',
18
95
  message: 'Please provide the user-frienldy name for the dataset',
19
96
  validate: required,
20
97
  },
21
98
  {
99
+ when: (response) => response.resourceType === 'datasets',
22
100
  type: 'input',
23
101
  name: 'description',
24
102
  message: 'Please provide the description for the dataset',
25
103
  validate: required,
26
104
  },
27
105
  {
106
+ when: (response) => response.resourceType === 'datasets',
28
107
  type: 'list',
29
108
  name: 'createTable',
30
109
  message: 'Do you want to create a table?',
@@ -32,20 +111,21 @@ module.exports = class extends BaseGenerator {
32
111
  choices: ['yes', 'no'],
33
112
  },
34
113
  {
35
- when: (response) => response.createTable === 'yes',
114
+ when: (response) => response.createTable === 'yes' && response.resourceType === 'datasets',
36
115
  type: 'input',
37
116
  name: 'tableId',
38
117
  message: 'Please provide the ID for the table',
39
118
  validate: required,
40
119
  },
41
120
  {
42
- when: (response) => response.createTable === 'yes',
121
+ when: (response) => response.createTable === 'yes' && response.resourceType === 'datasets',
43
122
  type: 'input',
44
123
  name: 'expirationTime',
45
124
  message: 'Please provide the time when the table expires (in milliseconds since the epoch). If set to `null`, the table will persist indefinitely.',
46
125
  validate: required,
47
126
  },
48
127
  {
128
+ when: (response) => response.resourceType === 'datasets',
49
129
  type: 'list',
50
130
  name: 'createRoutine',
51
131
  message: 'Do you want to create a routine?',
@@ -53,21 +133,21 @@ module.exports = class extends BaseGenerator {
53
133
  choices: ['yes', 'no'],
54
134
  },
55
135
  {
56
- when: (response) => response.createRoutine === 'yes',
136
+ when: (response) => response.createRoutine === 'yes' && response.resourceType === 'datasets',
57
137
  type: 'input',
58
138
  name: 'routineId',
59
139
  message: 'Please provide the ID of the routine. The ID must contain only letters, numbers, or underscores',
60
140
  validate: required,
61
141
  },
62
142
  {
63
- when: (response) => response.createRoutine === 'yes',
143
+ when: (response) => response.createRoutine === 'yes' && response.resourceType === 'datasets',
64
144
  type: 'input',
65
145
  name: 'routineDescription',
66
146
  message: 'Please provide the description of the routine',
67
147
  validate: required,
68
148
  },
69
149
  {
70
- when: (response) => response.createRoutine === 'yes',
150
+ when: (response) => response.createRoutine === 'yes' && response.resourceType === 'datasets',
71
151
  type: 'list',
72
152
  name: 'routineType',
73
153
  message: 'Please select a routine type',
@@ -75,7 +155,7 @@ module.exports = class extends BaseGenerator {
75
155
  choices: ['SCALAR_FUNCTION', 'PROCEDURE'],
76
156
  },
77
157
  {
78
- when: (response) => response.createRoutine === 'yes',
158
+ when: (response) => response.createRoutine === 'yes' && response.resourceType === 'datasets',
79
159
  type: 'list',
80
160
  name: 'language',
81
161
  message: 'Please select a language of the routine',
@@ -83,7 +163,7 @@ module.exports = class extends BaseGenerator {
83
163
  choices: ['SQL', 'JAVASCRIPT'],
84
164
  },
85
165
  {
86
- when: (response) => response.createRoutine === 'yes',
166
+ when: (response) => response.createRoutine === 'yes' && response.resourceType === 'datasets',
87
167
  type: 'input',
88
168
  name: 'definitionBody',
89
169
  message: 'Please provide the body of the routine, specify null if not needed',
@@ -110,10 +190,21 @@ module.exports = class extends BaseGenerator {
110
190
  language,
111
191
  definitionBody,
112
192
  routineDescription,
193
+ resourceType,
194
+ dataSourceId,
195
+ queryName,
196
+ destinationDatasetId,
197
+ schedule,
198
+ notificationPubsubTopic,
199
+ dataRefreshWindow,
200
+ enableFailureEmail,
201
+ dataPathTemplate,
202
+ destinationTableTemplate,
203
+ fileFormat,
113
204
  } = this.answers;
114
205
 
115
206
  ['prod', 'staging'].forEach((env) => {
116
- if (createTable === 'no') {
207
+ if (createTable === 'no' && resourceType === 'datasets') {
117
208
  this.copyDir(
118
209
  'bigquery',
119
210
  path.join('infra', env, 'bigquery', datasetId),
@@ -132,7 +223,9 @@ module.exports = class extends BaseGenerator {
132
223
  routineDescription,
133
224
  },
134
225
  );
135
- } else {
226
+ }
227
+
228
+ if (createTable === 'yes' && resourceType === 'datasets') {
136
229
  ['schema', 'bigquery'].forEach((folder) => {
137
230
  this.copyDir(
138
231
  folder,
@@ -156,6 +249,27 @@ module.exports = class extends BaseGenerator {
156
249
  );
157
250
  });
158
251
  }
252
+
253
+ if (resourceType === 'scheduledQueries') {
254
+ this.copyDir(
255
+ 'scheduled-queries',
256
+ path.join('infra', env, 'scheduled-queries'),
257
+ {
258
+ ...this.answers,
259
+ env,
260
+ dataSourceId,
261
+ queryName,
262
+ destinationDatasetId,
263
+ schedule,
264
+ notificationPubsubTopic,
265
+ dataRefreshWindow,
266
+ enableFailureEmail,
267
+ dataPathTemplate,
268
+ destinationTableTemplate,
269
+ fileFormat,
270
+ },
271
+ );
272
+ }
159
273
  });
160
274
  }
161
275
 
@@ -163,7 +277,7 @@ module.exports = class extends BaseGenerator {
163
277
  this.log(`
164
278
  ${chalk.green(`Your BigQuery resources have now been created. To finalize your configuration, please continue
165
279
  with manual editing of the generated files.`)}
166
- ${chalk.green('1.')} Review and add modify schema.json file, change null values to needed ones.))}
280
+ ${chalk.green('1.')} Review and add modify schema.json file, change null values to needed ones.
167
281
  ${chalk.green('2.')} Push this change in a feature branch and open a pull request.
168
282
  `);
169
283
  }
@@ -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/terraform-google-modules/terraform-google-bigquery"
4
+ source = "git::https://github.com/terraform-google-modules/terraform-google-bigquery?ref=v5.4.0"
5
5
  }
6
6
 
7
7
  # Include all settings from the root terragrunt.hcl file
@@ -0,0 +1,56 @@
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/extenda/terraform-google-bigquery//modules/scheduled_queries"
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
+ }
15
+
16
+ # These are the variables we have to pass in to use the module specified in the terragrunt configuration above
17
+ inputs = merge(
18
+ local.project_vars.locals,
19
+ {
20
+ project_id = local.project_vars.locals.project_id
21
+ queries = [
22
+ {
23
+ name = "<%-queryName%>"
24
+ location = "EU"
25
+ data_source_id = "<%-dataSourceId%>" # Cannot be changed once the transfer config is created.
26
+ <% if (destinationDatasetId == '') { %> destination_dataset_id = null <% } else { %>
27
+ destination_dataset_id = "<%-destinationDatasetId%>" <% } %>
28
+
29
+ # If the data source does not support a custom schedule, this should be empty.
30
+ # If it is empty, the default value for the data source will be used. The specified times are in UTC.
31
+ schedule = "<%-schedule%>"
32
+
33
+ # Pub/Sub topic where notifications will be sent after transfer runs associated with this transfer config finish.
34
+ <% if (notificationPubsubTopic == '') { %>
35
+ notification_pubsub_topic = null <% } else { %> notification_pubsub_topic = "<%-notificationPubsubTopic%>" <% } %>
36
+
37
+ # The number of days to look back to automatically refresh the data. Only valid if the data source supports the feature.
38
+ <% if (dataRefreshWindow == '') { %> data_refresh_window_days = null <% } else { %>
39
+ data_refresh_window_days = "<%-dataRefreshWindow%>" <% } %>
40
+
41
+ # When set to true, no runs are scheduled for a given transfer.
42
+ disabled = false
43
+
44
+ # Required parameters for Cloud Storage
45
+ params = {
46
+ data_path_template = "<%-dataPathTemplate%>"
47
+ destination_table_name_template = "<%-destinationTableTemplate%>"
48
+ file_format = "<%-fileFormat%>"
49
+ }
50
+
51
+ # Email notifications will be sent according to these preferences to the email address of the user who owns this transfer config
52
+ enable_failure_email = <%-enableFailureEmail%>
53
+ }
54
+ ]
55
+ }
56
+ )
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@hiiretail/gcp-infra-cli",
3
- "version": "0.68.0",
3
+ "version": "0.70.0",
4
4
  "description": "Infrastructure as code generator for GCP.",
5
5
  "main": "src/cli.js",
6
6
  "bin": {