Commit 80bd2ca8 authored by Shinya Maeda's avatar Shinya Maeda

Merge branch 'user-lists-strategies-unleash' into 'master'

Return User List Strategy to Unleash Clients

See merge request gitlab-org/gitlab!30650
parents 190173fb 7e3604dd
...@@ -53,7 +53,7 @@ module Operations ...@@ -53,7 +53,7 @@ module Operations
end end
def for_unleash_client(project, environment) def for_unleash_client(project, environment)
includes(strategies: :scopes) includes(strategies: [:scopes, :user_list])
.where(project: project) .where(project: project)
.merge(Operations::FeatureFlags::Scope.on_environment(environment)) .merge(Operations::FeatureFlags::Scope.on_environment(environment))
.reorder(:id) .reorder(:id)
......
...@@ -4,10 +4,12 @@ module Operations ...@@ -4,10 +4,12 @@ module Operations
module FeatureFlags module FeatureFlags
class Strategy < ApplicationRecord class Strategy < ApplicationRecord
STRATEGY_DEFAULT = 'default' STRATEGY_DEFAULT = 'default'
STRATEGY_GITLABUSERLIST = 'gitlabUserList'
STRATEGY_GRADUALROLLOUTUSERID = 'gradualRolloutUserId' STRATEGY_GRADUALROLLOUTUSERID = 'gradualRolloutUserId'
STRATEGY_USERWITHID = 'userWithId' STRATEGY_USERWITHID = 'userWithId'
STRATEGIES = { STRATEGIES = {
STRATEGY_DEFAULT => [].freeze, STRATEGY_DEFAULT => [].freeze,
STRATEGY_GITLABUSERLIST => [].freeze,
STRATEGY_GRADUALROLLOUTUSERID => %w[groupId percentage].freeze, STRATEGY_GRADUALROLLOUTUSERID => %w[groupId percentage].freeze,
STRATEGY_USERWITHID => ['userIds'].freeze STRATEGY_USERWITHID => ['userIds'].freeze
}.freeze }.freeze
...@@ -17,6 +19,8 @@ module Operations ...@@ -17,6 +19,8 @@ module Operations
belongs_to :feature_flag belongs_to :feature_flag
has_many :scopes, class_name: 'Operations::FeatureFlags::Scope' has_many :scopes, class_name: 'Operations::FeatureFlags::Scope'
has_one :strategy_user_list
has_one :user_list, through: :strategy_user_list
validates :name, validates :name,
inclusion: { inclusion: {
...@@ -25,11 +29,20 @@ module Operations ...@@ -25,11 +29,20 @@ module Operations
} }
validate :parameters_validations, if: -> { errors[:name].blank? } validate :parameters_validations, if: -> { errors[:name].blank? }
validates :user_list, presence: true, if: -> { name == STRATEGY_GITLABUSERLIST }
validates :user_list, absence: true, if: -> { name != STRATEGY_GITLABUSERLIST }
validate :same_project_validation, if: -> { user_list.present? }
accepts_nested_attributes_for :scopes, allow_destroy: true accepts_nested_attributes_for :scopes, allow_destroy: true
private private
def same_project_validation
unless user_list.project_id == feature_flag.project_id
errors.add(:user_list, 'must belong to the same project')
end
end
def parameters_validations def parameters_validations
validate_parameters_type && validate_parameters_type &&
validate_parameters_keys && validate_parameters_keys &&
......
# frozen_string_literal: true
module Operations
module FeatureFlags
class StrategyUserList < ApplicationRecord
self.table_name = 'operations_strategies_user_lists'
belongs_to :strategy
belongs_to :user_list
end
end
end
...@@ -7,7 +7,27 @@ module EE ...@@ -7,7 +7,27 @@ module EE
expose :name expose :name
expose :description, unless: ->(feature) { feature.description.nil? } expose :description, unless: ->(feature) { feature.description.nil? }
expose :active, as: :enabled expose :active, as: :enabled
expose :strategies, using: UnleashStrategy expose :strategies do |flag|
flag.strategies.map do |strategy|
if legacy_strategy?(strategy)
UnleashLegacyStrategy.represent(strategy)
elsif gitlab_user_list_strategy?(strategy)
UnleashGitlabUserListStrategy.represent(strategy)
else
UnleashStrategy.represent(strategy)
end
end
end
private
def legacy_strategy?(strategy)
!strategy.respond_to?(:name)
end
def gitlab_user_list_strategy?(strategy)
strategy.name == ::Operations::FeatureFlags::Strategy::STRATEGY_GITLABUSERLIST
end
end end
end end
end end
......
# frozen_string_literal: true
module EE
module API
module Entities
class UnleashGitlabUserListStrategy < Grape::Entity
expose :name do |_strategy|
::Operations::FeatureFlags::Strategy::STRATEGY_USERWITHID
end
expose :parameters do |strategy|
{ userIds: strategy.user_list.user_xids }
end
end
end
end
end
# frozen_string_literal: true
module EE
module API
module Entities
class UnleashLegacyStrategy < Grape::Entity
expose :name do |strategy|
strategy['name']
end
expose :parameters do |strategy|
strategy['parameters']
end
end
end
end
end
...@@ -4,20 +4,8 @@ module EE ...@@ -4,20 +4,8 @@ module EE
module API module API
module Entities module Entities
class UnleashStrategy < Grape::Entity class UnleashStrategy < Grape::Entity
expose :name do |strategy| expose :name
if strategy.respond_to?(:name) expose :parameters
strategy.name
else
strategy['name']
end
end
expose :parameters do |strategy|
if strategy.respond_to?(:parameters)
strategy.parameters
else
strategy['parameters']
end
end
end end
end end
end end
......
...@@ -494,6 +494,28 @@ describe API::Unleash do ...@@ -494,6 +494,28 @@ describe API::Unleash do
}] }]
}]) }])
end end
it 'returns a userWithId strategy for a gitlabUserList strategy' do
feature_flag = create(:operations_feature_flag, :new_version_flag, project: project,
name: 'myfeature', active: true)
user_list = create(:operations_feature_flag_user_list, project: project,
name: 'My List', user_xids: 'user1,user2')
strategy = create(:operations_strategy, feature_flag: feature_flag,
name: 'gitlabUserList', parameters: {}, user_list: user_list)
create(:operations_scope, strategy: strategy, environment_scope: 'production')
get api(features_url), headers: { 'UNLEASH-INSTANCEID' => client.token, 'UNLEASH-APPNAME' => 'production' }
expect(response).to have_gitlab_http_status(:ok)
expect(json_response['features']).to eq([{
'name' => 'myfeature',
'enabled' => true,
'strategies' => [{
'name' => 'userWithId',
'parameters' => { 'userIds' => 'user1,user2' }
}]
}])
end
end end
context 'when mixing version 1 and version 2 feature flags' do context 'when mixing version 1 and version 2 feature flags' do
......
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