Add acme_clients to mirage and client count utils (#26232)

* remove yarn script that no longer works in yarn 3

* delete other deprecated yarn script

* add acme_clients to mirage handler and utils

* consolidate client names

* revert changes to homogenizeClientNaming, wait until confirmation from backend

* remove flattenDataset helper

* revert deleting flattendataset method (done in separate PR)

* move response to helper file

* cleanup utils based on test changes

* add acme_clients to tests

* rename variables and add comments!

* refactor homogenizeClientNaming and rename

* move by_namespace to test helper as well

* add comments and finally delete flattenDataset

* add more comments and update response to match no mounts shape

* update test selector

* finish updates for removing clients: null from serialized response

* final comments!

* remove arrayOfCounts helper

* Update ui/tests/integration/components/clients/page/sync-test.js

Co-authored-by: Chelsea Shaw <82459713+hashishaw@users.noreply.github.com>

---------

Co-authored-by: Chelsea Shaw <82459713+hashishaw@users.noreply.github.com>
This commit is contained in:
claire bontempo
2024-04-03 13:21:24 -07:00
committed by GitHub
parent 262997a532
commit d8e6ed1c5b
10 changed files with 1042 additions and 1009 deletions

View File

@@ -6,6 +6,15 @@
import { parseAPITimestamp } from 'core/utils/date-formatters';
import { compareAsc, getUnixTime, isWithinInterval } from 'date-fns';
// add new types here
export const CLIENT_TYPES = [
'acme_clients',
'clients', // summation of total clients
'entity_clients',
'non_entity_clients',
'secret_syncs',
];
// returns array of VersionHistoryModels for noteworthy upgrades: 1.9, 1.10
// that occurred between timestamps (i.e. queried activity data)
export const filterVersionHistory = (versionHistory, start, end) => {
@@ -54,87 +63,57 @@ export const formatByMonths = (monthsArray) => {
const month = parseAPITimestamp(m.timestamp, 'M/yy');
const totalClientsByNamespace = formatByNamespace(m.namespaces);
const newClientsByNamespace = formatByNamespace(m.new_clients?.namespaces);
if (Object.keys(m).includes('counts')) {
const totalCounts = flattenDataset(m);
const newCounts = m.new_clients ? flattenDataset(m.new_clients) : {};
return {
return {
month,
timestamp: m.timestamp,
...destructureClientCounts(m?.counts),
namespaces: formatByNamespace(m.namespaces) || [],
namespaces_by_key: namespaceArrayToObject(
totalClientsByNamespace,
newClientsByNamespace,
month,
m.timestamp
),
new_clients: {
month,
timestamp: m.timestamp,
...totalCounts,
namespaces: formatByNamespace(m.namespaces) || [],
namespaces_by_key: namespaceArrayToObject(
totalClientsByNamespace,
newClientsByNamespace,
month,
m.timestamp
),
new_clients: {
month,
timestamp: m.timestamp,
...newCounts,
namespaces: formatByNamespace(m.new_clients?.namespaces) || [],
},
};
}
...destructureClientCounts(m?.new_clients?.counts),
namespaces: formatByNamespace(m.new_clients?.namespaces) || [],
},
};
});
};
export const formatByNamespace = (namespaceArray) => {
if (!Array.isArray(namespaceArray)) return namespaceArray;
return namespaceArray?.map((ns) => {
// 'namespace_path' is an empty string for root
if (ns['namespace_id'] === 'root') ns['namespace_path'] = 'root';
const label = ns['namespace_path'];
const flattenedNs = flattenDataset(ns);
// if no mounts, mounts will be an empty array
flattenedNs.mounts = [];
if (ns?.mounts && ns.mounts.length > 0) {
flattenedNs.mounts = ns.mounts.map((mount) => {
return {
label: mount['mount_path'],
...flattenDataset(mount),
};
});
// i.e. 'namespace_path' is an empty string for 'root', so use namespace_id
const label = ns.namespace_path === '' ? ns.namespace_id : ns.namespace_path;
// data prior to adding mount granularity will still have a mounts key,
// but with the value: "no mount accessor (pre-1.10 upgrade?)" (ref: vault/activity_log_util_common.go)
// transform to an empty array for type consistency
let mounts = [];
if (Array.isArray(ns.mounts)) {
mounts = ns.mounts.map((m) => ({ label: m['mount_path'], ...destructureClientCounts(m?.counts) }));
}
return {
label,
...flattenedNs,
...destructureClientCounts(ns.counts),
mounts,
};
});
};
// In 1.10 'distinct_entities' changed to 'entity_clients' and
// 'non_entity_tokens' to 'non_entity_clients'
export const homogenizeClientNaming = (object) => {
// if new key names exist, only return those key/value pairs
if (Object.keys(object).includes('entity_clients')) {
const { clients, entity_clients, non_entity_clients, secret_syncs } = object;
return {
clients,
entity_clients,
non_entity_clients,
secret_syncs,
};
}
// if object only has outdated key names, update naming
if (Object.keys(object).includes('distinct_entities')) {
const { clients, distinct_entities, non_entity_tokens } = object;
return {
clients,
entity_clients: distinct_entities,
non_entity_clients: non_entity_tokens,
};
}
return object;
};
export const flattenDataset = (object) => {
if (object?.counts) {
const flattenedObject = {};
Object.keys(object['counts']).forEach((key) => (flattenedObject[key] = object['counts'][key]));
return homogenizeClientNaming(flattenedObject);
}
return object;
// In 1.10 'distinct_entities' changed to 'entity_clients' and 'non_entity_tokens' to 'non_entity_clients'
// these deprecated keys still exist on the response, so only return relevant keys here
// when querying historical data the response will always contain the latest client type keys because the activity log is
// constructed based on the version of Vault the user is on (key values will be 0)
export const destructureClientCounts = (verboseObject) => {
if (!verboseObject) return;
return CLIENT_TYPES.reduce((newObj, clientType) => {
newObj[clientType] = verboseObject[clientType];
return newObj;
}, {});
};
export const sortMonthsByTimestamp = (monthsArray) => {
@@ -152,7 +131,6 @@ export const namespaceArrayToObject = (totalClientsByNamespace, newClientsByName
const nestNewClientsWithinNamespace = totalClientsByNamespace?.map((ns) => {
const newNamespaceCounts = newClientsByNamespace?.find((n) => n.label === ns.label);
if (newNamespaceCounts) {
const { label, clients, entity_clients, non_entity_clients, secret_syncs } = newNamespaceCounts;
const newClientsByMount = [...newNamespaceCounts.mounts];
const nestNewClientsWithinMounts = ns.mounts?.map((mount) => {
const new_clients = newClientsByMount?.find((m) => m.label === mount.label) || {};
@@ -164,11 +142,8 @@ export const namespaceArrayToObject = (totalClientsByNamespace, newClientsByName
return {
...ns,
new_clients: {
label,
clients,
entity_clients,
non_entity_clients,
secret_syncs,
label: ns.label,
...destructureClientCounts(newNamespaceCounts),
mounts: newClientsByMount,
},
mounts: [...nestNewClientsWithinMounts],
@@ -193,14 +168,11 @@ export const namespaceArrayToObject = (totalClientsByNamespace, newClientsByName
};
});
const { label, clients, entity_clients, non_entity_clients, secret_syncs, new_clients } = namespaceObject;
const { label, new_clients } = namespaceObject;
namespaces_by_key[label] = {
month,
timestamp,
clients,
entity_clients,
non_entity_clients,
secret_syncs,
...destructureClientCounts(namespaceObject),
new_clients: { month, ...new_clients },
mounts_by_key,
};
@@ -239,70 +211,3 @@ export const namespaceArrayToObject = (totalClientsByNamespace, newClientsByName
};
*/
};
/*
API RESPONSE STRUCTURE:
data: {
** by_namespace organized in descending order of client count number **
by_namespace: [
{
namespace_id: '96OwG',
namespace_path: 'test-ns/',
counts: {},
mounts: [{ mount_path: 'path-1', counts: {} }],
},
],
** months organized in ascending order of timestamps, oldest to most recent
months: [
{
timestamp: '2022-03-01T00:00:00Z',
counts: {},
namespaces: [
{
namespace_id: 'root',
namespace_path: '',
counts: {},
mounts: [{ mount_path: 'auth/up2/', counts: {} }],
},
],
new_clients: {
counts: {},
namespaces: [
{
namespace_id: 'root',
namespace_path: '',
counts: {},
mounts: [{ mount_path: 'auth/up2/', counts: {} }],
},
],
},
},
{
timestamp: '2022-04-01T00:00:00Z',
counts: {},
namespaces: [
{
namespace_id: 'root',
namespace_path: '',
counts: {},
mounts: [{ mount_path: 'auth/up2/', counts: {} }],
},
],
new_clients: {
counts: {},
namespaces: [
{
namespace_id: 'root',
namespace_path: '',
counts: {},
mounts: [{ mount_path: 'auth/up2/', counts: {} }],
},
],
},
},
],
start_time: 'start timestamp string',
end_time: 'end timestamp string',
total: { clients: 300, non_entity_clients: 100, entity_clients: 400} ,
}
*/