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 +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
|
[![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
|
-
#
|
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