yaml_master 0.4.2 → 1.0.0.beta

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 6b92fa420cc7d3c24f1bb62a31383d801a9723fb
4
- data.tar.gz: 18dc5fe8f6ac65c4b5944bca3ab5a1cc1beb05c2
3
+ metadata.gz: 070d60a6d5c053d57f09ac3b78adbadc0624a221
4
+ data.tar.gz: ad225310f64d0f800a4d31134098a901a440942b
5
5
  SHA512:
6
- metadata.gz: 77f5487fa6c68e326d89277ff4e94e6cb8c4338e28c817009921df0697c807b8533f25736b37c85eca140d53c285b1aba7cc5bfd287f5e748e1eacec0ec55b39
7
- data.tar.gz: 1ac82cbab64bd30db593e37bac4db1d3913a0540b30e5e5312948390d70a8edfa740be60ef30d54d0a6e779a3ddc30b59b797d42192c6f810146e2b6e01ce9ef
6
+ metadata.gz: bfc70674eb8c9a0208e0c1232cceb98d551089fa1c5184e796a23c6042d4df2ca7a87fb188a48ff8fa888184b0f61699df53839238c7b073fa17e5d271ef88b9
7
+ data.tar.gz: 582379f1ee6357a8336c1b0c1c19c7a4554bf865a0c376471d84025de3a1c01efd711a860e779e954baff02e419839ad2c8b751fc28dc73926b2ea97a44a940d
data/.travis.yml CHANGED
@@ -1,6 +1,7 @@
1
1
  language: ruby
2
2
  sudo: false
3
3
  rvm:
4
- - 2.2.3
5
- before_install: gem install bundler -v 1.10.5
4
+ - 2.3.4
5
+ - 2.4.1
6
+ before_install: gem install bundler -v 1.15.4
6
7
  cache: bundler
data/Dockerfile ADDED
@@ -0,0 +1,7 @@
1
+ FROM ruby:2.4-alpine
2
+
3
+ ARG version
4
+
5
+ RUN if [[ "$version" = "" ]]; then gem install yaml_master --no-document; else gem install yaml_master --no-document --version ${version}; fi
6
+
7
+ ENTRYPOINT ["yaml_master"]
data/README.md CHANGED
@@ -35,6 +35,17 @@ Usage: yaml_master [options]
35
35
  --version print the version
36
36
  ```
37
37
 
38
+ ### Support YAML tags
39
+
40
+ | tag | description |
41
+ | ------------------------ | ------------------------------------------------------------------------------------- |
42
+ | !include {yaml_filename} | Replace value by other yaml file content. included file can use alias in master file. |
43
+ | !master_path | Replace value by master file path |
44
+ | !user_home | Replace value by `ENV["HOME"]`. |
45
+ | !env {key} | Replace value by `ENV["{key}"]`. |
46
+ | !properties {key} | Replace value by fetched value from given properties. |
47
+ | !read_file_if_exist {filename} | Replace value by content of {filename}. if {filename} does not exist, Replace value by `null` |
48
+
38
49
  at first, Write master.yml
39
50
 
40
51
  ```yaml
@@ -96,6 +107,15 @@ data:
96
107
  database: my_database
97
108
  table: my_table
98
109
  mode: insert
110
+
111
+ tag_sample
112
+ included: !include included.yml
113
+ master_path: !master_path
114
+ user_home: !user_home
115
+ env: !env HOME
116
+ properties: !properties foo
117
+ read_file_if_exist: !read_file_if_exist sample.txt
118
+ read_file_if_exist_nothing: !read_file_if_exist nothing.txt
99
119
  ```
100
120
 
101
121
  ### single output
@@ -193,6 +213,54 @@ out:
193
213
  mode: insert
194
214
  ```
195
215
 
216
+ ```yaml
217
+ # ./tag_sample.yml
218
+
219
+ ---
220
+ included:
221
+ xyz: hoge
222
+ db:
223
+ adapter: mysql2
224
+ encoding: utf8
225
+ database: development
226
+ pool: 5
227
+ host:
228
+ username: root
229
+ password:
230
+ socket: "/tmp/mysql.sock"
231
+ abc:
232
+ - 1
233
+ - 2.3
234
+ - a: 1
235
+ b: 2
236
+ included2:
237
+ - foo: bar
238
+ - hoge: fuga
239
+ - :abc:
240
+ - 1
241
+ - 2
242
+ - 3
243
+ master_path: "/home/joker/.ghq/github.com/joker1007/yaml_master/spec/sample.yml"
244
+ master_path2: "/home/joker/.ghq/github.com/joker1007/yaml_master/spec/sample.yml"
245
+ user_home: "/home/joker"
246
+ user_home2: "/home/joker"
247
+ env: "/home/joker"
248
+ properties: '24'
249
+ read_file_if_exist: 'dummy
250
+
251
+ '
252
+ read_file_if_exist_nothing:
253
+ read_file_if_exist2: 'dummy '
254
+ ```
255
+
256
+ ## How to use with Docker
257
+
258
+ ```sh
259
+ docker run --rm \
260
+ -v `pwd`/:/vol \
261
+ joker1007/yaml_master -m /vol/spec/sample.yml -k database_yml -o /vol/test.yml
262
+ ```
263
+
196
264
  ## Development
197
265
 
198
266
  After checking out the repo, run `bin/setup` to install dependencies. Then, run `rake rspec` to run the tests. You can also run `bin/console` for an interactive prompt that will allow you to experiment.
data/exe/yaml_master CHANGED
@@ -1,45 +1,71 @@
1
1
  #!/usr/bin/env ruby
2
2
 
3
+ require "optparse"
3
4
  require "yaml_master"
4
- require "slop"
5
-
6
- opts = Slop.parse(strict: true) do
7
- on 'm', 'master=', 'master yaml file'
8
- on 'k', 'key=', 'single generate target key (in data: block)'
9
- on 'o', 'output=', 'output filename for single generate target'
10
- on 'a', 'all', 'target all key (defined in yaml_master: block)'
11
- on 'p', 'properties=', 'set property (--properties="NAME=VALUE,NAME=VALUE" or -p "NAME=VALUE" -p "NAME=VALUE")', as: Array
12
- on 'h', 'help', 'display this help'
13
- on 'v', 'verbose', 'verbose mode'
14
- on '--version', 'print the version' do
5
+
6
+ options = {properties: []}
7
+
8
+ opt_parser = OptionParser.new do |opts|
9
+ opts.on("-m", "--master=MASTER_FILE", "master yaml file") do |master|
10
+ options[:master] = master
11
+ end
12
+
13
+ opts.on("-k", "--key=KEY", "single generate target key (in data: block)") do |key|
14
+ options[:key] = key
15
+ end
16
+
17
+ opts.on("-o", "--output=OUTPUT", "output filename for single generate target") do |output|
18
+ options[:output] = output
19
+ end
20
+
21
+ opts.on("-a", "--all", "target all key (defined in yaml_master: block)") do |all|
22
+ options[:all] = true
23
+ end
24
+
25
+ opts.on("-d", "--dump", "dump evaluated master yaml") do ||
26
+ options[:dump] = true
27
+ end
28
+
29
+ opts.on("-p", "--properties=PROPERTIES", %q{set property (--properties="NAME=VALUE,NAME=VALUE" or -p "NAME=VALUE" -p "NAME=VALUE")}) do |properties|
30
+ options[:properties].concat(properties.split(/\s*,\s*/))
31
+ end
32
+
33
+ opts.on("-v", "--verbose", "verbose mode") do |verbose|
34
+ options[:verbose] = true
35
+ end
36
+
37
+ opts.on("--version", "Print version") do
15
38
  puts YamlMaster::VERSION
16
39
  exit
17
40
  end
18
- end
19
41
 
20
- options = opts.to_hash
21
-
22
- if options[:help]
23
- puts opts
24
- exit
42
+ opts.on("-h", "--help", "Prints this help") do
43
+ puts opts
44
+ exit
45
+ end
25
46
  end
26
47
 
48
+ opt_parser.parse!(ARGV)
49
+
27
50
  unless options[:master]
28
51
  puts "--master options is necessary"
29
- puts opts
52
+ puts opt_parser
30
53
  exit 1
31
54
  end
32
55
 
33
- if options[:all].nil? && options[:key].nil?
34
- puts "--all or --key is necessary"
35
- puts opts
56
+ if options[:all].nil? && options[:key].nil? && options[:dump].nil?
57
+ puts "--all or --key or --dump is necessary"
58
+ puts opt_parser
36
59
  exit 1
37
60
  end
38
61
 
39
- yaml_master = YamlMaster.new(options[:master], options[:properties] || [])
62
+ yaml_master = YamlMaster.new(options[:master], options[:properties])
40
63
 
41
64
  if options[:all]
42
65
  yaml_master.generate_all(verbose: options[:verbose])
66
+ elsif options[:dump]
67
+ result = yaml_master.dump(options[:output], {verbose: options[:verbose]})
68
+ puts result unless options[:output]
43
69
  else
44
70
  result = yaml_master.generate(options[:key], options[:output], {verbose: options[:verbose]})
45
71
  puts result unless options[:output]
data/lib/yaml_master.rb CHANGED
@@ -3,11 +3,8 @@ require "yaml_master/version"
3
3
  require "yaml"
4
4
  require "erb"
5
5
  require "pathname"
6
- require "pp"
7
6
 
8
- YAML.add_domain_type(nil, "include") do |type, val|
9
- YAML.load_file(val)
10
- end
7
+ require "yaml_master/yaml_tree_builder"
11
8
 
12
9
  class YamlMaster
13
10
  class KeyFetchError < StandardError
@@ -15,36 +12,36 @@ class YamlMaster
15
12
  super("cannot fetch key \"#{key}\" from\n#{data.pretty_inspect}")
16
13
  end
17
14
  end
18
- class PropertyParseError < StandardError; end
19
-
20
15
  attr_reader :master, :master_path, :properties
21
16
 
22
17
  def initialize(io_or_filename, property_strings = [])
23
- parse_properties(property_strings)
18
+ case io_or_filename
19
+ when String
20
+ @master_path = Pathname(io_or_filename).expand_path
21
+ when File
22
+ @master_path = Pathname(io_or_filename.absolute_path)
23
+ end
24
24
 
25
- embedded_methods_binding = EmbeddedMethods.new(self).get_binding
26
- data =
27
- if io_or_filename.is_a?(IO)
28
- ERB.new(io_or_filename.read).result(embedded_methods_binding)
29
- else
30
- @master_path = File.expand_path(io_or_filename)
31
- ERB.new(File.read(io_or_filename)).result(embedded_methods_binding)
32
- end
25
+ @properties = PropertyParser.parse_properties(property_strings)
26
+ yaml = Context.new(master_path, @properties).render_master
27
+
28
+ parser = YAML::Parser.new
29
+ parser.handler = YamlMaster::YAMLTreeBuilder.new(@master_path, @properties, parser)
30
+ @tree = parser.parse(yaml).handler.root
31
+ @master = @tree.to_ruby[0]
33
32
 
34
- @master = YAML.load(data)
35
33
  raise "yaml_master key is necessary on toplevel" unless @master["yaml_master"]
36
34
  raise "data key is necessary on toplevel" unless @master["data"]
37
35
  end
38
36
 
39
37
  def generate(key, output = nil, options = {})
40
- puts "gen: #{output}" if options[:verbose]
41
38
  yaml = YAML.dump(fetch_data_from_master(key))
39
+ write_to_output(yaml, output, options[:verbose])
40
+ end
42
41
 
43
- return yaml unless output
44
-
45
- File.open(output, 'w') do |f|
46
- f.write(yaml)
47
- end
42
+ def dump(output = nil, options = {})
43
+ yaml = @tree.to_yaml
44
+ write_to_output(yaml, output, options[:verbose])
48
45
  end
49
46
 
50
47
  def generate_all(options = {})
@@ -76,30 +73,43 @@ class YamlMaster
76
73
  end
77
74
  end
78
75
 
79
- def parse_properties(property_strings)
80
- @properties = {}
81
- if property_strings.is_a?(Hash)
82
- @properties = property_strings
83
- else
84
- property_strings.each_with_object(@properties) do |str, hash|
85
- key, value = str.split("=")
86
- raise PropertyParseError.new("#{str} is invalid format") unless key && value
87
- hash[key] = value
88
- end
76
+ def write_to_output(yaml, output, verbose)
77
+ if output && verbose
78
+ puts <<~VERBOSE
79
+ gen: #{output}
80
+ #{yaml}
81
+ VERBOSE
89
82
  end
90
- end
91
83
 
92
- class EmbeddedMethods
93
- def initialize(yaml_master)
94
- @yaml_master = yaml_master
84
+ return yaml unless output
85
+
86
+ File.open(output, 'w') do |f|
87
+ f.write(yaml)
95
88
  end
89
+ end
90
+
91
+ module PropertyParser
92
+ class ParseError < StandardError; end
96
93
 
97
- def master_path
98
- Pathname(@yaml_master.master_path)
94
+ def self.parse_properties(property_strings_or_hash)
95
+ if property_strings_or_hash.is_a?(Hash)
96
+ property_strings_or_hash
97
+ else
98
+ property_strings_or_hash.each_with_object({}) do |str, hash|
99
+ key, value = str.split("=")
100
+ raise ParseError.new("#{str} is invalid format") unless key && value
101
+ hash[key] = value
102
+ end
103
+ end
99
104
  end
105
+ end
106
+
107
+ class Context
108
+ attr_reader :master_path, :properties
100
109
 
101
- def properties
102
- @yaml_master.properties
110
+ def initialize(master_path, properties)
111
+ @master_path = master_path
112
+ @properties = properties
103
113
  end
104
114
 
105
115
  def user_home
@@ -111,8 +121,8 @@ class YamlMaster
111
121
  File.read(path)
112
122
  end
113
123
 
114
- def get_binding
115
- binding
124
+ def render_master
125
+ ERB.new(File.read(@master_path)).result(binding)
116
126
  end
117
127
  end
118
128
  end
@@ -1,3 +1,3 @@
1
1
  class YamlMaster
2
- VERSION = "0.4.2"
2
+ VERSION = "1.0.0.beta"
3
3
  end
@@ -0,0 +1,74 @@
1
+ # frozen_string_literal: false
2
+ require 'yaml'
3
+ require 'pathname'
4
+
5
+ class YamlMaster::YAMLTreeBuilder < YAML::TreeBuilder
6
+ def initialize(master_path, properties, parser)
7
+ super()
8
+ @master_path = master_path
9
+ @properties = properties
10
+ @parser = parser
11
+ end
12
+
13
+ def scalar(value, anchor, tag, plain, quoted, style)
14
+ case tag
15
+ when "!include"
16
+ ensure_tag_argument(tag, value)
17
+
18
+ path = Pathname(value)
19
+ path = path.absolute? ? path : @master_path.dirname.join(path)
20
+ tree = YAML.parse(File.read(path))
21
+ @last.children << tree.children[0]
22
+ when "!master_path"
23
+ s = build_scalar_node(@master_path.to_s)
24
+ @last.children << s
25
+ s
26
+ when "!user_home"
27
+ s = build_scalar_node(ENV["HOME"])
28
+ @last.children << s
29
+ s
30
+ when "!properties"
31
+ ensure_tag_argument(tag, value)
32
+
33
+ s = build_scalar_node(@properties[value])
34
+ @last.children << s
35
+ s
36
+ when "!env"
37
+ ensure_tag_argument(tag, value)
38
+
39
+ s = build_scalar_node(ENV[value])
40
+ @last.children << s
41
+ s
42
+ when "!read_file_if_exist"
43
+ ensure_tag_argument(tag, value)
44
+
45
+ path = Pathname(value)
46
+ path = path.absolute? ? path : @master_path.dirname.join(path)
47
+ content = path.file? && path.readable? ? File.read(path) : nil
48
+ s = build_scalar_node(content, false, true, 4)
49
+ @last.children << s
50
+ s
51
+ else
52
+ super
53
+ end
54
+ end
55
+
56
+ private
57
+
58
+ def ensure_tag_argument(tag, value)
59
+ if value.empty?
60
+ mark = @parser.mark
61
+ $stderr.puts "tag format error"
62
+ $stderr.puts "#{tag} requires 1 argument at #{mark.line}:#{mark.column}"
63
+ exit 1
64
+ end
65
+ end
66
+
67
+ def build_scalar_node(value, plain = true, quoted = true, style = 1)
68
+ if value
69
+ YAML::Nodes::Scalar.new(value, nil, nil, plain, quoted, style)
70
+ else
71
+ YAML::Nodes::Scalar.new("null", nil, nil, true, false, 1)
72
+ end
73
+ end
74
+ end
data/yaml_master.gemspec CHANGED
@@ -18,9 +18,7 @@ Gem::Specification.new do |spec|
18
18
  spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
19
19
  spec.require_paths = ["lib"]
20
20
 
21
- spec.add_runtime_dependency "slop", "~> 3.6"
22
-
23
- spec.add_development_dependency "bundler", "~> 1.10"
21
+ spec.add_development_dependency "bundler", "~> 1.15"
24
22
  spec.add_development_dependency "rake", "~> 10.0"
25
23
  spec.add_development_dependency "rspec"
26
24
  spec.add_development_dependency "fakefs"
metadata CHANGED
@@ -1,43 +1,29 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: yaml_master
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.4.2
4
+ version: 1.0.0.beta
5
5
  platform: ruby
6
6
  authors:
7
7
  - joker1007
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2016-03-24 00:00:00.000000000 Z
11
+ date: 2017-09-09 00:00:00.000000000 Z
12
12
  dependencies:
13
- - !ruby/object:Gem::Dependency
14
- name: slop
15
- requirement: !ruby/object:Gem::Requirement
16
- requirements:
17
- - - "~>"
18
- - !ruby/object:Gem::Version
19
- version: '3.6'
20
- type: :runtime
21
- prerelease: false
22
- version_requirements: !ruby/object:Gem::Requirement
23
- requirements:
24
- - - "~>"
25
- - !ruby/object:Gem::Version
26
- version: '3.6'
27
13
  - !ruby/object:Gem::Dependency
28
14
  name: bundler
29
15
  requirement: !ruby/object:Gem::Requirement
30
16
  requirements:
31
17
  - - "~>"
32
18
  - !ruby/object:Gem::Version
33
- version: '1.10'
19
+ version: '1.15'
34
20
  type: :development
35
21
  prerelease: false
36
22
  version_requirements: !ruby/object:Gem::Requirement
37
23
  requirements:
38
24
  - - "~>"
39
25
  - !ruby/object:Gem::Version
40
- version: '1.10'
26
+ version: '1.15'
41
27
  - !ruby/object:Gem::Dependency
42
28
  name: rake
43
29
  requirement: !ruby/object:Gem::Requirement
@@ -91,6 +77,7 @@ files:
91
77
  - ".gitignore"
92
78
  - ".rspec"
93
79
  - ".travis.yml"
80
+ - Dockerfile
94
81
  - Gemfile
95
82
  - README.md
96
83
  - Rakefile
@@ -99,6 +86,7 @@ files:
99
86
  - exe/yaml_master
100
87
  - lib/yaml_master.rb
101
88
  - lib/yaml_master/version.rb
89
+ - lib/yaml_master/yaml_tree_builder.rb
102
90
  - yaml_master.gemspec
103
91
  homepage: https://github.com/joker1007/yaml_master
104
92
  licenses: []
@@ -114,12 +102,12 @@ required_ruby_version: !ruby/object:Gem::Requirement
114
102
  version: '0'
115
103
  required_rubygems_version: !ruby/object:Gem::Requirement
116
104
  requirements:
117
- - - ">="
105
+ - - ">"
118
106
  - !ruby/object:Gem::Version
119
- version: '0'
107
+ version: 1.3.1
120
108
  requirements: []
121
109
  rubyforge_project:
122
- rubygems_version: 2.5.1
110
+ rubygems_version: 2.6.12
123
111
  signing_key:
124
112
  specification_version: 4
125
113
  summary: Helper of YAML file generation from single master YAML file