wright 0.0.1 → 0.1.0

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.
Files changed (83) hide show
  1. checksums.yaml +7 -0
  2. data/LICENSE +2 -2
  3. data/NEWS +8 -0
  4. data/README.md +70 -0
  5. data/Rakefile +19 -0
  6. data/lib/wright/config.rb +64 -0
  7. data/lib/wright/dry_run.rb +33 -0
  8. data/lib/wright/dsl.rb +63 -0
  9. data/lib/wright/logger.rb +73 -0
  10. data/lib/wright/provider/directory.rb +78 -0
  11. data/lib/wright/provider/file.rb +104 -0
  12. data/lib/wright/provider/package/apt.rb +93 -0
  13. data/lib/wright/provider/package.rb +38 -0
  14. data/lib/wright/provider/symlink.rb +86 -0
  15. data/lib/wright/provider.rb +30 -0
  16. data/lib/wright/resource/directory.rb +67 -0
  17. data/lib/wright/resource/file.rb +67 -0
  18. data/lib/wright/resource/package.rb +70 -0
  19. data/lib/wright/resource/symlink.rb +47 -0
  20. data/lib/wright/resource.rb +157 -0
  21. data/lib/wright/util/color.rb +51 -0
  22. data/lib/wright/util/file.rb +258 -0
  23. data/lib/wright/util/file_permissions.rb +129 -0
  24. data/lib/wright/util/recursive_autoloader.rb +91 -0
  25. data/lib/wright/util/stolen_from_activesupport.rb +202 -0
  26. data/lib/wright/util/user.rb +75 -0
  27. data/lib/wright/util.rb +72 -0
  28. data/lib/wright/version.rb +3 -2
  29. data/lib/wright.rb +10 -1
  30. data/spec/config_spec.rb +37 -0
  31. data/spec/dsl_spec.rb +65 -0
  32. data/spec/logger_spec.rb +65 -0
  33. data/spec/provider/directory_spec.rb +114 -0
  34. data/spec/provider/file_spec.rb +130 -0
  35. data/spec/provider/package/apt/apt-get_install_-qy_abcde=2.5.4-1.return +1 -0
  36. data/spec/provider/package/apt/apt-get_install_-qy_abcde=2.5.4-1.stderr +0 -0
  37. data/spec/provider/package/apt/apt-get_install_-qy_abcde=2.5.4-1.stdout +15 -0
  38. data/spec/provider/package/apt/apt-get_install_-qy_htop.return +1 -0
  39. data/spec/provider/package/apt/apt-get_install_-qy_htop.stderr +0 -0
  40. data/spec/provider/package/apt/apt-get_install_-qy_htop.stdout +19 -0
  41. data/spec/provider/package/apt/apt-get_install_-qy_unknown-package.return +1 -0
  42. data/spec/provider/package/apt/apt-get_install_-qy_unknown-package.stderr +1 -0
  43. data/spec/provider/package/apt/apt-get_install_-qy_unknown-package.stdout +3 -0
  44. data/spec/provider/package/apt/apt-get_remove_-qy_abcde.return +1 -0
  45. data/spec/provider/package/apt/apt-get_remove_-qy_abcde.stderr +0 -0
  46. data/spec/provider/package/apt/apt-get_remove_-qy_abcde.stdout +14 -0
  47. data/spec/provider/package/apt/dpkg-query_-s_abcde.return +1 -0
  48. data/spec/provider/package/apt/dpkg-query_-s_abcde.stderr +0 -0
  49. data/spec/provider/package/apt/dpkg-query_-s_abcde.stdout +23 -0
  50. data/spec/provider/package/apt/dpkg-query_-s_htop.return +1 -0
  51. data/spec/provider/package/apt/dpkg-query_-s_htop.stderr +0 -0
  52. data/spec/provider/package/apt/dpkg-query_-s_htop.stdout +19 -0
  53. data/spec/provider/package/apt/dpkg-query_-s_unknown-package.return +1 -0
  54. data/spec/provider/package/apt/dpkg-query_-s_unknown-package.stderr +3 -0
  55. data/spec/provider/package/apt/dpkg-query_-s_unknown-package.stdout +0 -0
  56. data/spec/provider/package/apt/dpkg-query_-s_vlc.return +1 -0
  57. data/spec/provider/package/apt/dpkg-query_-s_vlc.stderr +3 -0
  58. data/spec/provider/package/apt/dpkg-query_-s_vlc.stdout +0 -0
  59. data/spec/provider/package/apt_spec.rb +297 -0
  60. data/spec/provider/package_spec.rb +63 -0
  61. data/spec/provider/symlink_spec.rb +122 -0
  62. data/spec/provider_spec.rb +19 -0
  63. data/spec/recursive_autoloader/foo/bar/baz.rb +12 -0
  64. data/spec/recursive_autoloader/identically_named_dir_and_file/this_should_not_be_loaded.rb +1 -0
  65. data/spec/recursive_autoloader/identically_named_dir_and_file.rb +8 -0
  66. data/spec/recursive_autoloader/loaded_on_demand.rb +8 -0
  67. data/spec/recursive_autoloader/raises_exception.rb +1 -0
  68. data/spec/recursive_autoloader_spec.rb +41 -0
  69. data/spec/resource/directory_spec.rb +187 -0
  70. data/spec/resource/file_spec.rb +213 -0
  71. data/spec/resource/symlink_spec.rb +117 -0
  72. data/spec/resource_spec.rb +184 -0
  73. data/spec/spec_helper.rb +35 -0
  74. data/spec/spec_helpers/fake_capture3.rb +47 -0
  75. data/spec/util/activesupport_spec.rb +24 -0
  76. data/spec/util/file_permissions_spec.rb +141 -0
  77. data/spec/util/file_spec.rb +127 -0
  78. data/spec/util/user_spec.rb +46 -0
  79. data/spec/util_spec.rb +80 -0
  80. metadata +253 -20
  81. data/.gitignore +0 -17
  82. data/Gemfile +0 -3
  83. data/wright.gemspec +0 -16
@@ -0,0 +1,187 @@
1
+ require_relative '../spec_helper'
2
+
3
+ require 'wright/resource/directory'
4
+ require 'wright/provider/directory'
5
+ require 'fileutils'
6
+
7
+ describe Wright::Resource::Directory do
8
+ before(:each) { @dirname = 'foo' }
9
+
10
+ after(:each) { FakeFS::FileSystem.clear }
11
+
12
+ describe '#create' do
13
+ it 'should create directories' do
14
+ FakeFS do
15
+ dir = Wright::Resource::Directory.new(@dirname)
16
+ dir.create
17
+ assert File.directory?(@dirname)
18
+ Wright::Util::File.file_mode(@dirname).must_equal ~::File.umask & 0777
19
+ Wright::Util::File.file_owner(@dirname).must_equal Process.uid
20
+ Wright::Util::File.file_group(@dirname).must_equal Process.gid
21
+ end
22
+ end
23
+
24
+ it 'should create directories with the given permissions' do
25
+ FakeFS do
26
+ dir = Wright::Resource::Directory.new(@dirname)
27
+ dir.mode = '644'
28
+ dir.owner = 23
29
+ dir.group = 42
30
+ dir.create
31
+ assert File.directory?(@dirname)
32
+ Wright::Util::File.file_mode(@dirname).must_equal 0644
33
+ Wright::Util::File.file_owner(@dirname).must_equal 23
34
+ Wright::Util::File.file_group(@dirname).must_equal 42
35
+ end
36
+ end
37
+
38
+ it 'should create directories recursively' do
39
+ FakeFS do
40
+ dirname = File.join(@dirname, @dirname, @dirname)
41
+ dir = Wright::Resource::Directory.new(dirname)
42
+ dir.create
43
+ assert File.directory?(dirname)
44
+ end
45
+ end
46
+
47
+ it 'should update existing directories' do
48
+ FakeFS do
49
+ FileUtils.mkdir_p(@dirname)
50
+ FileUtils.chmod(0600, @dirname)
51
+ FileUtils.chown(0, 0, @dirname)
52
+ dir = Wright::Resource::Directory.new(@dirname)
53
+ dir.mode = '644'
54
+ dir.owner = 23
55
+ dir.group = 42
56
+ dir.create
57
+ assert File.directory?(@dirname)
58
+ Wright::Util::File.file_mode(@dirname).must_equal 0644
59
+ Wright::Util::File.file_owner(@dirname).must_equal 23
60
+ Wright::Util::File.file_group(@dirname).must_equal 42
61
+ end
62
+ end
63
+
64
+ it 'should update the access mode for existing directories' do
65
+ FakeFS do
66
+ FileUtils.mkdir_p(@dirname)
67
+ FileUtils.chmod(0600, @dirname)
68
+ dir = Wright::Resource::Directory.new(@dirname)
69
+ dir.mode = '644'
70
+ dir.create
71
+ assert File.directory?(@dirname)
72
+ Wright::Util::File.file_mode(@dirname).must_equal 0644
73
+ end
74
+ end
75
+
76
+ it 'should not change up-to-date directories' do
77
+ FakeFS do
78
+ FileUtils.mkdir_p(@dirname)
79
+ mode = Wright::Util::File.file_mode(@dirname)
80
+ owner = Wright::Util::File.file_owner(@dirname)
81
+ group = Wright::Util::File.file_group(@dirname)
82
+ Wright::Resource::Directory.new(@dirname).create
83
+ Wright::Util::File.file_mode(@dirname).must_equal(mode)
84
+ Wright::Util::File.file_owner(@dirname).must_equal(owner)
85
+ Wright::Util::File.file_group(@dirname).must_equal(group)
86
+ end
87
+ end
88
+
89
+ it 'should support owner:group notation' do
90
+ FakeFS do
91
+ FileUtils.mkdir_p(@dirname)
92
+ FileUtils.chown(23, 45, @dirname)
93
+ owner = Etc.getpwuid(Process.uid).name
94
+ group = Etc.getgrgid(Process.gid).name
95
+ dir = Wright::Resource::Directory.new(@dirname)
96
+ dir.owner = "#{owner}:#{group}"
97
+ dir.create
98
+ Wright::Util::File.file_owner(@dirname).must_equal Process.uid
99
+ Wright::Util::File.file_group(@dirname).must_equal Process.gid
100
+ end
101
+ end
102
+
103
+ it 'should raise an exception when setting an invalid owner or group' do
104
+ dir = Wright::Resource::Directory.new(@dirname)
105
+ user = 'this_user_doesnt_exist'
106
+ group = 'this_group_doesnt_exist'
107
+
108
+ FakeFS do
109
+ lambda do
110
+ dir.owner = user
111
+ dir.create
112
+ end.must_raise ArgumentError
113
+ Dir.exist?(@dirname).must_equal false
114
+
115
+ lambda do
116
+ dir.group = group
117
+ dir.create
118
+ end.must_raise ArgumentError
119
+ Dir.exist?(@dirname).must_equal false
120
+
121
+ lambda do
122
+ dir.owner = "#{user}:#{group}"
123
+ dir.create
124
+ end.must_raise ArgumentError
125
+ Dir.exist?(@dirname).must_equal false
126
+ end
127
+ end
128
+
129
+ it 'should raise an exception if there is a regular file at path' do
130
+ FakeFS do
131
+ FileUtils.touch(@dirname)
132
+ dir = Wright::Resource::Directory.new(@dirname)
133
+ -> { dir.create }.must_raise Errno::EEXIST
134
+ end
135
+ end
136
+
137
+ it 'should expand paths' do
138
+ FakeFS do
139
+ dirname = '~/foobar'
140
+ dir = Wright::Resource::Directory.new(dirname)
141
+ FileUtils.mkdir_p(File.expand_path('~'))
142
+ dir.create
143
+ Dir.exist?(File.expand_path(dirname)).must_equal true
144
+ end
145
+ end
146
+ end
147
+
148
+ describe '#remove' do
149
+ it 'should remove directories' do
150
+ FakeFS do
151
+ FileUtils.mkdir_p(@dirname)
152
+ dir = Wright::Resource::Directory.new(@dirname)
153
+ dir.remove
154
+ assert !File.exist?(@dirname)
155
+ end
156
+ end
157
+
158
+ it 'should not remove non-empty directories' do
159
+ FakeFS do
160
+ FileUtils.mkdir_p(@dirname)
161
+ FileUtils.touch(File.join(@dirname, 'somefile'))
162
+ dir = Wright::Resource::Directory.new(@dirname)
163
+ -> { dir.remove }.must_raise Errno::ENOTEMPTY
164
+ assert File.directory?(@dirname)
165
+ end
166
+ end
167
+
168
+ it 'should not remove regular files' do
169
+ FakeFS do
170
+ FileUtils.touch(@dirname)
171
+ dir = Wright::Resource::Directory.new(@dirname)
172
+ -> { dir.remove }.must_raise RuntimeError
173
+ assert File.exist?(@dirname)
174
+ end
175
+ end
176
+
177
+ it 'should expand paths' do
178
+ FakeFS do
179
+ dirname = '~/foobar'
180
+ dir = Wright::Resource::Directory.new(dirname)
181
+ FileUtils.mkdir_p(File.expand_path(dirname))
182
+ dir.remove
183
+ Dir.exist?(File.expand_path(dirname)).must_equal false
184
+ end
185
+ end
186
+ end
187
+ end
@@ -0,0 +1,213 @@
1
+ require_relative '../spec_helper'
2
+
3
+ require 'wright/resource/file'
4
+ require 'wright/provider/file'
5
+ require 'fileutils'
6
+
7
+ describe Wright::Resource::File do
8
+ before(:each) do
9
+ @filename = 'foo'
10
+ FakeFS { FileUtils.mkdir_p Dir.tmpdir }
11
+ end
12
+
13
+ after(:each) { FakeFS::FileSystem.clear }
14
+
15
+ describe '#create' do
16
+ it 'should create files' do
17
+ FakeFS do
18
+ file = Wright::Resource::File.new(@filename)
19
+ file.content = 'hello world'
20
+ file.create
21
+ assert File.file?(@filename)
22
+ File.read(@filename).must_equal 'hello world'
23
+ end
24
+ end
25
+
26
+ it 'should create empty files when content is not set' do
27
+ FakeFS do
28
+ file = Wright::Resource::File.new(@filename)
29
+ file.create
30
+ assert File.file?(@filename)
31
+ File.read(@filename).must_equal ''
32
+ end
33
+ end
34
+
35
+ it 'should create files with the correct owner, group and mode' do
36
+ FakeFS do
37
+ file = Wright::Resource::File.new(@filename)
38
+ file.content = 'hello world'
39
+ file.owner = 23
40
+ file.group = 42
41
+ file.mode = '700'
42
+ file.create
43
+ assert File.file?(@filename)
44
+ File.read(@filename).must_equal 'hello world'
45
+ Wright::Util::File.file_owner(@filename).must_equal 23
46
+ Wright::Util::File.file_group(@filename).must_equal 42
47
+ end
48
+ end
49
+
50
+ it 'should update existing files' do
51
+ FakeFS do
52
+ FileUtils.touch(@filename)
53
+ FileUtils.chmod(0600, @filename)
54
+ FileUtils.chown(0, 0, @filename)
55
+ file = Wright::Resource::File.new(@filename)
56
+ file.mode = '644'
57
+ file.owner = 23
58
+ file.group = 42
59
+ file.content = 'hello world'
60
+ file.create
61
+ File.read(@filename).must_equal 'hello world'
62
+ Wright::Util::File.file_mode(@filename).must_equal 0644
63
+ Wright::Util::File.file_owner(@filename).must_equal 23
64
+ Wright::Util::File.file_group(@filename).must_equal 42
65
+ end
66
+ end
67
+
68
+ it 'should not overwrite existing files when content is nil' do
69
+ FakeFS do
70
+ File.write(@filename, 'old content')
71
+ File.chmod(0600, @filename)
72
+ file = Wright::Resource::File.new(@filename)
73
+ file.mode = '644'
74
+ file.create
75
+ File.read(@filename).must_equal 'old content'
76
+ Wright::Util::File.file_mode(@filename).must_equal 0644
77
+ end
78
+ end
79
+
80
+ it 'should not change up-to-date files' do
81
+ FakeFS do
82
+ File.write(@filename, 'hello world')
83
+ FileUtils.chmod(0600, @filename)
84
+ FileUtils.chown(23, 42, @filename)
85
+ file = Wright::Resource::File.new(@filename)
86
+ file.mode = '600'
87
+ file.owner = 23
88
+ file.group = 42
89
+ file.content = 'hello world'
90
+ file.create
91
+ File.read(@filename).must_equal 'hello world'
92
+ Wright::Util::File.file_mode(@filename).must_equal 0600
93
+ Wright::Util::File.file_owner(@filename).must_equal 23
94
+ Wright::Util::File.file_group(@filename).must_equal 42
95
+ end
96
+ end
97
+
98
+ it 'should throw an exception when the target is a directory' do
99
+ FakeFS do
100
+ FileUtils.mkdir_p(@filename)
101
+ file = Wright::Resource::File.new(@filename)
102
+ -> { file.create }.must_raise Errno::EISDIR
103
+ assert File.directory?(@filename)
104
+ end
105
+ end
106
+
107
+ it 'should support owner:group notation' do
108
+ FakeFS do
109
+ FileUtils.touch(@filename)
110
+ FileUtils.chown(23, 45, @filename)
111
+ owner = Etc.getpwuid(Process.uid).name
112
+ group = Etc.getgrgid(Process.gid).name
113
+ file = Wright::Resource::File.new(@filename)
114
+ file.owner = "#{owner}:#{group}"
115
+ file.create
116
+ Wright::Util::File.file_owner(@filename).must_equal Process.uid
117
+ Wright::Util::File.file_group(@filename).must_equal Process.gid
118
+ end
119
+ end
120
+
121
+ it 'should raise an exception when setting invalid an owner/group' do
122
+ file = Wright::Resource::File.new(@filename)
123
+ user = 'this_user_doesnt_exist'
124
+ group = 'this_group_doesnt_exist'
125
+
126
+ FakeFS do
127
+ lambda do
128
+ file.owner = user
129
+ file.create
130
+ end.must_raise ArgumentError
131
+ File.exist?(@filename).must_equal false
132
+
133
+ file.owner = nil
134
+ lambda do
135
+ file.group = group
136
+ file.create
137
+ end.must_raise ArgumentError
138
+ File.exist?(@filename).must_equal false
139
+
140
+ file.group = nil
141
+ lambda do
142
+ file.owner = "#{user}:#{group}"
143
+ file.create
144
+ end.must_raise ArgumentError
145
+ File.exist?(@filename).must_equal false
146
+ end
147
+ end
148
+
149
+ it 'should raise an exception if there is a directory at path' do
150
+ FakeFS do
151
+ FileUtils.mkdir(@filename)
152
+ file = Wright::Resource::File.new(@filename)
153
+ -> { file.create }.must_raise Errno::EISDIR
154
+ end
155
+ end
156
+
157
+ it 'should expand paths' do
158
+ FakeFS do
159
+ filename = '~/foobar'
160
+ expanded_path = File.expand_path(filename)
161
+ file = Wright::Resource::File.new(filename)
162
+ FileUtils.mkdir_p(File.expand_path('~'))
163
+ file.mode = '0765'
164
+ file.create
165
+ File.exist?(expanded_path).must_equal true
166
+ Wright::Util::File.file_mode(expanded_path).must_equal 0765
167
+ end
168
+ end
169
+ end
170
+
171
+ describe '#remove' do
172
+ it 'should remove files' do
173
+ FakeFS do
174
+ FileUtils.touch(@filename)
175
+ file = Wright::Resource::File.new(@filename)
176
+ file.remove
177
+ assert !File.exist?(@filename)
178
+ end
179
+ end
180
+
181
+ it 'should not remove directories' do
182
+ FakeFS do
183
+ FileUtils.mkdir_p(@filename)
184
+ file = Wright::Resource::File.new(@filename)
185
+ -> { file.remove }.must_raise Errno::EISDIR
186
+ assert File.directory?(@filename)
187
+ end
188
+ end
189
+
190
+ it 'should remove symlinks' do
191
+ FakeFS do
192
+ FileUtils.touch('target_file')
193
+ FileUtils.ln_s('target_file', @filename)
194
+ file = Wright::Resource::File.new(@filename)
195
+ assert File.symlink?(@filename)
196
+ file.remove
197
+ assert !File.symlink?(@filename)
198
+ assert File.exist?('target_file')
199
+ end
200
+ end
201
+
202
+ it 'should expand paths' do
203
+ FakeFS do
204
+ filename = '~/foobar'
205
+ file = Wright::Resource::File.new(filename)
206
+ FileUtils.mkdir_p(File.expand_path('~'))
207
+ FileUtils.touch(File.expand_path(filename))
208
+ file.remove
209
+ File.exist?(File.expand_path(filename)).must_equal false
210
+ end
211
+ end
212
+ end
213
+ end
@@ -0,0 +1,117 @@
1
+ require_relative '../spec_helper'
2
+
3
+ require 'wright/resource/symlink'
4
+ require 'wright/provider/symlink'
5
+ require 'fileutils'
6
+
7
+ describe Wright::Resource::Symlink do
8
+ before(:each) do
9
+ @target = 'foo'
10
+ @link_name = 'bar'
11
+ end
12
+
13
+ after(:each) { FakeFS::FileSystem.clear }
14
+
15
+ def link_resource(target, link_name)
16
+ link = Wright::Resource::Symlink.new(link_name)
17
+ link.to = target
18
+ link
19
+ end
20
+
21
+ describe '#create' do
22
+ it 'should create symlinks' do
23
+ FakeFS do
24
+ link = link_resource(@target, @link_name)
25
+ link.create
26
+ File.symlink?(@link_name).must_equal true
27
+ File.readlink(@link_name).must_equal @target
28
+ end
29
+ end
30
+
31
+ it 'should update symlinks to files' do
32
+ FakeFS do
33
+ link = link_resource(@target, @link_name)
34
+ FileUtils.ln_sf('oldtarget', @link_name)
35
+ link.create
36
+
37
+ assert File.symlink?(@link_name)
38
+ File.readlink(@link_name).must_equal @target
39
+ end
40
+ end
41
+
42
+ it 'should update symlinks to directories' do
43
+ FakeFS do
44
+ link = link_resource(@target, @link_name)
45
+ FileUtils.mkdir_p('somedir')
46
+ FileUtils.ln_s('somedir', @link_name)
47
+ link.create
48
+
49
+ assert File.symlink?(@link_name)
50
+ File.readlink(@link_name).must_equal @target
51
+ end
52
+ end
53
+
54
+ it 'should not overwrite existing files' do
55
+ FakeFS do
56
+ file_content = 'Hello world'
57
+ File.write(@link_name, file_content)
58
+ link = link_resource(@target, @link_name)
59
+ -> { link.create }.must_raise Errno::EEXIST
60
+ File.read(@link_name).must_equal file_content
61
+ end
62
+ end
63
+
64
+ it 'should expand paths' do
65
+ FakeFS do
66
+ FileUtils.mkdir_p(File.expand_path('~'))
67
+ link = Wright::Resource::Symlink.new('~/foo')
68
+ link.to = '~/bar/..'
69
+ link.create
70
+
71
+ File.exist?(File.expand_path('~/foo')).must_equal true
72
+ expected = File.join(File.expand_path('~'), 'bar/..')
73
+ actual = File.readlink(File.expand_path('~/foo'))
74
+ expected.must_equal actual
75
+ end
76
+ end
77
+ end
78
+
79
+ describe '#remove' do
80
+ it 'should remove existing symlinks' do
81
+ FakeFS do
82
+ link = Wright::Resource::Symlink.new(@link_name)
83
+ FileUtils.touch(@target)
84
+ FileUtils.ln_s(@target, @link_name)
85
+
86
+ File.exist?(@target).must_equal true
87
+ File.symlink?(@link_name).must_equal true
88
+ link.remove
89
+ File.exist?(@target).must_equal true
90
+ File.symlink?(@link_name).must_equal false
91
+ end
92
+ end
93
+
94
+ it 'should not remove existing regular files' do
95
+ FakeFS do
96
+ FileUtils.touch(@link_name)
97
+ link = Wright::Resource::Symlink.new(@link_name)
98
+ File.exist?(@link_name).must_equal true
99
+ -> { link.remove }.must_raise RuntimeError
100
+ File.exist?(@link_name).must_equal true
101
+ end
102
+ end
103
+
104
+ it 'should expand paths' do
105
+ FakeFS do
106
+ FileUtils.mkdir_p(File.expand_path('~'))
107
+ FileUtils.touch(File.expand_path('~/bar'))
108
+ FileUtils.ln_sf(File.expand_path('~/bar'),
109
+ File.expand_path('~/foo'))
110
+ link = Wright::Resource::Symlink.new('~/foo')
111
+ link.remove
112
+ File.exist?(File.expand_path('~/foo')).must_equal false
113
+ File.exist?(File.expand_path('~/bar')).must_equal true
114
+ end
115
+ end
116
+ end
117
+ end
@@ -0,0 +1,184 @@
1
+ require_relative 'spec_helper'
2
+
3
+ require 'wright/resource'
4
+ require 'wright/provider'
5
+
6
+ module Wright
7
+ # add provider attribute reader for tests
8
+ class Resource
9
+ attr_reader :provider
10
+ end
11
+ end
12
+
13
+ module Wright
14
+ class Provider
15
+ class Sample < Wright::Provider; end
16
+ class AlternateSample < Wright::Provider; end
17
+
18
+ # provider that is always updated
19
+ class AlwaysUpdated < Wright::Provider
20
+ def updated?
21
+ true
22
+ end
23
+ end
24
+
25
+ # provider that is never updated
26
+ class NeverUpdated < Wright::Provider
27
+ def updated?
28
+ false
29
+ end
30
+ end
31
+ end
32
+ end
33
+
34
+ class Sample < Wright::Resource; end
35
+
36
+ # resource with a single method to test update notification
37
+ class Updater < Wright::Resource
38
+ def do_something
39
+ might_update_resource {}
40
+ end
41
+ end
42
+
43
+ describe Wright::Resource do
44
+ before(:each) do
45
+ @config = Wright::Config.config_hash.clone
46
+ Wright::Config.config_hash.clear
47
+ @hello = 'Hello world'
48
+ @say_hello = -> { print @hello }
49
+ end
50
+
51
+ after(:each) do
52
+ Wright::Config.config_hash = @config
53
+ end
54
+
55
+ it 'should retrieve a provider for a resource' do
56
+ provider_class = Wright::Provider::Sample
57
+ Sample.new.provider.must_be_kind_of provider_class
58
+ end
59
+
60
+ it 'should retrieve a provider for a resource listed in the config' do
61
+ # instantiating the Sample resource without any config should
62
+ # yield the Sample provider
63
+ provider_class = Wright::Provider::Sample
64
+ Sample.new.provider.must_be_kind_of provider_class
65
+
66
+ # when the provider for Sample resources is set to
67
+ # AlternateSample, AlternateSample should be instantiated
68
+ alternate = Wright::Provider::AlternateSample
69
+ Wright::Config[:resources] = { sample: { provider: alternate.name } }
70
+ Sample.new.provider.must_be_kind_of alternate
71
+ end
72
+
73
+ it 'should display warnings for nonexistent providers' do
74
+ class NonExistent < Wright::Resource; end
75
+ output = "WARN: Could not find a provider for resource NonExistent\n"
76
+ lambda do
77
+ reset_logger
78
+ NonExistent.new
79
+ end.must_output(output)
80
+ end
81
+
82
+ it 'should run update actions on updates' do
83
+ provider = Wright::Provider::AlwaysUpdated
84
+ Wright::Config[:resources] = { updater: { provider: provider.name } }
85
+ resource = Updater.new
86
+ lambda do
87
+ resource.on_update = @say_hello
88
+ assert resource.do_something
89
+ end.must_output @hello
90
+ end
91
+
92
+ it 'should not run update actions if there were no updates' do
93
+ provider = Wright::Provider::NeverUpdated
94
+ Wright::Config[:resources] = { updater: { provider: provider.name } }
95
+ resource = Updater.new
96
+ lambda do
97
+ resource.on_update = @say_hello
98
+ assert !resource.do_something
99
+ end.must_be_silent
100
+ end
101
+
102
+ it 'should not run update actions in dry-run mode' do
103
+ Wright.dry_run do
104
+ provider = Wright::Provider::AlwaysUpdated
105
+ Wright::Config[:resources] = { updater: { provider: provider.name } }
106
+ name = :farnsworth
107
+ resource = Updater.new(name)
108
+ resource_info = "#{resource.resource_name} '#{name}'"
109
+ output = "INFO: Would trigger update action for #{resource_info}\n"
110
+ lambda do
111
+ reset_logger
112
+ resource.on_update = @say_hello
113
+ assert resource.do_something
114
+ end.must_output output
115
+ end
116
+ end
117
+
118
+ it 'should raise an ArgumentError if on_update is not callable' do
119
+ resource = Sample.new
120
+ -> { resource.on_update = "I'm a string" }.must_raise ArgumentError
121
+ -> { resource.on_update = -> {} }.must_be_silent
122
+ -> { resource.on_update = nil }.must_be_silent
123
+ end
124
+
125
+ it 'should run actions' do
126
+ # simple resource to test different actions
127
+ class NiSayer < Wright::Resource
128
+ def say
129
+ print 'Ni!'
130
+ end
131
+
132
+ def shout
133
+ print 'NI!'
134
+ end
135
+ end
136
+ Wright::Config[:resources] = { ni_sayer: { provider: 'Sample' } }
137
+ ni_sayer = NiSayer.new
138
+ lambda do
139
+ ni_sayer.action = :say
140
+ ni_sayer.run_action
141
+ end.must_output 'Ni!'
142
+ lambda do
143
+ ni_sayer.action = :shout
144
+ ni_sayer.run_action
145
+ end.must_output 'NI!'
146
+ lambda do
147
+ ni_sayer.action = nil
148
+ ni_sayer.run_action
149
+ end.must_be_silent
150
+ end
151
+
152
+ it 'should not raise exceptions if ignore_failure is enabled' do
153
+ module Wright
154
+ class Provider
155
+ # provider that always raises exceptions
156
+ class RaisesExceptions < Wright::Provider
157
+ def fail_train
158
+ fail 'Fail train!'
159
+ end
160
+ end
161
+ end
162
+ end
163
+
164
+ # resource that always raises exceptions
165
+ class RaisesExceptions < Wright::Resource
166
+ def fail_train
167
+ might_update_resource { @provider.fail_train }
168
+ end
169
+ end
170
+
171
+ resource = RaisesExceptions.new('fake_name')
172
+
173
+ lambda do
174
+ resource.ignore_failure = true
175
+ reset_logger
176
+ resource.fail_train
177
+ end.must_output "ERROR: raises_exceptions 'fake_name': Fail train!\n"
178
+
179
+ lambda do
180
+ resource.ignore_failure = false
181
+ resource.fail_train
182
+ end.must_raise(RuntimeError)
183
+ end
184
+ end