mirror of
https://github.com/status-im/consul.git
synced 2025-02-07 03:15:47 +00:00
* v3.20.2...v3.24.0 * Fix handle undefined outlet in route component * Don't use template helper for optional modal.open Using the optional-helper here will trigger a computation in the same runloop error. This is because we are setting the `modal`-property when the `<Ref>` component gets rendered which will update the `this.modal`-property which will then recompute the `optional`-helper leading to this error. Instead we will create an action that will call the `open`-method on the modal when it is defined. This gets rid of the double computation error as we will not access the modal property twice in the same runloop when `modal` is getting set. * Fix - fn needs to be passed function tab-nav We create functions in the component file instead so that fn-helper stops complaining about the need to pass a function. * Update ember-exam to 6.1 version "Makes it compatible" with ember-qunit v5 * scheduleOnce setMaxHeight paged-collection We need to schedule to get around double-computation error. * Fix - model.data is removed from ember-data This has been private API all along - we need to work around the removal. Reference: https://github.com/emberjs/data/pull/7338/files#diff-9a8746fc5c86fd57e6122f00fef3155f76f0f3003a24b53fb7c4621d95dcd9bfL1310 * Fix `propContains` instead of `deepEqual` policy Recent model.data works differently than iterating attributes. We use `propContains` instead of `deepEqual`. We are only interested in the properties we assert against and match the previous behavior with this change. * Fix `propContains` instead of `deepEqual` token * Better handling single-records repo test-helper `model.data` has been removed we need to handle proxies and model instances differently. * Fix remaining repository tests with propContains We don't want to match entire objects - we don't care about properties we haven't defined in the assertion. * Don't use template helper for optional modal.open Using a template helper will give us a recomputation error - we work around it by creating an explicit action on the component instead. * Await `I $verb the $pageObject object` step * Fix no more customization ember-can No need to customize, the helper handles destruction fine on its own. * Fix - don't pass `optional` functions to fn We will declare the functions on the component instead. This gives us the same behavior but no error from `fn`, which expects a function to be passed. * Fix - handle `undefined` state on validate modifier StateChart can yield out an undefined `state` we need to handle that in the validate modifier * Fix linting errors tests directory * Warn / turn off new ember linting issues We will tackle them one by one and don't want to autofix issues that could be dangerous to auto-fix. * Auto-fix linting issues * More linting configuration * Fix remaining linting issues * Fix linting issues new files after rebase * ui: Remove ember-cli-uglify config now we are using terser (#14574) Co-authored-by: John Cowen <johncowen@users.noreply.github.com>
210 lines
6.1 KiB
JavaScript
210 lines
6.1 KiB
JavaScript
import Error from '@ember/error';
|
|
import { inject as service } from '@ember/service';
|
|
import RepositoryService from 'consul-ui/services/repository';
|
|
import dataSource from 'consul-ui/decorators/data-source';
|
|
import { HEADERS_DEFAULT_ACL_POLICY as DEFAULT_ACL_POLICY } from 'consul-ui/utils/http/consul';
|
|
|
|
const SECONDS = 1000;
|
|
const MODEL_NAME = 'dc';
|
|
|
|
const zero = {
|
|
Total: 0,
|
|
Passing: 0,
|
|
Warning: 0,
|
|
Critical: 0,
|
|
};
|
|
const aggregate = (prev, body, type) => {
|
|
return body[type].reduce((prev, item) => {
|
|
// for each Partitions, Namespaces
|
|
['Partition', 'Namespace'].forEach((bucket) => {
|
|
// lazily initialize
|
|
let obj = prev[bucket][item[bucket]];
|
|
if (typeof obj === 'undefined') {
|
|
obj = prev[bucket][item[bucket]] = {
|
|
Name: item[bucket],
|
|
};
|
|
}
|
|
if (typeof obj[type] === 'undefined') {
|
|
obj[type] = {
|
|
...zero,
|
|
};
|
|
}
|
|
//
|
|
|
|
// accumulate
|
|
obj[type].Total += item.Total;
|
|
obj[type].Passing += item.Passing;
|
|
obj[type].Warning += item.Warning;
|
|
obj[type].Critical += item.Critical;
|
|
});
|
|
|
|
// also aggregate the Datacenter, without doubling up
|
|
// for Partitions/Namespaces
|
|
prev.Datacenter[type].Total += item.Total;
|
|
prev.Datacenter[type].Passing += item.Passing;
|
|
prev.Datacenter[type].Warning += item.Warning;
|
|
prev.Datacenter[type].Critical += item.Critical;
|
|
return prev;
|
|
}, prev);
|
|
};
|
|
|
|
export default class DcService extends RepositoryService {
|
|
@service('env') env;
|
|
|
|
getModelName() {
|
|
return MODEL_NAME;
|
|
}
|
|
|
|
@dataSource('/:partition/:ns/:dc/datacenters')
|
|
async fetchAll({ partition, ns, dc }, { uri }, request) {
|
|
const Local = this.env.var('CONSUL_DATACENTER_LOCAL');
|
|
const Primary = this.env.var('CONSUL_DATACENTER_PRIMARY');
|
|
return (
|
|
await request`
|
|
GET /v1/catalog/datacenters
|
|
X-Request-ID: ${uri}
|
|
`
|
|
)((headers, body, cache) => {
|
|
// TODO: Not sure nowadays whether we need to keep lowercasing everything
|
|
// I vaguely remember when I last looked it was not needed for browsers anymore
|
|
// but I also vaguely remember something about Pretender lowercasing things still
|
|
// so if we can work around Pretender I think we can remove all the header lowercasing
|
|
// For the moment we lowercase here so as to not effect the ember-data-flavoured-v1 fork
|
|
const entry = Object.entries(headers).find(
|
|
([key, value]) => key.toLowerCase() === DEFAULT_ACL_POLICY.toLowerCase()
|
|
);
|
|
//
|
|
const DefaultACLPolicy = entry[1] || 'allow';
|
|
return {
|
|
meta: {
|
|
version: 2,
|
|
uri: uri,
|
|
},
|
|
body: body.map((dc) => {
|
|
return cache(
|
|
{
|
|
Name: dc,
|
|
Datacenter: '',
|
|
Local: dc === Local,
|
|
Primary: dc === Primary,
|
|
DefaultACLPolicy: DefaultACLPolicy,
|
|
},
|
|
(uri) => uri`${MODEL_NAME}:///${''}/${''}/${dc}/datacenter`
|
|
);
|
|
}),
|
|
};
|
|
});
|
|
}
|
|
|
|
@dataSource('/:partition/:ns/:dc/datacenter')
|
|
async fetch({ partition, ns, dc }, { uri }, request) {
|
|
return (
|
|
await request`
|
|
GET /v1/operator/autopilot/state?${{ dc }}
|
|
X-Request-ID: ${uri}
|
|
`
|
|
)((headers, body, cache) => {
|
|
// turn servers into an array instead of a map/object
|
|
const servers = Object.values(body.Servers);
|
|
const grouped = [];
|
|
return {
|
|
meta: {
|
|
version: 2,
|
|
uri: uri,
|
|
},
|
|
body: cache(
|
|
{
|
|
...body,
|
|
// all servers
|
|
Servers: servers,
|
|
RedundancyZones: Object.entries(body.RedundancyZones || {}).map(([key, value]) => {
|
|
const zone = {
|
|
...value,
|
|
Name: key,
|
|
Healthy: true,
|
|
// convert the string[] to Server[]
|
|
Servers: value.Servers.reduce((prev, item) => {
|
|
const server = body.Servers[item];
|
|
// keep a record of things
|
|
grouped.push(server.ID);
|
|
prev.push(server);
|
|
return prev;
|
|
}, []),
|
|
};
|
|
return zone;
|
|
}),
|
|
ReadReplicas: (body.ReadReplicas || []).map((item) => {
|
|
// keep a record of things
|
|
grouped.push(item);
|
|
return body.Servers[item];
|
|
}),
|
|
Default: {
|
|
Servers: servers.filter((item) => !grouped.includes(item.ID)),
|
|
},
|
|
},
|
|
(uri) => uri`${MODEL_NAME}:///${''}/${''}/${dc}/datacenter`
|
|
),
|
|
};
|
|
});
|
|
}
|
|
|
|
@dataSource('/:partition/:ns/:dc/catalog/health')
|
|
async fetchCatalogHealth({ partition, ns, dc }, { uri }, request) {
|
|
return (
|
|
await request`
|
|
GET /v1/internal/ui/catalog-overview?${{ dc, stale: null }}
|
|
X-Request-ID: ${uri}
|
|
`
|
|
)((headers, body, cache) => {
|
|
// for each Services/Nodes/Checks aggregate
|
|
const agg = ['Nodes', 'Services', 'Checks'].reduce(
|
|
(prev, item) => aggregate(prev, body, item),
|
|
{
|
|
Datacenter: {
|
|
Name: dc,
|
|
Nodes: {
|
|
...zero,
|
|
},
|
|
Services: {
|
|
...zero,
|
|
},
|
|
Checks: {
|
|
...zero,
|
|
},
|
|
},
|
|
Partition: {},
|
|
Namespace: {},
|
|
}
|
|
);
|
|
|
|
return {
|
|
meta: {
|
|
version: 2,
|
|
uri: uri,
|
|
interval: 30 * SECONDS,
|
|
},
|
|
body: {
|
|
Datacenter: agg.Datacenter,
|
|
Partitions: Object.values(agg.Partition),
|
|
Namespaces: Object.values(agg.Namespace),
|
|
...body,
|
|
},
|
|
};
|
|
});
|
|
}
|
|
|
|
@dataSource('/:partition/:ns/:dc/datacenter-cache/:name')
|
|
async find(params) {
|
|
const items = this.store.peekAll('dc');
|
|
const item = items.findBy('Name', params.name);
|
|
if (typeof item === 'undefined') {
|
|
// TODO: We should use a HTTPError error here and remove all occurances of
|
|
// the custom shaped ember-data error throughout the app
|
|
const e = new Error('Page not found');
|
|
e.status = '404';
|
|
throw { errors: [e] };
|
|
}
|
|
return item;
|
|
}
|
|
}
|