confswap 0.0.2 → 0.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: 63dffdfc16d8f6f014cc33d485e978b8cc8e98ae
4
- data.tar.gz: a115a0ad6878127a50ddb6fe417219b8a13a78e1
3
+ metadata.gz: 215b9df2a80e58dc45557cb8359c50e87077480c
4
+ data.tar.gz: b00ef6a97570079f5dd225eba7685347cf8f62bd
5
5
  SHA512:
6
- metadata.gz: 41e987aebba28bc2d7faf14b0e3a1a3d9326389c258f6414201b057f8c831b0c9ce66034845d196935875fc81b7dadf9f993ce0f5a6bca40e3d811600686ce93
7
- data.tar.gz: 5975397d4553080610508565f53ac613e3f0f483c0bbb5ec02292b30f120a18e87f8e47a69fa5d3353bbc4b1d7a92170b4fbb6fc906277f7643e844878416fc6
6
+ metadata.gz: 16bf29af5ea5965625970900ae230813e7c7267393212343532114e5b0eb46eeb20e65b23246cf0b2c3dc13d51248b513598c869b12377d969b8d79f05dafcda
7
+ data.tar.gz: 9814d9e753eba16381f24d07ad22aeed0d1fb87c79717f4e2ab15b55d65bd238f8f7cc2e23083b2071ca8d04f5407c5085df958538e03ef1011417ba6b09beb8
data/.gitignore CHANGED
@@ -4,6 +4,9 @@
4
4
  ## My little test files
5
5
  test.conf
6
6
  test.conf.out
7
+ test.txt
8
+ test.txt.out
9
+ pfile.txt
7
10
 
8
11
  ## Ignore Vim swp
9
12
  *.swp
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
- It appears to be taking the shape of a ruby gem...
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
- Config files can use the `%{}` style to replace a token in a stirng with a variable
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
- ### Optional:
49
- Use guard to rerun tests as you go...
50
- ``guard``
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.2'
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', '~> 0.6.3'
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")
@@ -0,0 +1,7 @@
1
+ Feature: See what version of confswap you're running
2
+ Scenario: Type confswap --version
3
+ Given I run `confswap --version`
4
+ Then the output should contain:
5
+ """
6
+ 0.0.2
7
+ """
@@ -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
- def help(*args)
10
+
11
+ def help(*args)
10
12
  return [
11
13
  "This is confswap version #{Confswap::VERSION}",
12
- super
13
- ].join("\n")
14
- end
14
+ super
15
+ ].join("\n")
16
+ end
15
17
 
16
- def run(*args)
18
+ def run(*args)
17
19
  super(*args)
18
- end
20
+ end
19
21
 
20
22
  def execute
21
-
22
23
  if version?
23
- puts Confswap::VERSION
24
- return 0
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
- return 0
30
+ return 0
30
31
  end
31
32
 
32
- if File.exists? configuration_filename
33
- swap_config configuration_filename
34
- return 0
35
- else
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
- return 1
38
- end
38
+ return 1
39
+ end
39
40
  end
40
41
 
41
- def swap_config configuration_filename
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
- begin
54
+ begin
48
55
  output = configuration_template % env_variables
49
- rescue KeyError => error
50
- puts "#{error.message}. Your configuration specifies this variable, but it was not found as an environment variable."
51
- exit(1)
52
- end
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
- end
62
+ end
56
63
 
57
- def write_file output_file_contents, output_filename
58
- return File.write output_filename, output_file_contents unless File.exists? output_filename
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
- else
70
+ else
64
71
  puts "#{output_filename} already exists, use the --force flag to overwrite"
65
72
  end
66
- end
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
- parameter "[TEMPLATE_FILE]", "Path to the configuration file", :attribute_name => :configuration_filename
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
@@ -1,7 +1,7 @@
1
1
  module Confswap
2
2
  class EnvironmentVariableReader
3
- def self.read_variables
4
- Hash[ENV.map { |key, value| [key.to_sym, value] }]
5
- end
3
+ def self.read_variables
4
+ Hash[ENV.map { |key, value| [key.to_sym, value] }]
5
+ end
6
6
  end
7
7
  end
@@ -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
+
@@ -1,3 +1,3 @@
1
1
  module Confswap
2
- VERSION = "0.0.1"
2
+ VERSION = '0.0.3'
3
3
  end
data/lib/confswap.rb CHANGED
@@ -1,3 +1,4 @@
1
1
  require 'confswap/env_reader'
2
2
  require 'confswap/conf_reader'
3
+ require 'confswap/property_reader'
3
4
  require 'confswap/version'
@@ -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
- expect(Confswap::ConfigurationFileReader.read '/tmp/test.txt').to eql(sample_config)
11
- end
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
- after(:each) do
18
- File.delete('/tmp/test.txt') if File.exists?('/tmp/test.txt')
19
- end
17
+ after(:each) do
18
+ File.delete('/tmp/test.txt') if File.exists?('/tmp/test.txt')
19
+ end
20
20
  end
@@ -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
- env_variables = Confswap::EnvironmentVariableReader.read_variables
6
- expect(env_variables).to be_instance_of Hash
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
- "# 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")
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.2
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: 2014-11-16 00:00:00.000000000 Z
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.6.3
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.6.3
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.2.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