Skip to content

Commit

Permalink
Merge pull request #10755 from torchiaf/10738-flee-agent
Browse files Browse the repository at this point in the history
Fetch `statefulset` resource to calculate fleet agent status
  • Loading branch information
torchiaf committed Apr 9, 2024
2 parents e6c4d01 + 074efb4 commit 31502d1
Show file tree
Hide file tree
Showing 2 changed files with 139 additions and 76 deletions.
92 changes: 65 additions & 27 deletions shell/pages/c/_cluster/explorer/__tests__/index.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,8 @@ describe('page: cluster dashboard', () => {
const mountOptions = {
computed: { monitoringStatus: () => ({ v2: true }) },
stubs: {
'n-link': true,
LiveDate: true
'router-link': true,
LiveDate: true
},
mocks: {
$store: {
Expand Down Expand Up @@ -62,41 +62,60 @@ describe('page: cluster dashboard', () => {
});

describe.each([
['fleet', true, [
[STATES_ENUM.IN_PROGRESS, 'icon-spinner', false, false, '', 0, 0],
[STATES_ENUM.UNHEALTHY, 'icon-warning', true, false, [{ status: 'False' }], 0, 0],
[STATES_ENUM.WARNING, 'icon-warning', true, true, [{ status: 'True' }], 0, 0],
[STATES_ENUM.WARNING, 'icon-warning', true, false, [{ status: 'True' }], 0, 0],
[STATES_ENUM.WARNING, 'icon-warning', true, false, [{ status: 'True' }], 0, 1],
[STATES_ENUM.HEALTHY, 'icon-checkmark', true, false, [{ status: 'True' }], 1, 0],
['local', 'fleet', true, ['fleetDeployment', 'fleetStatefulSet'], [
[STATES_ENUM.IN_PROGRESS, 'icon-spinner', false, false, false, '', 0, 0],
[STATES_ENUM.UNHEALTHY, 'icon-warning', true, false, false, [{ status: 'False' }], 0, 0],
[STATES_ENUM.UNHEALTHY, 'icon-warning', true, false, true, [{ status: 'True' }], 0, 0],
[STATES_ENUM.WARNING, 'icon-warning', true, true, false, [{ status: 'True' }], 0, 0],
[STATES_ENUM.WARNING, 'icon-warning', true, false, false, [{ status: 'True' }], 0, 0],
[STATES_ENUM.WARNING, 'icon-warning', true, false, false, [{ status: 'True' }], 0, 1],
[STATES_ENUM.HEALTHY, 'icon-checkmark', true, false, false, [{ status: 'True' }], 1, 0],
]],
['cattle', false, [
[STATES_ENUM.IN_PROGRESS, 'icon-spinner', false, false, '', 0, 0],
[STATES_ENUM.UNHEALTHY, 'icon-warning', true, false, [{ status: 'False' }], 0, 0],
[STATES_ENUM.UNHEALTHY, 'icon-warning', true, true, [{ status: 'True' }], 0, 0],
[STATES_ENUM.WARNING, 'icon-warning', true, false, [{ status: 'True' }], 0, 0],
[STATES_ENUM.WARNING, 'icon-warning', true, false, [{ status: 'True' }], 0, 1],
[STATES_ENUM.HEALTHY, 'icon-checkmark', true, false, [{ status: 'True' }], 1, 0],
['downstream RKE2', 'fleet', false, ['fleetStatefulSet'], [
[STATES_ENUM.IN_PROGRESS, 'icon-spinner', false, false, false, '', 0, 0],
[STATES_ENUM.UNHEALTHY, 'icon-warning', true, false, false, [{ status: 'False' }], 0, 0],
[STATES_ENUM.UNHEALTHY, 'icon-warning', true, false, true, [{ status: 'True' }], 0, 0],
[STATES_ENUM.WARNING, 'icon-warning', true, true, false, [{ status: 'True' }], 0, 0],
[STATES_ENUM.WARNING, 'icon-warning', true, false, false, [{ status: 'True' }], 0, 0],
[STATES_ENUM.WARNING, 'icon-warning', true, false, false, [{ status: 'True' }], 0, 1],
[STATES_ENUM.HEALTHY, 'icon-checkmark', true, false, false, [{ status: 'True' }], 1, 0],
]],
['downstream RKE2', 'cattle', false, ['cattleDeployment'], [
[STATES_ENUM.IN_PROGRESS, 'icon-spinner', false, false, false, '', 0, 0],
[STATES_ENUM.UNHEALTHY, 'icon-warning', true, false, false, [{ status: 'False' }], 0, 0],
[STATES_ENUM.UNHEALTHY, 'icon-warning', true, true, false, [{ status: 'True' }], 0, 0],
[STATES_ENUM.UNHEALTHY, 'icon-warning', true, false, true, [{ status: 'True' }], 0, 0],
[STATES_ENUM.WARNING, 'icon-warning', true, false, false, [{ status: 'True' }], 0, 0],
[STATES_ENUM.WARNING, 'icon-warning', true, false, false, [{ status: 'True' }], 0, 1],
[STATES_ENUM.HEALTHY, 'icon-checkmark', true, false, false, [{ status: 'True' }], 1, 0],
]]
])('%p agent health box', (agentId, isLocal, statuses) => {
it.each(statuses)('should show %p status', (status, iconClass, isLoaded, disconnected, conditions, readyReplicas, unavailableReplicas) => {
])('%p cluster - %p agent health box', (_, agentId, isLocal, agentResources, statuses) => {
it.each(statuses)('should show %p status', (status, iconClass, isLoaded, disconnected, error, conditions, readyReplicas, unavailableReplicas) => {
const options = clone(mountOptions);

options.mocks.$store.getters.currentCluster.isLocal = isLocal;

const agent = {
spec: { replicas: 1 },
status: {
readyReplicas,
unavailableReplicas,
conditions
}
};
const resources = agentResources.reduce((acc, r) => {
const agent = {
metadata: { state: { error } },
spec: { replicas: 1 },
status: {
readyReplicas,
unavailableReplicas,
conditions
}
};

return isLoaded ? {
...acc,
[r]: agent
} : 'loading';
}, {});

const wrapper = shallowMount(Dashboard, {
...options,
data: () => ({
[agentId]: isLoaded ? agent : 'loading',
...resources,
disconnected,
canViewAgents: true
})
Expand All @@ -110,4 +129,23 @@ describe('page: cluster dashboard', () => {
expect(icon.element.classList).toContain(iconClass);
});
});

it('local cluster - cattle agent health box - should be hidden', () => {
const options = clone(mountOptions);

options.mocks.$store.getters.currentCluster.isLocal = true;

const wrapper = shallowMount(Dashboard, {
...options,
data: () => ({
cattleDeployment: 'loading',
disconnected: false,
canViewAgents: true
})
});

const box = wrapper.find(`[data-testid="k8s-service-cattle"]`);

expect(box.element).toBeUndefined();
});
});
123 changes: 74 additions & 49 deletions shell/pages/c/_cluster/explorer/index.vue
Original file line number Diff line number Diff line change
Expand Up @@ -83,7 +83,7 @@ export default {
mixins: [metricPoller],
async fetch() {
fetch() {
fetchClusterResources(this.$store, NODE);
if (this.currentCluster) {
Expand Down Expand Up @@ -114,7 +114,11 @@ export default {
this.$store.dispatch('management/findAll', { type: MANAGEMENT.NODE });
}
await this.loadAgents();
this.canViewAgents = this.$store.getters['cluster/canList'](WORKLOAD_TYPES.DEPLOYMENT) && this.$store.getters['cluster/canList'](WORKLOAD_TYPES.STATEFUL_SET);
if (this.canViewAgents) {
this.loadAgents();
}
}
},
Expand All @@ -129,8 +133,9 @@ export default {
return {
nodeHeaders,
constraints: [],
cattle: 'loading',
fleet: 'loading',
cattleDeployment: 'loading',
fleetDeployment: 'loading',
fleetStatefulSet: 'loading',
canViewAgents: false,
disconnected: false,
events: [],
Expand Down Expand Up @@ -228,21 +233,65 @@ export default {
if (!this.currentCluster.isLocal) {
services.push({
name: 'cattle',
status: this.getAgentStatus(this.cattle, this.disconnected),
status: this.cattleStatus,
labelKey: 'clusterIndexPage.sections.componentStatus.cattle',
});
}
services.push({
name: 'fleet',
status: this.getAgentStatus(this.fleet),
status: this.fleetStatus,
labelKey: 'clusterIndexPage.sections.componentStatus.fleet',
});
}
return services;
},
cattleStatus() {
const resource = this.cattleDeployment;
if (resource === 'loading') {
return STATES_ENUM.IN_PROGRESS;
}
if (!resource || this.disconnected || resource.status.conditions?.find((c) => c.status !== 'True') || resource.metadata.state?.error) {
return STATES_ENUM.UNHEALTHY;
}
if (resource.spec.replicas !== resource.status.readyReplicas || resource.status.unavailableReplicas > 0) {
return STATES_ENUM.WARNING;
}
return STATES_ENUM.HEALTHY;
},
fleetStatus() {
const resources = [this.fleetStatefulSet];
if (this.currentCluster.isLocal) {
resources.push(this.fleetDeployment);
}
if (resources.find((r) => r === 'loading')) {
return STATES_ENUM.IN_PROGRESS;
}
for (const resource of resources) {
if (!resource || resource.status.conditions?.find((c) => c.status !== 'True') || resource.metadata.state?.error) {
return STATES_ENUM.UNHEALTHY;
}
}
for (const resource of resources) {
if (resource.spec.replicas !== resource.status.readyReplicas || resource.status.unavailableReplicas > 0) {
return STATES_ENUM.WARNING;
}
}
return STATES_ENUM.HEALTHY;
},
totalCountGaugeInput() {
const totalInput = {
name: this.t('clusterIndexPage.resourceGauge.totalResources'),
Expand Down Expand Up @@ -389,34 +438,26 @@ export default {
},
methods: {
async loadAgents() {
this.canViewAgents = !!this.$store.getters['cluster/schemaFor'](WORKLOAD_TYPES.DEPLOYMENT);
if (this.canViewAgents) {
if (!this.currentCluster.isLocal) {
try {
this.cattle = await this.$store.dispatch('cluster/find', {
type: WORKLOAD_TYPES.DEPLOYMENT,
id: 'cattle-system/cattle-cluster-agent'
});
} catch (err) {
this.cattle = null;
}
// Scaling Up/Down cattle deployment causes web sockets disconnection;
this.interval = setInterval(() => {
this.disconnected = !!this.$store.getters['cluster/inError']({ type: NODE });
}, 1000);
}
loadAgents() {
if (this.currentCluster.isLocal) {
this.setAgentResource('fleetDeployment', WORKLOAD_TYPES.DEPLOYMENT, 'cattle-fleet-system/fleet-controller');
this.setAgentResource('fleetStatefulSet', WORKLOAD_TYPES.STATEFUL_SET, 'cattle-fleet-local-system/fleet-agent');
} else {
this.setAgentResource('fleetStatefulSet', WORKLOAD_TYPES.STATEFUL_SET, 'cattle-fleet-system/fleet-agent');
this.setAgentResource('cattleDeployment', WORKLOAD_TYPES.DEPLOYMENT, 'cattle-system/cattle-cluster-agent');
// Scaling Up/Down cattle deployment causes web sockets disconnection;
this.interval = setInterval(() => {
this.disconnected = !!this.$store.getters['cluster/inError']({ type: NODE });
}, 1000);
}
},
try {
this.fleet = await this.$store.dispatch('cluster/find', {
type: WORKLOAD_TYPES.DEPLOYMENT,
id: `cattle-fleet-system/${ this.currentCluster.isLocal ? 'fleet-controller' : 'fleet-agent' }`,
});
} catch (err) {
this.fleet = null;
}
async setAgentResource(agent, type, id) {
try {
this[agent] = await this.$store.dispatch('cluster/find', { type, id });
} catch (err) {
this[agent] = null;
}
},
Expand All @@ -441,22 +482,6 @@ export default {
return STATES_ENUM.HEALTHY;
},
getAgentStatus(agent, disconnected = false) {
if (agent === 'loading') {
return STATES_ENUM.IN_PROGRESS;
}
if (!agent || disconnected || agent.status.conditions.find((c) => c.status !== 'True')) {
return STATES_ENUM.UNHEALTHY;
}
if (agent.spec.replicas !== agent.status.readyReplicas || agent.status.unavailableReplicas > 0) {
return STATES_ENUM.WARNING;
}
return STATES_ENUM.HEALTHY;
},
showActions() {
this.$store.commit('action-menu/show', {
resources: this.currentCluster,
Expand Down

0 comments on commit 31502d1

Please sign in to comment.