@hiiretail/gcp-infra-cli 0.75.0 → 0.76.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.
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
 
@@ -4,7 +4,7 @@ const fs = require('fs');
4
4
  const yaml = require('js-yaml');
5
5
  const BaseGenerator = require('../../../src/BaseGenerator');
6
6
  const { required } = require('../../../src/validators');
7
- const helper = require('./validate');
7
+ const validator = require('./validate');
8
8
  const handleSlosFile = require('./handle-slos');
9
9
  const handleUptimeFile = require('./handle-uptime');
10
10
  const handleAlerts = require('./handle-alerts');
@@ -33,14 +33,14 @@ module.exports = class extends BaseGenerator {
33
33
  choices: (answers) => Object.keys(alertTemplates[`${answers.alertResource}`]),
34
34
  },
35
35
  {
36
- when: (response) => response.monitoringResource === ('alerts' || 'slos' || 'uptime-checks'),
36
+ when: (response) => ['alerts', 'slos', 'uptime-checks'].includes(response.monitoringResource),
37
37
  type: 'input',
38
38
  name: 'systemName',
39
- message: 'Please provide three-letter system name as defined in Styra',
40
- validate: required && helper.validSystemName,
39
+ message: 'Please provide three-letter system name as defined in Styra (example: sre, ptf, sda, che, pnp, iam...)',
40
+ validate: required && validator.systemName,
41
41
  },
42
42
  {
43
- when: (response) => response.monitoringResource === ('slos' || 'uptime-checks') || response.alertResource === 'cloud_run',
43
+ when: (response) => ['slos', 'uptime-checks'].includes(response.monitoringResource) || response.alertResource === 'cloud_run',
44
44
  type: 'input',
45
45
  name: 'serviceName',
46
46
  message: 'Please provide the namespace where the service resides',
@@ -51,7 +51,7 @@ module.exports = class extends BaseGenerator {
51
51
  type: 'input',
52
52
  name: 'runbookLink',
53
53
  message: 'Please provide the full URL to your runbook in confluence (Leave empty if none)',
54
- validate: required && helper.validUrl,
54
+ validate: required && validator.url,
55
55
  },
56
56
  {
57
57
  when: (response) => response.alertResource === 'cloud_scheduler',
@@ -65,34 +65,35 @@ module.exports = class extends BaseGenerator {
65
65
  type: 'input',
66
66
  name: 'databaseId',
67
67
  message: 'Please provide the "database id"',
68
- validate: required,
68
+ validate: required && validator.databaseId,
69
69
  },
70
70
  {
71
71
  when: (response) => response.alertResource === 'memorystore',
72
72
  type: 'input',
73
73
  name: 'instanceId',
74
74
  message: 'Please provide the "instance id"',
75
- validate: required,
75
+ validate: required && validator.instanceID,
76
76
  },
77
77
  {
78
78
  when: (response) => response.alertResource === 'pub_sub',
79
79
  type: 'input',
80
80
  name: 'subscriptionId',
81
81
  message: 'Please provide the "subscription id"',
82
- validate: required,
82
+ validate: required && validator.pubSubSubscription,
83
83
  },
84
84
  {
85
85
  when: (response) => response.monitoringResource === 'uptime-checks',
86
86
  type: 'input',
87
87
  name: 'hostname',
88
88
  message: 'Please provide the base hostname of the service (example: my-service.retailsvc.com)',
89
- validate: required && helper.validHostname,
89
+ validate: required && validator.validHostname,
90
90
  },
91
91
  {
92
92
  when: (response) => response.monitoringResource === 'uptime-checks',
93
93
  type: 'input',
94
94
  name: 'path',
95
- message: 'Please provide the path to the page to run the check against. (example: /health)',
95
+ message: 'Please provide the path/endpoint to run the check against',
96
+ default: '/health',
96
97
  validate: required,
97
98
  },
98
99
  {
@@ -106,7 +107,7 @@ module.exports = class extends BaseGenerator {
106
107
  when: (response) => response.monitoringResource === 'slos',
107
108
  type: 'list',
108
109
  name: 'burnRateAlerts',
109
- message: 'Please select yes if you want to create burn rate alert for the SLI',
110
+ message: 'Please select yes if you want to have burn-rate alerts included',
110
111
  default: 'yes',
111
112
  choices: ['yes', 'no'],
112
113
  },
@@ -114,7 +115,7 @@ module.exports = class extends BaseGenerator {
114
115
  when: (response) => response.monitoringResource === 'slos' && response.sli === 'availability',
115
116
  type: 'confirm',
116
117
  name: 'info',
117
- message: 'WARNING: Make sure that an uptime check has been created before applying availability SLI',
118
+ message: 'WARNING: Make sure an uptime check has been created BEFORE continuing with the creation of this SLO.',
118
119
  },
119
120
  ]);
120
121
  }
@@ -1,37 +1,4 @@
1
1
  cloud_run:
2
- error_count:
3
- display_name: "[P3] <%-systemName%>.<%-serviceName%> | 5xx Error Request Count above 1"
4
- conditions:
5
- - display_name: Cloud Run Anthos - 5xx error Request Count above 1
6
- condition_threshold:
7
- filter: |
8
- resource.type="knative_revision"
9
- resource.labels.service_name="<%-serviceName%>"
10
- metric.type="knative.dev/serving/revision/request_count"
11
- metric.labels.response_code_class="5xx"
12
- threshold_value: 1
13
- aggregations:
14
- - alignment_period: 60s
15
- cross_series_reducer: REDUCE_SUM
16
- group_by_fields:
17
- - metric.label.response_code_class
18
- per_series_aligner: ALIGN_DELTA
19
- documentation:
20
- content: <% if (runbookLink) { %>[Runbook](<%-runbookLink%>)<%} else { %> <% } %>
21
- error_rate:
22
- display_name: "[P3] <%-systemName%>.<%-serviceName%> | High 5xx Error Rate"
23
- conditions:
24
- - display_name: Cloud Run Anthos - 3% of all requests during 10min are 5xx
25
- condition_monitoring_query_language:
26
- query: |
27
- fetch knative_revision::knative.dev/serving/revision/request_count
28
- | filter service_name = "store-data-resolver"
29
- | align int_mean_aligner(10m)
30
- | group_by [], sum(if(metric.response_code_class == '5xx', val(), 0)) / sum(val())
31
- | condition val() > 0.03
32
- | every 10m
33
- documentation:
34
- content: <% if (runbookLink) { %>[Runbook](<%-runbookLink%>)<%} else { %> <% } %>
35
2
  request_latency:
36
3
  display_name: "[P3] <%-systemName%>.<%-serviceName%> | High Request Latency"
37
4
  conditions:
@@ -45,7 +12,6 @@ cloud_run:
45
12
  duration: 300s
46
13
  aggregations:
47
14
  - alignment_period: 60s
48
- cross_series_reducer: REDUCE_NONE
49
15
  per_series_aligner: ALIGN_PERCENTILE_95
50
16
  documentation:
51
17
  content: <% if (runbookLink) { %>[Runbook](<%-runbookLink%>)<%} else { %> <% } %>
@@ -63,13 +29,12 @@ cloud_scheduler:
63
29
  threshold_value: 1
64
30
  aggregations:
65
31
  - alignment_period: 60s
66
- cross_series_reducer: REDUCE_NONE
67
32
  per_series_aligner: ALIGN_COUNT
68
33
  documentation:
69
34
  content: <% if (runbookLink) { %>[Runbook](<%-runbookLink%>)<%} else { %> <% } %>
70
35
  cloud_sql:
71
36
  cpu_over_65:
72
- display_name: "[P3] <%-systemName%> - CloudSQL | <%-databaseId%> - CPU over 65%"
37
+ display_name: "[P3] <%-systemName%> - CloudSQL | <%-databaseId.substring(databaseId.lastIndexOf(':') + 1)%> - CPU over 65%"
73
38
  conditions:
74
39
  - display_name: Cloud SQL Database - CPU utilization above 65% over 5 min
75
40
  condition_threshold:
@@ -81,12 +46,11 @@ cloud_sql:
81
46
  duration: 300s
82
47
  aggregations:
83
48
  - alignment_period: 60s
84
- cross_series_reducer: REDUCE_NONE
85
49
  per_series_aligner: ALIGN_MAX
86
50
  documentation:
87
51
  content: <% if (runbookLink) { %>[Runbook](<%-runbookLink%>)<%} else { %> <% } %>
88
52
  cpu_over_85:
89
- display_name: "[P3] <%-systemName%> - CloudSQL | <%-databaseId%> - CPU over 85%"
53
+ display_name: "[P3] <%-systemName%> - CloudSQL | <%-databaseId.substring(databaseId.lastIndexOf(':') + 1)%> - CPU over 85%"
90
54
  conditions:
91
55
  - display_name: "Cloud SQL Database - CPU-usage above 85% over 1 min"
92
56
  condition_threshold:
@@ -98,12 +62,11 @@ cloud_sql:
98
62
  duration: 60s
99
63
  aggregations:
100
64
  - alignment_period: 60s
101
- cross_series_reducer: REDUCE_NONE
102
65
  per_series_aligner: ALIGN_MAX
103
66
  documentation:
104
67
  content: <% if (runbookLink) { %>[Runbook](<%-runbookLink%>)<%} else { %> <% } %>
105
68
  cpu_over_90:
106
- display_name: "[P3] <%-systemName%> - CloudSQL | <%-databaseId%> - CPU over 90%"
69
+ display_name: "[P3] <%-systemName%> - CloudSQL | <%-databaseId.substring(databaseId.lastIndexOf(':') + 1)%> - CPU over 90%"
107
70
  conditions:
108
71
  - display_name: Cloud SQL Database - CPU-usage above 90%
109
72
  condition_threshold:
@@ -114,63 +77,11 @@ cloud_sql:
114
77
  threshold_value: 0.9
115
78
  aggregations:
116
79
  - alignment_period: 60s
117
- cross_series_reducer: REDUCE_NONE
118
80
  per_series_aligner: ALIGN_MAX
119
81
  documentation:
120
82
  content: <% if (runbookLink) { %>[Runbook](<%-runbookLink%>)<%} else { %> <% } %>
121
- memory_over_50:
122
- display_name: "[P3] <%-systemName%> - CloudSQL | <%-databaseId%> - Memory over 50%"
123
- conditions:
124
- - display_name: Cloud SQL Database - Memory utilization above 50% over 5 min
125
- condition_threshold:
126
- filter: |
127
- resource.type="cloudsql_database"
128
- resource.labels.database_id="<%-databaseId%>"
129
- metric.type="cloudsql.googleapis.com/database/memory/utilization"
130
- threshold_value: 50
131
- duration: 300s
132
- aggregations:
133
- - alignment_period: 60s
134
- cross_series_reducer: REDUCE_NONE
135
- per_series_aligner: ALIGN_MAX
136
- documentation:
137
- content: <% if (runbookLink) { %>[Runbook](<%-runbookLink%>)<%} else { %> <% } %>
138
- memory_over_75:
139
- display_name: "[P3] <%-systemName%> - CloudSQL | <%-databaseId%> - Memory over 75%"
140
- conditions:
141
- - display_name: Cloud SQL Database - Memory utilization above 75% over 5 min
142
- condition_threshold:
143
- filter: |
144
- resource.type="cloudsql_database"
145
- resource.labels.database_id="<%-databaseId%>"
146
- metric.type="cloudsql.googleapis.com/database/memory/utilization"
147
- threshold_value: 75
148
- duration: 300s
149
- aggregations:
150
- - alignment_period: 60s
151
- cross_series_reducer: REDUCE_NONE
152
- per_series_aligner: ALIGN_MAX
153
- documentation:
154
- content: <% if (runbookLink) { %>[Runbook](<%-runbookLink%>)<%} else { %> <% } %>
155
- memory_over_90:
156
- display_name: "[P3] <%-systemName%> - CloudSQL | <%-databaseId%> - Memory over 90%"
157
- conditions:
158
- - display_name: Cloud SQL Database - Memory utilization above 90%
159
- condition_threshold:
160
- filter: |
161
- resource.type="cloudsql_database"
162
- resource.labels.database_id="<%-databaseId%>"
163
- metric.type="cloudsql.googleapis.com/database/memory/utilization"
164
- threshold_value: 90
165
- duration: 60s
166
- aggregations:
167
- - alignment_period: 60s
168
- cross_series_reducer: REDUCE_NONE
169
- per_series_aligner: ALIGN_MAX
170
- documentation:
171
- content: <% if (runbookLink) { %>[Runbook](<%-runbookLink%>)<%} else { %> <% } %>
172
83
  query_over_1s:
173
- display_name: "[P4] <%-systemName%> - CloudSQL | <%-databaseId%> - Query resolve time"
84
+ display_name: "[P4] <%-systemName%> - CloudSQL | <%-databaseId.substring(databaseId.lastIndexOf(':') + 1)%> - Query resolve time"
174
85
  conditions:
175
86
  - display_name: Cloud SQL Instance Database - Per query execution times above 1000 ms
176
87
  condition_threshold:
@@ -181,13 +92,12 @@ cloud_sql:
181
92
  threshold_value: 1000000
182
93
  aggregations:
183
94
  - alignment_period: 60s
184
- cross_series_reducer: REDUCE_NONE
185
95
  per_series_aligner: ALIGN_DELTA
186
96
  documentation:
187
97
  content: <% if (runbookLink) { %>[Runbook](<%-runbookLink%>)<%} else { %> <% } %>
188
98
  memorystore:
189
99
  memory_over_50:
190
- display_name: "[P4] <%-systemName%> - Memorystore | <%-instanceId%> - Memory over 50%"
100
+ display_name: "[P4] <%-systemName%> - Memorystore | <%-instanceId.substring(instanceId.lastIndexOf('/') + 1)%> - Memory over 50%"
191
101
  conditions:
192
102
  - display_name: Memorystore Redis Instance - Memory Usage above 50% over 5 min
193
103
  condition_threshold:
@@ -199,12 +109,11 @@ memorystore:
199
109
  duration: 300s
200
110
  aggregations:
201
111
  - alignment_period: 60s
202
- cross_series_reducer: REDUCE_NONE
203
112
  per_series_aligner: ALIGN_MAX
204
113
  documentation:
205
114
  content: <% if (runbookLink) { %>[Runbook](<%-runbookLink%>)<%} else { %> <% } %>
206
115
  memory_over_75:
207
- display_name: "[P4] <%-systemName%> - Memorystore | <%-instanceId%> - Memory over 75%"
116
+ display_name: "[P4] <%-systemName%> - Memorystore | <%-instanceId.substring(instanceId.lastIndexOf('/') + 1)%> - Memory over 75%"
208
117
  conditions:
209
118
  - display_name: Memorystore Redis Instance - Memory Usage above 75% for 5min
210
119
  condition_threshold:
@@ -216,12 +125,11 @@ memorystore:
216
125
  duration: 300s
217
126
  aggregations:
218
127
  - alignment_period: 60s
219
- cross_series_reducer: REDUCE_NONE
220
128
  per_series_aligner: ALIGN_MAX
221
129
  documentation:
222
130
  content: <% if (runbookLink) { %>[Runbook](<%-runbookLink%>)<%} else { %> <% } %>
223
131
  memory_over_90:
224
- display_name: "[P2] <%-systemName%> - Memorystore | <%-instanceId%> - Memory over 90%"
132
+ display_name: "[P2] <%-systemName%> - Memorystore | <%-instanceId.substring(instanceId.lastIndexOf('/') + 1)%> - Memory over 90%"
225
133
  conditions:
226
134
  - display_name: Memorystore Redis Instance - Memory Usage above 90%
227
135
  condition_threshold:
@@ -233,13 +141,12 @@ memorystore:
233
141
  duration: 60s
234
142
  aggregations:
235
143
  - alignment_period: 60s
236
- cross_series_reducer: REDUCE_NONE
237
144
  per_series_aligner: ALIGN_MAX
238
145
  documentation:
239
146
  content: <% if (runbookLink) { %>[Runbook](<%-runbookLink%>)<%} else { %> <% } %>
240
147
  pub_sub:
241
148
  unacknowledged_messages:
242
- display_name: "[P4] <%-systemName%> - Pub/Sub | <%-subscriptionId%> - Undelivered message(s)"
149
+ display_name: "[P4] <%-systemName%> - Pub/Sub | <%-subscriptionId.substring(subscriptionId.lastIndexOf('/') + 1)%> - Undelivered message(s)"
243
150
  conditions:
244
151
  - display_name: Cloud Pub/Sub Subscription - Undelivered messages above 1 for 5 min
245
152
  condition_threshold:
@@ -251,7 +158,6 @@ pub_sub:
251
158
  duration: 300s
252
159
  aggregations:
253
160
  - alignment_period: 60s
254
- cross_series_reducer: REDUCE_NONE
255
161
  per_series_aligner: ALIGN_MEAN
256
162
  documentation:
257
163
  content: <% if (runbookLink) { %>[Runbook](<%-runbookLink%>)<%} else { %> <% } %>
@@ -1,6 +1,6 @@
1
- const helper = {};
1
+ const validator = {};
2
2
 
3
- helper.validHostname = (input) => {
3
+ validator.hostName = (input) => {
4
4
  const regex = new RegExp(/^(?:[a-z-]+\.){1,3}[a-z-]+$/g);
5
5
  if (input.match(regex)) {
6
6
  return true;
@@ -8,18 +8,33 @@ helper.validHostname = (input) => {
8
8
  return 'Hostname must not include path to the page to run the check against or spaces';
9
9
  };
10
10
 
11
- helper.validSystemName = (input) => {
11
+ validator.systemName = (input) => {
12
12
  if (input.replace(/\s/g, '').length === 3) {
13
13
  return true;
14
14
  }
15
15
  return 'System name must be 3 characters';
16
16
  };
17
17
 
18
- helper.validUrl = (input) => {
18
+ validator.url = (input) => {
19
19
  // eslint-disable-next-line no-useless-escape
20
20
  const regex = new RegExp(/^https:\/\/[a-zA-Z]*.[a-zA-Z]*.[a-zA-Z]*\/[a-zA-Z\/+_-]*.$/g);
21
21
  if (regex.test(input) || input === '') return true;
22
- return 'Enter a valid URL';
22
+ return 'You must enter a valid URL';
23
23
  };
24
24
 
25
- module.exports = helper;
25
+ validator.instanceID = (input) => {
26
+ if (input.split('/').length === 6) return true;
27
+ return 'You must enter the full instance path (example: projects/example/locations/europe-west1/instances/instanceID)';
28
+ };
29
+
30
+ validator.databaseId = (input) => {
31
+ if (input.split(':').length === 2) return true;
32
+ return 'You must enter the full database path (example: my-project:databaseID)';
33
+ };
34
+
35
+ validator.pubSubSubscription = (input) => {
36
+ if (input.split('/').length === 4) return true;
37
+ return 'You must enter the full subscription path (example: projects/example/subscriptions/subscriptionId)';
38
+ };
39
+
40
+ module.exports = validator;
@@ -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.75.0",
3
+ "version": "0.76.0",
4
4
  "description": "Infrastructure as code generator for GCP.",
5
5
  "main": "src/cli.js",
6
6
  "bin": {