@skyhook-io/k8s-ui 1.17.0 → 1.17.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +41 -0
- package/package.json +3 -3
- package/src/components/charts/AreaChart.interaction.test.tsx +118 -0
- package/src/components/charts/AreaChart.test.tsx +25 -0
- package/src/components/charts/AreaChart.tsx +141 -12
- package/src/components/charts/index.ts +1 -0
- package/src/components/checks/ChecksView.tsx +18 -1
- package/src/components/cnpg/CNPGBackupSummary.tsx +57 -9
- package/src/components/cnpg/CNPGClusterHASection.test.tsx +90 -0
- package/src/components/cnpg/CNPGClusterHASection.tsx +331 -0
- package/src/components/cnpg/CNPGClusterSummary.test.tsx +275 -0
- package/src/components/cnpg/CNPGClusterSummary.tsx +310 -96
- package/src/components/cnpg/CNPGConnectSection.test.tsx +64 -0
- package/src/components/cnpg/CNPGConnectSection.tsx +178 -0
- package/src/components/cnpg/CNPGDeclarativeSummary.tsx +157 -26
- package/src/components/cnpg/CNPGImageCatalogSummary.tsx +7 -4
- package/src/components/cnpg/CNPGLogicalPath.test.tsx +22 -0
- package/src/components/cnpg/CNPGLogicalPath.tsx +150 -0
- package/src/components/cnpg/CNPGObjectStoreSummary.tsx +9 -6
- package/src/components/cnpg/CNPGObjectSummary.test.tsx +193 -2
- package/src/components/cnpg/CNPGPoolerScheduling.test.tsx +36 -0
- package/src/components/cnpg/CNPGPoolerSummary.tsx +241 -14
- package/src/components/cnpg/CNPGSharedSummary.tsx +15 -8
- package/src/components/cnpg/CNPGWALArchivingFact.test.tsx +39 -0
- package/src/components/cnpg/backupRuns.test.ts +17 -0
- package/src/components/cnpg/backupRuns.ts +19 -0
- package/src/components/cnpg/connect.test.ts +124 -0
- package/src/components/cnpg/connect.ts +155 -0
- package/src/components/cnpg/databaseRole.test.ts +38 -0
- package/src/components/cnpg/databaseRole.ts +80 -0
- package/src/components/cnpg/ha.test.ts +446 -0
- package/src/components/cnpg/ha.ts +621 -0
- package/src/components/cnpg/index.ts +18 -0
- package/src/components/cnpg/logicalReplication.test.ts +121 -0
- package/src/components/cnpg/logicalReplication.ts +252 -0
- package/src/components/cnpg/pooler.test.ts +84 -0
- package/src/components/cnpg/pooler.ts +225 -0
- package/src/components/cnpg/primitives.tsx +21 -117
- package/src/components/cnpg/problems.ts +12 -0
- package/src/components/cnpg/relations.test.ts +63 -13
- package/src/components/cnpg/relations.ts +61 -52
- package/src/components/cnpg/schedule.ts +35 -0
- package/src/components/cnpg/workspace-disk.test.ts +97 -0
- package/src/components/cnpg/workspace-fleet-metrics.test.ts +250 -0
- package/src/components/cnpg/workspace-problems.test.ts +175 -0
- package/src/components/cnpg/workspace.test.ts +380 -9
- package/src/components/cnpg/workspace.ts +1137 -136
- package/src/components/dock/DockContext.test.tsx +32 -0
- package/src/components/dock/DockContext.tsx +18 -4
- package/src/components/dock/LocalTerminalTab.test.tsx +40 -0
- package/src/components/dock/LocalTerminalTab.tsx +4 -3
- package/src/components/dock/TerminalTab.tsx +20 -8
- package/src/components/facts/certainty.tsx +36 -0
- package/src/components/facts/facts.test.tsx +24 -0
- package/src/components/facts/facts.tsx +62 -0
- package/src/components/facts/index.ts +6 -0
- package/src/components/facts/managed-by.test.tsx +17 -0
- package/src/components/facts/managed-by.tsx +36 -0
- package/src/components/facts/public-exports.test.tsx +35 -0
- package/src/components/gitops/GitOpsGraphFilterRail.tsx +6 -2
- package/src/components/gitops/GitOpsHealthSourceNotice.test.tsx +38 -0
- package/src/components/gitops/GitOpsHealthSourceNotice.tsx +13 -3
- package/src/components/gitops/insights/ArgoResourceDiff.test.tsx +115 -0
- package/src/components/gitops/insights/ArgoResourceDiff.tsx +22 -5
- package/src/components/gitops/insights/DriftPanel.tsx +62 -0
- package/src/components/gitops/insights/GitOpsInsightViews.tsx +24 -71
- package/src/components/gitops/tree/GitOpsTreeGraph.test.ts +26 -1
- package/src/components/gitops/tree/GitOpsTreeGraph.tsx +38 -55
- package/src/components/gitops/tree/layout.test.ts +111 -0
- package/src/components/gitops/tree/layout.ts +128 -0
- package/src/components/gitops/tree/tree-helpers.test.ts +17 -0
- package/src/components/gitops/tree/tree-helpers.ts +7 -1
- package/src/components/issues/ConditionalCleanup.test.tsx +82 -0
- package/src/components/issues/IssuesView.tsx +40 -5
- package/src/components/issues/ResourceIssuesSection.test.tsx +28 -0
- package/src/components/issues/ResourceIssuesSection.tsx +3 -0
- package/src/components/issues/index.ts +3 -1
- package/src/components/issues/issue-timing.ts +12 -1
- package/src/components/issues/issues.test.ts +49 -1
- package/src/components/issues/severity.ts +21 -0
- package/src/components/issues/types.ts +23 -0
- package/src/components/logs/LogCore.theme.test.tsx +81 -3
- package/src/components/logs/LogCore.tsx +25 -17
- package/src/components/logs/LogToolbarSelects.tsx +3 -1
- package/src/components/logs/LogsViewer.test.tsx +291 -0
- package/src/components/logs/LogsViewer.tsx +72 -11
- package/src/components/logs/StructuredLogLine.test.tsx +76 -0
- package/src/components/logs/StructuredLogLine.tsx +22 -30
- package/src/components/logs/WorkloadLogsViewer.test.tsx +65 -0
- package/src/components/logs/WorkloadLogsViewer.tsx +39 -10
- package/src/components/logs/useLogBuffer.test.ts +8 -0
- package/src/components/logs/useLogStream.ts +17 -1
- package/src/components/problems/index.ts +1 -0
- package/src/components/problems/problems.test.tsx +63 -0
- package/src/components/problems/problems.tsx +165 -0
- package/src/components/resources/ActiveFilterBar.test.tsx +78 -0
- package/src/components/resources/ActiveFilterBar.tsx +86 -0
- package/src/components/resources/ResourcesSidebar.keyboard.test.tsx +42 -0
- package/src/components/resources/ResourcesSidebar.test.tsx +36 -2
- package/src/components/resources/ResourcesSidebar.tsx +92 -41
- package/src/components/resources/ResourcesView.kind-filter-memory.test.ts +52 -0
- package/src/components/resources/ResourcesView.kind-view.test.tsx +149 -0
- package/src/components/resources/ResourcesView.per-container.test.ts +56 -1
- package/src/components/resources/ResourcesView.tsx +302 -109
- package/src/components/resources/curated-column-ownership.test.ts +3 -3
- package/src/components/resources/renderers/AutoscalingReferences.test.tsx +286 -0
- package/src/components/resources/renderers/CAPIClusterRenderer.tsx +3 -2
- package/src/components/resources/renderers/CAPIExactReferenceNavigation.test.tsx +27 -0
- package/src/components/resources/renderers/CNPGBackupRenderer.test.tsx +23 -0
- package/src/components/resources/renderers/CNPGBackupRenderer.tsx +8 -19
- package/src/components/resources/renderers/CNPGClusterRenderer.tsx +5 -7
- package/src/components/resources/renderers/CNPGDeclarativeRenderer.tsx +25 -0
- package/src/components/resources/renderers/CNPGScheduledBackupRenderer.test.tsx +32 -0
- package/src/components/resources/renderers/CNPGScheduledBackupRenderer.tsx +7 -15
- package/src/components/resources/renderers/CompositeRenderer.navigation.test.tsx +35 -0
- package/src/components/resources/renderers/CompositeRenderer.tsx +3 -3
- package/src/components/resources/renderers/CompositionRenderer.tsx +3 -3
- package/src/components/resources/renderers/ContourExactReferenceNavigation.test.tsx +34 -0
- package/src/components/resources/renderers/ContourHTTPProxyRenderer.tsx +11 -10
- package/src/components/resources/renderers/EndpointSliceRenderer.test.tsx +39 -1
- package/src/components/resources/renderers/EndpointSliceRenderer.tsx +14 -13
- package/src/components/resources/renderers/HPARenderer.tsx +56 -16
- package/src/components/resources/renderers/IngressRenderer.defaultBackend.test.tsx +33 -0
- package/src/components/resources/renderers/IngressRenderer.tsx +30 -3
- package/src/components/resources/renderers/IstioDestinationRuleRenderer.tsx +9 -9
- package/src/components/resources/renderers/IstioExactReferenceNavigation.test.tsx +34 -0
- package/src/components/resources/renderers/IstioVirtualServiceRenderer.tsx +5 -8
- package/src/components/resources/renderers/KedaScaledObjectRenderer.tsx +13 -11
- package/src/components/resources/renderers/KnativeEventingRenderer.tsx +24 -31
- package/src/components/resources/renderers/KnativeExactReferenceNavigation.test.tsx +47 -0
- package/src/components/resources/renderers/KnativeFlowRenderer.tsx +6 -7
- package/src/components/resources/renderers/KnativeNetworkingRenderer.tsx +7 -9
- package/src/components/resources/renderers/KnativeReferenceLink.tsx +14 -0
- package/src/components/resources/renderers/KnativeReferenceLinks.test.tsx +60 -0
- package/src/components/resources/renderers/KnativeSourceRenderer.tsx +9 -11
- package/src/components/resources/renderers/ManagedResourceRenderer.tsx +2 -2
- package/src/components/resources/renderers/MetricsUnavailableNotice.tsx +3 -2
- package/src/components/resources/renderers/PodRenderer.test.tsx +32 -0
- package/src/components/resources/renderers/PodRenderer.tsx +41 -29
- package/src/components/resources/renderers/SimpleRouteRenderer.tsx +1 -1
- package/src/components/resources/renderers/VPARenderer.tsx +17 -11
- package/src/components/resources/resource-utils-capi.ts +1 -1
- package/src/components/resources/resource-utils-cnpg.test.ts +35 -10
- package/src/components/resources/resource-utils-cnpg.ts +51 -20
- package/src/components/resources/resource-utils-contour.test.ts +44 -0
- package/src/components/resources/resource-utils-contour.ts +16 -0
- package/src/components/resources/resource-utils-istio.ts +12 -8
- package/src/components/resources/resource-utils-knative.ts +18 -0
- package/src/components/resources/resource-utils.ts +82 -6
- package/src/components/resources/rules-column-width.test.ts +1 -1
- package/src/components/resources/summarize-scheduler-message.test.ts +30 -0
- package/src/components/shared/ActionConfirmDialog.test.tsx +154 -0
- package/src/components/shared/ActionConfirmDialog.tsx +246 -0
- package/src/components/shared/CreateResourceDialog.test.tsx +330 -0
- package/src/components/shared/CreateResourceDialog.tsx +126 -80
- package/src/components/shared/DetailShell.test.tsx +80 -0
- package/src/components/shared/DetailShell.tsx +85 -10
- package/src/components/shared/EditableYamlView.test.tsx +7 -0
- package/src/components/shared/EditableYamlView.tsx +1 -1
- package/src/components/shared/ResourceActionsBar.tsx +11 -4
- package/src/components/shared/ResourceRendererDispatch.tsx +12 -9
- package/src/components/shared/index.ts +2 -0
- package/src/components/timeline/TimelineSwimlanes.tsx +1 -1
- package/src/components/timeline/timeline-filters.ts +1 -0
- package/src/components/topology/K8sResourceNode.test.ts +18 -1
- package/src/components/topology/K8sResourceNode.tsx +44 -2
- package/src/components/topology/TopologyFilterSidebar.tsx +1 -0
- package/src/components/topology/TopologyGraph.tsx +3 -71
- package/src/components/topology/TopologySearch.tsx +1 -0
- package/src/components/topology/internet-groups.test.ts +35 -0
- package/src/components/topology/internet-groups.ts +55 -0
- package/src/components/topology/layout.ts +1 -1
- package/src/components/ui/Badge.tsx +1 -0
- package/src/components/ui/FoldSection.tsx +68 -0
- package/src/components/ui/ForceDeleteConfirmDialog.test.tsx +62 -0
- package/src/components/ui/ForceDeleteConfirmDialog.tsx +24 -12
- package/src/components/ui/RefLink.tsx +20 -0
- package/src/components/ui/RowActionMenu.tsx +8 -3
- package/src/components/ui/crd-definition-navigation.test.tsx +160 -0
- package/src/components/ui/drawer-components.test.tsx +110 -1
- package/src/components/ui/drawer-components.tsx +62 -9
- package/src/components/ui/index.ts +3 -1
- package/src/components/ui/monacoEditorFeatures.ts +77 -0
- package/src/components/ui/monacoRuntime.ts +14 -19
- package/src/components/ui/status-tone.test.ts +10 -1
- package/src/components/ui/status-tone.tsx +29 -0
- package/src/components/workload/WorkloadView.deleted.test.tsx +43 -0
- package/src/components/workload/WorkloadView.relationships.test.tsx +37 -0
- package/src/components/workload/WorkloadView.spec.test.tsx +149 -0
- package/src/components/workload/WorkloadView.tsx +180 -64
- package/src/index.ts +14 -1
- package/src/monaco-deep.d.ts +19 -12
- package/src/theme/components.css +13 -0
- package/src/types/capacity.ts +11 -2
- package/src/types/core.ts +29 -2
- package/src/types/gitops-flux-status.test.ts +32 -1
- package/src/types/gitops-insights.ts +19 -2
- package/src/types/gitops-tree.ts +10 -0
- package/src/types/gitops.ts +26 -6
- package/src/utils/api-resources.ts +7 -0
- package/src/utils/application-history.ts +1 -0
- package/src/utils/cnpg-backup.test.ts +26 -0
- package/src/utils/cnpg-backup.ts +70 -0
- package/src/utils/format.test.ts +9 -0
- package/src/utils/format.ts +4 -0
- package/src/utils/gitops-owner.ts +3 -2
- package/src/utils/grant.test.ts +19 -0
- package/src/utils/grant.ts +35 -0
- package/src/utils/index.ts +4 -0
- package/src/utils/k8s-errors.ts +7 -7
- package/src/utils/log-format.test.ts +41 -0
- package/src/utils/log-format.ts +71 -15
- package/src/utils/log-level.ts +12 -8
- package/src/utils/navigation.test.ts +57 -0
- package/src/utils/navigation.ts +86 -8
- package/src/utils/object-reference-navigation.test.ts +43 -0
- package/src/utils/resource-hierarchy.test.ts +37 -0
- package/src/utils/resource-hierarchy.ts +15 -7
- package/src/utils/resource-icons.ts +2 -0
- package/src/utils/skeleton-yaml.test.ts +21 -0
- package/src/utils/skeleton-yaml.ts +16 -0
- package/src/utils/url-path.test.ts +35 -0
- package/src/utils/url-path.ts +21 -0
- package/src/utils/validators.test.ts +4 -13
- package/src/utils/validators.ts +5 -19
- package/src/utils/view-transition.test.ts +35 -1
- package/src/utils/view-transition.ts +16 -1
|
@@ -90,6 +90,8 @@ export interface WorkloadExtraTab {
|
|
|
90
90
|
icon?: ReactNode
|
|
91
91
|
after?: WorkloadTabType
|
|
92
92
|
replaces?: WorkloadTabType
|
|
93
|
+
/** Trailing adornment after the label, e.g. a status mark. */
|
|
94
|
+
badge?: ReactNode
|
|
93
95
|
render: () => ReactNode
|
|
94
96
|
}
|
|
95
97
|
|
|
@@ -145,6 +147,23 @@ interface WorkloadViewProps {
|
|
|
145
147
|
* the Escape shortcut.
|
|
146
148
|
*/
|
|
147
149
|
breadcrumb?: ReactNode
|
|
150
|
+
/** Where the object lives, shown on the title line before its name (e.g. "Workspace / View /"). */
|
|
151
|
+
titlePrefix?: ReactNode
|
|
152
|
+
/**
|
|
153
|
+
* Kind, status and namespace on the title line, wrapping below the name
|
|
154
|
+
* only when there is no room; other chips (image, owners) keep a second
|
|
155
|
+
* row. The header actions then wrap below the title as a group rather
|
|
156
|
+
* than squeezing it.
|
|
157
|
+
*/
|
|
158
|
+
inlineBadges?: boolean
|
|
159
|
+
/** A note right after the namespace, e.g. that it is outside the namespace filter. */
|
|
160
|
+
namespaceNote?: ReactNode
|
|
161
|
+
/** Replaces the derived status badge on the title line, e.g. with the controller's own reported phase. */
|
|
162
|
+
renderStatusBadge?: (resource: any) => ReactNode
|
|
163
|
+
/** A short status right after the controller status on the title line, e.g. a derived health verdict. */
|
|
164
|
+
statusNote?: ReactNode
|
|
165
|
+
/** Leave out the kind badge, for a host whose title prefix already names the kind. */
|
|
166
|
+
hideKindBadge?: boolean
|
|
148
167
|
/** Suppress the standalone back arrow — for embeddings where "back" has no
|
|
149
168
|
* meaningful target (a single-workload app has no app graph to return to). */
|
|
150
169
|
hideBackButton?: boolean
|
|
@@ -319,6 +338,14 @@ interface WorkloadViewProps {
|
|
|
319
338
|
}) => ReactNode
|
|
320
339
|
/** Extra tabs for the expanded view (e.g. a domain's own sections). */
|
|
321
340
|
extraTabs?: WorkloadExtraTab[]
|
|
341
|
+
/** Expanded view: a line under the title, above the tabs, shown on every tab. */
|
|
342
|
+
subheader?: ReactNode
|
|
343
|
+
/** Expanded view: tab ids in display order; tabs not listed follow in their usual order. */
|
|
344
|
+
tabOrder?: string[]
|
|
345
|
+
/** Expanded view: relabel, lead, or replace the whole "Spec & status" body. */
|
|
346
|
+
specTab?: { label?: string; icon?: ReactNode; lead?: ReactNode; render?: () => ReactNode }
|
|
347
|
+
/** Domain actions rendered in the header (drawer and expanded). */
|
|
348
|
+
renderHeaderActions?: (props: { resource: any; context: 'drawer' | 'expanded'; onNavigate?: NavigateToResource }) => ReactNode
|
|
322
349
|
/** Render a full replacement for the expanded Overview tab. */
|
|
323
350
|
renderExpandedOverview?: (props: {
|
|
324
351
|
kind: string
|
|
@@ -409,6 +436,12 @@ export function WorkloadView({
|
|
|
409
436
|
initialTab,
|
|
410
437
|
group,
|
|
411
438
|
breadcrumb,
|
|
439
|
+
titlePrefix,
|
|
440
|
+
inlineBadges = false,
|
|
441
|
+
namespaceNote,
|
|
442
|
+
renderStatusBadge,
|
|
443
|
+
statusNote,
|
|
444
|
+
hideKindBadge = false,
|
|
412
445
|
hideBackButton,
|
|
413
446
|
scopeControls,
|
|
414
447
|
compactHeader,
|
|
@@ -469,6 +502,10 @@ export function WorkloadView({
|
|
|
469
502
|
renderExpandedOverview,
|
|
470
503
|
renderSummary,
|
|
471
504
|
extraTabs,
|
|
505
|
+
tabOrder,
|
|
506
|
+
specTab,
|
|
507
|
+
subheader,
|
|
508
|
+
renderHeaderActions,
|
|
472
509
|
renderRelatedYaml,
|
|
473
510
|
renderMetricsTab,
|
|
474
511
|
renderCostTab,
|
|
@@ -794,6 +831,9 @@ export function WorkloadView({
|
|
|
794
831
|
const renderOverviewLeadForState = resourceGone ? undefined : renderOverviewLead
|
|
795
832
|
const renderOverviewExtraForState = resourceGone ? undefined : renderOverviewExtra
|
|
796
833
|
const renderDiagnoseTabForState = resourceGone ? undefined : renderDiagnoseTab
|
|
834
|
+
// A host's summary, tabs and subheader can hold actions on the live object.
|
|
835
|
+
const renderSummaryForState = resourceGone ? undefined : renderSummary
|
|
836
|
+
const extraTabsForState = resourceGone ? undefined : extraTabs
|
|
797
837
|
// A remount closes any dialog the bar had open: once its actions are gone,
|
|
798
838
|
// a confirm button left on screen would do nothing.
|
|
799
839
|
const actionsBarKey = resourceGone ? 'gone' : 'live'
|
|
@@ -830,6 +870,7 @@ export function WorkloadView({
|
|
|
830
870
|
const renderDiagnose = actionsBarProps?.renderDiagnose as
|
|
831
871
|
| ((ctx: { kind: string; group?: string; namespace: string; name: string; health?: DiagnoseHealthHint }) => ReactNode)
|
|
832
872
|
| undefined
|
|
873
|
+
const headerActions = resource && !resourceGone && renderHeaderActions?.({ resource, context: expanded ? 'expanded' : 'drawer', onNavigate: onNavigateToResource })
|
|
833
874
|
const diagnoseAction = resourceGone ? null : renderDiagnose?.({
|
|
834
875
|
kind: resource?.kind ?? knownKindForPluralWithGroup(apiKind, group ?? '') ?? apiKind,
|
|
835
876
|
group,
|
|
@@ -849,11 +890,11 @@ export function WorkloadView({
|
|
|
849
890
|
const logsFallbackReady = !renderLogsTab || (!logsTabVisible && !podEvidenceLoading)
|
|
850
891
|
const requestedTab: TabType = activeTab
|
|
851
892
|
const summaryContext = { kind, apiKind, namespace, name, group, resource, onNavigate: onNavigateToResource }
|
|
852
|
-
const expandedSummary = expanded && resource ?
|
|
853
|
-
const drawerSummary = !expanded && resource ?
|
|
893
|
+
const expandedSummary = expanded && resource ? renderSummaryForState?.({ ...summaryContext, context: 'expanded' }) ?? null : null
|
|
894
|
+
const drawerSummary = !expanded && resource ? renderSummaryForState?.({ ...summaryContext, context: 'drawer' }) ?? null : null
|
|
854
895
|
const tabs: DetailShellTab<TabType>[] = [
|
|
855
896
|
{ id: 'overview', label: 'Overview', icon: <Layers className="w-4 h-4" /> },
|
|
856
|
-
{ id: 'spec', label: 'Spec & status', icon: <FileText className="w-4 h-4" />, hidden: !expandedSummary },
|
|
897
|
+
{ id: 'spec', label: specTab?.label ?? 'Spec & status', icon: specTab?.icon ?? <FileText className="w-4 h-4" />, hidden: !expandedSummary },
|
|
857
898
|
{ id: 'topology', label: 'Topology', icon: <Network className="w-4 h-4" />, hidden: topologyTabHidden },
|
|
858
899
|
{
|
|
859
900
|
id: 'timeline',
|
|
@@ -872,10 +913,10 @@ export function WorkloadView({
|
|
|
872
913
|
{ id: 'cost', label: 'Cost', icon: <Coins className="w-4 h-4" />, hidden: !costTabVisible },
|
|
873
914
|
{ id: 'yaml', label: 'YAML', icon: <FileText className="w-4 h-4" /> },
|
|
874
915
|
]
|
|
875
|
-
const allTabs = mergeExtraTabs(tabs, expanded ?
|
|
916
|
+
const allTabs = orderTabs(mergeExtraTabs(tabs, expanded ? extraTabsForState : undefined), expanded ? tabOrder : undefined)
|
|
876
917
|
const requestedTabAvailable = allTabs.some((tab) => tab.id === requestedTab && !tab.hidden)
|
|
877
918
|
const effectiveTab: TabType = requestedTabAvailable ? requestedTab : 'overview'
|
|
878
|
-
const activeExtraTab = expanded ?
|
|
919
|
+
const activeExtraTab = expanded ? extraTabsForState?.find((x) => x.id === effectiveTab) : undefined
|
|
879
920
|
const shouldCommitFallback =
|
|
880
921
|
requestedTab !== 'overview' &&
|
|
881
922
|
!requestedTabAvailable &&
|
|
@@ -904,13 +945,13 @@ export function WorkloadView({
|
|
|
904
945
|
<span className={clsx('badge', getKindColorOutline(apiKind))}>
|
|
905
946
|
{displayKindName(apiKind, resource?.kind)}
|
|
906
947
|
</span>
|
|
907
|
-
{status && (
|
|
948
|
+
{renderStatusBadge && resource && !resourceGone ? renderStatusBadge(resource) : status && (
|
|
908
949
|
<span className={clsx('badge', status.color)}>
|
|
909
950
|
{status.text}
|
|
910
951
|
</span>
|
|
911
952
|
)}
|
|
912
953
|
</div>
|
|
913
|
-
<div className="flex items-center gap-1.5">
|
|
954
|
+
<div className="flex shrink-0 flex-nowrap items-center justify-end gap-1.5">
|
|
914
955
|
{diagnoseAction}
|
|
915
956
|
{onExpand && (
|
|
916
957
|
<Tooltip content="Open full view" delay={150} position="bottom">
|
|
@@ -982,7 +1023,7 @@ export function WorkloadView({
|
|
|
982
1023
|
</div>
|
|
983
1024
|
|
|
984
1025
|
{/* Actions bar */}
|
|
985
|
-
<ResourceActionsBar key={actionsBarKey} resource={selectedResource} data={resource} onClose={onClose} showYaml={showYaml} onToggleYaml={() => switchView(!showYaml)} {...actionsBarPropsForState} />
|
|
1026
|
+
<ResourceActionsBar key={actionsBarKey} resource={selectedResource} data={resource} onClose={onClose} showYaml={showYaml} onToggleYaml={() => switchView(!showYaml)} {...actionsBarPropsForState} leadingActions={headerActions} />
|
|
986
1027
|
</div>
|
|
987
1028
|
|
|
988
1029
|
{/* Success animation overlay */}
|
|
@@ -1091,6 +1132,8 @@ export function WorkloadView({
|
|
|
1091
1132
|
<OperationalIssuesShownContext.Provider value={!!hasOperationalIssues || !!operationalIssuesPending}>
|
|
1092
1133
|
<DetailShell
|
|
1093
1134
|
breadcrumb={breadcrumb}
|
|
1135
|
+
wrapHeader={inlineBadges}
|
|
1136
|
+
subheader={resourceGone ? undefined : subheader}
|
|
1094
1137
|
nav={
|
|
1095
1138
|
breadcrumb || hideBackButton ? undefined : (
|
|
1096
1139
|
<Tooltip content="Go back (Esc)" delay={150} position="bottom">
|
|
@@ -1104,68 +1147,111 @@ export function WorkloadView({
|
|
|
1104
1147
|
</Tooltip>
|
|
1105
1148
|
)
|
|
1106
1149
|
}
|
|
1107
|
-
identity={
|
|
1108
|
-
|
|
1109
|
-
|
|
1110
|
-
<
|
|
1111
|
-
|
|
1112
|
-
|
|
1113
|
-
|
|
1114
|
-
|
|
1115
|
-
|
|
1116
|
-
|
|
1117
|
-
|
|
1118
|
-
|
|
1119
|
-
|
|
1120
|
-
|
|
1121
|
-
|
|
1122
|
-
|
|
1123
|
-
|
|
1124
|
-
|
|
1125
|
-
|
|
1126
|
-
|
|
1127
|
-
|
|
1128
|
-
|
|
1129
|
-
|
|
1130
|
-
|
|
1131
|
-
)}
|
|
1132
|
-
<div className="flex items-center gap-3 text-sm text-theme-text-secondary">
|
|
1133
|
-
<span className={clsx('badge', getKindColorOutline(apiKind))}>
|
|
1134
|
-
{displayKindName(apiKind, resource?.kind)}
|
|
1135
|
-
</span>
|
|
1136
|
-
{status && (
|
|
1137
|
-
<span className={clsx('badge', status.color)}>
|
|
1150
|
+
identity={(() => {
|
|
1151
|
+
const nameAndCopy = (
|
|
1152
|
+
<>
|
|
1153
|
+
<h1 className="text-lg font-semibold text-theme-text-primary truncate">{name}</h1>
|
|
1154
|
+
<Tooltip content="Copy name" delay={150}>
|
|
1155
|
+
<button
|
|
1156
|
+
onClick={() => copyToClipboard(name, 'name')}
|
|
1157
|
+
className="p-1 text-theme-text-secondary hover:text-theme-text-primary hover:bg-theme-elevated rounded shrink-0"
|
|
1158
|
+
aria-label="Copy name"
|
|
1159
|
+
>
|
|
1160
|
+
{copied === 'name' ? <Check className="w-3.5 h-3.5 text-green-400" /> : <Copy className="w-3.5 h-3.5" />}
|
|
1161
|
+
</button>
|
|
1162
|
+
</Tooltip>
|
|
1163
|
+
</>
|
|
1164
|
+
)
|
|
1165
|
+
const kindAndStatus = (
|
|
1166
|
+
<>
|
|
1167
|
+
{!hideKindBadge && (
|
|
1168
|
+
<span className={clsx('badge whitespace-nowrap', getKindColorOutline(apiKind))}>
|
|
1169
|
+
{displayKindName(apiKind, resource?.kind)}
|
|
1170
|
+
</span>
|
|
1171
|
+
)}
|
|
1172
|
+
{renderStatusBadge && resource && !resourceGone ? renderStatusBadge(resource) : status && (
|
|
1173
|
+
<span className={clsx('badge whitespace-nowrap', status.color)}>
|
|
1138
1174
|
{status.text}
|
|
1139
1175
|
</span>
|
|
1140
1176
|
)}
|
|
1177
|
+
{!resourceGone && statusNote}
|
|
1178
|
+
</>
|
|
1179
|
+
)
|
|
1180
|
+
const coreBadges = (
|
|
1181
|
+
<>
|
|
1182
|
+
{/* On the title line the kind and status wrap together, never apart. */}
|
|
1183
|
+
{inlineBadges ? <span className="inline-flex items-center gap-x-3">{kindAndStatus}</span> : kindAndStatus}
|
|
1141
1184
|
{namespace && namespace !== '_' && (
|
|
1142
|
-
<span>Namespace: <span className="text-theme-text-primary">{namespace}</span></span>
|
|
1185
|
+
<span className="whitespace-nowrap">Namespace: <span className="text-theme-text-primary">{namespace}</span></span>
|
|
1143
1186
|
)}
|
|
1144
|
-
{
|
|
1145
|
-
|
|
1146
|
-
|
|
1147
|
-
|
|
1148
|
-
|
|
1149
|
-
|
|
1150
|
-
|
|
1151
|
-
|
|
1152
|
-
|
|
1153
|
-
|
|
1154
|
-
|
|
1155
|
-
|
|
1156
|
-
|
|
1157
|
-
|
|
1158
|
-
|
|
1159
|
-
|
|
1160
|
-
|
|
1161
|
-
|
|
1162
|
-
|
|
1187
|
+
{namespace && namespace !== '_' && namespaceNote}
|
|
1188
|
+
</>
|
|
1189
|
+
)
|
|
1190
|
+
const extraChips = [
|
|
1191
|
+
headerImage && (
|
|
1192
|
+
<Tooltip key="image" content={headerImage} delay={300} wrapperClassName="min-w-0 max-w-md">
|
|
1193
|
+
<span className="truncate font-mono text-xs">
|
|
1194
|
+
{midTruncate(headerImage, 72)}
|
|
1195
|
+
</span>
|
|
1196
|
+
</Tooltip>
|
|
1197
|
+
),
|
|
1198
|
+
gitopsOwner && (
|
|
1199
|
+
<ManagedByChip key="gitops" owner={gitopsOwner} status={gitOpsOwnerStatus} verified={gitOpsOwnerVerified} pending={gitOpsOwnerPending} source={gitOpsOwnerSource} onOpen={onOpenGitOpsResource} variant="block" />
|
|
1200
|
+
),
|
|
1201
|
+
helmOwner && (
|
|
1202
|
+
<HelmManagedByChip key="helm" owner={helmOwner} source={helmOwnerSource} onOpen={onOpenHelmRelease} variant="block" />
|
|
1203
|
+
),
|
|
1204
|
+
gitOpsResourcePath && onNavigateGitOpsPath && (
|
|
1205
|
+
<OpenInGitOpsChip key="open-gitops" onClick={() => onNavigateGitOpsPath(gitOpsResourcePath)} />
|
|
1206
|
+
),
|
|
1207
|
+
onOpenLiveTraffic && <LiveTrafficChip key="live-traffic" onClick={onOpenLiveTraffic} />,
|
|
1208
|
+
relationships?.owner && !showOwnershipHeading && (
|
|
1209
|
+
<span key="owner">Owner: <button onClick={() => onNavigateToResource?.(refToSelectedResource(relationships.owner!))} className="text-blue-500 hover:underline">{relationships.owner.name}</button></span>
|
|
1210
|
+
),
|
|
1211
|
+
].filter(Boolean)
|
|
1212
|
+
if (inlineBadges && !(showOwnershipHeading && ownershipContext)) {
|
|
1213
|
+
// The name and its copy button stay together and truncate only when
|
|
1214
|
+
// the line holds nothing else; the badges wrap below before that.
|
|
1215
|
+
return (
|
|
1216
|
+
<>
|
|
1217
|
+
<div className="flex flex-wrap items-center gap-x-3 gap-y-1 text-sm text-theme-text-secondary">
|
|
1218
|
+
{titlePrefix}
|
|
1219
|
+
<div className="flex min-w-0 max-w-full items-center gap-2">{nameAndCopy}</div>
|
|
1220
|
+
{coreBadges}
|
|
1221
|
+
</div>
|
|
1222
|
+
{extraChips.length > 0 && (
|
|
1223
|
+
<div className="mt-1 flex flex-wrap items-center gap-x-3 gap-y-1 text-sm text-theme-text-secondary">{extraChips}</div>
|
|
1224
|
+
)}
|
|
1225
|
+
</>
|
|
1226
|
+
)
|
|
1227
|
+
}
|
|
1228
|
+
return (
|
|
1229
|
+
<>
|
|
1230
|
+
{showOwnershipHeading && ownershipContext ? (
|
|
1231
|
+
<OwnershipHeading
|
|
1232
|
+
podName={name}
|
|
1233
|
+
context={ownershipContext}
|
|
1234
|
+
copied={copied === 'name'}
|
|
1235
|
+
onCopy={() => copyToClipboard(name, 'name')}
|
|
1236
|
+
onNavigateToResource={onNavigateToResource}
|
|
1237
|
+
onOpenApplication={onOpenApplication}
|
|
1238
|
+
/>
|
|
1239
|
+
) : (
|
|
1240
|
+
<div className="flex items-center gap-3 mb-1">
|
|
1241
|
+
{titlePrefix}
|
|
1242
|
+
{nameAndCopy}
|
|
1243
|
+
</div>
|
|
1163
1244
|
)}
|
|
1164
|
-
|
|
1165
|
-
|
|
1166
|
-
|
|
1245
|
+
<div className="flex flex-wrap items-center gap-x-3 gap-y-1 text-sm text-theme-text-secondary">
|
|
1246
|
+
{coreBadges}
|
|
1247
|
+
{extraChips}
|
|
1248
|
+
</div>
|
|
1249
|
+
</>
|
|
1250
|
+
)
|
|
1251
|
+
})()}
|
|
1167
1252
|
headerActions={
|
|
1168
1253
|
<>
|
|
1254
|
+
{headerActions}
|
|
1169
1255
|
{diagnoseAction}
|
|
1170
1256
|
<Tooltip content="Refresh" delay={150} position="bottom">
|
|
1171
1257
|
<button
|
|
@@ -1224,6 +1310,8 @@ export function WorkloadView({
|
|
|
1224
1310
|
)}
|
|
1225
1311
|
{expandedOverview}
|
|
1226
1312
|
</div>
|
|
1313
|
+
) : effectiveTab === 'spec' && specTab?.render && !resourceGone ? (
|
|
1314
|
+
<div className="h-full min-h-0 overflow-y-auto">{specTab.render()}</div>
|
|
1227
1315
|
) : (effectiveTab === 'overview' || effectiveTab === 'spec') && (
|
|
1228
1316
|
<InfoTab
|
|
1229
1317
|
resource={resource}
|
|
@@ -1258,7 +1346,14 @@ export function WorkloadView({
|
|
|
1258
1346
|
updatesError={resourceFocusedUpdatesError}
|
|
1259
1347
|
extraContent={renderOverviewExtraForState && renderOverviewExtraForState({ kind, namespace, name, group, context: 'expanded' })}
|
|
1260
1348
|
introContent={overviewIntro}
|
|
1261
|
-
leadContent={
|
|
1349
|
+
leadContent={
|
|
1350
|
+
// A host's spec lead replaces the operational issues there: its Overview already leads with them.
|
|
1351
|
+
effectiveTab === 'spec' && specTab?.lead
|
|
1352
|
+
? specTab.lead
|
|
1353
|
+
: hasOperationalIssues && renderOverviewLeadForState
|
|
1354
|
+
? renderOverviewLeadForState({ kind, namespace, name })
|
|
1355
|
+
: undefined
|
|
1356
|
+
}
|
|
1262
1357
|
onEvaluateCapacity={onEvaluateCapacity}
|
|
1263
1358
|
recentImageSave={recentImageSave}
|
|
1264
1359
|
/>
|
|
@@ -2110,6 +2205,7 @@ function WorkloadOverviewTab({
|
|
|
2110
2205
|
const relationshipGroups = buildRelationshipGroups(relationships)
|
|
2111
2206
|
const servingRelationshipGroups = buildServingRelationshipGroups(relationships)
|
|
2112
2207
|
const dependencyRelationshipGroups = buildDependencyRelationshipGroups(relationships)
|
|
2208
|
+
const observationGroups = dependencyRelationshipGroups.filter((group) => group.label === 'Monitored By' || group.label === 'Staged Policies')
|
|
2113
2209
|
const showServingPath = servingRelationshipGroups.length > 0 && overviewShape !== 'job' && overviewShape !== 'cronjob'
|
|
2114
2210
|
const secondaryRelationshipGroups = showServingPath ? dependencyRelationshipGroups : relationshipGroups
|
|
2115
2211
|
const relationshipCardTitle =
|
|
@@ -2188,6 +2284,14 @@ function WorkloadOverviewTab({
|
|
|
2188
2284
|
onNavigate={onNavigate}
|
|
2189
2285
|
onSwitchToTopology={onSwitchToTopology}
|
|
2190
2286
|
/>
|
|
2287
|
+
{observationGroups.length > 0 && (
|
|
2288
|
+
<ServingDependenciesCard
|
|
2289
|
+
title="Related resources"
|
|
2290
|
+
groups={observationGroups}
|
|
2291
|
+
onNavigate={onNavigate}
|
|
2292
|
+
onSwitchToTopology={onSwitchToTopology}
|
|
2293
|
+
/>
|
|
2294
|
+
)}
|
|
2191
2295
|
{extraContent}
|
|
2192
2296
|
</div>
|
|
2193
2297
|
</div>
|
|
@@ -3877,6 +3981,7 @@ function buildServingRelationshipGroups(relationships: Relationships | undefined
|
|
|
3877
3981
|
...(relationships.ingresses ?? []),
|
|
3878
3982
|
...(relationships.gateways ?? []),
|
|
3879
3983
|
...(relationships.routes ?? []),
|
|
3984
|
+
...(relationships.routedFrom ?? []),
|
|
3880
3985
|
])
|
|
3881
3986
|
return [
|
|
3882
3987
|
{ label: 'Services', refs: dedupeResourceRefs(relationships.services ?? []) },
|
|
@@ -3891,6 +3996,8 @@ function buildDependencyRelationshipGroups(relationships: Relationships | undefi
|
|
|
3891
3996
|
{ label: 'Autoscalers', refs: dedupeResourceRefs(relationships.scalers ?? []) },
|
|
3892
3997
|
{ label: 'Disruption budgets', refs: dedupeResourceRefs(relationships.pdbs ?? []) },
|
|
3893
3998
|
{ label: 'Network policies', refs: dedupeResourceRefs(relationships.networkPolicies ?? []) },
|
|
3999
|
+
{ label: 'Staged Policies', refs: dedupeResourceRefs(relationships.stagedPolicies ?? []) },
|
|
4000
|
+
{ label: 'Monitored By', refs: dedupeResourceRefs(relationships.monitors ?? []) },
|
|
3894
4001
|
{ label: 'Storage claims', refs: dedupeResourceRefs(relationships.resourceClaims ?? []) },
|
|
3895
4002
|
].filter((group) => group.refs.length > 0)
|
|
3896
4003
|
}
|
|
@@ -3990,12 +4097,21 @@ function mergeAndRankEvents(events: TimelineEvent[], updates: TimelineEvent[]):
|
|
|
3990
4097
|
})
|
|
3991
4098
|
}
|
|
3992
4099
|
|
|
4100
|
+
function orderTabs(tabs: DetailShellTab<TabType>[], order: string[] | undefined): DetailShellTab<TabType>[] {
|
|
4101
|
+
if (!order || order.length === 0) return tabs
|
|
4102
|
+
const rank = (id: string) => {
|
|
4103
|
+
const i = order.indexOf(id)
|
|
4104
|
+
return i < 0 ? order.length : i
|
|
4105
|
+
}
|
|
4106
|
+
return tabs.map((t, i) => ({ t, i })).sort((a, b) => rank(a.t.id) - rank(b.t.id) || a.i - b.i).map((x) => x.t)
|
|
4107
|
+
}
|
|
4108
|
+
|
|
3993
4109
|
function mergeExtraTabs(tabs: DetailShellTab<TabType>[], extra: WorkloadExtraTab[] | undefined): DetailShellTab<TabType>[] {
|
|
3994
4110
|
if (!extra || extra.length === 0) return tabs
|
|
3995
4111
|
const replaced = new Set(extra.map((x) => x.replaces).filter(Boolean))
|
|
3996
4112
|
const out = tabs.map((t) => (replaced.has(t.id) ? { ...t, hidden: true } : t))
|
|
3997
4113
|
for (const x of extra) {
|
|
3998
|
-
const tab: DetailShellTab<TabType> = { id: x.id as TabType, label: x.label, icon: x.icon }
|
|
4114
|
+
const tab: DetailShellTab<TabType> = { id: x.id as TabType, label: x.label, icon: x.icon, badge: x.badge }
|
|
3999
4115
|
const anchor = x.after ?? x.replaces
|
|
4000
4116
|
const idx = anchor ? out.findIndex((t) => t.id === anchor) : -1
|
|
4001
4117
|
if (idx >= 0) out.splice(idx + 1, 0, tab)
|
package/src/index.ts
CHANGED
|
@@ -55,7 +55,7 @@ export * from './components/checks'
|
|
|
55
55
|
// queue)
|
|
56
56
|
export * from './components/issues'
|
|
57
57
|
|
|
58
|
-
// CloudNativePG workspace model (fleet derivation over /api/cnpg/workspace)
|
|
58
|
+
// CloudNativePG workspace model (fleet derivation over /api/cnpg/workspace) and summaries
|
|
59
59
|
export * from './components/cnpg'
|
|
60
60
|
|
|
61
61
|
// Cluster switcher (shared trigger+dropdown for OSS Radar and Radar Hub)
|
|
@@ -82,3 +82,16 @@ export * from './components/compare'
|
|
|
82
82
|
|
|
83
83
|
// Perf instrumentation (ELK + structureKey timers, surfaced in diagnostics overlay)
|
|
84
84
|
export * from './perf'
|
|
85
|
+
|
|
86
|
+
export { CertaintyGlyph, certaintyGlyph, certaintyValueLabel, type Certainty } from './components/facts/certainty'
|
|
87
|
+
|
|
88
|
+
export * from './components/facts'
|
|
89
|
+
export {
|
|
90
|
+
WorkspaceProblemCallout,
|
|
91
|
+
ProblemList,
|
|
92
|
+
ProblemMeta,
|
|
93
|
+
OpenIssueContext,
|
|
94
|
+
problemOriginLabel,
|
|
95
|
+
type WorkspaceProblem,
|
|
96
|
+
type ProblemOrigin,
|
|
97
|
+
} from './components/problems'
|
package/src/monaco-deep.d.ts
CHANGED
|
@@ -1,15 +1,22 @@
|
|
|
1
|
+
// @monaco-editor/react and @monaco-editor/loader type monaco through this path,
|
|
2
|
+
// which monaco-editor's exports map does not serve.
|
|
1
3
|
declare module 'monaco-editor/esm/vs/editor/editor.api' {
|
|
2
|
-
export * from 'monaco-editor'
|
|
4
|
+
export * from 'monaco-editor/editor/editor.api'
|
|
3
5
|
}
|
|
4
6
|
|
|
5
|
-
declare module 'monaco-editor/
|
|
6
|
-
declare module 'monaco-editor/
|
|
7
|
-
declare module 'monaco-editor/
|
|
8
|
-
declare module 'monaco-editor/
|
|
9
|
-
declare module 'monaco-editor/
|
|
10
|
-
declare module 'monaco-editor/
|
|
11
|
-
declare module 'monaco-editor/
|
|
12
|
-
declare module 'monaco-editor/
|
|
13
|
-
declare module 'monaco-editor/
|
|
14
|
-
declare module 'monaco-editor/
|
|
15
|
-
declare module 'monaco-editor/
|
|
7
|
+
declare module 'monaco-editor/languages/definitions/yaml/register'
|
|
8
|
+
declare module 'monaco-editor/languages/definitions/xml/register'
|
|
9
|
+
declare module 'monaco-editor/languages/definitions/html/register'
|
|
10
|
+
declare module 'monaco-editor/languages/definitions/css/register'
|
|
11
|
+
declare module 'monaco-editor/languages/definitions/javascript/register'
|
|
12
|
+
declare module 'monaco-editor/languages/definitions/typescript/register'
|
|
13
|
+
declare module 'monaco-editor/languages/definitions/python/register'
|
|
14
|
+
declare module 'monaco-editor/languages/definitions/shell/register'
|
|
15
|
+
declare module 'monaco-editor/languages/definitions/markdown/register'
|
|
16
|
+
declare module 'monaco-editor/languages/definitions/ini/register'
|
|
17
|
+
declare module 'monaco-editor/languages/definitions/dockerfile/register'
|
|
18
|
+
declare module 'monaco-editor/editor/contrib/*'
|
|
19
|
+
declare module 'monaco-editor/editor/standalone/*'
|
|
20
|
+
declare module 'monaco-editor/editor/browser/*'
|
|
21
|
+
declare module 'monaco-editor/editor/common/*'
|
|
22
|
+
declare module 'monaco-editor/features/*'
|
package/src/theme/components.css
CHANGED
|
@@ -35,6 +35,19 @@
|
|
|
35
35
|
opacity: 0.5;
|
|
36
36
|
}
|
|
37
37
|
|
|
38
|
+
.btn-secondary {
|
|
39
|
+
border: 1px solid var(--border-default);
|
|
40
|
+
background-color: var(--bg-surface);
|
|
41
|
+
color: var(--text-primary);
|
|
42
|
+
border-radius: 0.625rem;
|
|
43
|
+
}
|
|
44
|
+
.btn-secondary:hover {
|
|
45
|
+
background-color: var(--bg-hover);
|
|
46
|
+
}
|
|
47
|
+
.btn-secondary:disabled {
|
|
48
|
+
opacity: 0.5;
|
|
49
|
+
}
|
|
50
|
+
|
|
38
51
|
.btn-brand-toggle {
|
|
39
52
|
background-color: color-mix(in srgb, var(--color-brand) 50%, transparent);
|
|
40
53
|
color: var(--text-primary);
|
package/src/types/capacity.ts
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import type { Issue } from "../components/issues/types";
|
|
2
|
+
import type { Certainty } from "../components/facts/certainty";
|
|
2
3
|
import type { NodeLifecycleObservation } from "../utils/node-lifecycle";
|
|
3
4
|
|
|
4
5
|
export const CAPACITY_SCHEMA_VERSION = "v1alpha1" as const;
|
|
@@ -16,8 +17,7 @@ export interface CapacityResourceIdentity {
|
|
|
16
17
|
uid?: string;
|
|
17
18
|
}
|
|
18
19
|
|
|
19
|
-
export type CapacityCertainty =
|
|
20
|
-
"exact" | "lower_bound" | "upper_bound" | "unknown";
|
|
20
|
+
export type CapacityCertainty = Certainty;
|
|
21
21
|
export type CapacityGranularity =
|
|
22
22
|
"aggregate" | "aggregate_not_binpacked" | "per_node";
|
|
23
23
|
export type CapacityResourceVector = Record<string, string>;
|
|
@@ -418,6 +418,14 @@ export interface CapacityScalingFact {
|
|
|
418
418
|
summary: string;
|
|
419
419
|
}
|
|
420
420
|
|
|
421
|
+
/** Published scale-down observations; candidates do not imply a removal ETA. */
|
|
422
|
+
export interface CapacityAutoscalerScaleDown {
|
|
423
|
+
status?: string;
|
|
424
|
+
candidates?: number;
|
|
425
|
+
lastTransitionTime?: string;
|
|
426
|
+
asOf?: string;
|
|
427
|
+
}
|
|
428
|
+
|
|
421
429
|
export interface CapacityAutoscalerBackoff {
|
|
422
430
|
errorClass?: string;
|
|
423
431
|
errorCode?: string;
|
|
@@ -440,6 +448,7 @@ export interface CapacityAutoscalerChildObservation {
|
|
|
440
448
|
readyNodes?: number;
|
|
441
449
|
totalNodes?: number;
|
|
442
450
|
backoff?: CapacityAutoscalerBackoff;
|
|
451
|
+
scaleDown?: CapacityAutoscalerScaleDown;
|
|
443
452
|
asOf?: string;
|
|
444
453
|
}
|
|
445
454
|
|
package/src/types/core.ts
CHANGED
|
@@ -164,12 +164,15 @@ export interface FeatureCapabilities {
|
|
|
164
164
|
yamlSchemas?: boolean
|
|
165
165
|
workloadImages?: boolean
|
|
166
166
|
resourceIssues?: boolean
|
|
167
|
+
resourceIssueCoverage?: boolean
|
|
167
168
|
podEnvironment?: boolean
|
|
168
169
|
policyResource?: boolean
|
|
169
170
|
workloadHistory?: boolean
|
|
171
|
+
cnpgWorkspace?: boolean
|
|
172
|
+
cnpgProtectionSetup?: boolean
|
|
173
|
+
gitopsWriteEvidence?: boolean
|
|
170
174
|
serviceEndpointSlices?: boolean
|
|
171
175
|
trafficRecords?: boolean
|
|
172
|
-
gitopsWriteEvidence?: boolean
|
|
173
176
|
}
|
|
174
177
|
|
|
175
178
|
// DeploymentMode is the closed set of topologies Radar can run in.
|
|
@@ -201,6 +204,7 @@ export type CoreNodeKind =
|
|
|
201
204
|
| 'HTTPRoute'
|
|
202
205
|
| 'GRPCRoute'
|
|
203
206
|
| 'TCPRoute'
|
|
207
|
+
| 'UDPRoute'
|
|
204
208
|
| 'TLSRoute'
|
|
205
209
|
| 'Service'
|
|
206
210
|
| 'Deployment'
|
|
@@ -639,6 +643,8 @@ export interface ResourceRef {
|
|
|
639
643
|
|
|
640
644
|
// Computed relationships for a resource
|
|
641
645
|
export interface Relationships {
|
|
646
|
+
/** Istio registry domain supplied by the producer; omitted when unknown. */
|
|
647
|
+
istioServiceDomain?: string
|
|
642
648
|
reflection?: {
|
|
643
649
|
source?: ResourceRef
|
|
644
650
|
sourceResourceVersion?: string
|
|
@@ -658,6 +664,13 @@ export interface Relationships {
|
|
|
658
664
|
storageRefs?: ResourceRef[]
|
|
659
665
|
dependencies?: ResourceRef[]
|
|
660
666
|
dependents?: ResourceRef[]
|
|
667
|
+
monitors?: ResourceRef[]
|
|
668
|
+
monitorTargets?: ResourceRef[]
|
|
669
|
+
backends?: ResourceRef[]
|
|
670
|
+
routedFrom?: ResourceRef[]
|
|
671
|
+
protects?: ResourceRef[]
|
|
672
|
+
healthChecks?: ResourceRef[]
|
|
673
|
+
stagedPolicies?: ResourceRef[]
|
|
661
674
|
scaleTarget?: ResourceRef
|
|
662
675
|
pdbs?: ResourceRef[] // PodDisruptionBudgets protecting this workload
|
|
663
676
|
networkPolicies?: ResourceRef[] // NetworkPolicy / CiliumNetworkPolicy / ClusterNetworkPolicy variants selecting this workload
|
|
@@ -728,6 +741,7 @@ export interface HPADiagnosis extends HPADiagnosisView {
|
|
|
728
741
|
name?: string
|
|
729
742
|
}
|
|
730
743
|
bounds: HPABounds
|
|
744
|
+
/** Spec order keeps source references paired with values; unmatched status entries follow. */
|
|
731
745
|
metrics?: HPAMetricSummary[]
|
|
732
746
|
}
|
|
733
747
|
|
|
@@ -785,6 +799,8 @@ export interface APIResource {
|
|
|
785
799
|
name: string // Plural name (e.g., "deployments")
|
|
786
800
|
namespaced: boolean
|
|
787
801
|
isCrd: boolean
|
|
802
|
+
/** Confirmed, readable cached CRD identity; never inferred from isCrd. */
|
|
803
|
+
definitionName?: string
|
|
788
804
|
featured?: boolean
|
|
789
805
|
verbs: string[]
|
|
790
806
|
observation?: DynamicResourceObservation
|
|
@@ -1073,12 +1089,23 @@ export interface UpgradeInfo {
|
|
|
1073
1089
|
error?: string
|
|
1074
1090
|
// Machine-readable source-resolution failure, used to make the Helm drawer
|
|
1075
1091
|
// explain whether tracking an OCI source can help.
|
|
1076
|
-
sourceIssue?: 'untracked' | 'repo_index_error' | 'ambiguous_repository'
|
|
1092
|
+
sourceIssue?: 'untracked' | 'repo_index_error' | 'ambiguous_repository' | 'ambiguous_source' | 'source_unavailable'
|
|
1077
1093
|
// True only when the error is a genuinely untracked source (registering a
|
|
1078
1094
|
// chart source could fix it). Kept for compatibility; prefer sourceIssue.
|
|
1079
1095
|
untracked?: boolean
|
|
1080
1096
|
}
|
|
1081
1097
|
|
|
1098
|
+
export type ChartSourceCandidate =
|
|
1099
|
+
| { type: 'repository'; reference: string; url: string }
|
|
1100
|
+
| { type: 'oci'; reference: string; url?: never }
|
|
1101
|
+
|
|
1102
|
+
export interface ChartSourceStatus {
|
|
1103
|
+
recorded?: ChartSourceCandidate
|
|
1104
|
+
configured: boolean
|
|
1105
|
+
available: boolean
|
|
1106
|
+
candidates?: ChartSourceCandidate[]
|
|
1107
|
+
}
|
|
1108
|
+
|
|
1082
1109
|
// Batch upgrade info keyed by "storageNamespace/name".
|
|
1083
1110
|
export interface BatchUpgradeInfo {
|
|
1084
1111
|
releases: Record<string, UpgradeInfo>
|
|
@@ -29,13 +29,44 @@ describe('fluxConditionsToGitOpsStatus truth table', () => {
|
|
|
29
29
|
})
|
|
30
30
|
|
|
31
31
|
it('treats the -1 sentinel as drift', () => {
|
|
32
|
-
|
|
32
|
+
// A first reconcile reports Ready=Unknown; a reported failure outranks drift.
|
|
33
|
+
const got = fluxConditionsToGitOpsStatus([c('Ready', 'Unknown'), c('Reconciling', 'True')], false, {
|
|
33
34
|
generation: 1,
|
|
34
35
|
observedGeneration: -1,
|
|
35
36
|
})
|
|
36
37
|
expect(got.sync).toBe('Reconciling')
|
|
37
38
|
})
|
|
38
39
|
|
|
40
|
+
it('a failure while retrying and never reconciled is degraded', () => {
|
|
41
|
+
// Live shape of a GitRepository whose repository doesn't exist.
|
|
42
|
+
const got = fluxConditionsToGitOpsStatus(
|
|
43
|
+
[c('Reconciling', 'True', { reason: 'ProgressingWithRetry' }), c('Ready', 'False', { reason: 'GitOperationFailed', observedGeneration: 1 })],
|
|
44
|
+
false,
|
|
45
|
+
{ generation: 1, observedGeneration: -1 },
|
|
46
|
+
)
|
|
47
|
+
expect(got.sync).toBe('OutOfSync')
|
|
48
|
+
expect(got.health).toBe('Degraded')
|
|
49
|
+
})
|
|
50
|
+
|
|
51
|
+
it('a failure about an older generation does not outrank a new spec', () => {
|
|
52
|
+
const got = fluxConditionsToGitOpsStatus([c('Ready', 'False', { reason: 'BuildFailed', observedGeneration: 2 })], false, {
|
|
53
|
+
generation: 3,
|
|
54
|
+
observedGeneration: 1,
|
|
55
|
+
})
|
|
56
|
+
expect(got.sync).toBe('Reconciling')
|
|
57
|
+
expect(got.health).toBe('Progressing')
|
|
58
|
+
})
|
|
59
|
+
|
|
60
|
+
it('a retry while reconciling stays progressing', () => {
|
|
61
|
+
const got = fluxConditionsToGitOpsStatus(
|
|
62
|
+
[c('Reconciling', 'True', { reason: 'Progressing' }), c('Ready', 'False', { reason: 'ProgressingWithRetry' })],
|
|
63
|
+
false,
|
|
64
|
+
{ generation: 2, observedGeneration: 1 },
|
|
65
|
+
)
|
|
66
|
+
expect(got.sync).toBe('Reconciling')
|
|
67
|
+
expect(got.health).toBe('Progressing')
|
|
68
|
+
})
|
|
69
|
+
|
|
39
70
|
it('does not treat an absent observedGeneration as drift', () => {
|
|
40
71
|
// Kinds and controller versions that never set it must not all read stale.
|
|
41
72
|
expect(fluxConditionsToGitOpsStatus([c('Ready', 'True')], false, { generation: 3 }).sync).toBe('Synced')
|