mirror of https://github.com/rancher/dashboard.git
213 lines
6.1 KiB
JavaScript
213 lines
6.1 KiB
JavaScript
import find from 'lodash/find';
|
|
import { POD } from '@shell/config/types';
|
|
import SteveModel from '@shell/plugins/steve/steve-class';
|
|
import { parse } from '@shell/utils/selector';
|
|
|
|
// i18n-uses servicesPage.serviceTypes.clusterIp.*, servicesPage.serviceTypes.externalName.*, servicesPage.serviceTypes.headless.*
|
|
// i18n-uses servicesPage.serviceTypes.loadBalancer.*, servicesPage.serviceTypes.nodePort.*
|
|
export const DEFAULT_SERVICE_TYPES = [
|
|
{
|
|
id: 'ClusterIP',
|
|
label: 'servicesPage.serviceTypes.clusterIp.label',
|
|
description: 'servicesPage.serviceTypes.clusterIp.description',
|
|
bannerAbbrv: 'servicesPage.serviceTypes.clusterIp.abbrv',
|
|
},
|
|
{
|
|
id: 'ExternalName',
|
|
label: 'servicesPage.serviceTypes.externalName.label',
|
|
description: 'servicesPage.serviceTypes.externalName.description',
|
|
bannerAbbrv: 'servicesPage.serviceTypes.externalName.abbrv',
|
|
},
|
|
{
|
|
id: 'Headless',
|
|
label: 'servicesPage.serviceTypes.headless.label',
|
|
description: 'servicesPage.serviceTypes.headless.description',
|
|
bannerAbbrv: 'servicesPage.serviceTypes.headless.abbrv',
|
|
},
|
|
{
|
|
id: 'LoadBalancer',
|
|
label: 'servicesPage.serviceTypes.loadBalancer.label',
|
|
description: 'servicesPage.serviceTypes.loadBalancer.description',
|
|
bannerAbbrv: 'servicesPage.serviceTypes.loadBalancer.abbrv',
|
|
},
|
|
{
|
|
id: 'NodePort',
|
|
label: 'servicesPage.serviceTypes.nodePort.label',
|
|
description: 'servicesPage.serviceTypes.nodePort.description',
|
|
bannerAbbrv: 'servicesPage.serviceTypes.nodePort.abbrv',
|
|
},
|
|
];
|
|
|
|
export const HEADLESS = (() => {
|
|
const headless = find(DEFAULT_SERVICE_TYPES, ['id', 'Headless']);
|
|
|
|
return headless.id;
|
|
})();
|
|
|
|
export const CLUSTERIP = (() => {
|
|
const clusterIp = find(DEFAULT_SERVICE_TYPES, ['id', 'ClusterIP']);
|
|
|
|
return clusterIp.id;
|
|
})();
|
|
|
|
export default class Service extends SteveModel {
|
|
get customValidationRules() {
|
|
return [
|
|
{
|
|
nullable: false,
|
|
path: 'metadata.name',
|
|
required: true,
|
|
translationKey: 'generic.name',
|
|
type: 'dnsLabel',
|
|
},
|
|
{
|
|
nullable: false,
|
|
path: 'spec',
|
|
required: true,
|
|
type: 'array',
|
|
validators: ['servicePort'],
|
|
},
|
|
{
|
|
nullable: true,
|
|
path: 'spec',
|
|
required: true,
|
|
type: 'string',
|
|
validators: ['clusterIp'],
|
|
},
|
|
{
|
|
nullable: true,
|
|
path: 'spec',
|
|
required: true,
|
|
type: 'array',
|
|
validators: ['externalName'],
|
|
},
|
|
];
|
|
}
|
|
|
|
get details() {
|
|
const out = [{
|
|
label: this.t('generic.type'),
|
|
content: this.serviceType?.id || this.serviceType,
|
|
}];
|
|
|
|
const {
|
|
clusterIP, externalName, sessionAffinity, loadBalancerIP
|
|
} = this.spec;
|
|
|
|
if (clusterIP) {
|
|
out.push({
|
|
label: this.t('servicesPage.serviceTypes.clusterIp.label'),
|
|
content: clusterIP,
|
|
});
|
|
}
|
|
|
|
if (this.serviceType === 'LoadBalancer') {
|
|
const statusIps = this.status.loadBalancer?.ingress?.map((ingress) => ingress.hostname || ingress.ip).join(', ');
|
|
|
|
const loadbalancerInfo = loadBalancerIP || statusIps || '';
|
|
|
|
if (loadbalancerInfo) {
|
|
out.push({
|
|
label: this.t('servicesPage.ips.loadBalancer.label'),
|
|
content: loadbalancerInfo
|
|
});
|
|
}
|
|
}
|
|
|
|
if (externalName) {
|
|
out.push({
|
|
label: this.t('servicesPage.serviceTypes.externalName.label'),
|
|
content: externalName,
|
|
});
|
|
}
|
|
|
|
if (sessionAffinity) {
|
|
out.push({
|
|
label: this.t('servicesPage.affinity.label'),
|
|
content: sessionAffinity,
|
|
});
|
|
}
|
|
|
|
return out;
|
|
}
|
|
|
|
get podRelationship() {
|
|
const { metadata:{ relationships = [] } } = this;
|
|
|
|
return (relationships || []).filter((relationship) => relationship.toType === POD)[0];
|
|
}
|
|
|
|
async fetchPods() {
|
|
if (!this.podRelationship) {
|
|
// If empty or not present, the service is assumed to have an external process managing its endpoints
|
|
return [];
|
|
}
|
|
|
|
return await this.$dispatch('findLabelSelector', {
|
|
type: POD,
|
|
matching: {
|
|
namespace: this.metadata.namespace,
|
|
labelSelector: { matchExpressions: parse(this.podRelationship?.selector) },
|
|
}
|
|
});
|
|
}
|
|
|
|
async unWatchPods() {
|
|
return await this.$dispatch('unwatch', { type: POD, all: true });
|
|
}
|
|
|
|
/**
|
|
* This getter expects a superset of workload pods to have been fetched already
|
|
*
|
|
* It assumes fetchPods has been called and should be used instead of the response of fetchPods
|
|
* (findAll --> findLabelSelector world results won't trigger change detection)
|
|
*/
|
|
get pods() {
|
|
if (this.podRelationship?.selector) {
|
|
return this.$getters['matchingLabelSelector'](POD, { matchExpressions: parse(this.podRelationship?.selector) }, this.metadata.namespace);
|
|
} else {
|
|
return [];
|
|
}
|
|
}
|
|
|
|
get serviceType() {
|
|
const serviceType = this.spec?.type;
|
|
const clusterIp = this.spec?.clusterIP;
|
|
const defaultService = find(DEFAULT_SERVICE_TYPES, ['id', CLUSTERIP]);
|
|
|
|
if (serviceType) {
|
|
if (serviceType === CLUSTERIP && clusterIp === 'None') {
|
|
return HEADLESS;
|
|
} else {
|
|
return serviceType;
|
|
}
|
|
}
|
|
|
|
return defaultService;
|
|
}
|
|
|
|
proxyUrl(scheme, port) {
|
|
const view = this.linkFor('view');
|
|
const idx = view.lastIndexOf(`/`);
|
|
|
|
return proxyUrlFromBase(view.slice(0, idx), scheme, this.metadata.name, port);
|
|
}
|
|
}
|
|
|
|
export function proxyUrlFromParts(clusterId, namespace, name, scheme, port, path) {
|
|
const base = `/k8s/clusters/${ escape(clusterId) }/api/v1/namespaces/${ escape(namespace) }/services`;
|
|
|
|
return proxyUrlFromBase(base, scheme, name, port, path);
|
|
}
|
|
|
|
export function proxyUrlFromBase(base, scheme, name, port, path) {
|
|
const schemaNamePort = (scheme ? `${ escape(scheme) }:` : '') + escape(name) + (port ? `:${ escape(port) }` : '');
|
|
|
|
const cleanPath = `/${ (path || '').replace(/^\/+/g, '') }`;
|
|
const cleanBase = base.replace(/\/+$/g, '');
|
|
|
|
const out = `${ cleanBase }/${ schemaNamePort }/proxy${ cleanPath }`;
|
|
|
|
return out;
|
|
}
|