rdm 0.4.14.2 → 0.4.17
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +5 -5
- data/Gemfile.lock +26 -19
- data/bin/rdm +10 -10
- data/example/Rdm.packages +1 -17
- data/example/config/app.yml +6 -0
- data/example/infrastructure/repository/Package.rb +0 -1
- data/example/infrastructure/repository/fixture.txt +1 -0
- data/lib/rdm.rb +14 -7
- data/lib/rdm/errors.rb +3 -0
- data/lib/rdm/gen/init.rb +0 -4
- data/lib/rdm/package.rb +18 -9
- data/lib/rdm/package_importer.rb +4 -18
- data/lib/rdm/package_parser.rb +1 -0
- data/lib/rdm/packages/compiler_service.rb +1 -7
- data/lib/rdm/settings.rb +10 -21
- data/lib/rdm/source.rb +1 -18
- data/lib/rdm/source_parser.rb +2 -45
- data/lib/rdm/templates/init/Rdm.packages +0 -12
- data/lib/rdm/utils/ostruct_utils.rb +12 -0
- data/lib/rdm/version.rb +1 -1
- data/lib/rdm/yml_config/config_caster.rb +32 -0
- data/lib/rdm/yml_config/config_manager.rb +39 -0
- data/lib/rdm/yml_config/config_validator.rb +51 -0
- data/lib/rdm/yml_config/env_config.rb +46 -0
- data/lib/rdm/yml_config/env_config_dsl.rb +92 -0
- data/lib/rdm/yml_config/validate_config.rb +13 -0
- data/rdm.gemspec +3 -0
- data/spec/fixtures/SampleSource.rb +2 -4
- data/spec/fixtures/app.yml +17 -0
- data/spec/rdm/cli/gen_package_spec.rb +0 -2
- data/spec/rdm/gen/init_spec.rb +0 -12
- data/spec/rdm/gen/package_spec.rb +1 -0
- data/spec/rdm/package_importer_spec.rb +34 -2
- data/spec/rdm/rdm_spec.rb +1 -1
- data/spec/rdm/source_parser_spec.rb +0 -59
- data/spec/rdm/yml_config/config_caster_spec.rb +64 -0
- data/spec/rdm/yml_config/config_manager_spec.rb +7 -0
- data/spec/rdm/yml_config/config_validator_spec.rb +190 -0
- data/spec/rdm/yml_config/env_config_dsl_spec.rb +123 -0
- data/spec/spec_helper.rb +1 -0
- metadata +69 -34
- data/example/.rdm/templates/configs/<%=config_path%> +0 -2
- data/example/.rdm/templates/configs/<%=role_config_path%> +0 -2
- data/example/configs/app/default.yml +0 -2
- data/example/configs/app/production.yml +0 -2
- data/example/configs/database/default.yml +0 -3
- data/example/env_files/development.env +0 -3
- data/example/env_files/production.env +0 -5
- data/example/env_files/test.env +0 -3
- data/lib/rdm/cli/config.rb +0 -31
- data/lib/rdm/config.rb +0 -11
- data/lib/rdm/config_locals.rb +0 -11
- data/lib/rdm/config_manager.rb +0 -68
- data/lib/rdm/config_scope.rb +0 -23
- data/lib/rdm/gen/config.rb +0 -59
- data/lib/rdm/templates/configs/<%=config_path%> +0 -2
- data/lib/rdm/templates/configs/<%=role_config_path%> +0 -2
- data/lib/rdm/templates/init/env_files/development.env +0 -3
- data/lib/rdm/templates/init/env_files/production.env +0 -3
- data/lib/rdm/templates/init/env_files/test.env +0 -3
- data/spec/fixtures/config.yml +0 -2
- data/spec/rdm/config_manager_spec.rb +0 -136
- data/spec/rdm/gen/config_spec.rb +0 -31
data/lib/rdm/settings.rb
CHANGED
@@ -2,33 +2,22 @@ class Rdm::Settings
|
|
2
2
|
attr_reader :settings
|
3
3
|
|
4
4
|
SETTING_KEYS = [
|
5
|
-
:role, :package_subdir_name, :
|
5
|
+
:role, :package_subdir_name, :config_path,
|
6
6
|
:silence_missing_package_file, :silence_missing_package, :compile_path,
|
7
|
-
:compile_ignore_files, :compile_add_files
|
7
|
+
:compile_ignore_files, :compile_add_files
|
8
8
|
].freeze
|
9
9
|
|
10
|
-
SETTING_VARIABLES = [:role
|
10
|
+
SETTING_VARIABLES = [:role].freeze
|
11
11
|
|
12
12
|
# Default settings
|
13
13
|
def initialize
|
14
|
-
silence_missing_package
|
15
|
-
silence_missing_package_file
|
16
|
-
package_subdir_name
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
'.byebug_history',
|
22
|
-
'.irbrc',
|
23
|
-
'.rspec',
|
24
|
-
'*_spec.rb',
|
25
|
-
'*.log'
|
26
|
-
])
|
27
|
-
compile_add_files([
|
28
|
-
'Gemfile',
|
29
|
-
'Gemfile.lock'
|
30
|
-
])
|
31
|
-
compile_path('/tmp/rdm/:package_name')
|
14
|
+
silence_missing_package false
|
15
|
+
silence_missing_package_file false
|
16
|
+
package_subdir_name 'package'
|
17
|
+
compile_ignore_files %w(.gitignore .byebug_history .irbrc .rspec *_spec.rb *.log)
|
18
|
+
compile_add_files %w(Gemfile Gemfile.lock)
|
19
|
+
compile_path '/tmp/rdm/:package_name'
|
20
|
+
config_path 'config/:role.yml'
|
32
21
|
end
|
33
22
|
|
34
23
|
SETTING_KEYS.each do |key|
|
data/lib/rdm/source.rb
CHANGED
@@ -3,7 +3,6 @@ class Rdm::Source
|
|
3
3
|
|
4
4
|
def initialize(root_path:)
|
5
5
|
@root_path = root_path
|
6
|
-
@config_names = []
|
7
6
|
@package_paths = []
|
8
7
|
end
|
9
8
|
|
@@ -13,15 +12,6 @@ class Rdm::Source
|
|
13
12
|
@setup_block = block
|
14
13
|
end
|
15
14
|
|
16
|
-
# Add config to list of known configs
|
17
|
-
# @param config_name [String] Config name
|
18
|
-
def config(config_name)
|
19
|
-
config_name = config_name.to_s
|
20
|
-
raise Rdm::Errors::ConfigExists, config_name if @config_names.include?(config_name)
|
21
|
-
|
22
|
-
@config_names << config_name
|
23
|
-
end
|
24
|
-
|
25
15
|
# Add package to list of known packages
|
26
16
|
# @param package_path [String] Package path
|
27
17
|
def package(package_path)
|
@@ -32,9 +22,8 @@ class Rdm::Source
|
|
32
22
|
# @param value [Hash<String: Rdm::Package>] Hash of packages by it's name
|
33
23
|
# @param value [Hash<String: Rdm::Config>] Hash of configs by it's name
|
34
24
|
# @return [Hash<String: Rdm::Package>] Hash of packages by it's name
|
35
|
-
def init_with(packages
|
25
|
+
def init_with(packages:)
|
36
26
|
@packages = packages
|
37
|
-
@configs = configs
|
38
27
|
end
|
39
28
|
|
40
29
|
# Read initialized packages
|
@@ -42,10 +31,4 @@ class Rdm::Source
|
|
42
31
|
def packages
|
43
32
|
@packages || {}
|
44
33
|
end
|
45
|
-
|
46
|
-
# Read initialized configs
|
47
|
-
# @return [Hash<String: Rdm::Config>] Hash of configs by it's name
|
48
|
-
def configs
|
49
|
-
@configs || {}
|
50
|
-
end
|
51
34
|
end
|
data/lib/rdm/source_parser.rb
CHANGED
@@ -15,7 +15,7 @@ class Rdm::SourceParser
|
|
15
15
|
@stdout = stdout || STDOUT
|
16
16
|
end
|
17
17
|
|
18
|
-
# Read source file, parse and init it's packages
|
18
|
+
# Read source file, parse and init it's packages
|
19
19
|
# @param source_path [String] Source file path
|
20
20
|
# @return [Rdm::Source] Source
|
21
21
|
def read_and_init_source
|
@@ -28,9 +28,7 @@ class Rdm::SourceParser
|
|
28
28
|
validate_rdm_settings!
|
29
29
|
|
30
30
|
init_and_set_packages(source)
|
31
|
-
|
32
|
-
init_and_set_env_variables(source)
|
33
|
-
source.init_with(packages: packages, configs: configs)
|
31
|
+
source.init_with(packages: packages)
|
34
32
|
source
|
35
33
|
end
|
36
34
|
|
@@ -57,37 +55,6 @@ class Rdm::SourceParser
|
|
57
55
|
end
|
58
56
|
end
|
59
57
|
|
60
|
-
def init_and_set_configs(source)
|
61
|
-
source.config_names.each do |config_name|
|
62
|
-
default_path = settings.read_setting(:config_path, vars: { config_name: config_name })
|
63
|
-
role_path = settings.read_setting(:role_config_path, vars: { config_name: config_name })
|
64
|
-
config = Rdm::Config.new
|
65
|
-
config.default_path = default_path
|
66
|
-
config.role_path = role_path
|
67
|
-
config.name = config_name
|
68
|
-
configs[config_name] = config
|
69
|
-
end
|
70
|
-
end
|
71
|
-
|
72
|
-
def init_and_set_env_variables(source)
|
73
|
-
return unless settings.read_setting(:env_file_name)
|
74
|
-
|
75
|
-
unless File.exists?(env_file_path)
|
76
|
-
@stdout.puts "WARNING! Environment file '#{settings.read_setting(:env_file_name)}' was not found. Please, add #{env_file_path} file..."
|
77
|
-
return
|
78
|
-
end
|
79
|
-
|
80
|
-
File.foreach(env_file_path) do |line|
|
81
|
-
key, value = line.split('=').map(&:strip)
|
82
|
-
|
83
|
-
if ENV.has_key?(key) && ENV[key] != value
|
84
|
-
@stdout.puts "WARNING! Environment file '#{settings.read_setting(:env_file_name)}' overwrites ENV['#{key}'] variable from '#{ENV.fetch(key, nil)}' to '#{value}' ..."
|
85
|
-
end
|
86
|
-
|
87
|
-
ENV[key] = value
|
88
|
-
end
|
89
|
-
end
|
90
|
-
|
91
58
|
# Make sure that all required settings are in place
|
92
59
|
def validate_rdm_settings!
|
93
60
|
if settings.read_setting(:role).nil?
|
@@ -102,12 +69,6 @@ class Rdm::SourceParser
|
|
102
69
|
File.dirname(source_path)
|
103
70
|
end
|
104
71
|
|
105
|
-
def env_file_path
|
106
|
-
file_path = File.join(root_path, settings.read_setting(:env_files_dir), "#{settings.read_setting(:env_file_name)}")
|
107
|
-
|
108
|
-
file_path.gsub(/\.env$/, '').concat('.env')
|
109
|
-
end
|
110
|
-
|
111
72
|
# [String] Source file content
|
112
73
|
def source_content
|
113
74
|
@source_content ||= File.read(source_path)
|
@@ -117,10 +78,6 @@ class Rdm::SourceParser
|
|
117
78
|
@packages ||= {}
|
118
79
|
end
|
119
80
|
|
120
|
-
def configs
|
121
|
-
@configs ||= {}
|
122
|
-
end
|
123
|
-
|
124
81
|
def settings
|
125
82
|
Rdm.settings
|
126
83
|
end
|
@@ -3,22 +3,10 @@ setup do
|
|
3
3
|
ENV['RUBY_ENV'] || raise('please set RUBY_ENV environment variable')
|
4
4
|
end
|
5
5
|
|
6
|
-
env_file_name do
|
7
|
-
ENV['ENV_FILE']
|
8
|
-
end
|
9
|
-
|
10
|
-
configs_dir 'configs'
|
11
|
-
config_path ':configs_dir/:config_name/default.yml'
|
12
|
-
role_config_path ':configs_dir/:config_name/:role.yml'
|
13
|
-
|
14
|
-
env_files_dir 'env_files'
|
15
6
|
package_subdir_name 'package'
|
16
7
|
silence_missing_package true
|
17
8
|
end
|
18
9
|
|
19
|
-
config :database
|
20
|
-
config :logging
|
21
|
-
|
22
10
|
|
23
11
|
# package 'core/application/commands'
|
24
12
|
# package 'core/utils'
|
data/lib/rdm/version.rb
CHANGED
@@ -0,0 +1,32 @@
|
|
1
|
+
require 'morf'
|
2
|
+
|
3
|
+
class Rdm::ConfigCaster
|
4
|
+
def initialize(envs)
|
5
|
+
@envs = envs
|
6
|
+
end
|
7
|
+
|
8
|
+
def cast(hash)
|
9
|
+
hash[@envs.name] ||= {}
|
10
|
+
caster.cast(hash, input_keys: :string, skip_unexpected_attributes: true)
|
11
|
+
end
|
12
|
+
|
13
|
+
|
14
|
+
def to_hcast_string(env)
|
15
|
+
eval_string = "#{env.type} :#{env.name}, optional: #{env.optional}"
|
16
|
+
eval_string += env.is_array? ? ", each: :#{env.children.first.type}" : ""
|
17
|
+
eval_string += env.is_hash? ? %Q( do \n #{env.children.map { |e| to_hcast_string(e) }.join("\n")} \nend) : ""
|
18
|
+
|
19
|
+
eval_string
|
20
|
+
end
|
21
|
+
|
22
|
+
private
|
23
|
+
|
24
|
+
def caster
|
25
|
+
@caster ||= Class.new
|
26
|
+
@caster.include(Morf::Caster)
|
27
|
+
|
28
|
+
@caster.class_eval "attributes do\n #{to_hcast_string(@envs)}\n end"
|
29
|
+
|
30
|
+
@caster
|
31
|
+
end
|
32
|
+
end
|
@@ -0,0 +1,39 @@
|
|
1
|
+
require 'yaml'
|
2
|
+
|
3
|
+
class Rdm::ConfigManager
|
4
|
+
class << self
|
5
|
+
def load_config(envs:, path_to_config:)
|
6
|
+
new_config = Rdm::ConfigCaster.new(envs).cast(YAML.load(File.read(path_to_config)))
|
7
|
+
validate_params!(new_config, envs)
|
8
|
+
|
9
|
+
instance.config.merge! new_config
|
10
|
+
end
|
11
|
+
|
12
|
+
def reset!
|
13
|
+
instance.config.clear
|
14
|
+
end
|
15
|
+
|
16
|
+
def method_missing(meth, *args, &block)
|
17
|
+
instance.send(meth)
|
18
|
+
end
|
19
|
+
|
20
|
+
def instance
|
21
|
+
@instance ||= new
|
22
|
+
end
|
23
|
+
|
24
|
+
private
|
25
|
+
|
26
|
+
def validate_params!(config, envs)
|
27
|
+
Rdm::ConfigValidator.new(envs).validate!(config)
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
31
|
+
def method_missing(meth)
|
32
|
+
config.keys.include?(meth) ? Rdm::Utils::Ostruct.to_recursive_ostruct(config).send(meth) :
|
33
|
+
(raise ArgumentError, ":#{meth} configuration was not defined for current package. Add `import '#{meth}'` to your Package.rb file")
|
34
|
+
end
|
35
|
+
|
36
|
+
def config
|
37
|
+
@config ||= {}
|
38
|
+
end
|
39
|
+
end
|
@@ -0,0 +1,51 @@
|
|
1
|
+
require 'attr_validator'
|
2
|
+
|
3
|
+
class Rdm::ConfigValidator
|
4
|
+
def initialize(env_config)
|
5
|
+
@env_config = env_config
|
6
|
+
end
|
7
|
+
|
8
|
+
def validate!(hash_config)
|
9
|
+
dto = OpenStruct.new(hash_config)
|
10
|
+
|
11
|
+
if @env_config.is_hash?
|
12
|
+
@env_config.children.each do |subconfig|
|
13
|
+
self.class.new(subconfig).validate!(dto.send(@env_config.name).to_h)
|
14
|
+
end
|
15
|
+
elsif @env_config.is_array?
|
16
|
+
dto.send(@env_config.name).each do |el|
|
17
|
+
array_dto = OpenStruct.new(@env_config.name => el)
|
18
|
+
validator(@env_config.name, @env_config.children.first.validates.to_hash).validate!(array_dto)
|
19
|
+
end
|
20
|
+
else
|
21
|
+
validator(@env_config.name, @env_config.validates.to_hash).validate!(dto)
|
22
|
+
end
|
23
|
+
|
24
|
+
dto
|
25
|
+
rescue AttrValidator::Errors::ValidationError => e
|
26
|
+
raise Rdm::Errors::InvalidConfig, e.message
|
27
|
+
end
|
28
|
+
|
29
|
+
private
|
30
|
+
|
31
|
+
def validator(name, env_config)
|
32
|
+
return @validator if @validator
|
33
|
+
|
34
|
+
validator_class = Class.new
|
35
|
+
validator_class.include(AttrValidator::Validator)
|
36
|
+
|
37
|
+
validator_class.class_eval( to_attr_validator_string(name, env_config) )
|
38
|
+
|
39
|
+
@validator = validator_class.new
|
40
|
+
end
|
41
|
+
|
42
|
+
def to_attr_validator_string(name, validates)
|
43
|
+
validates_string = []
|
44
|
+
|
45
|
+
validates.each do |key, value|
|
46
|
+
validates_string.push "validates :#{name}, #{key}: #{value}"
|
47
|
+
end
|
48
|
+
|
49
|
+
validates_string.join("\n")
|
50
|
+
end
|
51
|
+
end
|
@@ -0,0 +1,46 @@
|
|
1
|
+
class Rdm::EnvConfig
|
2
|
+
module Types
|
3
|
+
STRING = :string
|
4
|
+
ARRAY = :array
|
5
|
+
HASH = :hash
|
6
|
+
SYMBOL = :symbol
|
7
|
+
INTEGER = :integer
|
8
|
+
|
9
|
+
ALL = [STRING, ARRAY, HASH, SYMBOL, INTEGER]
|
10
|
+
end
|
11
|
+
|
12
|
+
attr_reader :name, :type, :optional, :default, :validates
|
13
|
+
attr_accessor :children
|
14
|
+
|
15
|
+
def initialize(name:, type:, optional: false, default: nil, validates: nil, children: nil)
|
16
|
+
@name = name
|
17
|
+
@type = Types::ALL.include?(type) ? type: (raise ArgumentError, "Invalid env type")
|
18
|
+
@optional = !!optional
|
19
|
+
@validates = validates || Rdm::ValidateConfig.new
|
20
|
+
@children = (children || []).select {|e| e.is_a?(Rdm::EnvConfig)}
|
21
|
+
@default = default
|
22
|
+
end
|
23
|
+
|
24
|
+
def to_hash
|
25
|
+
hash = {
|
26
|
+
name: @name,
|
27
|
+
type: @type,
|
28
|
+
optional: @optional,
|
29
|
+
default: @default,
|
30
|
+
}.delete_if { |_, v| v.nil? }
|
31
|
+
|
32
|
+
hash[:children] = @children.map(&:to_hash) if @children.any?
|
33
|
+
hash[:validates] = @validates.to_hash if @validates.to_hash.any?
|
34
|
+
|
35
|
+
hash
|
36
|
+
end
|
37
|
+
|
38
|
+
def is_array?
|
39
|
+
@type == Types::ARRAY
|
40
|
+
end
|
41
|
+
|
42
|
+
def is_hash?
|
43
|
+
@type == Types::HASH
|
44
|
+
end
|
45
|
+
end
|
46
|
+
|
@@ -0,0 +1,92 @@
|
|
1
|
+
class Rdm::EnvConfigDSL
|
2
|
+
attr_reader :data
|
3
|
+
|
4
|
+
module Types
|
5
|
+
STRING = :string
|
6
|
+
ARRAY = :array
|
7
|
+
HASH = :hash
|
8
|
+
SYMBOL = :symbol
|
9
|
+
INTEGER = :integer
|
10
|
+
|
11
|
+
ALL = [STRING, ARRAY, HASH, SYMBOL, INTEGER]
|
12
|
+
end
|
13
|
+
|
14
|
+
def initialize
|
15
|
+
@data = []
|
16
|
+
end
|
17
|
+
|
18
|
+
def string(name, opts = {}, &block)
|
19
|
+
validations = Rdm::ValidateConfig.new
|
20
|
+
validations.instance_exec(&block) if block_given?
|
21
|
+
|
22
|
+
@data.push(
|
23
|
+
Rdm::EnvConfig.new(
|
24
|
+
name: name,
|
25
|
+
type: Types::STRING,
|
26
|
+
optional: opts[:optional],
|
27
|
+
default: opts[:default],
|
28
|
+
validates: validations
|
29
|
+
)
|
30
|
+
)
|
31
|
+
end
|
32
|
+
|
33
|
+
def symbol(name, opts = {}, &block)
|
34
|
+
validations = Rdm::ValidateConfig.new
|
35
|
+
validations.instance_exec(&block) if block_given?
|
36
|
+
|
37
|
+
@data.push(
|
38
|
+
Rdm::EnvConfig.new(
|
39
|
+
name: name,
|
40
|
+
type: Types::SYMBOL,
|
41
|
+
optional: opts[:optional],
|
42
|
+
default: opts[:default],
|
43
|
+
validates: validations
|
44
|
+
)
|
45
|
+
)
|
46
|
+
end
|
47
|
+
|
48
|
+
def integer(name, opts = {}, &block)
|
49
|
+
validations = Rdm::ValidateConfig.new
|
50
|
+
validations.instance_exec(&block) if block_given?
|
51
|
+
|
52
|
+
@data.push(
|
53
|
+
Rdm::EnvConfig.new(
|
54
|
+
name: name,
|
55
|
+
type: Types::INTEGER,
|
56
|
+
optional: opts[:optional],
|
57
|
+
default: opts[:default],
|
58
|
+
validates: validations
|
59
|
+
)
|
60
|
+
)
|
61
|
+
end
|
62
|
+
|
63
|
+
def array(name, opts = {}, &block)
|
64
|
+
array_values = self.class.new
|
65
|
+
array_values.send(opts.fetch(:each), nil, {}, &block)
|
66
|
+
|
67
|
+
@data.push(
|
68
|
+
Rdm::EnvConfig.new(
|
69
|
+
name: name,
|
70
|
+
type: Types::ARRAY,
|
71
|
+
optional: opts[:optional],
|
72
|
+
default: opts[:default],
|
73
|
+
children: array_values.data
|
74
|
+
)
|
75
|
+
)
|
76
|
+
end
|
77
|
+
|
78
|
+
def hash(name, opts = {}, &block)
|
79
|
+
hash_values = self.class.new
|
80
|
+
hash_values.instance_exec(&block)
|
81
|
+
|
82
|
+
@data.push(
|
83
|
+
Rdm::EnvConfig.new(
|
84
|
+
name: name,
|
85
|
+
type: Types::HASH,
|
86
|
+
optional: opts[:optional],
|
87
|
+
default: opts[:default],
|
88
|
+
children: hash_values.data
|
89
|
+
)
|
90
|
+
)
|
91
|
+
end
|
92
|
+
end
|