config_curator 0.0.0 → 0.0.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.travis.yml +2 -1
- data/CHANGELOG.md +2 -2
- data/Guardfile +10 -0
- data/README.md +1 -1
- data/Rakefile +2 -0
- data/bin/curate +5 -0
- data/config_curator.gemspec +3 -0
- data/lib/config_curator.rb +8 -0
- data/lib/config_curator/cli.rb +71 -0
- data/lib/config_curator/collection.rb +137 -0
- data/lib/config_curator/package_lookup.rb +77 -0
- data/lib/config_curator/unit.rb +122 -0
- data/lib/config_curator/units/component.rb +76 -0
- data/lib/config_curator/units/config_file.rb +76 -0
- data/lib/config_curator/units/symlink.rb +31 -0
- data/lib/config_curator/version.rb +2 -1
- data/spec/cli_spec.rb +69 -0
- data/spec/collection_spec.rb +280 -0
- data/spec/package_lookup_spec.rb +59 -0
- data/spec/spec_helper.rb +13 -0
- data/spec/unit_spec.rb +190 -0
- data/spec/units/component_spec.rb +59 -0
- data/spec/units/config_file_spec.rb +84 -0
- data/spec/units/symlink_spec.rb +46 -0
- metadata +55 -3
@@ -0,0 +1,59 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe ConfigCurator::PackageLookup do
|
4
|
+
|
5
|
+
subject(:lookup) { ConfigCurator::PackageLookup.new }
|
6
|
+
|
7
|
+
describe ".new" do
|
8
|
+
|
9
|
+
it "sets the package tool" do
|
10
|
+
lookup = ConfigCurator::PackageLookup.new tool: :dpkg
|
11
|
+
expect(lookup.tool).to eq :dpkg
|
12
|
+
end
|
13
|
+
end
|
14
|
+
|
15
|
+
describe "#tools" do
|
16
|
+
|
17
|
+
it "uses the default list of tools" do
|
18
|
+
expect(lookup.tools).to eq ConfigCurator::PackageLookup::TOOLS
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
22
|
+
describe "#tool" do
|
23
|
+
|
24
|
+
context "when tool is set" do
|
25
|
+
|
26
|
+
it "returns the tool" do
|
27
|
+
lookup.tool = :pacman
|
28
|
+
expect(lookup.tool).to eq :pacman
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
32
|
+
context "when tool not set" do
|
33
|
+
|
34
|
+
it "returns the first avaible tool" do
|
35
|
+
allow(lookup).to receive(:command?).with(:dpkg).and_return(true)
|
36
|
+
lookup.tools = %i(dpkg pacman)
|
37
|
+
expect(lookup.tool).to eq :dpkg
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|
41
|
+
|
42
|
+
describe "#installed?" do
|
43
|
+
|
44
|
+
it "calls the corresponding private lookup method" do
|
45
|
+
lookup.tool = :dpkg
|
46
|
+
expect(lookup).to receive(:dpkg).with('rsync')
|
47
|
+
lookup.installed? 'rsync'
|
48
|
+
end
|
49
|
+
|
50
|
+
context "when no package tool found" do
|
51
|
+
|
52
|
+
it "fails" do
|
53
|
+
lookup.tools = %i(dpkg)
|
54
|
+
allow(lookup).to receive(:command?).with(:dpkg).and_return(false)
|
55
|
+
expect { lookup.installed? 'rsync' }.to raise_error ConfigCurator::PackageLookup::LookupFailed
|
56
|
+
end
|
57
|
+
end
|
58
|
+
end
|
59
|
+
end
|
data/spec/spec_helper.rb
CHANGED
@@ -12,4 +12,17 @@ SimpleCov.start
|
|
12
12
|
|
13
13
|
RSpec.configure do |c|
|
14
14
|
c.expect_with(:rspec) { |e| e.syntax = :expect }
|
15
|
+
|
16
|
+
stderr = $stderr
|
17
|
+
stdout = $stdout
|
18
|
+
c.before(:all) do
|
19
|
+
$stderr = File.open File::NULL, 'w'
|
20
|
+
$stdout = File.open File::NULL, 'w'
|
21
|
+
end
|
22
|
+
c.after(:all) do
|
23
|
+
$stderr = stderr
|
24
|
+
$stdout = stdout
|
25
|
+
end
|
26
|
+
|
27
|
+
c.before(:each) { allow(FileUtils).to receive(:remove_entry_secure).with(anything) }
|
15
28
|
end
|
data/spec/unit_spec.rb
ADDED
@@ -0,0 +1,190 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe ConfigCurator::Unit do
|
4
|
+
|
5
|
+
subject(:unit) { ConfigCurator::Unit.new }
|
6
|
+
|
7
|
+
describe ".new" do
|
8
|
+
|
9
|
+
it "sets the logger" do
|
10
|
+
logger = Logger.new(STDOUT)
|
11
|
+
unit = ConfigCurator::Unit.new logger: logger
|
12
|
+
expect(unit.logger).to be logger
|
13
|
+
end
|
14
|
+
|
15
|
+
it "sets default options" do
|
16
|
+
expect(unit.options).to eq ConfigCurator::Unit::DEFAULT_OPTIONS
|
17
|
+
end
|
18
|
+
|
19
|
+
it "merges default options" do
|
20
|
+
unit = ConfigCurator::Unit.new options: {root: '/home/user'}
|
21
|
+
expect(unit.options).to eq ConfigCurator::Unit::DEFAULT_OPTIONS.merge(root: '/home/user')
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
25
|
+
describe "#logger" do
|
26
|
+
|
27
|
+
it "makes a new logger" do
|
28
|
+
expect(unit.logger).to be_a Logger
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
32
|
+
describe "#options" do
|
33
|
+
|
34
|
+
it "merges with default options" do
|
35
|
+
unit.options[:root] = '/home/user'
|
36
|
+
expect(unit.options).to eq ConfigCurator::Unit::DEFAULT_OPTIONS.merge(root: '/home/user')
|
37
|
+
end
|
38
|
+
|
39
|
+
it "can be called twice and merge options" do
|
40
|
+
unit.options[:root] = '/home/user'
|
41
|
+
unit.options[:perm] = 0600
|
42
|
+
expect(unit.options).to eq ConfigCurator::Unit::DEFAULT_OPTIONS.merge(root: '/home/user', perm: 0600)
|
43
|
+
end
|
44
|
+
end
|
45
|
+
|
46
|
+
describe "#source_path" do
|
47
|
+
|
48
|
+
it "expands the path" do
|
49
|
+
unit.source = 'path/../src_name'
|
50
|
+
expect(unit.source_path).to eq File.expand_path('path/../src_name')
|
51
|
+
end
|
52
|
+
|
53
|
+
context "when no source given" do
|
54
|
+
|
55
|
+
it "returns nil" do
|
56
|
+
expect(unit.source_path).to eq nil
|
57
|
+
end
|
58
|
+
end
|
59
|
+
end
|
60
|
+
|
61
|
+
describe "#destination_path" do
|
62
|
+
|
63
|
+
it "expands the path" do
|
64
|
+
unit.destination = 'path/../dest_name'
|
65
|
+
unit.options[:root] = '/tmp'
|
66
|
+
expect(unit.destination_path).to eq '/tmp/dest_name'
|
67
|
+
end
|
68
|
+
|
69
|
+
context "when no destination given" do
|
70
|
+
|
71
|
+
it "returns nil" do
|
72
|
+
expect(unit.destination_path).to eq nil
|
73
|
+
end
|
74
|
+
end
|
75
|
+
end
|
76
|
+
|
77
|
+
describe "#hosts" do
|
78
|
+
|
79
|
+
it "is empty by default" do
|
80
|
+
expect(unit.hosts).to be_a Array
|
81
|
+
expect(unit.hosts).to be_empty
|
82
|
+
end
|
83
|
+
end
|
84
|
+
|
85
|
+
describe "#packages" do
|
86
|
+
|
87
|
+
it "is empty by default" do
|
88
|
+
expect(unit.packages).to be_a Array
|
89
|
+
expect(unit.packages).to be_empty
|
90
|
+
end
|
91
|
+
end
|
92
|
+
|
93
|
+
describe "#package_lookup" do
|
94
|
+
|
95
|
+
it "returns a PackageLookup object" do
|
96
|
+
expect(unit.package_lookup).to be_a ConfigCurator::PackageLookup
|
97
|
+
end
|
98
|
+
|
99
|
+
it "sets the correct package tool" do
|
100
|
+
unit.options[:package_tool] = :pkg_tool
|
101
|
+
expect(unit.package_lookup.tool).to eq :pkg_tool
|
102
|
+
end
|
103
|
+
end
|
104
|
+
|
105
|
+
describe "#install" do
|
106
|
+
|
107
|
+
context "when unit should be installed" do
|
108
|
+
|
109
|
+
it "returns true" do
|
110
|
+
expect(unit).to receive(:install?).and_return(true)
|
111
|
+
expect(unit.install).to be true
|
112
|
+
end
|
113
|
+
end
|
114
|
+
|
115
|
+
context "when unit should not be installed" do
|
116
|
+
|
117
|
+
it "returns false" do
|
118
|
+
expect(unit).to receive(:install?).and_return(false)
|
119
|
+
expect(unit.install).to be false
|
120
|
+
end
|
121
|
+
end
|
122
|
+
end
|
123
|
+
|
124
|
+
describe "#install?" do
|
125
|
+
|
126
|
+
it "checks if host is allowed" do
|
127
|
+
expect(unit).to receive(:allowed_host?)
|
128
|
+
unit.install?
|
129
|
+
end
|
130
|
+
|
131
|
+
it "checks if package requirements are met" do
|
132
|
+
expect(unit).to receive(:packages_installed?)
|
133
|
+
unit.install?
|
134
|
+
end
|
135
|
+
end
|
136
|
+
|
137
|
+
describe "#allowed_host?" do
|
138
|
+
|
139
|
+
context "when hosts are given" do
|
140
|
+
|
141
|
+
it "allows host if host is listed" do
|
142
|
+
allow(unit).to receive(:hostname).and_return('test_hostname')
|
143
|
+
unit.hosts = %w(some_host test_hostname)
|
144
|
+
expect(unit.allowed_host?).to eq true
|
145
|
+
end
|
146
|
+
|
147
|
+
it "does not allow unlisted host" do
|
148
|
+
allow(unit).to receive(:hostname).and_return('bad_test_hostname')
|
149
|
+
unit.hosts = %w(some_host test_hostname)
|
150
|
+
expect(unit.allowed_host?).to eq false
|
151
|
+
end
|
152
|
+
end
|
153
|
+
|
154
|
+
context "when no hosts are given" do
|
155
|
+
|
156
|
+
it "allows any host" do
|
157
|
+
unit.hosts = []
|
158
|
+
expect(unit.allowed_host?).to eq true
|
159
|
+
end
|
160
|
+
end
|
161
|
+
end
|
162
|
+
|
163
|
+
describe "#packages_installed?" do
|
164
|
+
|
165
|
+
context "when packages listed" do
|
166
|
+
|
167
|
+
it "meets package requirements if no missing packages" do
|
168
|
+
allow(unit).to receive(:pkg_exists?).with('good_pkg_1').and_return(true)
|
169
|
+
allow(unit).to receive(:pkg_exists?).with('good_pkg_2').and_return(true)
|
170
|
+
unit.packages = %w(good_pkg_1 good_pkg_2)
|
171
|
+
expect(unit.packages_installed?).to eq true
|
172
|
+
end
|
173
|
+
|
174
|
+
it "does not meet package requirements if missing packages" do
|
175
|
+
allow(unit).to receive(:pkg_exists?).with('good_pkg').and_return(true)
|
176
|
+
allow(unit).to receive(:pkg_exists?).with('bad_pkg').and_return(false)
|
177
|
+
unit.packages = %w(good_pkg bad_pkg)
|
178
|
+
expect(unit.packages_installed?).to eq false
|
179
|
+
end
|
180
|
+
end
|
181
|
+
|
182
|
+
context "when no packages listed" do
|
183
|
+
|
184
|
+
it "meets package requirements" do
|
185
|
+
unit.packages = []
|
186
|
+
expect(unit.packages_installed?).to eq true
|
187
|
+
end
|
188
|
+
end
|
189
|
+
end
|
190
|
+
end
|
@@ -0,0 +1,59 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe ConfigCurator::Component do
|
4
|
+
|
5
|
+
subject(:component) { ConfigCurator::Component.new }
|
6
|
+
|
7
|
+
describe "#install" do
|
8
|
+
|
9
|
+
context "when component should be installed" do
|
10
|
+
|
11
|
+
it "installs the component and returns true" do
|
12
|
+
expect(component).to receive(:install?).and_return(true)
|
13
|
+
expect(component).to receive(:install_component)
|
14
|
+
expect(component).to receive(:set_mode)
|
15
|
+
expect(component).to receive(:set_owner)
|
16
|
+
expect(component.install).to be true
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
20
|
+
context "when component should not be installed" do
|
21
|
+
|
22
|
+
it "does not install the component and returns false" do
|
23
|
+
expect(component).to receive(:install?).and_return(false)
|
24
|
+
expect(component).to_not receive(:install_component)
|
25
|
+
expect(component).to_not receive(:set_mode)
|
26
|
+
expect(component).to_not receive(:set_owner)
|
27
|
+
expect(component.install).to be false
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
32
|
+
describe "#install?" do
|
33
|
+
|
34
|
+
context "when source not given" do
|
35
|
+
|
36
|
+
it "fails" do
|
37
|
+
component.destination = 'inst_path'
|
38
|
+
expect { component.install? }.to raise_error ConfigCurator::Symlink::InstallFailed
|
39
|
+
end
|
40
|
+
end
|
41
|
+
|
42
|
+
context "when destination not given" do
|
43
|
+
|
44
|
+
it "fails" do
|
45
|
+
component.source = 'dir'
|
46
|
+
expect { component.install? }.to raise_error ConfigCurator::Symlink::InstallFailed
|
47
|
+
end
|
48
|
+
end
|
49
|
+
|
50
|
+
context "when source does not exist" do
|
51
|
+
|
52
|
+
it "fails" do
|
53
|
+
component.destination = 'inst_path'
|
54
|
+
component.source = 'dir/that/does/not/exist'
|
55
|
+
expect { component.install? }.to raise_error ConfigCurator::Symlink::InstallFailed
|
56
|
+
end
|
57
|
+
end
|
58
|
+
end
|
59
|
+
end
|
@@ -0,0 +1,84 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe ConfigCurator::ConfigFile do
|
4
|
+
|
5
|
+
subject(:config_file) { ConfigCurator::ConfigFile.new }
|
6
|
+
|
7
|
+
describe "#destination" do
|
8
|
+
|
9
|
+
it "uses the source path to set the destination" do
|
10
|
+
config_file.source = 'path/to/file'
|
11
|
+
expect(config_file.destination).to eq 'path/to/file'
|
12
|
+
end
|
13
|
+
end
|
14
|
+
|
15
|
+
describe "#source" do
|
16
|
+
|
17
|
+
context "when host-specific file not found" do
|
18
|
+
|
19
|
+
let(:source) { 'path/../src_name.ext' }
|
20
|
+
|
21
|
+
it "returns the source path" do
|
22
|
+
config_file.source = source
|
23
|
+
allow(config_file).to receive(:search_for_host_specific_file).with(source)
|
24
|
+
.and_return(nil)
|
25
|
+
expect(config_file.source).to eq source
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
29
|
+
context "when host-specific file found" do
|
30
|
+
|
31
|
+
let(:source) { 'path/../src_name.ext' }
|
32
|
+
|
33
|
+
it "returns the host-specific source path" do
|
34
|
+
config_file.source = source
|
35
|
+
allow(config_file).to receive(:search_for_host_specific_file).with(source)
|
36
|
+
.and_return('path/../src_name.hostname.ext')
|
37
|
+
expect(config_file.source).to eq 'path/../src_name.hostname.ext'
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|
41
|
+
|
42
|
+
describe "#install" do
|
43
|
+
|
44
|
+
context "when config file should be installed" do
|
45
|
+
|
46
|
+
it "installs the config file and returns true" do
|
47
|
+
expect(config_file).to receive(:install?).and_return(true)
|
48
|
+
expect(config_file).to receive(:install_file)
|
49
|
+
expect(config_file).to receive(:set_mode)
|
50
|
+
expect(config_file).to receive(:set_owner)
|
51
|
+
expect(config_file.install).to be true
|
52
|
+
end
|
53
|
+
end
|
54
|
+
|
55
|
+
context "when config file should not be installed" do
|
56
|
+
|
57
|
+
it "does not install the config file and returns false" do
|
58
|
+
expect(config_file).to receive(:install?).and_return(false)
|
59
|
+
expect(config_file).to_not receive(:install_file)
|
60
|
+
expect(config_file).to_not receive(:set_mode)
|
61
|
+
expect(config_file).to_not receive(:set_owner)
|
62
|
+
expect(config_file.install).to be false
|
63
|
+
end
|
64
|
+
end
|
65
|
+
end
|
66
|
+
|
67
|
+
describe "#install?" do
|
68
|
+
|
69
|
+
context "when source not given" do
|
70
|
+
|
71
|
+
it "fails" do
|
72
|
+
expect { config_file.install? }.to raise_error ConfigCurator::Symlink::InstallFailed
|
73
|
+
end
|
74
|
+
end
|
75
|
+
|
76
|
+
context "when source does not exist" do
|
77
|
+
|
78
|
+
it "fails" do
|
79
|
+
config_file.source = 'dir/that/does/not/exist'
|
80
|
+
expect { config_file.install? }.to raise_error ConfigCurator::Symlink::InstallFailed
|
81
|
+
end
|
82
|
+
end
|
83
|
+
end
|
84
|
+
end
|
@@ -0,0 +1,46 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe ConfigCurator::Symlink do
|
4
|
+
|
5
|
+
subject(:symlink) { ConfigCurator::Symlink.new }
|
6
|
+
|
7
|
+
describe "#install" do
|
8
|
+
|
9
|
+
context "when symbolic link should be installed" do
|
10
|
+
|
11
|
+
it "installs the symbolic link and returns true" do
|
12
|
+
expect(symlink).to receive(:install?).and_return true
|
13
|
+
expect(symlink).to receive(:install_symlink)
|
14
|
+
expect(symlink.install).to be true
|
15
|
+
end
|
16
|
+
end
|
17
|
+
|
18
|
+
context "when symbolic link should not be installed" do
|
19
|
+
|
20
|
+
it "does not install the symbolic link and returns false" do
|
21
|
+
expect(symlink).to receive(:install?).and_return false
|
22
|
+
expect(symlink).to_not receive(:install_symlink)
|
23
|
+
expect(symlink.install).to be false
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
describe "#install?" do
|
29
|
+
|
30
|
+
context "when source not given" do
|
31
|
+
|
32
|
+
it "fails" do
|
33
|
+
symlink.destination = 'link_path'
|
34
|
+
expect { symlink.install? }.to raise_error ConfigCurator::Symlink::InstallFailed
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
38
|
+
context "when destination not given" do
|
39
|
+
|
40
|
+
it "fails" do
|
41
|
+
symlink.source = 'file'
|
42
|
+
expect { symlink.install? }.to raise_error ConfigCurator::Symlink::InstallFailed
|
43
|
+
end
|
44
|
+
end
|
45
|
+
end
|
46
|
+
end
|