Commit ba885679 authored by Jason Goodman's avatar Jason Goodman Committed by Shinya Maeda

Support version 2 feature flags in API POST, PUT, and DELETE

Hide behind feature flag
parent 1438907f
......@@ -34,7 +34,7 @@ module Operations
before_create :build_default_scope, if: -> { legacy_flag? && scopes.none? }
accepts_nested_attributes_for :scopes, allow_destroy: true
accepts_nested_attributes_for :strategies
accepts_nested_attributes_for :strategies, allow_destroy: true
scope :ordered, -> { order(:name) }
......
......@@ -26,6 +26,8 @@ module Operations
validate :parameters_validations, if: -> { errors[:name].blank? }
accepts_nested_attributes_for :scopes, allow_destroy: true
private
def parameters_validations
......
......@@ -30,9 +30,7 @@ module API
.new(user_project, current_user, declared_params(include_missing: false))
.execute
present paginate(feature_flags),
with: EE::API::Entities::FeatureFlag,
feature_flags_new_version_enabled: feature_flags_new_version_enabled?
present_entity(paginate(feature_flags))
end
desc 'Create a new feature flag' do
......@@ -42,26 +40,39 @@ module API
params do
requires :name, type: String, desc: 'The name of feature flag'
optional :description, type: String, desc: 'The description of the feature flag'
optional :version, type: String, desc: 'The version of the feature flag', values: Operations::FeatureFlag.versions.keys
optional :scopes, type: Array do
requires :environment_scope, type: String, desc: 'The environment scope of the scope'
requires :active, type: Boolean, desc: 'Active/inactive of the scope'
requires :strategies, type: JSON, desc: 'The strategies of the scope'
end
optional :strategies, type: Array do
requires :name, type: String, desc: 'The strategy name'
requires :parameters, type: JSON, desc: 'The strategy parameters'
optional :scopes, type: Array do
requires :environment_scope, type: String, desc: 'The environment scope of the scope'
end
end
end
post do
authorize_create_feature_flag!
attrs = declared_params(include_missing: false)
ensure_post_version_2_flags_enabled! if attrs[:version] == 'new_version_flag'
rename_key(attrs, :scopes, :scopes_attributes)
rename_key(attrs, :strategies, :strategies_attributes)
update_value(attrs, :strategies_attributes) do |strategies|
strategies.map { |s| rename_key(s, :scopes, :scopes_attributes) }
end
result = ::FeatureFlags::CreateService
.new(user_project, current_user, attrs)
.execute
if result[:status] == :success
present result[:feature_flag],
with: EE::API::Entities::FeatureFlag,
feature_flags_new_version_enabled: feature_flags_new_version_enabled?
present_entity(result[:feature_flag])
else
render_api_error!(result[:message], result[:http_status])
end
......@@ -79,9 +90,7 @@ module API
get do
authorize_read_feature_flag!
present feature_flag,
with: EE::API::Entities::FeatureFlag,
feature_flags_new_version_enabled: feature_flags_new_version_enabled?
present_entity(feature_flag)
end
desc 'Enable a strategy for a feature flag on an environment' do
......@@ -94,13 +103,14 @@ module API
end
post :enable do
not_found! unless Feature.enabled?(:feature_flag_api, user_project)
render_api_error!('Version 2 flags not supported', :unprocessable_entity) if new_version_flag_present?
result = ::FeatureFlags::EnableService
.new(user_project, current_user, params).execute
if result[:status] == :success
status :ok
present result[:feature_flag], with: EE::API::Entities::FeatureFlag
present_entity(result[:feature_flag])
else
render_api_error!(result[:message], result[:http_status])
end
......@@ -116,13 +126,55 @@ module API
end
post :disable do
not_found! unless Feature.enabled?(:feature_flag_api, user_project)
render_api_error!('Version 2 flags not supported', :unprocessable_entity) if feature_flag.new_version_flag?
result = ::FeatureFlags::DisableService
.new(user_project, current_user, params).execute
if result[:status] == :success
status :ok
present result[:feature_flag], with: EE::API::Entities::FeatureFlag
present_entity(result[:feature_flag])
else
render_api_error!(result[:message], result[:http_status])
end
end
desc 'Update a feature flag' do
detail 'This feature will be introduced in GitLab 13.1 if feature_flags_new_version feature flag is removed'
success EE::API::Entities::FeatureFlag
end
params do
optional :description, type: String, desc: 'The description of the feature flag'
optional :strategies, type: Array do
optional :id, type: Integer, desc: 'The strategy id'
optional :name, type: String, desc: 'The strategy type'
optional :parameters, type: JSON, desc: 'The strategy parameters'
optional :_destroy, type: Boolean, desc: 'Delete the strategy when true'
optional :scopes, type: Array do
optional :id, type: Integer, desc: 'The environment scope id'
optional :environment_scope, type: String, desc: 'The environment scope of the scope'
optional :_destroy, type: Boolean, desc: 'Delete the scope when true'
end
end
end
put do
not_found! unless feature_flags_new_version_enabled?
authorize_update_feature_flag!
render_api_error!('PUT operations are not supported for legacy feature flags', :unprocessable_entity) if feature_flag.legacy_flag?
attrs = declared_params(include_missing: false)
rename_key(attrs, :strategies, :strategies_attributes)
update_value(attrs, :strategies_attributes) do |strategies|
strategies.map { |s| rename_key(s, :scopes, :scopes_attributes) }
end
result = ::FeatureFlags::UpdateService
.new(user_project, current_user, attrs)
.execute(feature_flag)
if result[:status] == :success
present_entity(result[:feature_flag])
else
render_api_error!(result[:message], result[:http_status])
end
......@@ -140,9 +192,7 @@ module API
.execute(feature_flag)
if result[:status] == :success
present result[:feature_flag],
with: EE::API::Entities::FeatureFlag,
feature_flags_new_version_enabled: feature_flags_new_version_enabled?
present_entity(result[:feature_flag])
else
render_api_error!(result[:message], result[:http_status])
end
......@@ -163,18 +213,38 @@ module API
authorize! :create_feature_flag, user_project
end
def authorize_update_feature_flag!
authorize! :update_feature_flag, feature_flag
end
def authorize_destroy_feature_flag!
authorize! :destroy_feature_flag, feature_flag
end
def present_entity(result)
present result,
with: EE::API::Entities::FeatureFlag,
feature_flags_new_version_enabled: feature_flags_new_version_enabled?
end
def ensure_post_version_2_flags_enabled!
unless feature_flags_new_version_enabled?
render_api_error!('Version 2 flags are not enabled for this project', :unprocessable_entity)
end
end
def feature_flag
@feature_flag ||= if Feature.enabled?(:feature_flags_new_version, user_project)
@feature_flag ||= if feature_flags_new_version_enabled?
user_project.operations_feature_flags.find_by_name!(params[:name])
else
user_project.operations_feature_flags.legacy_flag.find_by_name!(params[:name])
end
end
def new_version_flag_present?
user_project.operations_feature_flags.new_version_flag.find_by_name(params[:name]).present?
end
def feature_flags_new_version_enabled?
Feature.enabled?(:feature_flags_new_version, user_project)
end
......@@ -183,6 +253,11 @@ module API
hash[new_key] = hash.delete(old_key) if hash.key?(old_key)
hash
end
def update_value(hash, key)
hash[key] = yield(hash[key]) if hash.key?(key)
hash
end
end
end
end
This diff is collapsed.
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