summaryrefslogtreecommitdiff
path: root/app/assets/javascripts/clusters_list/components/agent_table.vue
diff options
context:
space:
mode:
Diffstat (limited to 'app/assets/javascripts/clusters_list/components/agent_table.vue')
-rw-r--r--app/assets/javascripts/clusters_list/components/agent_table.vue152
1 files changed, 129 insertions, 23 deletions
diff --git a/app/assets/javascripts/clusters_list/components/agent_table.vue b/app/assets/javascripts/clusters_list/components/agent_table.vue
index 695e16b7b4b..61c4904aacf 100644
--- a/app/assets/javascripts/clusters_list/components/agent_table.vue
+++ b/app/assets/javascripts/clusters_list/components/agent_table.vue
@@ -1,23 +1,14 @@
<script>
import { GlLink, GlTable, GlIcon, GlSprintf, GlTooltip, GlPopover } from '@gitlab/ui';
-import { s__, __ } from '~/locale';
import TimeAgoTooltip from '~/vue_shared/components/time_ago_tooltip.vue';
import timeagoMixin from '~/vue_shared/mixins/timeago';
import { helpPagePath } from '~/helpers/help_page_helper';
-import { AGENT_STATUSES } from '../constants';
+import { AGENT_STATUSES, I18N_AGENT_TABLE } from '../constants';
import { getAgentConfigPath } from '../clusters_util';
-import AgentOptions from './agent_options.vue';
+import DeleteAgentButton from './delete_agent_button.vue';
export default {
- i18n: {
- nameLabel: s__('ClusterAgents|Name'),
- statusLabel: s__('ClusterAgents|Connection status'),
- lastContactLabel: s__('ClusterAgents|Last contact'),
- configurationLabel: s__('ClusterAgents|Configuration'),
- optionsLabel: __('Options'),
- troubleshootingText: s__('ClusterAgents|Learn how to troubleshoot'),
- neverConnectedText: s__('ClusterAgents|Never'),
- },
+ i18n: I18N_AGENT_TABLE,
components: {
GlLink,
GlTable,
@@ -26,13 +17,15 @@ export default {
GlTooltip,
GlPopover,
TimeAgoTooltip,
- AgentOptions,
+ DeleteAgentButton,
},
mixins: [timeagoMixin],
AGENT_STATUSES,
- troubleshooting_link: helpPagePath('user/clusters/agent/index', {
- anchor: 'troubleshooting',
+ troubleshootingLink: helpPagePath('user/clusters/agent/troubleshooting'),
+ versionUpdateLink: helpPagePath('user/clusters/agent/install/index', {
+ anchor: 'update-the-agent-version',
}),
+ inject: ['gitlabVersion'],
props: {
agents: {
required: true,
@@ -69,30 +62,93 @@ export default {
tdClass,
},
{
+ key: 'version',
+ label: this.$options.i18n.versionLabel,
+ tdClass,
+ },
+ {
key: 'configuration',
label: this.$options.i18n.configurationLabel,
tdClass,
},
{
key: 'options',
- label: this.$options.i18n.optionsLabel,
+ label: '',
tdClass,
},
];
},
+ agentsList() {
+ if (!this.agents.length) {
+ return [];
+ }
+
+ return this.agents.map((agent) => {
+ const versions = this.getAgentVersions(agent);
+ return { ...agent, versions };
+ });
+ },
},
methods: {
- getCellId(item) {
+ getStatusCellId(item) {
return `connection-status-${item.name}`;
},
+ getVersionCellId(item) {
+ return `version-${item.name}`;
+ },
+ getPopoverTestId(item) {
+ return `popover-${item.name}`;
+ },
getAgentConfigPath,
+ getAgentVersions(agent) {
+ const agentConnections = agent.connections?.nodes || [];
+
+ const agentVersions = agentConnections.map((agentConnection) =>
+ agentConnection.metadata.version.replace('v', ''),
+ );
+
+ const uniqueAgentVersions = [...new Set(agentVersions)];
+
+ return uniqueAgentVersions.sort((a, b) => a.localeCompare(b));
+ },
+ getAgentVersionString(agent) {
+ return agent.versions[0] || '';
+ },
+ isVersionMismatch(agent) {
+ return agent.versions.length > 1;
+ },
+ isVersionOutdated(agent) {
+ if (!agent.versions.length) return false;
+
+ const [agentMajorVersion, agentMinorVersion] = this.getAgentVersionString(agent).split('.');
+ const [gitlabMajorVersion, gitlabMinorVersion] = this.gitlabVersion.split('.');
+
+ const majorVersionMismatch = agentMajorVersion !== gitlabMajorVersion;
+
+ // We should warn user if their current GitLab and agent versions are more than 1 minor version apart:
+ const minorVersionMismatch = Math.abs(agentMinorVersion - gitlabMinorVersion) > 1;
+
+ return majorVersionMismatch || minorVersionMismatch;
+ },
+
+ getVersionPopoverTitle(agent) {
+ if (this.isVersionMismatch(agent) && this.isVersionOutdated(agent)) {
+ return this.$options.i18n.versionMismatchOutdatedTitle;
+ } else if (this.isVersionMismatch(agent)) {
+ return this.$options.i18n.versionMismatchTitle;
+ } else if (this.isVersionOutdated(agent)) {
+ return this.$options.i18n.versionOutdatedTitle;
+ }
+
+ return null;
+ },
},
};
</script>
<template>
<gl-table
- :items="agents"
+ :items="agentsList"
:fields="fields"
stacked="md"
head-variant="white"
@@ -107,19 +163,23 @@ export default {
</template>
<template #cell(status)="{ item }">
- <span :id="getCellId(item)" class="gl-md-pr-5" data-testid="cluster-agent-connection-status">
+ <span
+ :id="getStatusCellId(item)"
+ class="gl-md-pr-5"
+ data-testid="cluster-agent-connection-status"
+ >
<span :class="$options.AGENT_STATUSES[item.status].class" class="gl-mr-3">
<gl-icon :name="$options.AGENT_STATUSES[item.status].icon" :size="12" /></span
>{{ $options.AGENT_STATUSES[item.status].name }}
</span>
- <gl-tooltip v-if="item.status === 'active'" :target="getCellId(item)" placement="right">
+ <gl-tooltip v-if="item.status === 'active'" :target="getStatusCellId(item)" placement="right">
<gl-sprintf :message="$options.AGENT_STATUSES[item.status].tooltip.title"
><template #timeAgo>{{ timeFormatted(item.lastContact) }}</template>
</gl-sprintf>
</gl-tooltip>
<gl-popover
v-else
- :target="getCellId(item)"
+ :target="getStatusCellId(item)"
:title="$options.AGENT_STATUSES[item.status].tooltip.title"
placement="right"
container="viewport"
@@ -130,7 +190,7 @@ export default {
>
</p>
<p class="gl-mb-0">
- <gl-link :href="$options.troubleshooting_link" target="_blank" class="gl-font-sm">
+ <gl-link :href="$options.troubleshootingLink" target="_blank" class="gl-font-sm">
{{ $options.i18n.troubleshootingText }}</gl-link
>
</p>
@@ -144,6 +204,52 @@ export default {
</span>
</template>
+ <template #cell(version)="{ item }">
+ <span :id="getVersionCellId(item)" data-testid="cluster-agent-version">
+ {{ getAgentVersionString(item) }}
+
+ <gl-icon
+ v-if="isVersionMismatch(item) || isVersionOutdated(item)"
+ name="warning"
+ class="gl-text-orange-500 gl-ml-2"
+ />
+ </span>
+
+ <gl-popover
+ v-if="isVersionMismatch(item) || isVersionOutdated(item)"
+ :target="getVersionCellId(item)"
+ :title="getVersionPopoverTitle(item)"
+ :data-testid="getPopoverTestId(item)"
+ placement="right"
+ container="viewport"
+ >
+ <div v-if="isVersionMismatch(item) && isVersionOutdated(item)">
+ <p>{{ $options.i18n.versionMismatchText }}</p>
+
+ <p class="gl-mb-0">
+ <gl-sprintf :message="$options.i18n.versionOutdatedText">
+ <template #version>{{ gitlabVersion }}</template>
+ </gl-sprintf>
+ <gl-link :href="$options.versionUpdateLink" class="gl-font-sm">
+ {{ $options.i18n.viewDocsText }}</gl-link
+ >
+ </p>
+ </div>
+ <p v-else-if="isVersionMismatch(item)" class="gl-mb-0">
+ {{ $options.i18n.versionMismatchText }}
+ </p>
+
+ <p v-else-if="isVersionOutdated(item)" class="gl-mb-0">
+ <gl-sprintf :message="$options.i18n.versionOutdatedText">
+ <template #version>{{ gitlabVersion }}</template>
+ </gl-sprintf>
+ <gl-link :href="$options.versionUpdateLink" class="gl-font-sm">
+ {{ $options.i18n.viewDocsText }}</gl-link
+ >
+ </p>
+ </gl-popover>
+ </template>
+
<template #cell(configuration)="{ item }">
<span data-testid="cluster-agent-configuration-link">
<gl-link v-if="item.configFolder" :href="item.configFolder.webPath">
@@ -155,7 +261,7 @@ export default {
</template>
<template #cell(options)="{ item }">
- <agent-options
+ <delete-agent-button
:agent="item"
:default-branch-name="defaultBranchName"
:max-agents="maxAgents"