vanagon 0.3.18
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 +7 -0
- data/LICENSE +13 -0
- data/README.md +175 -0
- data/bin/build +33 -0
- data/bin/devkit +22 -0
- data/bin/repo +26 -0
- data/bin/ship +15 -0
- data/lib/vanagon.rb +8 -0
- data/lib/vanagon/common.rb +2 -0
- data/lib/vanagon/common/pathname.rb +87 -0
- data/lib/vanagon/common/user.rb +25 -0
- data/lib/vanagon/component.rb +157 -0
- data/lib/vanagon/component/dsl.rb +307 -0
- data/lib/vanagon/component/source.rb +66 -0
- data/lib/vanagon/component/source/git.rb +60 -0
- data/lib/vanagon/component/source/http.rb +158 -0
- data/lib/vanagon/driver.rb +112 -0
- data/lib/vanagon/engine/base.rb +82 -0
- data/lib/vanagon/engine/docker.rb +40 -0
- data/lib/vanagon/engine/local.rb +40 -0
- data/lib/vanagon/engine/pooler.rb +85 -0
- data/lib/vanagon/errors.rb +28 -0
- data/lib/vanagon/extensions/string.rb +11 -0
- data/lib/vanagon/optparse.rb +62 -0
- data/lib/vanagon/platform.rb +245 -0
- data/lib/vanagon/platform/deb.rb +71 -0
- data/lib/vanagon/platform/dsl.rb +293 -0
- data/lib/vanagon/platform/osx.rb +100 -0
- data/lib/vanagon/platform/rpm.rb +76 -0
- data/lib/vanagon/platform/rpm/wrl.rb +39 -0
- data/lib/vanagon/platform/solaris_10.rb +182 -0
- data/lib/vanagon/platform/solaris_11.rb +138 -0
- data/lib/vanagon/platform/swix.rb +35 -0
- data/lib/vanagon/project.rb +251 -0
- data/lib/vanagon/project/dsl.rb +218 -0
- data/lib/vanagon/utilities.rb +299 -0
- data/spec/fixures/component/invalid-test-fixture.json +3 -0
- data/spec/fixures/component/mcollective.service +1 -0
- data/spec/fixures/component/test-fixture.json +4 -0
- data/spec/lib/vanagon/common/pathname_spec.rb +103 -0
- data/spec/lib/vanagon/common/user_spec.rb +36 -0
- data/spec/lib/vanagon/component/dsl_spec.rb +443 -0
- data/spec/lib/vanagon/component/source/git_spec.rb +19 -0
- data/spec/lib/vanagon/component/source/http_spec.rb +43 -0
- data/spec/lib/vanagon/component/source_spec.rb +99 -0
- data/spec/lib/vanagon/component_spec.rb +22 -0
- data/spec/lib/vanagon/engine/base_spec.rb +40 -0
- data/spec/lib/vanagon/engine/docker_spec.rb +40 -0
- data/spec/lib/vanagon/engine/pooler_spec.rb +54 -0
- data/spec/lib/vanagon/platform/deb_spec.rb +60 -0
- data/spec/lib/vanagon/platform/dsl_spec.rb +128 -0
- data/spec/lib/vanagon/platform/rpm_spec.rb +41 -0
- data/spec/lib/vanagon/platform/solaris_11_spec.rb +44 -0
- data/spec/lib/vanagon/platform_spec.rb +53 -0
- data/spec/lib/vanagon/project/dsl_spec.rb +203 -0
- data/spec/lib/vanagon/project_spec.rb +44 -0
- data/spec/lib/vanagon/utilities_spec.rb +140 -0
- data/templates/Makefile.erb +116 -0
- data/templates/deb/changelog.erb +5 -0
- data/templates/deb/conffiles.erb +3 -0
- data/templates/deb/control.erb +21 -0
- data/templates/deb/dirs.erb +3 -0
- data/templates/deb/docs.erb +1 -0
- data/templates/deb/install.erb +3 -0
- data/templates/deb/postinst.erb +46 -0
- data/templates/deb/postrm.erb +15 -0
- data/templates/deb/prerm.erb +17 -0
- data/templates/deb/rules.erb +25 -0
- data/templates/osx/postinstall.erb +24 -0
- data/templates/osx/preinstall.erb +19 -0
- data/templates/osx/project-installer.xml.erb +19 -0
- data/templates/rpm/project.spec.erb +217 -0
- data/templates/solaris/10/depend.erb +3 -0
- data/templates/solaris/10/pkginfo.erb +13 -0
- data/templates/solaris/10/postinstall.erb +37 -0
- data/templates/solaris/10/preinstall.erb +7 -0
- data/templates/solaris/10/preremove.erb +6 -0
- data/templates/solaris/10/proto.erb +5 -0
- data/templates/solaris/11/p5m.erb +73 -0
- metadata +172 -0
@@ -0,0 +1,299 @@
|
|
1
|
+
require 'vanagon/errors'
|
2
|
+
require 'net/http'
|
3
|
+
require 'uri'
|
4
|
+
require 'json'
|
5
|
+
require 'digest'
|
6
|
+
require 'erb'
|
7
|
+
require 'timeout'
|
8
|
+
require 'vanagon/extensions/string'
|
9
|
+
|
10
|
+
class Vanagon
|
11
|
+
module Utilities
|
12
|
+
|
13
|
+
# Utility to get the md5 sum of a file
|
14
|
+
#
|
15
|
+
# @param file [String] file to md5sum
|
16
|
+
# @return [String] md5sum of the given file
|
17
|
+
def get_md5sum(file)
|
18
|
+
Digest::MD5.file(file).hexdigest.to_s
|
19
|
+
end
|
20
|
+
|
21
|
+
# Generic file summing utility
|
22
|
+
#
|
23
|
+
# @param file [String] file to sum
|
24
|
+
# @param type [String] type of sum to provide
|
25
|
+
# @return [String] sum of the given file
|
26
|
+
# @raise [RuntimeError] raises an exception if the given sum type is not supported
|
27
|
+
def get_sum(file, type)
|
28
|
+
case type.downcase
|
29
|
+
when 'md5'
|
30
|
+
Digest::MD5.file(file).hexdigest.to_s
|
31
|
+
when 'sha512'
|
32
|
+
Digest::SHA512.file(file).hexdigest.to_s
|
33
|
+
else
|
34
|
+
fail "Don't know how to produce a sum of type: '#{type}' for '#{file}'."
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
38
|
+
# Simple wrapper around Net::HTTP. Will make a request of the given type to
|
39
|
+
# the given url and return the body as parsed by JSON.
|
40
|
+
#
|
41
|
+
# @param url [String] The url to make the request against (needs to be parsable by URI
|
42
|
+
# @param type [String] One of the supported request types (currently 'get', 'post', 'delete')
|
43
|
+
# @param payload [String] The request body data payload used for POST and PUT
|
44
|
+
# @param header [Hash] Send additional information in the HTTP request header
|
45
|
+
# @return [Hash] The response body is parsed by JSON and returned
|
46
|
+
# @raise [RuntimeError, Vanagon::Error] an exception is raised if the
|
47
|
+
# action is not supported, or if there is a problem with the http request,
|
48
|
+
# or if the response is not JSON
|
49
|
+
def http_request(url, type, payload = {}.to_json, header = nil)
|
50
|
+
uri = URI.parse(url)
|
51
|
+
http = Net::HTTP.new(uri.host, uri.port)
|
52
|
+
|
53
|
+
case type.downcase
|
54
|
+
when "get"
|
55
|
+
request = Net::HTTP::Get.new(uri.request_uri)
|
56
|
+
when "post"
|
57
|
+
request = Net::HTTP::Post.new(uri.request_uri)
|
58
|
+
request.body = payload
|
59
|
+
when "put"
|
60
|
+
request = Net::HTTP::Put.new(uri.request_uri)
|
61
|
+
request.body = payload
|
62
|
+
when "delete"
|
63
|
+
request = Net::HTTP::Delete.new(uri.request_uri)
|
64
|
+
else
|
65
|
+
fail "ACTION: #{type} not supported by #http_request method. Maybe you should add it?"
|
66
|
+
end
|
67
|
+
|
68
|
+
# Add any headers to the request
|
69
|
+
if header && header.is_a?(Hash)
|
70
|
+
header.each do |key, val|
|
71
|
+
request[key] = val
|
72
|
+
end
|
73
|
+
end
|
74
|
+
|
75
|
+
response = http.request(request)
|
76
|
+
|
77
|
+
JSON.parse(response.body)
|
78
|
+
|
79
|
+
rescue Errno::ETIMEDOUT, Timeout::Error, Errno::EINVAL, Errno::ECONNRESET,
|
80
|
+
EOFError, Net::HTTPBadResponse, Net::HTTPHeaderSyntaxError,
|
81
|
+
Net::ProtocolError => e
|
82
|
+
raise Vanagon::Error.wrap(e, "Problem reaching #{url}. Is #{uri.host} down?")
|
83
|
+
rescue JSON::ParserError => e
|
84
|
+
raise Vanagon::Error.wrap(e, "#{uri.host} handed us a response that doesn't look like JSON.")
|
85
|
+
end
|
86
|
+
|
87
|
+
# Similar to rake's sh, the passed command will be executed and an
|
88
|
+
# exception will be raised on command failure. However, in contrast to
|
89
|
+
# rake's sh, this method returns the output of the command instead of a
|
90
|
+
# boolean.
|
91
|
+
#
|
92
|
+
# @param command [String] The command to be executed
|
93
|
+
# @return [String] The standard output of the executed command
|
94
|
+
# @raise [Vanagon::Error] If the command fails an exception is raised
|
95
|
+
def ex(command)
|
96
|
+
ret = `#{command}`
|
97
|
+
unless $?.success?
|
98
|
+
raise Vanagon::Error, "'#{command}' did not succeed"
|
99
|
+
end
|
100
|
+
ret
|
101
|
+
end
|
102
|
+
|
103
|
+
# Similar to the command-line utility which, the method will search the
|
104
|
+
# PATH for the passed command and return the full path to the command if it
|
105
|
+
# exists.
|
106
|
+
#
|
107
|
+
# @param command [String] Command to search for on PATH
|
108
|
+
# @param required [true, false] Whether or not to raise an exception if the command cannot be found
|
109
|
+
# @return [String, false] Returns either the full path to the command or false if the command cannot be found
|
110
|
+
# @raise [RuntimeError] If the command is required and cannot be found
|
111
|
+
def find_program_on_path(command, required = true)
|
112
|
+
ENV['PATH'].split(File::PATH_SEPARATOR).each do |path_elem|
|
113
|
+
location = File.join(path_elem, command)
|
114
|
+
return location if FileTest.executable?(location)
|
115
|
+
end
|
116
|
+
|
117
|
+
if required
|
118
|
+
fail "Could not find '#{command}'. Please install (or ensure it is on $PATH), and try again."
|
119
|
+
else
|
120
|
+
return false
|
121
|
+
end
|
122
|
+
end
|
123
|
+
|
124
|
+
# Method to retry a ruby block and fail if the command does not succeed
|
125
|
+
# within the number of tries and timeout.
|
126
|
+
#
|
127
|
+
# @param tries [Integer] number of times to try calling the block
|
128
|
+
# @param timeout [Integer] number of seconds to run the block before timing out
|
129
|
+
# @return [true] If the block succeeds, true is returned
|
130
|
+
# @raise [Vanagon::Error] if the block fails after the retries are exhausted, an error is raised
|
131
|
+
def retry_with_timeout(tries = 5, timeout = 1, &blk)
|
132
|
+
tries.times do
|
133
|
+
Timeout::timeout(timeout) do
|
134
|
+
begin
|
135
|
+
blk.call
|
136
|
+
return true
|
137
|
+
rescue
|
138
|
+
warn 'An error was encountered evaluating block. Retrying..'
|
139
|
+
end
|
140
|
+
end
|
141
|
+
end
|
142
|
+
|
143
|
+
raise Vanagon::Error, "Block failed maximum of #{tries} tries. Exiting.."
|
144
|
+
end
|
145
|
+
|
146
|
+
# Simple wrapper around git command line executes the given commands and
|
147
|
+
# returns the results.
|
148
|
+
#
|
149
|
+
# @param commands [String] The commands to be run
|
150
|
+
# @return [String] The output of the command
|
151
|
+
def git(*commands)
|
152
|
+
git_bin = find_program_on_path('git')
|
153
|
+
%x(#{git_bin} #{commands.join(' ')})
|
154
|
+
end
|
155
|
+
|
156
|
+
# Determines if the given directory is a git repo or not
|
157
|
+
#
|
158
|
+
# @param directory [String] The directory to check
|
159
|
+
# @return [true, false] True if the directory is a git repo, false otherwise
|
160
|
+
def is_git_repo?(directory = Dir.pwd)
|
161
|
+
Dir.chdir(directory) do
|
162
|
+
git('rev-parse', '--git-dir', '> /dev/null 2>&1')
|
163
|
+
$?.success?
|
164
|
+
end
|
165
|
+
end
|
166
|
+
|
167
|
+
# Determines a version for the given directory based on the git describe
|
168
|
+
# for the repository
|
169
|
+
#
|
170
|
+
# @param directory [String] The directory to use in versioning
|
171
|
+
# @return [String] The version of the directory accoring to git describe
|
172
|
+
# @raise [RuntimeError] If the given directory is not a git repo
|
173
|
+
def git_version(directory = Dir.pwd)
|
174
|
+
if is_git_repo?(directory)
|
175
|
+
Dir.chdir(directory) do
|
176
|
+
version = git('describe', '--tags', '2> /dev/null').chomp
|
177
|
+
if version.empty?
|
178
|
+
warn "Directory '#{directory}' cannot be versioned by git. Maybe it hasn't been tagged yet?"
|
179
|
+
end
|
180
|
+
return version
|
181
|
+
end
|
182
|
+
else
|
183
|
+
fail "Directory '#{directory}' is not a git repo, cannot get a version"
|
184
|
+
end
|
185
|
+
end
|
186
|
+
|
187
|
+
# Sends the desired file/directory to the destination using rsync
|
188
|
+
#
|
189
|
+
# @param source [String] file or directory to send
|
190
|
+
# @param target [String] ssh host to send to (user@machine)
|
191
|
+
# @param dest [String] path on target to place the source
|
192
|
+
# @param extra_flags [Array] any additional flags to pass to rsync
|
193
|
+
# @param port [Integer] Port number for ssh (default 22)
|
194
|
+
# @return [String] output of rsync command
|
195
|
+
def rsync_to(source, target, dest, port = 22, extra_flags = ["--ignore-existing"])
|
196
|
+
rsync = find_program_on_path('rsync')
|
197
|
+
flags = "-rHlv --no-perms --no-owner --no-group"
|
198
|
+
unless extra_flags.empty?
|
199
|
+
flags << " " << extra_flags.join(" ")
|
200
|
+
end
|
201
|
+
ex("#{rsync} -e '#{ssh_command(port)}' #{flags} #{source} #{target}:#{dest}")
|
202
|
+
end
|
203
|
+
|
204
|
+
# Hacky wrapper to add on the correct flags for ssh to be used in ssh and rsync methods
|
205
|
+
#
|
206
|
+
# @param port [Integer] Port number for ssh (default 22)
|
207
|
+
# @return [String] start of ssh command, including flags for ssh keys
|
208
|
+
def ssh_command(port = 22)
|
209
|
+
ssh = find_program_on_path('ssh')
|
210
|
+
args = ENV['VANAGON_SSH_KEY'] ? " -i #{ENV['VANAGON_SSH_KEY']}" : ""
|
211
|
+
args << " -p #{port} "
|
212
|
+
args << " -o UserKnownHostsFile=/dev/null"
|
213
|
+
args << " -o StrictHostKeyChecking=no"
|
214
|
+
return ssh + args
|
215
|
+
end
|
216
|
+
|
217
|
+
# Retrieves the desired file/directory from the destination using rsync
|
218
|
+
#
|
219
|
+
# @param source [String] path on target to retrieve from
|
220
|
+
# @param target [String] ssh host to retrieve from (user@machine)
|
221
|
+
# @param dest [String] path on local host to place the source
|
222
|
+
# @param port [Integer] port number for ssh (default 22)
|
223
|
+
# @param extra_flags [Array] any additional flags to pass to rsync
|
224
|
+
# @return [String] output of rsync command
|
225
|
+
def rsync_from(source, target, dest, port = 22, extra_flags = [])
|
226
|
+
rsync = find_program_on_path('rsync')
|
227
|
+
flags = "-rHlv -O --no-perms --no-owner --no-group"
|
228
|
+
unless extra_flags.empty?
|
229
|
+
flags << " " << extra_flags.join(" ")
|
230
|
+
end
|
231
|
+
ex("#{rsync} -e '#{ssh_command(port)}' #{flags} #{target}:#{source} #{dest}")
|
232
|
+
end
|
233
|
+
|
234
|
+
# Runs the command on the given host via ssh call
|
235
|
+
#
|
236
|
+
# @param target [String] ssh host to run command on (user@machine)
|
237
|
+
# @param command [String] command to run on the target
|
238
|
+
# @param port [Integer] port number for ssh (default 22)
|
239
|
+
# @param return_command_output [Boolean] whether or not command output should be returned
|
240
|
+
# @return [true, String] Returns true if the command was successful or the
|
241
|
+
# output of the command if return_command_output is true
|
242
|
+
# @raise [RuntimeError] If there is no target given or the command fails an exception is raised
|
243
|
+
def remote_ssh_command(target, command, port = 22, return_command_output: false)
|
244
|
+
if target
|
245
|
+
puts "Executing '#{command}' on #{target}"
|
246
|
+
if return_command_output
|
247
|
+
ret = %x(#{ssh_command(port)} -T #{target} '#{command.gsub("'", "'\\\\''")}').chomp
|
248
|
+
if $?.success?
|
249
|
+
return ret
|
250
|
+
else
|
251
|
+
raise "Remote ssh command (#{command}) failed on '#{target}'."
|
252
|
+
end
|
253
|
+
else
|
254
|
+
Kernel.system("#{ssh_command(port)} -T #{target} '#{command.gsub("'", "'\\\\''")}'")
|
255
|
+
$?.success? or raise "Remote ssh command (#{command}) failed on '#{target}'."
|
256
|
+
end
|
257
|
+
else
|
258
|
+
fail "Need a target to ssh to. Received none."
|
259
|
+
end
|
260
|
+
end
|
261
|
+
|
262
|
+
# Runs the command on the local host
|
263
|
+
#
|
264
|
+
# @param command [String] command to run on the target
|
265
|
+
# @return [true] Returns true if the command was successful
|
266
|
+
# @raise [RuntimeError] If the command fails an exception is raised
|
267
|
+
def local_command(command, workdir)
|
268
|
+
puts "Executing '#{command}' locally in #{workdir}"
|
269
|
+
Kernel.system(command, :chdir => workdir)
|
270
|
+
$?.success? or raise "Local command (#{command}) failed."
|
271
|
+
end
|
272
|
+
|
273
|
+
# Helper method that takes a template file and runs it through ERB
|
274
|
+
#
|
275
|
+
# @param erbfile [String] template to be evaluated
|
276
|
+
# @param b [Binding] binding to evaluate the template under
|
277
|
+
# @return [String] the evaluated template
|
278
|
+
def erb_string(erbfile, b = binding)
|
279
|
+
template = File.read(erbfile)
|
280
|
+
message = ERB.new(template, nil, "-")
|
281
|
+
message.result(b)
|
282
|
+
end
|
283
|
+
|
284
|
+
# Helper method that takes a template and writes the evaluated contents to a file on disk
|
285
|
+
#
|
286
|
+
# @param erbfile [String]
|
287
|
+
# @param outfile [String]
|
288
|
+
# @param remove_orig [true, false]
|
289
|
+
# @param opts [Hash]
|
290
|
+
def erb_file(erbfile, outfile = nil, remove_orig = false, opts = { :binding => binding })
|
291
|
+
outfile ||= File.join(Dir.mktmpdir, File.basename(erbfile).sub(File.extname(erbfile), ""))
|
292
|
+
output = erb_string(erbfile, opts[:binding])
|
293
|
+
File.open(outfile, 'w') { |f| f.write output }
|
294
|
+
puts "Generated: #{outfile}"
|
295
|
+
FileUtils.rm_rf erbfile if remove_orig
|
296
|
+
outfile
|
297
|
+
end
|
298
|
+
end
|
299
|
+
end
|
@@ -0,0 +1 @@
|
|
1
|
+
/opt/puppetlabs/puppet/bin/ruby -s mcollective -u root -a '/opt/puppetlabs/puppet/bin/mcollectived --config=/etc/puppetlabs/mcollective/server.cfg '
|
@@ -0,0 +1,103 @@
|
|
1
|
+
require 'vanagon/common/pathname'
|
2
|
+
|
3
|
+
describe "Vanagon::Common::Pathname" do
|
4
|
+
describe "#has_overrides?" do
|
5
|
+
it "is false for a pathname with just a path" do
|
6
|
+
dir = Vanagon::Common::Pathname.new("/a/b/c")
|
7
|
+
expect(dir.has_overrides?).to be(false)
|
8
|
+
end
|
9
|
+
|
10
|
+
it "is true if the pathname has more than a path set" do
|
11
|
+
dir = Vanagon::Common::Pathname.new("/a/b/c", mode: '0755')
|
12
|
+
expect(dir.has_overrides?).to be(true)
|
13
|
+
end
|
14
|
+
end
|
15
|
+
|
16
|
+
describe "#file" do
|
17
|
+
it 'creates a new Pathname instance, marked as a file' do
|
18
|
+
dir = Vanagon::Common::Pathname.file("/a/b/c/")
|
19
|
+
expect(dir.class).to eq(Vanagon::Common::Pathname)
|
20
|
+
expect(dir.configfile?).to eq(false)
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
24
|
+
describe "#configfile" do
|
25
|
+
it 'creates a new Pathname instance, marked as a configuration file' do
|
26
|
+
dir = Vanagon::Common::Pathname.configfile("/a/b/c/")
|
27
|
+
expect(dir.class).to eq(Vanagon::Common::Pathname)
|
28
|
+
expect(dir.configfile?).to eq(true)
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
32
|
+
describe "#initialize" do
|
33
|
+
it 'strips trailing slashes off of the path to normalize it' do
|
34
|
+
dir = Vanagon::Common::Pathname.new("/a/b/c/")
|
35
|
+
expect(dir.path).to eq("/a/b/c")
|
36
|
+
end
|
37
|
+
|
38
|
+
it 'removes extra / from the pathname to normalize it' do
|
39
|
+
dir = Vanagon::Common::Pathname.new("/a//b///c///")
|
40
|
+
expect(dir.path).to eq("/a/b/c")
|
41
|
+
end
|
42
|
+
end
|
43
|
+
|
44
|
+
describe "equality" do
|
45
|
+
it "is not equal if the paths differ" do
|
46
|
+
dir1 = Vanagon::Common::Pathname.new("/a/b/c")
|
47
|
+
dir2 = Vanagon::Common::Pathname.new("/a/b/c/d")
|
48
|
+
expect(dir1).not_to eq(dir2)
|
49
|
+
end
|
50
|
+
|
51
|
+
it "is not equal if there are different attributes set" do
|
52
|
+
dir1 = Vanagon::Common::Pathname.new("/a/b/c")
|
53
|
+
dir2 = Vanagon::Common::Pathname.new("/a/b/c", mode: '0123')
|
54
|
+
expect(dir1).not_to eq(dir2)
|
55
|
+
end
|
56
|
+
|
57
|
+
it "is equal if there are the same attributes set to the same values" do
|
58
|
+
dir1 = Vanagon::Common::Pathname.new("/a/b/c", mode: '0123')
|
59
|
+
dir2 = Vanagon::Common::Pathname.new("/a/b/c", mode: '0123')
|
60
|
+
expect(dir1).to eq(dir2)
|
61
|
+
end
|
62
|
+
|
63
|
+
it "is equal if the paths are the same and the only attribute set" do
|
64
|
+
dir1 = Vanagon::Common::Pathname.new("/a/b/c")
|
65
|
+
dir2 = Vanagon::Common::Pathname.new("/a/b/c")
|
66
|
+
expect(dir1).to eq(dir2)
|
67
|
+
end
|
68
|
+
end
|
69
|
+
|
70
|
+
describe "#hash" do
|
71
|
+
it "has the same hash is the attributes are the same" do
|
72
|
+
dir1 = Vanagon::Common::Pathname.new("/a/b/c", mode: '0123')
|
73
|
+
dir2 = Vanagon::Common::Pathname.new("/a/b/c", mode: '0123')
|
74
|
+
expect(dir1.hash).to eq(dir2.hash)
|
75
|
+
end
|
76
|
+
|
77
|
+
it "has different hashes if any attribute is different" do
|
78
|
+
dir1 = Vanagon::Common::Pathname.new("/a/b/c", mode: '0123', owner: 'alice')
|
79
|
+
dir2 = Vanagon::Common::Pathname.new("/a/b/c", mode: '0123', owner: 'bob')
|
80
|
+
expect(dir1.hash).to_not eq(dir2.hash)
|
81
|
+
end
|
82
|
+
end
|
83
|
+
|
84
|
+
describe "uniqueness of pathnames" do
|
85
|
+
it "should only add 1 Pathname object with the same attributes to a set" do
|
86
|
+
set = Set.new
|
87
|
+
dir1 = Vanagon::Common::Pathname.new("/a/b/c", mode: '0123')
|
88
|
+
dir2 = Vanagon::Common::Pathname.new("/a/b/c", mode: '0123')
|
89
|
+
dir3 = Vanagon::Common::Pathname.new("/a/b/c", mode: '0123', owner: 'alice')
|
90
|
+
set << dir1 << dir2 << dir3
|
91
|
+
expect(set.size).to eq(2)
|
92
|
+
end
|
93
|
+
|
94
|
+
it "should reduce an array to unique elements successfully" do
|
95
|
+
dir1 = Vanagon::Common::Pathname.new("/a/b/c", mode: '0123')
|
96
|
+
dir2 = Vanagon::Common::Pathname.new("/a/b/c", mode: '0123')
|
97
|
+
dir3 = Vanagon::Common::Pathname.new("/a/b/c", mode: '0123', owner: 'alice')
|
98
|
+
arr = [ dir1, dir2, dir3 ]
|
99
|
+
expect(arr.size).to eq(3)
|
100
|
+
expect(arr.uniq.size).to eq(2)
|
101
|
+
end
|
102
|
+
end
|
103
|
+
end
|
@@ -0,0 +1,36 @@
|
|
1
|
+
require 'vanagon/common/user'
|
2
|
+
|
3
|
+
describe 'Vanagon::Common::User' do
|
4
|
+
describe 'initialize' do
|
5
|
+
it 'group defaults to the name of the user' do
|
6
|
+
user = Vanagon::Common::User.new('willamette')
|
7
|
+
expect(user.group).to eq('willamette')
|
8
|
+
end
|
9
|
+
end
|
10
|
+
|
11
|
+
describe 'equality' do
|
12
|
+
it 'is not equal if the names differ' do
|
13
|
+
user1 = Vanagon::Common::User.new('willamette')
|
14
|
+
user2 = Vanagon::Common::User.new('columbia')
|
15
|
+
expect(user1).not_to eq(user2)
|
16
|
+
end
|
17
|
+
|
18
|
+
it 'is not equal if there are different attributes set' do
|
19
|
+
user1 = Vanagon::Common::User.new('willamette', 'group1')
|
20
|
+
user2 = Vanagon::Common::User.new('willamette', 'group2')
|
21
|
+
expect(user1).not_to eq(user2)
|
22
|
+
end
|
23
|
+
|
24
|
+
it 'is equal if there are the same attributes set to the same values' do
|
25
|
+
user1 = Vanagon::Common::User.new('willamette', 'group')
|
26
|
+
user2 = Vanagon::Common::User.new('willamette', 'group')
|
27
|
+
expect(user1).to eq(user2)
|
28
|
+
end
|
29
|
+
|
30
|
+
it 'is equal if the name are the same and the only attribute set' do
|
31
|
+
user1 = Vanagon::Common::User.new('willamette')
|
32
|
+
user2 = Vanagon::Common::User.new('willamette')
|
33
|
+
expect(user1).to eq(user2)
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|