@abgov/nx-oc 12.3.0 → 12.5.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
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@abgov/nx-oc",
3
- "version": "12.3.0",
3
+ "version": "12.5.0",
4
4
  "license": "Apache-2.0",
5
5
  "main": "src/index.js",
6
6
  "description": "Government of Alberta - Nx plugin for OpenShift.",
@@ -14,12 +14,14 @@ const express = require("express");
14
14
  const open = require("open");
15
15
  const simple_oauth2_1 = require("simple-oauth2");
16
16
  const environments_1 = require("./environments");
17
+ const token_cache_1 = require("./token-cache");
17
18
  function hasDependency(host, dependency) {
18
19
  const { dependencies, devDependencies } = (0, devkit_1.readJson)(host, 'package.json');
19
20
  return !!(dependencies === null || dependencies === void 0 ? void 0 : dependencies[dependency]) || !!(devDependencies === null || devDependencies === void 0 ? void 0 : devDependencies[dependency]);
20
21
  }
21
22
  function realmLogin(accessServiceUrl, realm) {
22
23
  return tslib_1.__awaiter(this, void 0, void 0, function* () {
24
+ var _a, _b;
23
25
  const client = new simple_oauth2_1.AuthorizationCode({
24
26
  client: {
25
27
  id: 'nx-adsp-cli',
@@ -31,6 +33,28 @@ function realmLogin(accessServiceUrl, realm) {
31
33
  authorizePath: `/auth/realms/${realm}/protocol/openid-connect/auth`,
32
34
  },
33
35
  });
36
+ // Core realm is only used to fetch the tenant list — not worth caching.
37
+ if (realm !== 'core') {
38
+ const cached = (0, token_cache_1.getCachedToken)(accessServiceUrl, realm);
39
+ if (cached) {
40
+ if (!(0, token_cache_1.isExpired)(cached)) {
41
+ return cached.accessToken;
42
+ }
43
+ if (cached.refreshToken) {
44
+ try {
45
+ const { token } = yield client
46
+ .createToken({ access_token: cached.accessToken, refresh_token: cached.refreshToken })
47
+ .refresh();
48
+ const expiresIn = (_a = token['expires_in']) !== null && _a !== void 0 ? _a : 300;
49
+ (0, token_cache_1.setCachedToken)(accessServiceUrl, realm, token['access_token'], token['refresh_token'], expiresIn);
50
+ return token['access_token'];
51
+ }
52
+ catch (_c) {
53
+ // Refresh failed — fall through to browser login.
54
+ }
55
+ }
56
+ }
57
+ }
34
58
  const redirect_uri = 'http://localhost:3000/callback';
35
59
  const authorizationUri = client.authorizeURL({
36
60
  redirect_uri,
@@ -59,6 +83,10 @@ function realmLogin(accessServiceUrl, realm) {
59
83
  tokenPromise,
60
84
  new Promise((_, reject) => setTimeout(() => reject(new Error('Timed out waiting for login.')), 120000)),
61
85
  ]).finally(() => server.close());
86
+ if (realm !== 'core') {
87
+ const expiresIn = (_b = token['expires_in']) !== null && _b !== void 0 ? _b : 300;
88
+ (0, token_cache_1.setCachedToken)(accessServiceUrl, realm, token['access_token'], token['refresh_token'], expiresIn);
89
+ }
62
90
  return token['access_token'];
63
91
  });
64
92
  }
@@ -1 +1 @@
1
- {"version":3,"file":"adsp-utils.js","sourceRoot":"","sources":["../../../../../packages/nx-oc/src/adsp/adsp-utils.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"adsp-utils.js","sourceRoot":"","sources":["../../../../../packages/nx-oc/src/adsp/adsp-utils.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,9 @@
1
+ export interface CacheEntry {
2
+ accessToken: string;
3
+ refreshToken?: string;
4
+ expiresAt: string;
5
+ }
6
+ export declare function getCacheFilePath(): string;
7
+ export declare function isExpired(entry: CacheEntry): boolean;
8
+ export declare function getCachedToken(accessServiceUrl: string, realm: string): CacheEntry | null;
9
+ export declare function setCachedToken(accessServiceUrl: string, realm: string, accessToken: string, refreshToken: string | undefined, expiresIn: number): void;
@@ -0,0 +1,49 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.getCacheFilePath = getCacheFilePath;
4
+ exports.isExpired = isExpired;
5
+ exports.getCachedToken = getCachedToken;
6
+ exports.setCachedToken = setCachedToken;
7
+ const fs = require("fs");
8
+ const os = require("os");
9
+ const path = require("path");
10
+ const EXPIRY_BUFFER_MS = 60000;
11
+ function getCacheFilePath() {
12
+ return path.join(os.homedir(), '.nx-adsp', 'token-cache.json');
13
+ }
14
+ function readCache() {
15
+ try {
16
+ return JSON.parse(fs.readFileSync(getCacheFilePath(), 'utf-8'));
17
+ }
18
+ catch (_a) {
19
+ return {};
20
+ }
21
+ }
22
+ function writeCache(cache) {
23
+ const filePath = getCacheFilePath();
24
+ const dir = path.dirname(filePath);
25
+ if (!fs.existsSync(dir)) {
26
+ fs.mkdirSync(dir, { recursive: true, mode: 0o700 });
27
+ }
28
+ fs.writeFileSync(filePath, JSON.stringify(cache, null, 2), { mode: 0o600, encoding: 'utf-8' });
29
+ }
30
+ function cacheKey(accessServiceUrl, realm) {
31
+ return `${accessServiceUrl}::${realm}`;
32
+ }
33
+ function isExpired(entry) {
34
+ return new Date(entry.expiresAt).getTime() - EXPIRY_BUFFER_MS < Date.now();
35
+ }
36
+ function getCachedToken(accessServiceUrl, realm) {
37
+ var _a;
38
+ return (_a = readCache()[cacheKey(accessServiceUrl, realm)]) !== null && _a !== void 0 ? _a : null;
39
+ }
40
+ function setCachedToken(accessServiceUrl, realm, accessToken, refreshToken, expiresIn) {
41
+ const cache = readCache();
42
+ cache[cacheKey(accessServiceUrl, realm)] = {
43
+ accessToken,
44
+ refreshToken,
45
+ expiresAt: new Date(Date.now() + expiresIn * 1000).toISOString(),
46
+ };
47
+ writeCache(cache);
48
+ }
49
+ //# sourceMappingURL=token-cache.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"token-cache.js","sourceRoot":"","sources":["../../../../../packages/nx-oc/src/adsp/token-cache.ts"],"names":[],"mappings":";;AAcA,4CAEC;AAuBD,8BAEC;AAED,wCAEC;AAED,wCAcC;AA7DD,yBAAyB;AACzB,yBAAyB;AACzB,6BAA6B;AAU7B,MAAM,gBAAgB,GAAG,KAAM,CAAC;AAEhC,SAAgB,gBAAgB;IAC9B,OAAO,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC,OAAO,EAAE,EAAE,UAAU,EAAE,kBAAkB,CAAC,CAAC;AACjE,CAAC;AAED,SAAS,SAAS;IAChB,IAAI,CAAC;QACH,OAAO,IAAI,CAAC,KAAK,CAAC,EAAE,CAAC,YAAY,CAAC,gBAAgB,EAAE,EAAE,OAAO,CAAC,CAAe,CAAC;IAChF,CAAC;IAAC,WAAM,CAAC;QACP,OAAO,EAAE,CAAC;IACZ,CAAC;AACH,CAAC;AAED,SAAS,UAAU,CAAC,KAAiB;IACnC,MAAM,QAAQ,GAAG,gBAAgB,EAAE,CAAC;IACpC,MAAM,GAAG,GAAG,IAAI,CAAC,OAAO,CAAC,QAAQ,CAAC,CAAC;IACnC,IAAI,CAAC,EAAE,CAAC,UAAU,CAAC,GAAG,CAAC,EAAE,CAAC;QACxB,EAAE,CAAC,SAAS,CAAC,GAAG,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,IAAI,EAAE,KAAK,EAAE,CAAC,CAAC;IACtD,CAAC;IACD,EAAE,CAAC,aAAa,CAAC,QAAQ,EAAE,IAAI,CAAC,SAAS,CAAC,KAAK,EAAE,IAAI,EAAE,CAAC,CAAC,EAAE,EAAE,IAAI,EAAE,KAAK,EAAE,QAAQ,EAAE,OAAO,EAAE,CAAC,CAAC;AACjG,CAAC;AAED,SAAS,QAAQ,CAAC,gBAAwB,EAAE,KAAa;IACvD,OAAO,GAAG,gBAAgB,KAAK,KAAK,EAAE,CAAC;AACzC,CAAC;AAED,SAAgB,SAAS,CAAC,KAAiB;IACzC,OAAO,IAAI,IAAI,CAAC,KAAK,CAAC,SAAS,CAAC,CAAC,OAAO,EAAE,GAAG,gBAAgB,GAAG,IAAI,CAAC,GAAG,EAAE,CAAC;AAC7E,CAAC;AAED,SAAgB,cAAc,CAAC,gBAAwB,EAAE,KAAa;;IACpE,OAAO,MAAA,SAAS,EAAE,CAAC,QAAQ,CAAC,gBAAgB,EAAE,KAAK,CAAC,CAAC,mCAAI,IAAI,CAAC;AAChE,CAAC;AAED,SAAgB,cAAc,CAC5B,gBAAwB,EACxB,KAAa,EACb,WAAmB,EACnB,YAAgC,EAChC,SAAiB;IAEjB,MAAM,KAAK,GAAG,SAAS,EAAE,CAAC;IAC1B,KAAK,CAAC,QAAQ,CAAC,gBAAgB,EAAE,KAAK,CAAC,CAAC,GAAG;QACzC,WAAW;QACX,YAAY;QACZ,SAAS,EAAE,IAAI,IAAI,CAAC,IAAI,CAAC,GAAG,EAAE,GAAG,SAAS,GAAG,IAAI,CAAC,CAAC,WAAW,EAAE;KACjE,CAAC;IACF,UAAU,CAAC,KAAK,CAAC,CAAC;AACpB,CAAC"}
@@ -0,0 +1,117 @@
1
+ import * as fs from 'fs';
2
+ import * as os from 'os';
3
+ import * as path from 'path';
4
+ import { getCacheFilePath, getCachedToken, isExpired, setCachedToken, CacheEntry } from './token-cache';
5
+
6
+ jest.mock('fs');
7
+ jest.mock('os');
8
+
9
+ const mockedFs = jest.mocked(fs);
10
+ const mockedOs = jest.mocked(os);
11
+
12
+ const FAKE_HOME = '/home/testuser';
13
+ const CACHE_PATH = path.join(FAKE_HOME, '.nx-adsp', 'token-cache.json');
14
+
15
+ const ACCESS_URL = 'https://access.example.com/auth';
16
+ const REALM = 'my-tenant';
17
+
18
+ function futureIso(secondsFromNow: number): string {
19
+ return new Date(Date.now() + secondsFromNow * 1000).toISOString();
20
+ }
21
+
22
+ function pastIso(secondsAgo: number): string {
23
+ return new Date(Date.now() - secondsAgo * 1000).toISOString();
24
+ }
25
+
26
+ describe('getCacheFilePath', () => {
27
+ it('returns path under home directory', () => {
28
+ mockedOs.homedir.mockReturnValue(FAKE_HOME);
29
+ expect(getCacheFilePath()).toBe(CACHE_PATH);
30
+ });
31
+ });
32
+
33
+ describe('isExpired', () => {
34
+ it('returns false when token expires in the future (beyond buffer)', () => {
35
+ const entry: CacheEntry = { accessToken: 'tok', expiresAt: futureIso(120) };
36
+ expect(isExpired(entry)).toBe(false);
37
+ });
38
+
39
+ it('returns true when token is past its expiry', () => {
40
+ const entry: CacheEntry = { accessToken: 'tok', expiresAt: pastIso(10) };
41
+ expect(isExpired(entry)).toBe(true);
42
+ });
43
+
44
+ it('returns true when token expires within the 60-second buffer', () => {
45
+ const entry: CacheEntry = { accessToken: 'tok', expiresAt: futureIso(30) };
46
+ expect(isExpired(entry)).toBe(true);
47
+ });
48
+ });
49
+
50
+ describe('getCachedToken', () => {
51
+ beforeEach(() => {
52
+ mockedOs.homedir.mockReturnValue(FAKE_HOME);
53
+ });
54
+
55
+ it('returns null when cache file does not exist', () => {
56
+ mockedFs.readFileSync.mockImplementation(() => { throw new Error('ENOENT'); });
57
+ expect(getCachedToken(ACCESS_URL, REALM)).toBeNull();
58
+ });
59
+
60
+ it('returns null when realm is not in cache', () => {
61
+ mockedFs.readFileSync.mockReturnValue(JSON.stringify({ 'other::realm': { accessToken: 'x', expiresAt: futureIso(3600) } }));
62
+ expect(getCachedToken(ACCESS_URL, REALM)).toBeNull();
63
+ });
64
+
65
+ it('returns the cached entry when present', () => {
66
+ const entry: CacheEntry = { accessToken: 'abc', refreshToken: 'ref', expiresAt: futureIso(3600) };
67
+ const key = `${ACCESS_URL}::${REALM}`;
68
+ mockedFs.readFileSync.mockReturnValue(JSON.stringify({ [key]: entry }));
69
+
70
+ expect(getCachedToken(ACCESS_URL, REALM)).toEqual(entry);
71
+ });
72
+ });
73
+
74
+ describe('setCachedToken', () => {
75
+ beforeEach(() => {
76
+ mockedOs.homedir.mockReturnValue(FAKE_HOME);
77
+ mockedFs.existsSync.mockReturnValue(true);
78
+ mockedFs.readFileSync.mockImplementation(() => { throw new Error('ENOENT'); });
79
+ (mockedFs.writeFileSync as jest.Mock).mockReset();
80
+ (mockedFs.mkdirSync as jest.Mock).mockReset();
81
+ });
82
+
83
+ it('writes a new entry with correct fields', () => {
84
+ setCachedToken(ACCESS_URL, REALM, 'access-tok', 'refresh-tok', 3600);
85
+
86
+ expect(mockedFs.writeFileSync).toHaveBeenCalledWith(
87
+ CACHE_PATH,
88
+ expect.stringContaining('"accessToken": "access-tok"'),
89
+ expect.objectContaining({ mode: 0o600 })
90
+ );
91
+
92
+ const written = JSON.parse((mockedFs.writeFileSync as jest.Mock).mock.calls[0][1] as string);
93
+ const entry = written[`${ACCESS_URL}::${REALM}`];
94
+ expect(entry.accessToken).toBe('access-tok');
95
+ expect(entry.refreshToken).toBe('refresh-tok');
96
+ expect(new Date(entry.expiresAt).getTime()).toBeGreaterThan(Date.now() + 3590 * 1000);
97
+ });
98
+
99
+ it('writes without refreshToken when not provided', () => {
100
+ setCachedToken(ACCESS_URL, REALM, 'access-tok', undefined, 3600);
101
+
102
+ const written = JSON.parse((mockedFs.writeFileSync as jest.Mock).mock.calls[0][1] as string);
103
+ const entry = written[`${ACCESS_URL}::${REALM}`];
104
+ expect(entry.refreshToken).toBeUndefined();
105
+ });
106
+
107
+ it('creates the cache directory if it does not exist', () => {
108
+ mockedFs.existsSync.mockReturnValue(false);
109
+
110
+ setCachedToken(ACCESS_URL, REALM, 'tok', undefined, 300);
111
+
112
+ expect(mockedFs.mkdirSync).toHaveBeenCalledWith(
113
+ path.dirname(CACHE_PATH),
114
+ expect.objectContaining({ recursive: true, mode: 0o700 })
115
+ );
116
+ });
117
+ });
@@ -14,13 +14,14 @@ function applyOcResources(host) {
14
14
  }
15
15
  function default_1(host) {
16
16
  return tslib_1.__awaiter(this, void 0, void 0, function* () {
17
- const { success } = (0, oc_utils_1.runOcCommand)('project', []);
18
- if (success) {
19
- applyOcResources(host);
17
+ try {
18
+ (0, oc_utils_1.ensureOcLogin)();
20
19
  }
21
- else {
22
- console.log(`Use oc login then run 'nx g @abgov/nx-oc:apply-infra'`);
20
+ catch (e) {
21
+ console.log(e instanceof Error ? e.message : String(e));
22
+ return;
23
23
  }
24
+ applyOcResources(host);
24
25
  });
25
26
  }
26
27
  //# sourceMappingURL=apply-infra.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"apply-infra.js","sourceRoot":"","sources":["../../../../../../packages/nx-oc/src/generators/apply-infra/apply-infra.ts"],"names":[],"mappings":";;AAuBA,4BAOC;;AA7BD,mDAAoD;AAEpD,SAAS,gBAAgB,CAAC,IAAU;IAClC,MAAM,EAAE,OAAO,EAAE,eAAe,EAAE,MAAM,EAAE,WAAW,EAAE,GAAG,IAAA,uBAAY,EACpE,OAAO,EACP,EAAE,EACF,IAAI,CAAC,IAAI,CAAC,kCAAkC,CAAC,CAC9C,CAAC;IACF,OAAO,CAAC,GAAG,CAAC,WAAW,aAAX,WAAW,uBAAX,WAAW,CAAE,QAAQ,EAAE,CAAC,CAAC;IAErC,MAAM,EAAE,OAAO,EAAE,UAAU,EAAE,MAAM,EAAE,MAAM,EAAE,GAAG,IAAA,uBAAY,EAC1D,OAAO,EACP,EAAE,EACF,IAAI,CAAC,IAAI,CAAC,6BAA6B,CAAC,CACzC,CAAC;IACF,OAAO,CAAC,GAAG,CAAC,MAAM,aAAN,MAAM,uBAAN,MAAM,CAAE,QAAQ,EAAE,CAAC,CAAC;IAEhC,IAAI,CAAC,eAAe,IAAI,CAAC,UAAU,EAAE,CAAC;QACpC,OAAO,CAAC,GAAG,CAAC,kDAAkD,CAAC,CAAC;IAClE,CAAC;AACH,CAAC;AAED,mBAA+B,IAAU;;QACvC,MAAM,EAAE,OAAO,EAAE,GAAG,IAAA,uBAAY,EAAC,SAAS,EAAE,EAAE,CAAC,CAAC;QAChD,IAAI,OAAO,EAAE,CAAC;YACZ,gBAAgB,CAAC,IAAI,CAAC,CAAC;QACzB,CAAC;aAAM,CAAC;YACN,OAAO,CAAC,GAAG,CAAC,uDAAuD,CAAC,CAAC;QACvE,CAAC;IACH,CAAC;CAAA"}
1
+ {"version":3,"file":"apply-infra.js","sourceRoot":"","sources":["../../../../../../packages/nx-oc/src/generators/apply-infra/apply-infra.ts"],"names":[],"mappings":";;AAuBA,4BAQC;;AA9BD,mDAAmE;AAEnE,SAAS,gBAAgB,CAAC,IAAU;IAClC,MAAM,EAAE,OAAO,EAAE,eAAe,EAAE,MAAM,EAAE,WAAW,EAAE,GAAG,IAAA,uBAAY,EACpE,OAAO,EACP,EAAE,EACF,IAAI,CAAC,IAAI,CAAC,kCAAkC,CAAC,CAC9C,CAAC;IACF,OAAO,CAAC,GAAG,CAAC,WAAW,aAAX,WAAW,uBAAX,WAAW,CAAE,QAAQ,EAAE,CAAC,CAAC;IAErC,MAAM,EAAE,OAAO,EAAE,UAAU,EAAE,MAAM,EAAE,MAAM,EAAE,GAAG,IAAA,uBAAY,EAC1D,OAAO,EACP,EAAE,EACF,IAAI,CAAC,IAAI,CAAC,6BAA6B,CAAC,CACzC,CAAC;IACF,OAAO,CAAC,GAAG,CAAC,MAAM,aAAN,MAAM,uBAAN,MAAM,CAAE,QAAQ,EAAE,CAAC,CAAC;IAEhC,IAAI,CAAC,eAAe,IAAI,CAAC,UAAU,EAAE,CAAC;QACpC,OAAO,CAAC,GAAG,CAAC,kDAAkD,CAAC,CAAC;IAClE,CAAC;AACH,CAAC;AAED,mBAA+B,IAAU;;QACvC,IAAI,CAAC;YACH,IAAA,wBAAa,GAAE,CAAC;QAClB,CAAC;QAAC,OAAO,CAAC,EAAE,CAAC;YACX,OAAO,CAAC,GAAG,CAAC,CAAC,YAAY,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,CAAC;YACxD,OAAO;QACT,CAAC;QACD,gBAAgB,CAAC,IAAI,CAAC,CAAC;IACzB,CAAC;CAAA"}
@@ -1,14 +1,16 @@
1
1
  import { createTree } from '@nx/devkit/testing';
2
2
  import { mocked } from 'jest-mock';
3
3
  import generator from './apply-infra';
4
- import { runOcCommand } from '../../utils/oc-utils';
4
+ import { ensureOcLogin, runOcCommand } from '../../utils/oc-utils';
5
5
  import { writeJson } from '@nx/devkit';
6
6
 
7
7
  jest.mock('../../utils/oc-utils');
8
+ const mockedEnsureOcLogin = mocked(ensureOcLogin);
8
9
  const mockedRunOcCommand = mocked(runOcCommand);
9
10
 
10
11
  describe('Apply Infra Generator', () => {
11
12
  beforeEach(() => {
13
+ mockedEnsureOcLogin.mockReset();
12
14
  mockedRunOcCommand.mockReset();
13
15
  });
14
16
 
@@ -21,9 +23,20 @@ describe('Apply Infra Generator', () => {
21
23
 
22
24
  await generator(host);
23
25
 
24
- expect(mockedRunOcCommand.mock.calls.length).toBe(3);
25
- expect(mockedRunOcCommand.mock.calls[0][0]).toBe('project');
26
+ expect(mockedEnsureOcLogin).toHaveBeenCalledTimes(1);
27
+ expect(mockedRunOcCommand.mock.calls.length).toBe(2);
28
+ expect(mockedRunOcCommand.mock.calls[0][0]).toBe('apply');
26
29
  expect(mockedRunOcCommand.mock.calls[1][0]).toBe('apply');
27
- expect(mockedRunOcCommand.mock.calls[2][0]).toBe('apply');
30
+ });
31
+
32
+ it('logs login error and exits cleanly without running oc apply', async () => {
33
+ const host = createTree();
34
+ mockedEnsureOcLogin.mockImplementation(() => {
35
+ throw new Error('oc CLI is not installed or not on PATH.');
36
+ });
37
+
38
+ await generator(host);
39
+
40
+ expect(mockedRunOcCommand).not.toHaveBeenCalled();
28
41
  });
29
42
  });
@@ -2,3 +2,4 @@ export declare function runOcCommand(command: 'project' | 'start-build' | 'proce
2
2
  success: boolean;
3
3
  stdout?: Buffer;
4
4
  };
5
+ export declare function ensureOcLogin(): void;
@@ -1,6 +1,7 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.runOcCommand = runOcCommand;
4
+ exports.ensureOcLogin = ensureOcLogin;
4
5
  const child_process_1 = require("child_process");
5
6
  function runOcCommand(command, params, input) {
6
7
  const args = input
@@ -16,4 +17,35 @@ function runOcCommand(command, params, input) {
16
17
  return { success: false };
17
18
  }
18
19
  }
20
+ function ensureOcLogin() {
21
+ try {
22
+ (0, child_process_1.execFileSync)('oc', ['version', '--client'], { stdio: 'pipe' });
23
+ }
24
+ catch (_a) {
25
+ throw new Error("oc CLI is not installed or not on PATH. Install it from https://mirror.openshift.com/pub/openshift-v4/clients/ocp/latest/ then re-run.");
26
+ }
27
+ try {
28
+ (0, child_process_1.execFileSync)('oc', ['whoami'], { stdio: 'pipe' });
29
+ return;
30
+ }
31
+ catch (_b) {
32
+ // not logged in — fall through to interactive login
33
+ }
34
+ let server = null;
35
+ try {
36
+ server =
37
+ (0, child_process_1.execFileSync)('oc', ['config', 'view', '--minify', '-o', 'jsonpath={.clusters[0].cluster.server}'], { stdio: 'pipe' })
38
+ .toString()
39
+ .trim() || null;
40
+ }
41
+ catch (_c) {
42
+ // no kubeconfig — oc login will prompt for server
43
+ }
44
+ console.log('Not logged in to OpenShift. Starting interactive login...');
45
+ const loginArgs = server ? ['login', server, '--web'] : ['login', '--web'];
46
+ const result = (0, child_process_1.spawnSync)('oc', loginArgs, { stdio: 'inherit' });
47
+ if (result.status !== 0) {
48
+ throw new Error("OpenShift login failed or was cancelled. Run 'oc login' manually then re-run the generator.");
49
+ }
50
+ }
19
51
  //# sourceMappingURL=oc-utils.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"oc-utils.js","sourceRoot":"","sources":["../../../../../packages/nx-oc/src/utils/oc-utils.ts"],"names":[],"mappings":";;AAEA,oCAiBC;AAnBD,iDAA6C;AAE7C,SAAgB,YAAY,CAC1B,OAAwD,EACxD,MAAgB,EAChB,KAAc;IAEd,MAAM,IAAI,GAAG,KAAK;QAChB,CAAC,CAAC,CAAC,OAAO,EAAE,IAAI,EAAE,GAAG,EAAE,GAAG,MAAM,CAAC;QACjC,CAAC,CAAC,CAAC,OAAO,EAAE,GAAG,MAAM,CAAC,CAAC;IAEzB,IAAI,CAAC;QACH,OAAO,CAAC,GAAG,CAAC,yBAAyB,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC;QACvD,MAAM,MAAM,GAAG,IAAA,4BAAY,EAAC,IAAI,EAAE,IAAI,EAAE,EAAE,KAAK,EAAE,MAAM,EAAE,KAAK,EAAE,CAAC,CAAC;QAClE,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,MAAM,EAAE,CAAC;IACnC,CAAC;IAAC,OAAO,CAAC,EAAE,CAAC;QACX,OAAO,CAAC,GAAG,CAAC,iCAAiC,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC;QAClE,OAAO,EAAE,OAAO,EAAE,KAAK,EAAE,CAAC;IAC5B,CAAC;AACH,CAAC"}
1
+ {"version":3,"file":"oc-utils.js","sourceRoot":"","sources":["../../../../../packages/nx-oc/src/utils/oc-utils.ts"],"names":[],"mappings":";;AAEA,oCAiBC;AAED,sCAmCC;AAxDD,iDAAwD;AAExD,SAAgB,YAAY,CAC1B,OAAwD,EACxD,MAAgB,EAChB,KAAc;IAEd,MAAM,IAAI,GAAG,KAAK;QAChB,CAAC,CAAC,CAAC,OAAO,EAAE,IAAI,EAAE,GAAG,EAAE,GAAG,MAAM,CAAC;QACjC,CAAC,CAAC,CAAC,OAAO,EAAE,GAAG,MAAM,CAAC,CAAC;IAEzB,IAAI,CAAC;QACH,OAAO,CAAC,GAAG,CAAC,yBAAyB,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC;QACvD,MAAM,MAAM,GAAG,IAAA,4BAAY,EAAC,IAAI,EAAE,IAAI,EAAE,EAAE,KAAK,EAAE,MAAM,EAAE,KAAK,EAAE,CAAC,CAAC;QAClE,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,MAAM,EAAE,CAAC;IACnC,CAAC;IAAC,OAAO,CAAC,EAAE,CAAC;QACX,OAAO,CAAC,GAAG,CAAC,iCAAiC,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC;QAClE,OAAO,EAAE,OAAO,EAAE,KAAK,EAAE,CAAC;IAC5B,CAAC;AACH,CAAC;AAED,SAAgB,aAAa;IAC3B,IAAI,CAAC;QACH,IAAA,4BAAY,EAAC,IAAI,EAAE,CAAC,SAAS,EAAE,UAAU,CAAC,EAAE,EAAE,KAAK,EAAE,MAAM,EAAE,CAAC,CAAC;IACjE,CAAC;IAAC,WAAM,CAAC;QACP,MAAM,IAAI,KAAK,CACb,wIAAwI,CACzI,CAAC;IACJ,CAAC;IAED,IAAI,CAAC;QACH,IAAA,4BAAY,EAAC,IAAI,EAAE,CAAC,QAAQ,CAAC,EAAE,EAAE,KAAK,EAAE,MAAM,EAAE,CAAC,CAAC;QAClD,OAAO;IACT,CAAC;IAAC,WAAM,CAAC;QACP,oDAAoD;IACtD,CAAC;IAED,IAAI,MAAM,GAAkB,IAAI,CAAC;IACjC,IAAI,CAAC;QACH,MAAM;YACJ,IAAA,4BAAY,EAAC,IAAI,EAAE,CAAC,QAAQ,EAAE,MAAM,EAAE,UAAU,EAAE,IAAI,EAAE,wCAAwC,CAAC,EAAE,EAAE,KAAK,EAAE,MAAM,EAAE,CAAC;iBAClH,QAAQ,EAAE;iBACV,IAAI,EAAE,IAAI,IAAI,CAAC;IACtB,CAAC;IAAC,WAAM,CAAC;QACP,kDAAkD;IACpD,CAAC;IAED,OAAO,CAAC,GAAG,CAAC,2DAA2D,CAAC,CAAC;IACzE,MAAM,SAAS,GAAG,MAAM,CAAC,CAAC,CAAC,CAAC,OAAO,EAAE,MAAM,EAAE,OAAO,CAAC,CAAC,CAAC,CAAC,CAAC,OAAO,EAAE,OAAO,CAAC,CAAC;IAC3E,MAAM,MAAM,GAAG,IAAA,yBAAS,EAAC,IAAI,EAAE,SAAS,EAAE,EAAE,KAAK,EAAE,SAAS,EAAE,CAAC,CAAC;IAEhE,IAAI,MAAM,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QACxB,MAAM,IAAI,KAAK,CACb,6FAA6F,CAC9F,CAAC;IACJ,CAAC;AACH,CAAC"}
@@ -1,9 +1,13 @@
1
- import { execFileSync } from 'child_process';
1
+ import { execFileSync, spawnSync } from 'child_process';
2
2
  import { mocked } from 'jest-mock';
3
- import { runOcCommand } from './oc-utils';
3
+ import { ensureOcLogin, runOcCommand } from './oc-utils';
4
4
 
5
5
  jest.mock('child_process');
6
6
  const mockedExecFileSync = mocked(execFileSync);
7
+ const mockedSpawnSync = mocked(spawnSync);
8
+
9
+ const SPAWN_OK = { status: 0, pid: 1, output: [], stdout: Buffer.from(''), stderr: Buffer.from(''), signal: null };
10
+ const SPAWN_FAIL = { ...SPAWN_OK, status: 1 };
7
11
 
8
12
  describe('runOcCommand', () => {
9
13
  beforeEach(() => {
@@ -61,3 +65,64 @@ describe('runOcCommand', () => {
61
65
  expect(result.stdout).toBeUndefined();
62
66
  });
63
67
  });
68
+
69
+ describe('ensureOcLogin', () => {
70
+ beforeEach(() => {
71
+ mockedExecFileSync.mockReset();
72
+ mockedSpawnSync.mockReset();
73
+ });
74
+
75
+ it('returns without spawning login when already logged in', () => {
76
+ mockedExecFileSync.mockReturnValueOnce(Buffer.from('Client Version: 4.14.0')); // oc version --client
77
+ mockedExecFileSync.mockReturnValueOnce(Buffer.from('developer')); // oc whoami
78
+
79
+ ensureOcLogin();
80
+
81
+ expect(mockedSpawnSync).not.toHaveBeenCalled();
82
+ });
83
+
84
+ it('throws a clear error when oc is not installed', () => {
85
+ mockedExecFileSync.mockImplementationOnce(() => {
86
+ throw new Error('oc: command not found');
87
+ });
88
+
89
+ expect(() => ensureOcLogin()).toThrow('oc CLI is not installed');
90
+ });
91
+
92
+ it('spawns oc login with server and --web when kubeconfig has a current context', () => {
93
+ mockedExecFileSync.mockReturnValueOnce(Buffer.from('Client Version: 4.14.0')); // oc version --client
94
+ mockedExecFileSync.mockImplementationOnce(() => { throw new Error('not logged in'); }); // oc whoami
95
+ mockedExecFileSync.mockReturnValueOnce(Buffer.from('https://api.example.openshift.com:6443')); // oc config view
96
+ mockedSpawnSync.mockReturnValue(SPAWN_OK);
97
+
98
+ ensureOcLogin();
99
+
100
+ expect(mockedSpawnSync).toHaveBeenCalledWith(
101
+ 'oc',
102
+ ['login', 'https://api.example.openshift.com:6443', '--web'],
103
+ { stdio: 'inherit' }
104
+ );
105
+ });
106
+
107
+ it('spawns oc login with only --web when no kubeconfig exists', () => {
108
+ mockedExecFileSync.mockReturnValueOnce(Buffer.from('Client Version: 4.14.0')); // oc version --client
109
+ mockedExecFileSync.mockImplementationOnce(() => { throw new Error('not logged in'); }); // oc whoami
110
+ mockedExecFileSync.mockImplementationOnce(() => { throw new Error('no config'); }); // oc config view
111
+
112
+ mockedSpawnSync.mockReturnValue(SPAWN_OK);
113
+
114
+ ensureOcLogin();
115
+
116
+ expect(mockedSpawnSync).toHaveBeenCalledWith('oc', ['login', '--web'], { stdio: 'inherit' });
117
+ });
118
+
119
+ it('throws when login is cancelled or fails', () => {
120
+ mockedExecFileSync.mockReturnValueOnce(Buffer.from('Client Version: 4.14.0')); // oc version --client
121
+ mockedExecFileSync.mockImplementationOnce(() => { throw new Error('not logged in'); }); // oc whoami
122
+ mockedExecFileSync.mockImplementationOnce(() => { throw new Error('no config'); }); // oc config view
123
+
124
+ mockedSpawnSync.mockReturnValue(SPAWN_FAIL);
125
+
126
+ expect(() => ensureOcLogin()).toThrow('OpenShift login failed or was cancelled');
127
+ });
128
+ });