mirror of
https://github.com/lensapp/lens.git
synced 2025-05-20 05:10:56 +00:00
Merge branch 'master' into upgrade-typedoc-to-0.20
This commit is contained in:
commit
fa2f145600
5
.github/workflows/test.yml
vendored
5
.github/workflows/test.yml
vendored
@ -20,6 +20,11 @@ jobs:
|
|||||||
with:
|
with:
|
||||||
fetch-depth: 0
|
fetch-depth: 0
|
||||||
|
|
||||||
|
- name: Add the current IP address, long hostname and short hostname record to /etc/hosts file
|
||||||
|
if: runner.os == 'Linux'
|
||||||
|
run: |
|
||||||
|
echo -e "$(ip addr show eth0 | grep "inet\b" | awk '{print $2}' | cut -d/ -f1)\t$(hostname -f) $(hostname -s)" | sudo tee -a /etc/hosts
|
||||||
|
|
||||||
- name: Using Node.js ${{ matrix.node-version }}
|
- name: Using Node.js ${{ matrix.node-version }}
|
||||||
uses: actions/setup-node@v1
|
uses: actions/setup-node@v1
|
||||||
with:
|
with:
|
||||||
|
|||||||
@ -1,9 +1,9 @@
|
|||||||
import { LensRendererExtension, Store, Interface, Component } from "@k8slens/extensions";
|
import { LensRendererExtension, Interface, Component, Catalog} from "@k8slens/extensions";
|
||||||
import { MetricsFeature } from "./src/metrics-feature";
|
import { MetricsFeature } from "./src/metrics-feature";
|
||||||
|
|
||||||
export default class ClusterMetricsFeatureExtension extends LensRendererExtension {
|
export default class ClusterMetricsFeatureExtension extends LensRendererExtension {
|
||||||
onActivate() {
|
onActivate() {
|
||||||
const category = Store.catalogCategories.getForGroupKind<Store.KubernetesClusterCategory>("entity.k8slens.dev", "KubernetesCluster");
|
const category = Catalog.catalogCategories.getForGroupKind<Catalog.KubernetesClusterCategory>("entity.k8slens.dev", "KubernetesCluster");
|
||||||
|
|
||||||
if (!category) {
|
if (!category) {
|
||||||
return;
|
return;
|
||||||
@ -12,7 +12,7 @@ export default class ClusterMetricsFeatureExtension extends LensRendererExtensio
|
|||||||
category.on("contextMenuOpen", this.clusterContextMenuOpen.bind(this));
|
category.on("contextMenuOpen", this.clusterContextMenuOpen.bind(this));
|
||||||
}
|
}
|
||||||
|
|
||||||
async clusterContextMenuOpen(cluster: Store.KubernetesCluster, ctx: Interface.CatalogEntityContextMenuContext) {
|
async clusterContextMenuOpen(cluster: Catalog.KubernetesCluster, ctx: Interface.CatalogEntityContextMenuContext) {
|
||||||
if (!cluster.status.active) {
|
if (!cluster.status.active) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,4 +1,4 @@
|
|||||||
import { ClusterFeature, Store, K8sApi } from "@k8slens/extensions";
|
import { ClusterFeature, Catalog, K8sApi } from "@k8slens/extensions";
|
||||||
import semver from "semver";
|
import semver from "semver";
|
||||||
import * as path from "path";
|
import * as path from "path";
|
||||||
|
|
||||||
@ -49,7 +49,7 @@ export class MetricsFeature extends ClusterFeature.Feature {
|
|||||||
storageClass: null,
|
storageClass: null,
|
||||||
};
|
};
|
||||||
|
|
||||||
async install(cluster: Store.KubernetesCluster): Promise<void> {
|
async install(cluster: Catalog.KubernetesCluster): Promise<void> {
|
||||||
// Check if there are storageclasses
|
// Check if there are storageclasses
|
||||||
const storageClassApi = K8sApi.forCluster(cluster, K8sApi.StorageClass);
|
const storageClassApi = K8sApi.forCluster(cluster, K8sApi.StorageClass);
|
||||||
const scs = await storageClassApi.list();
|
const scs = await storageClassApi.list();
|
||||||
@ -62,11 +62,11 @@ export class MetricsFeature extends ClusterFeature.Feature {
|
|||||||
super.applyResources(cluster, path.join(__dirname, "../resources/"));
|
super.applyResources(cluster, path.join(__dirname, "../resources/"));
|
||||||
}
|
}
|
||||||
|
|
||||||
async upgrade(cluster: Store.KubernetesCluster): Promise<void> {
|
async upgrade(cluster: Catalog.KubernetesCluster): Promise<void> {
|
||||||
return this.install(cluster);
|
return this.install(cluster);
|
||||||
}
|
}
|
||||||
|
|
||||||
async updateStatus(cluster: Store.KubernetesCluster): Promise<ClusterFeature.FeatureStatus> {
|
async updateStatus(cluster: Catalog.KubernetesCluster): Promise<ClusterFeature.FeatureStatus> {
|
||||||
try {
|
try {
|
||||||
const statefulSet = K8sApi.forCluster(cluster, K8sApi.StatefulSet);
|
const statefulSet = K8sApi.forCluster(cluster, K8sApi.StatefulSet);
|
||||||
const prometheus = await statefulSet.get({name: "prometheus", namespace: "lens-metrics"});
|
const prometheus = await statefulSet.get({name: "prometheus", namespace: "lens-metrics"});
|
||||||
@ -87,7 +87,7 @@ export class MetricsFeature extends ClusterFeature.Feature {
|
|||||||
return this.status;
|
return this.status;
|
||||||
}
|
}
|
||||||
|
|
||||||
async uninstall(cluster: Store.KubernetesCluster): Promise<void> {
|
async uninstall(cluster: Catalog.KubernetesCluster): Promise<void> {
|
||||||
const namespaceApi = K8sApi.forCluster(cluster, K8sApi.Namespace);
|
const namespaceApi = K8sApi.forCluster(cluster, K8sApi.Namespace);
|
||||||
const clusterRoleBindingApi = K8sApi.forCluster(cluster, K8sApi.ClusterRoleBinding);
|
const clusterRoleBindingApi = K8sApi.forCluster(cluster, K8sApi.ClusterRoleBinding);
|
||||||
const clusterRoleApi = K8sApi.forCluster(cluster, K8sApi.ClusterRole);
|
const clusterRoleApi = K8sApi.forCluster(cluster, K8sApi.ClusterRole);
|
||||||
|
|||||||
@ -1,4 +1,4 @@
|
|||||||
import { EventBus, Util, Store, App } from "@k8slens/extensions";
|
import { EventBus, Util, Catalog, App } from "@k8slens/extensions";
|
||||||
import ua from "universal-analytics";
|
import ua from "universal-analytics";
|
||||||
import Analytics from "analytics-node";
|
import Analytics from "analytics-node";
|
||||||
import { machineIdSync } from "node-machine-id";
|
import { machineIdSync } from "node-machine-id";
|
||||||
@ -102,7 +102,7 @@ export class Tracker extends Util.Singleton {
|
|||||||
}
|
}
|
||||||
|
|
||||||
protected reportData() {
|
protected reportData() {
|
||||||
const clustersList = Store.catalogEntities.getItemsForApiKind<Store.KubernetesCluster>("entity.k8slens.dev/v1alpha1", "KubernetesCluster");
|
const clustersList = Catalog.catalogEntities.getItemsForApiKind<Catalog.KubernetesCluster>("entity.k8slens.dev/v1alpha1", "KubernetesCluster");
|
||||||
|
|
||||||
this.event("generic-data", "report", {
|
this.event("generic-data", "report", {
|
||||||
appVersion: App.version,
|
appVersion: App.version,
|
||||||
@ -117,7 +117,7 @@ export class Tracker extends Util.Singleton {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
protected reportClusterData(cluster: Store.KubernetesCluster) {
|
protected reportClusterData(cluster: Catalog.KubernetesCluster) {
|
||||||
this.event("cluster-data", "report", {
|
this.event("cluster-data", "report", {
|
||||||
id: cluster.metadata.id,
|
id: cluster.metadata.id,
|
||||||
managed: cluster.metadata.source !== "local",
|
managed: cluster.metadata.source !== "local",
|
||||||
|
|||||||
@ -3,7 +3,7 @@ import path from "path";
|
|||||||
import hb from "handlebars";
|
import hb from "handlebars";
|
||||||
import { observable } from "mobx";
|
import { observable } from "mobx";
|
||||||
import { ResourceApplier } from "../main/resource-applier";
|
import { ResourceApplier } from "../main/resource-applier";
|
||||||
import { KubernetesCluster } from "./core-api/stores";
|
import { KubernetesCluster } from "./core-api/catalog";
|
||||||
import logger from "../main/logger";
|
import logger from "../main/logger";
|
||||||
import { app } from "electron";
|
import { app } from "electron";
|
||||||
import { requestMain } from "../common/ipc";
|
import { requestMain } from "../common/ipc";
|
||||||
|
|||||||
@ -3,6 +3,9 @@ import { computed } from "mobx";
|
|||||||
import { CatalogEntity } from "../../common/catalog-entity";
|
import { CatalogEntity } from "../../common/catalog-entity";
|
||||||
import { catalogEntityRegistry as registry } from "../../common/catalog-entity-registry";
|
import { catalogEntityRegistry as registry } from "../../common/catalog-entity-registry";
|
||||||
|
|
||||||
|
export { catalogCategoryRegistry as catalogCategories } from "../../common/catalog-category-registry";
|
||||||
|
export * from "../../common/catalog-entities";
|
||||||
|
|
||||||
export class CatalogEntityRegistry {
|
export class CatalogEntityRegistry {
|
||||||
@computed getItemsForApiKind<T extends CatalogEntity>(apiVersion: string, kind: string): T[] {
|
@computed getItemsForApiKind<T extends CatalogEntity>(apiVersion: string, kind: string): T[] {
|
||||||
return registry.getItemsForApiKind<T>(apiVersion, kind);
|
return registry.getItemsForApiKind<T>(apiVersion, kind);
|
||||||
|
|||||||
@ -9,10 +9,12 @@ import * as Store from "./stores";
|
|||||||
import * as Util from "./utils";
|
import * as Util from "./utils";
|
||||||
import * as ClusterFeature from "./cluster-feature";
|
import * as ClusterFeature from "./cluster-feature";
|
||||||
import * as Interface from "../interfaces";
|
import * as Interface from "../interfaces";
|
||||||
|
import * as Catalog from "./catalog";
|
||||||
|
|
||||||
export {
|
export {
|
||||||
App,
|
App,
|
||||||
EventBus,
|
EventBus,
|
||||||
|
Catalog,
|
||||||
ClusterFeature,
|
ClusterFeature,
|
||||||
Interface,
|
Interface,
|
||||||
Store,
|
Store,
|
||||||
|
|||||||
@ -1,4 +1 @@
|
|||||||
export { ExtensionStore } from "../extension-store";
|
export { ExtensionStore } from "../extension-store";
|
||||||
export { KubernetesCluster, KubernetesClusterCategory } from "../../common/catalog-entities/kubernetes-cluster";
|
|
||||||
export { catalogCategoryRegistry as catalogCategories } from "../../common/catalog-category-registry";
|
|
||||||
export { catalogEntities } from "./catalog";
|
|
||||||
|
|||||||
@ -15,8 +15,14 @@ export interface KubeObjectListLayoutProps extends ItemListLayoutProps {
|
|||||||
dependentStores?: KubeObjectStore[];
|
dependentStores?: KubeObjectStore[];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const defaultProps: Partial<KubeObjectListLayoutProps> = {
|
||||||
|
onDetails: (item: KubeObject) => showDetails(item.selfLink),
|
||||||
|
};
|
||||||
|
|
||||||
@observer
|
@observer
|
||||||
export class KubeObjectListLayout extends React.Component<KubeObjectListLayoutProps> {
|
export class KubeObjectListLayout extends React.Component<KubeObjectListLayoutProps> {
|
||||||
|
static defaultProps = defaultProps as object;
|
||||||
|
|
||||||
@computed get selectedItem() {
|
@computed get selectedItem() {
|
||||||
return this.props.store.getByPath(kubeSelectedUrlParam.get());
|
return this.props.store.getByPath(kubeSelectedUrlParam.get());
|
||||||
}
|
}
|
||||||
@ -33,14 +39,6 @@ export class KubeObjectListLayout extends React.Component<KubeObjectListLayoutPr
|
|||||||
]);
|
]);
|
||||||
}
|
}
|
||||||
|
|
||||||
onDetails = (item: KubeObject) => {
|
|
||||||
if (this.props.onDetails) {
|
|
||||||
this.props.onDetails(item);
|
|
||||||
} else {
|
|
||||||
showDetails(item.selfLink);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
render() {
|
render() {
|
||||||
const { className, store, items = store.contextItems, ...layoutProps } = this.props;
|
const { className, store, items = store.contextItems, ...layoutProps } = this.props;
|
||||||
|
|
||||||
@ -52,10 +50,7 @@ export class KubeObjectListLayout extends React.Component<KubeObjectListLayoutPr
|
|||||||
items={items}
|
items={items}
|
||||||
preloadStores={false} // loading handled in kubeWatchApi.subscribeStores()
|
preloadStores={false} // loading handled in kubeWatchApi.subscribeStores()
|
||||||
detailsItem={this.selectedItem}
|
detailsItem={this.selectedItem}
|
||||||
onDetails={this.onDetails}
|
renderItemMenu={(item: KubeObject) => <KubeObjectMenu object={item} />} // safe because we are dealing with KubeObjects here
|
||||||
renderItemMenu={(item) => {
|
|
||||||
return <KubeObjectMenu object={item}/>;
|
|
||||||
}}
|
|
||||||
/>
|
/>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
@ -7,13 +7,13 @@ import { hideDetails } from "./kube-object-details";
|
|||||||
import { apiManager } from "../../api/api-manager";
|
import { apiManager } from "../../api/api-manager";
|
||||||
import { kubeObjectMenuRegistry } from "../../../extensions/registries/kube-object-menu-registry";
|
import { kubeObjectMenuRegistry } from "../../../extensions/registries/kube-object-menu-registry";
|
||||||
|
|
||||||
export interface KubeObjectMenuProps<T extends KubeObject = any> extends MenuActionsProps {
|
export interface KubeObjectMenuProps<T> extends MenuActionsProps {
|
||||||
object: T;
|
object: T | null | undefined;
|
||||||
editable?: boolean;
|
editable?: boolean;
|
||||||
removable?: boolean;
|
removable?: boolean;
|
||||||
}
|
}
|
||||||
|
|
||||||
export class KubeObjectMenu extends React.Component<KubeObjectMenuProps> {
|
export class KubeObjectMenu<T extends KubeObject> extends React.Component<KubeObjectMenuProps<T>> {
|
||||||
get store() {
|
get store() {
|
||||||
const { object } = this.props;
|
const { object } = this.props;
|
||||||
|
|
||||||
@ -52,23 +52,35 @@ export class KubeObjectMenu extends React.Component<KubeObjectMenuProps> {
|
|||||||
@autobind()
|
@autobind()
|
||||||
renderRemoveMessage() {
|
renderRemoveMessage() {
|
||||||
const { object } = this.props;
|
const { object } = this.props;
|
||||||
const resourceKind = object.kind;
|
|
||||||
const resourceName = object.getName();
|
if (!object) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<p>Remove {resourceKind} <b>{resourceName}</b>?</p>
|
<p>Remove {object.kind} <b>{object.getName()}</b>?</p>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
getMenuItems(object: T): React.ReactChild[] {
|
||||||
|
if (!object) {
|
||||||
|
return [];
|
||||||
|
}
|
||||||
|
|
||||||
|
return kubeObjectMenuRegistry
|
||||||
|
.getItemsForKind(object.kind, object.apiVersion)
|
||||||
|
.map(({components: { MenuItem }}, index) => (
|
||||||
|
<MenuItem
|
||||||
|
object={object}
|
||||||
|
key={`menu-item-${index}`}
|
||||||
|
toolbar={toolbar}
|
||||||
|
/>
|
||||||
|
));
|
||||||
|
}
|
||||||
|
|
||||||
render() {
|
render() {
|
||||||
const { remove, update, renderRemoveMessage, isEditable, isRemovable } = this;
|
const { remove, update, renderRemoveMessage, isEditable, isRemovable } = this;
|
||||||
const { className, object, editable, removable, toolbar, ...menuProps } = this.props;
|
const { className, object, editable, removable, ...menuProps } = this.props;
|
||||||
|
|
||||||
if (!object) return null;
|
|
||||||
|
|
||||||
const menuItems = kubeObjectMenuRegistry.getItemsForKind(object.kind, object.apiVersion).map((item, index) => {
|
|
||||||
return <item.components.MenuItem object={object} key={`menu-item-${index}`} toolbar={toolbar} />;
|
|
||||||
});
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<MenuActions
|
<MenuActions
|
||||||
@ -76,10 +88,9 @@ export class KubeObjectMenu extends React.Component<KubeObjectMenuProps> {
|
|||||||
updateAction={isEditable ? update : undefined}
|
updateAction={isEditable ? update : undefined}
|
||||||
removeAction={isRemovable ? remove : undefined}
|
removeAction={isRemovable ? remove : undefined}
|
||||||
removeConfirmationMessage={renderRemoveMessage}
|
removeConfirmationMessage={renderRemoveMessage}
|
||||||
toolbar={toolbar}
|
|
||||||
{...menuProps}
|
{...menuProps}
|
||||||
>
|
>
|
||||||
{menuItems}
|
{this.getMenuItems(object)}
|
||||||
</MenuActions>
|
</MenuActions>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user