@catladder/cli 1.145.0 → 1.146.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/dist/bundles/catenv/index.js +1 -1
- package/dist/bundles/cli/index.js +1 -1
- package/dist/cli/src/apps/catci/commands/security/evaluateSecurityAudit.js.map +1 -1
- package/dist/cli/src/apps/catenv/catenv.js +8 -12
- package/dist/cli/src/apps/catenv/catenv.js.map +1 -1
- package/dist/cli/src/apps/cli/commands/general/namespaceAutoCompletion.js +1 -1
- package/dist/cli/src/apps/cli/commands/mongodb/projectMongoGetShell.js.map +1 -1
- package/dist/cli/src/apps/cli/commands/mongodb/projectMongoPortForward.js.map +1 -1
- package/dist/cli/src/apps/cli/commands/mongodb/utils/index.js.map +1 -1
- package/dist/cli/src/apps/cli/commands/project/setup/setupAccessTokens.js.map +1 -1
- package/dist/cli/src/apps/cli/commands/project/setup/setupCloudRun.js +1 -2
- package/dist/cli/src/apps/cli/commands/project/setup/setupCloudRun.js.map +1 -1
- package/dist/cli/src/apps/cli/commands/project/setup/setupKubernetes.js +1 -2
- package/dist/cli/src/apps/cli/commands/project/setup/setupKubernetes.js.map +1 -1
- package/dist/cli/src/apps/cli/commands/project/setup/setupTopic.js.map +1 -1
- package/dist/cli/src/apps/cli/commands/project/utils/ensureNamespace.js +1 -2
- package/dist/cli/src/apps/cli/commands/project/utils/ensureNamespace.js.map +1 -1
- package/dist/cli/src/gcloud/cloudSql/startProxy.js +1 -2
- package/dist/cli/src/gcloud/cloudSql/startProxy.js.map +1 -1
- package/dist/cli/src/utils/gitlab.d.ts +1 -1
- package/dist/cli/src/utils/gitlab.js +38 -26
- package/dist/cli/src/utils/gitlab.js.map +1 -1
- package/dist/cli/src/utils/promise.js.map +1 -1
- package/dist/pipeline/src/context/getEnvironmentVariables.js +1 -2
- package/dist/pipeline/src/context/getEnvironmentVariables.js.map +1 -1
- package/dist/pipeline/src/context/resolveReferences.js.map +1 -1
- package/dist/pipeline/src/deploy/base/deploy.js.map +1 -1
- package/dist/pipeline/src/deploy/cloudRun/createJobs/getCloudRunDeployScripts.js +1 -2
- package/dist/pipeline/src/deploy/cloudRun/createJobs/getCloudRunDeployScripts.js.map +1 -1
- package/dist/pipeline/src/deploy/cloudRun/index.js.map +1 -1
- package/dist/pipeline/src/deploy/kubernetes/kubeValues.js +1 -2
- package/dist/pipeline/src/deploy/kubernetes/kubeValues.js.map +1 -1
- package/dist/pipeline/src/pipeline/createMainPipeline.js.map +1 -1
- package/dist/pipeline/src/pipeline/gitlab/createGitlabJobs.js.map +1 -1
- package/dist/pipeline/src/pipeline/gitlab/getPipelineTriggerForGitlabChildPipeline.js.map +1 -1
- package/dist/pipeline/src/types/config.d.ts +1 -1
- package/dist/pipeline/src/types/jobs.d.ts +1 -1
- package/dist/tsconfig.tsbuildinfo +1 -1
- package/package.json +2 -2
- package/src/apps/catci/commands/security/auditDocument.ts +4 -4
- package/src/apps/catci/commands/security/commands.ts +14 -14
- package/src/apps/catci/commands/security/createSecurityAuditMergeRequest.ts +9 -9
- package/src/apps/catci/commands/security/evaluateSecurityAudit.ts +2 -2
- package/src/apps/catci/commands/security/topics.json +8 -16
- package/src/apps/catenv/catenv.ts +8 -7
- package/src/apps/catenv/printVariables.ts +3 -3
- package/src/apps/catenv/utils.ts +4 -4
- package/src/apps/catenv/writeDotEnvFiles.ts +1 -1
- package/src/apps/catenv/writeEnvDTs.ts +3 -3
- package/src/apps/cli/cli.ts +1 -1
- package/src/apps/cli/commands/cloudSQL/commandRestoreDb.ts +1 -1
- package/src/apps/cli/commands/general/index.ts +2 -2
- package/src/apps/cli/commands/general/namespaceAutoCompletion.ts +1 -1
- package/src/apps/cli/commands/mongodb/projectMongoDestroyMember.ts +11 -11
- package/src/apps/cli/commands/mongodb/projectMongoGetShell.ts +3 -4
- package/src/apps/cli/commands/mongodb/projectMongoPortForward.ts +3 -4
- package/src/apps/cli/commands/mongodb/utils/index.ts +8 -10
- package/src/apps/cli/commands/project/cloudSql/commandProjectRestoreDb.ts +6 -6
- package/src/apps/cli/commands/project/commandCloudSqlProxy.ts +7 -7
- package/src/apps/cli/commands/project/commandConfigSecrets.ts +22 -22
- package/src/apps/cli/commands/project/commandDeletePods.ts +1 -1
- package/src/apps/cli/commands/project/commandDeleteProject.ts +1 -1
- package/src/apps/cli/commands/project/commandEnvVars.ts +1 -1
- package/src/apps/cli/commands/project/commandGetMyTotalWorktime.ts +1 -1
- package/src/apps/cli/commands/project/commandGetShell.ts +1 -1
- package/src/apps/cli/commands/project/commandGitlabCi.ts +4 -4
- package/src/apps/cli/commands/project/commandListPods.ts +2 -2
- package/src/apps/cli/commands/project/commandMigrateHelm3.ts +6 -6
- package/src/apps/cli/commands/project/commandNamespace.ts +1 -1
- package/src/apps/cli/commands/project/commandOpenCostDashboard.ts +2 -2
- package/src/apps/cli/commands/project/commandOpenDashboard.ts +1 -1
- package/src/apps/cli/commands/project/commandOpenGit.ts +1 -1
- package/src/apps/cli/commands/project/commandOpenGrafana.ts +2 -2
- package/src/apps/cli/commands/project/commandOpenGrafanaPod.ts +2 -2
- package/src/apps/cli/commands/project/commandOpenLogs.ts +1 -1
- package/src/apps/cli/commands/project/commandPauseProject.ts +1 -1
- package/src/apps/cli/commands/project/commandSecretsClearBackups.ts +1 -1
- package/src/apps/cli/commands/project/commandSecurityEvaluate.ts +2 -2
- package/src/apps/cli/commands/project/commandSetup.ts +1 -1
- package/src/apps/cli/commands/project/setup/index.ts +1 -1
- package/src/apps/cli/commands/project/setup/setupAccessTokens.ts +5 -6
- package/src/apps/cli/commands/project/setup/setupCloudRun.ts +5 -5
- package/src/apps/cli/commands/project/setup/setupContext.ts +4 -4
- package/src/apps/cli/commands/project/setup/setupKubernetes.ts +14 -14
- package/src/apps/cli/commands/project/setup/setupTopic.ts +4 -9
- package/src/apps/cli/commands/project/utils/autocompletions.ts +1 -1
- package/src/apps/cli/commands/project/utils/ensureCluster.ts +2 -2
- package/src/apps/cli/commands/project/utils/ensureNamespace.ts +5 -5
- package/src/apps/cli/utils/getGoogleAuthUserNumber.ts +1 -1
- package/src/config/getProjectConfig.ts +11 -11
- package/src/gcloud/artifactsRegistry.ts +1 -1
- package/src/gcloud/cloudRun/getCloudRunDomainSuffix.ts +2 -2
- package/src/gcloud/cloudRun/openCloudRunDashboards.ts +2 -2
- package/src/gcloud/cloudSql/copyDb.ts +1 -1
- package/src/gcloud/cloudSql/startProxy.ts +7 -7
- package/src/gcloud/enableServices.ts +2 -2
- package/src/gcloud/openDashboard.ts +1 -1
- package/src/gcloud/serviceAccounts.ts +8 -8
- package/src/kubernetes/index.ts +1 -1
- package/src/kubernetes/openKubernetesDashboards.ts +2 -2
- package/src/kubernetes/portForward.ts +2 -2
- package/src/types/child-process-promise.d.ts +3 -3
- package/src/utils/editAsFile.ts +2 -2
- package/src/utils/gitlab.ts +43 -27
- package/src/utils/log.ts +1 -1
- package/src/utils/portForwards.ts +1 -1
- package/src/utils/promise.ts +7 -5
package/package.json
CHANGED
|
@@ -52,7 +52,7 @@
|
|
|
52
52
|
}
|
|
53
53
|
],
|
|
54
54
|
"license": "MIT",
|
|
55
|
-
"version": "1.
|
|
55
|
+
"version": "1.146.0",
|
|
56
56
|
"scripts": {
|
|
57
57
|
"lint": "eslint \"src/**/*.ts\"",
|
|
58
58
|
"lint:fix": "eslint \"src/**/*.ts\" --fix",
|
|
@@ -102,7 +102,7 @@
|
|
|
102
102
|
"memoizee": "^0.4.14",
|
|
103
103
|
"node-fetch": "^2.3.0",
|
|
104
104
|
"open": "^8.4.0",
|
|
105
|
-
"prettier": "^
|
|
105
|
+
"prettier": "^3.3.2",
|
|
106
106
|
"tmp-promise": "^2.0.2",
|
|
107
107
|
"ts-results-es": "^4.1.0-alpha.1",
|
|
108
108
|
"tsc-alias": "^1.8.10",
|
|
@@ -22,7 +22,7 @@ const rows = [
|
|
|
22
22
|
t.description,
|
|
23
23
|
"",
|
|
24
24
|
t.more,
|
|
25
|
-
])
|
|
25
|
+
]),
|
|
26
26
|
);
|
|
27
27
|
|
|
28
28
|
function makeTable(rows: string[][]) {
|
|
@@ -33,7 +33,7 @@ ${makeRow(rows[0], colWidths, " ")}
|
|
|
33
33
|
${makeRow(
|
|
34
34
|
rows[0].map(() => ""),
|
|
35
35
|
colWidths,
|
|
36
|
-
"-"
|
|
36
|
+
"-",
|
|
37
37
|
)}
|
|
38
38
|
${rows
|
|
39
39
|
.slice(1)
|
|
@@ -45,7 +45,7 @@ ${rows
|
|
|
45
45
|
function calculateColumnWidths(rows: string[][]) {
|
|
46
46
|
const columnCount = rows[0].length;
|
|
47
47
|
return Array.from({ length: columnCount }, (_, i) => i).map((columnIndex) =>
|
|
48
|
-
Math.max(...rows.map((row) => row[columnIndex].length))
|
|
48
|
+
Math.max(...rows.map((row) => row[columnIndex].length)),
|
|
49
49
|
);
|
|
50
50
|
}
|
|
51
51
|
|
|
@@ -115,7 +115,7 @@ export function evaluateDocument(document: string): SecurityEvaluation {
|
|
|
115
115
|
!isUnknown &&
|
|
116
116
|
!answer.includes(checkPlaceholder) &&
|
|
117
117
|
!responsibles.some((responsible) =>
|
|
118
|
-
responsible.includes(responsiblePlaceholder)
|
|
118
|
+
responsible.includes(responsiblePlaceholder),
|
|
119
119
|
);
|
|
120
120
|
const isSecured = !isUnknown && isAnswered && answer.includes(checkYes);
|
|
121
121
|
|
|
@@ -21,7 +21,7 @@ export default function (vorpal: Vorpal) {
|
|
|
21
21
|
type ActionFunc = (args: Vorpal.Args) => Promise<void>;
|
|
22
22
|
|
|
23
23
|
function resultAsExitCode(
|
|
24
|
-
func: (args: Vorpal.Args) => Promise<Result<unknown, unknown
|
|
24
|
+
func: (args: Vorpal.Args) => Promise<Result<unknown, unknown>>,
|
|
25
25
|
): ActionFunc {
|
|
26
26
|
return async (args: Vorpal.Args) => {
|
|
27
27
|
const result = await func(args);
|
|
@@ -40,7 +40,7 @@ async function commandCiJob(vorpal: Vorpal) {
|
|
|
40
40
|
<main-branch> main branch name
|
|
41
41
|
<project-id> project id to create security audit for
|
|
42
42
|
<user-id> gitlab user id that will be assignee of the audit
|
|
43
|
-
|
|
43
|
+
`,
|
|
44
44
|
)
|
|
45
45
|
.action(
|
|
46
46
|
resultAsExitCode(async (args) => {
|
|
@@ -49,7 +49,7 @@ async function commandCiJob(vorpal: Vorpal) {
|
|
|
49
49
|
if (evaluation.isErr()) {
|
|
50
50
|
console.log("could not evaluate security audit document");
|
|
51
51
|
console.log(
|
|
52
|
-
"creating new merge request with security audit template..."
|
|
52
|
+
"creating new merge request with security audit template...",
|
|
53
53
|
);
|
|
54
54
|
|
|
55
55
|
const { token, mainBranch, projectId, userId } = args;
|
|
@@ -67,14 +67,14 @@ async function commandCiJob(vorpal: Vorpal) {
|
|
|
67
67
|
|
|
68
68
|
if (mr.isErr()) {
|
|
69
69
|
console.error(
|
|
70
|
-
`could not create merge request with security audit template: ${mr.error}
|
|
70
|
+
`could not create merge request with security audit template: ${mr.error}`,
|
|
71
71
|
);
|
|
72
72
|
return mr;
|
|
73
73
|
}
|
|
74
74
|
|
|
75
75
|
console.log("security audit merge request created successfully");
|
|
76
76
|
console.log(
|
|
77
|
-
`please finish the MR by updating SECURITY.md document: ${mr.value.web_url}
|
|
77
|
+
`please finish the MR by updating SECURITY.md document: ${mr.value.web_url}`,
|
|
78
78
|
);
|
|
79
79
|
return Err("merge request created" as const);
|
|
80
80
|
}
|
|
@@ -82,14 +82,14 @@ async function commandCiJob(vorpal: Vorpal) {
|
|
|
82
82
|
if (evaluation.value.score.answeredTopics === 0) {
|
|
83
83
|
console.error("audit document has no answered topics");
|
|
84
84
|
console.error(
|
|
85
|
-
`please answer security topics in ${SECURITY_AUDIT_FILE_NAME} by adding responsible people and check/cross in the table
|
|
85
|
+
`please answer security topics in ${SECURITY_AUDIT_FILE_NAME} by adding responsible people and check/cross in the table`,
|
|
86
86
|
);
|
|
87
87
|
return Err("audit document has no answered topics" as const);
|
|
88
88
|
}
|
|
89
89
|
|
|
90
90
|
console.log(makeSecurityAuditOverview(evaluation.value));
|
|
91
91
|
return Ok({});
|
|
92
|
-
})
|
|
92
|
+
}),
|
|
93
93
|
);
|
|
94
94
|
}
|
|
95
95
|
|
|
@@ -97,7 +97,7 @@ async function commandEvaluate(vorpal: Vorpal) {
|
|
|
97
97
|
vorpal
|
|
98
98
|
.command(
|
|
99
99
|
"security-audit-evaluate <path>",
|
|
100
|
-
"Evaluates security audit document in given <path>"
|
|
100
|
+
"Evaluates security audit document in given <path>",
|
|
101
101
|
)
|
|
102
102
|
.action(
|
|
103
103
|
resultAsExitCode(async (args) => {
|
|
@@ -107,13 +107,13 @@ async function commandEvaluate(vorpal: Vorpal) {
|
|
|
107
107
|
if (result.isErr()) {
|
|
108
108
|
console.error(result.error);
|
|
109
109
|
console.error(
|
|
110
|
-
`please make sure the security audit document ${SECURITY_AUDIT_FILE_NAME} is in the repository
|
|
110
|
+
`please make sure the security audit document ${SECURITY_AUDIT_FILE_NAME} is in the repository`,
|
|
111
111
|
);
|
|
112
112
|
} else {
|
|
113
113
|
console.log(makeSecurityAuditOverview(result.value));
|
|
114
114
|
}
|
|
115
115
|
return result;
|
|
116
|
-
})
|
|
116
|
+
}),
|
|
117
117
|
);
|
|
118
118
|
}
|
|
119
119
|
|
|
@@ -127,7 +127,7 @@ async function commandCreate(vorpal: Vorpal) {
|
|
|
127
127
|
<main-branch> main branch name
|
|
128
128
|
<project-id> project id to create security audit for
|
|
129
129
|
<user-id> gitlab user id that will be assignee of the audit
|
|
130
|
-
|
|
130
|
+
`,
|
|
131
131
|
)
|
|
132
132
|
.action(
|
|
133
133
|
resultAsExitCode(async (args) => {
|
|
@@ -147,15 +147,15 @@ async function commandCreate(vorpal: Vorpal) {
|
|
|
147
147
|
|
|
148
148
|
if (result.isErr()) {
|
|
149
149
|
console.error(
|
|
150
|
-
`could not create security audit merge request: ${result.error}
|
|
150
|
+
`could not create security audit merge request: ${result.error}`,
|
|
151
151
|
);
|
|
152
152
|
} else {
|
|
153
153
|
console.log("security audit merge request created successfully");
|
|
154
154
|
console.log(
|
|
155
|
-
`please finish the MR by updating SECURITY.md document: ${result.value.web_url}
|
|
155
|
+
`please finish the MR by updating SECURITY.md document: ${result.value.web_url}`,
|
|
156
156
|
);
|
|
157
157
|
}
|
|
158
158
|
return result;
|
|
159
|
-
})
|
|
159
|
+
}),
|
|
160
160
|
);
|
|
161
161
|
}
|
|
@@ -27,7 +27,7 @@ export async function createSecurityAuditMergeRequest({
|
|
|
27
27
|
state: "opened",
|
|
28
28
|
wip: "yes",
|
|
29
29
|
labels: "security-audit",
|
|
30
|
-
})
|
|
30
|
+
}),
|
|
31
31
|
)
|
|
32
32
|
).mapErr(() => `could not search for existing merge requests` as const);
|
|
33
33
|
if (mrs.isErr()) return mrs;
|
|
@@ -35,11 +35,11 @@ export async function createSecurityAuditMergeRequest({
|
|
|
35
35
|
const existingMr = mrs.value[0];
|
|
36
36
|
if (existingMr)
|
|
37
37
|
return Err(
|
|
38
|
-
`open merge request with security audit already exists: ${existingMr.web_url}
|
|
38
|
+
`open merge request with security audit already exists: ${existingMr.web_url}`,
|
|
39
39
|
);
|
|
40
40
|
|
|
41
41
|
const auditTemplate = Result.wrap(() => makeTemplate()).mapErr(
|
|
42
|
-
() => "could not make security audit template document" as const
|
|
42
|
+
() => "could not make security audit template document" as const,
|
|
43
43
|
);
|
|
44
44
|
if (auditTemplate.isErr()) return auditTemplate;
|
|
45
45
|
|
|
@@ -48,8 +48,8 @@ export async function createSecurityAuditMergeRequest({
|
|
|
48
48
|
api.Branches.create(
|
|
49
49
|
projectId,
|
|
50
50
|
makeDatedBranchName("chore/security-audit"),
|
|
51
|
-
mainBranch
|
|
52
|
-
)
|
|
51
|
+
mainBranch,
|
|
52
|
+
),
|
|
53
53
|
)
|
|
54
54
|
).mapErr((e) => {
|
|
55
55
|
console.log(e);
|
|
@@ -70,8 +70,8 @@ export async function createSecurityAuditMergeRequest({
|
|
|
70
70
|
content: auditTemplate.value,
|
|
71
71
|
encoding: "text",
|
|
72
72
|
},
|
|
73
|
-
]
|
|
74
|
-
)
|
|
73
|
+
],
|
|
74
|
+
),
|
|
75
75
|
)
|
|
76
76
|
).mapErr(() => "could not create commit" as const);
|
|
77
77
|
if (commit.isErr()) return commit;
|
|
@@ -89,8 +89,8 @@ export async function createSecurityAuditMergeRequest({
|
|
|
89
89
|
squash: true,
|
|
90
90
|
labels: "security-audit",
|
|
91
91
|
removeSourceBranch: true,
|
|
92
|
-
}
|
|
93
|
-
)
|
|
92
|
+
},
|
|
93
|
+
),
|
|
94
94
|
)
|
|
95
95
|
).mapErr(() => "could not create merge request" as const);
|
|
96
96
|
|
|
@@ -25,6 +25,6 @@ export function makeSecurityAuditOverview(evaluation: SecurityEvaluation) {
|
|
|
25
25
|
📢 Answered topics: ${evaluation.score.answeredTopics}
|
|
26
26
|
❔ Unknown topics: ${evaluation.score.unknownTopics}
|
|
27
27
|
📊 Rating: ${ratingToEmo(evaluation.score.rating)} ${
|
|
28
|
-
|
|
29
|
-
|
|
28
|
+
evaluation.score.rating
|
|
29
|
+
}/100`;
|
|
30
30
|
}
|
|
@@ -20,8 +20,7 @@
|
|
|
20
20
|
"more": "[Logging guide](https://www.notion.so/panterch/Long-story-logging-022722bb878f4724ae5b49e17667b630?pvs=4#9e5a36b7158a4953b73ec6a345bd8989), [Tracing guide](https://www.notion.so/panterch/Long-story-tracing-d8a9ec1ac2ff4fa78cefa8991233224e?pvs=4#535121b5bf9741fbaf8654b4b64d879d)"
|
|
21
21
|
},
|
|
22
22
|
{
|
|
23
|
-
"description":
|
|
24
|
-
"Passwords are stored hashed with salt and salt is not stored in the repository",
|
|
23
|
+
"description": "Passwords are stored hashed with salt and salt is not stored in the repository",
|
|
25
24
|
"responsibles": 1,
|
|
26
25
|
"more": "[guide](https://git.panter.ch/panter/security-guide/-/blob/main/docs/audit/hash.md)"
|
|
27
26
|
},
|
|
@@ -46,8 +45,7 @@
|
|
|
46
45
|
"more": "[guide](https://git.panter.ch/panter/security-guide/-/blob/main/docs/audit/cookies.md)"
|
|
47
46
|
},
|
|
48
47
|
{
|
|
49
|
-
"description":
|
|
50
|
-
"The app uses JWT with a secret and the secret is not stored in the repository",
|
|
48
|
+
"description": "The app uses JWT with a secret and the secret is not stored in the repository",
|
|
51
49
|
"responsibles": 1,
|
|
52
50
|
"more": "[guide](https://git.panter.ch/panter/security-guide/-/blob/main/docs/audit/cookies.md)"
|
|
53
51
|
},
|
|
@@ -62,8 +60,7 @@
|
|
|
62
60
|
"more": "[guide](https://git.panter.ch/panter/security-guide/-/blob/main/docs/audit/cors.md)"
|
|
63
61
|
},
|
|
64
62
|
{
|
|
65
|
-
"description":
|
|
66
|
-
"CSP headers are properly configured (no `unsafe-inline` or `unsafe-eval`)",
|
|
63
|
+
"description": "CSP headers are properly configured (no `unsafe-inline` or `unsafe-eval`)",
|
|
67
64
|
"responsibles": 1,
|
|
68
65
|
"more": "[guide](https://git.panter.ch/panter/security-guide/-/blob/main/docs/audit/csp.md)"
|
|
69
66
|
},
|
|
@@ -73,8 +70,7 @@
|
|
|
73
70
|
"more": "[guide](https://git.panter.ch/panter/security-guide/-/blob/main/docs/audit/dos.md)"
|
|
74
71
|
},
|
|
75
72
|
{
|
|
76
|
-
"description":
|
|
77
|
-
"YAML/XML parsing is not used or used YAML/XML parsers have disabled DTD",
|
|
73
|
+
"description": "YAML/XML parsing is not used or used YAML/XML parsers have disabled DTD",
|
|
78
74
|
"responsibles": 1,
|
|
79
75
|
"more": "[guide](https://git.panter.ch/panter/security-guide/-/blob/main/docs/audit/dos.md)"
|
|
80
76
|
},
|
|
@@ -89,8 +85,7 @@
|
|
|
89
85
|
"more": ""
|
|
90
86
|
},
|
|
91
87
|
{
|
|
92
|
-
"description":
|
|
93
|
-
"The app has disabled GraphQL introspection and schema registry",
|
|
88
|
+
"description": "The app has disabled GraphQL introspection and schema registry",
|
|
94
89
|
"responsibles": 1,
|
|
95
90
|
"more": "[guide](https://git.panter.ch/panter/security-guide/-/blob/main/docs/audit/graphql.md)"
|
|
96
91
|
},
|
|
@@ -105,20 +100,17 @@
|
|
|
105
100
|
"more": ""
|
|
106
101
|
},
|
|
107
102
|
{
|
|
108
|
-
"description":
|
|
109
|
-
"Cloud storage is (private) configured to not leak any sensitive data publicly",
|
|
103
|
+
"description": "Cloud storage is (private) configured to not leak any sensitive data publicly",
|
|
110
104
|
"responsibles": 1,
|
|
111
105
|
"more": ""
|
|
112
106
|
},
|
|
113
107
|
{
|
|
114
|
-
"description":
|
|
115
|
-
"Security Dashboard checks weekly vulnerable dependencies https://dep.panter.swiss/",
|
|
108
|
+
"description": "Security Dashboard checks weekly vulnerable dependencies https://dep.panter.swiss/",
|
|
116
109
|
"responsibles": 1,
|
|
117
110
|
"more": ""
|
|
118
111
|
},
|
|
119
112
|
{
|
|
120
|
-
"description":
|
|
121
|
-
"The app has `.well-known/security.txt` https://securitytxt.org/",
|
|
113
|
+
"description": "The app has `.well-known/security.txt` https://securitytxt.org/",
|
|
122
114
|
"responsibles": 1,
|
|
123
115
|
"more": ""
|
|
124
116
|
}
|
|
@@ -11,13 +11,14 @@ export default async (choice?: Choice) => {
|
|
|
11
11
|
return;
|
|
12
12
|
}
|
|
13
13
|
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
14
|
+
await Promise.all([
|
|
15
|
+
config.pipelineType
|
|
16
|
+
? generatePipelineFiles(config, config.pipelineType, "local")
|
|
17
|
+
: undefined,
|
|
18
|
+
writeDotEnvFiles(config, choice),
|
|
19
19
|
|
|
20
|
-
|
|
20
|
+
writeDTsFiles(config, choice),
|
|
21
21
|
|
|
22
|
-
|
|
22
|
+
printVariables(config, choice),
|
|
23
|
+
]);
|
|
23
24
|
};
|
|
@@ -10,7 +10,7 @@ import {
|
|
|
10
10
|
const getAllVariablesToPrint = async (config: Config, choice?: Choice) => {
|
|
11
11
|
const { env, currentComponent } = await getCurrentComponentAndEnvFromChoice(
|
|
12
12
|
config,
|
|
13
|
-
choice
|
|
13
|
+
choice,
|
|
14
14
|
);
|
|
15
15
|
|
|
16
16
|
if (currentComponent) {
|
|
@@ -39,11 +39,11 @@ const getAllVariablesToPrint = async (config: Config, choice?: Choice) => {
|
|
|
39
39
|
Object.entries(subappvars).map(([key, value]) => [
|
|
40
40
|
`${sanitizeEnvVarName(componentName.toUpperCase())}_${key}`,
|
|
41
41
|
value,
|
|
42
|
-
])
|
|
42
|
+
]),
|
|
43
43
|
),
|
|
44
44
|
};
|
|
45
45
|
},
|
|
46
|
-
Promise.resolve({} as Record<string, string>)
|
|
46
|
+
Promise.resolve({} as Record<string, string>),
|
|
47
47
|
);
|
|
48
48
|
}
|
|
49
49
|
};
|
package/src/apps/catenv/utils.ts
CHANGED
|
@@ -5,7 +5,7 @@ import type { Choice, Variables } from "./types";
|
|
|
5
5
|
export const getComponentFullPath = (
|
|
6
6
|
gitRoot: string,
|
|
7
7
|
config: Config,
|
|
8
|
-
componentName: string
|
|
8
|
+
componentName: string,
|
|
9
9
|
) => {
|
|
10
10
|
return join(gitRoot, config.components[componentName].dir);
|
|
11
11
|
};
|
|
@@ -13,13 +13,13 @@ const getCurrentComponentName = async (config: Config) => {
|
|
|
13
13
|
const gitRoot = await getGitRoot();
|
|
14
14
|
const currentDir = process.cwd();
|
|
15
15
|
return Object.keys(config.components).find((c) =>
|
|
16
|
-
currentDir.startsWith(getComponentFullPath(gitRoot, config, c))
|
|
16
|
+
currentDir.startsWith(getComponentFullPath(gitRoot, config, c)),
|
|
17
17
|
);
|
|
18
18
|
};
|
|
19
19
|
|
|
20
20
|
export const getCurrentComponentAndEnvFromChoice = async (
|
|
21
21
|
config: Config,
|
|
22
|
-
choice?: Choice
|
|
22
|
+
choice?: Choice,
|
|
23
23
|
) => {
|
|
24
24
|
const env = choice?.env ?? "local";
|
|
25
25
|
const currentComponent =
|
|
@@ -41,7 +41,7 @@ export const sanitizeMultiLine = (variables: Variables) => {
|
|
|
41
41
|
Object.entries(variables).map(([key, value]) => [
|
|
42
42
|
key,
|
|
43
43
|
value.replaceAll("\n", "\\n"),
|
|
44
|
-
])
|
|
44
|
+
]),
|
|
45
45
|
);
|
|
46
46
|
};
|
|
47
47
|
|
|
@@ -14,7 +14,7 @@ import {
|
|
|
14
14
|
export const writeDotEnvFiles = async (config: Config, choice?: Choice) => {
|
|
15
15
|
const { env, currentComponent } = await getCurrentComponentAndEnvFromChoice(
|
|
16
16
|
config,
|
|
17
|
-
choice
|
|
17
|
+
choice,
|
|
18
18
|
);
|
|
19
19
|
|
|
20
20
|
const componentsWithEnabledDotEnvWrite = Object.entries(config.components)
|
|
@@ -11,7 +11,7 @@ import {
|
|
|
11
11
|
export const writeDTsFiles = async (config: Config, choice?: Choice) => {
|
|
12
12
|
const { env, currentComponent } = await getCurrentComponentAndEnvFromChoice(
|
|
13
13
|
config,
|
|
14
|
-
choice
|
|
14
|
+
choice,
|
|
15
15
|
);
|
|
16
16
|
|
|
17
17
|
const componentsWithEnabledEnvDTsWrite = Object.entries(config.components)
|
|
@@ -39,7 +39,7 @@ export const writeDTsFiles = async (config: Config, choice?: Choice) => {
|
|
|
39
39
|
|
|
40
40
|
async function getEnvsForDTs(
|
|
41
41
|
env: string,
|
|
42
|
-
componentName: string
|
|
42
|
+
componentName: string,
|
|
43
43
|
): Promise<string[]> {
|
|
44
44
|
const environment = await getEnvironment(env, componentName);
|
|
45
45
|
const allEnvKeys = Object.keys(environment.envVars);
|
|
@@ -47,7 +47,7 @@ async function getEnvsForDTs(
|
|
|
47
47
|
environment.secretEnvVarKeys
|
|
48
48
|
.filter((s) => s.hidden)
|
|
49
49
|
.map((s) => s.key)
|
|
50
|
-
.concat(["_ALL_ENV_VAR_KEYS"])
|
|
50
|
+
.concat(["_ALL_ENV_VAR_KEYS"]),
|
|
51
51
|
);
|
|
52
52
|
const dTsEnvKeys = allEnvKeys.filter((k) => !hiddenEnvKeys.has(k));
|
|
53
53
|
|
package/src/apps/cli/cli.ts
CHANGED
|
@@ -7,7 +7,7 @@ export default async (vorpal: Vorpal) =>
|
|
|
7
7
|
vorpal
|
|
8
8
|
.command(
|
|
9
9
|
"cloud-sql-restore-db",
|
|
10
|
-
"restore a db from one source to another target"
|
|
10
|
+
"restore a db from one source to another target",
|
|
11
11
|
)
|
|
12
12
|
.action(async function restoreDb() {
|
|
13
13
|
const { sourceInstance } = await this.prompt({
|
|
@@ -17,7 +17,7 @@ const getAllNamespaces = memoizee(
|
|
|
17
17
|
const res = await k8sApi.listNamespace();
|
|
18
18
|
return res.body.items;
|
|
19
19
|
},
|
|
20
|
-
{ maxAge: 30000, promise: true }
|
|
20
|
+
{ maxAge: 30000, promise: true },
|
|
21
21
|
);
|
|
22
22
|
|
|
23
23
|
export const getAllNamespacesNames = async () => {
|
|
@@ -65,7 +65,7 @@ export default async (vorpal: Vorpal) => {
|
|
|
65
65
|
vorpal
|
|
66
66
|
.command(
|
|
67
67
|
"kube-get-shell <namespace>",
|
|
68
|
-
"get a shell to a pod in the environment"
|
|
68
|
+
"get a shell to a pod in the environment",
|
|
69
69
|
)
|
|
70
70
|
.autocomplete(namespaceAutoCompletion)
|
|
71
71
|
.action(async function ({ namespace }) {
|
|
@@ -10,22 +10,22 @@ import { getMongoDbPodsWithReplInfo } from "./utils";
|
|
|
10
10
|
const removeFinalizer = async (
|
|
11
11
|
namespace: string,
|
|
12
12
|
type: "pod" | "pv" | "pvc",
|
|
13
|
-
name: string
|
|
13
|
+
name: string,
|
|
14
14
|
) =>
|
|
15
15
|
exec(
|
|
16
|
-
`kubectl patch --namespace ${namespace} ${type} ${name} -p '{"metadata":{"finalizers":null}}'
|
|
16
|
+
`kubectl patch --namespace ${namespace} ${type} ${name} -p '{"metadata":{"finalizers":null}}'`,
|
|
17
17
|
);
|
|
18
18
|
|
|
19
19
|
const deleteResource = async (
|
|
20
20
|
namespace: string,
|
|
21
21
|
type: "pod" | "pv" | "pvc",
|
|
22
|
-
name: string
|
|
22
|
+
name: string,
|
|
23
23
|
) => exec(`kubectl delete --namespace ${namespace} ${type} ${name}`);
|
|
24
24
|
|
|
25
25
|
const removeFinalizerAndDelete = async (
|
|
26
26
|
namespace: string,
|
|
27
27
|
type: "pod" | "pv" | "pvc",
|
|
28
|
-
name: string
|
|
28
|
+
name: string,
|
|
29
29
|
) => {
|
|
30
30
|
return Promise.all([
|
|
31
31
|
removeFinalizer(namespace, type, name),
|
|
@@ -36,29 +36,29 @@ export default async (vorpal: Vorpal) =>
|
|
|
36
36
|
vorpal
|
|
37
37
|
.command(
|
|
38
38
|
"project-mongo-destroy-member <envComponent>",
|
|
39
|
-
"DESTROY a member of a replicaset in order to reinitialize it"
|
|
39
|
+
"DESTROY a member of a replicaset in order to reinitialize it",
|
|
40
40
|
)
|
|
41
41
|
.autocomplete(await envAndComponents())
|
|
42
42
|
.action(async function ({ envComponent }) {
|
|
43
43
|
await ensureCluster.call(this, envComponent);
|
|
44
44
|
this.log(
|
|
45
|
-
"this command tries to delete a (secondary) member of the replicaset, it's persistent volume claim (pvc) and the volume"
|
|
45
|
+
"this command tries to delete a (secondary) member of the replicaset, it's persistent volume claim (pvc) and the volume",
|
|
46
46
|
);
|
|
47
47
|
this.log("");
|
|
48
48
|
this.log(
|
|
49
|
-
"this is useful, if you update the stateful set with new volume configuration (different size or storage class)"
|
|
49
|
+
"this is useful, if you update the stateful set with new volume configuration (different size or storage class)",
|
|
50
50
|
);
|
|
51
51
|
this.log("");
|
|
52
52
|
this.log(
|
|
53
|
-
"Kubernetes will usually recreate the missing member with the updated config and mongodb will start synchronizing the new member."
|
|
53
|
+
"Kubernetes will usually recreate the missing member with the updated config and mongodb will start synchronizing the new member.",
|
|
54
54
|
);
|
|
55
55
|
this.log("");
|
|
56
56
|
this.log(
|
|
57
|
-
"This works without downtime, but should be done when load on the db is low. Also it has not been tested with large dbs (> 10gi)"
|
|
57
|
+
"This works without downtime, but should be done when load on the db is low. Also it has not been tested with large dbs (> 10gi)",
|
|
58
58
|
);
|
|
59
59
|
this.log("");
|
|
60
60
|
this.log(
|
|
61
|
-
"Deleting the volume and claim often stuck, just wait or cancel and restart."
|
|
61
|
+
"Deleting the volume and claim often stuck, just wait or cancel and restart.",
|
|
62
62
|
);
|
|
63
63
|
this.log("");
|
|
64
64
|
const { understood } = await this.prompt({
|
|
@@ -96,7 +96,7 @@ export default async (vorpal: Vorpal) =>
|
|
|
96
96
|
).podName;
|
|
97
97
|
|
|
98
98
|
const thePvc = pvcs.find(
|
|
99
|
-
(pvc) => pvc.metadata.name === `datadir-${podName}
|
|
99
|
+
(pvc) => pvc.metadata.name === `datadir-${podName}`,
|
|
100
100
|
);
|
|
101
101
|
if (!thePvc) {
|
|
102
102
|
logError(this, `sorry, no pvc found for ${podName}`);
|
|
@@ -12,15 +12,14 @@ export default async (vorpal: Vorpal) =>
|
|
|
12
12
|
vorpal
|
|
13
13
|
.command(
|
|
14
14
|
"project-mongo-get-shell <envComponent>",
|
|
15
|
-
"get a shell to a mongodb in the environment"
|
|
15
|
+
"get a shell to a mongodb in the environment",
|
|
16
16
|
)
|
|
17
17
|
.autocomplete(await envAndComponents())
|
|
18
18
|
.action(async function ({ envComponent }) {
|
|
19
19
|
await ensureCluster.call(this, envComponent);
|
|
20
20
|
const namespace = await getProjectNamespace(envComponent);
|
|
21
|
-
const podNames =
|
|
22
|
-
envComponent
|
|
23
|
-
);
|
|
21
|
+
const podNames =
|
|
22
|
+
await getProjectMongodbAllPodsSortedWithLabel(envComponent);
|
|
24
23
|
if (podNames.length === 0) {
|
|
25
24
|
logError(this, "sorry, no pods found");
|
|
26
25
|
return;
|
|
@@ -15,15 +15,14 @@ export default async (vorpal: Vorpal) =>
|
|
|
15
15
|
vorpal
|
|
16
16
|
.command(
|
|
17
17
|
"project-mongo-port-forward <envComponent>",
|
|
18
|
-
"port foward to a mongodb"
|
|
18
|
+
"port foward to a mongodb",
|
|
19
19
|
)
|
|
20
20
|
.autocomplete(await envAndComponents())
|
|
21
21
|
.action(async function ({ envComponent }) {
|
|
22
22
|
await ensureCluster.call(this, envComponent);
|
|
23
23
|
const namespace = await getProjectNamespace(envComponent);
|
|
24
|
-
const podNames =
|
|
25
|
-
envComponent
|
|
26
|
-
);
|
|
24
|
+
const podNames =
|
|
25
|
+
await getProjectMongodbAllPodsSortedWithLabel(envComponent);
|
|
27
26
|
if (podNames.length === 0) {
|
|
28
27
|
logError(this, "sorry, no pods found");
|
|
29
28
|
return;
|
|
@@ -7,7 +7,7 @@ const filterMongoDbs = (podNames: string[]) =>
|
|
|
7
7
|
(name) =>
|
|
8
8
|
name.includes("mongodb") &&
|
|
9
9
|
!name.includes("mongodb-backup") &&
|
|
10
|
-
!name.includes("arbiter")
|
|
10
|
+
!name.includes("arbiter"),
|
|
11
11
|
);
|
|
12
12
|
|
|
13
13
|
export const getProjectMongodbAllPods = async (envComponent: string) =>
|
|
@@ -32,7 +32,7 @@ export const getMongodbShell = async (namespace: string, podName: string) => {
|
|
|
32
32
|
export const executeMongodbCommand = async (
|
|
33
33
|
namespace: string,
|
|
34
34
|
podName: string,
|
|
35
|
-
mongoCommand: string
|
|
35
|
+
mongoCommand: string,
|
|
36
36
|
) => {
|
|
37
37
|
const fullCommand = `kubectl exec -it ${podName} --namespace ${namespace} -- mongo --quiet --eval "JSON.stringify(${mongoCommand})"`;
|
|
38
38
|
const { stdout } = await exec(fullCommand, {
|
|
@@ -50,7 +50,7 @@ export const podIsMaster = async (namespace: string, podName: string) => {
|
|
|
50
50
|
const result = await executeMongodbCommand(
|
|
51
51
|
namespace,
|
|
52
52
|
podName,
|
|
53
|
-
"db.isMaster()"
|
|
53
|
+
"db.isMaster()",
|
|
54
54
|
);
|
|
55
55
|
|
|
56
56
|
return result.ismaster;
|
|
@@ -66,28 +66,26 @@ export const getMongoDbPodsWithReplInfo = async (envComponent: string) => {
|
|
|
66
66
|
const namespace = await getProjectNamespace(envComponent);
|
|
67
67
|
return (
|
|
68
68
|
await Promise.all(
|
|
69
|
-
(
|
|
70
|
-
await getProjectMongodbAllPods(envComponent)
|
|
71
|
-
).map(async (podName) => ({
|
|
69
|
+
(await getProjectMongodbAllPods(envComponent)).map(async (podName) => ({
|
|
72
70
|
podName,
|
|
73
71
|
componentName: podName.replace(/-mongodb-replicaset-[0-9]+/, ""),
|
|
74
72
|
isMaster: await podIsMaster(namespace, podName),
|
|
75
|
-
}))
|
|
73
|
+
})),
|
|
76
74
|
)
|
|
77
75
|
).sort((podA, podB) => (podA.isMaster ? (podB.isMaster ? 0 : -1) : 1));
|
|
78
76
|
};
|
|
79
77
|
|
|
80
78
|
export const getProjectMongodbAllPodsSortedWithLabel = async (
|
|
81
|
-
envComponent: string
|
|
79
|
+
envComponent: string,
|
|
82
80
|
) => {
|
|
83
81
|
const pods = await getMongoDbPodsWithReplInfo(envComponent);
|
|
84
82
|
const maxComponentNameLength = Math.max(
|
|
85
|
-
...pods.map((c) => c.componentName.length)
|
|
83
|
+
...pods.map((c) => c.componentName.length),
|
|
86
84
|
);
|
|
87
85
|
return pods.map(({ podName, isMaster, componentName }) => ({
|
|
88
86
|
value: podName,
|
|
89
87
|
name: `[ ${componentName}${spaces(
|
|
90
|
-
maxComponentNameLength - componentName.length
|
|
88
|
+
maxComponentNameLength - componentName.length,
|
|
91
89
|
)} ${isMaster ? " PRIMARY " : " secondary "}] ${podName}`,
|
|
92
90
|
}));
|
|
93
91
|
};
|