Skip to content
Snippets Groups Projects
Commit 630d0b7c authored by 🤖 GitLab Bot 🤖's avatar 🤖 GitLab Bot 🤖
Browse files

Automatic merge of gitlab-org/gitlab master

parents 356a454b 6f792b08
No related branches found
No related tags found
No related merge requests found
Showing
with 161 additions and 12 deletions
......@@ -63,7 +63,6 @@ export default {
data-testid="preview-item"
@click="onClickDraft(draft)"
>
{{ isOnLatestDiff(draft) }}
<preview-item :draft="draft" :is-last="isLast(index)" />
</gl-dropdown-item>
</gl-dropdown>
......
......@@ -136,6 +136,7 @@ export default {
v-for="group in groups"
:key="group.id"
:name="group.name"
data-qa-selector="group_select_dropdown_item"
@click="selectGroup(group)"
>
<gl-avatar-labeled
......
......@@ -4,8 +4,8 @@ module Clusters
class AgentsFinder
include FinderMethods
def initialize(project, current_user, params: {})
@project = project
def initialize(object, current_user, params: {})
@object = object
@current_user = current_user
@params = params
end
......@@ -13,7 +13,7 @@ def initialize(project, current_user, params: {})
def execute
return ::Clusters::Agent.none unless can_read_cluster_agents?
agents = project.cluster_agents
agents = object.cluster_agents
agents = agents.with_name(params[:name]) if params[:name].present?
agents.ordered_by_name
......@@ -21,10 +21,10 @@ def execute
private
attr_reader :project, :current_user, :params
attr_reader :object, :current_user, :params
def can_read_cluster_agents?
current_user.can?(:read_cluster, project)
current_user&.can?(:read_cluster, object)
end
end
end
......@@ -15,12 +15,10 @@ class AgentsResolver < BaseResolver
description: 'Name of the cluster agent.'
end
alias_method :project, :object
def resolve_with_lookahead(**args)
apply_lookahead(
::Clusters::AgentsFinder
.new(project, current_user, params: args)
.new(object, current_user, params: args)
.execute
)
end
......
......@@ -53,3 +53,5 @@ def to_ability_name
end
end
end
Clusters::Agent.prepend_mod_with('Clusters::Agent')
......@@ -11694,6 +11694,7 @@ four standard [pagination arguments](#connection-pagination-arguments):
| <a id="groupallowstalerunnerpruning"></a>`allowStaleRunnerPruning` | [`Boolean!`](#boolean) | Indicates whether to regularly prune stale group runners. Defaults to false. |
| <a id="groupautodevopsenabled"></a>`autoDevopsEnabled` | [`Boolean`](#boolean) | Indicates whether Auto DevOps is enabled for all projects within this group. |
| <a id="groupavatarurl"></a>`avatarUrl` | [`String`](#string) | Avatar URL of the group. |
| <a id="groupclusteragents"></a>`clusterAgents` | [`ClusterAgentConnection`](#clusteragentconnection) | Cluster agents associated with projects in the group and its subgroups. (see [Connections](#connections)) |
| <a id="groupcontainerrepositoriescount"></a>`containerRepositoriesCount` | [`Int!`](#int) | Number of container repositories in the group. |
| <a id="groupcontainslockedprojects"></a>`containsLockedProjects` | [`Boolean!`](#boolean) | Includes at least one project where the repository size exceeds the limit. |
| <a id="groupcrossprojectpipelineavailable"></a>`crossProjectPipelineAvailable` | [`Boolean!`](#boolean) | Indicates if the cross_project_pipeline feature is available for the namespace. |
......@@ -12573,6 +12574,7 @@ A block of time for which a participant is on-call.
 
| Name | Type | Description |
| ---- | ---- | ----------- |
| <a id="instancesecuritydashboardclusteragents"></a>`clusterAgents` | [`ClusterAgentConnection`](#clusteragentconnection) | Cluster agents associated with projects selected in the Instance Security Dashboard. (see [Connections](#connections)) |
| <a id="instancesecuritydashboardvulnerabilitygrades"></a>`vulnerabilityGrades` | [`[VulnerableProjectsByGrade!]!`](#vulnerableprojectsbygrade) | Represents vulnerable project counts for each grade. |
| <a id="instancesecuritydashboardvulnerabilityscanners"></a>`vulnerabilityScanners` | [`VulnerabilityScannerConnection`](#vulnerabilityscannerconnection) | Vulnerability scanners reported on the vulnerabilities from projects selected in Instance Security Dashboard. (see [Connections](#connections)) |
 
......@@ -41,7 +41,7 @@ Please consider using a virtual machine to run GitLab.
### Redis versions
GitLab 13.0 and later requires Redis version 4.0 or higher.
GitLab 13.0 and later requires Redis version 5.0 or higher.
Redis version 6.0 or higher is recommended, as this is what ships with
[Omnibus GitLab](https://docs.gitlab.com/omnibus/) packages starting with GitLab 13.9.
......
......@@ -115,6 +115,13 @@ module GroupType
description: 'Indicates whether to regularly prune stale group runners. Defaults to false.',
method: :allow_stale_runner_pruning?
field :cluster_agents,
::Types::Clusters::AgentType.connection_type,
extras: [:lookahead],
null: true,
description: 'Cluster agents associated with projects in the group and its subgroups.',
resolver: ::Resolvers::Clusters::AgentsResolver
def billable_members_count(requested_hosted_plan: nil)
object.billable_members_count(requested_hosted_plan)
end
......
......@@ -27,6 +27,13 @@ class InstanceSecurityDashboardType < BaseObject
null: false,
description: 'Represents vulnerable project counts for each grade.'
field :cluster_agents,
::Types::Clusters::AgentType.connection_type,
extras: [:lookahead],
null: true,
description: 'Cluster agents associated with projects selected in the Instance Security Dashboard.',
resolver: ::Resolvers::Clusters::AgentsResolver
def vulnerability_grades
::Gitlab::Graphql::Aggregations::VulnerabilityStatistics::LazyAggregate.new(
context,
......
# frozen_string_literal: true
module EE
module Clusters
module Agent
extend ActiveSupport::Concern
prepended do
scope :for_projects, -> (projects) { where(project: projects) }
end
end
end
end
......@@ -630,6 +630,10 @@ def shared_externally?
end
end
def cluster_agents
::Clusters::Agent.for_projects(all_projects)
end
private
override :post_create_hook
......
......@@ -51,6 +51,12 @@ def has_projects?
projects.count > 0
end
def cluster_agents
return Clusters::Agent.none if projects.empty?
Clusters::Agent.for_projects(projects)
end
private
attr_reader :project_ids, :user
......
......@@ -577,6 +577,7 @@
trait :with_cluster_image_scanning_scanning_metadata do
transient do
location_image { "alpine:3.7" }
agent_id { '46357' }
end
after(:build) do |finding, evaluator|
......@@ -594,7 +595,7 @@
"image": evaluator.location_image,
"kubernetes_resource": {
"cluster_id": "1",
"agent_id": "46357"
"agent_id": evaluator.agent_id
}
}
finding.raw_metadata = {
......
......@@ -23,6 +23,7 @@
it { expect(described_class).to have_graphql_field(:external_audit_event_destinations) }
it { expect(described_class).to have_graphql_field(:merge_request_violations) }
it { expect(described_class).to have_graphql_field(:allow_stale_runner_pruning) }
it { expect(described_class).to have_graphql_field(:cluster_agents) }
describe 'vulnerabilities' do
let_it_be(:group) { create(:group) }
......
# frozen_string_literal: true
require 'spec_helper'
RSpec.describe Resolvers::Clusters::AgentsResolver do
include GraphqlHelpers
specify do
expect(described_class).to have_nullable_graphql_type(Types::Clusters::AgentType.connection_type)
end
specify do
expect(described_class.field_options).to include(extras: include(:lookahead))
end
describe '#resolve' do
let_it_be(:project) { create(:project) }
let_it_be(:maintainer) { create(:user, developer_projects: [project]) }
let_it_be(:reporter) { create(:user) }
let_it_be(:agent_1) { create(:cluster_agent, project: project) }
let_it_be(:agent_2) { create(:cluster_agent, project: project) }
before do
project.add_reporter(reporter)
end
let(:ctx) { { current_user: current_user } }
let(:params) { {} }
subject { resolve_agents(params) }
context 'the current user has access to clusters' do
let(:current_user) { maintainer }
it 'finds all agents' do
expect(subject).to contain_exactly(agent_1, agent_2)
end
end
context 'the current user does not have access to clusters' do
let(:current_user) { reporter }
it 'returns an empty result' do
expect(subject).to be_empty
end
end
end
def resolve_agents(args = {})
resolve(described_class, obj: project, ctx: ctx, lookahead: positive_lookahead, args: args)
end
end
......@@ -8,7 +8,7 @@
let_it_be(:user) { create(:user, security_dashboard_projects: [project]) }
let(:fields) do
%i[projects vulnerability_scanners vulnerability_severities_count vulnerability_grades]
%i[projects vulnerability_scanners vulnerability_severities_count vulnerability_grades cluster_agents]
end
before do
......
# frozen_string_literal: true
require 'spec_helper'
RSpec.describe Clusters::Agent do
it { is_expected.to include_module(EE::Clusters::Agent) }
describe '.for_projects' do
let_it_be(:agent_1) { create(:cluster_agent) }
let_it_be(:agent_2) { create(:cluster_agent) }
let_it_be(:agent_3) { create(:cluster_agent) }
it 'return agents for selected projects' do
expect(described_class.for_projects([agent_1.project, agent_3.project])).to contain_exactly(agent_1, agent_3)
end
end
end
......@@ -2524,4 +2524,22 @@ def webhook_headers
.to contain_exactly(project_user.id, owner1.id, owner2.id, project2_user.id, bot_project_user.id, requesting_user.id, group_user.id)
end
end
describe '#cluster_agents' do
let_it_be(:other_group) { create(:group) }
let_it_be(:other_project) { create(:project, namespace: other_group) }
let_it_be(:root_group) { create(:group) }
let_it_be(:subgroup) { create(:group, parent: root_group) }
let_it_be(:project_in_group) { create(:project, namespace: root_group) }
let_it_be(:project_in_subgroup) { create(:project, namespace: subgroup) }
let_it_be(:cluster_agent_for_other_project) { create(:cluster_agent, project: other_project) }
let_it_be(:cluster_agent_for_project) { create(:cluster_agent, project: project_in_group) }
let_it_be(:cluster_agent_for_project_in_subgroup) { create(:cluster_agent, project: project_in_subgroup) }
subject { root_group.cluster_agents }
it { is_expected.to contain_exactly(cluster_agent_for_project, cluster_agent_for_project_in_subgroup) }
end
end
......@@ -217,6 +217,23 @@
end
end
describe '#cluster_agents' do
let_it_be(:cluster_agent_for_project_1) { create(:cluster_agent, project: project1) }
let_it_be(:cluster_agent_for_project_3) { create(:cluster_agent, project: project3) }
context 'when instance security dashboard has projects added' do
it { expect(instance_dashboard.cluster_agents).to contain_exactly(cluster_agent_for_project_1) }
end
context 'when instance security dashboard does not have any projects added' do
let_it_be(:other_user) { create(:user) }
subject(:instance_dashboard) { described_class.new(other_user, project_ids: []) }
it { expect(instance_dashboard.cluster_agents).to be_empty }
end
end
describe '#full_path' do
let(:user) { create(:user) }
......
......@@ -17,6 +17,7 @@ def self.included(base)
base.view 'app/assets/javascripts/invite_members/components/group_select.vue' do
element :group_select_dropdown_search_field
element :group_select_dropdown_item
end
base.view 'app/assets/javascripts/invite_members/components/members_token_select.vue' do
......@@ -59,6 +60,8 @@ def invite_group(group_name, access_level = 'Guest')
within_element(:invite_members_modal_content) do
click_button 'Select a group'
Support::Waiter.wait_until { has_element?(:group_select_dropdown_item) }
# Helps stabilize race condition with concurrent group API calls while searching
# TODO: Replace with `fill_element :group_select_dropdown_search_field, group_name` when this bug is resolved: https://gitlab.com/gitlab-org/gitlab/-/issues/349379
send_keys_to_element(:group_select_dropdown_search_field, group_name)
......
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