etcdist 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 ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: 31d1efd6790453a5cc15c0c2400d7e3d6c629865
4
+ data.tar.gz: ad13049f8d7a5c640a1be8e52db5888af619c870
5
+ SHA512:
6
+ metadata.gz: 7f638b9482640267f0b4f0e5172568705d7c1fea319613c981f737afc3d8c11adcf786782d1d5a2b578fde43708a78f906a6aa88455d6cbfef16e44c427e89e2
7
+ data.tar.gz: a8f872b5fd43654733b24db3b4e76e7e7e3d9f210ad21f309c6ef01b2ece0251aae412fa1d5c8e04602bb4cce461acf5605a48a76cf73a2e5192f052d9aa48bc
data/.gitignore ADDED
@@ -0,0 +1,14 @@
1
+ /.bundle/
2
+ /.yardoc
3
+ /Gemfile.lock
4
+ /_yardoc/
5
+ /coverage/
6
+ /doc/
7
+ /pkg/
8
+ /spec/reports/
9
+ /tmp/
10
+ *.bundle
11
+ *.so
12
+ *.o
13
+ *.a
14
+ mkmf.log
data/.rubocop.yml ADDED
@@ -0,0 +1,15 @@
1
+ AllCops:
2
+ Include:
3
+ - lib/**/*.rb
4
+ - spec/**/*.rb
5
+
6
+ Documentation:
7
+ Exclude:
8
+ - lib/**/version.rb
9
+ - spec/**/*
10
+
11
+ Style/EachWithObject:
12
+ Enabled: false
13
+
14
+ LineLength:
15
+ Max: 120
data/Gemfile ADDED
@@ -0,0 +1,4 @@
1
+ source 'https://rubygems.org'
2
+
3
+ # Specify your gem's dependencies in etcdist.gemspec
4
+ gemspec
data/Guardfile ADDED
@@ -0,0 +1,6 @@
1
+ # More info at https://github.com/guard/guard#readme
2
+ guard :rspec, cmd: 'bundle exec rspec' do
3
+ watch(%r{^spec/.+_spec\.rb$})
4
+ watch(%r{^lib/(.+)\.rb$}) { |m| "spec/#{m[1]}_spec.rb" }
5
+ watch('spec/spec_helper.rb') { 'spec' }
6
+ end
data/LICENSE.txt ADDED
@@ -0,0 +1,22 @@
1
+ Copyright (c) 2014 Springer, Part of Springer Science+Business Media
2
+
3
+ MIT License
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining
6
+ a copy of this software and associated documentation files (the
7
+ "Software"), to deal in the Software without restriction, including
8
+ without limitation the rights to use, copy, modify, merge, publish,
9
+ distribute, sublicense, and/or sell copies of the Software, and to
10
+ permit persons to whom the Software is furnished to do so, subject to
11
+ the following conditions:
12
+
13
+ The above copyright notice and this permission notice shall be
14
+ included in all copies or substantial portions of the Software.
15
+
16
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
17
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
19
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
20
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
21
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
22
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,109 @@
1
+ # Etcdist
2
+
3
+ This is a small gem that helps you manage your etcd keys and values in a way that's easy to version control.
4
+
5
+ ## Installation
6
+
7
+ Add this line to your application's Gemfile:
8
+
9
+ ```ruby
10
+ gem 'etcdist'
11
+ ```
12
+
13
+ And then execute:
14
+
15
+ $ bundle
16
+
17
+ Or install it yourself as:
18
+
19
+ $ gem install etcdist
20
+
21
+ ## Usage
22
+
23
+ ### Create the data
24
+
25
+ Create your desired directory structure. This will be replicated in etcd. For example:
26
+
27
+ ```bash
28
+ mkdir -p data/foo/bar
29
+ ```
30
+
31
+ Then create a file in the leaf directory containing the keys and values that you want to go into etcd. For example:
32
+
33
+ ```bash
34
+ cat <<EOT > data/foo/bar/food.data
35
+ fish=plankton
36
+ cows=grass
37
+ EOT
38
+ ```
39
+
40
+ The name of the file containing the keys and values doesn't matter. In fact, you can split the data into multiple files, if you want. An example would look like:
41
+
42
+ ```text
43
+ ./data
44
+ └── ./foo
45
+ └── ./bar
46
+    ├── food.data # contains fish=plankton and cows=grass
47
+    └── more.data # could contain more keys and values
48
+ ```
49
+
50
+ ### Populate etcd
51
+
52
+ Then pass the path to your data directory to Etcdist. For example:
53
+
54
+ ```ruby
55
+ #!/usr/bin/env ruby
56
+ require 'etcdist'
57
+ Etcdist.execute('data')
58
+ ```
59
+
60
+ If you want Etcdist to remove data from etcd that is no longer in your data files, use `dangerous` mode:
61
+
62
+ ```ruby
63
+ Etcdist.execute('data', dangerous: true)
64
+ ```
65
+
66
+ If you just want to perform a trial run without making any changes, then use the `dry_run` mode:
67
+
68
+ ```ruby
69
+ Etcdist.execute('data', dangerous: true, dry_run: true)
70
+ ```
71
+
72
+ ## Configuration
73
+
74
+ ### Etcd host
75
+
76
+ ```ruby
77
+ Etcdist.execute(dir) # defaults to localhost:4001
78
+ Etcdist.execute(dir, host: '127.0.0.1', port: 4003)
79
+ ```
80
+
81
+ ### Log level
82
+
83
+ You can control the log level, as follows:
84
+
85
+ ```ruby
86
+ Etcdist::Log.level = :info
87
+ ```
88
+
89
+ ## Developing
90
+
91
+ Clone the source code. To see what's possible, run:
92
+
93
+ $ rake -T
94
+
95
+ To get the acceptance test to pass, make sure you've got etcd running locally:
96
+
97
+ $ docker run -d -p 4001:4001 coreos/etcd
98
+
99
+ To continuously run tests, run:
100
+
101
+ $ guard
102
+
103
+ ## Contributing
104
+
105
+ 1. Fork it
106
+ 2. Create your feature branch (`git checkout -b my-new-feature`)
107
+ 3. Commit your changes (`git commit -am 'Add some feature'`)
108
+ 4. Push to the branch (`git push origin my-new-feature`)
109
+ 5. Create a new Pull Request
data/Rakefile ADDED
@@ -0,0 +1,23 @@
1
+ require 'bundler/gem_tasks'
2
+ require 'rdoc/task'
3
+ require 'rubocop/rake_task'
4
+ require 'rspec/core/rake_task'
5
+
6
+ RSpec::Core::RakeTask.new('spec')
7
+
8
+ task default: :test
9
+
10
+ RuboCop::RakeTask.new do |task|
11
+ task.fail_on_error = true
12
+ end
13
+
14
+ RDoc::Task.new do |rdoc|
15
+ rdoc.main = 'README.rdoc'
16
+ rdoc.rdoc_files.include('lib /*.rb')
17
+ end
18
+
19
+ desc 'Run specs and code checks.'
20
+ task :test do
21
+ Rake::Task['spec'].invoke
22
+ Rake::Task['rubocop'].invoke
23
+ end
data/TODO ADDED
@@ -0,0 +1,9 @@
1
+ # TODO
2
+ * think about / improve error handling (for example: write operation is not atomic)
3
+ * gemspec: specify required ruby version
4
+
5
+ ## Lower priority
6
+ * feature: **optionally** remove directories from etcd if no longer present
7
+ * feature: do not process directories that don't have any modified files
8
+ * feature: provide etcdist as a binary so that it can be executed from the command line.
9
+
data/etcdist.gemspec ADDED
@@ -0,0 +1,29 @@
1
+ # coding: utf-8
2
+ lib = File.expand_path('../lib', __FILE__)
3
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
+ require 'etcdist/version'
5
+
6
+ Gem::Specification.new do |spec|
7
+ spec.name = 'etcdist'
8
+ spec.version = Etcdist::VERSION
9
+ spec.authors = ['Springer, Part of Springer Science+Business Media']
10
+ spec.summary = 'Populate etcd in a reproducable way. '
11
+ spec.homepage = 'https://github.com/springersbm/etcdist'
12
+ spec.license = 'MIT'
13
+
14
+ spec.files = `git ls-files -z`.split("\x0")
15
+ spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
16
+ spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
17
+ spec.require_paths = ['lib']
18
+ spec.required_ruby_version = '>= 2.0'
19
+
20
+ spec.add_runtime_dependency 'etcd', '~> 0.2.4'
21
+ spec.add_runtime_dependency 'mixlib-log'
22
+
23
+ spec.add_development_dependency 'bundler', '~> 1.7'
24
+ spec.add_development_dependency 'rake', '~> 10.0'
25
+ spec.add_development_dependency 'rspec', '~> 3.0'
26
+ spec.add_development_dependency 'rspec-mocks', '~> 3.0'
27
+ spec.add_development_dependency 'guard-rspec'
28
+ spec.add_development_dependency 'rubocop'
29
+ end
@@ -0,0 +1,8 @@
1
+ require 'mixlib/log'
2
+
3
+ module Etcdist
4
+ # A wrapper class that extends Mixlib::Log
5
+ class Log
6
+ extend Mixlib::Log
7
+ end
8
+ end
@@ -0,0 +1,26 @@
1
+ require 'etcdist/log'
2
+
3
+ module Etcdist
4
+ # Reads data from file system into directories, keys and values.
5
+ class Reader
6
+ # @param [String] dir The path to the data directory
7
+ def initialize(dir)
8
+ @dir = dir
9
+ end
10
+
11
+ # Returns a hash of type { directory => { key => val } }
12
+ def read
13
+ @dir = File.expand_path(@dir)
14
+ files = Dir[File.join(@dir, '**', '*')].reject { |p| File.directory? p }
15
+ Log.info("found #{files.length} files in #{@dir}")
16
+
17
+ files.reduce(Hash.new { |h, k| h[k] = {} }) do |h, f|
18
+ directory = File.dirname(f).gsub(@dir, '')
19
+ entries = Hash[IO.readlines(f).map { |e| e.chomp.split('=') }]
20
+ Log.debug("found #{entries.length} entries in #{f.gsub(@dir, '')}: #{entries}")
21
+ h[directory].merge!(entries)
22
+ h
23
+ end
24
+ end
25
+ end
26
+ end
@@ -0,0 +1,3 @@
1
+ module Etcdist
2
+ VERSION = '0.0.3'
3
+ end
@@ -0,0 +1,47 @@
1
+ require 'etcdist/log'
2
+
3
+ module Etcdist
4
+ # Writes data into etcd.
5
+ class Writer
6
+ # @param [Hash] opts Options
7
+ # @opts [String] :dangerous remove data from etcd (default false)
8
+ # @opts [String] :dry_run perform a trial run with no changes made (default false)
9
+ def initialize(etcd, opts = {})
10
+ @etcd = etcd
11
+ @dangerous = opts[:dangerous] || false
12
+ @dry_run = opts[:dry_run] || false
13
+ end
14
+
15
+ # Writes data into etcd and optionally removes extra data from etcd
16
+ # @param [Hash] data of type { directory => { key => val } }
17
+ def write(data)
18
+ count = { put: 0, del: 0 }
19
+ data.each do |dir, entries|
20
+ count[:put] += put(dir, entries)
21
+ count[:del] += delete(dir, entries) if @dangerous
22
+ end
23
+ Log.info("#{count[:put]} entries added/modified. #{count[:del]} entries deleted.")
24
+ end
25
+
26
+ private
27
+
28
+ def put(dir, entries)
29
+ existing = entries_in(dir)
30
+ to_put = entries.select { |k, v| existing[k] != v }
31
+ to_put.each { |k, v| @etcd.set([dir, '/', k].join, value: v) } unless @dry_run
32
+ Log.debug("wrote #{to_put.length} entries to #{dir}: #{to_put}")
33
+ to_put.length
34
+ end
35
+
36
+ def delete(dir, entries)
37
+ to_delete = entries_in(dir).keys - entries.keys
38
+ to_delete.each { |k| @etcd.delete([dir, '/', k].join) } unless @dry_run
39
+ Log.debug("deleted #{to_delete.length} entries from #{dir}: #{to_delete}")
40
+ to_delete.length
41
+ end
42
+
43
+ def entries_in(dir)
44
+ @etcd.exists?(dir) ? Hash[@etcd.get(dir).children.map { |n| [n.key.sub(/.*\//, ''), n.value] }] : {}
45
+ end
46
+ end
47
+ end
data/lib/etcdist.rb ADDED
@@ -0,0 +1,25 @@
1
+ require 'etcd'
2
+ require 'etcdist/log'
3
+ require 'etcdist/reader'
4
+ require 'etcdist/writer'
5
+
6
+ # The Etcdist name space
7
+ module Etcdist
8
+ Log.level = :info
9
+
10
+ # Main entry point to read data from F/S and write into etcd.
11
+ #
12
+ # @param [String] dir The path to the data directory
13
+ # @param [Hash] opts Options
14
+ # @opts [String] :host IP address of the etcd server (default 127.0.0.1)
15
+ # @opts [Fixnum] :port Port number of the etcd server (default 4001)
16
+ def self.execute(dir, opts = {})
17
+ etcd = Etcd::Client.new(opts)
18
+ reader = Etcdist::Reader.new(dir)
19
+ writer = Etcdist::Writer.new(etcd, opts)
20
+
21
+ Log.info("using etcd host at: #{etcd.host}:#{etcd.port}")
22
+ writer.write(reader.read)
23
+ Log.info('finished successfully.')
24
+ end
25
+ end
@@ -0,0 +1,2 @@
1
+ fish=plankton
2
+ cows=grass
@@ -0,0 +1 @@
1
+ dogs=bones
@@ -0,0 +1,14 @@
1
+ require 'spec_helper'
2
+
3
+ describe Etcdist::Reader do
4
+
5
+ let(:reader) do
6
+ dir = File.join(File.dirname(__FILE__), '../data')
7
+ Etcdist::Reader.new(dir)
8
+ end
9
+
10
+ it 'should return directories pointing to key/values' do
11
+ expect(reader.read).to match('/etcdist/foo' => { 'fish' => 'plankton', 'cows' => 'grass', 'dogs' => 'bones' })
12
+ end
13
+
14
+ end
@@ -0,0 +1,84 @@
1
+ require 'spec_helper'
2
+
3
+ describe Etcdist::Writer do
4
+
5
+ let(:etcd) do
6
+ double('etcd').as_null_object
7
+ end
8
+
9
+ let(:writer) do
10
+ Etcdist::Writer.new(etcd)
11
+ end
12
+
13
+ describe 'PUTs' do
14
+
15
+ it 'should put entries in etcd' do
16
+ pretend_etcd_contains(nothing)
17
+ expect(etcd).to receive(:set).with('/foo/bar/fish', value: 'plankton')
18
+ writer.write('/foo/bar' => { 'fish' => 'plankton' })
19
+ end
20
+
21
+ it 'should put entries in correct directory' do
22
+ pretend_etcd_contains(nothing)
23
+ expect(etcd).to receive(:set).with('/water/fish', value: 'plankton')
24
+ expect(etcd).to receive(:set).with('/land/cows', value: 'grass')
25
+ writer.write('/water' => { 'fish' => 'plankton' }, '/land' => { 'cows' => 'grass' })
26
+ end
27
+
28
+ it 'should not put unchanged entries' do
29
+ pretend_etcd_contains('/foo' => { 'fish' => 'plankton', 'cows' => 'grass' })
30
+ expect(etcd).not_to receive(:set)
31
+ writer.write('/foo' => { 'fish' => 'plankton' })
32
+ end
33
+
34
+ context 'dry run mode' do
35
+ let(:writer) do
36
+ Etcdist::Writer.new(etcd, dry_run: true)
37
+ end
38
+
39
+ it 'should not put entries in etcd' do
40
+ pretend_etcd_contains(nothing)
41
+ expect(etcd).not_to receive(:set)
42
+ writer.write( '/foo/bar' => { 'fish' => 'plankton' } )
43
+ end
44
+ end
45
+ end
46
+
47
+ describe 'DELETEs' do
48
+
49
+ it 'should not delete extra entries by default' do
50
+ pretend_etcd_contains('/foo' => { 'fish' => 'plankton' })
51
+ expect(etcd).not_to receive(:delete)
52
+ writer.write('/foo' => {})
53
+ end
54
+
55
+ context 'dangerous mode' do
56
+
57
+ let(:writer) do
58
+ Etcdist::Writer.new(etcd, dangerous: true)
59
+ end
60
+
61
+ it 'should delete extra entries' do
62
+ pretend_etcd_contains('/foo' => { 'fish' => 'plankton' })
63
+ expect(etcd).to receive(:delete).with('/foo/fish')
64
+ writer.write('/foo' => { 'cows' => 'grass' })
65
+ end
66
+
67
+ end
68
+
69
+ context 'dry run mode' do
70
+ let(:writer) do
71
+ Etcdist::Writer.new(etcd, dangerous: true, dry_run: true)
72
+ end
73
+
74
+ it 'should not delete entries' do
75
+ pretend_etcd_contains('/foo' => { 'fish' => 'plankton' })
76
+ expect(etcd).not_to receive(:delete)
77
+ writer.write( '/foo' => { 'cows' => 'grass'} )
78
+ end
79
+
80
+ end
81
+
82
+ end
83
+
84
+ end
@@ -0,0 +1,26 @@
1
+ require 'spec_helper'
2
+
3
+ describe Etcdist do
4
+
5
+ describe 'acceptance test - expects etcd running on localhost:4001' do
6
+
7
+ let(:etcd_opts) do
8
+ { host: 'localhost', port: 4001 }
9
+ end
10
+
11
+ let(:etcd) do
12
+ Etcd.client(etcd_opts)
13
+ end
14
+
15
+ let(:dir) do
16
+ File.join(File.dirname(__FILE__), 'data')
17
+ end
18
+
19
+ it 'should read data and put entries to etcd' do
20
+ Etcdist.execute(dir, etcd_opts)
21
+ expect(etcd.get('/etcdist/foo/fish').value).to eq('plankton')
22
+ end
23
+
24
+ end
25
+
26
+ end
@@ -0,0 +1,32 @@
1
+ $LOAD_PATH.unshift(File.expand_path('../lib', __FILE__))
2
+ $LOAD_PATH.unshift(File.expand_path('../spec', __FILE__))
3
+
4
+ require 'etcdist'
5
+ require 'etcdist/log'
6
+
7
+ Etcdist::Log.level = :warn
8
+
9
+ module Etcdist
10
+ module SpecHelper
11
+ def nothing
12
+ {}
13
+ end
14
+
15
+ def pretend_etcd_contains(data = nothing)
16
+ allow(etcd).to receive(:exists?).with(any_args).and_return(!data.empty?)
17
+ data.each do |dir, entries|
18
+ nodes = entries.map { |k, v| { 'key' => k, 'value' => v } }
19
+ opts = { 'node' => { 'dir' => true, 'nodes' => nodes } }
20
+ allow(etcd).to receive(:get).with(dir).and_return(Etcd::Response.new(opts))
21
+ end
22
+ end
23
+ end
24
+ end
25
+
26
+ RSpec.configure do |config|
27
+ config.include Etcdist::SpecHelper
28
+ config.color = true
29
+ config.expect_with :rspec do |c|
30
+ c.syntax = :expect
31
+ end
32
+ end
metadata ADDED
@@ -0,0 +1,181 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: etcdist
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.3
5
+ platform: ruby
6
+ authors:
7
+ - Springer, Part of Springer Science+Business Media
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2014-09-03 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: etcd
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - ~>
18
+ - !ruby/object:Gem::Version
19
+ version: 0.2.4
20
+ type: :runtime
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - ~>
25
+ - !ruby/object:Gem::Version
26
+ version: 0.2.4
27
+ - !ruby/object:Gem::Dependency
28
+ name: mixlib-log
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'
41
+ - !ruby/object:Gem::Dependency
42
+ name: bundler
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - ~>
46
+ - !ruby/object:Gem::Version
47
+ version: '1.7'
48
+ type: :development
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - ~>
53
+ - !ruby/object:Gem::Version
54
+ version: '1.7'
55
+ - !ruby/object:Gem::Dependency
56
+ name: rake
57
+ requirement: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - ~>
60
+ - !ruby/object:Gem::Version
61
+ version: '10.0'
62
+ type: :development
63
+ prerelease: false
64
+ version_requirements: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - ~>
67
+ - !ruby/object:Gem::Version
68
+ version: '10.0'
69
+ - !ruby/object:Gem::Dependency
70
+ name: rspec
71
+ requirement: !ruby/object:Gem::Requirement
72
+ requirements:
73
+ - - ~>
74
+ - !ruby/object:Gem::Version
75
+ version: '3.0'
76
+ type: :development
77
+ prerelease: false
78
+ version_requirements: !ruby/object:Gem::Requirement
79
+ requirements:
80
+ - - ~>
81
+ - !ruby/object:Gem::Version
82
+ version: '3.0'
83
+ - !ruby/object:Gem::Dependency
84
+ name: rspec-mocks
85
+ requirement: !ruby/object:Gem::Requirement
86
+ requirements:
87
+ - - ~>
88
+ - !ruby/object:Gem::Version
89
+ version: '3.0'
90
+ type: :development
91
+ prerelease: false
92
+ version_requirements: !ruby/object:Gem::Requirement
93
+ requirements:
94
+ - - ~>
95
+ - !ruby/object:Gem::Version
96
+ version: '3.0'
97
+ - !ruby/object:Gem::Dependency
98
+ name: guard-rspec
99
+ requirement: !ruby/object:Gem::Requirement
100
+ requirements:
101
+ - - '>='
102
+ - !ruby/object:Gem::Version
103
+ version: '0'
104
+ type: :development
105
+ prerelease: false
106
+ version_requirements: !ruby/object:Gem::Requirement
107
+ requirements:
108
+ - - '>='
109
+ - !ruby/object:Gem::Version
110
+ version: '0'
111
+ - !ruby/object:Gem::Dependency
112
+ name: rubocop
113
+ requirement: !ruby/object:Gem::Requirement
114
+ requirements:
115
+ - - '>='
116
+ - !ruby/object:Gem::Version
117
+ version: '0'
118
+ type: :development
119
+ prerelease: false
120
+ version_requirements: !ruby/object:Gem::Requirement
121
+ requirements:
122
+ - - '>='
123
+ - !ruby/object:Gem::Version
124
+ version: '0'
125
+ description:
126
+ email:
127
+ executables: []
128
+ extensions: []
129
+ extra_rdoc_files: []
130
+ files:
131
+ - .gitignore
132
+ - .rubocop.yml
133
+ - Gemfile
134
+ - Guardfile
135
+ - LICENSE.txt
136
+ - README.md
137
+ - Rakefile
138
+ - TODO
139
+ - etcdist.gemspec
140
+ - lib/etcdist.rb
141
+ - lib/etcdist/log.rb
142
+ - lib/etcdist/reader.rb
143
+ - lib/etcdist/version.rb
144
+ - lib/etcdist/writer.rb
145
+ - spec/data/etcdist/foo/one.config
146
+ - spec/data/etcdist/foo/two.config
147
+ - spec/etcdist/reader_spec.rb
148
+ - spec/etcdist/writer_spec.rb
149
+ - spec/etcdist_spec.rb
150
+ - spec/spec_helper.rb
151
+ homepage: https://github.com/springersbm/etcdist
152
+ licenses:
153
+ - MIT
154
+ metadata: {}
155
+ post_install_message:
156
+ rdoc_options: []
157
+ require_paths:
158
+ - lib
159
+ required_ruby_version: !ruby/object:Gem::Requirement
160
+ requirements:
161
+ - - '>='
162
+ - !ruby/object:Gem::Version
163
+ version: '2.0'
164
+ required_rubygems_version: !ruby/object:Gem::Requirement
165
+ requirements:
166
+ - - '>='
167
+ - !ruby/object:Gem::Version
168
+ version: '0'
169
+ requirements: []
170
+ rubyforge_project:
171
+ rubygems_version: 2.0.3
172
+ signing_key:
173
+ specification_version: 4
174
+ summary: Populate etcd in a reproducable way.
175
+ test_files:
176
+ - spec/data/etcdist/foo/one.config
177
+ - spec/data/etcdist/foo/two.config
178
+ - spec/etcdist/reader_spec.rb
179
+ - spec/etcdist/writer_spec.rb
180
+ - spec/etcdist_spec.rb
181
+ - spec/spec_helper.rb