dupervisor 1.0.2
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/.atom-build.json +22 -0
- data/.codeclimate.yml +30 -0
- data/.gitignore +16 -0
- data/.rspec +2 -0
- data/.rubocop.yml +1156 -0
- data/.travis.yml +15 -0
- data/Gemfile +4 -0
- data/LICENSE +21 -0
- data/README.md +162 -0
- data/Rakefile +6 -0
- data/bin/console +14 -0
- data/bin/setup +8 -0
- data/dupervisor.gemspec +30 -0
- data/exe/dv +16 -0
- data/lib/dupervisor.rb +8 -0
- data/lib/dupervisor/cli.rb +84 -0
- data/lib/dupervisor/config.rb +30 -0
- data/lib/dupervisor/content.rb +27 -0
- data/lib/dupervisor/detector.rb +23 -0
- data/lib/dupervisor/formats.rb +60 -0
- data/lib/dupervisor/formats/ini.rb +45 -0
- data/lib/dupervisor/formats/json.rb +11 -0
- data/lib/dupervisor/formats/yaml.rb +14 -0
- data/lib/dupervisor/main.rb +24 -0
- data/lib/dupervisor/parser.rb +50 -0
- data/lib/dupervisor/renderer.rb +24 -0
- data/lib/dupervisor/version.rb +3 -0
- metadata +189 -0
data/.travis.yml
ADDED
@@ -0,0 +1,15 @@
|
|
1
|
+
language: ruby
|
2
|
+
env:
|
3
|
+
- CODECLIMATE_REPO_TOKEN=49ca8c0e2d56ab70e7eabc237692e21cc8fe43ef13ed5d411fa20bf1e8997a44
|
4
|
+
rvm:
|
5
|
+
- 2.2.3
|
6
|
+
- 2.3.0
|
7
|
+
script: "bundle exec rspec --format documentation"
|
8
|
+
notifications:
|
9
|
+
slack:
|
10
|
+
rooms:
|
11
|
+
email:
|
12
|
+
recipients:
|
13
|
+
- kigster@gmail.com
|
14
|
+
on_success: change
|
15
|
+
on_failure: always
|
data/Gemfile
ADDED
data/LICENSE
ADDED
@@ -0,0 +1,21 @@
|
|
1
|
+
The MIT License (MIT)
|
2
|
+
|
3
|
+
Copyright (c) 2016 Konstantin Gredeskoul
|
4
|
+
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
7
|
+
in the Software without restriction, including without limitation the rights
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
10
|
+
furnished to do so, subject to the following conditions:
|
11
|
+
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
13
|
+
copies or substantial portions of the Software.
|
14
|
+
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
21
|
+
SOFTWARE.
|
data/README.md
ADDED
@@ -0,0 +1,162 @@
|
|
1
|
+
[![Gem Version](https://badge.fury.io/rb/dupervisor.svg)](https://badge.fury.io/rb/dupervisor)
|
2
|
+
[![Build Status](https://travis-ci.org/kigster/dupervisor.svg?branch=master)](https://travis-ci.org/kigster/dupervisor)
|
3
|
+
[![Code Climate](https://codeclimate.com/github/kigster/dupervisor/badges/gpa.svg)](https://codeclimate.com/github/kigster/dupervisor)
|
4
|
+
[![Test Coverage](https://codeclimate.com/github/kigster/dupervisor/badges/coverage.svg)](https://codeclimate.com/github/kigster/dupervisor/coverage)
|
5
|
+
[![Issue Count](https://codeclimate.com/github/kigster/dupervisor/badges/issue_count.svg)](https://codeclimate.com/github/kigster/dupervisor)
|
6
|
+
|
7
|
+
# DuperVisorâ„¢ Pro
|
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.
|
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.
|
12
|
+
|
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.
|
14
|
+
|
15
|
+
If you enjoy using this converted, please star the repo and we very much welcome all pull requests and contributions.
|
16
|
+
|
17
|
+
## YAML/JSON vs INI
|
18
|
+
|
19
|
+
Consider the following example taken from the [_supervisord_ configuration documentation](http://supervisord.org/configuration.html]):
|
20
|
+
|
21
|
+
```ini
|
22
|
+
[supervisord]
|
23
|
+
nodaemon = false
|
24
|
+
minfds = 1024
|
25
|
+
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
|
+
|
35
|
+
[program:cat]
|
36
|
+
command=/bin/cat
|
37
|
+
process_name=%(program_name)s
|
38
|
+
numprocs=1
|
39
|
+
directory=/tmp
|
40
|
+
umask=022
|
41
|
+
priority=999
|
42
|
+
autostart=true
|
43
|
+
autorestart=unexpected
|
44
|
+
|
45
|
+
```
|
46
|
+
|
47
|
+
We think that it is much easier to read this:
|
48
|
+
|
49
|
+
```yaml
|
50
|
+
supervisord:
|
51
|
+
nodaemon: false
|
52
|
+
minfds: 1024
|
53
|
+
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
|
+
|
63
|
+
program:
|
64
|
+
cat:
|
65
|
+
command: /bin/cat
|
66
|
+
process_name: %(program_name)s
|
67
|
+
numprocs: 1
|
68
|
+
directory: /tmp
|
69
|
+
umask: 022
|
70
|
+
priority: 999
|
71
|
+
autostart: true
|
72
|
+
autorestart: unexpected
|
73
|
+
```
|
74
|
+
|
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.
|
76
|
+
|
77
|
+
## Installation
|
78
|
+
|
79
|
+
Install the gem:
|
80
|
+
|
81
|
+
```
|
82
|
+
gem install dupervisor
|
83
|
+
```
|
84
|
+
|
85
|
+
or, if you are using Bundler, you can add it to your gem file like so:
|
86
|
+
|
87
|
+
```ruby
|
88
|
+
gem 'dupervisor'
|
89
|
+
```
|
90
|
+
|
91
|
+
## Usage
|
92
|
+
|
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:
|
94
|
+
|
95
|
+
```ruby
|
96
|
+
# This helper extracts format from a file extension
|
97
|
+
Detector.new('myfile.json').detect # => :json
|
98
|
+
|
99
|
+
# This is how you can parse content by specifying the format
|
100
|
+
content = Parser.new(File.read('myfile.json')).parse(:json)
|
101
|
+
|
102
|
+
# But the gem can also guess the source format from either
|
103
|
+
# the filename (if available) or the source content
|
104
|
+
content = Parser.new(File.read('myfile.json')).parse()
|
105
|
+
content.format # => :json
|
106
|
+
content.parse_result # => { ... } Hash
|
107
|
+
|
108
|
+
# Finally, here we are using Renderer to convert a hash stored
|
109
|
+
# in content.parse_result into a YAML formatted string.
|
110
|
+
Renderer.new(content.parse_result).render(:yaml) # => YAML string
|
111
|
+
```
|
112
|
+
|
113
|
+
You can use the provided executable `dupervisor` to convert from a JSON or YAML file into an INI
|
114
|
+
|
115
|
+
### `dv [source-file] [options]`
|
116
|
+
|
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.
|
119
|
+
|
120
|
+
#### Specific Options
|
121
|
+
|
122
|
+
```
|
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
|
130
|
+
```
|
131
|
+
|
132
|
+
#### Examples
|
133
|
+
|
134
|
+
__Guess input format, convert YAML format to an INI file:__
|
135
|
+
|
136
|
+
```
|
137
|
+
$ cat config.yml | dv --ini > config.ini
|
138
|
+
```
|
139
|
+
|
140
|
+
__Guess input format, convert INI format to a JSON file:__
|
141
|
+
|
142
|
+
```
|
143
|
+
$ dv config.ini --json -o config.json
|
144
|
+
```
|
145
|
+
|
146
|
+
|
147
|
+
## Contributing
|
148
|
+
|
149
|
+
Bug reports and pull requests are welcome on GitHub at https://github.com/kigster/dupervisor.
|
150
|
+
|
151
|
+
## Author
|
152
|
+
|
153
|
+
<p>© 2016 Konstantin Gredeskoul, all rights reserved.</p>
|
154
|
+
|
155
|
+
#### Acknowledgements
|
156
|
+
|
157
|
+
* [Shippo, Inc.](https://goshippo.com/) for sponsoring this work financially, and their commitment to open source.
|
158
|
+
* [Wissam Jarjoul](https://github.com/bosswissam) for many great ideas and a good eye for bugs.
|
159
|
+
|
160
|
+
## License
|
161
|
+
|
162
|
+
This project is distributed under the [MIT License](https://raw.githubusercontent.com/kigster/dupervisor/master/LICENSE).
|
data/Rakefile
ADDED
data/bin/console
ADDED
@@ -0,0 +1,14 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
|
3
|
+
require "bundler/setup"
|
4
|
+
require "dupervisor"
|
5
|
+
|
6
|
+
# You can add fixtures and/or initialization code here to make experimenting
|
7
|
+
# with your gem easier. You can also use a different console, if you like.
|
8
|
+
|
9
|
+
# (If you use this, don't forget to add pry to your Gemfile!)
|
10
|
+
# require "pry"
|
11
|
+
# Pry.start
|
12
|
+
|
13
|
+
require "irb"
|
14
|
+
IRB.start
|
data/bin/setup
ADDED
data/dupervisor.gemspec
ADDED
@@ -0,0 +1,30 @@
|
|
1
|
+
# coding: utf-8
|
2
|
+
lib = File.expand_path('../lib', __FILE__)
|
3
|
+
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
4
|
+
require 'dupervisor/version'
|
5
|
+
|
6
|
+
Gem::Specification.new do |spec|
|
7
|
+
spec.name = 'dupervisor'
|
8
|
+
spec.version = DuperVisor::VERSION
|
9
|
+
spec.authors = ['Konstantin Gredeskoul']
|
10
|
+
spec.email = ['kigster@gmail.com']
|
11
|
+
|
12
|
+
spec.summary = %q{Convert between YAML/JSON format and Windows INI format. }
|
13
|
+
spec.description = %q{This gem's purpose in life is to freely convert various configurations between supported formats, which are currently YAML, JSON and Windows INI file format. The gem is named after a popular package supervisord, which uses INI file format for it's configuration. This gem will allow you to move supervisord configuration into a YAML file, and integrate with other DevOps tools, while generating INI file on the fly. When installed, library exposes 'dv' executable, which is a an easy-to-use converter between these three formats.}
|
14
|
+
spec.homepage = 'https://github.com/kigster/dupervisor'
|
15
|
+
|
16
|
+
spec.files = `git ls-files -z`.split("\x0").reject { |f| f.match(%r{^(test|spec|features)/}) }
|
17
|
+
spec.bindir = 'exe'
|
18
|
+
spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
|
19
|
+
spec.require_paths = ['lib']
|
20
|
+
|
21
|
+
spec.add_dependency 'require_dir'
|
22
|
+
spec.add_dependency 'awesome_print'
|
23
|
+
spec.add_dependency 'colored2'
|
24
|
+
spec.add_dependency 'inifile'
|
25
|
+
|
26
|
+
spec.add_development_dependency 'codeclimate-test-reporter'
|
27
|
+
spec.add_development_dependency 'bundler', '~> 1.12'
|
28
|
+
spec.add_development_dependency 'rake', '~> 10.0'
|
29
|
+
spec.add_development_dependency 'rspec', '~> 3.0'
|
30
|
+
end
|
data/exe/dv
ADDED
@@ -0,0 +1,16 @@
|
|
1
|
+
#!/usr/bin/env ruby -W0
|
2
|
+
lib_path = File.dirname(__FILE__) + '/../lib'
|
3
|
+
if Dir.exist?(lib_path)
|
4
|
+
$LOAD_PATH << lib_path
|
5
|
+
end
|
6
|
+
require 'colored2'
|
7
|
+
require 'dupervisor'
|
8
|
+
require 'awesome_print'
|
9
|
+
|
10
|
+
begin
|
11
|
+
DuperVisor::Main.new(DuperVisor::CLI.new(ARGV).parse).run
|
12
|
+
rescue DuperVisor::CLIError => e
|
13
|
+
STDERR.puts 'Usage error: ' + e.message.bold.red
|
14
|
+
puts
|
15
|
+
DuperVisor::CLI.new(['--help']).parse
|
16
|
+
end
|
data/lib/dupervisor.rb
ADDED
@@ -0,0 +1,84 @@
|
|
1
|
+
require 'optparse'
|
2
|
+
require 'optparse/time'
|
3
|
+
require 'ostruct'
|
4
|
+
require 'pp'
|
5
|
+
require_relative 'config'
|
6
|
+
|
7
|
+
module DuperVisor
|
8
|
+
class CLI
|
9
|
+
attr_accessor :args, :config, :parser
|
10
|
+
|
11
|
+
def initialize(args)
|
12
|
+
self.args = args
|
13
|
+
self.config = Config.new
|
14
|
+
end
|
15
|
+
|
16
|
+
def parse
|
17
|
+
self.parser = OptionParser.new do |opts|
|
18
|
+
usage_banner(opts)
|
19
|
+
|
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
|
29
|
+
|
30
|
+
opts.on('-o', '--output [FILE]',
|
31
|
+
'File to write, if not supplied write to STDOUT') do |file|
|
32
|
+
config.output = file
|
33
|
+
end
|
34
|
+
|
35
|
+
opts.on('-v', '--verbose',
|
36
|
+
'Print extra debugging info') do
|
37
|
+
config.verbose = true
|
38
|
+
end
|
39
|
+
example_banner(opts)
|
40
|
+
|
41
|
+
# No argument, shows at tail. This will print an options summary.
|
42
|
+
# Try it and see!
|
43
|
+
opts.on_tail('-h', '--help', 'Show this message') do
|
44
|
+
puts opts
|
45
|
+
exit
|
46
|
+
end
|
47
|
+
|
48
|
+
# Another typical switch to print the version.
|
49
|
+
opts.on_tail('--version', 'Show version') do
|
50
|
+
puts DuperVisor::VERSION
|
51
|
+
exit
|
52
|
+
end
|
53
|
+
end
|
54
|
+
parser.parse!(args)
|
55
|
+
config
|
56
|
+
end
|
57
|
+
|
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
|
67
|
+
|
68
|
+
opts.separator ''
|
69
|
+
opts.separator 'Common options:'.bold.blue
|
70
|
+
end
|
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
|
82
|
+
end
|
83
|
+
end
|
84
|
+
end
|
@@ -0,0 +1,30 @@
|
|
1
|
+
require_relative 'content'
|
2
|
+
require_relative 'renderer'
|
3
|
+
require_relative 'detector'
|
4
|
+
|
5
|
+
module DuperVisor
|
6
|
+
class CLIError < ArgumentError
|
7
|
+
end
|
8
|
+
|
9
|
+
class Config
|
10
|
+
attr_accessor :to, :output, :verbose
|
11
|
+
|
12
|
+
def initialize(to: nil, output: nil, verbose: false)
|
13
|
+
self.to = to
|
14
|
+
self.verbose = verbose
|
15
|
+
self.output = output
|
16
|
+
end
|
17
|
+
|
18
|
+
def validate!
|
19
|
+
raise CLIError.new('Either the output format or filename is required!') unless to
|
20
|
+
|
21
|
+
self.output = if output.is_a?(String) && output != ''
|
22
|
+
File.open(output, 'w')
|
23
|
+
elsif output.respond_to?(:puts)
|
24
|
+
output
|
25
|
+
else
|
26
|
+
STDOUT
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
@@ -0,0 +1,27 @@
|
|
1
|
+
require 'yaml'
|
2
|
+
require 'json'
|
3
|
+
require 'inifile'
|
4
|
+
|
5
|
+
module DuperVisor
|
6
|
+
#
|
7
|
+
# This class is responsible for taking the input and converting it into a
|
8
|
+
# Hash. It can also be initialized with the Hash, in which no conversion is performed.
|
9
|
+
#
|
10
|
+
# The +result+
|
11
|
+
class Content
|
12
|
+
attr_accessor :body, :format, :parse_result
|
13
|
+
|
14
|
+
def initialize(body: nil, format: nil)
|
15
|
+
self.body = body
|
16
|
+
self.format = format
|
17
|
+
self.parse_result = {}
|
18
|
+
end
|
19
|
+
|
20
|
+
def self.to_format_from(hash, format)
|
21
|
+
format_class = ::DuperVisor::Formats::Base.formats[format]
|
22
|
+
raise ArgumentError.new("No format #{format} found") unless format_class
|
23
|
+
Content.new(body: format_class.to.call(hash), format: format_class.format)
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
@@ -0,0 +1,23 @@
|
|
1
|
+
module DuperVisor
|
2
|
+
class Detector
|
3
|
+
attr_accessor :filename
|
4
|
+
def initialize(filename)
|
5
|
+
self.filename = filename
|
6
|
+
end
|
7
|
+
|
8
|
+
def detect
|
9
|
+
format_from_extension(filename) if filename.is_a?(String)
|
10
|
+
end
|
11
|
+
|
12
|
+
private
|
13
|
+
|
14
|
+
def format_from_extension(filename)
|
15
|
+
extension = filename.gsub(/.*\.([\w]+)/, '\1')
|
16
|
+
format = if extension =~ /(json|ya?ml|ini)/i
|
17
|
+
f = extension.downcase.to_sym
|
18
|
+
f == :yml ? :yaml : f
|
19
|
+
end
|
20
|
+
format
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|