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 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