Skip to content

Commit

Permalink
Release/v5.3.4 (#4721)
Browse files Browse the repository at this point in the history
* Use electron.clipboard for all clipboard uses (#4535)

Signed-off-by: Jim Ehrismann <jehrismann@mirantis.com>

* Fix ERR_UNSAFE_PORT from LensProxy (#4558)

* Fix ERR_UNSAFE_PORT from LensProxy

- Use the current list of ports from chromium as it is much easier to
  just reject using one of those instead of trying to handle the
  ERR_UNSAFE_PORT laod error from a BrowserWindow.on("did-fail-load")

Signed-off-by: Sebastian Malton <sebastian@malton.name>

* Move all port handling into LensProxy

Signed-off-by: Sebastian Malton <sebastian@malton.name>

* don't use so many exceptions

Signed-off-by: Sebastian Malton <sebastian@malton.name>
Signed-off-by: Jim Ehrismann <jehrismann@mirantis.com>

* Fix not being able to clear set cluster icon (#4555)

Signed-off-by: Jim Ehrismann <jehrismann@mirantis.com>

* Fix extension engine range not working for some ^ ranges (#4554)

Signed-off-by: Jim Ehrismann <jehrismann@mirantis.com>

* Fix crash on NetworkPolicy when matchLabels is missing (#4500)

Signed-off-by: Jim Ehrismann <jehrismann@mirantis.com>

* Replace all uses of promiseExec with promiseExecFile (#4514)

Signed-off-by: Jim Ehrismann <jehrismann@mirantis.com>

* Less noisy metrics-not-available error logging (#4602)

Signed-off-by: Jari Kolehmainen <jari.kolehmainen@gmail.com>
Signed-off-by: Jim Ehrismann <jehrismann@mirantis.com>

* Fix close button overflow in Preferences (#4611)

* Adding basic colors to tailwind theme

Signed-off-by: Alex Andreev <alex.andreev.email@gmail.com>

* Using tailwind inline to style close button

Signed-off-by: Alex Andreev <alex.andreev.email@gmail.com>

* Make Select look similar to inputs

Signed-off-by: Alex Andreev <alex.andreev.email@gmail.com>

* Moving styles into separate module

Signed-off-by: Alex Andreev <alex.andreev.email@gmail.com>

* Convert tailwind commands to css

Signed-off-by: Alex Andreev <alex.andreev.email@gmail.com>
Signed-off-by: Jim Ehrismann <jehrismann@mirantis.com>

* Fix prometheus operator metrics work out of the box (#4617)

Signed-off-by: Lauri Nevala <lauri.nevala@gmail.com>
Signed-off-by: Jim Ehrismann <jehrismann@mirantis.com>

* Fix CRD.getPreferedVersion() to work based on apiVersion (#4553)

* Fix CRD.getPreferedVersion() to work based on apiVersion

Signed-off-by: Sebastian Malton <sebastian@malton.name>

* Add tests

Signed-off-by: Sebastian Malton <sebastian@malton.name>
Signed-off-by: Jim Ehrismann <jehrismann@mirantis.com>

* Fix crash for KubeObjectStore.loadAll() (#4675)

Signed-off-by: Sebastian Malton <sebastian@malton.name>
Signed-off-by: Jim Ehrismann <jehrismann@mirantis.com>

* Convert CloseButton styles out from css modules (#4723)

* Convert CloseButton styles out from css modules

Signed-off-by: Alex Andreev <alex.andreev.email@gmail.com>

* Fix close button styling

Signed-off-by: Alex Andreev <alex.andreev.email@gmail.com>

* release v5.3.4

Signed-off-by: Jim Ehrismann <jehrismann@mirantis.com>

Co-authored-by: Sebastian Malton <sebastian@malton.name>
Co-authored-by: Jari Kolehmainen <jari.kolehmainen@gmail.com>
Co-authored-by: Alex Andreev <alex.andreev.email@gmail.com>
Co-authored-by: Lauri Nevala <lauri.nevala@gmail.com>
  • Loading branch information
5 people committed Jan 20, 2022
1 parent 0a6bafc commit e8d8f8f
Show file tree
Hide file tree
Showing 34 changed files with 630 additions and 466 deletions.
3 changes: 2 additions & 1 deletion integration/__tests__/app-preferences.tests.ts
Original file line number Diff line number Diff line change
Expand Up @@ -71,7 +71,8 @@ describe("preferences page tests", () => {
}
}, 10*60*1000);

utils.itIf(process.platform !== "win32")("ensures helm repos", async () => {
// Skipping, but will turn it on again in the follow up PR
it.skip("ensures helm repos", async () => {
await window.click("[data-testid=kubernetes-tab]");
await window.waitForSelector("[data-testid=repository-name]", {
timeout: 140_000,
Expand Down
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
"productName": "OpenLens",
"description": "OpenLens - Open Source IDE for Kubernetes",
"homepage": "https://github.com/lensapp/lens",
"version": "5.3.3",
"version": "5.3.4",
"main": "static/build/main.js",
"copyright": "© 2021 OpenLens Authors",
"license": "MIT",
Expand Down
6 changes: 5 additions & 1 deletion src/common/cluster-types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -90,7 +90,11 @@ export interface ClusterPreferences extends ClusterPrometheusPreferences {
terminalCWD?: string;
clusterName?: string;
iconOrder?: number;
icon?: string;
/**
* The <img> src for the cluster. If set to `null` that means that it was
* cleared by preferences.
*/
icon?: string | null;
httpsProxy?: string;
hiddenMetrics?: string[];
nodeShellImage?: string;
Expand Down
15 changes: 11 additions & 4 deletions src/common/k8s-api/__tests__/crd.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -19,10 +19,10 @@
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/

import { CustomResourceDefinition } from "../endpoints";
import { CustomResourceDefinition, CustomResourceDefinitionSpec } from "../endpoints";

describe("Crds", () => {
describe("getVersion", () => {
describe("getVersion()", () => {
it("should throw if none of the versions are served", () => {
const crd = new CustomResourceDefinition({
apiVersion: "apiextensions.k8s.io/v1",
Expand Down Expand Up @@ -136,7 +136,7 @@ describe("Crds", () => {
expect(crd.getVersion()).toBe("123");
});

it("should get the version name from the version field", () => {
it("should get the version name from the version field, ignoring versions on v1beta", () => {
const crd = new CustomResourceDefinition({
apiVersion: "apiextensions.k8s.io/v1beta1",
kind: "CustomResourceDefinition",
Expand All @@ -147,7 +147,14 @@ describe("Crds", () => {
},
spec: {
version: "abc",
},
versions: [
{
name: "foobar",
served: true,
storage: true,
},
],
} as CustomResourceDefinitionSpec,
});

expect(crd.getVersion()).toBe("abc");
Expand Down
97 changes: 51 additions & 46 deletions src/common/k8s-api/endpoints/crd.api.ts
Original file line number Diff line number Diff line change
Expand Up @@ -48,34 +48,36 @@ export interface CRDVersion {
additionalPrinterColumns?: AdditionalPrinterColumnsV1[];
}

export interface CustomResourceDefinition {
spec: {
group: string;
/**
* @deprecated for apiextensions.k8s.io/v1 but used previously
*/
version?: string;
names: {
plural: string;
singular: string;
kind: string;
listKind: string;
};
scope: "Namespaced" | "Cluster" | string;
/**
* @deprecated for apiextensions.k8s.io/v1 but used previously
*/
validation?: object;
versions?: CRDVersion[];
conversion: {
strategy?: string;
webhook?: any;
};
/**
* @deprecated for apiextensions.k8s.io/v1 but used previously
*/
additionalPrinterColumns?: AdditionalPrinterColumnsV1Beta[];
export interface CustomResourceDefinitionSpec {
group: string;
/**
* @deprecated for apiextensions.k8s.io/v1 but used in v1beta1
*/
version?: string;
names: {
plural: string;
singular: string;
kind: string;
listKind: string;
};
scope: "Namespaced" | "Cluster";
/**
* @deprecated for apiextensions.k8s.io/v1 but used in v1beta1
*/
validation?: object;
versions?: CRDVersion[];
conversion: {
strategy?: string;
webhook?: any;
};
/**
* @deprecated for apiextensions.k8s.io/v1 but used in v1beta1
*/
additionalPrinterColumns?: AdditionalPrinterColumnsV1Beta[];
}

export interface CustomResourceDefinition {
spec: CustomResourceDefinitionSpec;
status: {
conditions: {
lastTransitionTime: string;
Expand Down Expand Up @@ -150,27 +152,30 @@ export class CustomResourceDefinition extends KubeObject {
}

getPreferedVersion(): CRDVersion {
// Prefer the modern `versions` over the legacy `version`
if (this.spec.versions) {
for (const version of this.spec.versions) {
if (version.storage) {
return version;
const { apiVersion } = this;

switch (apiVersion) {
case "apiextensions.k8s.io/v1":
for (const version of this.spec.versions) {
if (version.storage) {
return version;
}
}
}
} else if (this.spec.version) {
const { additionalPrinterColumns: apc } = this.spec;
const additionalPrinterColumns = apc?.map(({ JSONPath, ...apc }) => ({ ...apc, jsonPath: JSONPath }));

return {
name: this.spec.version,
served: true,
storage: true,
schema: this.spec.validation,
additionalPrinterColumns,
};
break;
case "apiextensions.k8s.io/v1beta1":
const { additionalPrinterColumns: apc } = this.spec;
const additionalPrinterColumns = apc?.map(({ JSONPath, ...apc }) => ({ ...apc, jsonPath: JSONPath }));

return {
name: this.spec.version,
served: true,
storage: true,
schema: this.spec.validation,
additionalPrinterColumns,
};
}

throw new Error(`Failed to find a version for CustomResourceDefinition ${this.metadata.name}`);
throw new Error(`Unknown apiVersion=${apiVersion}: Failed to find a version for CustomResourceDefinition ${this.metadata.name}`);
}

getVersion() {
Expand All @@ -197,7 +202,7 @@ export class CustomResourceDefinition extends KubeObject {
const columns = this.getPreferedVersion().additionalPrinterColumns ?? [];

return columns
.filter(column => column.name != "Age" && (ignorePriority || !column.priority));
.filter(column => column.name.toLowerCase() != "age" && (ignorePriority || !column.priority));
}

getValidation() {
Expand Down
3 changes: 2 additions & 1 deletion src/common/k8s-api/kube-object.store.ts
Original file line number Diff line number Diff line change
Expand Up @@ -235,8 +235,9 @@ export abstract class KubeObjectStore<T extends KubeObject> extends ItemStore<T>
}

@action
async loadAll({ namespaces = this.context.contextNamespaces, merge = true, reqInit, onLoadFailure }: KubeObjectStoreLoadAllParams = {}): Promise<void | T[]> {
async loadAll({ namespaces, merge = true, reqInit, onLoadFailure }: KubeObjectStoreLoadAllParams = {}): Promise<void | T[]> {
await this.contextReady;
namespaces ??= this.context.contextNamespaces;
this.isLoading = true;

try {
Expand Down
22 changes: 14 additions & 8 deletions src/common/system-ca.ts
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@
import { isMac, isWindows } from "./vars";
import wincaAPI from "win-ca/api";
import https from "https";
import { promiseExec } from "./utils/promise-exec";
import { promiseExecFile } from "./utils/promise-exec";

// DST Root CA X3, which was expired on 9.30.2021
export const DSTRootCAX3 = "-----BEGIN CERTIFICATE-----\nMIIDSjCCAjKgAwIBAgIQRK+wgNajJ7qJMDmGLvhAazANBgkqhkiG9w0BAQUFADA/\nMSQwIgYDVQQKExtEaWdpdGFsIFNpZ25hdHVyZSBUcnVzdCBDby4xFzAVBgNVBAMT\nDkRTVCBSb290IENBIFgzMB4XDTAwMDkzMDIxMTIxOVoXDTIxMDkzMDE0MDExNVow\nPzEkMCIGA1UEChMbRGlnaXRhbCBTaWduYXR1cmUgVHJ1c3QgQ28uMRcwFQYDVQQD\nEw5EU1QgUm9vdCBDQSBYMzCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEB\nAN+v6ZdQCINXtMxiZfaQguzH0yxrMMpb7NnDfcdAwRgUi+DoM3ZJKuM/IUmTrE4O\nrz5Iy2Xu/NMhD2XSKtkyj4zl93ewEnu1lcCJo6m67XMuegwGMoOifooUMM0RoOEq\nOLl5CjH9UL2AZd+3UWODyOKIYepLYYHsUmu5ouJLGiifSKOeDNoJjj4XLh7dIN9b\nxiqKqy69cK3FCxolkHRyxXtqqzTWMIn/5WgTe1QLyNau7Fqckh49ZLOMxt+/yUFw\n7BZy1SbsOFU5Q9D8/RhcQPGX69Wam40dutolucbY38EVAjqr2m7xPi71XAicPNaD\naeQQmxkqtilX4+U9m5/wAl0CAwEAAaNCMEAwDwYDVR0TAQH/BAUwAwEB/zAOBgNV\nHQ8BAf8EBAMCAQYwHQYDVR0OBBYEFMSnsaR7LHH62+FLkHX/xBVghYkQMA0GCSqG\nSIb3DQEBBQUAA4IBAQCjGiybFwBcqR7uKGY3Or+Dxz9LwwmglSBd49lZRNI+DT69\nikugdB/OEIKcdBodfpga3csTS7MgROSR6cz8faXbauX+5v3gTt23ADq1cEmv8uXr\nAvHRAosZy5Q6XkjEGB5YGV8eAlrwDPGxrancWYaLbumR9YbK+rlmM6pZW87ipxZz\nR8srzJmwN0jP41ZL9c8PDHIyh8bwRLtTcm1D9SZImlJnt1ir/md2cXjbDaJWFBM5\nJDGFoqgCWjBH4d1QB7wCCZAA62RjYJsWvIjJEubSfZGL+T0yjWW06XyxV3bqxbYo\nOb8VZRzI9neWagqNdwvYkQsEjgfbKbYK7p2CNTUQ\n-----END CERTIFICATE-----\n";
Expand All @@ -33,19 +33,25 @@ export function isCertActive(cert: string) {
return !isExpired;
}

// https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Regular_Expressions/Cheatsheet#other_assertions
const certSplitPattern = /(?=-----BEGIN\sCERTIFICATE-----)/g;

async function execSecurity(...args: string[]): Promise<string[]> {
const { stdout } = await promiseExecFile("/usr/bin/security", args);

return stdout.split(certSplitPattern);
}

/**
* Get root CA certificate from MacOSX system keychain
* Only return non-expred certificates.
*/
export async function getMacRootCA() {
// inspired mac-ca https://github.com/jfromaniello/mac-ca
const args = "find-certificate -a -p";
// https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Regular_Expressions/Cheatsheet#other_assertions
const splitPattern = /(?=-----BEGIN\sCERTIFICATE-----)/g;
const systemRootCertsPath = "/System/Library/Keychains/SystemRootCertificates.keychain";
const bin = "/usr/bin/security";
const trusted = (await promiseExec(`${bin} ${args}`)).stdout.toString().split(splitPattern);
const rootCA = (await promiseExec(`${bin} ${args} ${systemRootCertsPath}`)).stdout.toString().split(splitPattern);
const [trusted, rootCA] = await Promise.all([
execSecurity("find-certificate", "-a", "-p"),
execSecurity("find-certificate", "-a", "-p", "/System/Library/Keychains/SystemRootCertificates.keychain"),
]);

return [...new Set([...trusted, ...rootCA])].filter(isCertActive);
}
Expand Down
3 changes: 1 addition & 2 deletions src/common/utils/promise-exec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,6 @@
*/

import * as util from "util";
import { exec, execFile } from "child_process";
import { execFile } from "child_process";

export const promiseExec = util.promisify(exec);
export const promiseExecFile = util.promisify(execFile);
44 changes: 25 additions & 19 deletions src/extensions/__tests__/extension-compatibility.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -19,29 +19,24 @@
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/

import { isCompatibleExtension } from "../extension-compatibility";
import { rawIsCompatibleExtension } from "../extension-compatibility";
import { Console } from "console";
import { stdout, stderr } from "process";
import type { LensExtensionManifest } from "../lens-extension";
import { appSemVer } from "../../common/vars";
import { SemVer } from "semver";

console = new Console(stdout, stderr);

describe("extension compatibility", () => {
describe("appSemVer with no prerelease tag", () => {
beforeAll(() => {
appSemVer.major = 5;
appSemVer.minor = 0;
appSemVer.patch = 3;
appSemVer.prerelease = [];
});
const isCompatibleExtension = rawIsCompatibleExtension(new SemVer("5.0.3"));

it("has no extension comparator", () => {
const manifest = { name: "extensionName", version: "0.0.1" };

expect(isCompatibleExtension(manifest)).toBe(false);
});

it.each([
{
comparator: "",
Expand Down Expand Up @@ -83,19 +78,32 @@ describe("extension compatibility", () => {
});

describe("appSemVer with prerelease tag", () => {
beforeAll(() => {
appSemVer.major = 5;
appSemVer.minor = 0;
appSemVer.patch = 3;
appSemVer.prerelease = ["beta", 3];
const isCompatibleExtension = rawIsCompatibleExtension(new SemVer("5.0.3-beta.3"));

it("^5.1.0 should work when lens' version is 5.1.0-latest.123456789", () => {
const comparer = rawIsCompatibleExtension(new SemVer("5.1.0-latest.123456789"));

expect(comparer({ name: "extensionName", version: "0.0.1", engines: { lens: "^5.1.0" }})).toBe(true);
});


it("^5.1.0 should not when lens' version is 5.1.0-beta.1.123456789", () => {
const comparer = rawIsCompatibleExtension(new SemVer("5.1.0-beta.123456789"));

expect(comparer({ name: "extensionName", version: "0.0.1", engines: { lens: "^5.1.0" }})).toBe(false);
});

it("^5.1.0 should not when lens' version is 5.1.0-alpha.1.123456789", () => {
const comparer = rawIsCompatibleExtension(new SemVer("5.1.0-alpha.123456789"));

expect(comparer({ name: "extensionName", version: "0.0.1", engines: { lens: "^5.1.0" }})).toBe(false);
});

it("has no extension comparator", () => {
const manifest = { name: "extensionName", version: "0.0.1" };

expect(isCompatibleExtension(manifest)).toBe(false);
});

it.each([
{
comparator: "",
Expand Down Expand Up @@ -130,9 +138,7 @@ describe("extension compatibility", () => {
expected: false,
},
])("extension comparator test: %p", ({ comparator, expected }) => {
const manifest: LensExtensionManifest = { name: "extensionName", version: "0.0.1", engines: { lens: comparator }};

expect(isCompatibleExtension(manifest)).toBe(expected);
expect(isCompatibleExtension({ name: "extensionName", version: "0.0.1", engines: { lens: comparator }})).toBe(expected);
});
});
});
40 changes: 34 additions & 6 deletions src/extensions/extension-compatibility.ts
Original file line number Diff line number Diff line change
Expand Up @@ -19,19 +19,47 @@
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/

import semver from "semver";
import semver, { SemVer } from "semver";
import { appSemVer, isProduction } from "../common/vars";
import type { LensExtensionManifest } from "./lens-extension";

export function isCompatibleExtension(manifest: LensExtensionManifest): boolean {
if (manifest.engines?.lens) {
/* include Lens's prerelease tag in the matching so the extension's compatibility is not limited by it */
return semver.satisfies(appSemVer, manifest.engines.lens, { includePrerelease: true });
export function rawIsCompatibleExtension(version: SemVer): (manifest: LensExtensionManifest) => boolean {
const { major, minor, patch, prerelease: oldPrelease } = version;
let prerelease = "";

if (oldPrelease.length > 0) {
const [first] = oldPrelease;

if (first === "alpha" || first === "beta" || first === "rc") {
/**
* Strip the build IDs and "latest" prerelease tag as that is not really
* a part of API version
*/
prerelease = `-${oldPrelease.slice(0, 2).join(".")}`;
}
}

return false;
/**
* We unfortunately have to format as string because the constructor only
* takes an instance or a string.
*/
const strippedVersion = new SemVer(`${major}.${minor}.${patch}${prerelease}`, { includePrerelease: true });

return (manifest: LensExtensionManifest): boolean => {
if (manifest.engines?.lens) {
/**
* include Lens's prerelease tag in the matching so the extension's
* compatibility is not limited by it
*/
return semver.satisfies(strippedVersion, manifest.engines.lens, { includePrerelease: true });
}

return false;
};
}

export const isCompatibleExtension = rawIsCompatibleExtension(appSemVer);

export function isCompatibleBundledExtension(manifest: LensExtensionManifest): boolean {
return !isProduction || manifest.version === appSemVer.raw;
}
Loading

0 comments on commit e8d8f8f

Please sign in to comment.