keycloakify 11.5.0 → 11.5.2
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/bin/40.index.js +85 -0
- package/bin/490.index.js +85 -0
- package/bin/573.index.js +85 -0
- package/bin/653.index.js +85 -0
- package/bin/658.index.js +85 -0
- package/bin/682.index.js +246 -39
- package/bin/735.index.js +85 -0
- package/bin/main.js +1 -118
- package/bin/start-keycloak/getSupportedDockerImageTags.d.ts +4 -1
- package/bin/start-keycloak/realmConfig/ParsedRealmJson.d.ts +8 -1
- package/package.json +1 -1
- package/src/bin/main.ts +2 -41
- package/src/bin/start-keycloak/getSupportedDockerImageTags.ts +51 -14
- package/src/bin/start-keycloak/realmConfig/ParsedRealmJson.ts +20 -2
- package/src/bin/start-keycloak/realmConfig/defaultConfig/realm-kc-26.json +27 -9
- package/src/bin/start-keycloak/realmConfig/dumpContainerConfig.ts +71 -24
- package/src/bin/start-keycloak/realmConfig/prepareRealmConfig.ts +64 -1
- package/src/bin/start-keycloak/realmConfig/realmConfig.ts +13 -5
- package/src/bin/start-keycloak/start-keycloak.ts +3 -3
package/package.json
CHANGED
package/src/bin/main.ts
CHANGED
@@ -5,9 +5,6 @@ import { readThisNpmPackageVersion } from "./tools/readThisNpmPackageVersion";
|
|
5
5
|
import * as child_process from "child_process";
|
6
6
|
import { assertNoPnpmDlx } from "./tools/assertNoPnpmDlx";
|
7
7
|
import { getBuildContext } from "./shared/buildContext";
|
8
|
-
import { SemVer } from "./tools/SemVer";
|
9
|
-
import { assert, is } from "tsafe/assert";
|
10
|
-
import chalk from "chalk";
|
11
8
|
|
12
9
|
type CliCommandOptions = {
|
13
10
|
projectDirPath: string | undefined;
|
@@ -137,47 +134,11 @@ program
|
|
137
134
|
handler: async ({ projectDirPath, keycloakVersion, port, realmJsonFilePath }) => {
|
138
135
|
const { command } = await import("./start-keycloak");
|
139
136
|
|
140
|
-
validate_keycloak_version: {
|
141
|
-
if (keycloakVersion === undefined) {
|
142
|
-
break validate_keycloak_version;
|
143
|
-
}
|
144
|
-
|
145
|
-
const isValidVersion = (() => {
|
146
|
-
if (typeof keycloakVersion === "number") {
|
147
|
-
return false;
|
148
|
-
}
|
149
|
-
|
150
|
-
try {
|
151
|
-
SemVer.parse(keycloakVersion);
|
152
|
-
} catch {
|
153
|
-
return false;
|
154
|
-
}
|
155
|
-
|
156
|
-
return;
|
157
|
-
})();
|
158
|
-
|
159
|
-
if (isValidVersion) {
|
160
|
-
break validate_keycloak_version;
|
161
|
-
}
|
162
|
-
|
163
|
-
console.log(
|
164
|
-
chalk.red(
|
165
|
-
[
|
166
|
-
`Invalid Keycloak version: ${keycloakVersion}`,
|
167
|
-
"It should be a valid semver version example: 26.0.4"
|
168
|
-
].join(" ")
|
169
|
-
)
|
170
|
-
);
|
171
|
-
|
172
|
-
process.exit(1);
|
173
|
-
}
|
174
|
-
|
175
|
-
assert(is<string | undefined>(keycloakVersion));
|
176
|
-
|
177
137
|
await command({
|
178
138
|
buildContext: getBuildContext({ projectDirPath }),
|
179
139
|
cliCommandOptions: {
|
180
|
-
keycloakVersion
|
140
|
+
keycloakVersion:
|
141
|
+
keycloakVersion === undefined ? undefined : `${keycloakVersion}`,
|
181
142
|
port,
|
182
143
|
realmJsonFilePath
|
183
144
|
}
|
@@ -10,6 +10,7 @@ import { join as pathJoin, dirname as pathDirname } from "path";
|
|
10
10
|
import * as fs from "fs/promises";
|
11
11
|
import { existsAsync } from "../tools/fs.existsAsync";
|
12
12
|
import { readThisNpmPackageVersion } from "../tools/readThisNpmPackageVersion";
|
13
|
+
import type { ReturnType } from "tsafe";
|
13
14
|
|
14
15
|
export type BuildContextLike = {
|
15
16
|
fetchOptions: BuildContext["fetchOptions"];
|
@@ -20,7 +21,10 @@ assert<BuildContext extends BuildContextLike ? true : false>;
|
|
20
21
|
|
21
22
|
export async function getSupportedDockerImageTags(params: {
|
22
23
|
buildContext: BuildContextLike;
|
23
|
-
}) {
|
24
|
+
}): Promise<{
|
25
|
+
allSupportedTags: string[];
|
26
|
+
latestMajorTags: string[];
|
27
|
+
}> {
|
24
28
|
const { buildContext } = params;
|
25
29
|
|
26
30
|
{
|
@@ -31,14 +35,14 @@ export async function getSupportedDockerImageTags(params: {
|
|
31
35
|
}
|
32
36
|
}
|
33
37
|
|
34
|
-
const
|
38
|
+
const tags_queryResponse: string[] = [];
|
35
39
|
|
36
40
|
await (async function callee(url: string) {
|
37
41
|
const r = await fetch(url, buildContext.fetchOptions);
|
38
42
|
|
39
43
|
await Promise.all([
|
40
44
|
(async () => {
|
41
|
-
|
45
|
+
tags_queryResponse.push(
|
42
46
|
...z
|
43
47
|
.object({
|
44
48
|
tags: z.array(z.string())
|
@@ -70,7 +74,9 @@ export async function getSupportedDockerImageTags(params: {
|
|
70
74
|
]);
|
71
75
|
})("https://quay.io/v2/keycloak/keycloak/tags/list");
|
72
76
|
|
73
|
-
const
|
77
|
+
const supportedKeycloakMajorVersions = getSupportedKeycloakMajorVersions();
|
78
|
+
|
79
|
+
const allSupportedTags_withVersion = tags_queryResponse
|
74
80
|
.map(tag => ({
|
75
81
|
tag,
|
76
82
|
version: (() => {
|
@@ -86,28 +92,35 @@ export async function getSupportedDockerImageTags(params: {
|
|
86
92
|
return undefined;
|
87
93
|
}
|
88
94
|
|
95
|
+
if (tag.split(".").length !== 3) {
|
96
|
+
return undefined;
|
97
|
+
}
|
98
|
+
|
99
|
+
if (!supportedKeycloakMajorVersions.includes(version.major)) {
|
100
|
+
return undefined;
|
101
|
+
}
|
102
|
+
|
89
103
|
return version;
|
90
104
|
})()
|
91
105
|
}))
|
92
106
|
.map(({ tag, version }) => (version === undefined ? undefined : { tag, version }))
|
93
|
-
.filter(exclude(undefined))
|
107
|
+
.filter(exclude(undefined))
|
108
|
+
.sort(({ version: a }, { version: b }) => SemVer.compare(b, a));
|
94
109
|
|
95
|
-
const
|
110
|
+
const latestTagByMajor: Record<number, SemVer | undefined> = {};
|
96
111
|
|
97
|
-
for (const { version } of
|
98
|
-
const version_current =
|
112
|
+
for (const { version } of allSupportedTags_withVersion) {
|
113
|
+
const version_current = latestTagByMajor[version.major];
|
99
114
|
|
100
115
|
if (
|
101
116
|
version_current === undefined ||
|
102
117
|
SemVer.compare(version_current, version) === -1
|
103
118
|
) {
|
104
|
-
|
119
|
+
latestTagByMajor[version.major] = version;
|
105
120
|
}
|
106
121
|
}
|
107
122
|
|
108
|
-
const
|
109
|
-
|
110
|
-
const result = Object.entries(versionByMajor)
|
123
|
+
const latestMajorTags = Object.entries(latestTagByMajor)
|
111
124
|
.sort(([a], [b]) => parseInt(b) - parseInt(a))
|
112
125
|
.map(([, version]) => version)
|
113
126
|
.map(version => {
|
@@ -121,16 +134,40 @@ export async function getSupportedDockerImageTags(params: {
|
|
121
134
|
})
|
122
135
|
.filter(exclude(undefined));
|
123
136
|
|
137
|
+
const allSupportedTags = allSupportedTags_withVersion.map(({ tag }) => tag);
|
138
|
+
|
139
|
+
const result = {
|
140
|
+
latestMajorTags,
|
141
|
+
allSupportedTags
|
142
|
+
};
|
143
|
+
|
124
144
|
await setCachedValue({ cacheDirPath: buildContext.cacheDirPath, result });
|
125
145
|
|
126
146
|
return result;
|
127
147
|
}
|
128
148
|
|
129
149
|
const { getCachedValue, setCachedValue } = (() => {
|
150
|
+
type Result = ReturnType<typeof getSupportedDockerImageTags>;
|
151
|
+
|
152
|
+
const zResult = (() => {
|
153
|
+
type TargetType = Result;
|
154
|
+
|
155
|
+
const zTargetType = z.object({
|
156
|
+
allSupportedTags: z.array(z.string()),
|
157
|
+
latestMajorTags: z.array(z.string())
|
158
|
+
});
|
159
|
+
|
160
|
+
type InferredType = z.infer<typeof zTargetType>;
|
161
|
+
|
162
|
+
assert<Equals<TargetType, InferredType>>;
|
163
|
+
|
164
|
+
return id<z.ZodType<TargetType>>(zTargetType);
|
165
|
+
})();
|
166
|
+
|
130
167
|
type Cache = {
|
131
168
|
keycloakifyVersion: string;
|
132
169
|
time: number;
|
133
|
-
result:
|
170
|
+
result: Result;
|
134
171
|
};
|
135
172
|
|
136
173
|
const zCache = (() => {
|
@@ -139,7 +176,7 @@ const { getCachedValue, setCachedValue } = (() => {
|
|
139
176
|
const zTargetType = z.object({
|
140
177
|
keycloakifyVersion: z.string(),
|
141
178
|
time: z.number(),
|
142
|
-
result:
|
179
|
+
result: zResult
|
143
180
|
});
|
144
181
|
|
145
182
|
type InferredType = z.infer<typeof zTargetType>;
|
@@ -39,7 +39,14 @@ export type ParsedRealmJson = {
|
|
39
39
|
"post.logout.redirect.uris"?: string;
|
40
40
|
};
|
41
41
|
protocol?: string;
|
42
|
-
protocolMappers?:
|
42
|
+
protocolMappers?: {
|
43
|
+
id: string;
|
44
|
+
name: string;
|
45
|
+
protocol: string; // "openid-connect" or something else
|
46
|
+
protocolMapper: string; // "oidc-hardcoded-claim-mapper" or something else
|
47
|
+
consentRequired: boolean;
|
48
|
+
config?: Record<string, string>;
|
49
|
+
}[];
|
43
50
|
}[];
|
44
51
|
};
|
45
52
|
|
@@ -89,7 +96,18 @@ const zParsedRealmJson = (() => {
|
|
89
96
|
})
|
90
97
|
.optional(),
|
91
98
|
protocol: z.string().optional(),
|
92
|
-
protocolMappers: z
|
99
|
+
protocolMappers: z
|
100
|
+
.array(
|
101
|
+
z.object({
|
102
|
+
id: z.string(),
|
103
|
+
name: z.string(),
|
104
|
+
protocol: z.string(),
|
105
|
+
protocolMapper: z.string(),
|
106
|
+
consentRequired: z.boolean(),
|
107
|
+
config: z.record(z.string()).optional()
|
108
|
+
})
|
109
|
+
)
|
110
|
+
.optional()
|
93
111
|
})
|
94
112
|
)
|
95
113
|
});
|
@@ -985,6 +985,24 @@
|
|
985
985
|
"claim.name": "locale",
|
986
986
|
"jsonType.label": "String"
|
987
987
|
}
|
988
|
+
},
|
989
|
+
{
|
990
|
+
"id": "8fd0d584-7052-4d04-a615-d18a71050873",
|
991
|
+
"name": "allowed-origins",
|
992
|
+
"protocol": "openid-connect",
|
993
|
+
"protocolMapper": "oidc-hardcoded-claim-mapper",
|
994
|
+
"consentRequired": false,
|
995
|
+
"config": {
|
996
|
+
"introspection.token.claim": "true",
|
997
|
+
"claim.value": "[\"*\"]",
|
998
|
+
"userinfo.token.claim": "true",
|
999
|
+
"id.token.claim": "false",
|
1000
|
+
"lightweight.claim": "false",
|
1001
|
+
"access.token.claim": "true",
|
1002
|
+
"claim.name": "allowed-origins",
|
1003
|
+
"jsonType.label": "JSON",
|
1004
|
+
"access.tokenResponse.claim": "false"
|
1005
|
+
}
|
988
1006
|
}
|
989
1007
|
],
|
990
1008
|
"defaultClientScopes": [
|
@@ -1640,13 +1658,13 @@
|
|
1640
1658
|
"config": {
|
1641
1659
|
"allowed-protocol-mapper-types": [
|
1642
1660
|
"oidc-usermodel-property-mapper",
|
1643
|
-
"saml-user-attribute-mapper",
|
1644
1661
|
"saml-user-property-mapper",
|
1645
|
-
"oidc-full-name-mapper",
|
1646
|
-
"oidc-sha256-pairwise-sub-mapper",
|
1647
1662
|
"oidc-address-mapper",
|
1663
|
+
"saml-user-attribute-mapper",
|
1664
|
+
"saml-role-list-mapper",
|
1665
|
+
"oidc-sha256-pairwise-sub-mapper",
|
1648
1666
|
"oidc-usermodel-attribute-mapper",
|
1649
|
-
"
|
1667
|
+
"oidc-full-name-mapper"
|
1650
1668
|
]
|
1651
1669
|
}
|
1652
1670
|
},
|
@@ -1676,14 +1694,14 @@
|
|
1676
1694
|
"subComponents": {},
|
1677
1695
|
"config": {
|
1678
1696
|
"allowed-protocol-mapper-types": [
|
1679
|
-
"oidc-sha256-pairwise-sub-mapper",
|
1680
1697
|
"saml-user-attribute-mapper",
|
1681
|
-
"oidc-usermodel-property-mapper",
|
1682
1698
|
"oidc-full-name-mapper",
|
1683
|
-
"
|
1699
|
+
"oidc-sha256-pairwise-sub-mapper",
|
1684
1700
|
"saml-user-property-mapper",
|
1685
|
-
"oidc-usermodel-
|
1686
|
-
"
|
1701
|
+
"oidc-usermodel-property-mapper",
|
1702
|
+
"saml-role-list-mapper",
|
1703
|
+
"oidc-address-mapper",
|
1704
|
+
"oidc-usermodel-attribute-mapper"
|
1687
1705
|
]
|
1688
1706
|
}
|
1689
1707
|
},
|
@@ -1,6 +1,6 @@
|
|
1
1
|
import { CONTAINER_NAME } from "../../shared/constants";
|
2
2
|
import child_process from "child_process";
|
3
|
-
import { join as pathJoin } from "path";
|
3
|
+
import { join as pathJoin, dirname as pathDirname, basename as pathBasename } from "path";
|
4
4
|
import chalk from "chalk";
|
5
5
|
import { Deferred } from "evt/tools/Deferred";
|
6
6
|
import { assert, is } from "tsafe/assert";
|
@@ -20,16 +20,37 @@ export async function dumpContainerConfig(params: {
|
|
20
20
|
}): Promise<ParsedRealmJson> {
|
21
21
|
const { realmName, keycloakMajorVersionNumber, buildContext } = params;
|
22
22
|
|
23
|
-
|
24
|
-
|
25
|
-
const doesUseLockedH2Database = keycloakMajorVersionNumber >= 25;
|
23
|
+
// https://github.com/keycloak/keycloak/issues/33800
|
24
|
+
const doesUseLockedH2Database = keycloakMajorVersionNumber >= 25;
|
26
25
|
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
26
|
+
if (doesUseLockedH2Database) {
|
27
|
+
const dCompleted = new Deferred<void>();
|
28
|
+
|
29
|
+
const cmd = `docker exec ${CONTAINER_NAME} sh -c "cp -rp /opt/keycloak/data/h2 /tmp"`;
|
30
|
+
|
31
|
+
child_process.exec(cmd, error => {
|
32
|
+
if (error !== null) {
|
33
|
+
dCompleted.reject(error);
|
34
|
+
return;
|
35
|
+
}
|
36
|
+
|
37
|
+
dCompleted.resolve();
|
38
|
+
});
|
39
|
+
|
40
|
+
try {
|
41
|
+
await dCompleted.pr;
|
42
|
+
} catch (error) {
|
43
|
+
assert(is<Error>(error));
|
44
|
+
|
45
|
+
console.log(chalk.red(`Docker command failed: ${cmd}`));
|
46
|
+
|
47
|
+
console.log(chalk.red(error.message));
|
48
|
+
|
49
|
+
throw error;
|
31
50
|
}
|
51
|
+
}
|
32
52
|
|
53
|
+
{
|
33
54
|
const dCompleted = new Deferred<void>();
|
34
55
|
|
35
56
|
const child = child_process.spawn(
|
@@ -56,7 +77,9 @@ export async function dumpContainerConfig(params: {
|
|
56
77
|
let output = "";
|
57
78
|
|
58
79
|
const onExit = (code: number | null) => {
|
59
|
-
dCompleted.reject(
|
80
|
+
dCompleted.reject(
|
81
|
+
new Error(`docker exec kc.sh export command failed with code ${code}`)
|
82
|
+
);
|
60
83
|
};
|
61
84
|
|
62
85
|
child.once("exit", onExit);
|
@@ -96,25 +119,34 @@ export async function dumpContainerConfig(params: {
|
|
96
119
|
|
97
120
|
console.log(output);
|
98
121
|
|
99
|
-
|
122
|
+
throw error;
|
100
123
|
}
|
124
|
+
}
|
101
125
|
|
102
|
-
|
103
|
-
|
126
|
+
if (doesUseLockedH2Database) {
|
127
|
+
const dCompleted = new Deferred<void>();
|
104
128
|
|
105
|
-
|
106
|
-
`docker exec ${CONTAINER_NAME} sh -c "rm -rf /tmp/h2"`,
|
107
|
-
error => {
|
108
|
-
if (error !== null) {
|
109
|
-
dCompleted.reject(error);
|
110
|
-
return;
|
111
|
-
}
|
129
|
+
const cmd = `docker exec ${CONTAINER_NAME} sh -c "rm -rf /tmp/h2"`;
|
112
130
|
|
113
|
-
|
114
|
-
|
115
|
-
|
131
|
+
child_process.exec(cmd, error => {
|
132
|
+
if (error !== null) {
|
133
|
+
dCompleted.reject(error);
|
134
|
+
return;
|
135
|
+
}
|
116
136
|
|
137
|
+
dCompleted.resolve();
|
138
|
+
});
|
139
|
+
|
140
|
+
try {
|
117
141
|
await dCompleted.pr;
|
142
|
+
} catch (error) {
|
143
|
+
assert(is<Error>(error));
|
144
|
+
|
145
|
+
console.log(chalk.red(`Docker command failed: ${cmd}`));
|
146
|
+
|
147
|
+
console.log(chalk.red(error.message));
|
148
|
+
|
149
|
+
throw error;
|
118
150
|
}
|
119
151
|
}
|
120
152
|
|
@@ -126,8 +158,13 @@ export async function dumpContainerConfig(params: {
|
|
126
158
|
{
|
127
159
|
const dCompleted = new Deferred<void>();
|
128
160
|
|
161
|
+
const cmd = `docker cp ${CONTAINER_NAME}:/tmp/${realmName}-realm.json ${pathBasename(targetRealmConfigJsonFilePath_tmp)}`;
|
162
|
+
|
129
163
|
child_process.exec(
|
130
|
-
|
164
|
+
cmd,
|
165
|
+
{
|
166
|
+
cwd: pathDirname(targetRealmConfigJsonFilePath_tmp)
|
167
|
+
},
|
131
168
|
error => {
|
132
169
|
if (error !== null) {
|
133
170
|
dCompleted.reject(error);
|
@@ -138,7 +175,17 @@ export async function dumpContainerConfig(params: {
|
|
138
175
|
}
|
139
176
|
);
|
140
177
|
|
141
|
-
|
178
|
+
try {
|
179
|
+
await dCompleted.pr;
|
180
|
+
} catch (error) {
|
181
|
+
assert(is<Error>(error));
|
182
|
+
|
183
|
+
console.log(chalk.red(`Docker command failed: ${cmd}`));
|
184
|
+
|
185
|
+
console.log(chalk.red(error.message));
|
186
|
+
|
187
|
+
throw error;
|
188
|
+
}
|
142
189
|
}
|
143
190
|
|
144
191
|
return readRealmJsonFile({
|
@@ -276,7 +276,7 @@ function editAccountConsoleAndSecurityAdminConsole(params: {
|
|
276
276
|
}) {
|
277
277
|
const { parsedRealmJson } = params;
|
278
278
|
|
279
|
-
for (const clientId of ["account-console", "security-admin-console"]) {
|
279
|
+
for (const clientId of ["account-console", "security-admin-console"] as const) {
|
280
280
|
const client = parsedRealmJson.clients.find(
|
281
281
|
client => client.clientId === clientId
|
282
282
|
);
|
@@ -298,5 +298,68 @@ function editAccountConsoleAndSecurityAdminConsole(params: {
|
|
298
298
|
(client.attributes ??= {})["post.logout.redirect.uris"] = "+";
|
299
299
|
|
300
300
|
client.webOrigins = ["*"];
|
301
|
+
|
302
|
+
admin_specific: {
|
303
|
+
if (clientId !== "security-admin-console") {
|
304
|
+
break admin_specific;
|
305
|
+
}
|
306
|
+
|
307
|
+
const protocolMapper_preexisting = client.protocolMappers?.find(
|
308
|
+
protocolMapper => {
|
309
|
+
if (protocolMapper.protocolMapper !== "oidc-hardcoded-claim-mapper") {
|
310
|
+
return false;
|
311
|
+
}
|
312
|
+
|
313
|
+
if (protocolMapper.protocol !== "openid-connect") {
|
314
|
+
return false;
|
315
|
+
}
|
316
|
+
|
317
|
+
if (protocolMapper.config === undefined) {
|
318
|
+
return false;
|
319
|
+
}
|
320
|
+
|
321
|
+
if (protocolMapper.config["claim.name"] !== "allowed-origins") {
|
322
|
+
return false;
|
323
|
+
}
|
324
|
+
|
325
|
+
return true;
|
326
|
+
}
|
327
|
+
);
|
328
|
+
|
329
|
+
let protocolMapper: NonNullable<typeof protocolMapper_preexisting>;
|
330
|
+
|
331
|
+
const config = {
|
332
|
+
"introspection.token.claim": "true",
|
333
|
+
"claim.value": '["*"]',
|
334
|
+
"userinfo.token.claim": "true",
|
335
|
+
"id.token.claim": "false",
|
336
|
+
"lightweight.claim": "false",
|
337
|
+
"access.token.claim": "true",
|
338
|
+
"claim.name": "allowed-origins",
|
339
|
+
"jsonType.label": "JSON",
|
340
|
+
"access.tokenResponse.claim": "false"
|
341
|
+
};
|
342
|
+
|
343
|
+
if (protocolMapper_preexisting !== undefined) {
|
344
|
+
protocolMapper = protocolMapper_preexisting;
|
345
|
+
} else {
|
346
|
+
protocolMapper = {
|
347
|
+
id: "8fd0d584-7052-4d04-a615-d18a71050873",
|
348
|
+
name: "allowed-origins",
|
349
|
+
protocol: "openid-connect",
|
350
|
+
protocolMapper: "oidc-hardcoded-claim-mapper",
|
351
|
+
consentRequired: false,
|
352
|
+
config
|
353
|
+
};
|
354
|
+
|
355
|
+
(client.protocolMappers ??= []).push(protocolMapper);
|
356
|
+
}
|
357
|
+
|
358
|
+
assert(protocolMapper.config !== undefined);
|
359
|
+
|
360
|
+
if (config !== protocolMapper.config) {
|
361
|
+
Object.assign(protocolMapper.config, config);
|
362
|
+
}
|
363
|
+
}
|
301
364
|
}
|
302
365
|
}
|
@@ -105,11 +105,19 @@ export async function getRealmConfig(params: {
|
|
105
105
|
chalk.grey(`Changes detected to the '${realmName}' config, backing up...`)
|
106
106
|
);
|
107
107
|
|
108
|
-
|
109
|
-
|
110
|
-
|
111
|
-
|
112
|
-
|
108
|
+
let parsedRealmJson: ParsedRealmJson;
|
109
|
+
|
110
|
+
try {
|
111
|
+
parsedRealmJson = await dumpContainerConfig({
|
112
|
+
buildContext,
|
113
|
+
realmName,
|
114
|
+
keycloakMajorVersionNumber
|
115
|
+
});
|
116
|
+
} catch (error) {
|
117
|
+
console.log(chalk.red(`Failed to backup '${realmName}' config:`));
|
118
|
+
|
119
|
+
return;
|
120
|
+
}
|
113
121
|
|
114
122
|
await writeRealmJsonFile({ parsedRealmJson });
|
115
123
|
|
@@ -97,7 +97,7 @@ export async function command(params: {
|
|
97
97
|
|
98
98
|
const { cliCommandOptions, buildContext } = params;
|
99
99
|
|
100
|
-
const
|
100
|
+
const { allSupportedTags, latestMajorTags } = await getSupportedDockerImageTags({
|
101
101
|
buildContext
|
102
102
|
});
|
103
103
|
|
@@ -105,7 +105,7 @@ export async function command(params: {
|
|
105
105
|
if (cliCommandOptions.keycloakVersion !== undefined) {
|
106
106
|
const cliCommandOptions_keycloakVersion = cliCommandOptions.keycloakVersion;
|
107
107
|
|
108
|
-
const tag =
|
108
|
+
const tag = allSupportedTags.find(tag =>
|
109
109
|
tag.startsWith(cliCommandOptions_keycloakVersion)
|
110
110
|
);
|
111
111
|
|
@@ -143,7 +143,7 @@ export async function command(params: {
|
|
143
143
|
);
|
144
144
|
|
145
145
|
const { value: tag } = await cliSelect<string>({
|
146
|
-
values:
|
146
|
+
values: latestMajorTags
|
147
147
|
}).catch(() => {
|
148
148
|
process.exit(-1);
|
149
149
|
});
|