Merge pull request #2293 from mantis-toboggan-md/workload-service

fix endpoints table formatter
This commit is contained in:
Vincent Fiduccia 2021-02-08 09:55:10 -07:00 committed by GitHub
commit 5498858b09
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
9 changed files with 114 additions and 83 deletions

View File

@ -1796,6 +1796,7 @@ serviceTypes:
nodeport: Node Port
servicesPage:
anyNode: Any Node
labelsAnnotations:
label: Labels & Annotations
affinity:

View File

@ -1,4 +1,5 @@
<script>
import { NODE } from '@/config/types';
export default {
props: {
@ -17,49 +18,54 @@ export default {
},
computed: {
nodes() {
return this.$store.getters['cluster/all'](NODE);
},
// value may be JSON from "field.cattle.io/publicEndpoints" label
parsed() {
const nodes = this.nodes;
const nodeWithExternal = nodes.find(node => !!node.externalIp) || {};
const externalIp = nodeWithExternal.externalIp;
if ( this.value && this.value.length ) {
let out ;
try {
out = JSON.parse(this.value);
} catch (err) {
return this.value[0];
}
return out;
}
return null;
},
bestLink() {
if (this.parsed && this.parsed.length ) {
if (this.parsed[0].addresses) {
out.forEach((endpoint) => {
let protocol = 'http';
if (this.parsed[0].port === 443) {
if (endpoint.port === 443) {
protocol = 'https';
}
return `${ protocol }://${ this.parsed[0].addresses[0] }:${ this.parsed[0].port }`;
if (endpoint.addresses) {
endpoint.link = `${ protocol }://${ endpoint.addresses[0] }:${ endpoint.port }`;
} else if (externalIp) {
endpoint.link = `${ protocol }://${ externalIp }:${ endpoint.port }`;
} else {
endpoint.display = `[${ this.t('servicesPage.anyNode') }]:${ endpoint.port }`;
}
});
return out;
} catch (err) {
return this.value[0];
}
}
return this.parsed;
} else {
return null;
}
},
protocol() {
const link = this.bestLink;
const { parsed } = this;
if ( link) {
if ( parsed) {
if (this.parsed[0].protocol) {
return this.parsed[0].protocol;
}
const match = link.match(/^([^:]+):\/\//);
const match = parsed.match(/^([^:]+):\/\//);
if ( match ) {
return match[1];
@ -76,11 +82,18 @@ export default {
<template>
<span>
<a v-if="bestLink" :href="bestLink" target="_blank" rel="nofollow noopener noreferrer">
<span v-if="parsed[0].port">{{ parsed[0].port }}/</span>{{ protocol }}
<template v-for="endpoint in parsed">
<span v-if="endpoint.display" :key="endpoint.display" class="block">{{ endpoint.display }}</span>
<a
v-else
:key="endpoint.link"
class="block"
:href="endpoint.link"
target="_blank"
rel="nofollow noopener noreferrer"
>
<span v-if="endpoint.port">{{ endpoint.port }}/</span>{{ endpoint.protocol }}
</a>
<span v-else class="text-muted">
&mdash;
</span>
</template>
</span>
</template>

View File

@ -1,7 +1,7 @@
<script>
import { isV4Format, isV6Format } from 'ip';
import CopyToClipboard from '@/components/CopyToClipboard';
import { mapGetters } from 'vuex';
export default {
components: { CopyToClipboard },
props: {
@ -13,7 +13,8 @@ export default {
computed: {
showBoth() {
return this.row.internalIp !== this.row.externalIp;
}
},
...mapGetters({ t: 'i18n/t' })
},
methods: {
isIp(ip) {
@ -29,7 +30,7 @@ export default {
{{ row.externalIp }} <CopyToClipboard label-as="tooltip" :text="row.externalIp" class="icon-btn" action-color="bg-transparent" />
</template>
<template v-else>
{{ t('internalExternalIp.none') }}
{{ t('internalExternalIP.none') }}
</template>
<template v-if="showBoth">
@ -37,7 +38,7 @@ export default {
/ {{ row.internalIp }} <CopyToClipboard label-as="tooltip" :text="row.internalIp" class="icon-btn" action-color="bg-transparent" />
</template>
<template v-else>
{{ t('internalExternalIp.none') }}
{{ t('internalExternalIP.none') }}
</template>
</template>
</span>

View File

@ -1,8 +1,8 @@
<script>
import isEmpty from 'lodash/isEmpty';
import { CATTLE_PUBLIC_ENDPOINTS } from '@/config/labels-annotations';
import has from 'lodash/has';
import Endpoints from '@/components/formatter/Endpoints';
import has from 'lodash/has';
export default {
components: { Endpoints },
@ -31,6 +31,7 @@ export default {
return false;
},
parsed() {
const { row, hasPublic } = this;
const {

View File

@ -1,26 +0,0 @@
<script>
export default {
props: {
value: {
type: String,
required: true
}
},
data() {
const endpoints = this.value.split(',');
return { endpoints };
}
};
</script>
<template>
<span>
<template v-for="endpoint in endpoints">
<span v-if="endpoint==='<none>'" :key="endpoint">{{ endpoint }}</span>
<a v-else :key="endpoint" rel="nofollow noopener noreferrer" target="_blank" :href="`//${endpoint}`">{{ endpoint }}</a>
<br :key="endpoint+'br'" />
</template>
</span>
</template>

View File

@ -1,3 +1,4 @@
import { CATTLE_PUBLIC_ENDPOINTS } from '@/config/labels-annotations';
import { NODE as NODE_TYPE } from '@/config/types';
// Note: 'id' is always the last sort, so you don't have to specify it here.
@ -600,8 +601,9 @@ export const WORKLOAD_IMAGES = { ...POD_IMAGES, value: '' };
export const WORKLOAD_ENDPOINTS = {
name: 'workloadEndpoints',
labelKey: 'tableHeaders.endpoints',
value: 'endpoints',
formatter: 'WorkloadEndpoints'
value: `$['metadata']['annotations']['${ CATTLE_PUBLIC_ENDPOINTS }']`,
formatter: 'Endpoints',
dashIfEmpty: true,
};
export const FLEET_SUMMARY = {

43
list/service.vue Normal file
View File

@ -0,0 +1,43 @@
<script>
import ResourceTable from '@/components/ResourceTable';
import Loading from '@/components/Loading';
import { NODE } from '@/config/types';
import { allHash } from '@/utils/promise';
export default {
name: 'ListService',
components: { Loading, ResourceTable },
// fetch nodes before loading this page, as they may be referenced in the Target table column
async fetch() {
const store = this.$store;
const inStore = store.getters['currentProduct'].inStore;
let hasNodes = false;
try {
const schema = store.getters[`${ inStore }/schemaFor`](NODE);
if (schema) {
hasNodes = true;
}
} catch {}
const hash = { rows: store.dispatch(`${ inStore }/findAll`, { type: this.$attrs.resource }) };
if (hasNodes) {
hash.nodes = store.dispatch(`${ inStore }/findAll`, { type: NODE });
}
const res = await allHash(hash);
this.rows = res.rows;
},
data() {
return { rows: [] };
}
};
</script>
<template>
<Loading v-if="$fetchState.pending" />
<ResourceTable v-else :schema="$attrs.schema" :rows="rows" :headers="$attrs.headers" :group-by="$attrs.groupBy" />
</template>

View File

@ -1,6 +1,6 @@
<script>
import ResourceTable from '@/components/ResourceTable';
import { WORKLOAD_TYPES, SCHEMA, ENDPOINTS } from '@/config/types';
import { WORKLOAD_TYPES, SCHEMA, NODE } from '@/config/types';
import Loading from '@/components/Loading';
const schema = {
@ -18,7 +18,13 @@ export default {
components: { Loading, ResourceTable },
async fetch() {
this.$store.dispatch('cluster/findAll', { type: ENDPOINTS });
try {
const schema = this.$store.getters[`cluster/schemaFor`](NODE);
if (schema) {
this.$store.dispatch('cluster/findAll', { type: NODE });
}
} catch {}
let resources;

View File

@ -1,7 +1,7 @@
import { insertAt } from '@/utils/array';
import { TARGET_WORKLOADS, TIMESTAMP, UI_MANAGED } from '@/config/labels-annotations';
import { WORKLOAD_TYPES, POD, ENDPOINTS, SERVICE } from '@/config/types';
import { get, set } from '@/utils/object';
import { WORKLOAD_TYPES, POD, SERVICE } from '@/config/types';
import { clone, get, set } from '@/utils/object';
import day from 'dayjs';
import { _CREATE } from '@/config/query-params';
@ -286,18 +286,6 @@ export default {
};
},
endpoints() {
const endpoints = this.$rootGetters['cluster/byId'](ENDPOINTS, this.id);
if (endpoints) {
const out = endpoints.metadata.fields[1];
return out;
}
},
// 30422
// create clusterip, nodeport, loadbalancer services from container port spec
servicesFromContainerPorts() {
return async(mode) => {
@ -391,10 +379,12 @@ export default {
case 'NodePort':
nodePort.spec.ports.push(portSpec);
break;
case 'LoadBalancer':
portSpec.port = port._lbPort;
loadBalancer.spec.ports.push(portSpec);
break;
case 'LoadBalancer': {
const lbPort = clone(portSpec);
lbPort.port = port._lbPort;
loadBalancer.spec.ports.push(lbPort);
break; }
default:
break;
}