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.
Files changed (63) hide show
  1. checksums.yaml +5 -5
  2. data/Gemfile.lock +26 -19
  3. data/bin/rdm +10 -10
  4. data/example/Rdm.packages +1 -17
  5. data/example/config/app.yml +6 -0
  6. data/example/infrastructure/repository/Package.rb +0 -1
  7. data/example/infrastructure/repository/fixture.txt +1 -0
  8. data/lib/rdm.rb +14 -7
  9. data/lib/rdm/errors.rb +3 -0
  10. data/lib/rdm/gen/init.rb +0 -4
  11. data/lib/rdm/package.rb +18 -9
  12. data/lib/rdm/package_importer.rb +4 -18
  13. data/lib/rdm/package_parser.rb +1 -0
  14. data/lib/rdm/packages/compiler_service.rb +1 -7
  15. data/lib/rdm/settings.rb +10 -21
  16. data/lib/rdm/source.rb +1 -18
  17. data/lib/rdm/source_parser.rb +2 -45
  18. data/lib/rdm/templates/init/Rdm.packages +0 -12
  19. data/lib/rdm/utils/ostruct_utils.rb +12 -0
  20. data/lib/rdm/version.rb +1 -1
  21. data/lib/rdm/yml_config/config_caster.rb +32 -0
  22. data/lib/rdm/yml_config/config_manager.rb +39 -0
  23. data/lib/rdm/yml_config/config_validator.rb +51 -0
  24. data/lib/rdm/yml_config/env_config.rb +46 -0
  25. data/lib/rdm/yml_config/env_config_dsl.rb +92 -0
  26. data/lib/rdm/yml_config/validate_config.rb +13 -0
  27. data/rdm.gemspec +3 -0
  28. data/spec/fixtures/SampleSource.rb +2 -4
  29. data/spec/fixtures/app.yml +17 -0
  30. data/spec/rdm/cli/gen_package_spec.rb +0 -2
  31. data/spec/rdm/gen/init_spec.rb +0 -12
  32. data/spec/rdm/gen/package_spec.rb +1 -0
  33. data/spec/rdm/package_importer_spec.rb +34 -2
  34. data/spec/rdm/rdm_spec.rb +1 -1
  35. data/spec/rdm/source_parser_spec.rb +0 -59
  36. data/spec/rdm/yml_config/config_caster_spec.rb +64 -0
  37. data/spec/rdm/yml_config/config_manager_spec.rb +7 -0
  38. data/spec/rdm/yml_config/config_validator_spec.rb +190 -0
  39. data/spec/rdm/yml_config/env_config_dsl_spec.rb +123 -0
  40. data/spec/spec_helper.rb +1 -0
  41. metadata +69 -34
  42. data/example/.rdm/templates/configs/<%=config_path%> +0 -2
  43. data/example/.rdm/templates/configs/<%=role_config_path%> +0 -2
  44. data/example/configs/app/default.yml +0 -2
  45. data/example/configs/app/production.yml +0 -2
  46. data/example/configs/database/default.yml +0 -3
  47. data/example/env_files/development.env +0 -3
  48. data/example/env_files/production.env +0 -5
  49. data/example/env_files/test.env +0 -3
  50. data/lib/rdm/cli/config.rb +0 -31
  51. data/lib/rdm/config.rb +0 -11
  52. data/lib/rdm/config_locals.rb +0 -11
  53. data/lib/rdm/config_manager.rb +0 -68
  54. data/lib/rdm/config_scope.rb +0 -23
  55. data/lib/rdm/gen/config.rb +0 -59
  56. data/lib/rdm/templates/configs/<%=config_path%> +0 -2
  57. data/lib/rdm/templates/configs/<%=role_config_path%> +0 -2
  58. data/lib/rdm/templates/init/env_files/development.env +0 -3
  59. data/lib/rdm/templates/init/env_files/production.env +0 -3
  60. data/lib/rdm/templates/init/env_files/test.env +0 -3
  61. data/spec/fixtures/config.yml +0 -2
  62. data/spec/rdm/config_manager_spec.rb +0 -136
  63. data/spec/rdm/gen/config_spec.rb +0 -31
@@ -2,33 +2,22 @@ class Rdm::Settings
2
2
  attr_reader :settings
3
3
 
4
4
  SETTING_KEYS = [
5
- :role, :package_subdir_name, :configs_dir, :config_path, :role_config_path,
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, :env_files_dir, :env_file_name
7
+ :compile_ignore_files, :compile_add_files
8
8
  ].freeze
9
9
 
10
- SETTING_VARIABLES = [:role, :configs_dir, :config_path, :role_config_path].freeze
10
+ SETTING_VARIABLES = [:role].freeze
11
11
 
12
12
  # Default settings
13
13
  def initialize
14
- silence_missing_package(false)
15
- silence_missing_package_file(false)
16
- package_subdir_name('package')
17
- configs_dir('configs')
18
- env_files_dir('env_files')
19
- compile_ignore_files([
20
- '.gitignore',
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|
@@ -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:, configs:)
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
@@ -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 and configs
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
- init_and_set_configs(source)
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'
@@ -0,0 +1,12 @@
1
+ require 'ostruct'
2
+
3
+ class Rdm::Utils::Ostruct
4
+ class << self
5
+ def to_recursive_ostruct(hash)
6
+ OpenStruct.new(hash.each_with_object({}) do |(key, val), memo|
7
+ memo[key] = val.is_a?(Hash) ? to_recursive_ostruct(val) : val
8
+ end)
9
+ end
10
+ end
11
+ end
12
+
@@ -1,3 +1,3 @@
1
1
  module Rdm
2
- VERSION = '0.4.14.2'.freeze
2
+ VERSION = '0.4.17'.freeze
3
3
  end
@@ -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