Commit 1a6dd64e authored by Fabio Pitino's avatar Fabio Pitino Committed by Shinya Maeda

Allow setting feature flag for a single namespace

The `group` actor could only support Group models. With this
change it can also support `UserNamespace` types and allow
the feature flag to be set for a specific namespace.

Changelog: changed
parent 0cd5c848
...@@ -245,11 +245,11 @@ class Feature ...@@ -245,11 +245,11 @@ class Feature
end end
def gate_specified? def gate_specified?
%i(user project group feature_group).any? { |key| params.key?(key) } %i(user project group feature_group namespace).any? { |key| params.key?(key) }
end end
def targets def targets
[feature_group, user, project, group].compact [feature_group, user, project, group, namespace].compact
end end
private private
...@@ -279,6 +279,13 @@ class Feature ...@@ -279,6 +279,13 @@ class Feature
Group.find_by_full_path(params[:group]) Group.find_by_full_path(params[:group])
end end
def namespace
return unless params.key?(:namespace)
# We are interested in Group or UserNamespace
Namespace.without_project_namespaces.find_by_full_path(params[:namespace])
end
end end
end end
......
...@@ -167,76 +167,85 @@ RSpec.describe API::Features, stub_feature_flags: false do ...@@ -167,76 +167,85 @@ RSpec.describe API::Features, stub_feature_flags: false do
end end
end end
shared_examples 'does not enable the flag' do |actor_type, actor_path|
it 'returns the current state of the flag without changes' do
post api("/features/#{feature_name}", admin), params: { value: 'true', actor_type => actor_path }
expect(response).to have_gitlab_http_status(:created)
expect(json_response).to match(
"name" => feature_name,
"state" => "off",
"gates" => [
{ "key" => "boolean", "value" => false }
],
'definition' => known_feature_flag_definition_hash
)
end
end
shared_examples 'enables the flag for the actor' do |actor_type|
it 'sets the feature gate' do
post api("/features/#{feature_name}", admin), params: { value: 'true', actor_type => actor.full_path }
expect(response).to have_gitlab_http_status(:created)
expect(json_response).to match(
'name' => feature_name,
'state' => 'conditional',
'gates' => [
{ 'key' => 'boolean', 'value' => false },
{ 'key' => 'actors', 'value' => ["#{actor.class}:#{actor.id}"] }
],
'definition' => known_feature_flag_definition_hash
)
end
end
context 'when enabling for a project by path' do context 'when enabling for a project by path' do
context 'when the project exists' do context 'when the project exists' do
let!(:project) { create(:project) } it_behaves_like 'enables the flag for the actor', :project do
let(:actor) { create(:project) }
it 'sets the feature gate' do
post api("/features/#{feature_name}", admin), params: { value: 'true', project: project.full_path }
expect(response).to have_gitlab_http_status(:created)
expect(json_response).to match(
'name' => feature_name,
'state' => 'conditional',
'gates' => [
{ 'key' => 'boolean', 'value' => false },
{ 'key' => 'actors', 'value' => ["Project:#{project.id}"] }
],
'definition' => known_feature_flag_definition_hash
)
end end
end end
context 'when the project does not exist' do context 'when the project does not exist' do
it 'sets no new values' do it_behaves_like 'does not enable the flag', :project, 'mep/to/the/mep/mep'
post api("/features/#{feature_name}", admin), params: { value: 'true', project: 'mep/to/the/mep/mep' }
expect(response).to have_gitlab_http_status(:created)
expect(json_response).to match(
"name" => feature_name,
"state" => "off",
"gates" => [
{ "key" => "boolean", "value" => false }
],
'definition' => known_feature_flag_definition_hash
)
end
end end
end end
context 'when enabling for a group by path' do context 'when enabling for a group by path' do
context 'when the group exists' do context 'when the group exists' do
it 'sets the feature gate' do it_behaves_like 'enables the flag for the actor', :group do
group = create(:group) let(:actor) { create(:group) }
post api("/features/#{feature_name}", admin), params: { value: 'true', group: group.full_path }
expect(response).to have_gitlab_http_status(:created)
expect(json_response).to match(
'name' => feature_name,
'state' => 'conditional',
'gates' => [
{ 'key' => 'boolean', 'value' => false },
{ 'key' => 'actors', 'value' => ["Group:#{group.id}"] }
],
'definition' => known_feature_flag_definition_hash
)
end end
end end
context 'when the group does not exist' do context 'when the group does not exist' do
it 'sets no new values and keeps the feature disabled' do it_behaves_like 'does not enable the flag', :group, 'not/a/group'
post api("/features/#{feature_name}", admin), params: { value: 'true', group: 'not/a/group' } end
end
expect(response).to have_gitlab_http_status(:created)
expect(json_response).to match( context 'when enabling for a namespace by path' do
"name" => feature_name, context 'when the user namespace exists' do
"state" => "off", it_behaves_like 'enables the flag for the actor', :namespace do
"gates" => [ let(:actor) { create(:namespace) }
{ "key" => "boolean", "value" => false } end
], end
'definition' => known_feature_flag_definition_hash
) context 'when the group namespace exists' do
it_behaves_like 'enables the flag for the actor', :namespace do
let(:actor) { create(:group) }
end
end
context 'when the user namespace does not exist' do
it_behaves_like 'does not enable the flag', :namespace, 'not/a/group'
end
context 'when a project namespace exists' do
let(:project_namespace) { create(:project_namespace) }
it_behaves_like 'does not enable the flag', :namespace do
let(:actor_path) { project_namespace.full_path }
end end
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