mirror of
https://github.com/hashicorp/vault.git
synced 2025-08-23 23:51:08 +02:00
* Allow Managed clusters to see Secrets Sync Overview and Sidebar nav (#26649) * update badge text and allow hvd on secrets sync views * update logic in Secrets Sync overview and cta for hvd. * spacing * rearrange based on pr feedback * fix return on badgeText and cluster nav test * fix landing cta tests * update test to reflect new changes * moved call to feature-flags from application route to the service to match patterns * add managed test coverage on overview component test and remove premium feature so cta message appplies to both managed and non-managed clusters * missed service name and unskip admin test * clean up * fix tests * flags test fix * Rename isManaged and managedNamespaceRoot (#26697) * renames * lowercase HVD to match * missed some * test failure * [Secrets Sync] enable access to Sync clients page for HVD clusters (#26713) * feat: split client counts navbar into separate component * acceptance/clients/counts/overview-test: remove tests now covered by int tests * clients counts route: rename isSecretsSyncActivated to showSecretsSync * sync clients page: show unactivated state unless sync client history or feature is activated * client counts navbar: show sync tab only if client history or is /able to be/ activated * clients overview page: only show sync charts if activated * fix: rename isManaged to isHvd * acceptance/counts/overview-test: add HVD tests * acceptance/counts/overview-test: clean up unused cruft * aceptance/clients/counts/overview-test: ensure we dont get false negatives * chore: move Clients::Error to Clients::Counts::Error * chore: calculate showSecretSync in page component instead of route * chore: add copyright headers * acceptance/clients/counts/overview-test: stub activated flags to fix test * [Secrets sync] update sync test selectors (#26824) * acceptance/clients/counts/overview-test: use imported test selectors * general-selectors: add missing emptyStateSubtitle property * acceptance/clients/counts/sync: nest tests in top level module for easier test runs * Add permissions check to show/hide activate button (#26840) * add permissions check to flags service and consume in overview template * add back missing refresh * fix test failures * add test coverage * clean up * address flaky test * grr * address test failures * add changelog * try to fix test failure only on gh * fix fetch to match previous implementation of feature-flags * fix failing test * update comment --------- Co-authored-by: Noelle Daley <noelledaley@users.noreply.github.com> Co-authored-by: clairebontempo@gmail.com <clairebontempo@gmail.com>
169 lines
5.1 KiB
TypeScript
169 lines
5.1 KiB
TypeScript
/**
|
|
* Copyright (c) HashiCorp, Inc.
|
|
* SPDX-License-Identifier: BUSL-1.1
|
|
*/
|
|
|
|
// base component for counts child routes that can be extended as needed
|
|
// contains getters that filter and extract data from activity model for use in charts
|
|
|
|
import Component from '@glimmer/component';
|
|
import { isSameMonth, fromUnixTime } from 'date-fns';
|
|
import { parseAPITimestamp } from 'core/utils/date-formatters';
|
|
import { calculateAverage } from 'vault/utils/chart-helpers';
|
|
import { filterVersionHistory, hasMountsKey, hasNamespacesKey } from 'core/utils/client-count-utils';
|
|
|
|
import type ClientsActivityModel from 'vault/models/clients/activity';
|
|
import type ClientsVersionHistoryModel from 'vault/models/clients/version-history';
|
|
import type {
|
|
ByMonthNewClients,
|
|
MountNewClients,
|
|
NamespaceByKey,
|
|
NamespaceNewClients,
|
|
} from 'core/utils/client-count-utils';
|
|
|
|
interface Args {
|
|
activity: ClientsActivityModel;
|
|
versionHistory: ClientsVersionHistoryModel[];
|
|
startTimestamp: number;
|
|
endTimestamp: number;
|
|
namespace: string;
|
|
mountPath: string;
|
|
}
|
|
|
|
export default class ClientsActivityComponent extends Component<Args> {
|
|
average = (
|
|
data:
|
|
| (ByMonthNewClients | NamespaceNewClients | MountNewClients | undefined)[]
|
|
| (NamespaceByKey | undefined)[],
|
|
key: string
|
|
) => {
|
|
return calculateAverage(data, key);
|
|
};
|
|
|
|
get startTimeISO() {
|
|
return fromUnixTime(this.args.startTimestamp).toISOString();
|
|
}
|
|
|
|
get endTimeISO() {
|
|
return fromUnixTime(this.args.endTimestamp).toISOString();
|
|
}
|
|
|
|
get byMonthActivityData() {
|
|
const { activity, namespace } = this.args;
|
|
return namespace ? this.filteredActivityByMonth : activity.byMonth;
|
|
}
|
|
|
|
get byMonthNewClients() {
|
|
return this.byMonthActivityData ? this.byMonthActivityData?.map((m) => m?.new_clients) : [];
|
|
}
|
|
|
|
get filteredActivityByMonth() {
|
|
const { namespace, mountPath, activity } = this.args;
|
|
if (!namespace && !mountPath) {
|
|
return activity.byMonth;
|
|
}
|
|
const namespaceData = activity.byMonth
|
|
?.map((m) => m.namespaces_by_key[namespace])
|
|
.filter((d) => d !== undefined);
|
|
|
|
if (!mountPath) {
|
|
return namespaceData || [];
|
|
}
|
|
|
|
const mountData = namespaceData
|
|
?.map((namespace) => namespace?.mounts_by_key[mountPath])
|
|
.filter((d) => d !== undefined);
|
|
|
|
return mountData || [];
|
|
}
|
|
|
|
get filteredActivityByNamespace() {
|
|
const { namespace, activity } = this.args;
|
|
return activity.byNamespace.find((ns) => ns.label === namespace);
|
|
}
|
|
|
|
get filteredActivityByAuthMount() {
|
|
return this.filteredActivityByNamespace?.mounts?.find((mount) => mount.label === this.args.mountPath);
|
|
}
|
|
|
|
get filteredActivity() {
|
|
return this.args.mountPath ? this.filteredActivityByAuthMount : this.filteredActivityByNamespace;
|
|
}
|
|
|
|
get isCurrentMonth() {
|
|
const { activity } = this.args;
|
|
const current = parseAPITimestamp(activity.responseTimestamp) as Date;
|
|
const start = parseAPITimestamp(activity.startTime) as Date;
|
|
const end = parseAPITimestamp(activity.endTime) as Date;
|
|
return isSameMonth(start, current) && isSameMonth(end, current);
|
|
}
|
|
|
|
get isDateRange() {
|
|
const { activity } = this.args;
|
|
return !isSameMonth(
|
|
parseAPITimestamp(activity.startTime) as Date,
|
|
parseAPITimestamp(activity.endTime) as Date
|
|
);
|
|
}
|
|
|
|
// (object) top level TOTAL client counts for given date range
|
|
get totalUsageCounts() {
|
|
const { namespace, activity } = this.args;
|
|
return namespace ? this.filteredActivity : activity.total;
|
|
}
|
|
|
|
get upgradesDuringActivity() {
|
|
const { versionHistory, activity } = this.args;
|
|
return filterVersionHistory(versionHistory, activity.startTime, activity.endTime);
|
|
}
|
|
|
|
// (object) single month new client data with total counts and array of
|
|
// either namespaces or mounts
|
|
get newClientCounts() {
|
|
if (this.isDateRange || this.byMonthActivityData.length === 0) {
|
|
return null;
|
|
}
|
|
|
|
return this.byMonthActivityData[0]?.new_clients;
|
|
}
|
|
|
|
// total client data for horizontal bar chart in attribution component
|
|
get totalClientAttribution() {
|
|
const { namespace, activity } = this.args;
|
|
if (namespace) {
|
|
return this.filteredActivityByNamespace?.mounts || null;
|
|
} else {
|
|
return activity.byNamespace || null;
|
|
}
|
|
}
|
|
|
|
// new client data for horizontal bar chart
|
|
get newClientAttribution() {
|
|
// new client attribution only available in a single, historical month (not a date range or current month)
|
|
if (this.isDateRange || this.isCurrentMonth || !this.newClientCounts) return null;
|
|
|
|
const newCounts = this.newClientCounts;
|
|
if (this.args.namespace && hasMountsKey(newCounts)) return newCounts?.mounts;
|
|
|
|
if (hasNamespacesKey(newCounts)) return newCounts?.namespaces;
|
|
|
|
return null;
|
|
}
|
|
|
|
get hasAttributionData() {
|
|
const { mountPath, namespace } = this.args;
|
|
if (!mountPath) {
|
|
if (namespace) {
|
|
const mounts = this.filteredActivityByNamespace?.mounts?.map((mount) => ({
|
|
id: mount.label,
|
|
name: mount.label,
|
|
}));
|
|
return mounts && mounts.length > 0;
|
|
}
|
|
return !!this.totalClientAttribution && this.totalUsageCounts && this.totalUsageCounts.clients !== 0;
|
|
}
|
|
|
|
return false;
|
|
}
|
|
}
|