Commit 9b64bd06 authored by Luke Duncalfe's avatar Luke Duncalfe

Merge branch 'move-agent-graphql-to-core' into 'master'

Move Agent GraphQL types and resolvers to core

See merge request gitlab-org/gitlab!70759
parents 9d9a3a4e 5f54a7c0
...@@ -18,7 +18,7 @@ module Resolvers ...@@ -18,7 +18,7 @@ module Resolvers
private private
def can_read_agent_tokens? def can_read_agent_tokens?
project.feature_available?(:cluster_agents) && current_user.can?(:admin_cluster, project) current_user.can?(:admin_cluster, project)
end end
end end
end end
......
...@@ -21,7 +21,7 @@ module Resolvers ...@@ -21,7 +21,7 @@ module Resolvers
private private
def can_read_agent_configuration? def can_read_agent_configuration?
project.licensed_feature_available?(:cluster_agents) && current_user.can?(:admin_cluster, project) current_user.can?(:admin_cluster, project)
end end
def kas_client def kas_client
......
...@@ -24,7 +24,7 @@ module Resolvers ...@@ -24,7 +24,7 @@ module Resolvers
private private
def can_read_connected_agents? def can_read_connected_agents?
project.licensed_feature_available?(:cluster_agents) && current_user.can?(:admin_cluster, project) current_user.can?(:admin_cluster, project)
end end
def get_connected_agents def get_connected_agents
......
...@@ -361,6 +361,25 @@ module Types ...@@ -361,6 +361,25 @@ module Types
complexity: 5, complexity: 5,
resolver: ::Resolvers::TimelogResolver resolver: ::Resolvers::TimelogResolver
field :agent_configurations,
::Types::Kas::AgentConfigurationType.connection_type,
null: true,
description: 'Agent configurations defined by the project',
resolver: ::Resolvers::Kas::AgentConfigurationsResolver
field :cluster_agent,
::Types::Clusters::AgentType,
null: true,
description: 'Find a single cluster agent by name.',
resolver: ::Resolvers::Clusters::AgentsResolver.single
field :cluster_agents,
::Types::Clusters::AgentType.connection_type,
extras: [:lookahead],
null: true,
description: 'Cluster agents associated with the project.',
resolver: ::Resolvers::Clusters::AgentsResolver
def label(title:) def label(title:)
BatchLoader::GraphQL.for(title).batch(key: project) do |titles, loader, args| BatchLoader::GraphQL.for(title).batch(key: project) do |titles, loader, args|
LabelsFinder LabelsFinder
......
...@@ -95,25 +95,6 @@ module EE ...@@ -95,25 +95,6 @@ module EE
resolver: ::Resolvers::DastSiteValidationResolver, resolver: ::Resolvers::DastSiteValidationResolver,
description: 'DAST Site Validations associated with the project.' description: 'DAST Site Validations associated with the project.'
field :agent_configurations,
::Types::Kas::AgentConfigurationType.connection_type,
null: true,
description: 'Agent configurations defined by the project',
resolver: ::Resolvers::Kas::AgentConfigurationsResolver
field :cluster_agent,
::Types::Clusters::AgentType,
null: true,
description: 'Find a single cluster agent by name.',
resolver: ::Resolvers::Clusters::AgentsResolver.single
field :cluster_agents,
::Types::Clusters::AgentType.connection_type,
extras: [:lookahead],
null: true,
description: 'Cluster agents associated with the project.',
resolver: ::Resolvers::Clusters::AgentsResolver
field :repository_size_excess, field :repository_size_excess,
GraphQL::FLOAT_TYPE, GraphQL::FLOAT_TYPE,
null: true, null: true,
......
...@@ -19,7 +19,7 @@ RSpec.describe GitlabSchema.types['Project'] do ...@@ -19,7 +19,7 @@ RSpec.describe GitlabSchema.types['Project'] do
expected_fields = %w[ expected_fields = %w[
vulnerabilities vulnerability_scanners requirement_states_count vulnerabilities vulnerability_scanners requirement_states_count
vulnerability_severities_count packages compliance_frameworks vulnerabilities_count_by_day vulnerability_severities_count packages compliance_frameworks vulnerabilities_count_by_day
security_dashboard_path iterations iteration_cadences cluster_agents repository_size_excess actual_repository_size_limit security_dashboard_path iterations iteration_cadences repository_size_excess actual_repository_size_limit
code_coverage_summary api_fuzzing_ci_configuration path_locks incident_management_escalation_policies code_coverage_summary api_fuzzing_ci_configuration path_locks incident_management_escalation_policies
incident_management_escalation_policy scan_execution_policies network_policies incident_management_escalation_policy scan_execution_policies network_policies
] ]
...@@ -101,139 +101,6 @@ RSpec.describe GitlabSchema.types['Project'] do ...@@ -101,139 +101,6 @@ RSpec.describe GitlabSchema.types['Project'] do
end end
end end
describe 'agent_configurations' do
let_it_be(:query) do
%(
query {
project(fullPath: "#{project.full_path}") {
agentConfigurations {
nodes {
agentName
}
}
}
}
)
end
let(:agent_name) { 'example-agent-name' }
let(:kas_client) { instance_double(Gitlab::Kas::Client, list_agent_config_files: [double(agent_name: agent_name)]) }
subject { GitlabSchema.execute(query, context: { current_user: user }).as_json }
before do
stub_licensed_features(cluster_agents: true)
project.add_maintainer(user)
allow(Gitlab::Kas::Client).to receive(:new).and_return(kas_client)
end
it 'returns configured agents' do
agents = subject.dig('data', 'project', 'agentConfigurations', 'nodes')
expect(agents.count).to eq(1)
expect(agents.first['agentName']).to eq(agent_name)
end
end
describe 'cluster_agents' do
let_it_be(:cluster_agent) { create(:cluster_agent, project: project, name: 'agent-name') }
let_it_be(:query) do
%(
query {
project(fullPath: "#{project.full_path}") {
clusterAgents {
count
nodes {
id
name
createdAt
updatedAt
project {
id
}
}
}
}
}
)
end
subject { GitlabSchema.execute(query, context: { current_user: user }).as_json }
before do
stub_licensed_features(cluster_agents: true)
project.add_maintainer(user)
end
it 'returns associated cluster agents' do
agents = subject.dig('data', 'project', 'clusterAgents', 'nodes')
expect(agents.count).to be(1)
expect(agents.first['id']).to eq(cluster_agent.to_global_id.to_s)
expect(agents.first['name']).to eq('agent-name')
expect(agents.first['createdAt']).to be_present
expect(agents.first['updatedAt']).to be_present
expect(agents.first['project']['id']).to eq(project.to_global_id.to_s)
end
it 'returns count of cluster agents' do
count = subject.dig('data', 'project', 'clusterAgents', 'count')
expect(count).to be(project.cluster_agents.size)
end
end
describe 'cluster_agent' do
let_it_be(:cluster_agent) { create(:cluster_agent, project: project, name: 'agent-name') }
let_it_be(:agent_token) { create(:cluster_agent_token, agent: cluster_agent) }
let_it_be(:query) do
%(
query {
project(fullPath: "#{project.full_path}") {
clusterAgent(name: "#{cluster_agent.name}") {
id
tokens {
count
nodes {
id
}
}
}
}
}
)
end
subject { GitlabSchema.execute(query, context: { current_user: user }).as_json }
before do
stub_licensed_features(cluster_agents: true)
project.add_maintainer(user)
end
it 'returns associated cluster agents' do
agent = subject.dig('data', 'project', 'clusterAgent')
tokens = agent.dig('tokens', 'nodes')
expect(agent['id']).to eq(cluster_agent.to_global_id.to_s)
expect(tokens.count).to be(1)
expect(tokens.first['id']).to eq(agent_token.to_global_id.to_s)
end
it 'returns count of agent tokens' do
agent = subject.dig('data', 'project', 'clusterAgent')
count = agent.dig('tokens', 'count')
expect(cluster_agent.agent_tokens.size).to be(count)
end
end
describe 'code coverage summary field' do describe 'code coverage summary field' do
subject { described_class.fields['codeCoverageSummary'] } subject { described_class.fields['codeCoverageSummary'] }
......
...@@ -11,7 +11,6 @@ RSpec.describe Resolvers::Clusters::AgentTokensResolver do ...@@ -11,7 +11,6 @@ RSpec.describe Resolvers::Clusters::AgentTokensResolver do
describe '#resolve' do describe '#resolve' do
let(:agent) { create(:cluster_agent) } let(:agent) { create(:cluster_agent) }
let(:user) { create(:user, maintainer_projects: [agent.project]) } let(:user) { create(:user, maintainer_projects: [agent.project]) }
let(:feature_available) { true }
let(:ctx) { Hash(current_user: user) } let(:ctx) { Hash(current_user: user) }
let!(:matching_token1) { create(:cluster_agent_token, agent: agent, last_used_at: 5.days.ago) } let!(:matching_token1) { create(:cluster_agent_token, agent: agent, last_used_at: 5.days.ago) }
...@@ -20,20 +19,10 @@ RSpec.describe Resolvers::Clusters::AgentTokensResolver do ...@@ -20,20 +19,10 @@ RSpec.describe Resolvers::Clusters::AgentTokensResolver do
subject { resolve(described_class, obj: agent, ctx: ctx) } subject { resolve(described_class, obj: agent, ctx: ctx) }
before do
stub_licensed_features(cluster_agents: feature_available)
end
it 'returns tokens associated with the agent, ordered by last_used_at' do it 'returns tokens associated with the agent, ordered by last_used_at' do
expect(subject).to eq([matching_token2, matching_token1]) expect(subject).to eq([matching_token2, matching_token1])
end end
context 'feature is not available' do
let(:feature_available) { false }
it { is_expected.to be_empty }
end
context 'user does not have permission' do context 'user does not have permission' do
let(:user) { create(:user, developer_projects: [agent.project]) } let(:user) { create(:user, developer_projects: [agent.project]) }
......
...@@ -21,10 +21,6 @@ RSpec.describe Resolvers::Clusters::AgentsResolver do ...@@ -21,10 +21,6 @@ RSpec.describe Resolvers::Clusters::AgentsResolver do
let(:ctx) { { current_user: current_user } } let(:ctx) { { current_user: current_user } }
before do
stub_licensed_features(cluster_agents: true)
end
subject { resolve_agents } subject { resolve_agents }
context 'the current user has access to clusters' do context 'the current user has access to clusters' do
......
...@@ -14,7 +14,6 @@ RSpec.describe Resolvers::Kas::AgentConfigurationsResolver do ...@@ -14,7 +14,6 @@ RSpec.describe Resolvers::Kas::AgentConfigurationsResolver do
let(:user) { create(:user, maintainer_projects: [project]) } let(:user) { create(:user, maintainer_projects: [project]) }
let(:ctx) { Hash(current_user: user) } let(:ctx) { Hash(current_user: user) }
let(:feature_available) { true }
let(:agent1) { double } let(:agent1) { double }
let(:agent2) { double } let(:agent2) { double }
...@@ -23,8 +22,6 @@ RSpec.describe Resolvers::Kas::AgentConfigurationsResolver do ...@@ -23,8 +22,6 @@ RSpec.describe Resolvers::Kas::AgentConfigurationsResolver do
subject { resolve(described_class, obj: project, ctx: ctx) } subject { resolve(described_class, obj: project, ctx: ctx) }
before do before do
stub_licensed_features(cluster_agents: feature_available)
allow(Gitlab::Kas::Client).to receive(:new).and_return(kas_client) allow(Gitlab::Kas::Client).to receive(:new).and_return(kas_client)
end end
...@@ -42,12 +39,6 @@ RSpec.describe Resolvers::Kas::AgentConfigurationsResolver do ...@@ -42,12 +39,6 @@ RSpec.describe Resolvers::Kas::AgentConfigurationsResolver do
end end
end end
context 'feature is not available' do
let(:feature_available) { false }
it { is_expected.to be_empty }
end
context 'user does not have permission' do context 'user does not have permission' do
let(:user) { create(:user) } let(:user) { create(:user) }
......
...@@ -15,7 +15,6 @@ RSpec.describe Resolvers::Kas::AgentConnectionsResolver do ...@@ -15,7 +15,6 @@ RSpec.describe Resolvers::Kas::AgentConnectionsResolver do
let(:user) { create(:user, maintainer_projects: [project]) } let(:user) { create(:user, maintainer_projects: [project]) }
let(:ctx) { Hash(current_user: user) } let(:ctx) { Hash(current_user: user) }
let(:feature_available) { true }
let(:connection1) { double(agent_id: agent1.id) } let(:connection1) { double(agent_id: agent1.id) }
let(:connection2) { double(agent_id: agent1.id) } let(:connection2) { double(agent_id: agent1.id) }
...@@ -30,8 +29,6 @@ RSpec.describe Resolvers::Kas::AgentConnectionsResolver do ...@@ -30,8 +29,6 @@ RSpec.describe Resolvers::Kas::AgentConnectionsResolver do
end end
before do before do
stub_licensed_features(cluster_agents: feature_available)
allow(Gitlab::Kas::Client).to receive(:new).and_return(kas_client) allow(Gitlab::Kas::Client).to receive(:new).and_return(kas_client)
end end
...@@ -60,12 +57,6 @@ RSpec.describe Resolvers::Kas::AgentConnectionsResolver do ...@@ -60,12 +57,6 @@ RSpec.describe Resolvers::Kas::AgentConnectionsResolver do
end end
end end
context 'feature is not available' do
let(:feature_available) { false }
it { is_expected.to be_empty }
end
context 'user does not have permission' do context 'user does not have permission' do
let(:user) { create(:user) } let(:user) { create(:user) }
......
...@@ -33,6 +33,7 @@ RSpec.describe GitlabSchema.types['Project'] do ...@@ -33,6 +33,7 @@ RSpec.describe GitlabSchema.types['Project'] do
issue_status_counts terraform_states alert_management_integrations issue_status_counts terraform_states alert_management_integrations
container_repositories container_repositories_count container_repositories container_repositories_count
pipeline_analytics squash_read_only sast_ci_configuration pipeline_analytics squash_read_only sast_ci_configuration
cluster_agent cluster_agents agent_configurations
ci_template timelogs ci_template timelogs
] ]
...@@ -458,4 +459,137 @@ RSpec.describe GitlabSchema.types['Project'] do ...@@ -458,4 +459,137 @@ RSpec.describe GitlabSchema.types['Project'] do
it { is_expected.to have_graphql_type(Types::Ci::JobTokenScopeType) } it { is_expected.to have_graphql_type(Types::Ci::JobTokenScopeType) }
it { is_expected.to have_graphql_resolver(Resolvers::Ci::JobTokenScopeResolver) } it { is_expected.to have_graphql_resolver(Resolvers::Ci::JobTokenScopeResolver) }
end end
describe 'agent_configurations' do
let_it_be(:project) { create(:project) }
let_it_be(:user) { create(:user) }
let_it_be(:query) do
%(
query {
project(fullPath: "#{project.full_path}") {
agentConfigurations {
nodes {
agentName
}
}
}
}
)
end
let(:agent_name) { 'example-agent-name' }
let(:kas_client) { instance_double(Gitlab::Kas::Client, list_agent_config_files: [double(agent_name: agent_name)]) }
subject { GitlabSchema.execute(query, context: { current_user: user }).as_json }
before do
project.add_maintainer(user)
allow(Gitlab::Kas::Client).to receive(:new).and_return(kas_client)
end
it 'returns configured agents' do
agents = subject.dig('data', 'project', 'agentConfigurations', 'nodes')
expect(agents.count).to eq(1)
expect(agents.first['agentName']).to eq(agent_name)
end
end
describe 'cluster_agents' do
let_it_be(:project) { create(:project) }
let_it_be(:user) { create(:user) }
let_it_be(:cluster_agent) { create(:cluster_agent, project: project, name: 'agent-name') }
let_it_be(:query) do
%(
query {
project(fullPath: "#{project.full_path}") {
clusterAgents {
count
nodes {
id
name
createdAt
updatedAt
project {
id
}
}
}
}
}
)
end
subject { GitlabSchema.execute(query, context: { current_user: user }).as_json }
before do
project.add_maintainer(user)
end
it 'returns associated cluster agents' do
agents = subject.dig('data', 'project', 'clusterAgents', 'nodes')
expect(agents.count).to be(1)
expect(agents.first['id']).to eq(cluster_agent.to_global_id.to_s)
expect(agents.first['name']).to eq('agent-name')
expect(agents.first['createdAt']).to be_present
expect(agents.first['updatedAt']).to be_present
expect(agents.first['project']['id']).to eq(project.to_global_id.to_s)
end
it 'returns count of cluster agents' do
count = subject.dig('data', 'project', 'clusterAgents', 'count')
expect(count).to be(project.cluster_agents.size)
end
end
describe 'cluster_agent' do
let_it_be(:project) { create(:project) }
let_it_be(:user) { create(:user) }
let_it_be(:cluster_agent) { create(:cluster_agent, project: project, name: 'agent-name') }
let_it_be(:agent_token) { create(:cluster_agent_token, agent: cluster_agent) }
let_it_be(:query) do
%(
query {
project(fullPath: "#{project.full_path}") {
clusterAgent(name: "#{cluster_agent.name}") {
id
tokens {
count
nodes {
id
}
}
}
}
}
)
end
subject { GitlabSchema.execute(query, context: { current_user: user }).as_json }
before do
project.add_maintainer(user)
end
it 'returns associated cluster agents' do
agent = subject.dig('data', 'project', 'clusterAgent')
tokens = agent.dig('tokens', 'nodes')
expect(agent['id']).to eq(cluster_agent.to_global_id.to_s)
expect(tokens.count).to be(1)
expect(tokens.first['id']).to eq(agent_token.to_global_id.to_s)
end
it 'returns count of agent tokens' do
agent = subject.dig('data', 'project', 'clusterAgent')
count = agent.dig('tokens', 'count')
expect(cluster_agent.agent_tokens.size).to be(count)
end
end
end end
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment