dupervisor 1.0.2 → 1.0.3

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: bca39c7b710df3bc2a87932f40b4f778b7612ccf
4
- data.tar.gz: 13aa34c9976da2a02b7ba1c3dcb532f845b8ce1d
3
+ metadata.gz: 76bfc503dc8997edc0e6926cde6a7aed182d4a32
4
+ data.tar.gz: 683bb204b680c970a7c2156791ce6735d34cc438
5
5
  SHA512:
6
- metadata.gz: 2682e95d55df050f8e9828ecbcf1a176c9d73e8ff8187f200ea0cb037efa209b96cbeed4bfebce6f5531a11d2f82a250baac46108667dbac11677923af001d11
7
- data.tar.gz: a59a88ea3b11907152002dd2cb61862b67ed546531e72b6f8ad80453a328771d7a9a64234cedf5f282c4d2c92ec8a9b1c9f863294e2547970619f08f2a1b3e82
6
+ metadata.gz: 48c9203124a4d72d534e4af996f60be2189ad70b716141972978339f02e63e77c9179f3eff77eaa04c8c632dfbfaac6a89a5da7efd507ec7a3fa94498232d960
7
+ data.tar.gz: c18ae3908021f61dfe427987a296adbc3557aa41420102f670323eb7b3ac63c9cec7be14dcef54b6208fbf3baa564383b88bfd804537149148d9f8ff631f1820
data/README.md CHANGED
@@ -4,15 +4,17 @@
4
4
  [![Test Coverage](https://codeclimate.com/github/kigster/dupervisor/badges/coverage.svg)](https://codeclimate.com/github/kigster/dupervisor/coverage)
5
5
  [![Issue Count](https://codeclimate.com/github/kigster/dupervisor/badges/issue_count.svg)](https://codeclimate.com/github/kigster/dupervisor)
6
6
 
7
- # DuperVisor™ Pro
7
+ # dupervisor
8
8
 
9
- The super-duper awesome library is your best friend if you want an easy way to convert configuration between any one of the supported formats, which at this time are: JSON, YAML, and Windows INI format.
9
+ Ruby gem `dupervisor` is a well tested library that offers an easy way to convert configuration between any two of the supported formats, which (at this time) are:
10
10
 
11
- This tool was originally created to allow storing configs of another great tool called [__supervisord__](http://supervisord.org), which is still highly applicable today, but unfortunately uses a rather [archaic configuration file format](http://supervisord.org/configuration.html) of the decades old Windows INI format.
11
+ * JSON
12
+ * YAML
13
+ * and the Windows INI file formats.
12
14
 
13
- Whatever your preferences are, the truth is that some of the modern DevOps tools (such as Ansible and SaltStack) are using YAML format extensively to configure the environments. Ability to "embed" YAML configuration for a tool like supervisord means that you don't have to go to multiple places to see what is being run everywhere.
15
+ Please see the [section "Motivation"](#motivation) below, which contains further discussion about why this is useful.
14
16
 
15
- If you enjoy using this converted, please star the repo and we very much welcome all pull requests and contributions.
17
+ If you enjoy using this library, please star the repo, and do submit pull requests and/or bug reports, as well as any other contributions – which are all accepted with gratitude.
16
18
 
17
19
  ## YAML/JSON vs INI
18
20
 
@@ -23,25 +25,12 @@ Consider the following example taken from the [_supervisord_ configuration docum
23
25
  nodaemon = false
24
26
  minfds = 1024
25
27
  minprocs = 200
26
- umask = 022
27
- user = chrism
28
- identifier = supervisor
29
- directory = /tmp
30
- nocleanup = true
31
- childlogdir = /tmp
32
- strip_ansi = false
33
- environment = PATH="/usr/bin:/usr/local/bin:/bin:/sbin",ENVIRONMENT="development"
34
28
 
35
29
  [program:cat]
36
30
  command=/bin/cat
37
31
  process_name=%(program_name)s
38
- numprocs=1
39
- directory=/tmp
40
- umask=022
41
- priority=999
42
32
  autostart=true
43
33
  autorestart=unexpected
44
-
45
34
  ```
46
35
 
47
36
  We think that it is much easier to read this:
@@ -51,28 +40,22 @@ supervisord:
51
40
  nodaemon: false
52
41
  minfds: 1024
53
42
  minprocs: 200
54
- umask: 022
55
- user: chrism
56
- identifier: supervisor
57
- directory: /tmp
58
- nocleanup: true
59
- childlogdir: /tmp
60
- strip_ansi: false
61
- environment: PATH="/usr/bin:/usr/local/bin:/bin:/sbin",ENVIRONMENT="development"
62
43
 
63
44
  program:
64
45
  cat:
65
46
  command: /bin/cat
66
47
  process_name: %(program_name)s
67
- numprocs: 1
68
- directory: /tmp
69
- umask: 022
70
- priority: 999
71
48
  autostart: true
72
49
  autorestart: unexpected
73
50
  ```
74
51
 
75
- Not only that, but with this structure you can leverage existing tools for merging information from the default environment to your production, and so on.
52
+ Besides arguably better readability, YAML format also allows you to leverage existing configuration management tools such as Chef, SaltStack or Ansible.
53
+
54
+ ### Supervisord Specifics
55
+
56
+ When parsing INI files, and upon encountering a hash key of the form `word1:word2`, such key is broken up into the two parts and second part is used to create a sub-hash, thus generating a three-level hash. Supervisord uses this syntax for describing all commands to run, such as `program:cat` or `program:pgbouncer`, etc. Parser for INI format will create a hash with keys `cat` and `pgbouncer`, which itself will be mapped to the key `program`.
57
+
58
+ Reverse is also true – and such a three-level hash will be collapsed by joining second and third level keys with a colon, before rendering INI file.
76
59
 
77
60
  ## Installation
78
61
 
@@ -90,12 +73,13 @@ gem 'dupervisor'
90
73
 
91
74
  ## Usage
92
75
 
93
- To perform translations in code, you would use `DuperVisor::Parser` class to parse an existing format, and `DuperVisor::Renderer` class to convert the intermediary hash into the destination format:
76
+ ### From Ruby Code
94
77
 
95
- ```ruby
96
- # This helper extracts format from a file extension
97
- Detector.new('myfile.json').detect # => :json
78
+ To perform config transformations in ruby, you would typically use the `DuperVisor::Parser` class to parse an existing format and, optionally, to guess the format of the content.
79
+
80
+ You would then use the `DuperVisor::Renderer` class to render the intermediate hash into the destination format, like so:
98
81
 
82
+ ```ruby
99
83
  # This is how you can parse content by specifying the format
100
84
  content = Parser.new(File.read('myfile.json')).parse(:json)
101
85
 
@@ -110,39 +94,81 @@ content.parse_result # => { ... } Hash
110
94
  Renderer.new(content.parse_result).render(:yaml) # => YAML string
111
95
  ```
112
96
 
113
- You can use the provided executable `dupervisor` to convert from a JSON or YAML file into an INI
97
+ There is an additional helper available to grab format from a filename:
114
98
 
115
- ### `dv [source-file] [options]`
99
+ ```ruby
100
+ # This helper extracts format from a file extension
101
+ Detector.new('myfile.json').detect # => :json
102
+ ```
116
103
 
117
- Summary: convert between several hierarchical configuration file formats, such as ini, yaml, json
118
- Automatically guesses the source format based either on the file extension, or by attempting to parse it for STDIN.
104
+ ### Command Line
119
105
 
120
- #### Specific Options
106
+ You can also use the provided executable `dv` to transform between supported formats.
121
107
 
108
+ ```bash
109
+ $ dv [source_file | STDIN ]
110
+ [ --yaml | --ini | --json ]
111
+ [ -o | --output output_file | STDOUT ]
122
112
  ```
123
- --ini Generate an INI file
124
- --yaml Generate a YAML file
125
- --json Generate a JSON file
126
- -o, --output [FILE] File to write, if not supplied write to STDOUT
127
- -v, --verbose Print extra debugging info
128
- -h, --help Show this message
129
- --version Show version
113
+
114
+ #### CLI Options
115
+
116
+ ```
117
+ --ini Generate an INI file
118
+ --yaml Generate a YAML file
119
+ --json Generate a JSON file
120
+ -o, --output [FILE] File to write, if not supplied write to STDOUT
121
+ -v, --verbose Print extra debugging info
122
+ -h, --help Show this message
123
+ --version Show version
130
124
  ```
131
125
 
132
126
  #### Examples
133
127
 
134
128
  __Guess input format, convert YAML format to an INI file:__
135
129
 
136
- ```
130
+ ```bash
137
131
  $ cat config.yml | dv --ini > config.ini
138
132
  ```
139
133
 
140
134
  __Guess input format, convert INI format to a JSON file:__
141
135
 
142
- ```
136
+ ```bash
143
137
  $ dv config.ini --json -o config.json
144
138
  ```
145
139
 
140
+ ## Adding New Formats
141
+
142
+ It should be relatively trivial to add new formats to the gem. Please check out the `lib/dupervisor/formats` folder, copy eg. `yaml.rb` file to a new name, and update the code.
143
+
144
+ Below is the actual code of YAML converter.
145
+
146
+ ```ruby
147
+ module DuperVisor
148
+ module Formats
149
+ class YAML < Base
150
+ aliases %i(yml)
151
+ from ->(string) { ::YAML.load(string) }
152
+ to ->(hash) { ::YAML.dump(hash) }
153
+ errors [Psych::SyntaxError]
154
+ end
155
+ end
156
+ end
157
+ ```
158
+
159
+ * __aliases__ are additional names of the format. Main name is the class name without the modules.
160
+ * __from__ is a proc that receives a string, and should return a hash or raise an error.
161
+ * __to__ is a proc that receives a hash, and is supposed to return a string representing the hash in a given format.
162
+ * __errors__ is a list of exceptions that parsing (`#to`) may raise if the content is not valid for this format.
163
+
164
+
165
+ ## Motivation
166
+
167
+ This tool was originally created to allow storing as YAML configuration of [__supervisord__](http://supervisord.org), which uses a [decades old configuration file format](http://supervisord.org/configuration.html) known as the Windows INI file.
168
+
169
+ Some of the modern DevOps tools (such as Ansible and SaltStack) are using YAML format extensively to configure the environments. Chef stores node attributes as a hash, which is DuperVisor's intermediate data structure. Therefore DuperVisor offers an opportunity to "embed" INI-files for tools like _supervisord_ natively within the configuration management software, to keep all configuration centralized. When configuration management tool executes, INI files can be re-rendered on the fly.
170
+
171
+ Note that the same applies to rendering into YAML or JSON, and that the source could also be any one of the three.
146
172
 
147
173
  ## Contributing
148
174
 
@@ -9,76 +9,76 @@ module DuperVisor
9
9
  attr_accessor :args, :config, :parser
10
10
 
11
11
  def initialize(args)
12
- self.args = args
12
+ self.args = args
13
13
  self.config = Config.new
14
14
  end
15
15
 
16
16
  def parse
17
17
  self.parser = OptionParser.new do |opts|
18
- usage_banner(opts)
18
+ decorator = OptionsDecorator.new(opts, config)
19
+ decorator.usage
20
+ decorator.flags
21
+ decorator.examples
22
+ end
19
23
 
20
- opts.on('--ini', 'Generate an INI file') do
21
- config.to = :ini
22
- end
23
- opts.on('--yaml', 'Generate a YAML file') do
24
- config.to = :yaml
25
- end
26
- opts.on('--json', 'Generate a JSON file') do
27
- config.to = :json
28
- end
24
+ parser.parse!(args)
25
+ config
26
+ end
27
+
28
+ class OptionsDecorator < Struct.new(:opts, :config)
29
+
30
+ def flags
31
+ opts.separator 'Options:'.bold.blue.underlined
32
+ opts.separator ' Output Format:'.bold.yellow
33
+ opts.on('--ini', 'Generate an INI file') { config.to = :ini }
34
+ opts.on('--yaml', 'Generate a YAML file') { config.to = :yaml }
35
+ opts.on('--json', 'Generate a JSON file') { config.to = :json }
36
+ opts.separator ''
29
37
 
38
+ opts.separator ' Flags:'.bold.yellow
30
39
  opts.on('-o', '--output [FILE]',
31
- 'File to write, if not supplied write to STDOUT') do |file|
40
+ 'File to write, STDOUT if none.') do |file|
32
41
  config.output = file
33
42
  end
34
43
 
35
- opts.on('-v', '--verbose',
36
- 'Print extra debugging info') do
37
- config.verbose = true
38
- end
39
- example_banner(opts)
40
-
41
44
  # No argument, shows at tail. This will print an options summary.
42
45
  # Try it and see!
43
- opts.on_tail('-h', '--help', 'Show this message') do
46
+ opts.on('-h', '--help', 'Show this message') do
44
47
  puts opts
45
48
  exit
46
49
  end
47
50
 
48
51
  # Another typical switch to print the version.
49
- opts.on_tail('--version', 'Show version') do
52
+ opts.on('--version', 'Show version') do
50
53
  puts DuperVisor::VERSION
51
54
  exit
52
55
  end
56
+
53
57
  end
54
- parser.parse!(args)
55
- config
56
- end
57
58
 
58
- def example_banner(opts)
59
- opts.separator ''
60
- opts.separator 'Examples:'.bold.blue
61
- opts.separator ''
62
- opts.separator ' # guess input format, convert YAML format to an INI file'
63
- opts.separator ' cat config.yml | dv --ini > config.ini'.green
64
- opts.separator ''
65
- opts.separator ' # guess input format, convert INI format to a JSON file '
66
- opts.separator ' dv config.ini --json -o config.json'.green
59
+ def examples
60
+ opts.separator ''
61
+ opts.separator 'Examples:'.bold.blue.underlined
62
+ opts.separator ''
63
+ opts.separator ' # guess input format, convert YAML format to an INI file'
64
+ opts.separator ' cat config.yml | dv --ini > config.ini'.green
65
+ opts.separator ''
66
+ opts.separator ' # guess input format, convert INI format to a JSON file '
67
+ opts.separator ' dv config.ini --json -o config.json'.green
67
68
 
68
- opts.separator ''
69
- opts.separator 'Common options:'.bold.blue
70
- end
69
+ opts.separator ''
70
+ end
71
71
 
72
- def usage_banner(opts)
73
- opts.banner = 'Usage: '.bold.blue + 'dv [source-file] [options] '.bold.green
74
- opts.separator ''
75
- opts.separator ' Convert between several hierarchical configuration'
76
- opts.separator ' file formats, such as ' + 'ini, yaml, json'.bold.green
77
- opts.separator ''
78
- opts.separator ' Automatically guesses the source format based either on'
79
- opts.separator ' the file extension, or by attempting to parse it for STDIN'
80
- opts.separator ''
81
- opts.separator 'Specific options:'.bold.blue
72
+ def usage
73
+ opts.banner = 'Usage:'.bold.blue.underlined + "\n" + ' dv [source-file] [options] '.bold.green
74
+ opts.separator ''
75
+ opts.separator ' Convert between several hierarchical configuration'
76
+ opts.separator ' file formats, such as ' + 'ini, yaml, json.'.bold.green
77
+ opts.separator ''
78
+ opts.separator ' Automatically detects the source format based on either'
79
+ opts.separator ' the file extension, or by attempting to parse STDIN.'
80
+ opts.separator ''
81
+ end
82
82
  end
83
83
  end
84
84
  end
@@ -7,11 +7,10 @@ module DuperVisor
7
7
  end
8
8
 
9
9
  class Config
10
- attr_accessor :to, :output, :verbose
10
+ attr_accessor :to, :output
11
11
 
12
- def initialize(to: nil, output: nil, verbose: false)
12
+ def initialize(to: nil, output: nil)
13
13
  self.to = to
14
- self.verbose = verbose
15
14
  self.output = output
16
15
  end
17
16
 
@@ -10,5 +10,4 @@ module DuperVisor
10
10
  errors [Psych::SyntaxError]
11
11
  end
12
12
  end
13
-
14
13
  end
@@ -17,6 +17,10 @@ module DuperVisor
17
17
  self.content = Parser.new(ARGF.read).parse(from_format)
18
18
  Renderer.new(content.parse_result, config.output).render(config.to)
19
19
  rescue DuperVisor::Parser::ParseError => e
20
+ report_error(e)
21
+ end
22
+
23
+ def report_error(e)
20
24
  puts ' Error:'.bold.white + ' Unable to parse input.'.bold.red
21
25
  puts 'Details:'.bold.white + " #{e.inspect}".red
22
26
  end
@@ -1,3 +1,3 @@
1
1
  module DuperVisor
2
- VERSION = "1.0.2"
2
+ VERSION = '1.0.3'.freeze
3
3
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: dupervisor
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.0.2
4
+ version: 1.0.3
5
5
  platform: ruby
6
6
  authors:
7
7
  - Konstantin Gredeskoul