Commit 83d1b092 authored by Kamil Trzciński's avatar Kamil Trzciński

Merge branch 'ab-add-composable-array' into 'master'

Add ComposableArray to DRY CI entry `compose!`

See merge request gitlab-org/gitlab!44193
parents ca3bca71 3d456ab2
......@@ -7,7 +7,7 @@ module Gitlab
##
# Entry that represents a set of needs dependencies.
#
class Needs < ::Gitlab::Config::Entry::Node
class Needs < ::Gitlab::Config::Entry::ComposableArray
include ::Gitlab::Config::Entry::Validatable
validations do
......@@ -29,27 +29,16 @@ module Gitlab
end
end
def compose!(deps = nil)
super(deps) do
[@config].flatten.each_with_index do |need, index|
@entries[index] = ::Gitlab::Config::Entry::Factory.new(Entry::Need)
.value(need)
.with(key: "need", parent: self, description: "need definition.") # rubocop:disable CodeReuse/ActiveRecord
.create!
end
@entries.each_value do |entry|
entry.compose!(deps)
end
end
end
def value
values = @entries.values.select(&:type)
values = @entries.select(&:type)
values.group_by(&:type).transform_values do |values|
values.map(&:value)
end
end
def composable_class
Entry::Need
end
end
end
end
......
......@@ -7,7 +7,7 @@ module Gitlab
##
# Entry that represents a configuration of the ports of a Docker service.
#
class Ports < ::Gitlab::Config::Entry::Node
class Ports < ::Gitlab::Config::Entry::ComposableArray
include ::Gitlab::Config::Entry::Validatable
validations do
......@@ -16,28 +16,8 @@ module Gitlab
validates :config, port_unique: true
end
def compose!(deps = nil)
super do
@entries = []
@config.each do |config|
@entries << ::Gitlab::Config::Entry::Factory.new(Entry::Port)
.value(config || {})
.with(key: "port", parent: self, description: "port definition.") # rubocop:disable CodeReuse/ActiveRecord
.create!
end
@entries.each do |entry|
entry.compose!(deps)
end
end
end
def value
@entries.map(&:value)
end
def descendants
@entries
def composable_class
Entry::Port
end
end
end
......
......@@ -4,7 +4,7 @@ module Gitlab
module Ci
class Config
module Entry
class Rules < ::Gitlab::Config::Entry::Node
class Rules < ::Gitlab::Config::Entry::ComposableArray
include ::Gitlab::Config::Entry::Validatable
validations do
......@@ -12,24 +12,13 @@ module Gitlab
validates :config, type: Array
end
def compose!(deps = nil)
super(deps) do
@config.each_with_index do |rule, index|
@entries[index] = ::Gitlab::Config::Entry::Factory.new(Entry::Rules::Rule)
.value(rule)
.with(key: "rule", parent: self, description: "rule definition.") # rubocop:disable CodeReuse/ActiveRecord
.create!
end
@entries.each_value do |entry|
entry.compose!(deps)
end
end
end
def value
@config
end
def composable_class
Entry::Rules::Rule
end
end
end
end
......
......@@ -7,7 +7,7 @@ module Gitlab
##
# Entry that represents a configuration of Docker services.
#
class Services < ::Gitlab::Config::Entry::Node
class Services < ::Gitlab::Config::Entry::ComposableArray
include ::Gitlab::Config::Entry::Validatable
validations do
......@@ -15,28 +15,8 @@ module Gitlab
validates :config, services_with_ports_alias_unique: true, if: ->(record) { record.opt(:with_image_ports) }
end
def compose!(deps = nil)
super do
@entries = []
@config.each do |config|
@entries << ::Gitlab::Config::Entry::Factory.new(Entry::Service)
.value(config || {})
.with(key: "service", parent: self, description: "service definition.") # rubocop:disable CodeReuse/ActiveRecord
.create!
end
@entries.each do |entry|
entry.compose!(deps)
end
end
end
def value
@entries.map(&:value)
end
def descendants
@entries
def composable_class
Entry::Service
end
end
end
......
# frozen_string_literal: true
module Gitlab
module Config
module Entry
##
# Entry that represents a composable array definition
#
class ComposableArray < ::Gitlab::Config::Entry::Node
include ::Gitlab::Config::Entry::Validatable
include Gitlab::Utils::StrongMemoize
# TODO: Refactor `Validatable` code so that validations can apply to a child class
# See: https://gitlab.com/gitlab-org/gitlab/-/issues/263231
validations do
validates :config, type: Array
end
def compose!(deps = nil)
super do
@entries = Array(@entries)
# TODO: Isolate handling for a hash via: `[@config].flatten` to the `Needs` entry
# See: https://gitlab.com/gitlab-org/gitlab/-/issues/264376
[@config].flatten.each_with_index do |value, index|
raise ArgumentError, 'Missing Composable class' unless composable_class
composable_class_name = composable_class.name.demodulize.underscore
@entries << ::Gitlab::Config::Entry::Factory.new(composable_class)
.value(value)
.with(key: composable_class_name, parent: self, description: "#{composable_class_name} definition") # rubocop:disable CodeReuse/ActiveRecord
.create!
end
@entries.each do |entry|
entry.compose!(deps)
end
end
end
def value
@entries.map(&:value)
end
def descendants
@entries
end
def composable_class
strong_memoize(:composable_class) do
opt(:composable_class)
end
end
end
end
end
end
......@@ -10,7 +10,7 @@ module Gitlab
class ComposableHash < ::Gitlab::Config::Entry::Node
include ::Gitlab::Config::Entry::Validatable
# TODO: Refactor Validatable so these validations will not apply to a child class
# TODO: Refactor `Validatable` code so that validations can apply to a child class
# See: https://gitlab.com/gitlab-org/gitlab/-/issues/263231
validations do
validates :config, type: Hash
......
# frozen_string_literal: true
require 'spec_helper'
RSpec.describe Gitlab::Config::Entry::ComposableArray, :aggregate_failures do
let(:valid_config) do
[
{
DATABASE_SECRET: 'passw0rd'
},
{
API_TOKEN: 'passw0rd2'
}
]
end
let(:config) { valid_config }
let(:entry) { described_class.new(config) }
before do
allow(entry).to receive(:composable_class).and_return(Gitlab::Config::Entry::Node)
end
describe '#valid?' do
it 'is valid' do
expect(entry).to be_valid
end
context 'is invalid' do
let(:config) { { hello: :world } }
it { expect(entry).not_to be_valid }
end
end
describe '#compose!' do
before do
entry.compose!
end
it 'composes child entry with configured value' do
expect(entry.value).to eq(config)
end
it 'composes child entries with configured values' do
expect(entry[0]).to be_a(Gitlab::Config::Entry::Node)
expect(entry[0].description).to eq('node definition')
expect(entry[0].key).to eq('node')
expect(entry[0].metadata).to eq({})
expect(entry[0].parent.class).to eq(Gitlab::Config::Entry::ComposableArray)
expect(entry[0].value).to eq(DATABASE_SECRET: 'passw0rd')
expect(entry[1]).to be_a(Gitlab::Config::Entry::Node)
expect(entry[1].description).to eq('node definition')
expect(entry[1].key).to eq('node')
expect(entry[1].metadata).to eq({})
expect(entry[1].parent.class).to eq(Gitlab::Config::Entry::ComposableArray)
expect(entry[1].value).to eq(API_TOKEN: 'passw0rd2')
end
describe '#descendants' do
it 'creates descendant nodes' do
expect(entry.descendants.first).to be_a(Gitlab::Config::Entry::Node)
expect(entry.descendants.first.value).to eq(DATABASE_SECRET: 'passw0rd')
expect(entry.descendants.second).to be_a(Gitlab::Config::Entry::Node)
expect(entry.descendants.second.value).to eq(API_TOKEN: 'passw0rd2')
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