dupervisor 1.0.2 → 1.0.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/README.md +75 -49
- data/lib/dupervisor/cli.rb +45 -45
- data/lib/dupervisor/config.rb +2 -3
- data/lib/dupervisor/formats/yaml.rb +0 -1
- data/lib/dupervisor/main.rb +4 -0
- data/lib/dupervisor/version.rb +1 -1
- metadata +1 -1
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 76bfc503dc8997edc0e6926cde6a7aed182d4a32
|
4
|
+
data.tar.gz: 683bb204b680c970a7c2156791ce6735d34cc438
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 48c9203124a4d72d534e4af996f60be2189ad70b716141972978339f02e63e77c9179f3eff77eaa04c8c632dfbfaac6a89a5da7efd507ec7a3fa94498232d960
|
7
|
+
data.tar.gz: c18ae3908021f61dfe427987a296adbc3557aa41420102f670323eb7b3ac63c9cec7be14dcef54b6208fbf3baa564383b88bfd804537149148d9f8ff631f1820
|
data/README.md
CHANGED
@@ -4,15 +4,17 @@
|
|
4
4
|
[](https://codeclimate.com/github/kigster/dupervisor/coverage)
|
5
5
|
[](https://codeclimate.com/github/kigster/dupervisor)
|
6
6
|
|
7
|
-
#
|
7
|
+
# dupervisor
|
8
8
|
|
9
|
-
|
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
|
-
|
11
|
+
* JSON
|
12
|
+
* YAML
|
13
|
+
* and the Windows INI file formats.
|
12
14
|
|
13
|
-
|
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
|
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
|
-
|
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
|
-
|
76
|
+
### From Ruby Code
|
94
77
|
|
95
|
-
|
96
|
-
|
97
|
-
|
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
|
-
|
97
|
+
There is an additional helper available to grab format from a filename:
|
114
98
|
|
115
|
-
|
99
|
+
```ruby
|
100
|
+
# This helper extracts format from a file extension
|
101
|
+
Detector.new('myfile.json').detect # => :json
|
102
|
+
```
|
116
103
|
|
117
|
-
|
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
|
-
|
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
|
-
|
124
|
-
|
125
|
-
|
126
|
-
|
127
|
-
|
128
|
-
|
129
|
-
--
|
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
|
|
data/lib/dupervisor/cli.rb
CHANGED
@@ -9,76 +9,76 @@ module DuperVisor
|
|
9
9
|
attr_accessor :args, :config, :parser
|
10
10
|
|
11
11
|
def initialize(args)
|
12
|
-
self.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
|
-
|
18
|
+
decorator = OptionsDecorator.new(opts, config)
|
19
|
+
decorator.usage
|
20
|
+
decorator.flags
|
21
|
+
decorator.examples
|
22
|
+
end
|
19
23
|
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
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
|
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.
|
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.
|
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
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
|
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
|
-
|
69
|
-
|
70
|
-
end
|
69
|
+
opts.separator ''
|
70
|
+
end
|
71
71
|
|
72
|
-
|
73
|
-
|
74
|
-
|
75
|
-
|
76
|
-
|
77
|
-
|
78
|
-
|
79
|
-
|
80
|
-
|
81
|
-
|
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
|
data/lib/dupervisor/config.rb
CHANGED
@@ -7,11 +7,10 @@ module DuperVisor
|
|
7
7
|
end
|
8
8
|
|
9
9
|
class Config
|
10
|
-
attr_accessor :to, :output
|
10
|
+
attr_accessor :to, :output
|
11
11
|
|
12
|
-
def initialize(to: nil, output: nil
|
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
|
|
data/lib/dupervisor/main.rb
CHANGED
@@ -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
|
data/lib/dupervisor/version.rb
CHANGED