@hiiretail/gcp-infra-cli 0.104.0 → 1.0.1
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 +9 -46
- package/bin/gcp-infra +5 -2
- package/package.json +7 -30
- package/src/gcp-infra.js +90 -0
- package/LICENSE +0 -21
- package/generators/clan-resources/clan-project/generator.json +0 -4
- package/generators/clan-resources/clan-project/index.js +0 -135
- package/generators/clan-resources/clan-project/templates/clan-resources/cloud-nat/terragrunt.hcl +0 -52
- package/generators/clan-resources/clan-project/templates/clan-resources/cloud-nat-static-ip/spec.hcl +0 -7
- package/generators/clan-resources/clan-project/templates/clan-resources/cloud-nat-static-ip/terragrunt.hcl +0 -25
- package/generators/clan-resources/clan-project/templates/clan-resources/cloud-router/terragrunt.hcl +0 -34
- package/generators/clan-resources/clan-project/templates/clan-resources/gke/gke-resources/terragrunt.hcl +0 -40
- package/generators/clan-resources/clan-project/templates/clan-resources/gke/spec.hcl +0 -18
- package/generators/clan-resources/clan-project/templates/clan-resources/gke/terragrunt.hcl +0 -52
- package/generators/clan-resources/clan-project/templates/clan-resources/network/firewall-rules/config/main.tf +0 -41
- package/generators/clan-resources/clan-project/templates/clan-resources/network/firewall-rules/config/vars.tf +0 -9
- package/generators/clan-resources/clan-project/templates/clan-resources/network/firewall-rules/terragrunt.hcl +0 -32
- package/generators/clan-resources/clan-project/templates/clan-resources/network/spec.hcl +0 -54
- package/generators/clan-resources/clan-project/templates/clan-resources/network/terragrunt.hcl +0 -29
- package/generators/clan-resources/clan-project/templates/clan-resources/private-vpc-connection/config/main.tf +0 -18
- package/generators/clan-resources/clan-project/templates/clan-resources/private-vpc-connection/config/vars.tf +0 -27
- package/generators/clan-resources/clan-project/templates/clan-resources/private-vpc-connection/terragrunt.hcl +0 -35
- package/generators/clan-resources/clan-project/templates/clan-resources/serverless-vpc-connector/terragrunt.hcl +0 -40
- package/generators/clan-resources/clan-project/templates/clan-resources/terragrunt.hcl +0 -3
- package/generators/clan-resources/command.json +0 -7
- package/generators/common-resources/bigquery/generator.json +0 -4
- package/generators/common-resources/bigquery/index.js +0 -284
- package/generators/common-resources/bigquery/templates/bigquery/spec.hcl +0 -8
- package/generators/common-resources/bigquery/templates/bigquery/terragrunt.hcl +0 -53
- package/generators/common-resources/bigquery/templates/scheduled-queries/terragrunt.hcl +0 -56
- package/generators/common-resources/bigquery/templates/schema/schema.json +0 -14
- package/generators/common-resources/budget/generator.json +0 -4
- package/generators/common-resources/budget/index.js +0 -89
- package/generators/common-resources/budget/templates/budget/terragrunt.hcl +0 -45
- package/generators/common-resources/cloud-armor/generator.json +0 -4
- package/generators/common-resources/cloud-armor/index.js +0 -45
- package/generators/common-resources/cloud-armor/templates/policies.yaml +0 -53
- package/generators/common-resources/cloud-armor/templates/terragrunt.hcl +0 -30
- package/generators/common-resources/cloud-storage/generator.json +0 -4
- package/generators/common-resources/cloud-storage/index.js +0 -156
- package/generators/common-resources/cloud-storage/templates/cloud-storage/storage.yaml +0 -26
- package/generators/common-resources/cloud-storage/templates/cloud-storage/terragrunt.hcl +0 -32
- package/generators/common-resources/cloudsql/generator.json +0 -4
- package/generators/common-resources/cloudsql/index.js +0 -106
- package/generators/common-resources/cloudsql/templates/mssql/instance/spec.hcl +0 -76
- package/generators/common-resources/cloudsql/templates/mssql/instance/terragrunt.hcl +0 -38
- package/generators/common-resources/cloudsql/templates/mssql/instance-secrets/terragrunt.hcl +0 -37
- package/generators/common-resources/cloudsql/templates/mysql/instance/spec.hcl +0 -73
- package/generators/common-resources/cloudsql/templates/mysql/instance/terragrunt.hcl +0 -40
- package/generators/common-resources/cloudsql/templates/mysql/instance-secrets/terragrunt.hcl +0 -38
- package/generators/common-resources/cloudsql/templates/postgres-clan/instance/spec.hcl +0 -102
- package/generators/common-resources/cloudsql/templates/postgres-clan/instance/terragrunt.hcl +0 -36
- package/generators/common-resources/cloudsql/templates/postgres-clan/instance-secrets/terragrunt.hcl +0 -44
- package/generators/common-resources/cloudsql-database/generator.json +0 -4
- package/generators/common-resources/cloudsql-database/index.js +0 -70
- package/generators/common-resources/cloudsql-database/templates/mysql/database/proxy_port.hcl +0 -4
- package/generators/common-resources/cloudsql-database/templates/mysql/database/terragrunt.hcl +0 -69
- package/generators/common-resources/cloudsql-database/templates/mysql/outputs.json +0 -5
- package/generators/common-resources/cloudsql-database/templates/mysql/secrets/terragrunt.hcl +0 -30
- package/generators/common-resources/cloudsql-database/templates/postgres/database/proxy_port.hcl +0 -4
- package/generators/common-resources/cloudsql-database/templates/postgres/database/spec.hcl +0 -17
- package/generators/common-resources/cloudsql-database/templates/postgres/database/terragrunt.hcl +0 -74
- package/generators/common-resources/cloudsql-database/templates/postgres/outputs.json +0 -5
- package/generators/common-resources/cloudsql-database/templates/postgres/secrets/terragrunt.hcl +0 -30
- package/generators/common-resources/command.json +0 -8
- package/generators/common-resources/confluent-cluster/generator.json +0 -4
- package/generators/common-resources/confluent-cluster/index.js +0 -52
- package/generators/common-resources/confluent-cluster/templates/confluent/spec.hcl +0 -5
- package/generators/common-resources/confluent-cluster/templates/confluent/terragrunt.hcl +0 -25
- package/generators/common-resources/datastore/generator.json +0 -4
- package/generators/common-resources/datastore/index.js +0 -91
- package/generators/common-resources/datastore/templates/datastore/indexes.yaml +0 -6
- package/generators/common-resources/datastore/templates/datastore/terragrunt.hcl +0 -23
- package/generators/common-resources/elastic-cloud/generator.json +0 -4
- package/generators/common-resources/elastic-cloud/index.js +0 -52
- package/generators/common-resources/elastic-cloud/templates/elastic/spec.hcl +0 -27
- package/generators/common-resources/elastic-cloud/templates/elastic/terragrunt.hcl +0 -27
- package/generators/common-resources/elastic-index-policy/generator.json +0 -4
- package/generators/common-resources/elastic-index-policy/handle-yaml.js +0 -76
- package/generators/common-resources/elastic-index-policy/index.js +0 -210
- package/generators/common-resources/elastic-index-policy/templates/policy/policy.yaml +0 -28
- package/generators/common-resources/elastic-index-policy/templates/policy/terragrunt.hcl +0 -25
- package/generators/common-resources/elastic-template/generator.json +0 -4
- package/generators/common-resources/elastic-template/index.js +0 -84
- package/generators/common-resources/elastic-template/templates/elastic-template/mappings.json +0 -1
- package/generators/common-resources/elastic-template/templates/elastic-template/terragrunt.hcl +0 -35
- package/generators/common-resources/firestore/generator.json +0 -4
- package/generators/common-resources/firestore/index.js +0 -141
- package/generators/common-resources/firestore/templates/firestore/indexes/indexes.yaml +0 -12
- package/generators/common-resources/firestore/templates/firestore/indexes/terragrunt.hcl +0 -27
- package/generators/common-resources/firestore/templates/firestore/spec.hcl +0 -31
- package/generators/common-resources/firestore/templates/firestore/terragrunt.hcl +0 -25
- package/generators/common-resources/iam/generator.json +0 -4
- package/generators/common-resources/iam/index.js +0 -62
- package/generators/common-resources/iam/templates/github/workflows/iam.yml +0 -18
- package/generators/common-resources/iam/templates/iam.yaml +0 -8
- package/generators/common-resources/iam/valid-prefix.js +0 -8
- package/generators/common-resources/kafka-connect/generator.json +0 -4
- package/generators/common-resources/kafka-connect/index.js +0 -75
- package/generators/common-resources/kafka-connect/templates/elastic/terragrunt.hcl +0 -92
- package/generators/common-resources/kafka-connect/templates/pubsub/terragrunt.hcl +0 -75
- package/generators/common-resources/kafka-topics/generator.json +0 -4
- package/generators/common-resources/kafka-topics/index.js +0 -54
- package/generators/common-resources/kafka-topics/templates/kafka/kafka.yaml +0 -20
- package/generators/common-resources/kafka-topics/templates/kafka/terragrunt.hcl +0 -21
- package/generators/common-resources/kms/generator.json +0 -4
- package/generators/common-resources/kms/index.js +0 -69
- package/generators/common-resources/kms/templates/kms/spec.hcl +0 -5
- package/generators/common-resources/kms/templates/kms/terragrunt.hcl +0 -33
- package/generators/common-resources/memorystore/generator.json +0 -4
- package/generators/common-resources/memorystore/index.js +0 -69
- package/generators/common-resources/memorystore/templates/outputs.json +0 -3
- package/generators/common-resources/memorystore/templates/redis-instance/spec.hcl +0 -16
- package/generators/common-resources/memorystore/templates/redis-instance/terragrunt.hcl +0 -35
- package/generators/common-resources/memorystore/templates/secrets/terragrunt.hcl +0 -31
- package/generators/common-resources/monitoring/generator.json +0 -4
- package/generators/common-resources/monitoring/handle-yaml.js +0 -48
- package/generators/common-resources/monitoring/index.js +0 -192
- package/generators/common-resources/monitoring/templates/alerts/generic-infra.yaml +0 -633
- package/generators/common-resources/monitoring/templates/alerts/terragrunt.hcl +0 -37
- package/generators/common-resources/monitoring/templates/service/service.yaml +0 -16
- package/generators/common-resources/monitoring/templates/service/terragrunt.hcl +0 -37
- package/generators/common-resources/monitoring/templates/uptime-checks/terragrunt.hcl +0 -36
- package/generators/common-resources/monitoring/templates/uptime-checks/uptime-checks.yaml +0 -3
- package/generators/common-resources/monitoring/validate.js +0 -58
- package/generators/common-resources/pubsub/append.js +0 -120
- package/generators/common-resources/pubsub/generator.json +0 -4
- package/generators/common-resources/pubsub/get-gcp-projects.js +0 -34
- package/generators/common-resources/pubsub/handle-subscribers.js +0 -63
- package/generators/common-resources/pubsub/index.js +0 -316
- package/generators/common-resources/pubsub/templates/pubsub/spec.hcl +0 -7
- package/generators/common-resources/pubsub/templates/pubsub/subscribers.yaml +0 -16
- package/generators/common-resources/pubsub/templates/pubsub/terragrunt.hcl +0 -34
- package/generators/common-resources/pubsub/templates/pubsub-dlq/terragrunt.hcl +0 -42
- package/generators/common-resources/pubsub/templates/pubsub-external/spec.hcl +0 -10
- package/generators/common-resources/pubsub/templates/pubsub-external/subscribers.yaml +0 -16
- package/generators/common-resources/pubsub/templates/pubsub-external/terragrunt.hcl +0 -31
- package/generators/common-resources/pubsub/validate.js +0 -44
- package/generators/common-resources/scheduler/append.js +0 -83
- package/generators/common-resources/scheduler/generator.json +0 -4
- package/generators/common-resources/scheduler/index.js +0 -103
- package/generators/common-resources/scheduler/templates/scheduler/terragrunt.hcl +0 -44
- package/generators/common-resources/spanner/append.js +0 -27
- package/generators/common-resources/spanner/generator.json +0 -4
- package/generators/common-resources/spanner/index.js +0 -169
- package/generators/common-resources/spanner/templates/spanner/databases.yaml +0 -5
- package/generators/common-resources/spanner/templates/spanner/spec.hcl +0 -22
- package/generators/common-resources/spanner/templates/spanner/terragrunt.hcl +0 -33
- package/generators/common-resources/spanner/validate.js +0 -38
- package/generators/docs/command.json +0 -7
- package/generators/docs/rca/generator.json +0 -4
- package/generators/docs/rca/index.js +0 -50
- package/generators/docs/rca/templates/docs/rca_external.md +0 -43
- package/generators/docs/rca/templates/docs/rca_internal.md +0 -88
- package/generators/docs/runbook/generator.json +0 -4
- package/generators/docs/runbook/index.js +0 -42
- package/generators/docs/runbook/templates/docs/runbook.md +0 -106
- package/generators/docs/srb/generator.json +0 -4
- package/generators/docs/srb/index.js +0 -62
- package/generators/docs/srb/templates/docs/README.md +0 -42
- package/generators/docs/srb/templates/docs/adr.cmd +0 -3
- package/generators/docs/srb/templates/docs/adr.sh +0 -4
- package/generators/docs/srb/templates/docs/architecture.md +0 -68
- package/generators/docs/srb/templates/docs/cost-estimates.md +0 -39
- package/generators/docs/srb/templates/docs/dsl2png.cmd +0 -3
- package/generators/docs/srb/templates/docs/dsl2png.sh +0 -4
- package/generators/docs/srb/templates/docs/sre.md +0 -43
- package/generators/docs/srb/templates/sample.dsl +0 -36
- package/generators/init/clan-infra/gcp-projects.js +0 -36
- package/generators/init/clan-infra/generator.json +0 -4
- package/generators/init/clan-infra/index.js +0 -170
- package/generators/init/clan-infra/templates/.yamllint +0 -17
- package/generators/init/clan-infra/templates/env/project.hcl +0 -15
- package/generators/init/clan-infra/templates/env/secrets/secrets.yaml +0 -4
- package/generators/init/clan-infra/templates/env/secrets/terragrunt.hcl +0 -31
- package/generators/init/clan-infra/templates/github/CODEOWNERS +0 -1
- package/generators/init/clan-infra/templates/github/workflows/infra-verify.yml +0 -16
- package/generators/init/clan-infra/templates/github/workflows/infra.yml +0 -17
- package/generators/init/clan-infra/templates/github/workflows/release-notes.yml +0 -33
- package/generators/init/clan-infra/templates/github/workflows/sync-docs.yml +0 -29
- package/generators/init/clan-infra/templates/infra/.terraform-version +0 -1
- package/generators/init/clan-infra/templates/infra/.terragrunt-version +0 -1
- package/generators/init/clan-infra/templates/infra/README.md +0 -5
- package/generators/init/clan-infra/templates/infra/common.hcl +0 -24
- package/generators/init/clan-infra/templates/infra/terragrunt_root.hcl +0 -44
- package/generators/init/clan-infra/templates/notification-channels/notification-channels.yaml +0 -7
- package/generators/init/clan-infra/templates/notification-channels/terragrunt.hcl +0 -29
- package/generators/init/clan-infra/templates/release-notes/example-service.yaml +0 -23
- package/generators/init/clan-infra/templates/release-notes-schema/release-notes.schema.json +0 -63
- package/generators/init/clan-infra/tribe-clan-repo.js +0 -38
- package/generators/init/clan-infra/validate.js +0 -8
- package/generators/init/command.json +0 -7
- package/generators/maintenance/command.json +0 -7
- package/generators/maintenance/manage-states/generator.json +0 -4
- package/generators/maintenance/manage-states/index.js +0 -188
- package/generators/maintenance/update-modules/generator.json +0 -4
- package/generators/maintenance/update-modules/index.js +0 -102
- package/generators/organization/clan-project/__tests__/__snapshots__/googlecloud.test.js.snap +0 -27
- package/generators/organization/clan-project/generator.json +0 -4
- package/generators/organization/clan-project/googlecloud.js +0 -119
- package/generators/organization/clan-project/index.js +0 -139
- package/generators/organization/clan-project/templates/clan/clan.yaml +0 -22
- package/generators/organization/clan-project/templates/clan/terragrunt.hcl +0 -39
- package/generators/organization/clan-project/templates/clan-project/project.yaml +0 -14
- package/generators/organization/clan-project/templates/clan-project/terragrunt.hcl +0 -51
- package/generators/organization/clan-project/templates/clans-folder/terragrunt.hcl +0 -3
- package/generators/organization/clan-project/templates/department/terragrunt.hcl +0 -32
- package/generators/organization/clan-project/templates/tribe/terragrunt.hcl +0 -67
- package/generators/organization/clan-project/templates/tribe/tribe.yaml +0 -19
- package/generators/organization/command.json +0 -8
- package/src/BaseGenerator.js +0 -73
- package/src/SecretsGenerator.js +0 -105
- package/src/cli.js +0 -73
- package/src/dependency-check.js +0 -48
- package/src/update-check.js +0 -30
- package/src/validators.js +0 -32
- package/src/yeoman.js +0 -71
|
@@ -1,89 +0,0 @@
|
|
|
1
|
-
const path = require('path');
|
|
2
|
-
const chalk = require('chalk');
|
|
3
|
-
const BaseGenerator = require('../../../src/BaseGenerator');
|
|
4
|
-
|
|
5
|
-
module.exports = class extends BaseGenerator {
|
|
6
|
-
prompting() {
|
|
7
|
-
const prompts = [
|
|
8
|
-
{
|
|
9
|
-
type: 'list',
|
|
10
|
-
name: 'usingGKE',
|
|
11
|
-
message: 'Is the clan using GKE?',
|
|
12
|
-
default: 'false',
|
|
13
|
-
choices: ['true', 'false'],
|
|
14
|
-
},
|
|
15
|
-
{
|
|
16
|
-
type: 'input',
|
|
17
|
-
name: 'expectedServiceCount',
|
|
18
|
-
message: 'How many services will eventually be in use simultanously?',
|
|
19
|
-
},
|
|
20
|
-
{
|
|
21
|
-
type: 'list',
|
|
22
|
-
name: 'usingInternalTraffic',
|
|
23
|
-
message: 'Is the clan using internal traffic (service to service communication)?',
|
|
24
|
-
default: 'true',
|
|
25
|
-
choices: ['true', 'false'],
|
|
26
|
-
},
|
|
27
|
-
];
|
|
28
|
-
return this.prompt(prompts).then((props) => {
|
|
29
|
-
this.answers = props;
|
|
30
|
-
});
|
|
31
|
-
}
|
|
32
|
-
|
|
33
|
-
writing() {
|
|
34
|
-
let overheadPercentage = 0.01;
|
|
35
|
-
if (this.answers.usingInternalTraffic === 'false'
|
|
36
|
-
&& this.answers.usingGKE === 'false'
|
|
37
|
-
&& this.answers.expectedServiceCount < 8) {
|
|
38
|
-
overheadPercentage = 0.01;
|
|
39
|
-
} else if (this.answers.usingInternalTraffic === 'true'
|
|
40
|
-
&& this.answers.usingGKE === 'false'
|
|
41
|
-
&& this.answers.expectedServiceCount < 8) {
|
|
42
|
-
overheadPercentage = 0.03;
|
|
43
|
-
} else if (this.answers.usingInternalTraffic === 'true'
|
|
44
|
-
&& this.answers.usingGKE === 'false'
|
|
45
|
-
&& this.answers.expectedServiceCount > 8) {
|
|
46
|
-
overheadPercentage = 0.04;
|
|
47
|
-
} else if (this.answers.usingInternalTraffic === 'true'
|
|
48
|
-
&& this.answers.usingGKE === 'true'
|
|
49
|
-
&& this.answers.expectedServiceCount < 8) {
|
|
50
|
-
overheadPercentage = 0.04;
|
|
51
|
-
} else if (this.answers.usingInternalTraffic === 'true'
|
|
52
|
-
&& this.answers.usingGKE === 'true'
|
|
53
|
-
&& this.answers.expectedServiceCount > 8) {
|
|
54
|
-
overheadPercentage = 0.05;
|
|
55
|
-
} else if (this.answers.usingInternalTraffic === 'false'
|
|
56
|
-
&& this.answers.usingGKE === 'false'
|
|
57
|
-
&& this.answers.expectedServiceCount > 8) {
|
|
58
|
-
overheadPercentage = 0.03;
|
|
59
|
-
} else if (this.answers.usingInternalTraffic === 'false'
|
|
60
|
-
&& this.answers.usingGKE === 'true'
|
|
61
|
-
&& this.answers.expectedServiceCount < 8) {
|
|
62
|
-
overheadPercentage = 0.03;
|
|
63
|
-
} else if (this.answers.usingInternalTraffic === 'false'
|
|
64
|
-
&& this.answers.usingGKE === 'true'
|
|
65
|
-
&& this.answers.expectedServiceCount > 8) {
|
|
66
|
-
overheadPercentage = 0.04;
|
|
67
|
-
}
|
|
68
|
-
|
|
69
|
-
['prod', 'staging'].forEach((env) => {
|
|
70
|
-
this.copyDir(
|
|
71
|
-
'budget',
|
|
72
|
-
path.join('infra', env, 'budget'),
|
|
73
|
-
{
|
|
74
|
-
...this.answers,
|
|
75
|
-
env,
|
|
76
|
-
overheadPercentage,
|
|
77
|
-
},
|
|
78
|
-
);
|
|
79
|
-
});
|
|
80
|
-
}
|
|
81
|
-
|
|
82
|
-
end() {
|
|
83
|
-
this.log(`
|
|
84
|
-
${chalk.green('Your budget has been created.')}
|
|
85
|
-
${chalk.green('1.')} To finalize your configuration, please continue with manual editing of the generated files.
|
|
86
|
-
${chalk.green('2.')} Push the changes in a feature branch and open a pull request.
|
|
87
|
-
`);
|
|
88
|
-
}
|
|
89
|
-
};
|
|
@@ -1,45 +0,0 @@
|
|
|
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-project-factory//modules/budget?ref=feat/CNP-25"
|
|
5
|
-
}
|
|
6
|
-
|
|
7
|
-
# Dependency on the email notification channel(s)
|
|
8
|
-
dependency "notification_channel" {
|
|
9
|
-
config_path = "../monitoring/notification-channels/"
|
|
10
|
-
mock_outputs = {
|
|
11
|
-
notification_channels_email_ids = "notification-channel-dummy-ids"
|
|
12
|
-
}
|
|
13
|
-
}
|
|
14
|
-
|
|
15
|
-
# Include all settings from the root terragrunt.hcl file
|
|
16
|
-
include {
|
|
17
|
-
path = find_in_parent_folders("terragrunt_root.hcl")
|
|
18
|
-
}
|
|
19
|
-
|
|
20
|
-
locals {
|
|
21
|
-
project_vars = read_terragrunt_config(find_in_parent_folders("project.hcl"))
|
|
22
|
-
common_vars = read_terragrunt_config(find_in_parent_folders("common.hcl"))
|
|
23
|
-
}
|
|
24
|
-
|
|
25
|
-
# These are the variables we have to pass in to use the module specified in the terragrunt configuration above
|
|
26
|
-
# The amount has a percentage added if one or more of the following is true:
|
|
27
|
-
# - Clan makes use of GKE
|
|
28
|
-
# - Clan makes use of more than 10 services
|
|
29
|
-
# - Clan makes use of service to service communication (internal traffic)
|
|
30
|
-
# where combinations make steps of 3%, 4% or 5% or 1% if none applies
|
|
31
|
-
# If there is no dependency from the notification channels either create it by updating the notification
|
|
32
|
-
# module to atleast 1.0.2 and add atleast one email notification channel.
|
|
33
|
-
# Or if you already know the ID of an email notification channel use that, format would be
|
|
34
|
-
# ["projects/{projectID}/notificationChannels/{ID}"]
|
|
35
|
-
inputs = merge(
|
|
36
|
-
{
|
|
37
|
-
projects = [local.project_vars.locals.project_id]
|
|
38
|
-
display_name = "${local.project_vars.locals.project_name}-budget"
|
|
39
|
-
billing_account = "01580F-3DD16A-C066A5"
|
|
40
|
-
amount = floor(local.project_vars.locals.amount + (local.project_vars.locals.amount * <%- overheadPercentage %>))
|
|
41
|
-
monitoring_notification_channels = dependency.notification_channel.outputs.notification_channels_email_ids
|
|
42
|
-
disable_default_iam_recipients = true
|
|
43
|
-
alert_spent_percents = [0.8, 1.0, 1.2]
|
|
44
|
-
}
|
|
45
|
-
)
|
|
@@ -1,45 +0,0 @@
|
|
|
1
|
-
const path = require('path');
|
|
2
|
-
const chalk = require('chalk');
|
|
3
|
-
const BaseGenerator = require('../../../src/BaseGenerator');
|
|
4
|
-
const getTribeAndClanName = require('../../init/clan-infra/tribe-clan-repo');
|
|
5
|
-
|
|
6
|
-
module.exports = class extends BaseGenerator {
|
|
7
|
-
prompting() {
|
|
8
|
-
const prompts = [
|
|
9
|
-
{
|
|
10
|
-
type: 'input',
|
|
11
|
-
name: 'name',
|
|
12
|
-
default: getTribeAndClanName().clan,
|
|
13
|
-
message: 'Enter your policy name or leave blank for default',
|
|
14
|
-
},
|
|
15
|
-
];
|
|
16
|
-
return this.prompt(prompts).then((props) => {
|
|
17
|
-
this.answers = props;
|
|
18
|
-
});
|
|
19
|
-
}
|
|
20
|
-
|
|
21
|
-
writing() {
|
|
22
|
-
const {
|
|
23
|
-
name,
|
|
24
|
-
} = this.answers;
|
|
25
|
-
|
|
26
|
-
const run = (env) => {
|
|
27
|
-
this.copyDir(
|
|
28
|
-
path.join(''),
|
|
29
|
-
path.join('infra', env, 'cloud-armor', name),
|
|
30
|
-
);
|
|
31
|
-
};
|
|
32
|
-
run('staging');
|
|
33
|
-
run('prod');
|
|
34
|
-
}
|
|
35
|
-
|
|
36
|
-
end() {
|
|
37
|
-
const {
|
|
38
|
-
name,
|
|
39
|
-
} = this.answers;
|
|
40
|
-
this.log(`
|
|
41
|
-
${chalk.green(`Your cloud armor policy ${chalk.cyan(name)} has been created. To finalize your configuration, please continue
|
|
42
|
-
with manual editing of the generated files.`)}
|
|
43
|
-
`);
|
|
44
|
-
}
|
|
45
|
-
};
|
|
@@ -1,53 +0,0 @@
|
|
|
1
|
-
## This yaml file will configure your cloud armor policies
|
|
2
|
-
## For more information on how to configure the expressions
|
|
3
|
-
## Visit https://cloud.google.com/armor/docs/rules-language-reference
|
|
4
|
-
|
|
5
|
-
## Logging filter for this policy:
|
|
6
|
-
# resource.type:(http_load_balancer) AND jsonPayload.enforcedSecurityPolicy.name:(<%-name%>)
|
|
7
|
-
|
|
8
|
-
description: Cloud armor policy
|
|
9
|
-
default-action: allow ## if no requests match any rules this value will be honored ( allow | deny )
|
|
10
|
-
rules:
|
|
11
|
-
deny-no-auth-header:
|
|
12
|
-
action: deny(403)
|
|
13
|
-
priority: 10 # Priority 1 will be executed before 10 see the language reference for a more detailed explenation.
|
|
14
|
-
description: Block requests without auth header
|
|
15
|
-
preview: true ## dry run true | false
|
|
16
|
-
## Expression will block any request not containing the authorization header
|
|
17
|
-
expression: >-
|
|
18
|
-
!has(request.headers["authorization"])
|
|
19
|
-
|
|
20
|
-
## Example rules
|
|
21
|
-
# ban-requests:
|
|
22
|
-
# action: rate_based_ban
|
|
23
|
-
# priority: 500
|
|
24
|
-
# description: ban requests if more then 10 with the same authorization token
|
|
25
|
-
# preview: true
|
|
26
|
-
# expression: >-
|
|
27
|
-
# inIpRange(origin.ip, "0.0.0.0/0") && has(request.headers["authorization"])
|
|
28
|
-
# rate_limit_options:
|
|
29
|
-
# exceed_action: deny(502)
|
|
30
|
-
## Ban if we get more than 10 requests in 10 minutes for 40 minutes
|
|
31
|
-
# ban_http_request_count: 10
|
|
32
|
-
# ban_http_request_interval_sec: 600
|
|
33
|
-
# ban_duration_sec: 2700
|
|
34
|
-
## Throttle if we get more than 5 requests every 60 seconds
|
|
35
|
-
# rate_limit_http_request_count: 5
|
|
36
|
-
# rate_limit_http_request_interval_sec: 60
|
|
37
|
-
## Enforce on auth header only
|
|
38
|
-
# enforce_on_key_configs:
|
|
39
|
-
# - enforce_on_key_type: HTTP_HEADER
|
|
40
|
-
# enforce_on_key_name: authorization
|
|
41
|
-
# throttle-requests:
|
|
42
|
-
# action: throttle
|
|
43
|
-
# priority: 1000
|
|
44
|
-
# description: throttle requests from SE (100/minute)
|
|
45
|
-
# preview: true
|
|
46
|
-
# expression: >-
|
|
47
|
-
# inIpRange(origin.ip, "0.0.0.0/0") && origin.region_code == "SE"
|
|
48
|
-
# rate_limit_options:
|
|
49
|
-
# exceed_action: deny(429)
|
|
50
|
-
## Throttle if we get 100 requests per minute from sweden and the same IP
|
|
51
|
-
# rate_limit_http_request_count: 100
|
|
52
|
-
# rate_limit_http_request_interval_sec: 60
|
|
53
|
-
# enforce_on_key: ALL
|
|
@@ -1,30 +0,0 @@
|
|
|
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/GoogleCloudPlatform/terraform-google-cloud-armor//?ref=v2.2.0"
|
|
5
|
-
}
|
|
6
|
-
|
|
7
|
-
include {
|
|
8
|
-
path = find_in_parent_folders("terragrunt_root.hcl")
|
|
9
|
-
}
|
|
10
|
-
|
|
11
|
-
locals {
|
|
12
|
-
project_vars = read_terragrunt_config(find_in_parent_folders("project.hcl"))
|
|
13
|
-
common_vars = read_terragrunt_config(find_in_parent_folders("common.hcl"))
|
|
14
|
-
policies = yamldecode(file("${get_terragrunt_dir()}/policies.yaml"))
|
|
15
|
-
name = basename(get_terragrunt_dir())
|
|
16
|
-
}
|
|
17
|
-
|
|
18
|
-
inputs = merge(
|
|
19
|
-
{
|
|
20
|
-
project_id = local.project_vars.locals.project_id
|
|
21
|
-
name = local.name
|
|
22
|
-
description = local.policies["description"]
|
|
23
|
-
default_rule_action = local.policies["default-action"]
|
|
24
|
-
type = "CLOUD_ARMOR"
|
|
25
|
-
layer_7_ddos_defense_enable = false
|
|
26
|
-
json_parsing = "STANDARD"
|
|
27
|
-
log_level = "VERBOSE"
|
|
28
|
-
custom_rules = local.policies["rules"]
|
|
29
|
-
}
|
|
30
|
-
)
|
|
@@ -1,156 +0,0 @@
|
|
|
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: 'bucketName',
|
|
12
|
-
message: 'Please provide the Cloud Storage bucket name',
|
|
13
|
-
validate: required,
|
|
14
|
-
},
|
|
15
|
-
{
|
|
16
|
-
type: 'list',
|
|
17
|
-
name: 'versioning',
|
|
18
|
-
message: 'Do you want to enable versioning for the bucket?',
|
|
19
|
-
default: 'true',
|
|
20
|
-
choices: ['true', 'false'],
|
|
21
|
-
},
|
|
22
|
-
{
|
|
23
|
-
type: 'input',
|
|
24
|
-
name: 'prefix',
|
|
25
|
-
message: 'Please provide the prefix for the bucket name',
|
|
26
|
-
validate: required,
|
|
27
|
-
},
|
|
28
|
-
{
|
|
29
|
-
type: 'list',
|
|
30
|
-
name: 'lifecycleRules',
|
|
31
|
-
message: 'Do you want to set up lifecycle rules for the bucket?',
|
|
32
|
-
default: 'false',
|
|
33
|
-
choices: ['true', 'false'],
|
|
34
|
-
},
|
|
35
|
-
{
|
|
36
|
-
when: (response) => response.lifecycleRules === 'true',
|
|
37
|
-
type: 'list',
|
|
38
|
-
name: 'action',
|
|
39
|
-
message: 'Select the action of this Lifecycle Rule',
|
|
40
|
-
default: 'Delete',
|
|
41
|
-
choices: ['Delete', 'SetStorageClass'],
|
|
42
|
-
},
|
|
43
|
-
{
|
|
44
|
-
when: (response) => response.lifecycleRules === 'true' && response.action === 'SetStorageClass',
|
|
45
|
-
type: 'list',
|
|
46
|
-
name: 'storageClass',
|
|
47
|
-
message: 'Select the Storage Class for objects in the bucket',
|
|
48
|
-
default: 'STANDARD',
|
|
49
|
-
choices: ['STANDARD', 'MULTI_REGIONAL', 'REGIONAL', 'NEARLINE', 'COLDLINE', 'ARCHIVE'],
|
|
50
|
-
},
|
|
51
|
-
{
|
|
52
|
-
when: (response) => response.lifecycleRules === 'true',
|
|
53
|
-
type: 'input',
|
|
54
|
-
name: 'age',
|
|
55
|
-
message: 'Minimum age of an object in days to satisfy the condition. Use null to not set the value',
|
|
56
|
-
validate: required,
|
|
57
|
-
},
|
|
58
|
-
{
|
|
59
|
-
when: (response) => response.lifecycleRules === 'true',
|
|
60
|
-
type: 'input',
|
|
61
|
-
name: 'createdBefore',
|
|
62
|
-
message: 'A date in format YYYY-MM-DD. This condition is satisfied when an object is created before midnight of the specified date in UTC. Use null to not set the value',
|
|
63
|
-
validate: required,
|
|
64
|
-
},
|
|
65
|
-
{
|
|
66
|
-
when: (response) => response.lifecycleRules === 'true',
|
|
67
|
-
type: 'list',
|
|
68
|
-
name: 'withState',
|
|
69
|
-
message: 'Match to live and/or archived objects. Unversioned buckets have only live objects. Use null to not set the value',
|
|
70
|
-
default: 'LIVE',
|
|
71
|
-
choices: ['LIVE', 'ARCHIVED', 'ANY', 'null'],
|
|
72
|
-
},
|
|
73
|
-
{
|
|
74
|
-
when: (response) => response.lifecycleRules === 'true',
|
|
75
|
-
type: 'input',
|
|
76
|
-
name: 'matchesStorageClass',
|
|
77
|
-
message: 'Specify comma delimited string of Storage Class of objects to satisfy the condition. Supported values: STANDARD, MULTI_REGIONAL, REGIONAL, NEARLINE, COLDLINE, ARCHIVE, DURABLE_REDUCED_AVAILABILITY. Use null to not set the value',
|
|
78
|
-
validate: required,
|
|
79
|
-
},
|
|
80
|
-
{
|
|
81
|
-
when: (response) => response.lifecycleRules === 'true',
|
|
82
|
-
type: 'input',
|
|
83
|
-
name: 'numNewerVersions',
|
|
84
|
-
message: 'Relevant only for versioned objects. The number of newer versions of an object to satisfy the condition. Use null to not set the value',
|
|
85
|
-
validate: required,
|
|
86
|
-
},
|
|
87
|
-
{
|
|
88
|
-
type: 'list',
|
|
89
|
-
name: 'retentionPolicy',
|
|
90
|
-
message: 'Do you want to set up a retention period for the bucket?',
|
|
91
|
-
default: 'false',
|
|
92
|
-
choices: ['true', 'false'],
|
|
93
|
-
},
|
|
94
|
-
{
|
|
95
|
-
when: (response) => response.retentionPolicy === 'true',
|
|
96
|
-
type: 'input',
|
|
97
|
-
name: 'retentionPeriod',
|
|
98
|
-
message: 'The period of time, in seconds, that objects in the bucket must be retained and cannot be deleted, overwritten, or archived. The value must be less than 2147483647 seconds',
|
|
99
|
-
validate: required,
|
|
100
|
-
},
|
|
101
|
-
];
|
|
102
|
-
|
|
103
|
-
return this.prompt(prompts).then((props) => {
|
|
104
|
-
this.answers = props;
|
|
105
|
-
});
|
|
106
|
-
}
|
|
107
|
-
|
|
108
|
-
writing() {
|
|
109
|
-
const {
|
|
110
|
-
bucketName,
|
|
111
|
-
prefix,
|
|
112
|
-
lifecycleRules,
|
|
113
|
-
retentionPolicy,
|
|
114
|
-
versioning,
|
|
115
|
-
action,
|
|
116
|
-
storageClass,
|
|
117
|
-
age,
|
|
118
|
-
createdBefore,
|
|
119
|
-
withState,
|
|
120
|
-
matchesStorageClass,
|
|
121
|
-
numNewerVersions,
|
|
122
|
-
retentionPeriod,
|
|
123
|
-
} = this.answers;
|
|
124
|
-
|
|
125
|
-
['prod', 'staging'].forEach((env) => {
|
|
126
|
-
this.copyDir(
|
|
127
|
-
'cloud-storage',
|
|
128
|
-
path.join('infra', env, 'cloud-storage'),
|
|
129
|
-
{
|
|
130
|
-
...this.answers,
|
|
131
|
-
env,
|
|
132
|
-
bucketName,
|
|
133
|
-
prefix,
|
|
134
|
-
lifecycleRules,
|
|
135
|
-
retentionPolicy,
|
|
136
|
-
versioning,
|
|
137
|
-
action,
|
|
138
|
-
storageClass,
|
|
139
|
-
age,
|
|
140
|
-
createdBefore,
|
|
141
|
-
withState,
|
|
142
|
-
matchesStorageClass,
|
|
143
|
-
numNewerVersions,
|
|
144
|
-
retentionPeriod,
|
|
145
|
-
},
|
|
146
|
-
);
|
|
147
|
-
});
|
|
148
|
-
}
|
|
149
|
-
|
|
150
|
-
end() {
|
|
151
|
-
this.log(`
|
|
152
|
-
${chalk.green('Your Cloud Storage resources have now been created.')}
|
|
153
|
-
${chalk.yellow('Note: Bucket names are globally unique, the staging bucket has the suffix -staging')}
|
|
154
|
-
${chalk.green('1.')} Push this change in a feature branch and open a pull request.`);
|
|
155
|
-
}
|
|
156
|
-
};
|
|
@@ -1,26 +0,0 @@
|
|
|
1
|
-
names:
|
|
2
|
-
- "<%-bucketName%><% if (env == 'staging') { %>-staging<% } %>"
|
|
3
|
-
prefix: "<%-prefix%>"
|
|
4
|
-
storage_class: "STANDARD" <% if (env == 'prod') { %>
|
|
5
|
-
location: "EU" <% } else { %>
|
|
6
|
-
location: "EUROPE-WEST1"<% } %>
|
|
7
|
-
versioning:
|
|
8
|
-
"<%-bucketName%>": <%-versioning%>
|
|
9
|
-
set_viewer_roles: true <% if (lifecycleRules == 'true') { %>
|
|
10
|
-
lifecycle_rules:
|
|
11
|
-
- action:
|
|
12
|
-
type: "<%-action%>" <% if (action == 'SetStorageClass') { %>
|
|
13
|
-
storage_class: "<%-storageClass%>" <% } else { %>
|
|
14
|
-
storage_class: null <% } %>
|
|
15
|
-
condition:
|
|
16
|
-
age: <%-age%> <% if (createdBefore != 'null') { %>
|
|
17
|
-
created_before: "<%-createdBefore%>" <% } else { %>
|
|
18
|
-
created_before: null <% } %> <% if (withState != 'null') { %>
|
|
19
|
-
with_state: "<%-withState%>" <% } else { %>
|
|
20
|
-
with_state: null <% } %> <% if (matchesStorageClass != 'null') { %>
|
|
21
|
-
matches_storage_class: "<%-matchesStorageClass%>" <% } else { %>
|
|
22
|
-
matches_storage_class: null <% } %>
|
|
23
|
-
num_newer_versions: <%-numNewerVersions%> <% } %> <% if (retentionPolicy == 'true') { %>
|
|
24
|
-
retention_policy:
|
|
25
|
-
"<%-bucketName%><% if (env == 'staging') { %>-staging<% } %>":
|
|
26
|
-
retention_period: <%-retentionPeriod%> <% } %>
|
|
@@ -1,32 +0,0 @@
|
|
|
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-cloud-storage//?ref=v6.0.1"
|
|
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
|
-
labels = merge(local.common_vars.locals.default_user_labels, local.project_vars.locals.default_user_labels, {
|
|
16
|
-
component = local.common_vars.locals.component
|
|
17
|
-
product = local.common_vars.locals.product
|
|
18
|
-
tenant-alias = local.common_vars.locals.tenant_alias
|
|
19
|
-
})
|
|
20
|
-
}
|
|
21
|
-
|
|
22
|
-
# These are the variables we have to pass in to use the module specified in the terragrunt configuration above
|
|
23
|
-
inputs = merge(
|
|
24
|
-
yamldecode(file("${get_terragrunt_dir()}/storage.yaml")),
|
|
25
|
-
local.project_vars.locals,
|
|
26
|
-
{
|
|
27
|
-
project_id = local.project_vars.locals.project_id
|
|
28
|
-
# IAM-style members who will be granted roles/storage.objectViewer on all buckets.
|
|
29
|
-
viewers = ["group:${local.common_vars.locals.clan_group_email}"]
|
|
30
|
-
labels = local.labels,
|
|
31
|
-
}
|
|
32
|
-
)
|
|
@@ -1,106 +0,0 @@
|
|
|
1
|
-
const path = require('path');
|
|
2
|
-
const chalk = require('chalk');
|
|
3
|
-
const BaseGenerator = require('../../../src/BaseGenerator');
|
|
4
|
-
|
|
5
|
-
module.exports = class extends BaseGenerator {
|
|
6
|
-
prompting() {
|
|
7
|
-
const prompts = [
|
|
8
|
-
{
|
|
9
|
-
type: 'list',
|
|
10
|
-
name: 'instanceType',
|
|
11
|
-
message: 'Select Cloud SQL database instance type',
|
|
12
|
-
store: true,
|
|
13
|
-
default: 'postgres-clan',
|
|
14
|
-
choices: ['postgres-clan', 'mysql', 'mssql'],
|
|
15
|
-
},
|
|
16
|
-
{
|
|
17
|
-
type: 'list',
|
|
18
|
-
name: 'instanceDatabaseVersion',
|
|
19
|
-
message: 'Select Database Version',
|
|
20
|
-
store: true,
|
|
21
|
-
default: (response) => {
|
|
22
|
-
const defaultTypes = {
|
|
23
|
-
'postgres-clan': 'POSTGRES_16',
|
|
24
|
-
mysql: 'MYSQL_5_7',
|
|
25
|
-
mssql: 'SQLSERVER_2017_STANDARD',
|
|
26
|
-
};
|
|
27
|
-
return defaultTypes[response.instanceType];
|
|
28
|
-
},
|
|
29
|
-
choices: (response) => {
|
|
30
|
-
const tierTypes = {
|
|
31
|
-
'postgres-clan': ['POSTGRES_13', 'POSTGRES_14', 'POSTGRES_15', 'POSTGRES_16'],
|
|
32
|
-
mysql: ['MYSQL_5_6', 'MYSQL_5_7'],
|
|
33
|
-
mssql: ['SQLSERVER_2017_STANDARD', 'SQLSERVER_2017_ENTERPRISE', 'SQLSERVER_2017_EXPRESS', 'SQLSERVER_2017_WEB'],
|
|
34
|
-
};
|
|
35
|
-
return tierTypes[response.instanceType];
|
|
36
|
-
},
|
|
37
|
-
},
|
|
38
|
-
{
|
|
39
|
-
type: 'number',
|
|
40
|
-
name: 'diskSize',
|
|
41
|
-
message: 'Enter the disk size for the instance, in GB',
|
|
42
|
-
store: true,
|
|
43
|
-
default: 10,
|
|
44
|
-
},
|
|
45
|
-
{
|
|
46
|
-
type: 'list',
|
|
47
|
-
name: 'enableBackups',
|
|
48
|
-
message: 'Enable Databases backup?',
|
|
49
|
-
default: 'true',
|
|
50
|
-
choices: ['true', 'false'],
|
|
51
|
-
},
|
|
52
|
-
];
|
|
53
|
-
|
|
54
|
-
return this.prompt(prompts).then((props) => {
|
|
55
|
-
this.answers = props;
|
|
56
|
-
});
|
|
57
|
-
}
|
|
58
|
-
|
|
59
|
-
writing() {
|
|
60
|
-
const {
|
|
61
|
-
instanceType,
|
|
62
|
-
} = this.answers;
|
|
63
|
-
|
|
64
|
-
// CloudSQL Instance
|
|
65
|
-
['prod', 'staging'].forEach((env) => {
|
|
66
|
-
this.copyDir(
|
|
67
|
-
path.join(instanceType, 'instance'),
|
|
68
|
-
path.join('infra', env, 'cloud-sql', instanceType, 'instance'),
|
|
69
|
-
{
|
|
70
|
-
...this.answers,
|
|
71
|
-
env,
|
|
72
|
-
},
|
|
73
|
-
);
|
|
74
|
-
});
|
|
75
|
-
|
|
76
|
-
// CloudSQL Instance secrets
|
|
77
|
-
['prod', 'staging'].forEach((env) => {
|
|
78
|
-
this.copyDir(
|
|
79
|
-
path.join(instanceType, 'instance-secrets'),
|
|
80
|
-
path.join('infra', env, 'cloud-sql', instanceType, 'secrets'),
|
|
81
|
-
{
|
|
82
|
-
...this.answers,
|
|
83
|
-
env,
|
|
84
|
-
},
|
|
85
|
-
);
|
|
86
|
-
});
|
|
87
|
-
}
|
|
88
|
-
|
|
89
|
-
end() {
|
|
90
|
-
const {
|
|
91
|
-
instanceType,
|
|
92
|
-
} = this.answers;
|
|
93
|
-
|
|
94
|
-
const specStageFile = path.join('infra', 'staging', 'cloud-sql', instanceType, 'instance', 'spec.hcl');
|
|
95
|
-
const specProdFile = path.join('infra', 'prod', 'cloud-sql', instanceType, 'instance', 'spec.hcl');
|
|
96
|
-
|
|
97
|
-
this.log(`
|
|
98
|
-
${chalk.green(`Your CloudSQL ${chalk.cyan(instanceType)} instance have now been created. To finalize your configuration, please continue
|
|
99
|
-
with manual editing of the generated files.`)}
|
|
100
|
-
${chalk.green('1.')} Review and change specs if needed.
|
|
101
|
-
\u2192 ${chalk.cyan(specStageFile)}
|
|
102
|
-
\u2192 ${chalk.cyan(specProdFile)}
|
|
103
|
-
${chalk.green('2.')} Push this change in a feature branch and open a pull request.
|
|
104
|
-
`);
|
|
105
|
-
}
|
|
106
|
-
};
|