open-consul/ui/packages/consul-ui/app/serializers/service-instance.js
John Cowen 493cda4bd7
ui: New search/sort/filtering bar for Node > ServiceInstances (#9326)
* Model layer changes to turn Node:ServiceInstances into hasMany

We tried to make something that feels a little like ember-data yet
not leave our approach of re-shaping the JSON directly from the
response.

1. We added transformHasManyResponse for re-shaping JSON for hasMany
relationships. we avoided the normalize word as ember-data serialize
methods usually return something JSON:API shaped and we distinctly don't
want to do that. Transform was the best word we could think of.

2. The integration tests across all of our models here feel very much
like those types of tests that aren't really testing much, or assert
too much to an extent that they get in the way rather than be of any
use. I'd very much like to move a lot of this to unit tests. Currently
most of the fingerprinting functionality is unit tested and these
integration tests were originally to give confidence that IDs and
related properties were being added correctly.

3. We've added a hasMany relationship, but not the corresponding
belongsTo - yet at least. We don't require the belongsTo right now, and
if we do  we can add it later.

* Integrate ServiceInstance search bar for Node:ServiceInstances

* Hide Node.Meta when on the Node:ServiceINstance page

We use a little string replace hack here for a human-like label, this is
soon to be replaced with proper i10n replacement

* Always ensure that a Namespace is set, and add comment explaining
2020-12-09 13:08:30 +00:00

112 lines
2.8 KiB
JavaScript

import Serializer from './application';
import { PRIMARY_KEY, SLUG_KEY } from 'consul-ui/models/service-instance';
export default class ServiceInstanceSerializer extends Serializer {
primaryKey = PRIMARY_KEY;
slugKey = SLUG_KEY;
hash = JSON.stringify;
extractUid(item) {
return this.hash([
item.Namespace || 'default',
item.Datacenter,
item.Node.Node,
item.Service.ID,
]);
}
transformHasManyResponseFromNode(node, item, checks) {
const serviceChecks = checks[item.ID] || [];
const statuses = serviceChecks.reduce(
(prev, item) => {
switch (item.Status) {
case 'passing':
prev.ChecksPassing.push(item);
break;
case 'warning':
prev.ChecksWarning.push(item);
break;
case 'critical':
prev.ChecksCritical.push(item);
break;
}
return prev;
},
{
ChecksPassing: [],
ChecksWarning: [],
ChecksCritical: [],
}
);
const instance = {
...statuses,
Service: item,
Checks: serviceChecks,
Node: {
Datacenter: node.Datacenter,
Namespace: node.Namespace,
ID: node.ID,
Node: node.Node,
Address: node.Address,
TaggedAddresses: node.TaggedAddresses,
Meta: node.Meta,
},
};
instance.uid = this.extractUid(instance);
return instance;
}
respondForQuery(respond, query) {
const body = super.respondForQuery(cb => {
return respond((headers, body) => {
if (body.length === 0) {
const e = new Error();
e.errors = [
{
status: '404',
title: 'Not found',
},
];
throw e;
}
body.forEach(item => {
item.Datacenter = query.dc;
item.Namespace = query.ns || 'default';
item.uid = this.extractUid(item);
});
return cb(headers, body);
});
}, query);
return body;
}
respondForQueryRecord(respond, query) {
return super.respondForQueryRecord(cb => {
return respond((headers, body) => {
body.forEach(item => {
item.Datacenter = query.dc;
item.Namespace = query.ns || 'default';
item.uid = this.extractUid(item);
});
body = body.find(function(item) {
return item.Node.Node === query.node && item.Service.ID === query.serviceId;
});
if (typeof body === 'undefined') {
const e = new Error();
e.errors = [
{
status: '404',
title: 'Not found',
},
];
throw e;
}
body.Namespace = body.Service.Namespace;
return cb(headers, body);
});
}, query);
}
}