confswap 0.0.2 → 0.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/.gitignore +3 -0
- data/README.md +15 -20
- data/Rakefile +5 -0
- data/confswap.gemspec +3 -2
- data/features/version.feature +7 -0
- data/lib/confswap/command.rb +41 -33
- data/lib/confswap/env_reader.rb +3 -3
- data/lib/confswap/property_reader.rb +45 -0
- data/lib/confswap/version.rb +1 -1
- data/lib/confswap.rb +1 -0
- data/spec/conf_reader_spec.rb +6 -6
- data/spec/env_reader_spec.rb +6 -6
- data/spec/property_reader_spec.rb +50 -0
- data/spec/spec_helper.rb +6 -6
- metadata +26 -7
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 215b9df2a80e58dc45557cb8359c50e87077480c
|
4
|
+
data.tar.gz: b00ef6a97570079f5dd225eba7685347cf8f62bd
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 16bf29af5ea5965625970900ae230813e7c7267393212343532114e5b0eb46eeb20e65b23246cf0b2c3dc13d51248b513598c869b12377d969b8d79f05dafcda
|
7
|
+
data.tar.gz: 9814d9e753eba16381f24d07ad22aeed0d1fb87c79717f4e2ab15b55d65bd238f8f7cc2e23083b2071ca8d04f5407c5085df958538e03ef1011417ba6b09beb8
|
data/.gitignore
CHANGED
data/README.md
CHANGED
@@ -3,33 +3,27 @@
|
|
3
3
|
|
4
4
|
|
5
5
|
|
6
|
-
|
7
6
|
A simple command line tool to take a configuration file with template placeholders and replace those placeholders with environment variables.
|
8
7
|
|
9
|
-
|
10
|
-
|
11
|
-
## Introduction
|
12
|
-
|
13
|
-
This is mostly for me to use as a convenience tool when creating docker containers.
|
14
|
-
|
15
|
-
When working with elasticsearch, I have used their system for using environment variables in the config, and this has worked very well for me especially when using ENV variables with docker run.
|
8
|
+
The variables can come explicitly from the command, or read from a properties file.
|
16
9
|
|
17
10
|
## Usage
|
18
11
|
|
19
|
-
|
12
|
+
Configuration files come in different shapes and forms, confswap doesn't care if its toml or yaml
|
20
13
|
|
21
|
-
`export GIBLET_STATUS=active`
|
22
|
-
`export SPLENETIC_JUICE_FACTOR=10`
|
23
|
-
|
24
|
-
`example.conf|.toml|.yaml`
|
25
14
|
```
|
15
|
+
# example.conf|.toml|.yaml
|
16
|
+
|
26
17
|
# This is a configuration file
|
18
|
+
|
27
19
|
giblet_status=%{GIBLETS_STATUS}
|
28
20
|
splenetic_juice_factor=%{SPLENETIC_JUICE_FACTOR}
|
29
21
|
```
|
30
22
|
|
31
23
|
Then run confswap on the file
|
32
24
|
|
25
|
+
confswap
|
26
|
+
|
33
27
|
## Requirements
|
34
28
|
|
35
29
|
Requires ruby version > 2.0
|
@@ -45,19 +39,20 @@ Get the dependencies
|
|
45
39
|
Run the tests
|
46
40
|
``rake spec``
|
47
41
|
|
48
|
-
|
49
|
-
|
50
|
-
|
42
|
+
## Thoughts?
|
43
|
+
|
44
|
+
Why not just use sed and replace in some kind of bash script?
|
45
|
+
|
46
|
+
I originally used this approach but the script grew unwieldy, maybe I don't do good bash or maybe its just because of lack of testing. Whilst the benefit of a bash script is that it will run as-is on many systems, I find it better to treat a tool like this as software and therefore use the ecosystems already available to manage dependencies and deploy. I also enjoy programming in ruby :)
|
51
47
|
|
52
48
|
## Tasks to do and improvement ideas
|
53
49
|
|
54
50
|
- ~~error message when config contains env variable that doesnt exist~~
|
51
|
+
- ~~acceptance tests~~
|
52
|
+
- Read config from properties file
|
55
53
|
- verbose command
|
56
54
|
- summary of what will change? dry-run maybe?
|
55
|
+
- diff on what has changed in a config if overwriting?
|
57
56
|
- test command.rb
|
58
|
-
- ~~acceptance tests~~
|
59
|
-
|
60
|
-
- internationalization :)
|
61
57
|
- document...
|
62
|
-
- diff on what has changed in a config if overwriting?
|
63
58
|
|
data/Rakefile
CHANGED
@@ -1,4 +1,5 @@
|
|
1
1
|
begin
|
2
|
+
require 'rubygems'
|
2
3
|
require 'bundler/gem_tasks'
|
3
4
|
require 'rspec/core/rake_task'
|
4
5
|
require 'cucumber'
|
@@ -10,6 +11,10 @@ begin
|
|
10
11
|
|
11
12
|
RSpec::Core::RakeTask.new(:spec)
|
12
13
|
|
14
|
+
task :bump do
|
15
|
+
end
|
16
|
+
|
17
|
+
task :build => ['bump']
|
13
18
|
task :default => ['spec']
|
14
19
|
task :test => ['spec','features']
|
15
20
|
|
data/confswap.gemspec
CHANGED
@@ -1,13 +1,14 @@
|
|
1
1
|
Gem::Specification.new do |s|
|
2
2
|
s.name = 'confswap'
|
3
|
-
s.version = '0.0.
|
3
|
+
s.version = '0.0.3'
|
4
4
|
s.licenses = ['APACHE2']
|
5
5
|
s.summary = "Confswap swaps conf variables!"
|
6
6
|
s.description = "Create a configuration from a template using environment variables"
|
7
7
|
s.authors = ["Tom Cowling"]
|
8
8
|
s.email = 'tom.cowling@gmail.com'
|
9
9
|
s.homepage = 'https://www.tlcowling.com/gems/confswap'
|
10
|
-
s.add_runtime_dependency 'clamp'
|
10
|
+
s.add_runtime_dependency 'clamp'
|
11
|
+
s.add_runtime_dependency 'thor'
|
11
12
|
|
12
13
|
s.files = `git ls-files`.split("\n")
|
13
14
|
s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
|
data/lib/confswap/command.rb
CHANGED
@@ -3,73 +3,81 @@ require 'confswap'
|
|
3
3
|
|
4
4
|
module Confswap
|
5
5
|
class Command < Clamp::Command
|
6
|
+
|
6
7
|
def initialize(*args)
|
7
8
|
super(*args)
|
8
9
|
end
|
9
|
-
|
10
|
+
|
11
|
+
def help(*args)
|
10
12
|
return [
|
11
13
|
"This is confswap version #{Confswap::VERSION}",
|
12
|
-
|
13
|
-
|
14
|
-
|
14
|
+
super
|
15
|
+
].join("\n")
|
16
|
+
end
|
15
17
|
|
16
|
-
|
18
|
+
def run(*args)
|
17
19
|
super(*args)
|
18
|
-
|
20
|
+
end
|
19
21
|
|
20
22
|
def execute
|
21
|
-
|
22
23
|
if version?
|
23
|
-
|
24
|
-
|
24
|
+
puts Confswap::VERSION
|
25
|
+
return 0
|
25
26
|
end
|
26
27
|
|
27
28
|
if configuration_filename.nil?
|
28
29
|
puts 'Specify a template file or use --help for usage information'
|
29
|
-
|
30
|
+
return 0
|
30
31
|
end
|
31
32
|
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
33
|
+
if File.exists? configuration_filename
|
34
|
+
swap_config configuration_filename
|
35
|
+
return 0
|
36
|
+
else
|
36
37
|
puts "Error: Configuration template file with name #{configuration_filename} does not exist"
|
37
|
-
|
38
|
-
|
38
|
+
return 1
|
39
|
+
end
|
39
40
|
end
|
40
41
|
|
41
|
-
|
42
|
+
def swap_config configuration_filename
|
42
43
|
output_filename_default = configuration_filename + '.out' if output_filename.nil?
|
43
44
|
|
44
45
|
configuration_template = Confswap::ConfigurationFileReader.read configuration_filename
|
45
46
|
env_variables = Confswap::EnvironmentVariableReader.read_variables
|
47
|
+
|
48
|
+
if (!property_file.nil?) || (File.exists? property_file)
|
49
|
+
puts 'pfile specified'
|
50
|
+
env_variables = Confswap::PropertyFileVariableReader.read_variables_from_file property_file
|
51
|
+
p env_variables
|
52
|
+
end
|
46
53
|
|
47
|
-
|
54
|
+
begin
|
48
55
|
output = configuration_template % env_variables
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
56
|
+
rescue KeyError => error
|
57
|
+
puts "#{error.message}. Your configuration specifies this variable, but it was not found as an environment variable."
|
58
|
+
exit(1)
|
59
|
+
end
|
53
60
|
|
54
61
|
write_file output, output_filename || output_filename_default
|
55
|
-
|
62
|
+
end
|
56
63
|
|
57
|
-
|
58
|
-
|
64
|
+
def write_file output_file_contents, output_filename
|
65
|
+
return File.write output_filename, output_file_contents unless File.exists? output_filename
|
59
66
|
|
60
67
|
if File.exists? output_filename and force?
|
61
68
|
puts "Overwriting #{output_filename}..."
|
62
69
|
File.write output_filename, output_file_contents
|
63
|
-
|
70
|
+
else
|
64
71
|
puts "#{output_filename} already exists, use the --force flag to overwrite"
|
65
72
|
end
|
66
|
-
|
67
|
-
|
68
|
-
option ['-f','--force'], :flag, "Overwrite file if it already exists", :attribute_name => :force
|
69
|
-
option ['-v', '--version'], :flag, "The version of confswap you are running", :attribute_name => :version
|
70
|
-
option ['-o', '--output'], "FILE", "Specifies the filepath for the file", :attribute_name => :output_filename
|
71
|
-
option ['--verbose'], :flag, "Be more verbose"
|
73
|
+
end
|
72
74
|
|
73
|
-
|
75
|
+
option ['-p', '--property-file'], "FILE PATH", 'A path to a property file to use for your template variables', :attribute_name => :property_file
|
76
|
+
option ['-e', '--envvar'], "VARIABLE", 'Specify one or more additional environment variables', :multivalued => true
|
77
|
+
option ['-f','--force'], :flag, "Overwrite file if it already exists", :attribute_name => :force
|
78
|
+
option ['-v', '--version'], :flag, "The version of confswap you are running", :attribute_name => :version
|
79
|
+
option ['-o', '--output'], "FILE PATH", "Specifies the filepath for the file", :attribute_name => :output_filename
|
80
|
+
option ['--verbose'], :flag, "Be more verbose"
|
81
|
+
parameter "[TEMPLATE_FILE]", "Path to the configuration file", :attribute_name => :configuration_filename
|
74
82
|
end
|
75
83
|
end
|
data/lib/confswap/env_reader.rb
CHANGED
@@ -0,0 +1,45 @@
|
|
1
|
+
class Confswap::PropertyFileVariableReader
|
2
|
+
def self.read_variables_from_file file_path
|
3
|
+
contents = File.read file_path
|
4
|
+
self.parse_file_contents contents
|
5
|
+
end
|
6
|
+
|
7
|
+
private
|
8
|
+
def self.parse_file_contents contents
|
9
|
+
raise InvalidPropertyFileException unless self.valid_property_file_contents? contents
|
10
|
+
raw_file_contents = contents.split(/\n/)
|
11
|
+
variables = self.ignore_blank_or_comment_lines(raw_file_contents)
|
12
|
+
variables_hash = {}
|
13
|
+
|
14
|
+
variables.each { |variable_line|
|
15
|
+
split_variable_line = variable_line.split(/:/, 2)
|
16
|
+
variable_key = split_variable_line.first.to_sym
|
17
|
+
variable_value = split_variable_line.at(1).strip
|
18
|
+
|
19
|
+
variables_hash[variable_key] = variable_value
|
20
|
+
}
|
21
|
+
|
22
|
+
variables_hash
|
23
|
+
end
|
24
|
+
|
25
|
+
def self.ignore_blank_or_comment_lines file_contents
|
26
|
+
file_contents.reject{|v| v.empty? || self.comment_line?(v) }
|
27
|
+
end
|
28
|
+
|
29
|
+
def self.comment_line? line
|
30
|
+
line.start_with? '#'
|
31
|
+
end
|
32
|
+
|
33
|
+
def self.valid_property_file_contents? property_file_contents
|
34
|
+
file_contents_not_empty = !property_file_contents.empty?
|
35
|
+
file_contents_not_empty
|
36
|
+
end
|
37
|
+
end
|
38
|
+
|
39
|
+
class Confswap::PropertyFileVariableReader::InvalidPropertyFileException < Exception
|
40
|
+
def initalize message
|
41
|
+
super message
|
42
|
+
end
|
43
|
+
end
|
44
|
+
|
45
|
+
|
data/lib/confswap/version.rb
CHANGED
data/lib/confswap.rb
CHANGED
data/spec/conf_reader_spec.rb
CHANGED
@@ -7,14 +7,14 @@ describe 'Confswap::ConfigFileReader' do
|
|
7
7
|
end
|
8
8
|
|
9
9
|
it 'should read the contents of a file specified' do
|
10
|
-
|
11
|
-
|
12
|
-
|
10
|
+
expect(Confswap::ConfigurationFileReader.read '/tmp/test.txt').to eql(sample_config)
|
11
|
+
end
|
12
|
+
|
13
13
|
it 'should return nil if the file does not exist' do
|
14
14
|
expect(Confswap::ConfigurationFileReader.read '/path/does/not/exist.txt').to be_nil
|
15
15
|
end
|
16
16
|
|
17
|
-
|
18
|
-
|
19
|
-
|
17
|
+
after(:each) do
|
18
|
+
File.delete('/tmp/test.txt') if File.exists?('/tmp/test.txt')
|
19
|
+
end
|
20
20
|
end
|
data/spec/env_reader_spec.rb
CHANGED
@@ -2,11 +2,11 @@ require 'confswap/env_reader'
|
|
2
2
|
|
3
3
|
describe 'Confswap::EnvironmentVariableReader' do
|
4
4
|
it 'should read environment variables and store them in a hash' do
|
5
|
-
|
6
|
-
|
5
|
+
env_variables = Confswap::EnvironmentVariableReader.read_variables
|
6
|
+
expect(env_variables).to be_instance_of Hash
|
7
|
+
end
|
8
|
+
it 'should store the environment variable FOO=bar in a hash' do
|
9
|
+
ENV['FOO']="bar"
|
10
|
+
expect(Confswap::EnvironmentVariableReader.read_variables).to include(:FOO => "bar")
|
7
11
|
end
|
8
|
-
it 'should store the environment variable FOO=bar in a hash' do
|
9
|
-
ENV['FOO']="bar"
|
10
|
-
expect(Confswap::EnvironmentVariableReader.read_variables).to include(:FOO => "bar")
|
11
|
-
end
|
12
12
|
end
|
@@ -0,0 +1,50 @@
|
|
1
|
+
require 'confswap/property_reader'
|
2
|
+
|
3
|
+
describe 'Confswap::PropertyFileVariableReader' do
|
4
|
+
it 'should read environment variables from a file and store them in a hash' do
|
5
|
+
read_variables = Confswap::PropertyFileVariableReader.read_variables_from_file 'tmp/test1vars'
|
6
|
+
expect(read_variables).to be_instance_of Hash
|
7
|
+
end
|
8
|
+
|
9
|
+
it 'should split only on first colon and extra newlines' do
|
10
|
+
variables = "VAR1: 192.168.0.1\n\n\nVAR2: giblets\nVAR3: this should : : have: colons"
|
11
|
+
File.write 'tmp/test2vars', variables
|
12
|
+
vars = Confswap::PropertyFileVariableReader.read_variables_from_file 'tmp/test2vars'
|
13
|
+
|
14
|
+
expect(vars.length).to equal(3)
|
15
|
+
expect(vars).to eq({
|
16
|
+
:VAR1 => '192.168.0.1',
|
17
|
+
:VAR2 => 'giblets',
|
18
|
+
:VAR3 => 'this should : : have: colons'
|
19
|
+
})
|
20
|
+
|
21
|
+
end
|
22
|
+
|
23
|
+
it 'should ignore comments in a property file' do
|
24
|
+
file_contents = "# this is a comment \nVAR1: 192.168.0.1\n\n\nVAR2: giblets\nVAR3: this should : : have: colons"
|
25
|
+
File.write 'tmp/property_file_with_comments', file_contents
|
26
|
+
vars = Confswap::PropertyFileVariableReader.read_variables_from_file 'tmp/property_file_with_comments'
|
27
|
+
expect(vars.length).to eq(3)
|
28
|
+
expect(vars).to eq({
|
29
|
+
:VAR1 => '192.168.0.1',
|
30
|
+
:VAR2 => 'giblets',
|
31
|
+
:VAR3 => 'this should : : have: colons'
|
32
|
+
})
|
33
|
+
end
|
34
|
+
|
35
|
+
it 'should warn for invalid property file when property file is empty' do
|
36
|
+
file_contents = ""
|
37
|
+
File.write 'tmp/invalid_property_file', file_contents
|
38
|
+
expect {
|
39
|
+
Confswap::PropertyFileVariableReader.read_variables_from_file 'tmp/invalid_property_file'
|
40
|
+
}.to raise_exception Confswap::PropertyFileVariableReader::InvalidPropertyFileException
|
41
|
+
end
|
42
|
+
|
43
|
+
pending 'should warn for invalid property file when property file is invalid' do
|
44
|
+
file_contents = "# this is a comment \nVAR1: "
|
45
|
+
File.write 'tmp/invalid_property_file', file_contents
|
46
|
+
expect {
|
47
|
+
Confswap::PropertyFileVariableReader.read_variables_from_file 'tmp/invalid_property_file'
|
48
|
+
}.to raise_exception Confswap::PropertyFileVariableReader::InvalidPropertyFileException
|
49
|
+
end
|
50
|
+
end
|
data/spec/spec_helper.rb
CHANGED
@@ -3,12 +3,12 @@ SimpleCov.start
|
|
3
3
|
|
4
4
|
def sample_config
|
5
5
|
[ "# This is a sample config",
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
6
|
+
"# A bunch of lines that will be in a file",
|
7
|
+
"# Because thats what its all about",
|
8
|
+
"test=%{ITEM1}",
|
9
|
+
"test2=%{ITEM2}",
|
10
|
+
"test3=%{ITEM3}"
|
11
|
+
].join("\n")
|
12
12
|
end
|
13
13
|
|
14
14
|
def sample_variables
|
metadata
CHANGED
@@ -1,29 +1,43 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: confswap
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.0.
|
4
|
+
version: 0.0.3
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Tom Cowling
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date:
|
11
|
+
date: 2015-01-01 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: clamp
|
15
15
|
requirement: !ruby/object:Gem::Requirement
|
16
16
|
requirements:
|
17
|
-
- - "
|
17
|
+
- - ">="
|
18
18
|
- !ruby/object:Gem::Version
|
19
|
-
version: 0
|
19
|
+
version: '0'
|
20
20
|
type: :runtime
|
21
21
|
prerelease: false
|
22
22
|
version_requirements: !ruby/object:Gem::Requirement
|
23
23
|
requirements:
|
24
|
-
- - "
|
24
|
+
- - ">="
|
25
25
|
- !ruby/object:Gem::Version
|
26
|
-
version: 0
|
26
|
+
version: '0'
|
27
|
+
- !ruby/object:Gem::Dependency
|
28
|
+
name: thor
|
29
|
+
requirement: !ruby/object:Gem::Requirement
|
30
|
+
requirements:
|
31
|
+
- - ">="
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: '0'
|
34
|
+
type: :runtime
|
35
|
+
prerelease: false
|
36
|
+
version_requirements: !ruby/object:Gem::Requirement
|
37
|
+
requirements:
|
38
|
+
- - ">="
|
39
|
+
- !ruby/object:Gem::Version
|
40
|
+
version: '0'
|
27
41
|
description: Create a configuration from a template using environment variables
|
28
42
|
email: tom.cowling@gmail.com
|
29
43
|
executables:
|
@@ -44,13 +58,16 @@ files:
|
|
44
58
|
- features/support/env.rb
|
45
59
|
- features/support/hooks.rb
|
46
60
|
- features/swap.feature
|
61
|
+
- features/version.feature
|
47
62
|
- lib/confswap.rb
|
48
63
|
- lib/confswap/command.rb
|
49
64
|
- lib/confswap/conf_reader.rb
|
50
65
|
- lib/confswap/env_reader.rb
|
66
|
+
- lib/confswap/property_reader.rb
|
51
67
|
- lib/confswap/version.rb
|
52
68
|
- spec/conf_reader_spec.rb
|
53
69
|
- spec/env_reader_spec.rb
|
70
|
+
- spec/property_reader_spec.rb
|
54
71
|
- spec/spec_helper.rb
|
55
72
|
homepage: https://www.tlcowling.com/gems/confswap
|
56
73
|
licenses:
|
@@ -72,7 +89,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
72
89
|
version: '0'
|
73
90
|
requirements: []
|
74
91
|
rubyforge_project:
|
75
|
-
rubygems_version: 2.
|
92
|
+
rubygems_version: 2.4.5
|
76
93
|
signing_key:
|
77
94
|
specification_version: 4
|
78
95
|
summary: Confswap swaps conf variables!
|
@@ -81,6 +98,8 @@ test_files:
|
|
81
98
|
- features/support/env.rb
|
82
99
|
- features/support/hooks.rb
|
83
100
|
- features/swap.feature
|
101
|
+
- features/version.feature
|
84
102
|
- spec/conf_reader_spec.rb
|
85
103
|
- spec/env_reader_spec.rb
|
104
|
+
- spec/property_reader_spec.rb
|
86
105
|
- spec/spec_helper.rb
|