Skip to content
Snippets Groups Projects
Verified Commit 3303b2d8 authored by Enrique Alcántara's avatar Enrique Alcántara
Browse files

Display unmapped agents in Agent authorization UI

Display unmapped agents in the Agent Authorization UI.
The user can choose to display unmapped agents by clicking
the All Agents tab
parent b4084df1
No related branches found
No related tags found
2 merge requests!162233Draft: Script to update Topology Service Gem,!153254Display unmapped agents in Agent authorization UI
Showing
with 487 additions and 106 deletions
<script>
import { GlAlert } from '@gitlab/ui';
import { s__ } from '~/locale';
import { GlAlert, GlTabs, GlTab, GlBadge } from '@gitlab/ui';
import { s__, sprintf } from '~/locale';
import { AGENT_MAPPING_STATUS_MAPPED } from '../constants';
import AgentsTable from './agents_table.vue';
import GetAvailableAgentsQuery from './get_available_agents_query.vue';
import GetAgentsWithMappingStatusQuery from './get_agents_with_mapping_status_query.vue';
const NO_ALLOWED_AGENTS_MESSAGE = s__(
'Workspaces|This group has no available agents. Select the All agents tab and allow at least one agent.',
'Workspaces|This group has no available agents. Select the %{strongStart}All agents%{strongEnd} tab and allow at least one agent.',
);
const NO_AGENTS_MESSAGE = s__('Workspaces|This group has no agents. Start by creating an agent.');
const ERROR_LOADING_AVAILABLE_AGENTS_MESSAGE = s__(
'Workspaces|Could not load available agents. Refresh the page to try again.',
);
......@@ -14,8 +16,11 @@ const ERROR_LOADING_AVAILABLE_AGENTS_MESSAGE = s__(
export default {
components: {
GlAlert,
GlBadge,
GlTabs,
GlTab,
AgentsTable,
GetAvailableAgentsQuery,
GetAgentsWithMappingStatusQuery,
},
inject: {
namespace: {
......@@ -28,35 +33,74 @@ export default {
errorMessage: '',
};
},
computed: {
allowedAgents() {
return this.agents.filter((agent) => agent.mappingStatus === AGENT_MAPPING_STATUS_MAPPED);
},
allowedAgentsTableEmptyMessage() {
return this.agents.length
? sprintf(
NO_ALLOWED_AGENTS_MESSAGE,
{ strongStart: '<strong>', strongEnd: '</strong>' },
false,
)
: NO_AGENTS_MESSAGE;
},
},
methods: {
onGetAvailableAgentsQueryResult({ agents }) {
onQueryResult({ agents }) {
this.agents = agents;
},
onGetAvailableAgentsQueryError() {
onErrorResult() {
this.errorMessage = ERROR_LOADING_AVAILABLE_AGENTS_MESSAGE;
},
},
NO_ALLOWED_AGENTS_MESSAGE,
NO_AGENTS_MESSAGE,
};
</script>
<template>
<div>
<get-available-agents-query
:namespace="namespace"
@result="onGetAvailableAgentsQueryResult"
@error="onGetAvailableAgentsQueryError"
>
<template #default="{ loading }">
<gl-alert v-if="errorMessage" variant="danger" :dismissible="false">
<get-agents-with-mapping-status-query
:namespace="namespace"
@result="onQueryResult"
@error="onErrorResult"
>
<template #default="{ loading }">
<div>
<gl-alert v-if="errorMessage" class="mb-3" variant="danger" :dismissible="false">
{{ errorMessage }}
</gl-alert>
<agents-table
v-else
:agents="agents"
:is-loading="loading"
:empty-state-message="$options.NO_ALLOWED_AGENTS_MESSAGE"
/>
</template>
</get-available-agents-query>
</div>
<gl-tabs lazy>
<gl-tab data-testid="allowed-agents-tab">
<template #title>
<span>{{ s__('Workspaces|Allowed Agents') }}</span>
<gl-badge size="sm" class="gl-tab-counter-badge">{{ allowedAgents.length }}</gl-badge>
<span class="sr-only">{{ __('agents') }}</span>
</template>
<agents-table
v-if="!errorMessage"
data-testid="allowed-agents-table"
:agents="allowedAgents"
:is-loading="loading"
:empty-state-message="allowedAgentsTableEmptyMessage"
/>
</gl-tab>
<gl-tab data-testid="all-agents-tab">
<template #title>
<span>{{ s__('Workspaces|All agents') }}</span>
<gl-badge size="sm" class="gl-tab-counter-badge">{{ agents.length }}</gl-badge>
<span class="sr-only">{{ __('agents') }}</span>
</template>
<agents-table
v-if="!errorMessage"
data-testid="all-agents-table"
:agents="agents"
:is-loading="loading"
display-mapping-status
:empty-state-message="$options.NO_AGENTS_MESSAGE"
/>
</gl-tab>
</gl-tabs>
</div>
</template>
</get-agents-with-mapping-status-query>
</template>
<script>
import { GlSkeletonLoader, GlTable, GlCard } from '@gitlab/ui';
import { __ } from '~/locale';
import SafeHtml from '~/vue_shared/directives/safe_html';
import { AGENT_MAPPING_STATUS_MAPPED, AGENT_MAPPING_STATUS_UNMAPPED } from '../constants';
const AGENT_MAPPING_STATUS_LABELS = {
[AGENT_MAPPING_STATUS_MAPPED]: __('Allowed'),
[AGENT_MAPPING_STATUS_UNMAPPED]: __('Blocked'),
};
const NAME_FIELD = {
key: 'name',
label: __('Name'),
sortable: true,
};
const MAPPING_STATUS_LABEL_FIELD = {
key: 'mappingStatusLabel',
label: __('Availability'),
sortable: true,
};
export default {
components: {
......@@ -8,6 +27,9 @@ export default {
GlTable,
GlCard,
},
directives: {
SafeHtml,
},
props: {
agents: {
type: Array,
......@@ -22,14 +44,29 @@ export default {
required: false,
default: false,
},
displayMappingStatus: {
type: Boolean,
required: false,
default: false,
},
},
fields: [
{
key: 'name',
label: __('Name'),
sortable: true,
computed: {
agentsWithStatusLabels() {
return this.agents.map((agent) => ({
...agent,
mappingStatusLabel: AGENT_MAPPING_STATUS_LABELS[agent.mappingStatus],
}));
},
fields() {
const fields = [NAME_FIELD];
if (this.displayMappingStatus) {
fields.push(MAPPING_STATUS_LABEL_FIELD);
}
return fields;
},
],
},
};
</script>
<template>
......@@ -37,13 +74,16 @@ export default {
<div v-if="isLoading" class="p-3 flex justify-start">
<gl-skeleton-loader :lines="4" :equal-width-lines="true" :width="600" />
</div>
<gl-table v-else :fields="$options.fields" :items="agents" show-empty stacked="sm">
<gl-table v-else :fields="fields" :items="agentsWithStatusLabels" show-empty stacked="sm">
<template #empty>
<div class="text-center">{{ emptyStateMessage }}</div>
<div v-safe-html="emptyStateMessage" class="text-center"></div>
</template>
<template #cell(name)="{ item }">
<span data-testid="agent-name">{{ item.name }}</span>
</template>
<template v-if="displayMappingStatus" #cell(mappingStatusLabel)="{ item }">
<span data-testid="agent-mapping-status-label">{{ item.mappingStatusLabel }}</span>
</template>
</gl-table>
</gl-card>
</template>
<script>
import { logError } from '~/lib/logger';
import getRemoteDevelopmentClusterAgentsQuery from 'ee/workspaces/common/graphql/queries/get_remote_development_cluster_agents.query.graphql';
import getAgentsWithAuthorizationStatusQuery from '../graphql/queries/get_agents_with_mapping_status.query.graphql';
import { AGENT_MAPPING_STATUS_MAPPED, AGENT_MAPPING_STATUS_UNMAPPED } from '../constants';
export default {
props: {
......@@ -11,8 +12,8 @@ export default {
},
},
apollo: {
getRemoteDevelopmentClusterAgents: {
query: getRemoteDevelopmentClusterAgentsQuery,
getGroupClusterAgents: {
query: getAgentsWithAuthorizationStatusQuery,
variables() {
return {
namespace: this.namespace,
......@@ -33,11 +34,22 @@ export default {
return;
}
const { remoteDevelopmentClusterAgents, clusterAgents } = result.data.group;
const agents =
result.data.namespace?.remoteDevelopmentClusterAgents?.nodes.map(({ id, name }) => ({
id,
name,
})) || [];
clusterAgents?.nodes.map(({ id, name }) => {
const mappingStatus = remoteDevelopmentClusterAgents?.nodes.some(
(agent) => agent.id === id,
)
? AGENT_MAPPING_STATUS_MAPPED
: AGENT_MAPPING_STATUS_UNMAPPED;
return {
id,
name,
mappingStatus,
};
}) || [];
this.$emit('result', { agents });
},
......
export const AGENT_MAPPING_STATUS_MAPPED = 'mapped';
export const AGENT_MAPPING_STATUS_UNMAPPED = 'unmapped';
query getAgentsWithMappingStatus($namespace: ID!) {
group(fullPath: $namespace) {
id
remoteDevelopmentClusterAgents(filter: AVAILABLE) {
nodes {
id
name
}
}
clusterAgents {
nodes {
id
name
}
}
}
}
......@@ -35,7 +35,7 @@
end
end
context 'when there are available agents' do
context 'when there are mapped agents' do
let_it_be(:cluster_agent_mapping) do
create(
:remote_development_namespace_cluster_agent_mapping,
......@@ -48,5 +48,29 @@
expect(page).to have_content agent.name
end
end
context 'when there are mapped and unmapped agents' do
let_it_be(:agent_two) do
create(:ee_cluster_agent, :with_remote_development_agent_config, project: project, created_by_user: user)
end
let_it_be(:cluster_agent_mapping) do
create(
:remote_development_namespace_cluster_agent_mapping,
user: user, agent: agent,
namespace: group
)
end
it 'displays all agents in the All agents tab with availability status' do
click_link 'All agents'
expect(page).to have_content agent.name
expect(page).to have_content agent_two.name
expect(page).to have_content 'Allowed'
expect(page).to have_content 'Blocked'
end
end
end
end
import { GlAlert } from '@gitlab/ui';
import { shallowMount } from '@vue/test-utils';
import { nextTick } from 'vue';
import { GlAlert, GlTabs, GlTab, GlBadge } from '@gitlab/ui';
import { shallowMountExtended } from 'helpers/vue_test_utils_helper';
import {
AGENT_MAPPING_STATUS_MAPPED,
AGENT_MAPPING_STATUS_UNMAPPED,
} from 'ee/workspaces/agent_mapping/constants';
import AgentMapping from 'ee_component/workspaces/agent_mapping/components/agent_mapping.vue';
import AgentsTable from 'ee_component/workspaces/agent_mapping/components/agents_table.vue';
import GetAvailableAgentsQuery from 'ee_component/workspaces/agent_mapping/components/get_available_agents_query.vue';
import GetAgentsWithMappingStatusQuery from 'ee_component/workspaces/agent_mapping/components/get_agents_with_mapping_status_query.vue';
import { stubComponent } from 'helpers/stub_component';
describe('workspaces/agent_mapping/components/agent_mapping.vue', () => {
......@@ -10,22 +15,29 @@ describe('workspaces/agent_mapping/components/agent_mapping.vue', () => {
const NAMESPACE = 'foo/bar';
const buildWrapper = ({ mappedAgentsQueryState = {} } = {}) => {
wrapper = shallowMount(AgentMapping, {
wrapper = shallowMountExtended(AgentMapping, {
provide: {
namespace: NAMESPACE,
},
stubs: {
GetAvailableAgentsQuery: stubComponent(GetAvailableAgentsQuery, {
GetAgentsWithMappingStatusQuery: stubComponent(GetAgentsWithMappingStatusQuery, {
render() {
return this.$scopedSlots.default?.(mappedAgentsQueryState);
},
}),
GlTabs,
GlTab,
GlBadge,
},
});
};
const findGetAvailableAgentsQuery = () => wrapper.findComponent(GetAvailableAgentsQuery);
const findAgentsTable = () => wrapper.findComponent(AgentsTable);
const findGetAgentsWithMappingStatusQuery = () =>
wrapper.findComponent(GetAgentsWithMappingStatusQuery);
const findAllowedAgentsTable = () => wrapper.findByTestId('allowed-agents-table');
const findAllAgentsTable = () => wrapper.findByTestId('all-agents-table');
const findErrorAlert = () => wrapper.findComponent(GlAlert);
const findAllowedAgentsTab = () => wrapper.findByTestId('allowed-agents-tab');
const findAllAgentsTab = () => wrapper.findByTestId('all-agents-tab');
describe('default', () => {
beforeEach(() => {
......@@ -38,61 +50,141 @@ describe('workspaces/agent_mapping/components/agent_mapping.vue', () => {
});
describe('available agents table', () => {
it('renders GetAvailableAgentsQuery component and passes namespace path', () => {
it('renders GetAgentsWithMappingStatusQuery component and passes namespace path', () => {
buildWrapper();
expect(findGetAvailableAgentsQuery().props('namespace')).toBe(NAMESPACE);
expect(findGetAgentsWithMappingStatusQuery().props('namespace')).toBe(NAMESPACE);
});
describe('when GetAvailableAgentsQuery component emits results event', () => {
describe('when GetAgentsWithMappingStatusQuery component emits result event', () => {
let agents;
let allowedAgents;
beforeEach(() => {
beforeEach(async () => {
buildWrapper();
agents = [{}];
findGetAvailableAgentsQuery().vm.$emit('result', { agents });
agents = [
{
id: 'agent-1',
name: 'agent one',
mappingStatus: AGENT_MAPPING_STATUS_MAPPED,
},
{
id: 'agent-2',
name: 'agent two',
mappingStatus: AGENT_MAPPING_STATUS_UNMAPPED,
},
{
id: 'agent-3',
name: 'agent three',
mappingStatus: AGENT_MAPPING_STATUS_UNMAPPED,
},
];
allowedAgents = agents.filter(
(agent) => agent.mappingStatus === AGENT_MAPPING_STATUS_MAPPED,
);
findGetAgentsWithMappingStatusQuery().vm.$emit('result', { agents });
await nextTick();
});
it('displays the number of mapped agents in the Allowed Agents Tab', () => {
expect(findAllowedAgentsTab().findComponent(GlBadge).text()).toContain(
allowedAgents.length.toString(),
);
});
it('displays the number of all unmapped agents in the All Agents Tab', () => {
expect(findAllAgentsTab().findComponent(GlBadge).text()).toContain(
agents.length.toString(),
);
});
it('passes allowed agents to the allowed agents table', () => {
expect(findAllowedAgentsTable().props('agents')).toEqual(allowedAgents);
});
it('passes query result to the AgentsTable component', () => {
expect(findAgentsTable().props('agents')).toBe(agents);
it('passes all agents to the all agents table', () => {
expect(findAllAgentsTable().props('agents')).toEqual(agents);
});
it('sets displayMappingStatus on all agents table', () => {
expect(findAllAgentsTable().props('displayMappingStatus')).toBe(true);
});
describe('when there are unmapped agents but not mapped agents', () => {
beforeEach(async () => {
buildWrapper();
agents = [
{
id: 'agent-2',
name: 'agent two',
mappingStatus: AGENT_MAPPING_STATUS_UNMAPPED,
},
{
id: 'agent-3',
name: 'agent three',
mappingStatus: AGENT_MAPPING_STATUS_UNMAPPED,
},
];
findGetAgentsWithMappingStatusQuery().vm.$emit('result', { agents });
await nextTick();
});
it('passes a "no allowed agents" empty message to the allowed agents table', () => {
expect(findAllowedAgentsTable().props('emptyStateMessage')).toBe(
'This group has no available agents. Select the <strong>All agents</strong> tab and allow at least one agent.',
);
});
});
describe('when there are no agents', () => {
beforeEach(async () => {
buildWrapper();
agents = [];
findGetAgentsWithMappingStatusQuery().vm.$emit('result', { agents });
await nextTick();
});
it('passes a "not agents" empty message to the "allowed" and "all agents" tables', () => {
expect(findAllowedAgentsTable().props('emptyStateMessage')).toBe(
'This group has no agents. Start by creating an agent.',
);
expect(findAllAgentsTable().props('emptyStateMessage')).toBe(
'This group has no agents. Start by creating an agent.',
);
});
});
});
describe('when GetAvailableAgentsQuery component emits error event', () => {
describe('when GetAgentsWithMappingStatusQuery component emits error event', () => {
beforeEach(() => {
buildWrapper();
findGetAvailableAgentsQuery().vm.$emit('error');
findGetAgentsWithMappingStatusQuery().vm.$emit('error');
});
it('displays error as a danger alert', () => {
expect(findErrorAlert().text()).toContain('Could not load available agents');
});
it('does not render AgentsTable component', () => {
expect(findAgentsTable().exists()).toBe(false);
it('does not render any table', () => {
expect(findAllowedAgentsTable().exists()).toBe(false);
expect(findAllAgentsTable().exists()).toBe(false);
});
});
it('renders AgentsTable component', () => {
buildWrapper();
expect(findAgentsTable().exists()).toBe(true);
});
it('provides empty state message to the AgentsTable component', () => {
buildWrapper();
expect(findAgentsTable().props('emptyStateMessage')).toBe(
'This group has no available agents. Select the All agents tab and allow at least one agent.',
);
expect(findAllowedAgentsTable().exists()).toBe(true);
});
it('provides loading state from the GetAvailableAgentsQuery to the AgentsTable component', () => {
it('provides loading state from the GetAgentsWithMappingStatusQuery to the AgentsTable component', () => {
buildWrapper({ mappedAgentsQueryState: { loading: true } });
expect(findAgentsTable().props('isLoading')).toBe(true);
expect(findAllowedAgentsTable().props('isLoading')).toBe(true);
});
});
});
import { GlTable, GlSkeletonLoader } from '@gitlab/ui';
import { shallowMount, mount } from '@vue/test-utils';
import { shallowMountExtended, mountExtended } from 'helpers/vue_test_utils_helper';
import AgentsTable from 'ee_component/workspaces/agent_mapping/components/agents_table.vue';
import {
AGENT_MAPPING_STATUS_MAPPED,
AGENT_MAPPING_STATUS_UNMAPPED,
} from 'ee_component/workspaces/agent_mapping/constants';
describe('workspaces/agent_mapping/components/agents_table.vue', () => {
let wrapper;
const EMPTY_STATE_MESSAGE = 'No agents found';
const agents = [
{ name: 'agent-1', mappingStatus: AGENT_MAPPING_STATUS_MAPPED },
{ name: 'agent-1', mappingStatus: AGENT_MAPPING_STATUS_UNMAPPED },
];
const buildWrapper = ({ propsData = {} } = {}, mountFn = shallowMount) => {
const buildWrapper = ({ propsData = {} } = {}, mountFn = shallowMountExtended) => {
wrapper = mountFn(AgentsTable, {
propsData: {
agents: [],
......@@ -66,7 +74,7 @@ describe('workspaces/agent_mapping/components/agents_table.vue', () => {
agents: [],
},
},
mount,
mountExtended,
);
});
......@@ -90,10 +98,10 @@ describe('workspaces/agent_mapping/components/agents_table.vue', () => {
{
propsData: {
isLoading: false,
agents: [{ name: 'agent-1' }],
agents,
},
},
mount,
mountExtended,
);
});
......@@ -108,5 +116,42 @@ describe('workspaces/agent_mapping/components/agents_table.vue', () => {
it('displays agents list', () => {
expect(findAgentsTable().text()).toContain('agent-1');
});
describe('when displayMappingStatus is true', () => {
it('displays agent status using label', () => {
buildWrapper(
{
propsData: {
isLoading: false,
displayMappingStatus: true,
agents,
},
},
mountExtended,
);
const labels = wrapper
.findAllByTestId('agent-mapping-status-label')
.wrappers.map((labelWrapper) => labelWrapper.text());
expect(labels).toEqual(['Allowed', 'Blocked']);
});
});
describe('when displayAgentStatus is false', () => {
it('does not display agent status using label', () => {
buildWrapper(
{
propsData: {
isLoading: false,
mappingStatus: false,
agents,
},
},
mountExtended,
);
expect(wrapper.findAllByTestId('agent-mapping-status-label').length).toBe(0);
});
});
});
});
......@@ -2,27 +2,31 @@ import { shallowMount } from '@vue/test-utils';
import VueApollo from 'vue-apollo';
import Vue from 'vue';
import { logError } from '~/lib/logger';
import getRemoteDevelopmentClusterAgentsQuery from 'ee/workspaces/common/graphql/queries/get_remote_development_cluster_agents.query.graphql';
import GetAvailableAgentsQuery from 'ee/workspaces/agent_mapping/components/get_available_agents_query.vue';
import getAgentsWithMappingStatusQuery from 'ee/workspaces/agent_mapping/graphql/queries/get_agents_with_mapping_status.query.graphql';
import GetAgentsWithAuthorizationStatusQuery from 'ee/workspaces/agent_mapping/components/get_agents_with_mapping_status_query.vue';
import {
AGENT_MAPPING_STATUS_MAPPED,
AGENT_MAPPING_STATUS_UNMAPPED,
} from 'ee/workspaces/agent_mapping/constants';
import createMockApollo from 'helpers/mock_apollo_helper';
import waitForPromises from 'helpers/wait_for_promises';
import { GET_REMOTE_DEVELOPMENT_CLUSTER_AGENTS_QUERY_RESULT_TWO_AGENTS } from '../../mock_data';
import { GET_AGENTS_WITH_MAPPING_STATUS_QUERY_RESULT } from '../../mock_data';
Vue.use(VueApollo);
jest.mock('~/lib/logger');
describe('workspaces/agent_mapping/components/get_available_agents_query.vue', () => {
let getRemoteDevelopmentClusterAgentsQueryHandler;
describe('workspaces/agent_mapping/components/get_agents_with_mapping_status_query.vue', () => {
let getAgentsWithMappingStatusQueryHandler;
let wrapper;
const NAMESPACE = 'gitlab-org/gitlab';
const buildWrapper = async ({ propsData = {}, scopedSlots = {} } = {}) => {
const apolloProvider = createMockApollo([
[getRemoteDevelopmentClusterAgentsQuery, getRemoteDevelopmentClusterAgentsQueryHandler],
[getAgentsWithMappingStatusQuery, getAgentsWithMappingStatusQueryHandler],
]);
wrapper = shallowMount(GetAvailableAgentsQuery, {
wrapper = shallowMount(GetAgentsWithAuthorizationStatusQuery, {
apolloProvider,
propsData: {
...propsData,
......@@ -36,22 +40,12 @@ describe('workspaces/agent_mapping/components/get_available_agents_query.vue', (
};
const buildWrapperWithNamespace = () => buildWrapper({ propsData: { namespace: NAMESPACE } });
const setupRemoteDevelopmentClusterAgentsQueryHandler = (responses) => {
getRemoteDevelopmentClusterAgentsQueryHandler.mockResolvedValueOnce(responses);
const setupAgentsWithMappingStatusQueryHandler = (responses) => {
getAgentsWithMappingStatusQueryHandler.mockResolvedValueOnce(responses);
};
const transformRemoteDevelopmentClusterAgentGraphQLResultToClusterAgents = (
clusterAgentsGraphQLResult,
) =>
clusterAgentsGraphQLResult.data.namespace.remoteDevelopmentClusterAgents.nodes.map(
({ id, name }) => ({
name,
id,
}),
);
beforeEach(() => {
getRemoteDevelopmentClusterAgentsQueryHandler = jest.fn();
getAgentsWithMappingStatusQueryHandler = jest.fn();
logError.mockReset();
});
......@@ -72,19 +66,17 @@ describe('workspaces/agent_mapping/components/get_available_agents_query.vue', (
});
describe('when namespace path is provided', () => {
it('executes getRemoteDevelopmentClusterAgentsQuery query', async () => {
it('executes getAgentsWithAuthorizationStatusQuery query', async () => {
await buildWrapperWithNamespace();
expect(getRemoteDevelopmentClusterAgentsQueryHandler).toHaveBeenCalledWith({
expect(getAgentsWithMappingStatusQueryHandler).toHaveBeenCalledWith({
namespace: NAMESPACE,
});
});
describe('when the query is successful', () => {
beforeEach(() => {
setupRemoteDevelopmentClusterAgentsQueryHandler(
GET_REMOTE_DEVELOPMENT_CLUSTER_AGENTS_QUERY_RESULT_TWO_AGENTS,
);
setupAgentsWithMappingStatusQueryHandler(GET_AGENTS_WITH_MAPPING_STATUS_QUERY_RESULT);
});
it('triggers result event with the agents list', async () => {
......@@ -93,9 +85,18 @@ describe('workspaces/agent_mapping/components/get_available_agents_query.vue', (
expect(wrapper.emitted('result')).toEqual([
[
{
agents: transformRemoteDevelopmentClusterAgentGraphQLResultToClusterAgents(
GET_REMOTE_DEVELOPMENT_CLUSTER_AGENTS_QUERY_RESULT_TWO_AGENTS,
),
agents: [
{
id: 'gid://gitlab/Clusters::Agent/1',
name: 'rootgroup-agent',
mappingStatus: AGENT_MAPPING_STATUS_MAPPED,
},
{
id: 'gid://gitlab/Clusters::Agent/2',
name: 'rootgroup-agent-2',
mappingStatus: AGENT_MAPPING_STATUS_UNMAPPED,
},
],
},
],
]);
......@@ -106,8 +107,8 @@ describe('workspaces/agent_mapping/components/get_available_agents_query.vue', (
const error = new Error();
beforeEach(() => {
getRemoteDevelopmentClusterAgentsQueryHandler.mockReset();
getRemoteDevelopmentClusterAgentsQueryHandler.mockRejectedValueOnce(error);
getAgentsWithMappingStatusQueryHandler.mockReset();
getAgentsWithMappingStatusQueryHandler.mockRejectedValueOnce(error);
});
it('logs the error', async () => {
......@@ -133,13 +134,11 @@ describe('workspaces/agent_mapping/components/get_available_agents_query.vue', (
});
describe('when namespace path is not provided', () => {
it('does not getRemoteDevelopmentClusterAgentsQuery query', async () => {
setupRemoteDevelopmentClusterAgentsQueryHandler(
GET_REMOTE_DEVELOPMENT_CLUSTER_AGENTS_QUERY_RESULT_TWO_AGENTS,
);
it('does not getAgentsWithAuthorizationStatusQuery query', async () => {
setupAgentsWithMappingStatusQueryHandler(GET_AGENTS_WITH_MAPPING_STATUS_QUERY_RESULT);
await buildWrapper();
expect(getRemoteDevelopmentClusterAgentsQueryHandler).not.toHaveBeenCalled();
expect(getAgentsWithMappingStatusQueryHandler).not.toHaveBeenCalled();
});
});
});
......@@ -336,6 +336,47 @@ export const GET_REMOTE_DEVELOPMENT_CLUSTER_AGENTS_QUERY_RESULT_TWO_AGENTS = {
},
};
export const GET_AGENTS_WITH_MAPPING_STATUS_QUERY_RESULT = {
data: {
group: {
id: 'gid://gitlab/Group/81',
fullPath: 'gitlab-org/subgroup',
clusterAgents: {
nodes: [
{
id: 'gid://gitlab/Clusters::Agent/1',
name: 'rootgroup-agent',
project: {
id: 'gid://gitlab/Project/101',
nameWithNamespace: 'GitLab Org / GitLab Agent One',
},
},
{
id: 'gid://gitlab/Clusters::Agent/2',
name: 'rootgroup-agent-2',
project: {
id: 'gid://gitlab/Project/102',
nameWithNamespace: 'GitLab Org / GitLab Agent Two',
},
},
],
},
remoteDevelopmentClusterAgents: {
nodes: [
{
id: 'gid://gitlab/Clusters::Agent/1',
name: 'rootgroup-agent',
project: {
id: 'gid://gitlab/Project/101',
nameWithNamespace: 'GitLab Org / GitLab Agent One',
},
},
],
},
},
},
};
export const WORKSPACE_CREATE_MUTATION_RESULT = {
data: {
workspaceCreate: {
......
......@@ -7616,6 +7616,9 @@ msgstr ""
msgid "Autosave|Note"
msgstr ""
 
msgid "Availability"
msgstr ""
msgid "Available"
msgstr ""
 
......@@ -59065,6 +59068,12 @@ msgstr ""
msgid "Workspaces|Agents connect workspaces to your Kubernetes cluster. To create a workspace with an allowed agent, group members must have at least the Developer role."
msgstr ""
 
msgid "Workspaces|All agents"
msgstr ""
msgid "Workspaces|Allowed Agents"
msgstr ""
msgid "Workspaces|Cancel"
msgstr ""
 
......@@ -59167,7 +59176,10 @@ msgstr ""
msgid "Workspaces|The branch, tag, or commit hash GitLab uses to create your workspace."
msgstr ""
 
msgid "Workspaces|This group has no available agents. Select the All agents tab and allow at least one agent."
msgid "Workspaces|This group has no agents. Start by creating an agent."
msgstr ""
msgid "Workspaces|This group has no available agents. Select the %{strongStart}All agents%{strongEnd} tab and allow at least one agent."
msgstr ""
 
msgid "Workspaces|To create a workspace, add a devfile to this project. A devfile is a configuration file for your workspace."
......@@ -60524,6 +60536,9 @@ msgstr ""
msgid "added a Zoom call to this issue"
msgstr ""
 
msgid "agents"
msgstr ""
msgid "ago"
msgstr ""
 
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment