diff --git a/MAINTAINERS b/MAINTAINERS index 0a62017..9be9c41 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -18,6 +18,6 @@ Jeff Ng Email: jeffn@indeed.com GitHub username: @jeffhem -Jade Applegate - Email: japplegate@indeed.com - GitHub username: @jadeapplegate \ No newline at end of file +Renisha Nellums + Email: renisha@indeed.com + GitHub username: @coffeesippa diff --git a/README.md b/README.md index 42f7241..52b056a 100644 --- a/README.md +++ b/README.md @@ -101,12 +101,16 @@ kubectl create serviceaccount skooner-sa # Give that service account root on the cluster kubectl create clusterrolebinding skooner-sa --clusterrole=cluster-admin --serviceaccount=default:skooner-sa +# For Kubernetes v1.21 or lower # Find the secret that was created to hold the token for the SA kubectl get secrets # Show the contents of the secret to extract the token kubectl describe secret skooner-sa-token-xxxxx +# For Kubernetes v1.22 or higher +kubectl create token skooner-sa + ``` Copy the `token` value from the secret, and enter it into the login screen to access the dashboard. diff --git a/client/src/utils/unitHelpers.test.ts b/client/src/utils/unitHelpers.test.ts index b9154be..c484345 100644 --- a/client/src/utils/unitHelpers.test.ts +++ b/client/src/utils/unitHelpers.test.ts @@ -1,27 +1,153 @@ -import {parseUnitsOfRam} from './unitHelpers'; +import { + parseDiskSpace, + parseRam, + parseUnitsOfRam, + unparseRam, + parseCpu, + unparseCpu, +} from './unitHelpers'; -describe('unitHelpers', () => { - test('parseUnitsOfRam basic usage', () => { +describe('parseDiskSpace', () => { + it('returns 0 when given no value', () => { + expect(parseDiskSpace()).toEqual(0); + expect(parseDiskSpace('')).toEqual(0); + }); + + it('correctly handles Mebibyte derivatives', () => { + expect(parseDiskSpace('')).toEqual(0); + expect(parseDiskSpace('1Bi')).toEqual(1); + expect(parseDiskSpace('1Ki')).toEqual(1024); + expect(parseDiskSpace('1Mi')).toEqual(1048576); + expect(parseDiskSpace('1Gi')).toEqual(1073741824); + expect(parseDiskSpace('1Ti')).toEqual(1099511627776); + expect(parseDiskSpace('1Pi')).toEqual(1125899906842624); + expect(parseDiskSpace('1Ei')).toEqual(1152921504606847000); + }); + + it('correctly handles MegaBytes derivatives including milibytes', () => { + expect(parseDiskSpace('')).toEqual(0); + expect(parseDiskSpace('1m')).toEqual(0.001); + expect(parseDiskSpace('1000m')).toEqual(1); + expect(parseDiskSpace('1B')).toEqual(1); + expect(parseDiskSpace('1K')).toEqual(1000); + expect(parseDiskSpace('1M')).toEqual(1000000); + expect(parseDiskSpace('1G')).toEqual(1000000000); + expect(parseDiskSpace('1T')).toEqual(1000000000000); + expect(parseDiskSpace('1P')).toEqual(1000000000000000); + expect(parseDiskSpace('1E')).toEqual(1000000000000000000); + }); + + it('ignores additional chars when parsing units', () => { + expect(parseDiskSpace('1Gb')).toEqual(parseDiskSpace('1G')); + }); +}); + +describe('parseRam', () => { + it('returns 0 when given no value', () => { + expect(parseRam()).toEqual(0); + expect(parseRam('')).toEqual(0); + }); + + it('correctly handles MegaBytes derivatives including milibytes', () => { + expect(parseRam('1Bi')).toEqual(1); + expect(parseRam('1Ki')).toEqual(1024); + expect(parseRam('1Mi')).toEqual(1048576); + expect(parseRam('1Gi')).toEqual(1073741824); + expect(parseRam('1Ti')).toEqual(1099511627776); + expect(parseRam('1Pi')).toEqual(1125899906842624); + expect(parseRam('1Ei')).toEqual(1152921504606847000); + }); + it('correctly handles MegaBytes usage - including milibytes', () => { + expect(parseRam('1m')).toEqual(0.001); + expect(parseRam('1000m')).toEqual(1); + expect(parseRam('1B')).toEqual(1); + expect(parseRam('1K')).toEqual(1000); + expect(parseRam('1M')).toEqual(1000000); + expect(parseRam('1G')).toEqual(1000000000); + expect(parseRam('1T')).toEqual(1000000000000); + expect(parseRam('1P')).toEqual(1000000000000000); + expect(parseRam('1E')).toEqual(1000000000000000000); + }); + + it('fixes specific issue #395 - RAM Request/Limits calculation is incorrect', () => { + const bytes = parseRam('1503238553600m'); + const unitValue = unparseRam(bytes); + expect(unitValue).toEqual({unit: 'Gi', value: 1.4}); + }); + + it('ignores additional chars when parsing units', () => { + expect(parseRam('1Gb')).toEqual(parseRam('1G')); + }); +}); + +describe('parseUnitsOfRam', () => { + it('returns undefined when given no bytes', () => { + expect(parseUnitsOfRam()).toBeUndefined(); + expect(parseUnitsOfRam(undefined)).toBeUndefined(); + expect(parseUnitsOfRam(0)).toBeUndefined(); + }); + + it('should return the correct value and unit for bytes input', () => { + const bytes = 1500; + expect(parseUnitsOfRam(bytes)).toEqual({value: 1.5, unit: 'Kb'}); + }); + + it('parseUnitsOfRam basic usage', () => { expect(parseUnitsOfRam(1_000)).toEqual({value: 1, unit: 'Kb'}); expect(parseUnitsOfRam(1_000_000)).toEqual({value: 1, unit: 'Mb'}); expect(parseUnitsOfRam(1_000_000_000)).toEqual({value: 1, unit: 'Gb'}); expect(parseUnitsOfRam(1_000_000_000_000)).toEqual({value: 1, unit: 'Tb'}); }); - test('parseUnitsOfRam #188 use case', () => { + it('parseUnitsOfRam #188 use case', () => { expect(parseUnitsOfRam(473_300_000_000)).toEqual({value: 473.3, unit: 'Gb'}); expect(parseUnitsOfRam(3_000_000_000_000)).toEqual({value: 3, unit: 'Tb'}); }); - test('parseUnitsOfRam with explicit targetUnit', () => { + it('parseUnitsOfRam with explicit targetUnit', () => { expect(parseUnitsOfRam(473_300_000_000, 'T')).toEqual({value: 0.47, unit: 'Tb'}); expect(parseUnitsOfRam(473_300_000_000, 'Tb')).toEqual({value: 0.47, unit: 'Tb'}); expect(parseUnitsOfRam(3_500_000_000_000)).toEqual({value: 3.5, unit: 'Tb'}); }); - test('parseUnitsOfRam #188 fixed use case', () => { + it('parseUnitsOfRam #188 fixed use case', () => { const available = parseUnitsOfRam(3_500_000_000_000); const used = parseUnitsOfRam(473_300_000_000, available?.unit); expect(used).toEqual({value: 0.47, unit: 'Tb'}); }); }); + +describe('unparseRam', () => { + it('should correctly unparse RAM values', () => { + expect(unparseRam(1)).toEqual({value: 1, unit: 'Bi'}); + expect(unparseRam(1000)).toEqual({value: 1000, unit: 'Bi'}); + expect(unparseRam(1024)).toEqual({value: 1, unit: 'Ki'}); + expect(unparseRam(1024 * 1024)).toEqual({value: 1, unit: 'Mi'}); + expect(unparseRam(1024 * 1024 * 1024)).toEqual({value: 1, unit: 'Gi'}); + expect(unparseRam(1024 * 1024 * 1024 * 1024)).toEqual({value: 1, unit: 'Ti'}); + expect(unparseRam(1024 * 1024 * 1024 * 1024 * 1024)).toEqual({value: 1, unit: 'Pi'}); + expect(unparseRam(1024 * 1024 * 1024 * 1024 * 1024 * 1024)).toEqual({value: 1, unit: 'Ei'}); + expect(unparseRam(1536)).toEqual({value: 1.5, unit: 'Ki'}); + expect(unparseRam(12345678)).toEqual({value: 11.8, unit: 'Mi'}); + }); +}); + +describe('parseCpu', () => { + it('should correctly parse CPU values', () => { + expect(parseCpu('0')).toEqual(0); + expect(parseCpu('1n')).toEqual(1); + expect(parseCpu('1u')).toEqual(1000); + expect(parseCpu('1m')).toEqual(1000000); + expect(parseCpu('1')).toEqual(1000000000); + }); +}); + +describe('unparseCpu', () => { + it('should correctly unparse CPU values', () => { + expect(unparseCpu(0)).toEqual({value: 0, unit: 'm'}); + expect(unparseCpu(1000 * 10)).toEqual({value: 0.01, unit: 'm'}); + expect(unparseCpu(1000000000 / 10)).toEqual({value: 100, unit: 'm'}); + expect(unparseCpu(1000000000)).toEqual({value: 1000, unit: 'm'}); + expect(unparseCpu(1000000000 * 10)).toEqual({value: 10000, unit: 'm'}); + }); +}); diff --git a/client/src/utils/unitHelpers.ts b/client/src/utils/unitHelpers.ts index 420aa9b..ee4bb6a 100644 --- a/client/src/utils/unitHelpers.ts +++ b/client/src/utils/unitHelpers.ts @@ -33,31 +33,24 @@ export function parseUnitsOfRam(bytes?: number, targetUnit?: string) { } function parseUnitsOfBytes(value?: string | {string: string}) { - if (!value) return 0; - const cleanValue = typeof value === 'object' ? value?.string : value; + const stringValue = typeof value === 'object' ? value.string.trim() : value?.trim(); + if (!stringValue) return 0; - const groups = cleanValue.match(/(\d+)([BKMGTPEe])?(i)?(\d+)?/)!; - const number = parseInt(groups[1], 10); + const regexMatch = stringValue.match(/(\d+)([BKMGTPEe])?(i)?(\d+)?(m)?/); + if (!regexMatch) return 0; - // number ex. 1000 - if (groups[2] === undefined) { - return number; - } + const [, numberStr, unit, isI, exponentStr, isMiliBytes] = regexMatch; + const number = parseInt(numberStr, 10); + const exponent = exponentStr ? parseInt(exponentStr, 10) : 0; + const unitIndex = unit ? UNITS.indexOf(unit.toUpperCase()) : 0; + const isMili = isMiliBytes !== undefined; - // number with exponent ex. 1e3 - if (groups[4] !== undefined) { - return number * (10 ** parseInt(groups[4], 10)); - } + const unitFactor = isI ? 1024 : 1000; + let factor = unitFactor ** unitIndex; + if (isMili) factor /= 1000; + if (exponent) factor *= 10 ** exponent; - const unitIndex = _.indexOf(UNITS, groups[2]); - - // Unit + i ex. 1Ki - if (groups[3] !== undefined) { - return number * (1024 ** unitIndex); - } - - // Unit ex. 1K - return number * (1000 ** unitIndex); + return number * factor; } export function unparseRam(value: number) { diff --git a/server/index.js b/server/index.js index ad50eda..050a1ce 100644 --- a/server/index.js +++ b/server/index.js @@ -13,6 +13,7 @@ const OIDC_CLIENT_ID = process.env.OIDC_CLIENT_ID; const OIDC_SECRET = process.env.OIDC_SECRET; const OIDC_URL = process.env.OIDC_URL; const OIDC_SCOPES = process.env.OIDC_SCOPES || 'openid email'; +const OIDC_CODE_CHALLENGE_METHOD = process.env.OIDC_CODE_CHALLENGE_METHOD || 'plain'; const OIDC_METADATA = JSON.parse(process.env.OIDC_METADATA || '{}'); const clientMetadata = Object.assign({client_id: OIDC_CLIENT_ID, client_secret: OIDC_SECRET}, OIDC_METADATA); @@ -130,7 +131,7 @@ async function getOidcEndpoint() { if (!OIDC_URL) return; const provider = await getOidcProvider(); - return provider.authorizationUrl({scope: OIDC_SCOPES}); + return provider.authorizationUrl({scope: OIDC_SCOPES, code_challenge_method: OIDC_CODE_CHALLENGE_METHOD}); } async function oidcAuthenticate(code, redirectUri) {