From 08d2787c83656b3c8ef13240c3a3fecc4c9c61e0 Mon Sep 17 00:00:00 2001 From: Alejandro Ruiz Date: Thu, 31 Oct 2024 13:33:39 +0100 Subject: [PATCH 01/28] Use BundleDeployment status to calculate GitRepo resources --- shell/components/fleet/FleetRepos.vue | 6 -- shell/config/labels-annotations.js | 1 + shell/models/fleet.cattle.io.gitrepo.js | 104 +++++++++++++----------- 3 files changed, 59 insertions(+), 52 deletions(-) diff --git a/shell/components/fleet/FleetRepos.vue b/shell/components/fleet/FleetRepos.vue index 2c0d4bae452..b1ad3d59bfe 100644 --- a/shell/components/fleet/FleetRepos.vue +++ b/shell/components/fleet/FleetRepos.vue @@ -118,12 +118,6 @@ export default { parseTargetMode(row) { return row.targetInfo?.mode === 'clusterGroup' ? this.t('fleet.gitRepo.warningTooltip.clusterGroup') : this.t('fleet.gitRepo.warningTooltip.cluster'); }, - - clusterViewResourceStatus(row) { - return row.clusterResourceStatus.find((c) => { - return c.metadata?.labels[FLEET.CLUSTER_NAME] === this.clusterId; - }); - } }, }; diff --git a/shell/config/labels-annotations.js b/shell/config/labels-annotations.js index 19209c14ad5..7e862ca9d99 100644 --- a/shell/config/labels-annotations.js +++ b/shell/config/labels-annotations.js @@ -111,6 +111,7 @@ export const FLEET = { CLUSTER_NAME: 'management.cattle.io/cluster-name', BUNDLE_ID: 'fleet.cattle.io/bundle-id', MANAGED: 'fleet.cattle.io/managed', + CLUSTER_NAMESPACE: 'fleet.cattle.io/cluster-namespace', CLUSTER: 'fleet.cattle.io/cluster' }; diff --git a/shell/models/fleet.cattle.io.gitrepo.js b/shell/models/fleet.cattle.io.gitrepo.js index 9c8ac614290..cc30aaa97e7 100644 --- a/shell/models/fleet.cattle.io.gitrepo.js +++ b/shell/models/fleet.cattle.io.gitrepo.js @@ -20,6 +20,39 @@ function quacksLikeAHash(str) { return false; } +function clusterIdFromLabels(labels) { + const clusterNamespace = labels?.[FLEET_ANNOTATIONS.CLUSTER_NAMESPACE]; + const clusterName = labels?.[FLEET_ANNOTATIONS.CLUSTER]; + + return `${ clusterNamespace }/${ clusterName }`; +} + +// bundleDeploymentResources extracts the list of resources deployed by a BundleDeployment +function bundleDeploymentResources(status) { + // Use a map to avoid `find` over and over again + const resourceKey = (r) => `${ r.kind }/${ r.namespace }/${ r.name }`; + + // status.resources includes of resources that were deployed by Fleet *and still exist in the cluster* + const resources = new Map((status?.resources || []).map((r) => [ + resourceKey(r), Object.assign({ state: STATES_ENUM.READY }, r)])); + + const modified = []; + + for (const r of status?.modifiedStatus || []) { + const state = r.create ? STATES_ENUM.MISSING : r.delete ? STATES_ENUM.ORPHANED : STATES_ENUM.MODIFIED; + const found = resources.get(resourceKey(r)); + + // Depending on the state, the same resource can appear in both fields + if (found) { + found.state = state; + } else { + modified.push(Object.assign({ state }, r)); + } + } + + return modified.concat(...resources.values()); +} + export default class GitRepo extends SteveModel { applyDefaults() { const spec = this.spec || {}; @@ -323,34 +356,16 @@ export default class GitRepo extends SteveModel { get resourcesStatuses() { const clusters = this.targetClusters || []; - const resources = this.status?.resources || []; - const conditions = this.status?.conditions || []; + const bundleDeployments = this.bundleDeployments || []; const out = []; - for (const c of clusters) { - const clusterBundleDeploymentResources = this.bundleDeployments - .find((bd) => bd.metadata?.labels?.[FLEET_ANNOTATIONS.CLUSTER] === c.metadata.name) - ?.status?.resources || []; - - resources.forEach((r, i) => { - let namespacedName = r.name; - - if (r.namespace) { - namespacedName = `${ r.namespace }:${ r.name }`; - } + for (const bd of bundleDeployments) { + const c = clusters.find((c) => clusterIdFromLabels(bd.metadata?.labels) === c.id); + const resources = bundleDeploymentResources(bd.status); - let state = r.state; - const perEntry = r.perClusterState?.find((x) => x.clusterId === c.id); - const tooMany = r.perClusterState?.length >= 10 || false; - - if (perEntry) { - state = perEntry.state; - } else if (tooMany) { - state = STATES_ENUM.UNKNOWN; - } else { - state = STATES_ENUM.READY; - } + resources.forEach((r) => { + const state = r.state; const color = colorForState(state).replace('text-', 'bg-'); const display = stateDisplay(state); @@ -367,26 +382,25 @@ export default class GitRepo extends SteveModel { }; out.push({ - key: `${ r.id }-${ c.id }-${ r.type }-${ r.namespace }-${ r.name }`, - tableKey: `${ r.id }-${ c.id }-${ r.type }-${ r.namespace }-${ r.name }-${ randomStr(8) }`, - kind: r.kind, - apiVersion: r.apiVersion, - type: r.type, - id: r.id, - namespace: r.namespace, - name: r.name, - clusterId: c.id, - clusterLabel: c.metadata.labels[FLEET_ANNOTATIONS.CLUSTER_NAME], - clusterName: c.nameDisplay, - state: mapStateToEnum(state), - stateBackground: color, - stateDisplay: display, - stateSort: stateSort(color, display), - namespacedName, + key: `${ r.id }-${ c.id }-${ r.type }-${ r.namespace }-${ r.name }`, + tableKey: `${ r.id }-${ c.id }-${ r.type }-${ r.namespace }-${ r.name }-${ randomStr(8) }`, + + // columns + state: mapStateToEnum(state), + clusterName: c.nameDisplay, + apiVersion: r.apiVersion, + kind: r.kind, + name: r.name, + namespace: r.namespace, + creationTimestamp: r.createdAt, + clusterId: c.id, + clusterLabel: c.metadata.labels[FLEET_ANNOTATIONS.CLUSTER_NAME], + + // other properties + stateBackground: color, + stateDisplay: display, + stateSort: stateSort(color, display), detailLocation, - conditions: conditions[i], - bundleDeploymentStatus: clusterBundleDeploymentResources?.[i], - creationTimestamp: clusterBundleDeploymentResources?.[i]?.createdAt }); }); } @@ -407,9 +421,7 @@ export default class GitRepo extends SteveModel { get clusterResourceStatus() { const clusterStatuses = this.resourcesStatuses.reduce((prev, curr) => { - const { clusterId, clusterLabel } = curr; - - const state = curr.state; + const { clusterId, clusterLabel, state } = curr; if (!prev[clusterId]) { prev[clusterId] = { From 4fa9d9226fc2aaec12546354352f2b60bf4b9480 Mon Sep 17 00:00:00 2001 From: Alejandro Ruiz Date: Thu, 31 Oct 2024 13:34:05 +0100 Subject: [PATCH 02/28] Exclude spec.resources when fetching bundles --- shell/pages/c/_cluster/fleet/index.vue | 1 + shell/utils/auth.js | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/shell/pages/c/_cluster/fleet/index.vue b/shell/pages/c/_cluster/fleet/index.vue index 5d73ac2a0c0..3c4261e6435 100644 --- a/shell/pages/c/_cluster/fleet/index.vue +++ b/shell/pages/c/_cluster/fleet/index.vue @@ -40,6 +40,7 @@ export default { allBundles: { inStoreType: 'management', type: FLEET.BUNDLE, + opt: { excludeFields: ['metadata.managedFields', 'spec.resources'] }, }, gitRepos: { inStoreType: 'management', diff --git a/shell/utils/auth.js b/shell/utils/auth.js index 162ce4009d6..9b08def3517 100644 --- a/shell/utils/auth.js +++ b/shell/utils/auth.js @@ -99,7 +99,7 @@ export const checkSchemasForFindAllHash = (types, store) => { const validSchema = value.schemaValidator ? value.schemaValidator(schema) : !!schema; if (validSchema) { - hash[key] = store.dispatch(`${ value.inStoreType }/findAll`, { type: value.type } ); + hash[key] = store.dispatch(`${ value.inStoreType }/findAll`, { type: value.type, opt: value.opt } ); } } From 044900539274116bde3458553549fadd4a1daabb Mon Sep 17 00:00:00 2001 From: Alejandro Ruiz Date: Thu, 31 Oct 2024 13:52:35 +0100 Subject: [PATCH 03/28] Avoid using spec for getting resources in Bundle details page --- shell/detail/fleet.cattle.io.bundle.vue | 64 +------------------------ 1 file changed, 2 insertions(+), 62 deletions(-) diff --git a/shell/detail/fleet.cattle.io.bundle.vue b/shell/detail/fleet.cattle.io.bundle.vue index d4ed8a0c8ea..06df257b92f 100644 --- a/shell/detail/fleet.cattle.io.bundle.vue +++ b/shell/detail/fleet.cattle.io.bundle.vue @@ -1,5 +1,4 @@