mirror of https://github.com/rancher/dashboard.git
215 lines
5.3 KiB
JavaScript
215 lines
5.3 KiB
JavaScript
import { CAPI, NODE } from '@/config/types';
|
|
import { CAPI as CAPI_LABELS, MACHINE_ROLES } from '@/config/labels-annotations';
|
|
import { NAME as EXPLORER } from '@/config/product/explorer';
|
|
import { listNodeRoles } from '@/models/cluster/node';
|
|
import { escapeHtml } from '@/utils/string';
|
|
import { insertAt, findBy } from '@/utils/array';
|
|
import { get } from '@/utils/object';
|
|
import { downloadUrl } from '@/utils/download';
|
|
import SteveModel from '@/plugins/steve/steve-class';
|
|
|
|
export default class CapiMachine extends SteveModel {
|
|
get _availableActions() {
|
|
const out = super._availableActions;
|
|
|
|
const openSsh = {
|
|
action: 'openSsh',
|
|
enabled: !!this.links.shell && this.isRunning,
|
|
icon: 'icon icon-fw icon-chevron-right',
|
|
label: 'SSH Shell',
|
|
};
|
|
const downloadKeys = {
|
|
action: 'downloadKeys',
|
|
enabled: !!this.links.sshkeys,
|
|
icon: 'icon icon-fw icon-download',
|
|
label: this.t('node.actions.downloadSSHKey'),
|
|
};
|
|
const forceRemove = {
|
|
action: 'toggleForceRemoveModal',
|
|
altAction: 'forceMachineRemove',
|
|
enabled: !!this.isRemoveForceable,
|
|
label: this.t('node.actions.forceDelete'),
|
|
icon: 'icon icon-trash',
|
|
};
|
|
const scaleDown = {
|
|
action: 'toggleScaleDownModal',
|
|
bulkAction: 'toggleScaleDownModal',
|
|
enabled: !!this.canScaleDown,
|
|
icon: 'icon icon-minus icon-fw',
|
|
label: this.t('node.actions.scaleDown'),
|
|
bulkable: true
|
|
};
|
|
|
|
insertAt(out, 0, { divider: true });
|
|
insertAt(out, 0, downloadKeys);
|
|
insertAt(out, 0, openSsh);
|
|
insertAt(out, 0, scaleDown);
|
|
insertAt(out, 0, forceRemove);
|
|
|
|
return out;
|
|
}
|
|
|
|
get canClone() {
|
|
return false;
|
|
}
|
|
|
|
openSsh() {
|
|
this.$dispatch('wm/open', {
|
|
id: `${ this.id }-ssh`,
|
|
label: this.nameDisplay,
|
|
icon: 'terminal',
|
|
component: 'MachineSsh',
|
|
attrs: { machine: this, pod: {} }
|
|
}, { root: true });
|
|
}
|
|
|
|
downloadKeys() {
|
|
downloadUrl(this.links.sshkeys);
|
|
}
|
|
|
|
toggleForceRemoveModal(resources = this) {
|
|
this.$dispatch('promptModal', {
|
|
resources,
|
|
component: 'ForceMachineRemoveDialog'
|
|
});
|
|
}
|
|
|
|
async forceMachineRemove() {
|
|
const machine = await this.machineRef();
|
|
|
|
machine.setAnnotation(CAPI_LABELS.FORCE_MACHINE_REMOVE, 'true');
|
|
await machine.save();
|
|
}
|
|
|
|
toggleScaleDownModal(resources = this) {
|
|
this.$dispatch('promptModal', {
|
|
resources,
|
|
component: 'ScaleMachineDownDialog',
|
|
modalWidth: '450px'
|
|
});
|
|
}
|
|
|
|
async machineRef() {
|
|
const ref = this.spec.infrastructureRef;
|
|
const id = `${ ref.namespace }/${ ref.name }`;
|
|
const kind = `rke-machine.cattle.io.${ ref.kind.toLowerCase() }`;
|
|
|
|
return await this.$dispatch('find', { type: kind, id });
|
|
}
|
|
|
|
get cluster() {
|
|
if ( !this.spec.clusterName ) {
|
|
return null;
|
|
}
|
|
|
|
const clusterId = `${ this.metadata.namespace }/${ this.spec.clusterName }`;
|
|
|
|
const cluster = this.$rootGetters['management/byId'](CAPI.RANCHER_CLUSTER, clusterId);
|
|
|
|
return cluster;
|
|
}
|
|
|
|
get poolName() {
|
|
return this.metadata?.labels?.[ CAPI_LABELS.DEPLOYMENT_NAME ] || '';
|
|
}
|
|
|
|
get poolId() {
|
|
const poolId = `${ this.metadata.namespace }/${ this.poolName }`;
|
|
|
|
return poolId;
|
|
}
|
|
|
|
get pool() {
|
|
return this.$rootGetters['management/byId'](CAPI.MACHINE_DEPLOYMENT, this.poolId);
|
|
}
|
|
|
|
get operatingSystem() {
|
|
return this.metadata?.labels['cattle.io/os'] || 'linux';
|
|
}
|
|
|
|
get kubeNodeDetailLocation() {
|
|
const kubeId = this.status?.nodeRef?.name;
|
|
const cluster = this.cluster?.status?.clusterName;
|
|
|
|
if ( kubeId && cluster ) {
|
|
return {
|
|
name: 'c-cluster-product-resource-id',
|
|
params: {
|
|
cluster: this.cluster.status.clusterName,
|
|
product: EXPLORER,
|
|
resource: NODE,
|
|
id: kubeId
|
|
}
|
|
};
|
|
}
|
|
|
|
return kubeId;
|
|
}
|
|
|
|
get groupByLabel() {
|
|
const name = this.cluster?.nameDisplay || this.spec.clusterName;
|
|
|
|
return this.$rootGetters['i18n/t']('resourceTable.groupLabel.cluster', { name: escapeHtml(name) });
|
|
}
|
|
|
|
get labels() {
|
|
return this.metadata?.labels || {};
|
|
}
|
|
|
|
get isWorker() {
|
|
return `${ this.labels[MACHINE_ROLES.WORKER] }` === 'true';
|
|
}
|
|
|
|
get isControlPlane() {
|
|
return `${ this.labels[MACHINE_ROLES.CONTROL_PLANE] }` === 'true';
|
|
}
|
|
|
|
get isEtcd() {
|
|
return `${ this.labels[MACHINE_ROLES.ETCD] }` === 'true';
|
|
}
|
|
|
|
get isRemoveForceable() {
|
|
const conditions = get(this, 'status.conditions');
|
|
const reasonMessage = (findBy(conditions, 'type', 'InfrastructureReady') || {}).reason;
|
|
|
|
if (reasonMessage === 'DeleteError') {
|
|
return true;
|
|
}
|
|
|
|
return null;
|
|
}
|
|
|
|
get canScaleDown() {
|
|
if (!this.canUpdate || !this.pool?.canUpdate) {
|
|
return false;
|
|
}
|
|
|
|
if (!this.isControlPlane) {
|
|
return true;
|
|
}
|
|
|
|
let foundControlPlane;
|
|
|
|
for (const m of this.cluster.machines) {
|
|
if (m.isControlPlane) {
|
|
if (foundControlPlane) {
|
|
return true;
|
|
}
|
|
foundControlPlane = true;
|
|
}
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
get roles() {
|
|
const { isControlPlane, isWorker, isEtcd } = this;
|
|
|
|
return listNodeRoles(isControlPlane, isWorker, isEtcd, this.t('generic.all'));
|
|
}
|
|
|
|
get isRunning() {
|
|
return this.status.phase === 'Running';
|
|
}
|
|
}
|