@catladder/cli 1.58.1 → 1.60.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/package.json CHANGED
@@ -24,7 +24,7 @@
24
24
  "node": ">=12.0.0"
25
25
  },
26
26
  "devDependencies": {
27
- "@catladder/pipeline": "1.58.1",
27
+ "@catladder/pipeline": "1.60.0",
28
28
  "@kubernetes/client-node": "^0.16.2",
29
29
  "@tsconfig/node14": "^1.0.1",
30
30
  "@types/common-tags": "^1.8.0",
@@ -57,5 +57,5 @@
57
57
  "typescript": "^4.5.4",
58
58
  "vorpal": "^1.12.0"
59
59
  },
60
- "version": "1.58.1"
60
+ "version": "1.60.0"
61
61
  }
@@ -1,3 +1,4 @@
1
+ import type { Context } from "@catladder/pipeline";
1
2
  import { isOfDeployType } from "@catladder/pipeline";
2
3
  import { spawn } from "child-process-promise";
3
4
  import { writeFile } from "fs-extra";
@@ -7,11 +8,15 @@ import {
7
8
  getEnvVars,
8
9
  getGitlabVar,
9
10
  getPipelineContextByChoice,
10
- getProjectConfig,
11
11
  parseChoice,
12
12
  } from "../../../../config/getProjectConfig";
13
13
  import { envAndComponents } from "./utils/autocompletions";
14
14
 
15
+ type ProxyInfo = {
16
+ instanceName: string;
17
+ DB_NAME: string;
18
+ DB_PASSWORD: string;
19
+ };
15
20
  export default async (vorpal: Vorpal) =>
16
21
  vorpal
17
22
  .command("project-cloud-sql-proxy <envComponent>", "proxy to cloud sql db")
@@ -19,9 +24,26 @@ export default async (vorpal: Vorpal) =>
19
24
  .action(async function ({ envComponent }) {
20
25
  const { env, componentName } = parseChoice(envComponent);
21
26
 
22
- const config = await getProjectConfig();
23
- // skynet-164509:europe-west6:pvl-cyclomania-review=tcp:5432
27
+ const context = await getPipelineContextByChoice(env, componentName);
28
+ let proxyInfo: ProxyInfo;
29
+
30
+ if (env === "review") {
31
+ vorpal.log(
32
+ "⚠️ connection string does not include mr information on review environments"
33
+ );
34
+ }
35
+ if (isOfDeployType(context.componentConfig.deploy, "kubernetes")) {
36
+ proxyInfo = await getProxyInfoForKubernetes(context);
37
+ } else if (
38
+ isOfDeployType(context.componentConfig.deploy, "google-cloudrun")
39
+ ) {
40
+ proxyInfo = await getProxyInfoForCloudRun(context);
41
+ } else {
42
+ throw new Error("unsupported environment");
43
+ }
24
44
 
45
+ // skynet-164509:europe-west6:pvl-cyclomania-review=tcp:5432
46
+ const { DB_PASSWORD, DB_NAME, instanceName } = proxyInfo;
25
47
  const { localPort } = await this.prompt({
26
48
  type: "number",
27
49
  name: "localPort",
@@ -29,35 +51,16 @@ export default async (vorpal: Vorpal) =>
29
51
  message: "Local port: ",
30
52
  });
31
53
 
32
- const envVars = await getEnvVars(this, env, componentName);
33
- const POSTGRESQL_PASSWORD = envVars?.POSTGRESQL_PASSWORD;
34
-
35
- const context = await getPipelineContextByChoice(env, componentName);
36
- if (!isOfDeployType(context.componentConfig.deploy, "kubernetes")) {
37
- throw new Error("currently only supported for kubernetes deployment");
38
- }
39
54
  this.log("");
40
- this.log(`postgres-PW: ${POSTGRESQL_PASSWORD}`);
55
+ this.log(`postgres-PW: ${DB_PASSWORD}`);
41
56
  this.log("");
42
57
  this.log(
43
- `POSTGRESQL_URL=postgresql://postgres:${POSTGRESQL_PASSWORD}@localhost:${localPort}/${context.environment.envVars.KUBE_APP_NAME}?schema=public`
58
+ `POSTGRESQL_URL=postgresql://postgres:${DB_PASSWORD}@localhost:${localPort}/${DB_NAME}?schema=public`
44
59
  );
45
60
  this.log("");
46
61
 
47
- const values = context.componentConfig.deploy.values;
48
-
49
- const projectId =
50
- values?.cloudsql?.projectId ||
51
- context.componentConfig.deploy.cluster?.projectId;
52
-
53
- const defaultInstanceId = `${config.customerName}-${config.appName}-${env}`;
54
- const instanceId = values?.cloudsql?.instanceId || defaultInstanceId;
55
-
56
- const defaultRegion = "europe-west6"; // currently hardcoded
57
- const region = values?.cloudsql?.region || defaultRegion;
58
-
59
- const instanceName = `${projectId}:${region}:${instanceId}=tcp:${localPort}`;
60
-
62
+ // legacy, some projects have the cloudsqlProxyCredentials in the secrets
63
+ // actually it works without, if the current local shell user has access to the db through google cloud
61
64
  const cloudsqlProxyCredentials = await getGitlabVar(
62
65
  this,
63
66
  env,
@@ -65,20 +68,20 @@ export default async (vorpal: Vorpal) =>
65
68
  "cloudsqlProxyCredentials"
66
69
  );
67
70
 
68
- if (!cloudsqlProxyCredentials) {
69
- // we store cloudsqlProxyCredentials on gitlab, but its currently get pushed via bitwarden due to legacy reasons
70
- // this will be fixed with when https://git.panter.ch/catladder/catladder/-/merge_requests/32/ is merged
71
- this.log(
72
- "cloudsqlProxyCredentials env var missing in gitlab. Please contact gilde-ci-cd about that."
73
- );
74
- throw new Error("cloudsqlProxyCredentials missing in secrets");
75
- }
76
71
  await withFile(async ({ path: tmpFilePath }) => {
77
- await writeFile(tmpFilePath, cloudsqlProxyCredentials);
72
+ if (cloudsqlProxyCredentials) {
73
+ await writeFile(tmpFilePath, cloudsqlProxyCredentials);
74
+ }
78
75
 
79
76
  await spawn(
80
77
  "cloud_sql_proxy",
81
- ["-instances", instanceName, "-credential_file", tmpFilePath],
78
+ [
79
+ "-instances",
80
+ `${instanceName}=tcp:${localPort}`,
81
+ ...(cloudsqlProxyCredentials
82
+ ? ["-credential_file", tmpFilePath]
83
+ : []),
84
+ ],
82
85
  {
83
86
  stdio: "inherit",
84
87
  shell: true,
@@ -86,3 +89,69 @@ export default async (vorpal: Vorpal) =>
86
89
  );
87
90
  });
88
91
  });
92
+
93
+ const getProxyInfoForKubernetes = async (
94
+ context: Context
95
+ ): Promise<ProxyInfo> => {
96
+ if (!isOfDeployType(context.componentConfig.deploy, "kubernetes")) {
97
+ throw new Error("unsupported");
98
+ }
99
+
100
+ const envVars = await getEnvVars(
101
+ this,
102
+ context.environment.shortName,
103
+ context.componentName
104
+ );
105
+
106
+ const DB_PASSWORD = envVars?.DB_PASSWORD || envVars?.POSTGRESQL_PASSWORD;
107
+
108
+ const DB_NAME = context.environment.envVars.KUBE_APP_NAME;
109
+
110
+ const values = context.componentConfig.deploy.values;
111
+
112
+ const projectId =
113
+ values?.cloudsql?.projectId ||
114
+ context.componentConfig.deploy.cluster?.projectId;
115
+
116
+ const defaultInstanceId = `${context.fullConfig.customerName}-${context.fullConfig.appName}-${context.environment.shortName}`;
117
+ const instanceId = values?.cloudsql?.instanceId || defaultInstanceId;
118
+
119
+ const defaultRegion = "europe-west6"; // currently hardcoded
120
+ const region = values?.cloudsql?.region || defaultRegion;
121
+
122
+ const instanceName = `${projectId}:${region}:${instanceId}`;
123
+
124
+ return {
125
+ instanceName,
126
+ DB_PASSWORD,
127
+ DB_NAME,
128
+ };
129
+ };
130
+
131
+ const getProxyInfoForCloudRun = async (
132
+ context: Context
133
+ ): Promise<ProxyInfo> => {
134
+ if (
135
+ !isOfDeployType(context.componentConfig.deploy, "google-cloudrun") ||
136
+ !context.componentConfig.deploy.cloudSql
137
+ ) {
138
+ throw new Error("unsupported");
139
+ }
140
+
141
+ const envVars = await getEnvVars(
142
+ this,
143
+ context.environment.shortName,
144
+ context.componentName
145
+ );
146
+
147
+ const DB_PASSWORD = envVars?.DB_PASSWORD;
148
+
149
+ const DB_NAME = context.environment.envVars.DB_NAME;
150
+
151
+ return {
152
+ instanceName:
153
+ context.componentConfig.deploy.cloudSql.instanceConnectionName,
154
+ DB_PASSWORD,
155
+ DB_NAME,
156
+ };
157
+ };
@@ -26,7 +26,13 @@ export const setupCloudRun = async (
26
26
 
27
27
  instance.log("enable required servies...");
28
28
  await enableGCloudServices(
29
- ["run.googleapis.com", "artifactregistry.googleapis.com"],
29
+ [
30
+ "run.googleapis.com",
31
+ "artifactregistry.googleapis.com",
32
+ ...(config.cloudSql
33
+ ? ["sqladmin.googleapis.com", "sql-component.googleapis.com"]
34
+ : []),
35
+ ],
30
36
  config
31
37
  );
32
38
  instance.log("upsert artifacts registry...");
@@ -46,6 +52,7 @@ export const setupCloudRun = async (
46
52
  "roles/artifactregistry.repoAdmin",
47
53
  "roles/run.admin",
48
54
  "roles/iam.serviceAccountUser",
55
+ ...(config.cloudSql ? ["roles/cloudsql.admin"] : []),
49
56
  ],
50
57
  },
51
58
  GCLOUD_DEPLOY_CREDENTIALS_KEY
@@ -1,15 +1,18 @@
1
1
  import type { Context } from "@catladder/pipeline";
2
- import { getCloudSQLConfig, hasCloudSQL } from "@catladder/pipeline";
2
+ import {
3
+ getKubernetesCloudSQLConfig,
4
+ hasKubernetesCloudSQL,
5
+ } from "@catladder/pipeline";
3
6
  import type { CommandInstance } from "vorpal";
4
7
 
5
8
  export const setupCloudSQL = async (
6
9
  instance: CommandInstance,
7
10
  context: Context
8
11
  ) => {
9
- if (!hasCloudSQL(context)) {
12
+ if (!hasKubernetesCloudSQL(context)) {
10
13
  throw new Error("cannot setup cloudsql, as it has none");
11
14
  }
12
- const config = getCloudSQLConfig(context);
15
+ const config = getKubernetesCloudSQLConfig(context);
13
16
  instance.log("");
14
17
  instance.log(
15
18
  "! make sure to provide cloudsqlProxyCredentials for the cloud sql service account in " +
@@ -1,5 +1,5 @@
1
1
  import type { Context } from "@catladder/pipeline";
2
- import { isOfDeployType, hasCloudSQL } from "@catladder/pipeline";
2
+ import { isOfDeployType, hasKubernetesCloudSQL } from "@catladder/pipeline";
3
3
  import type { CommandInstance } from "vorpal";
4
4
  import { setupCloudRun } from "./setupCloudRun";
5
5
  import { setupCloudSQL } from "./setupCloudSQL";
@@ -25,7 +25,7 @@ export const setupContext = async (
25
25
  if (isOfDeployType(context.componentConfig.deploy, "google-cloudrun")) {
26
26
  await setupCloudRun(instance, context);
27
27
  }
28
- if (hasCloudSQL(context)) {
28
+ if (hasKubernetesCloudSQL(context)) {
29
29
  await setupCloudSQL(instance, context);
30
30
  }
31
31