diff --git a/.github/actions/cmx-versions/dist/index.js b/.github/actions/cmx-versions/dist/index.js index 85624a1de8..ec01d62d19 100644 --- a/.github/actions/cmx-versions/dist/index.js +++ b/.github/actions/cmx-versions/dist/index.js @@ -6112,1303 +6112,1303 @@ exports.parseURL = __nccwpck_require__(2158).parseURL; /***/ ((module, __unused_webpack_exports, __nccwpck_require__) => { "use strict"; - -const punycode = __nccwpck_require__(5477); -const tr46 = __nccwpck_require__(4256); - -const specialSchemes = { - ftp: 21, - file: null, - gopher: 70, - http: 80, - https: 443, - ws: 80, - wss: 443 -}; - -const failure = Symbol("failure"); - -function countSymbols(str) { - return punycode.ucs2.decode(str).length; -} - -function at(input, idx) { - const c = input[idx]; - return isNaN(c) ? undefined : String.fromCodePoint(c); -} - -function isASCIIDigit(c) { - return c >= 0x30 && c <= 0x39; -} - -function isASCIIAlpha(c) { - return (c >= 0x41 && c <= 0x5A) || (c >= 0x61 && c <= 0x7A); -} - -function isASCIIAlphanumeric(c) { - return isASCIIAlpha(c) || isASCIIDigit(c); -} - -function isASCIIHex(c) { - return isASCIIDigit(c) || (c >= 0x41 && c <= 0x46) || (c >= 0x61 && c <= 0x66); -} - -function isSingleDot(buffer) { - return buffer === "." || buffer.toLowerCase() === "%2e"; -} - -function isDoubleDot(buffer) { - buffer = buffer.toLowerCase(); - return buffer === ".." || buffer === "%2e." || buffer === ".%2e" || buffer === "%2e%2e"; -} - -function isWindowsDriveLetterCodePoints(cp1, cp2) { - return isASCIIAlpha(cp1) && (cp2 === 58 || cp2 === 124); -} - -function isWindowsDriveLetterString(string) { - return string.length === 2 && isASCIIAlpha(string.codePointAt(0)) && (string[1] === ":" || string[1] === "|"); -} - -function isNormalizedWindowsDriveLetterString(string) { - return string.length === 2 && isASCIIAlpha(string.codePointAt(0)) && string[1] === ":"; -} - -function containsForbiddenHostCodePoint(string) { - return string.search(/\u0000|\u0009|\u000A|\u000D|\u0020|#|%|\/|:|\?|@|\[|\\|\]/) !== -1; -} - -function containsForbiddenHostCodePointExcludingPercent(string) { - return string.search(/\u0000|\u0009|\u000A|\u000D|\u0020|#|\/|:|\?|@|\[|\\|\]/) !== -1; -} - -function isSpecialScheme(scheme) { - return specialSchemes[scheme] !== undefined; -} - -function isSpecial(url) { - return isSpecialScheme(url.scheme); -} - -function defaultPort(scheme) { - return specialSchemes[scheme]; -} - -function percentEncode(c) { - let hex = c.toString(16).toUpperCase(); - if (hex.length === 1) { - hex = "0" + hex; - } - - return "%" + hex; -} - -function utf8PercentEncode(c) { - const buf = new Buffer(c); - - let str = ""; - - for (let i = 0; i < buf.length; ++i) { - str += percentEncode(buf[i]); - } - - return str; -} - -function utf8PercentDecode(str) { - const input = new Buffer(str); - const output = []; - for (let i = 0; i < input.length; ++i) { - if (input[i] !== 37) { - output.push(input[i]); - } else if (input[i] === 37 && isASCIIHex(input[i + 1]) && isASCIIHex(input[i + 2])) { - output.push(parseInt(input.slice(i + 1, i + 3).toString(), 16)); - i += 2; - } else { - output.push(input[i]); - } - } - return new Buffer(output).toString(); -} - -function isC0ControlPercentEncode(c) { - return c <= 0x1F || c > 0x7E; -} - -const extraPathPercentEncodeSet = new Set([32, 34, 35, 60, 62, 63, 96, 123, 125]); -function isPathPercentEncode(c) { - return isC0ControlPercentEncode(c) || extraPathPercentEncodeSet.has(c); -} - -const extraUserinfoPercentEncodeSet = - new Set([47, 58, 59, 61, 64, 91, 92, 93, 94, 124]); -function isUserinfoPercentEncode(c) { - return isPathPercentEncode(c) || extraUserinfoPercentEncodeSet.has(c); -} - -function percentEncodeChar(c, encodeSetPredicate) { - const cStr = String.fromCodePoint(c); - - if (encodeSetPredicate(c)) { - return utf8PercentEncode(cStr); - } - - return cStr; -} - -function parseIPv4Number(input) { - let R = 10; - - if (input.length >= 2 && input.charAt(0) === "0" && input.charAt(1).toLowerCase() === "x") { - input = input.substring(2); - R = 16; - } else if (input.length >= 2 && input.charAt(0) === "0") { - input = input.substring(1); - R = 8; - } - - if (input === "") { - return 0; - } - - const regex = R === 10 ? /[^0-9]/ : (R === 16 ? /[^0-9A-Fa-f]/ : /[^0-7]/); - if (regex.test(input)) { - return failure; - } - - return parseInt(input, R); -} - -function parseIPv4(input) { - const parts = input.split("."); - if (parts[parts.length - 1] === "") { - if (parts.length > 1) { - parts.pop(); - } - } - - if (parts.length > 4) { - return input; - } - - const numbers = []; - for (const part of parts) { - if (part === "") { - return input; - } - const n = parseIPv4Number(part); - if (n === failure) { - return input; - } - - numbers.push(n); - } - - for (let i = 0; i < numbers.length - 1; ++i) { - if (numbers[i] > 255) { - return failure; - } - } - if (numbers[numbers.length - 1] >= Math.pow(256, 5 - numbers.length)) { - return failure; - } - - let ipv4 = numbers.pop(); - let counter = 0; - - for (const n of numbers) { - ipv4 += n * Math.pow(256, 3 - counter); - ++counter; - } - - return ipv4; -} - -function serializeIPv4(address) { - let output = ""; - let n = address; - - for (let i = 1; i <= 4; ++i) { - output = String(n % 256) + output; - if (i !== 4) { - output = "." + output; - } - n = Math.floor(n / 256); - } - - return output; -} - -function parseIPv6(input) { - const address = [0, 0, 0, 0, 0, 0, 0, 0]; - let pieceIndex = 0; - let compress = null; - let pointer = 0; - - input = punycode.ucs2.decode(input); - - if (input[pointer] === 58) { - if (input[pointer + 1] !== 58) { - return failure; - } - - pointer += 2; - ++pieceIndex; - compress = pieceIndex; - } - - while (pointer < input.length) { - if (pieceIndex === 8) { - return failure; - } - - if (input[pointer] === 58) { - if (compress !== null) { - return failure; - } - ++pointer; - ++pieceIndex; - compress = pieceIndex; - continue; - } - - let value = 0; - let length = 0; - - while (length < 4 && isASCIIHex(input[pointer])) { - value = value * 0x10 + parseInt(at(input, pointer), 16); - ++pointer; - ++length; - } - - if (input[pointer] === 46) { - if (length === 0) { - return failure; - } - - pointer -= length; - - if (pieceIndex > 6) { - return failure; - } - - let numbersSeen = 0; - - while (input[pointer] !== undefined) { - let ipv4Piece = null; - - if (numbersSeen > 0) { - if (input[pointer] === 46 && numbersSeen < 4) { - ++pointer; - } else { - return failure; - } - } - - if (!isASCIIDigit(input[pointer])) { - return failure; - } - - while (isASCIIDigit(input[pointer])) { - const number = parseInt(at(input, pointer)); - if (ipv4Piece === null) { - ipv4Piece = number; - } else if (ipv4Piece === 0) { - return failure; - } else { - ipv4Piece = ipv4Piece * 10 + number; - } - if (ipv4Piece > 255) { - return failure; - } - ++pointer; - } - - address[pieceIndex] = address[pieceIndex] * 0x100 + ipv4Piece; - - ++numbersSeen; - - if (numbersSeen === 2 || numbersSeen === 4) { - ++pieceIndex; - } - } - - if (numbersSeen !== 4) { - return failure; - } - - break; - } else if (input[pointer] === 58) { - ++pointer; - if (input[pointer] === undefined) { - return failure; - } - } else if (input[pointer] !== undefined) { - return failure; - } - - address[pieceIndex] = value; - ++pieceIndex; - } - - if (compress !== null) { - let swaps = pieceIndex - compress; - pieceIndex = 7; - while (pieceIndex !== 0 && swaps > 0) { - const temp = address[compress + swaps - 1]; - address[compress + swaps - 1] = address[pieceIndex]; - address[pieceIndex] = temp; - --pieceIndex; - --swaps; - } - } else if (compress === null && pieceIndex !== 8) { - return failure; - } - - return address; -} - -function serializeIPv6(address) { - let output = ""; - const seqResult = findLongestZeroSequence(address); - const compress = seqResult.idx; - let ignore0 = false; - - for (let pieceIndex = 0; pieceIndex <= 7; ++pieceIndex) { - if (ignore0 && address[pieceIndex] === 0) { - continue; - } else if (ignore0) { - ignore0 = false; - } - - if (compress === pieceIndex) { - const separator = pieceIndex === 0 ? "::" : ":"; - output += separator; - ignore0 = true; - continue; - } - - output += address[pieceIndex].toString(16); - - if (pieceIndex !== 7) { - output += ":"; - } - } - - return output; -} - -function parseHost(input, isSpecialArg) { - if (input[0] === "[") { - if (input[input.length - 1] !== "]") { - return failure; - } - - return parseIPv6(input.substring(1, input.length - 1)); - } - - if (!isSpecialArg) { - return parseOpaqueHost(input); - } - - const domain = utf8PercentDecode(input); - const asciiDomain = tr46.toASCII(domain, false, tr46.PROCESSING_OPTIONS.NONTRANSITIONAL, false); - if (asciiDomain === null) { - return failure; - } - - if (containsForbiddenHostCodePoint(asciiDomain)) { - return failure; - } - - const ipv4Host = parseIPv4(asciiDomain); - if (typeof ipv4Host === "number" || ipv4Host === failure) { - return ipv4Host; - } - - return asciiDomain; -} - -function parseOpaqueHost(input) { - if (containsForbiddenHostCodePointExcludingPercent(input)) { - return failure; - } - - let output = ""; - const decoded = punycode.ucs2.decode(input); - for (let i = 0; i < decoded.length; ++i) { - output += percentEncodeChar(decoded[i], isC0ControlPercentEncode); - } - return output; -} - -function findLongestZeroSequence(arr) { - let maxIdx = null; - let maxLen = 1; // only find elements > 1 - let currStart = null; - let currLen = 0; - - for (let i = 0; i < arr.length; ++i) { - if (arr[i] !== 0) { - if (currLen > maxLen) { - maxIdx = currStart; - maxLen = currLen; - } - - currStart = null; - currLen = 0; - } else { - if (currStart === null) { - currStart = i; - } - ++currLen; - } - } - - // if trailing zeros - if (currLen > maxLen) { - maxIdx = currStart; - maxLen = currLen; - } - - return { - idx: maxIdx, - len: maxLen - }; -} - -function serializeHost(host) { - if (typeof host === "number") { - return serializeIPv4(host); - } - - // IPv6 serializer - if (host instanceof Array) { - return "[" + serializeIPv6(host) + "]"; - } - - return host; -} - -function trimControlChars(url) { - return url.replace(/^[\u0000-\u001F\u0020]+|[\u0000-\u001F\u0020]+$/g, ""); -} - -function trimTabAndNewline(url) { - return url.replace(/\u0009|\u000A|\u000D/g, ""); -} - -function shortenPath(url) { - const path = url.path; - if (path.length === 0) { - return; - } - if (url.scheme === "file" && path.length === 1 && isNormalizedWindowsDriveLetter(path[0])) { - return; - } - - path.pop(); -} - -function includesCredentials(url) { - return url.username !== "" || url.password !== ""; -} - -function cannotHaveAUsernamePasswordPort(url) { - return url.host === null || url.host === "" || url.cannotBeABaseURL || url.scheme === "file"; -} - -function isNormalizedWindowsDriveLetter(string) { - return /^[A-Za-z]:$/.test(string); -} - -function URLStateMachine(input, base, encodingOverride, url, stateOverride) { - this.pointer = 0; - this.input = input; - this.base = base || null; - this.encodingOverride = encodingOverride || "utf-8"; - this.stateOverride = stateOverride; - this.url = url; - this.failure = false; - this.parseError = false; - - if (!this.url) { - this.url = { - scheme: "", - username: "", - password: "", - host: null, - port: null, - path: [], - query: null, - fragment: null, - - cannotBeABaseURL: false - }; - - const res = trimControlChars(this.input); - if (res !== this.input) { - this.parseError = true; - } - this.input = res; - } - - const res = trimTabAndNewline(this.input); - if (res !== this.input) { - this.parseError = true; - } - this.input = res; - - this.state = stateOverride || "scheme start"; - - this.buffer = ""; - this.atFlag = false; - this.arrFlag = false; - this.passwordTokenSeenFlag = false; - - this.input = punycode.ucs2.decode(this.input); - - for (; this.pointer <= this.input.length; ++this.pointer) { - const c = this.input[this.pointer]; - const cStr = isNaN(c) ? undefined : String.fromCodePoint(c); - - // exec state machine - const ret = this["parse " + this.state](c, cStr); - if (!ret) { - break; // terminate algorithm - } else if (ret === failure) { - this.failure = true; - break; - } - } -} - -URLStateMachine.prototype["parse scheme start"] = function parseSchemeStart(c, cStr) { - if (isASCIIAlpha(c)) { - this.buffer += cStr.toLowerCase(); - this.state = "scheme"; - } else if (!this.stateOverride) { - this.state = "no scheme"; - --this.pointer; - } else { - this.parseError = true; - return failure; - } - - return true; -}; - -URLStateMachine.prototype["parse scheme"] = function parseScheme(c, cStr) { - if (isASCIIAlphanumeric(c) || c === 43 || c === 45 || c === 46) { - this.buffer += cStr.toLowerCase(); - } else if (c === 58) { - if (this.stateOverride) { - if (isSpecial(this.url) && !isSpecialScheme(this.buffer)) { - return false; - } - - if (!isSpecial(this.url) && isSpecialScheme(this.buffer)) { - return false; - } - - if ((includesCredentials(this.url) || this.url.port !== null) && this.buffer === "file") { - return false; - } - - if (this.url.scheme === "file" && (this.url.host === "" || this.url.host === null)) { - return false; - } - } - this.url.scheme = this.buffer; - this.buffer = ""; - if (this.stateOverride) { - return false; - } - if (this.url.scheme === "file") { - if (this.input[this.pointer + 1] !== 47 || this.input[this.pointer + 2] !== 47) { - this.parseError = true; - } - this.state = "file"; - } else if (isSpecial(this.url) && this.base !== null && this.base.scheme === this.url.scheme) { - this.state = "special relative or authority"; - } else if (isSpecial(this.url)) { - this.state = "special authority slashes"; - } else if (this.input[this.pointer + 1] === 47) { - this.state = "path or authority"; - ++this.pointer; - } else { - this.url.cannotBeABaseURL = true; - this.url.path.push(""); - this.state = "cannot-be-a-base-URL path"; - } - } else if (!this.stateOverride) { - this.buffer = ""; - this.state = "no scheme"; - this.pointer = -1; - } else { - this.parseError = true; - return failure; - } - - return true; -}; - -URLStateMachine.prototype["parse no scheme"] = function parseNoScheme(c) { - if (this.base === null || (this.base.cannotBeABaseURL && c !== 35)) { - return failure; - } else if (this.base.cannotBeABaseURL && c === 35) { - this.url.scheme = this.base.scheme; - this.url.path = this.base.path.slice(); - this.url.query = this.base.query; - this.url.fragment = ""; - this.url.cannotBeABaseURL = true; - this.state = "fragment"; - } else if (this.base.scheme === "file") { - this.state = "file"; - --this.pointer; - } else { - this.state = "relative"; - --this.pointer; - } - - return true; -}; - -URLStateMachine.prototype["parse special relative or authority"] = function parseSpecialRelativeOrAuthority(c) { - if (c === 47 && this.input[this.pointer + 1] === 47) { - this.state = "special authority ignore slashes"; - ++this.pointer; - } else { - this.parseError = true; - this.state = "relative"; - --this.pointer; - } - - return true; -}; - -URLStateMachine.prototype["parse path or authority"] = function parsePathOrAuthority(c) { - if (c === 47) { - this.state = "authority"; - } else { - this.state = "path"; - --this.pointer; - } - - return true; -}; - -URLStateMachine.prototype["parse relative"] = function parseRelative(c) { - this.url.scheme = this.base.scheme; - if (isNaN(c)) { - this.url.username = this.base.username; - this.url.password = this.base.password; - this.url.host = this.base.host; - this.url.port = this.base.port; - this.url.path = this.base.path.slice(); - this.url.query = this.base.query; - } else if (c === 47) { - this.state = "relative slash"; - } else if (c === 63) { - this.url.username = this.base.username; - this.url.password = this.base.password; - this.url.host = this.base.host; - this.url.port = this.base.port; - this.url.path = this.base.path.slice(); - this.url.query = ""; - this.state = "query"; - } else if (c === 35) { - this.url.username = this.base.username; - this.url.password = this.base.password; - this.url.host = this.base.host; - this.url.port = this.base.port; - this.url.path = this.base.path.slice(); - this.url.query = this.base.query; - this.url.fragment = ""; - this.state = "fragment"; - } else if (isSpecial(this.url) && c === 92) { - this.parseError = true; - this.state = "relative slash"; - } else { - this.url.username = this.base.username; - this.url.password = this.base.password; - this.url.host = this.base.host; - this.url.port = this.base.port; - this.url.path = this.base.path.slice(0, this.base.path.length - 1); - - this.state = "path"; - --this.pointer; - } - - return true; -}; - -URLStateMachine.prototype["parse relative slash"] = function parseRelativeSlash(c) { - if (isSpecial(this.url) && (c === 47 || c === 92)) { - if (c === 92) { - this.parseError = true; - } - this.state = "special authority ignore slashes"; - } else if (c === 47) { - this.state = "authority"; - } else { - this.url.username = this.base.username; - this.url.password = this.base.password; - this.url.host = this.base.host; - this.url.port = this.base.port; - this.state = "path"; - --this.pointer; - } - - return true; -}; - -URLStateMachine.prototype["parse special authority slashes"] = function parseSpecialAuthoritySlashes(c) { - if (c === 47 && this.input[this.pointer + 1] === 47) { - this.state = "special authority ignore slashes"; - ++this.pointer; - } else { - this.parseError = true; - this.state = "special authority ignore slashes"; - --this.pointer; - } - - return true; -}; - -URLStateMachine.prototype["parse special authority ignore slashes"] = function parseSpecialAuthorityIgnoreSlashes(c) { - if (c !== 47 && c !== 92) { - this.state = "authority"; - --this.pointer; - } else { - this.parseError = true; - } - - return true; -}; - -URLStateMachine.prototype["parse authority"] = function parseAuthority(c, cStr) { - if (c === 64) { - this.parseError = true; - if (this.atFlag) { - this.buffer = "%40" + this.buffer; - } - this.atFlag = true; - - // careful, this is based on buffer and has its own pointer (this.pointer != pointer) and inner chars - const len = countSymbols(this.buffer); - for (let pointer = 0; pointer < len; ++pointer) { - const codePoint = this.buffer.codePointAt(pointer); - - if (codePoint === 58 && !this.passwordTokenSeenFlag) { - this.passwordTokenSeenFlag = true; - continue; - } - const encodedCodePoints = percentEncodeChar(codePoint, isUserinfoPercentEncode); - if (this.passwordTokenSeenFlag) { - this.url.password += encodedCodePoints; - } else { - this.url.username += encodedCodePoints; - } - } - this.buffer = ""; - } else if (isNaN(c) || c === 47 || c === 63 || c === 35 || - (isSpecial(this.url) && c === 92)) { - if (this.atFlag && this.buffer === "") { - this.parseError = true; - return failure; - } - this.pointer -= countSymbols(this.buffer) + 1; - this.buffer = ""; - this.state = "host"; - } else { - this.buffer += cStr; - } - - return true; -}; - -URLStateMachine.prototype["parse hostname"] = -URLStateMachine.prototype["parse host"] = function parseHostName(c, cStr) { - if (this.stateOverride && this.url.scheme === "file") { - --this.pointer; - this.state = "file host"; - } else if (c === 58 && !this.arrFlag) { - if (this.buffer === "") { - this.parseError = true; - return failure; - } - - const host = parseHost(this.buffer, isSpecial(this.url)); - if (host === failure) { - return failure; - } - - this.url.host = host; - this.buffer = ""; - this.state = "port"; - if (this.stateOverride === "hostname") { - return false; - } - } else if (isNaN(c) || c === 47 || c === 63 || c === 35 || - (isSpecial(this.url) && c === 92)) { - --this.pointer; - if (isSpecial(this.url) && this.buffer === "") { - this.parseError = true; - return failure; - } else if (this.stateOverride && this.buffer === "" && - (includesCredentials(this.url) || this.url.port !== null)) { - this.parseError = true; - return false; - } - - const host = parseHost(this.buffer, isSpecial(this.url)); - if (host === failure) { - return failure; - } - - this.url.host = host; - this.buffer = ""; - this.state = "path start"; - if (this.stateOverride) { - return false; - } - } else { - if (c === 91) { - this.arrFlag = true; - } else if (c === 93) { - this.arrFlag = false; - } - this.buffer += cStr; - } - - return true; -}; - -URLStateMachine.prototype["parse port"] = function parsePort(c, cStr) { - if (isASCIIDigit(c)) { - this.buffer += cStr; - } else if (isNaN(c) || c === 47 || c === 63 || c === 35 || - (isSpecial(this.url) && c === 92) || - this.stateOverride) { - if (this.buffer !== "") { - const port = parseInt(this.buffer); - if (port > Math.pow(2, 16) - 1) { - this.parseError = true; - return failure; - } - this.url.port = port === defaultPort(this.url.scheme) ? null : port; - this.buffer = ""; - } - if (this.stateOverride) { - return false; - } - this.state = "path start"; - --this.pointer; - } else { - this.parseError = true; - return failure; - } - - return true; -}; - -const fileOtherwiseCodePoints = new Set([47, 92, 63, 35]); - -URLStateMachine.prototype["parse file"] = function parseFile(c) { - this.url.scheme = "file"; - - if (c === 47 || c === 92) { - if (c === 92) { - this.parseError = true; - } - this.state = "file slash"; - } else if (this.base !== null && this.base.scheme === "file") { - if (isNaN(c)) { - this.url.host = this.base.host; - this.url.path = this.base.path.slice(); - this.url.query = this.base.query; - } else if (c === 63) { - this.url.host = this.base.host; - this.url.path = this.base.path.slice(); - this.url.query = ""; - this.state = "query"; - } else if (c === 35) { - this.url.host = this.base.host; - this.url.path = this.base.path.slice(); - this.url.query = this.base.query; - this.url.fragment = ""; - this.state = "fragment"; - } else { - if (this.input.length - this.pointer - 1 === 0 || // remaining consists of 0 code points - !isWindowsDriveLetterCodePoints(c, this.input[this.pointer + 1]) || - (this.input.length - this.pointer - 1 >= 2 && // remaining has at least 2 code points - !fileOtherwiseCodePoints.has(this.input[this.pointer + 2]))) { - this.url.host = this.base.host; - this.url.path = this.base.path.slice(); - shortenPath(this.url); - } else { - this.parseError = true; - } - - this.state = "path"; - --this.pointer; - } - } else { - this.state = "path"; - --this.pointer; - } - - return true; -}; - -URLStateMachine.prototype["parse file slash"] = function parseFileSlash(c) { - if (c === 47 || c === 92) { - if (c === 92) { - this.parseError = true; - } - this.state = "file host"; - } else { - if (this.base !== null && this.base.scheme === "file") { - if (isNormalizedWindowsDriveLetterString(this.base.path[0])) { - this.url.path.push(this.base.path[0]); - } else { - this.url.host = this.base.host; - } - } - this.state = "path"; - --this.pointer; - } - - return true; -}; - -URLStateMachine.prototype["parse file host"] = function parseFileHost(c, cStr) { - if (isNaN(c) || c === 47 || c === 92 || c === 63 || c === 35) { - --this.pointer; - if (!this.stateOverride && isWindowsDriveLetterString(this.buffer)) { - this.parseError = true; - this.state = "path"; - } else if (this.buffer === "") { - this.url.host = ""; - if (this.stateOverride) { - return false; - } - this.state = "path start"; - } else { - let host = parseHost(this.buffer, isSpecial(this.url)); - if (host === failure) { - return failure; - } - if (host === "localhost") { - host = ""; - } - this.url.host = host; - - if (this.stateOverride) { - return false; - } - - this.buffer = ""; - this.state = "path start"; - } - } else { - this.buffer += cStr; - } - - return true; -}; - -URLStateMachine.prototype["parse path start"] = function parsePathStart(c) { - if (isSpecial(this.url)) { - if (c === 92) { - this.parseError = true; - } - this.state = "path"; - - if (c !== 47 && c !== 92) { - --this.pointer; - } - } else if (!this.stateOverride && c === 63) { - this.url.query = ""; - this.state = "query"; - } else if (!this.stateOverride && c === 35) { - this.url.fragment = ""; - this.state = "fragment"; - } else if (c !== undefined) { - this.state = "path"; - if (c !== 47) { - --this.pointer; - } - } - - return true; -}; - -URLStateMachine.prototype["parse path"] = function parsePath(c) { - if (isNaN(c) || c === 47 || (isSpecial(this.url) && c === 92) || - (!this.stateOverride && (c === 63 || c === 35))) { - if (isSpecial(this.url) && c === 92) { - this.parseError = true; - } - - if (isDoubleDot(this.buffer)) { - shortenPath(this.url); - if (c !== 47 && !(isSpecial(this.url) && c === 92)) { - this.url.path.push(""); - } - } else if (isSingleDot(this.buffer) && c !== 47 && - !(isSpecial(this.url) && c === 92)) { - this.url.path.push(""); - } else if (!isSingleDot(this.buffer)) { - if (this.url.scheme === "file" && this.url.path.length === 0 && isWindowsDriveLetterString(this.buffer)) { - if (this.url.host !== "" && this.url.host !== null) { - this.parseError = true; - this.url.host = ""; - } - this.buffer = this.buffer[0] + ":"; - } - this.url.path.push(this.buffer); - } - this.buffer = ""; - if (this.url.scheme === "file" && (c === undefined || c === 63 || c === 35)) { - while (this.url.path.length > 1 && this.url.path[0] === "") { - this.parseError = true; - this.url.path.shift(); - } - } - if (c === 63) { - this.url.query = ""; - this.state = "query"; - } - if (c === 35) { - this.url.fragment = ""; - this.state = "fragment"; - } - } else { - // TODO: If c is not a URL code point and not "%", parse error. - - if (c === 37 && - (!isASCIIHex(this.input[this.pointer + 1]) || - !isASCIIHex(this.input[this.pointer + 2]))) { - this.parseError = true; - } - - this.buffer += percentEncodeChar(c, isPathPercentEncode); - } - - return true; -}; - -URLStateMachine.prototype["parse cannot-be-a-base-URL path"] = function parseCannotBeABaseURLPath(c) { - if (c === 63) { - this.url.query = ""; - this.state = "query"; - } else if (c === 35) { - this.url.fragment = ""; - this.state = "fragment"; - } else { - // TODO: Add: not a URL code point - if (!isNaN(c) && c !== 37) { - this.parseError = true; - } - - if (c === 37 && - (!isASCIIHex(this.input[this.pointer + 1]) || - !isASCIIHex(this.input[this.pointer + 2]))) { - this.parseError = true; - } - - if (!isNaN(c)) { - this.url.path[0] = this.url.path[0] + percentEncodeChar(c, isC0ControlPercentEncode); - } - } - - return true; -}; - -URLStateMachine.prototype["parse query"] = function parseQuery(c, cStr) { - if (isNaN(c) || (!this.stateOverride && c === 35)) { - if (!isSpecial(this.url) || this.url.scheme === "ws" || this.url.scheme === "wss") { - this.encodingOverride = "utf-8"; - } - - const buffer = new Buffer(this.buffer); // TODO: Use encoding override instead - for (let i = 0; i < buffer.length; ++i) { - if (buffer[i] < 0x21 || buffer[i] > 0x7E || buffer[i] === 0x22 || buffer[i] === 0x23 || - buffer[i] === 0x3C || buffer[i] === 0x3E) { - this.url.query += percentEncode(buffer[i]); - } else { - this.url.query += String.fromCodePoint(buffer[i]); - } - } - - this.buffer = ""; - if (c === 35) { - this.url.fragment = ""; - this.state = "fragment"; - } - } else { - // TODO: If c is not a URL code point and not "%", parse error. - if (c === 37 && - (!isASCIIHex(this.input[this.pointer + 1]) || - !isASCIIHex(this.input[this.pointer + 2]))) { - this.parseError = true; - } - - this.buffer += cStr; - } - - return true; -}; - -URLStateMachine.prototype["parse fragment"] = function parseFragment(c) { - if (isNaN(c)) { // do nothing - } else if (c === 0x0) { - this.parseError = true; - } else { - // TODO: If c is not a URL code point and not "%", parse error. - if (c === 37 && - (!isASCIIHex(this.input[this.pointer + 1]) || - !isASCIIHex(this.input[this.pointer + 2]))) { - this.parseError = true; - } - - this.url.fragment += percentEncodeChar(c, isC0ControlPercentEncode); - } - - return true; -}; - -function serializeURL(url, excludeFragment) { - let output = url.scheme + ":"; - if (url.host !== null) { - output += "//"; - - if (url.username !== "" || url.password !== "") { - output += url.username; - if (url.password !== "") { - output += ":" + url.password; - } - output += "@"; - } - - output += serializeHost(url.host); - - if (url.port !== null) { - output += ":" + url.port; - } - } else if (url.host === null && url.scheme === "file") { - output += "//"; - } - - if (url.cannotBeABaseURL) { - output += url.path[0]; - } else { - for (const string of url.path) { - output += "/" + string; - } - } - - if (url.query !== null) { - output += "?" + url.query; - } - - if (!excludeFragment && url.fragment !== null) { - output += "#" + url.fragment; - } - - return output; -} - -function serializeOrigin(tuple) { - let result = tuple.scheme + "://"; - result += serializeHost(tuple.host); - - if (tuple.port !== null) { - result += ":" + tuple.port; - } - - return result; -} - -module.exports.serializeURL = serializeURL; - -module.exports.serializeURLOrigin = function (url) { - // https://url.spec.whatwg.org/#concept-url-origin - switch (url.scheme) { - case "blob": - try { - return module.exports.serializeURLOrigin(module.exports.parseURL(url.path[0])); - } catch (e) { - // serializing an opaque origin returns "null" - return "null"; - } - case "ftp": - case "gopher": - case "http": - case "https": - case "ws": - case "wss": - return serializeOrigin({ - scheme: url.scheme, - host: url.host, - port: url.port - }); - case "file": - // spec says "exercise to the reader", chrome says "file://" - return "file://"; - default: - // serializing an opaque origin returns "null" - return "null"; - } -}; - -module.exports.basicURLParse = function (input, options) { - if (options === undefined) { - options = {}; - } - - const usm = new URLStateMachine(input, options.baseURL, options.encodingOverride, options.url, options.stateOverride); - if (usm.failure) { - return "failure"; - } - - return usm.url; -}; - -module.exports.setTheUsername = function (url, username) { - url.username = ""; - const decoded = punycode.ucs2.decode(username); - for (let i = 0; i < decoded.length; ++i) { - url.username += percentEncodeChar(decoded[i], isUserinfoPercentEncode); - } -}; - -module.exports.setThePassword = function (url, password) { - url.password = ""; - const decoded = punycode.ucs2.decode(password); - for (let i = 0; i < decoded.length; ++i) { - url.password += percentEncodeChar(decoded[i], isUserinfoPercentEncode); - } -}; - -module.exports.serializeHost = serializeHost; - -module.exports.cannotHaveAUsernamePasswordPort = cannotHaveAUsernamePasswordPort; - -module.exports.serializeInteger = function (integer) { - return String(integer); -}; - -module.exports.parseURL = function (input, options) { - if (options === undefined) { - options = {}; - } - - // We don't handle blobs, so this just delegates: - return module.exports.basicURLParse(input, { baseURL: options.baseURL, encodingOverride: options.encodingOverride }); -}; + +const punycode = __nccwpck_require__(5477); +const tr46 = __nccwpck_require__(4256); + +const specialSchemes = { + ftp: 21, + file: null, + gopher: 70, + http: 80, + https: 443, + ws: 80, + wss: 443 +}; + +const failure = Symbol("failure"); + +function countSymbols(str) { + return punycode.ucs2.decode(str).length; +} + +function at(input, idx) { + const c = input[idx]; + return isNaN(c) ? undefined : String.fromCodePoint(c); +} + +function isASCIIDigit(c) { + return c >= 0x30 && c <= 0x39; +} + +function isASCIIAlpha(c) { + return (c >= 0x41 && c <= 0x5A) || (c >= 0x61 && c <= 0x7A); +} + +function isASCIIAlphanumeric(c) { + return isASCIIAlpha(c) || isASCIIDigit(c); +} + +function isASCIIHex(c) { + return isASCIIDigit(c) || (c >= 0x41 && c <= 0x46) || (c >= 0x61 && c <= 0x66); +} + +function isSingleDot(buffer) { + return buffer === "." || buffer.toLowerCase() === "%2e"; +} + +function isDoubleDot(buffer) { + buffer = buffer.toLowerCase(); + return buffer === ".." || buffer === "%2e." || buffer === ".%2e" || buffer === "%2e%2e"; +} + +function isWindowsDriveLetterCodePoints(cp1, cp2) { + return isASCIIAlpha(cp1) && (cp2 === 58 || cp2 === 124); +} + +function isWindowsDriveLetterString(string) { + return string.length === 2 && isASCIIAlpha(string.codePointAt(0)) && (string[1] === ":" || string[1] === "|"); +} + +function isNormalizedWindowsDriveLetterString(string) { + return string.length === 2 && isASCIIAlpha(string.codePointAt(0)) && string[1] === ":"; +} + +function containsForbiddenHostCodePoint(string) { + return string.search(/\u0000|\u0009|\u000A|\u000D|\u0020|#|%|\/|:|\?|@|\[|\\|\]/) !== -1; +} + +function containsForbiddenHostCodePointExcludingPercent(string) { + return string.search(/\u0000|\u0009|\u000A|\u000D|\u0020|#|\/|:|\?|@|\[|\\|\]/) !== -1; +} + +function isSpecialScheme(scheme) { + return specialSchemes[scheme] !== undefined; +} + +function isSpecial(url) { + return isSpecialScheme(url.scheme); +} + +function defaultPort(scheme) { + return specialSchemes[scheme]; +} + +function percentEncode(c) { + let hex = c.toString(16).toUpperCase(); + if (hex.length === 1) { + hex = "0" + hex; + } + + return "%" + hex; +} + +function utf8PercentEncode(c) { + const buf = new Buffer(c); + + let str = ""; + + for (let i = 0; i < buf.length; ++i) { + str += percentEncode(buf[i]); + } + + return str; +} + +function utf8PercentDecode(str) { + const input = new Buffer(str); + const output = []; + for (let i = 0; i < input.length; ++i) { + if (input[i] !== 37) { + output.push(input[i]); + } else if (input[i] === 37 && isASCIIHex(input[i + 1]) && isASCIIHex(input[i + 2])) { + output.push(parseInt(input.slice(i + 1, i + 3).toString(), 16)); + i += 2; + } else { + output.push(input[i]); + } + } + return new Buffer(output).toString(); +} + +function isC0ControlPercentEncode(c) { + return c <= 0x1F || c > 0x7E; +} + +const extraPathPercentEncodeSet = new Set([32, 34, 35, 60, 62, 63, 96, 123, 125]); +function isPathPercentEncode(c) { + return isC0ControlPercentEncode(c) || extraPathPercentEncodeSet.has(c); +} + +const extraUserinfoPercentEncodeSet = + new Set([47, 58, 59, 61, 64, 91, 92, 93, 94, 124]); +function isUserinfoPercentEncode(c) { + return isPathPercentEncode(c) || extraUserinfoPercentEncodeSet.has(c); +} + +function percentEncodeChar(c, encodeSetPredicate) { + const cStr = String.fromCodePoint(c); + + if (encodeSetPredicate(c)) { + return utf8PercentEncode(cStr); + } + + return cStr; +} + +function parseIPv4Number(input) { + let R = 10; + + if (input.length >= 2 && input.charAt(0) === "0" && input.charAt(1).toLowerCase() === "x") { + input = input.substring(2); + R = 16; + } else if (input.length >= 2 && input.charAt(0) === "0") { + input = input.substring(1); + R = 8; + } + + if (input === "") { + return 0; + } + + const regex = R === 10 ? /[^0-9]/ : (R === 16 ? /[^0-9A-Fa-f]/ : /[^0-7]/); + if (regex.test(input)) { + return failure; + } + + return parseInt(input, R); +} + +function parseIPv4(input) { + const parts = input.split("."); + if (parts[parts.length - 1] === "") { + if (parts.length > 1) { + parts.pop(); + } + } + + if (parts.length > 4) { + return input; + } + + const numbers = []; + for (const part of parts) { + if (part === "") { + return input; + } + const n = parseIPv4Number(part); + if (n === failure) { + return input; + } + + numbers.push(n); + } + + for (let i = 0; i < numbers.length - 1; ++i) { + if (numbers[i] > 255) { + return failure; + } + } + if (numbers[numbers.length - 1] >= Math.pow(256, 5 - numbers.length)) { + return failure; + } + + let ipv4 = numbers.pop(); + let counter = 0; + + for (const n of numbers) { + ipv4 += n * Math.pow(256, 3 - counter); + ++counter; + } + + return ipv4; +} + +function serializeIPv4(address) { + let output = ""; + let n = address; + + for (let i = 1; i <= 4; ++i) { + output = String(n % 256) + output; + if (i !== 4) { + output = "." + output; + } + n = Math.floor(n / 256); + } + + return output; +} + +function parseIPv6(input) { + const address = [0, 0, 0, 0, 0, 0, 0, 0]; + let pieceIndex = 0; + let compress = null; + let pointer = 0; + + input = punycode.ucs2.decode(input); + + if (input[pointer] === 58) { + if (input[pointer + 1] !== 58) { + return failure; + } + + pointer += 2; + ++pieceIndex; + compress = pieceIndex; + } + + while (pointer < input.length) { + if (pieceIndex === 8) { + return failure; + } + + if (input[pointer] === 58) { + if (compress !== null) { + return failure; + } + ++pointer; + ++pieceIndex; + compress = pieceIndex; + continue; + } + + let value = 0; + let length = 0; + + while (length < 4 && isASCIIHex(input[pointer])) { + value = value * 0x10 + parseInt(at(input, pointer), 16); + ++pointer; + ++length; + } + + if (input[pointer] === 46) { + if (length === 0) { + return failure; + } + + pointer -= length; + + if (pieceIndex > 6) { + return failure; + } + + let numbersSeen = 0; + + while (input[pointer] !== undefined) { + let ipv4Piece = null; + + if (numbersSeen > 0) { + if (input[pointer] === 46 && numbersSeen < 4) { + ++pointer; + } else { + return failure; + } + } + + if (!isASCIIDigit(input[pointer])) { + return failure; + } + + while (isASCIIDigit(input[pointer])) { + const number = parseInt(at(input, pointer)); + if (ipv4Piece === null) { + ipv4Piece = number; + } else if (ipv4Piece === 0) { + return failure; + } else { + ipv4Piece = ipv4Piece * 10 + number; + } + if (ipv4Piece > 255) { + return failure; + } + ++pointer; + } + + address[pieceIndex] = address[pieceIndex] * 0x100 + ipv4Piece; + + ++numbersSeen; + + if (numbersSeen === 2 || numbersSeen === 4) { + ++pieceIndex; + } + } + + if (numbersSeen !== 4) { + return failure; + } + + break; + } else if (input[pointer] === 58) { + ++pointer; + if (input[pointer] === undefined) { + return failure; + } + } else if (input[pointer] !== undefined) { + return failure; + } + + address[pieceIndex] = value; + ++pieceIndex; + } + + if (compress !== null) { + let swaps = pieceIndex - compress; + pieceIndex = 7; + while (pieceIndex !== 0 && swaps > 0) { + const temp = address[compress + swaps - 1]; + address[compress + swaps - 1] = address[pieceIndex]; + address[pieceIndex] = temp; + --pieceIndex; + --swaps; + } + } else if (compress === null && pieceIndex !== 8) { + return failure; + } + + return address; +} + +function serializeIPv6(address) { + let output = ""; + const seqResult = findLongestZeroSequence(address); + const compress = seqResult.idx; + let ignore0 = false; + + for (let pieceIndex = 0; pieceIndex <= 7; ++pieceIndex) { + if (ignore0 && address[pieceIndex] === 0) { + continue; + } else if (ignore0) { + ignore0 = false; + } + + if (compress === pieceIndex) { + const separator = pieceIndex === 0 ? "::" : ":"; + output += separator; + ignore0 = true; + continue; + } + + output += address[pieceIndex].toString(16); + + if (pieceIndex !== 7) { + output += ":"; + } + } + + return output; +} + +function parseHost(input, isSpecialArg) { + if (input[0] === "[") { + if (input[input.length - 1] !== "]") { + return failure; + } + + return parseIPv6(input.substring(1, input.length - 1)); + } + + if (!isSpecialArg) { + return parseOpaqueHost(input); + } + + const domain = utf8PercentDecode(input); + const asciiDomain = tr46.toASCII(domain, false, tr46.PROCESSING_OPTIONS.NONTRANSITIONAL, false); + if (asciiDomain === null) { + return failure; + } + + if (containsForbiddenHostCodePoint(asciiDomain)) { + return failure; + } + + const ipv4Host = parseIPv4(asciiDomain); + if (typeof ipv4Host === "number" || ipv4Host === failure) { + return ipv4Host; + } + + return asciiDomain; +} + +function parseOpaqueHost(input) { + if (containsForbiddenHostCodePointExcludingPercent(input)) { + return failure; + } + + let output = ""; + const decoded = punycode.ucs2.decode(input); + for (let i = 0; i < decoded.length; ++i) { + output += percentEncodeChar(decoded[i], isC0ControlPercentEncode); + } + return output; +} + +function findLongestZeroSequence(arr) { + let maxIdx = null; + let maxLen = 1; // only find elements > 1 + let currStart = null; + let currLen = 0; + + for (let i = 0; i < arr.length; ++i) { + if (arr[i] !== 0) { + if (currLen > maxLen) { + maxIdx = currStart; + maxLen = currLen; + } + + currStart = null; + currLen = 0; + } else { + if (currStart === null) { + currStart = i; + } + ++currLen; + } + } + + // if trailing zeros + if (currLen > maxLen) { + maxIdx = currStart; + maxLen = currLen; + } + + return { + idx: maxIdx, + len: maxLen + }; +} + +function serializeHost(host) { + if (typeof host === "number") { + return serializeIPv4(host); + } + + // IPv6 serializer + if (host instanceof Array) { + return "[" + serializeIPv6(host) + "]"; + } + + return host; +} + +function trimControlChars(url) { + return url.replace(/^[\u0000-\u001F\u0020]+|[\u0000-\u001F\u0020]+$/g, ""); +} + +function trimTabAndNewline(url) { + return url.replace(/\u0009|\u000A|\u000D/g, ""); +} + +function shortenPath(url) { + const path = url.path; + if (path.length === 0) { + return; + } + if (url.scheme === "file" && path.length === 1 && isNormalizedWindowsDriveLetter(path[0])) { + return; + } + + path.pop(); +} + +function includesCredentials(url) { + return url.username !== "" || url.password !== ""; +} + +function cannotHaveAUsernamePasswordPort(url) { + return url.host === null || url.host === "" || url.cannotBeABaseURL || url.scheme === "file"; +} + +function isNormalizedWindowsDriveLetter(string) { + return /^[A-Za-z]:$/.test(string); +} + +function URLStateMachine(input, base, encodingOverride, url, stateOverride) { + this.pointer = 0; + this.input = input; + this.base = base || null; + this.encodingOverride = encodingOverride || "utf-8"; + this.stateOverride = stateOverride; + this.url = url; + this.failure = false; + this.parseError = false; + + if (!this.url) { + this.url = { + scheme: "", + username: "", + password: "", + host: null, + port: null, + path: [], + query: null, + fragment: null, + + cannotBeABaseURL: false + }; + + const res = trimControlChars(this.input); + if (res !== this.input) { + this.parseError = true; + } + this.input = res; + } + + const res = trimTabAndNewline(this.input); + if (res !== this.input) { + this.parseError = true; + } + this.input = res; + + this.state = stateOverride || "scheme start"; + + this.buffer = ""; + this.atFlag = false; + this.arrFlag = false; + this.passwordTokenSeenFlag = false; + + this.input = punycode.ucs2.decode(this.input); + + for (; this.pointer <= this.input.length; ++this.pointer) { + const c = this.input[this.pointer]; + const cStr = isNaN(c) ? undefined : String.fromCodePoint(c); + + // exec state machine + const ret = this["parse " + this.state](c, cStr); + if (!ret) { + break; // terminate algorithm + } else if (ret === failure) { + this.failure = true; + break; + } + } +} + +URLStateMachine.prototype["parse scheme start"] = function parseSchemeStart(c, cStr) { + if (isASCIIAlpha(c)) { + this.buffer += cStr.toLowerCase(); + this.state = "scheme"; + } else if (!this.stateOverride) { + this.state = "no scheme"; + --this.pointer; + } else { + this.parseError = true; + return failure; + } + + return true; +}; + +URLStateMachine.prototype["parse scheme"] = function parseScheme(c, cStr) { + if (isASCIIAlphanumeric(c) || c === 43 || c === 45 || c === 46) { + this.buffer += cStr.toLowerCase(); + } else if (c === 58) { + if (this.stateOverride) { + if (isSpecial(this.url) && !isSpecialScheme(this.buffer)) { + return false; + } + + if (!isSpecial(this.url) && isSpecialScheme(this.buffer)) { + return false; + } + + if ((includesCredentials(this.url) || this.url.port !== null) && this.buffer === "file") { + return false; + } + + if (this.url.scheme === "file" && (this.url.host === "" || this.url.host === null)) { + return false; + } + } + this.url.scheme = this.buffer; + this.buffer = ""; + if (this.stateOverride) { + return false; + } + if (this.url.scheme === "file") { + if (this.input[this.pointer + 1] !== 47 || this.input[this.pointer + 2] !== 47) { + this.parseError = true; + } + this.state = "file"; + } else if (isSpecial(this.url) && this.base !== null && this.base.scheme === this.url.scheme) { + this.state = "special relative or authority"; + } else if (isSpecial(this.url)) { + this.state = "special authority slashes"; + } else if (this.input[this.pointer + 1] === 47) { + this.state = "path or authority"; + ++this.pointer; + } else { + this.url.cannotBeABaseURL = true; + this.url.path.push(""); + this.state = "cannot-be-a-base-URL path"; + } + } else if (!this.stateOverride) { + this.buffer = ""; + this.state = "no scheme"; + this.pointer = -1; + } else { + this.parseError = true; + return failure; + } + + return true; +}; + +URLStateMachine.prototype["parse no scheme"] = function parseNoScheme(c) { + if (this.base === null || (this.base.cannotBeABaseURL && c !== 35)) { + return failure; + } else if (this.base.cannotBeABaseURL && c === 35) { + this.url.scheme = this.base.scheme; + this.url.path = this.base.path.slice(); + this.url.query = this.base.query; + this.url.fragment = ""; + this.url.cannotBeABaseURL = true; + this.state = "fragment"; + } else if (this.base.scheme === "file") { + this.state = "file"; + --this.pointer; + } else { + this.state = "relative"; + --this.pointer; + } + + return true; +}; + +URLStateMachine.prototype["parse special relative or authority"] = function parseSpecialRelativeOrAuthority(c) { + if (c === 47 && this.input[this.pointer + 1] === 47) { + this.state = "special authority ignore slashes"; + ++this.pointer; + } else { + this.parseError = true; + this.state = "relative"; + --this.pointer; + } + + return true; +}; + +URLStateMachine.prototype["parse path or authority"] = function parsePathOrAuthority(c) { + if (c === 47) { + this.state = "authority"; + } else { + this.state = "path"; + --this.pointer; + } + + return true; +}; + +URLStateMachine.prototype["parse relative"] = function parseRelative(c) { + this.url.scheme = this.base.scheme; + if (isNaN(c)) { + this.url.username = this.base.username; + this.url.password = this.base.password; + this.url.host = this.base.host; + this.url.port = this.base.port; + this.url.path = this.base.path.slice(); + this.url.query = this.base.query; + } else if (c === 47) { + this.state = "relative slash"; + } else if (c === 63) { + this.url.username = this.base.username; + this.url.password = this.base.password; + this.url.host = this.base.host; + this.url.port = this.base.port; + this.url.path = this.base.path.slice(); + this.url.query = ""; + this.state = "query"; + } else if (c === 35) { + this.url.username = this.base.username; + this.url.password = this.base.password; + this.url.host = this.base.host; + this.url.port = this.base.port; + this.url.path = this.base.path.slice(); + this.url.query = this.base.query; + this.url.fragment = ""; + this.state = "fragment"; + } else if (isSpecial(this.url) && c === 92) { + this.parseError = true; + this.state = "relative slash"; + } else { + this.url.username = this.base.username; + this.url.password = this.base.password; + this.url.host = this.base.host; + this.url.port = this.base.port; + this.url.path = this.base.path.slice(0, this.base.path.length - 1); + + this.state = "path"; + --this.pointer; + } + + return true; +}; + +URLStateMachine.prototype["parse relative slash"] = function parseRelativeSlash(c) { + if (isSpecial(this.url) && (c === 47 || c === 92)) { + if (c === 92) { + this.parseError = true; + } + this.state = "special authority ignore slashes"; + } else if (c === 47) { + this.state = "authority"; + } else { + this.url.username = this.base.username; + this.url.password = this.base.password; + this.url.host = this.base.host; + this.url.port = this.base.port; + this.state = "path"; + --this.pointer; + } + + return true; +}; + +URLStateMachine.prototype["parse special authority slashes"] = function parseSpecialAuthoritySlashes(c) { + if (c === 47 && this.input[this.pointer + 1] === 47) { + this.state = "special authority ignore slashes"; + ++this.pointer; + } else { + this.parseError = true; + this.state = "special authority ignore slashes"; + --this.pointer; + } + + return true; +}; + +URLStateMachine.prototype["parse special authority ignore slashes"] = function parseSpecialAuthorityIgnoreSlashes(c) { + if (c !== 47 && c !== 92) { + this.state = "authority"; + --this.pointer; + } else { + this.parseError = true; + } + + return true; +}; + +URLStateMachine.prototype["parse authority"] = function parseAuthority(c, cStr) { + if (c === 64) { + this.parseError = true; + if (this.atFlag) { + this.buffer = "%40" + this.buffer; + } + this.atFlag = true; + + // careful, this is based on buffer and has its own pointer (this.pointer != pointer) and inner chars + const len = countSymbols(this.buffer); + for (let pointer = 0; pointer < len; ++pointer) { + const codePoint = this.buffer.codePointAt(pointer); + + if (codePoint === 58 && !this.passwordTokenSeenFlag) { + this.passwordTokenSeenFlag = true; + continue; + } + const encodedCodePoints = percentEncodeChar(codePoint, isUserinfoPercentEncode); + if (this.passwordTokenSeenFlag) { + this.url.password += encodedCodePoints; + } else { + this.url.username += encodedCodePoints; + } + } + this.buffer = ""; + } else if (isNaN(c) || c === 47 || c === 63 || c === 35 || + (isSpecial(this.url) && c === 92)) { + if (this.atFlag && this.buffer === "") { + this.parseError = true; + return failure; + } + this.pointer -= countSymbols(this.buffer) + 1; + this.buffer = ""; + this.state = "host"; + } else { + this.buffer += cStr; + } + + return true; +}; + +URLStateMachine.prototype["parse hostname"] = +URLStateMachine.prototype["parse host"] = function parseHostName(c, cStr) { + if (this.stateOverride && this.url.scheme === "file") { + --this.pointer; + this.state = "file host"; + } else if (c === 58 && !this.arrFlag) { + if (this.buffer === "") { + this.parseError = true; + return failure; + } + + const host = parseHost(this.buffer, isSpecial(this.url)); + if (host === failure) { + return failure; + } + + this.url.host = host; + this.buffer = ""; + this.state = "port"; + if (this.stateOverride === "hostname") { + return false; + } + } else if (isNaN(c) || c === 47 || c === 63 || c === 35 || + (isSpecial(this.url) && c === 92)) { + --this.pointer; + if (isSpecial(this.url) && this.buffer === "") { + this.parseError = true; + return failure; + } else if (this.stateOverride && this.buffer === "" && + (includesCredentials(this.url) || this.url.port !== null)) { + this.parseError = true; + return false; + } + + const host = parseHost(this.buffer, isSpecial(this.url)); + if (host === failure) { + return failure; + } + + this.url.host = host; + this.buffer = ""; + this.state = "path start"; + if (this.stateOverride) { + return false; + } + } else { + if (c === 91) { + this.arrFlag = true; + } else if (c === 93) { + this.arrFlag = false; + } + this.buffer += cStr; + } + + return true; +}; + +URLStateMachine.prototype["parse port"] = function parsePort(c, cStr) { + if (isASCIIDigit(c)) { + this.buffer += cStr; + } else if (isNaN(c) || c === 47 || c === 63 || c === 35 || + (isSpecial(this.url) && c === 92) || + this.stateOverride) { + if (this.buffer !== "") { + const port = parseInt(this.buffer); + if (port > Math.pow(2, 16) - 1) { + this.parseError = true; + return failure; + } + this.url.port = port === defaultPort(this.url.scheme) ? null : port; + this.buffer = ""; + } + if (this.stateOverride) { + return false; + } + this.state = "path start"; + --this.pointer; + } else { + this.parseError = true; + return failure; + } + + return true; +}; + +const fileOtherwiseCodePoints = new Set([47, 92, 63, 35]); + +URLStateMachine.prototype["parse file"] = function parseFile(c) { + this.url.scheme = "file"; + + if (c === 47 || c === 92) { + if (c === 92) { + this.parseError = true; + } + this.state = "file slash"; + } else if (this.base !== null && this.base.scheme === "file") { + if (isNaN(c)) { + this.url.host = this.base.host; + this.url.path = this.base.path.slice(); + this.url.query = this.base.query; + } else if (c === 63) { + this.url.host = this.base.host; + this.url.path = this.base.path.slice(); + this.url.query = ""; + this.state = "query"; + } else if (c === 35) { + this.url.host = this.base.host; + this.url.path = this.base.path.slice(); + this.url.query = this.base.query; + this.url.fragment = ""; + this.state = "fragment"; + } else { + if (this.input.length - this.pointer - 1 === 0 || // remaining consists of 0 code points + !isWindowsDriveLetterCodePoints(c, this.input[this.pointer + 1]) || + (this.input.length - this.pointer - 1 >= 2 && // remaining has at least 2 code points + !fileOtherwiseCodePoints.has(this.input[this.pointer + 2]))) { + this.url.host = this.base.host; + this.url.path = this.base.path.slice(); + shortenPath(this.url); + } else { + this.parseError = true; + } + + this.state = "path"; + --this.pointer; + } + } else { + this.state = "path"; + --this.pointer; + } + + return true; +}; + +URLStateMachine.prototype["parse file slash"] = function parseFileSlash(c) { + if (c === 47 || c === 92) { + if (c === 92) { + this.parseError = true; + } + this.state = "file host"; + } else { + if (this.base !== null && this.base.scheme === "file") { + if (isNormalizedWindowsDriveLetterString(this.base.path[0])) { + this.url.path.push(this.base.path[0]); + } else { + this.url.host = this.base.host; + } + } + this.state = "path"; + --this.pointer; + } + + return true; +}; + +URLStateMachine.prototype["parse file host"] = function parseFileHost(c, cStr) { + if (isNaN(c) || c === 47 || c === 92 || c === 63 || c === 35) { + --this.pointer; + if (!this.stateOverride && isWindowsDriveLetterString(this.buffer)) { + this.parseError = true; + this.state = "path"; + } else if (this.buffer === "") { + this.url.host = ""; + if (this.stateOverride) { + return false; + } + this.state = "path start"; + } else { + let host = parseHost(this.buffer, isSpecial(this.url)); + if (host === failure) { + return failure; + } + if (host === "localhost") { + host = ""; + } + this.url.host = host; + + if (this.stateOverride) { + return false; + } + + this.buffer = ""; + this.state = "path start"; + } + } else { + this.buffer += cStr; + } + + return true; +}; + +URLStateMachine.prototype["parse path start"] = function parsePathStart(c) { + if (isSpecial(this.url)) { + if (c === 92) { + this.parseError = true; + } + this.state = "path"; + + if (c !== 47 && c !== 92) { + --this.pointer; + } + } else if (!this.stateOverride && c === 63) { + this.url.query = ""; + this.state = "query"; + } else if (!this.stateOverride && c === 35) { + this.url.fragment = ""; + this.state = "fragment"; + } else if (c !== undefined) { + this.state = "path"; + if (c !== 47) { + --this.pointer; + } + } + + return true; +}; + +URLStateMachine.prototype["parse path"] = function parsePath(c) { + if (isNaN(c) || c === 47 || (isSpecial(this.url) && c === 92) || + (!this.stateOverride && (c === 63 || c === 35))) { + if (isSpecial(this.url) && c === 92) { + this.parseError = true; + } + + if (isDoubleDot(this.buffer)) { + shortenPath(this.url); + if (c !== 47 && !(isSpecial(this.url) && c === 92)) { + this.url.path.push(""); + } + } else if (isSingleDot(this.buffer) && c !== 47 && + !(isSpecial(this.url) && c === 92)) { + this.url.path.push(""); + } else if (!isSingleDot(this.buffer)) { + if (this.url.scheme === "file" && this.url.path.length === 0 && isWindowsDriveLetterString(this.buffer)) { + if (this.url.host !== "" && this.url.host !== null) { + this.parseError = true; + this.url.host = ""; + } + this.buffer = this.buffer[0] + ":"; + } + this.url.path.push(this.buffer); + } + this.buffer = ""; + if (this.url.scheme === "file" && (c === undefined || c === 63 || c === 35)) { + while (this.url.path.length > 1 && this.url.path[0] === "") { + this.parseError = true; + this.url.path.shift(); + } + } + if (c === 63) { + this.url.query = ""; + this.state = "query"; + } + if (c === 35) { + this.url.fragment = ""; + this.state = "fragment"; + } + } else { + // TODO: If c is not a URL code point and not "%", parse error. + + if (c === 37 && + (!isASCIIHex(this.input[this.pointer + 1]) || + !isASCIIHex(this.input[this.pointer + 2]))) { + this.parseError = true; + } + + this.buffer += percentEncodeChar(c, isPathPercentEncode); + } + + return true; +}; + +URLStateMachine.prototype["parse cannot-be-a-base-URL path"] = function parseCannotBeABaseURLPath(c) { + if (c === 63) { + this.url.query = ""; + this.state = "query"; + } else if (c === 35) { + this.url.fragment = ""; + this.state = "fragment"; + } else { + // TODO: Add: not a URL code point + if (!isNaN(c) && c !== 37) { + this.parseError = true; + } + + if (c === 37 && + (!isASCIIHex(this.input[this.pointer + 1]) || + !isASCIIHex(this.input[this.pointer + 2]))) { + this.parseError = true; + } + + if (!isNaN(c)) { + this.url.path[0] = this.url.path[0] + percentEncodeChar(c, isC0ControlPercentEncode); + } + } + + return true; +}; + +URLStateMachine.prototype["parse query"] = function parseQuery(c, cStr) { + if (isNaN(c) || (!this.stateOverride && c === 35)) { + if (!isSpecial(this.url) || this.url.scheme === "ws" || this.url.scheme === "wss") { + this.encodingOverride = "utf-8"; + } + + const buffer = new Buffer(this.buffer); // TODO: Use encoding override instead + for (let i = 0; i < buffer.length; ++i) { + if (buffer[i] < 0x21 || buffer[i] > 0x7E || buffer[i] === 0x22 || buffer[i] === 0x23 || + buffer[i] === 0x3C || buffer[i] === 0x3E) { + this.url.query += percentEncode(buffer[i]); + } else { + this.url.query += String.fromCodePoint(buffer[i]); + } + } + + this.buffer = ""; + if (c === 35) { + this.url.fragment = ""; + this.state = "fragment"; + } + } else { + // TODO: If c is not a URL code point and not "%", parse error. + if (c === 37 && + (!isASCIIHex(this.input[this.pointer + 1]) || + !isASCIIHex(this.input[this.pointer + 2]))) { + this.parseError = true; + } + + this.buffer += cStr; + } + + return true; +}; + +URLStateMachine.prototype["parse fragment"] = function parseFragment(c) { + if (isNaN(c)) { // do nothing + } else if (c === 0x0) { + this.parseError = true; + } else { + // TODO: If c is not a URL code point and not "%", parse error. + if (c === 37 && + (!isASCIIHex(this.input[this.pointer + 1]) || + !isASCIIHex(this.input[this.pointer + 2]))) { + this.parseError = true; + } + + this.url.fragment += percentEncodeChar(c, isC0ControlPercentEncode); + } + + return true; +}; + +function serializeURL(url, excludeFragment) { + let output = url.scheme + ":"; + if (url.host !== null) { + output += "//"; + + if (url.username !== "" || url.password !== "") { + output += url.username; + if (url.password !== "") { + output += ":" + url.password; + } + output += "@"; + } + + output += serializeHost(url.host); + + if (url.port !== null) { + output += ":" + url.port; + } + } else if (url.host === null && url.scheme === "file") { + output += "//"; + } + + if (url.cannotBeABaseURL) { + output += url.path[0]; + } else { + for (const string of url.path) { + output += "/" + string; + } + } + + if (url.query !== null) { + output += "?" + url.query; + } + + if (!excludeFragment && url.fragment !== null) { + output += "#" + url.fragment; + } + + return output; +} + +function serializeOrigin(tuple) { + let result = tuple.scheme + "://"; + result += serializeHost(tuple.host); + + if (tuple.port !== null) { + result += ":" + tuple.port; + } + + return result; +} + +module.exports.serializeURL = serializeURL; + +module.exports.serializeURLOrigin = function (url) { + // https://url.spec.whatwg.org/#concept-url-origin + switch (url.scheme) { + case "blob": + try { + return module.exports.serializeURLOrigin(module.exports.parseURL(url.path[0])); + } catch (e) { + // serializing an opaque origin returns "null" + return "null"; + } + case "ftp": + case "gopher": + case "http": + case "https": + case "ws": + case "wss": + return serializeOrigin({ + scheme: url.scheme, + host: url.host, + port: url.port + }); + case "file": + // spec says "exercise to the reader", chrome says "file://" + return "file://"; + default: + // serializing an opaque origin returns "null" + return "null"; + } +}; + +module.exports.basicURLParse = function (input, options) { + if (options === undefined) { + options = {}; + } + + const usm = new URLStateMachine(input, options.baseURL, options.encodingOverride, options.url, options.stateOverride); + if (usm.failure) { + return "failure"; + } + + return usm.url; +}; + +module.exports.setTheUsername = function (url, username) { + url.username = ""; + const decoded = punycode.ucs2.decode(username); + for (let i = 0; i < decoded.length; ++i) { + url.username += percentEncodeChar(decoded[i], isUserinfoPercentEncode); + } +}; + +module.exports.setThePassword = function (url, password) { + url.password = ""; + const decoded = punycode.ucs2.decode(password); + for (let i = 0; i < decoded.length; ++i) { + url.password += percentEncodeChar(decoded[i], isUserinfoPercentEncode); + } +}; + +module.exports.serializeHost = serializeHost; + +module.exports.cannotHaveAUsernamePasswordPort = cannotHaveAUsernamePasswordPort; + +module.exports.serializeInteger = function (integer) { + return String(integer); +}; + +module.exports.parseURL = function (input, options) { + if (options === undefined) { + options = {}; + } + + // We don't handle blobs, so this just delegates: + return module.exports.basicURLParse(input, { baseURL: options.baseURL, encodingOverride: options.encodingOverride }); +}; /***/ }), @@ -7661,7 +7661,7 @@ async function getClusterVersions() { clusterVersions.forEach((distribution) => { const distroName = distribution.short_name; - if (distroName === 'helmvm' || distroName === 'kurl') { + if (distroName === 'embedded_cluster' || distroName === 'kurl') { // excluding the embedded distributions return; } @@ -7710,4 +7710,4 @@ getClusterVersions(); module.exports = __webpack_exports__; /******/ })() -; \ No newline at end of file +; diff --git a/.github/actions/cmx-versions/index.js b/.github/actions/cmx-versions/index.js index 213ffe0939..ffc802451d 100644 --- a/.github/actions/cmx-versions/index.js +++ b/.github/actions/cmx-versions/index.js @@ -41,7 +41,7 @@ async function getClusterVersions() { clusterVersions.forEach((distribution) => { const distroName = distribution.short_name; - if (distroName === 'helmvm' || distroName === 'kurl') { + if (distroName === 'embedded_cluster' || distroName === 'kurl') { // excluding the embedded distributions return; } diff --git a/.github/workflows/regression.yaml b/.github/workflows/regression.yaml index 2a99593730..bd40a77491 100644 --- a/.github/workflows/regression.yaml +++ b/.github/workflows/regression.yaml @@ -191,9 +191,9 @@ jobs: is_upgrade: "1" }, { - name: "type=helmvm cluster, env=online, phase=new install, rbac=cluster admin", - backend_config: "helmvm-online-install-backend-config.tfvars", - terraform_script: "helmvm-online-install.sh" + name: "type=embeddedcluster cluster, env=online, phase=new install, rbac=cluster admin", + backend_config: "embeddedcluster-online-install-backend-config.tfvars", + terraform_script: "embeddedcluster-online-install.sh" } ] steps: diff --git a/migrations/tables/k0s_tokens.yaml b/migrations/tables/embeded_cluster_tokens.yaml similarity index 84% rename from migrations/tables/k0s_tokens.yaml rename to migrations/tables/embeded_cluster_tokens.yaml index 1ae6760972..6c233ba4d9 100644 --- a/migrations/tables/k0s_tokens.yaml +++ b/migrations/tables/embeded_cluster_tokens.yaml @@ -1,9 +1,9 @@ apiVersion: schemas.schemahero.io/v1alpha4 kind: Table metadata: - name: k0s-tokens + name: embedded-cluster-tokens spec: - name: k0s_tokens + name: embedded_cluster_tokens requires: [] schema: rqlite: diff --git a/pkg/helmvm/delete_node.go b/pkg/embeddedcluster/delete_node.go similarity index 90% rename from pkg/helmvm/delete_node.go rename to pkg/embeddedcluster/delete_node.go index 24d7e5e46d..a50a99eb75 100644 --- a/pkg/helmvm/delete_node.go +++ b/pkg/embeddedcluster/delete_node.go @@ -1,4 +1,4 @@ -package helmvm +package embeddedcluster import ( "context" diff --git a/pkg/helmvm/drain_node.go b/pkg/embeddedcluster/drain_node.go similarity index 88% rename from pkg/helmvm/drain_node.go rename to pkg/embeddedcluster/drain_node.go index b8fa55afbb..0d1439b979 100644 --- a/pkg/helmvm/drain_node.go +++ b/pkg/embeddedcluster/drain_node.go @@ -1,4 +1,4 @@ -package helmvm +package embeddedcluster import ( "context" diff --git a/pkg/helmvm/exec.go b/pkg/embeddedcluster/exec.go similarity index 94% rename from pkg/helmvm/exec.go rename to pkg/embeddedcluster/exec.go index 04f94635de..be71e0a014 100644 --- a/pkg/helmvm/exec.go +++ b/pkg/embeddedcluster/exec.go @@ -1,4 +1,4 @@ -package helmvm +package embeddedcluster import ( corev1client "k8s.io/client-go/kubernetes/typed/core/v1" diff --git a/pkg/helmvm/helmvm_node.go b/pkg/embeddedcluster/helmvm_node.go similarity index 98% rename from pkg/helmvm/helmvm_node.go rename to pkg/embeddedcluster/helmvm_node.go index a9b17f497e..2b7fff9dd7 100644 --- a/pkg/helmvm/helmvm_node.go +++ b/pkg/embeddedcluster/helmvm_node.go @@ -1,4 +1,4 @@ -package helmvm +package embeddedcluster import ( "context" @@ -7,7 +7,7 @@ import ( "strconv" "strings" - "github.com/replicatedhq/kots/pkg/helmvm/types" + "github.com/replicatedhq/kots/pkg/embeddedcluster/types" "github.com/replicatedhq/kots/pkg/k8sutil" corev1 "k8s.io/api/core/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" diff --git a/pkg/helmvm/helmvm_nodes.go b/pkg/embeddedcluster/helmvm_nodes.go similarity index 88% rename from pkg/helmvm/helmvm_nodes.go rename to pkg/embeddedcluster/helmvm_nodes.go index 9396e6508c..7b0eb7729e 100644 --- a/pkg/helmvm/helmvm_nodes.go +++ b/pkg/embeddedcluster/helmvm_nodes.go @@ -1,9 +1,10 @@ -package helmvm +package embeddedcluster import ( "context" + "github.com/pkg/errors" - "github.com/replicatedhq/kots/pkg/helmvm/types" + "github.com/replicatedhq/kots/pkg/embeddedcluster/types" "github.com/replicatedhq/kots/pkg/k8sutil" corev1 "k8s.io/api/core/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" @@ -12,7 +13,7 @@ import ( ) // GetNodes will get a list of nodes with stats -func GetNodes(ctx context.Context, client kubernetes.Interface) (*types.HelmVMNodes, error) { +func GetNodes(ctx context.Context, client kubernetes.Interface) (*types.EmbeddedClusterNodes, error) { nodes, err := client.CoreV1().Nodes().List(ctx, metav1.ListOptions{}) if err != nil { return nil, errors.Wrap(err, "list nodes") @@ -28,7 +29,7 @@ func GetNodes(ctx context.Context, client kubernetes.Interface) (*types.HelmVMNo return nil, errors.Wrap(err, "failed to create metrics client") } - toReturn := types.HelmVMNodes{} + toReturn := types.EmbeddedClusterNodes{} for _, node := range nodes.Items { nodeMet, err := nodeMetrics(ctx, client, metricsClient, node) @@ -39,11 +40,11 @@ func GetNodes(ctx context.Context, client kubernetes.Interface) (*types.HelmVMNo toReturn.Nodes = append(toReturn.Nodes, *nodeMet) } - isHelmVM, err := IsHelmVM(client) + isEmbeddedCluster, err := IsEmbeddedCluster(client) if err != nil { - return nil, errors.Wrap(err, "is helmvm") + return nil, errors.Wrap(err, "is embeddedcluster") } - toReturn.IsHelmVMEnabled = isHelmVM + toReturn.IsEmbeddedClusterEnabled = isEmbeddedCluster isHA, err := IsHA(client) if err != nil { diff --git a/pkg/helmvm/node_join.go b/pkg/embeddedcluster/node_join.go similarity index 97% rename from pkg/helmvm/node_join.go rename to pkg/embeddedcluster/node_join.go index 4a4bb6c068..b0835b3761 100644 --- a/pkg/helmvm/node_join.go +++ b/pkg/embeddedcluster/node_join.go @@ -1,4 +1,4 @@ -package helmvm +package embeddedcluster import ( "context" @@ -8,7 +8,7 @@ import ( "sync" "time" - "github.com/replicatedhq/kots/pkg/helmvm/types" + "github.com/replicatedhq/kots/pkg/embeddedcluster/types" corev1 "k8s.io/api/core/v1" kuberneteserrors "k8s.io/apimachinery/pkg/api/errors" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" @@ -24,7 +24,7 @@ type joinTokenEntry struct { var joinTokenMapMut = sync.Mutex{} var joinTokenMap = map[string]*joinTokenEntry{} -// GenerateAddNodeToken will generate the HelmVM node add command for a primary or secondary node +// GenerateAddNodeToken will generate the embedded cluster node add command for a node with the specified roles // join commands will last for 24 hours, and will be cached for 1 hour after first generation func GenerateAddNodeToken(ctx context.Context, client kubernetes.Interface, nodeRole string) (string, error) { // get the joinToken struct entry for this node role @@ -214,7 +214,7 @@ func runAddNodeCommandPod(ctx context.Context, client kubernetes.Interface, node } // GenerateAddNodeCommand returns the command a user should run to add a node with the provided token -// the command will be of the form 'helmvm node join ip:port UUID' +// the command will be of the form 'embeddedcluster node join ip:port UUID' func GenerateAddNodeCommand(ctx context.Context, client kubernetes.Interface, token string) (string, error) { cm, err := ReadConfigMap(client) if err != nil { diff --git a/pkg/helmvm/types/types.go b/pkg/embeddedcluster/types/types.go similarity index 88% rename from pkg/helmvm/types/types.go rename to pkg/embeddedcluster/types/types.go index 10bf390368..f9b93a4b8c 100644 --- a/pkg/helmvm/types/types.go +++ b/pkg/embeddedcluster/types/types.go @@ -3,10 +3,10 @@ package types const EMBEDDED_CLUSTER_LABEL = "kots.io/embedded-cluster" const EMBEDDED_CLUSTER_ROLE_LABEL = EMBEDDED_CLUSTER_LABEL + "-role" -type HelmVMNodes struct { - Nodes []Node `json:"nodes"` - HA bool `json:"ha"` - IsHelmVMEnabled bool `json:"isHelmVMEnabled"` +type EmbeddedClusterNodes struct { + Nodes []Node `json:"nodes"` + HA bool `json:"ha"` + IsEmbeddedClusterEnabled bool `json:"isEmbeddedClusterEnabled"` } type Node struct { diff --git a/pkg/helmvm/util.go b/pkg/embeddedcluster/util.go similarity index 93% rename from pkg/helmvm/util.go rename to pkg/embeddedcluster/util.go index 87b6bfe285..87f120b7d8 100644 --- a/pkg/helmvm/util.go +++ b/pkg/embeddedcluster/util.go @@ -1,4 +1,4 @@ -package helmvm +package embeddedcluster import ( "context" @@ -18,7 +18,7 @@ func ReadConfigMap(client kubernetes.Interface) (*corev1.ConfigMap, error) { return client.CoreV1().ConfigMaps(configMapNamespace).Get(context.TODO(), configMapName, metav1.GetOptions{}) } -func IsHelmVM(clientset kubernetes.Interface) (bool, error) { +func IsEmbeddedCluster(clientset kubernetes.Interface) (bool, error) { if clientset == nil { return false, fmt.Errorf("clientset is nil") } diff --git a/pkg/handlers/helmvm_delete_node.go b/pkg/handlers/embedded_cluster_delete_node.go similarity index 82% rename from pkg/handlers/helmvm_delete_node.go rename to pkg/handlers/embedded_cluster_delete_node.go index 1b732ab07f..7c2ec94b29 100644 --- a/pkg/handlers/helmvm_delete_node.go +++ b/pkg/handlers/embedded_cluster_delete_node.go @@ -2,17 +2,17 @@ package handlers import ( "context" + "github.com/replicatedhq/kots/pkg/embeddedcluster" "net/http" "github.com/gorilla/mux" - "github.com/replicatedhq/kots/pkg/helmvm" "github.com/replicatedhq/kots/pkg/k8sutil" "github.com/replicatedhq/kots/pkg/logger" "k8s.io/apimachinery/pkg/api/errors" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" ) -func (h *Handler) DeleteHelmVMNode(w http.ResponseWriter, r *http.Request) { +func (h *Handler) DeleteEmbeddedClusterNode(w http.ResponseWriter, r *http.Request) { client, err := k8sutil.GetClientset() if err != nil { logger.Error(err) @@ -41,7 +41,7 @@ func (h *Handler) DeleteHelmVMNode(w http.ResponseWriter, r *http.Request) { return } - if err := helmvm.DeleteNode(ctx, client, restconfig, node); err != nil { + if err := embeddedcluster.DeleteNode(ctx, client, restconfig, node); err != nil { logger.Error(err) w.WriteHeader(http.StatusInternalServerError) return diff --git a/pkg/handlers/helmvm_drain_node.go b/pkg/handlers/embedded_cluster_drain_node.go similarity index 82% rename from pkg/handlers/helmvm_drain_node.go rename to pkg/handlers/embedded_cluster_drain_node.go index ae0a337f6f..6651885579 100644 --- a/pkg/handlers/helmvm_drain_node.go +++ b/pkg/handlers/embedded_cluster_drain_node.go @@ -2,17 +2,17 @@ package handlers import ( "context" + "github.com/replicatedhq/kots/pkg/embeddedcluster" "net/http" "github.com/gorilla/mux" - "github.com/replicatedhq/kots/pkg/helmvm" "github.com/replicatedhq/kots/pkg/k8sutil" "github.com/replicatedhq/kots/pkg/logger" "k8s.io/apimachinery/pkg/api/errors" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" ) -func (h *Handler) DrainHelmVMNode(w http.ResponseWriter, r *http.Request) { +func (h *Handler) DrainEmbeddedClusterNode(w http.ResponseWriter, r *http.Request) { client, err := k8sutil.GetClientset() if err != nil { logger.Error(err) @@ -36,7 +36,7 @@ func (h *Handler) DrainHelmVMNode(w http.ResponseWriter, r *http.Request) { // This pod may get evicted and not be able to respond to the request go func() { - if err := helmvm.DrainNode(ctx, client, node); err != nil { + if err := embeddedcluster.DrainNode(ctx, client, node); err != nil { logger.Error(err) return } diff --git a/pkg/handlers/helmvm_get.go b/pkg/handlers/embedded_cluster_get.go similarity index 67% rename from pkg/handlers/helmvm_get.go rename to pkg/handlers/embedded_cluster_get.go index 4f736996ed..b08d02072a 100644 --- a/pkg/handlers/helmvm_get.go +++ b/pkg/handlers/embedded_cluster_get.go @@ -4,12 +4,12 @@ import ( "net/http" "github.com/gorilla/mux" - "github.com/replicatedhq/kots/pkg/helmvm" + "github.com/replicatedhq/kots/pkg/embeddedcluster" "github.com/replicatedhq/kots/pkg/k8sutil" "github.com/replicatedhq/kots/pkg/logger" ) -func (h *Handler) GetHelmVMNodes(w http.ResponseWriter, r *http.Request) { +func (h *Handler) GetEmbeddedClusterNodes(w http.ResponseWriter, r *http.Request) { client, err := k8sutil.GetClientset() if err != nil { logger.Error(err) @@ -17,7 +17,7 @@ func (h *Handler) GetHelmVMNodes(w http.ResponseWriter, r *http.Request) { return } - nodes, err := helmvm.GetNodes(r.Context(), client) + nodes, err := embeddedcluster.GetNodes(r.Context(), client) if err != nil { logger.Error(err) w.WriteHeader(http.StatusInternalServerError) @@ -26,7 +26,7 @@ func (h *Handler) GetHelmVMNodes(w http.ResponseWriter, r *http.Request) { JSON(w, http.StatusOK, nodes) } -func (h *Handler) GetHelmVMNode(w http.ResponseWriter, r *http.Request) { +func (h *Handler) GetEmbeddedClusterNode(w http.ResponseWriter, r *http.Request) { client, err := k8sutil.GetClientset() if err != nil { logger.Error(err) @@ -35,7 +35,7 @@ func (h *Handler) GetHelmVMNode(w http.ResponseWriter, r *http.Request) { } nodeName := mux.Vars(r)["nodeName"] - node, err := helmvm.GetNode(r.Context(), client, nodeName) + node, err := embeddedcluster.GetNode(r.Context(), client, nodeName) if err != nil { logger.Error(err) w.WriteHeader(http.StatusInternalServerError) diff --git a/pkg/handlers/helmvm_node_join_command.go b/pkg/handlers/embedded_cluster_node_join_command.go similarity index 68% rename from pkg/handlers/helmvm_node_join_command.go rename to pkg/handlers/embedded_cluster_node_join_command.go index b4d6a0da4f..e732fbe458 100644 --- a/pkg/handlers/helmvm_node_join_command.go +++ b/pkg/handlers/embedded_cluster_node_join_command.go @@ -3,30 +3,30 @@ package handlers import ( "encoding/json" "fmt" + "github.com/replicatedhq/kots/pkg/embeddedcluster" "net/http" - "github.com/replicatedhq/kots/pkg/helmvm" "github.com/replicatedhq/kots/pkg/k8sutil" "github.com/replicatedhq/kots/pkg/logger" "github.com/replicatedhq/kots/pkg/store/kotsstore" ) -type GenerateK0sNodeJoinCommandResponse struct { +type GenerateEmbeddedClusterNodeJoinCommandResponse struct { Command []string `json:"command"` } -type GetK0sNodeJoinCommandResponse struct { +type GetEmbeddedClusterNodeJoinCommandResponse struct { ClusterID string `json:"clusterID"` K0sJoinCommand string `json:"k0sJoinCommand"` K0sToken string `json:"k0sToken"` } -type GenerateHelmVMNodeJoinCommandRequest struct { +type GenerateEmbeddedClusterNodeJoinCommandRequest struct { Roles []string `json:"roles"` } -func (h *Handler) GenerateK0sNodeJoinCommand(w http.ResponseWriter, r *http.Request) { - generateHelmVMNodeJoinCommandRequest := GenerateHelmVMNodeJoinCommandRequest{} +func (h *Handler) GenerateEmbeddedClusterNodeJoinCommand(w http.ResponseWriter, r *http.Request) { + generateHelmVMNodeJoinCommandRequest := GenerateEmbeddedClusterNodeJoinCommandRequest{} if err := json.NewDecoder(r.Body).Decode(&generateHelmVMNodeJoinCommandRequest); err != nil { logger.Error(fmt.Errorf("failed to decode request body: %w", err)) w.WriteHeader(http.StatusBadRequest) @@ -34,7 +34,7 @@ func (h *Handler) GenerateK0sNodeJoinCommand(w http.ResponseWriter, r *http.Requ } store := kotsstore.StoreFromEnv() - token, err := store.SetK0sInstallCommandRoles(generateHelmVMNodeJoinCommandRequest.Roles) + token, err := store.SetEmbeddedClusterInstallCommandRoles(generateHelmVMNodeJoinCommandRequest.Roles) if err != nil { logger.Error(fmt.Errorf("failed to set k0s install command roles: %w", err)) w.WriteHeader(http.StatusInternalServerError) @@ -47,24 +47,24 @@ func (h *Handler) GenerateK0sNodeJoinCommand(w http.ResponseWriter, r *http.Requ w.WriteHeader(http.StatusInternalServerError) return } - nodeJoinCommand, err := helmvm.GenerateAddNodeCommand(r.Context(), client, token) + nodeJoinCommand, err := embeddedcluster.GenerateAddNodeCommand(r.Context(), client, token) if err != nil { logger.Error(fmt.Errorf("failed to generate add node command: %w", err)) w.WriteHeader(http.StatusInternalServerError) return } - JSON(w, http.StatusOK, GenerateK0sNodeJoinCommandResponse{ + JSON(w, http.StatusOK, GenerateEmbeddedClusterNodeJoinCommandResponse{ Command: []string{nodeJoinCommand}, }) } // this function relies on the token being valid for authentication -func (h *Handler) GetK0sNodeJoinCommand(w http.ResponseWriter, r *http.Request) { +func (h *Handler) GetEmbeddedClusterNodeJoinCommand(w http.ResponseWriter, r *http.Request) { // read query string, ensure that the token is valid token := r.URL.Query().Get("token") store := kotsstore.StoreFromEnv() - roles, err := store.GetK0sInstallCommandRoles(token) + roles, err := store.GetEmbeddedClusterInstallCommandRoles(token) if err != nil { logger.Error(fmt.Errorf("failed to get k0s install command roles: %w", err)) w.WriteHeader(http.StatusInternalServerError) @@ -87,28 +87,28 @@ func (h *Handler) GetK0sNodeJoinCommand(w http.ResponseWriter, r *http.Request) } } - k0sToken, err := helmvm.GenerateAddNodeToken(r.Context(), client, k0sRole) + k0sToken, err := embeddedcluster.GenerateAddNodeToken(r.Context(), client, k0sRole) if err != nil { logger.Error(fmt.Errorf("failed to generate add node token: %w", err)) w.WriteHeader(http.StatusInternalServerError) return } - k0sJoinCommand, err := helmvm.GenerateK0sJoinCommand(r.Context(), client, roles) + k0sJoinCommand, err := embeddedcluster.GenerateK0sJoinCommand(r.Context(), client, roles) if err != nil { logger.Error(fmt.Errorf("failed to generate k0s join command: %w", err)) w.WriteHeader(http.StatusInternalServerError) return } - clusterID, err := helmvm.ClusterID(client) + clusterID, err := embeddedcluster.ClusterID(client) if err != nil { logger.Error(fmt.Errorf("failed to get cluster id: %w", err)) w.WriteHeader(http.StatusInternalServerError) return } - JSON(w, http.StatusOK, GetK0sNodeJoinCommandResponse{ + JSON(w, http.StatusOK, GetEmbeddedClusterNodeJoinCommandResponse{ ClusterID: clusterID, K0sJoinCommand: k0sJoinCommand, K0sToken: k0sToken, diff --git a/pkg/handlers/handlers.go b/pkg/handlers/handlers.go index 2ebf1fea32..077525ca96 100644 --- a/pkg/handlers/handlers.go +++ b/pkg/handlers/handlers.go @@ -275,18 +275,18 @@ func RegisterSessionAuthRoutes(r *mux.Router, kotsStore store.Store, handler KOT r.Name("GetKurlNodes").Path("/api/v1/kurl/nodes").Methods("GET"). HandlerFunc(middleware.EnforceAccess(policy.ClusterRead, handler.GetKurlNodes)) - // HelmVM - r.Name("HelmVM").Path("/api/v1/helmvm").HandlerFunc(NotImplemented) - r.Name("GenerateK0sNodeJoinCommand").Path("/api/v1/helmvm/generate-node-join-command").Methods("POST"). - HandlerFunc(middleware.EnforceAccess(policy.ClusterWrite, handler.GenerateK0sNodeJoinCommand)) - r.Name("DrainHelmVMNode").Path("/api/v1/helmvm/nodes/{nodeName}/drain").Methods("POST"). - HandlerFunc(middleware.EnforceAccess(policy.ClusterWrite, handler.DrainHelmVMNode)) - r.Name("DeleteHelmVMNode").Path("/api/v1/helmvm/nodes/{nodeName}").Methods("DELETE"). - HandlerFunc(middleware.EnforceAccess(policy.ClusterWrite, handler.DeleteHelmVMNode)) - r.Name("GetHelmVMNodes").Path("/api/v1/helmvm/nodes").Methods("GET"). - HandlerFunc(middleware.EnforceAccess(policy.ClusterRead, handler.GetHelmVMNodes)) - r.Name("GetHelmVMNode").Path("/api/v1/helmvm/node/{nodeName}").Methods("GET"). - HandlerFunc(middleware.EnforceAccess(policy.ClusterRead, handler.GetHelmVMNode)) + // Embedded Cluster + r.Name("EmbeddedCluster").Path("/api/v1/embedded-cluster").HandlerFunc(NotImplemented) + r.Name("GenerateK0sNodeJoinCommand").Path("/api/v1/embedded-cluster/generate-node-join-command").Methods("POST"). + HandlerFunc(middleware.EnforceAccess(policy.ClusterWrite, handler.GenerateEmbeddedClusterNodeJoinCommand)) + r.Name("DrainEmbeddedClusterNode").Path("/api/v1/embedded-cluster/nodes/{nodeName}/drain").Methods("POST"). + HandlerFunc(middleware.EnforceAccess(policy.ClusterWrite, handler.DrainEmbeddedClusterNode)) + r.Name("DeleteEmbeddedClusterNode").Path("/api/v1/embedded-cluster/nodes/{nodeName}").Methods("DELETE"). + HandlerFunc(middleware.EnforceAccess(policy.ClusterWrite, handler.DeleteEmbeddedClusterNode)) + r.Name("GetEmbeddedClusterNodes").Path("/api/v1/embedded-cluster/nodes").Methods("GET"). + HandlerFunc(middleware.EnforceAccess(policy.ClusterRead, handler.GetEmbeddedClusterNodes)) + r.Name("GetEmbeddedClusterNode").Path("/api/v1/embedded-cluster/node/{nodeName}").Methods("GET"). + HandlerFunc(middleware.EnforceAccess(policy.ClusterRead, handler.GetEmbeddedClusterNode)) // Prometheus r.Name("SetPrometheusAddress").Path("/api/v1/prometheus").Methods("POST"). @@ -357,7 +357,7 @@ func RegisterUnauthenticatedRoutes(handler *Handler, kotsStore store.Store, debu loggingRouter.Path("/api/v1/app/custom-metrics").Methods("POST").HandlerFunc(handler.GetSendCustomAppMetricsHandler(kotsStore)) // This handler requires a valid token in the query - loggingRouter.Path("/api/v1/embedded-cluster/join").Methods("GET").HandlerFunc(handler.GetK0sNodeJoinCommand) + loggingRouter.Path("/api/v1/embedded-cluster/join").Methods("GET").HandlerFunc(handler.GetEmbeddedClusterNodeJoinCommand) } func StreamJSON(c *websocket.Conn, payload interface{}) { diff --git a/pkg/handlers/handlers_test.go b/pkg/handlers/handlers_test.go index 9d4ee77a74..c502bb6733 100644 --- a/pkg/handlers/handlers_test.go +++ b/pkg/handlers/handlers_test.go @@ -1209,66 +1209,56 @@ var HandlerPolicyTests = map[string][]HandlerPolicyTest{ }, }, - "HelmVM": {}, // Not implemented - "GenerateK0sNodeJoinCommand": { + "EmbeddedCluster": {}, // Not implemented + "GenerateEmbeddedClusterNodeJoinCommand": { { Roles: []rbactypes.Role{rbac.ClusterAdminRole}, SessionRoles: []string{rbac.ClusterAdminRoleID}, Calls: func(storeRecorder *mock_store.MockStoreMockRecorder, handlerRecorder *mock_handlers.MockKOTSHandlerMockRecorder) { - handlerRecorder.GenerateK0sNodeJoinCommand(gomock.Any(), gomock.Any()) + handlerRecorder.GenerateEmbeddedClusterNodeJoinCommand(gomock.Any(), gomock.Any()) }, ExpectStatus: http.StatusOK, }, }, - "DrainHelmVMNode": { + "DrainEmbeddedClusterNode": { { Vars: map[string]string{"nodeName": "node-name"}, Roles: []rbactypes.Role{rbac.ClusterAdminRole}, SessionRoles: []string{rbac.ClusterAdminRoleID}, Calls: func(storeRecorder *mock_store.MockStoreMockRecorder, handlerRecorder *mock_handlers.MockKOTSHandlerMockRecorder) { - handlerRecorder.DrainHelmVMNode(gomock.Any(), gomock.Any()) + handlerRecorder.DrainEmbeddedClusterNode(gomock.Any(), gomock.Any()) }, ExpectStatus: http.StatusOK, }, }, - "DeleteHelmVMNode": { + "DeleteEmbeddedClusterNode": { { Vars: map[string]string{"nodeName": "node-name"}, Roles: []rbactypes.Role{rbac.ClusterAdminRole}, SessionRoles: []string{rbac.ClusterAdminRoleID}, Calls: func(storeRecorder *mock_store.MockStoreMockRecorder, handlerRecorder *mock_handlers.MockKOTSHandlerMockRecorder) { - handlerRecorder.DeleteHelmVMNode(gomock.Any(), gomock.Any()) + handlerRecorder.DeleteEmbeddedClusterNode(gomock.Any(), gomock.Any()) }, ExpectStatus: http.StatusOK, }, }, - "GetHelmVMNodes": { + "GetEmbeddedClusterNodes": { { Roles: []rbactypes.Role{rbac.ClusterAdminRole}, SessionRoles: []string{rbac.ClusterAdminRoleID}, Calls: func(storeRecorder *mock_store.MockStoreMockRecorder, handlerRecorder *mock_handlers.MockKOTSHandlerMockRecorder) { - handlerRecorder.GetHelmVMNodes(gomock.Any(), gomock.Any()) + handlerRecorder.GetEmbeddedClusterNodes(gomock.Any(), gomock.Any()) }, ExpectStatus: http.StatusOK, }, }, - "GetHelmVMNode": { + "GetEmbeddedClusterNode": { { Vars: map[string]string{"nodeName": "node-name"}, Roles: []rbactypes.Role{rbac.ClusterAdminRole}, SessionRoles: []string{rbac.ClusterAdminRoleID}, Calls: func(storeRecorder *mock_store.MockStoreMockRecorder, handlerRecorder *mock_handlers.MockKOTSHandlerMockRecorder) { - handlerRecorder.GetHelmVMNode(gomock.Any(), gomock.Any()) - }, - ExpectStatus: http.StatusOK, - }, - }, - "GetK0sNodeJoinCommand": { - { - Roles: []rbactypes.Role{rbac.ClusterAdminRole}, - SessionRoles: []string{rbac.ClusterAdminRoleID}, - Calls: func(storeRecorder *mock_store.MockStoreMockRecorder, handlerRecorder *mock_handlers.MockKOTSHandlerMockRecorder) { - handlerRecorder.GetK0sNodeJoinCommand(gomock.Any(), gomock.Any()) + handlerRecorder.GetEmbeddedClusterNode(gomock.Any(), gomock.Any()) }, ExpectStatus: http.StatusOK, }, diff --git a/pkg/handlers/interface.go b/pkg/handlers/interface.go index 67dd05d3bc..a8fe1bd4dc 100644 --- a/pkg/handlers/interface.go +++ b/pkg/handlers/interface.go @@ -138,13 +138,12 @@ type KOTSHandler interface { DeleteKurlNode(w http.ResponseWriter, r *http.Request) GetKurlNodes(w http.ResponseWriter, r *http.Request) - // HelmVM - GenerateK0sNodeJoinCommand(w http.ResponseWriter, r *http.Request) - DrainHelmVMNode(w http.ResponseWriter, r *http.Request) - DeleteHelmVMNode(w http.ResponseWriter, r *http.Request) - GetHelmVMNodes(w http.ResponseWriter, r *http.Request) - GetHelmVMNode(w http.ResponseWriter, r *http.Request) - GetK0sNodeJoinCommand(w http.ResponseWriter, r *http.Request) + // EmbeddedCLuster + GenerateEmbeddedClusterNodeJoinCommand(w http.ResponseWriter, r *http.Request) + DrainEmbeddedClusterNode(w http.ResponseWriter, r *http.Request) + DeleteEmbeddedClusterNode(w http.ResponseWriter, r *http.Request) + GetEmbeddedClusterNodes(w http.ResponseWriter, r *http.Request) + GetEmbeddedClusterNode(w http.ResponseWriter, r *http.Request) // Prometheus SetPrometheusAddress(w http.ResponseWriter, r *http.Request) diff --git a/pkg/handlers/metadata.go b/pkg/handlers/metadata.go index 81903b26dd..cc7253551e 100644 --- a/pkg/handlers/metadata.go +++ b/pkg/handlers/metadata.go @@ -50,9 +50,9 @@ type MetadataResponseBranding struct { } type AdminConsoleMetadata struct { - IsAirgap bool `json:"isAirgap"` - IsKurl bool `json:"isKurl"` - IsHelmVM bool `json:"isHelmVM"` + IsAirgap bool `json:"isAirgap"` + IsKurl bool `json:"isKurl"` + IsEmbeddedCluster bool `json:"isEmbeddedCluster"` } // GetMetadataHandler helper function that returns a http handler func that returns metadata. It takes a function that @@ -73,7 +73,7 @@ func GetMetadataHandler(getK8sInfoFn MetadataK8sFn, kotsStore store.Store) http. if kuberneteserrors.IsNotFound(err) { metadataResponse.AdminConsoleMetadata.IsAirgap = kotsadmMetadata.IsAirgap metadataResponse.AdminConsoleMetadata.IsKurl = kotsadmMetadata.IsKurl - metadataResponse.AdminConsoleMetadata.IsHelmVM = kotsadmMetadata.IsHelmVM + metadataResponse.AdminConsoleMetadata.IsEmbeddedCluster = kotsadmMetadata.IsEmbeddedCluster logger.Info(fmt.Sprintf("config map %q not found", metadataConfigMapName)) JSON(w, http.StatusOK, &metadataResponse) @@ -114,9 +114,9 @@ func GetMetadataHandler(getK8sInfoFn MetadataK8sFn, kotsStore store.Store) http. metadataResponse.UpstreamURI = brandingConfigMap.Data[upstreamUriKey] metadataResponse.ConsoleFeatureFlags = application.Spec.ConsoleFeatureFlags metadataResponse.AdminConsoleMetadata = AdminConsoleMetadata{ - IsAirgap: kotsadmMetadata.IsAirgap, - IsKurl: kotsadmMetadata.IsKurl, - IsHelmVM: kotsadmMetadata.IsHelmVM, + IsAirgap: kotsadmMetadata.IsAirgap, + IsKurl: kotsadmMetadata.IsKurl, + IsEmbeddedCluster: kotsadmMetadata.IsEmbeddedCluster, } JSON(w, http.StatusOK, metadataResponse) diff --git a/pkg/handlers/mock/mock.go b/pkg/handlers/mock/mock.go index 736883ad70..c122017330 100644 --- a/pkg/handlers/mock/mock.go +++ b/pkg/handlers/mock/mock.go @@ -262,16 +262,16 @@ func (mr *MockKOTSHandlerMockRecorder) DeleteBackup(w, r interface{}) *gomock.Ca return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "DeleteBackup", reflect.TypeOf((*MockKOTSHandler)(nil).DeleteBackup), w, r) } -// DeleteHelmVMNode mocks base method. -func (m *MockKOTSHandler) DeleteHelmVMNode(w http.ResponseWriter, r *http.Request) { +// DeleteEmbeddedClusterNode mocks base method. +func (m *MockKOTSHandler) DeleteEmbeddedClusterNode(w http.ResponseWriter, r *http.Request) { m.ctrl.T.Helper() - m.ctrl.Call(m, "DeleteHelmVMNode", w, r) + m.ctrl.Call(m, "DeleteEmbeddedClusterNode", w, r) } -// DeleteHelmVMNode indicates an expected call of DeleteHelmVMNode. -func (mr *MockKOTSHandlerMockRecorder) DeleteHelmVMNode(w, r interface{}) *gomock.Call { +// DeleteEmbeddedClusterNode indicates an expected call of DeleteEmbeddedClusterNode. +func (mr *MockKOTSHandlerMockRecorder) DeleteEmbeddedClusterNode(w, r interface{}) *gomock.Call { mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "DeleteHelmVMNode", reflect.TypeOf((*MockKOTSHandler)(nil).DeleteHelmVMNode), w, r) + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "DeleteEmbeddedClusterNode", reflect.TypeOf((*MockKOTSHandler)(nil).DeleteEmbeddedClusterNode), w, r) } // DeleteKurlNode mocks base method. @@ -394,16 +394,16 @@ func (mr *MockKOTSHandlerMockRecorder) DownloadSupportBundle(w, r interface{}) * return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "DownloadSupportBundle", reflect.TypeOf((*MockKOTSHandler)(nil).DownloadSupportBundle), w, r) } -// DrainHelmVMNode mocks base method. -func (m *MockKOTSHandler) DrainHelmVMNode(w http.ResponseWriter, r *http.Request) { +// DrainEmbeddedClusterNode mocks base method. +func (m *MockKOTSHandler) DrainEmbeddedClusterNode(w http.ResponseWriter, r *http.Request) { m.ctrl.T.Helper() - m.ctrl.Call(m, "DrainHelmVMNode", w, r) + m.ctrl.Call(m, "DrainEmbeddedClusterNode", w, r) } -// DrainHelmVMNode indicates an expected call of DrainHelmVMNode. -func (mr *MockKOTSHandlerMockRecorder) DrainHelmVMNode(w, r interface{}) *gomock.Call { +// DrainEmbeddedClusterNode indicates an expected call of DrainEmbeddedClusterNode. +func (mr *MockKOTSHandlerMockRecorder) DrainEmbeddedClusterNode(w, r interface{}) *gomock.Call { mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "DrainHelmVMNode", reflect.TypeOf((*MockKOTSHandler)(nil).DrainHelmVMNode), w, r) + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "DrainEmbeddedClusterNode", reflect.TypeOf((*MockKOTSHandler)(nil).DrainEmbeddedClusterNode), w, r) } // DrainKurlNode mocks base method. @@ -442,16 +442,16 @@ func (mr *MockKOTSHandlerMockRecorder) GarbageCollectImages(w, r interface{}) *g return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GarbageCollectImages", reflect.TypeOf((*MockKOTSHandler)(nil).GarbageCollectImages), w, r) } -// GenerateK0sNodeJoinCommand mocks base method. -func (m *MockKOTSHandler) GenerateK0sNodeJoinCommand(w http.ResponseWriter, r *http.Request) { +// GenerateEmbeddedClusterNodeJoinCommand mocks base method. +func (m *MockKOTSHandler) GenerateEmbeddedClusterNodeJoinCommand(w http.ResponseWriter, r *http.Request) { m.ctrl.T.Helper() - m.ctrl.Call(m, "GenerateK0sNodeJoinCommand", w, r) + m.ctrl.Call(m, "GenerateEmbeddedClusterNodeJoinCommand", w, r) } -// GenerateK0sNodeJoinCommand indicates an expected call of GenerateK0sNodeJoinCommand. -func (mr *MockKOTSHandlerMockRecorder) GenerateK0sNodeJoinCommand(w, r interface{}) *gomock.Call { +// GenerateEmbeddedClusterNodeJoinCommand indicates an expected call of GenerateEmbeddedClusterNodeJoinCommand. +func (mr *MockKOTSHandlerMockRecorder) GenerateEmbeddedClusterNodeJoinCommand(w, r interface{}) *gomock.Call { mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GenerateK0sNodeJoinCommand", reflect.TypeOf((*MockKOTSHandler)(nil).GenerateK0sNodeJoinCommand), w, r) + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GenerateEmbeddedClusterNodeJoinCommand", reflect.TypeOf((*MockKOTSHandler)(nil).GenerateEmbeddedClusterNodeJoinCommand), w, r) } // GenerateKurlNodeJoinCommandMaster mocks base method. @@ -706,6 +706,30 @@ func (mr *MockKOTSHandlerMockRecorder) GetDownstreamOutput(w, r interface{}) *go return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetDownstreamOutput", reflect.TypeOf((*MockKOTSHandler)(nil).GetDownstreamOutput), w, r) } +// GetEmbeddedClusterNode mocks base method. +func (m *MockKOTSHandler) GetEmbeddedClusterNode(w http.ResponseWriter, r *http.Request) { + m.ctrl.T.Helper() + m.ctrl.Call(m, "GetEmbeddedClusterNode", w, r) +} + +// GetEmbeddedClusterNode indicates an expected call of GetEmbeddedClusterNode. +func (mr *MockKOTSHandlerMockRecorder) GetEmbeddedClusterNode(w, r interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetEmbeddedClusterNode", reflect.TypeOf((*MockKOTSHandler)(nil).GetEmbeddedClusterNode), w, r) +} + +// GetEmbeddedClusterNodes mocks base method. +func (m *MockKOTSHandler) GetEmbeddedClusterNodes(w http.ResponseWriter, r *http.Request) { + m.ctrl.T.Helper() + m.ctrl.Call(m, "GetEmbeddedClusterNodes", w, r) +} + +// GetEmbeddedClusterNodes indicates an expected call of GetEmbeddedClusterNodes. +func (mr *MockKOTSHandlerMockRecorder) GetEmbeddedClusterNodes(w, r interface{}) *gomock.Call { + mr.mock.ctrl.T.Helper() + return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetEmbeddedClusterNodes", reflect.TypeOf((*MockKOTSHandler)(nil).GetEmbeddedClusterNodes), w, r) +} + // GetFileSystemSnapshotProviderInstructions mocks base method. func (m *MockKOTSHandler) GetFileSystemSnapshotProviderInstructions(w http.ResponseWriter, r *http.Request) { m.ctrl.T.Helper() @@ -742,30 +766,6 @@ func (mr *MockKOTSHandlerMockRecorder) GetGlobalSnapshotSettings(w, r interface{ return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetGlobalSnapshotSettings", reflect.TypeOf((*MockKOTSHandler)(nil).GetGlobalSnapshotSettings), w, r) } -// GetHelmVMNode mocks base method. -func (m *MockKOTSHandler) GetHelmVMNode(w http.ResponseWriter, r *http.Request) { - m.ctrl.T.Helper() - m.ctrl.Call(m, "GetHelmVMNode", w, r) -} - -// GetHelmVMNode indicates an expected call of GetHelmVMNode. -func (mr *MockKOTSHandlerMockRecorder) GetHelmVMNode(w, r interface{}) *gomock.Call { - mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetHelmVMNode", reflect.TypeOf((*MockKOTSHandler)(nil).GetHelmVMNode), w, r) -} - -// GetHelmVMNodes mocks base method. -func (m *MockKOTSHandler) GetHelmVMNodes(w http.ResponseWriter, r *http.Request) { - m.ctrl.T.Helper() - m.ctrl.Call(m, "GetHelmVMNodes", w, r) -} - -// GetHelmVMNodes indicates an expected call of GetHelmVMNodes. -func (mr *MockKOTSHandlerMockRecorder) GetHelmVMNodes(w, r interface{}) *gomock.Call { - mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetHelmVMNodes", reflect.TypeOf((*MockKOTSHandler)(nil).GetHelmVMNodes), w, r) -} - // GetIdentityServiceConfig mocks base method. func (m *MockKOTSHandler) GetIdentityServiceConfig(w http.ResponseWriter, r *http.Request) { m.ctrl.T.Helper() @@ -802,18 +802,6 @@ func (mr *MockKOTSHandlerMockRecorder) GetInstanceSnapshotConfig(w, r interface{ return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetInstanceSnapshotConfig", reflect.TypeOf((*MockKOTSHandler)(nil).GetInstanceSnapshotConfig), w, r) } -// GetK0sNodeJoinCommand mocks base method. -func (m *MockKOTSHandler) GetK0sNodeJoinCommand(w http.ResponseWriter, r *http.Request) { - m.ctrl.T.Helper() - m.ctrl.Call(m, "GetK0sNodeJoinCommand", w, r) -} - -// GetK0sNodeJoinCommand indicates an expected call of GetK0sNodeJoinCommand. -func (mr *MockKOTSHandlerMockRecorder) GetK0sNodeJoinCommand(w, r interface{}) *gomock.Call { - mr.mock.ctrl.T.Helper() - return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "GetK0sNodeJoinCommand", reflect.TypeOf((*MockKOTSHandler)(nil).GetK0sNodeJoinCommand), w, r) -} - // GetKotsadmRegistry mocks base method. func (m *MockKOTSHandler) GetKotsadmRegistry(w http.ResponseWriter, r *http.Request) { m.ctrl.T.Helper() diff --git a/pkg/kotsadm/metadata.go b/pkg/kotsadm/metadata.go index 9c9b045cb0..9c2c09b90a 100644 --- a/pkg/kotsadm/metadata.go +++ b/pkg/kotsadm/metadata.go @@ -1,7 +1,7 @@ package kotsadm import ( - "github.com/replicatedhq/kots/pkg/helmvm" + "github.com/replicatedhq/kots/pkg/embeddedcluster" "github.com/replicatedhq/kots/pkg/kotsadm/types" "github.com/replicatedhq/kots/pkg/kurl" "k8s.io/client-go/kubernetes" @@ -9,12 +9,12 @@ import ( func GetMetadata(clientset kubernetes.Interface) types.Metadata { isKurl, _ := kurl.IsKurl(clientset) - isHelmVM, _ := helmvm.IsHelmVM(clientset) + isEmbeddedCluster, _ := embeddedcluster.IsEmbeddedCluster(clientset) metadata := types.Metadata{ - IsAirgap: IsAirgap(), - IsKurl: isKurl, - IsHelmVM: isHelmVM, + IsAirgap: IsAirgap(), + IsKurl: isKurl, + IsEmbeddedCluster: isEmbeddedCluster, } return metadata diff --git a/pkg/kotsadm/types/metadata.go b/pkg/kotsadm/types/metadata.go index 79e8b142a6..8ff2225f42 100644 --- a/pkg/kotsadm/types/metadata.go +++ b/pkg/kotsadm/types/metadata.go @@ -1,7 +1,7 @@ package types type Metadata struct { - IsAirgap bool - IsKurl bool - IsHelmVM bool + IsAirgap bool + IsKurl bool + IsEmbeddedCluster bool } diff --git a/pkg/store/kotsstore/k0s_store.go b/pkg/store/kotsstore/embedded_cluster_store.go similarity index 71% rename from pkg/store/kotsstore/k0s_store.go rename to pkg/store/kotsstore/embedded_cluster_store.go index 4eb7a9bd7b..39cc5cda5b 100644 --- a/pkg/store/kotsstore/k0s_store.go +++ b/pkg/store/kotsstore/embedded_cluster_store.go @@ -9,18 +9,18 @@ import ( "github.com/replicatedhq/kots/pkg/rand" ) -func (s *KOTSStore) SetK0sInstallCommandRoles(roles []string) (string, error) { +func (s *KOTSStore) SetEmbeddedClusterInstallCommandRoles(roles []string) (string, error) { db := persistence.MustGetDBSession() installID := rand.StringWithCharset(24, rand.LOWER_CASE+rand.UPPER_CASE) - query := `delete from k0s_tokens where token = ?` + query := `delete from embedded_cluster_tokens where token = ?` wr, err := db.WriteOneParameterized(gorqlite.ParameterizedStatement{ Query: query, Arguments: []interface{}{installID}, }) if err != nil { - return "", fmt.Errorf("delete k0s join token: %v: %v", err, wr.Err) + return "", fmt.Errorf("delete embedded_cluster join token: %v: %v", err, wr.Err) } jsonRoles, err := json.Marshal(roles) @@ -28,21 +28,21 @@ func (s *KOTSStore) SetK0sInstallCommandRoles(roles []string) (string, error) { return "", fmt.Errorf("failed to marshal roles: %w", err) } - query = `insert into k0s_tokens (token, roles) values (?, ?)` + query = `insert into embedded_cluster_tokens (token, roles) values (?, ?)` wr, err = db.WriteOneParameterized(gorqlite.ParameterizedStatement{ Query: query, Arguments: []interface{}{installID, string(jsonRoles)}, }) if err != nil { - return "", fmt.Errorf("insert k0s join token: %v: %v", err, wr.Err) + return "", fmt.Errorf("insert embedded_cluster join token: %v: %v", err, wr.Err) } return installID, nil } -func (s *KOTSStore) GetK0sInstallCommandRoles(token string) ([]string, error) { +func (s *KOTSStore) GetEmbeddedClusterInstallCommandRoles(token string) ([]string, error) { db := persistence.MustGetDBSession() - query := `select roles from k0s_tokens where token = ?` + query := `select roles from embedded_cluster_tokens where token = ?` rows, err := db.QueryOneParameterized(gorqlite.ParameterizedStatement{ Query: query, Arguments: []interface{}{token}, diff --git a/web/src/components/apps/HelmVMClusterManagement.tsx b/web/src/components/apps/HelmVMClusterManagement.tsx index f7ced8bec4..f801d0c1e2 100644 --- a/web/src/components/apps/HelmVMClusterManagement.tsx +++ b/web/src/components/apps/HelmVMClusterManagement.tsx @@ -1,14 +1,14 @@ -import { useQuery } from "@tanstack/react-query"; +import {useQuery} from "@tanstack/react-query"; import classNames from "classnames"; -import MaterialReactTable, { MRT_ColumnDef } from "material-react-table"; -import React, { ChangeEvent, useMemo, useReducer, useState } from "react"; +import MaterialReactTable, {MRT_ColumnDef} from "material-react-table"; +import React, {ChangeEvent, useMemo, useReducer, useState} from "react"; import Modal from "react-modal"; -import { Link, useParams } from "react-router-dom"; +import {Link, useParams} from "react-router-dom"; -import { KotsPageTitle } from "@components/Head"; -import { useApps } from "@features/App"; -import { rbacRoles } from "../../constants/rbac"; -import { Utilities } from "../../utilities/utilities"; +import {KotsPageTitle} from "@components/Head"; +import {useApps} from "@features/App"; +import {rbacRoles} from "../../constants/rbac"; +import {Utilities} from "../../utilities/utilities"; import Icon from "../Icon"; import CodeSnippet from "../shared/CodeSnippet"; @@ -20,7 +20,7 @@ const testData = { // const testData = { // nodes: [ // { -// name: "laverya-helmvm", +// name: "laverya-embeddedcluster", // isConnected: true, // isReady: true, // isPrimaryNode: true, @@ -79,7 +79,7 @@ const HelmVMClusterManagement = ({ const [selectedNodeTypes, setSelectedNodeTypes] = useState([]); const { data: appsData } = useApps(); - // we grab the first app because helmvm users should only ever have one app + // we grab the first app because embeddedcluster users should only ever have one app const app = appsData?.apps?.[0]; const { slug } = useParams(); diff --git a/web/src/components/apps/HelmVMViewNode.jsx b/web/src/components/apps/HelmVMViewNode.jsx index 6bd7651568..f7b3452524 100644 --- a/web/src/components/apps/HelmVMViewNode.jsx +++ b/web/src/components/apps/HelmVMViewNode.jsx @@ -1,12 +1,12 @@ -import { MaterialReactTable } from "material-react-table"; -import React, { useMemo, setState } from "react"; -import { useQuery } from "@tanstack/react-query"; -import { Link, useParams } from "react-router-dom"; +import {MaterialReactTable} from "material-react-table"; +import React, {useMemo} from "react"; +import {useQuery} from "@tanstack/react-query"; +import {Link, useParams} from "react-router-dom"; import Loader from "@components/shared/Loader"; const testData = undefined; // const testData = { -// name: "laverya-helmvm", +// name: "laverya-embeddedcluster", // isConnected: true, // isReady: true, // isPrimaryNode: true, @@ -29,7 +29,7 @@ const testData = undefined; // { // name: "example-es-85fc9df74-8x8l6", // status: "Running", -// namespace: "helmvm", +// namespace: "embeddedcluster", // cpu: "0.0345789345 GB", // memory: 0, // },