frm 0.0.1 → 0.0.2
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.
- data/.gitignore +4 -0
- data/LICENSE +30 -0
- data/Rakefile +19 -0
- data/bin/fpm +91 -0
- data/lib/frm/deb.rb +327 -0
- data/lib/frm/s3.rb +89 -0
- data/lib/frm/version.rb +1 -1
- data/test/deb_test.rb +457 -0
- data/test/deb_test2.rb +31 -0
- data/test/s3.rb +56 -0
- metadata +15 -7
- data/frm/.gitignore +0 -4
data/.gitignore
CHANGED
data/LICENSE
ADDED
@@ -0,0 +1,30 @@
|
|
1
|
+
Copyright (c) 2012, Martin K. Rhoads and FRM Project Contributors.
|
2
|
+
All rights reserved.
|
3
|
+
|
4
|
+
Redistribution and use in source and binary forms, with or without
|
5
|
+
modification, are permitted provided that the following conditions are
|
6
|
+
met:
|
7
|
+
|
8
|
+
* Redistributions of source code must retain the above copyright
|
9
|
+
notice, this list of conditions and the following disclaimer.
|
10
|
+
|
11
|
+
* Redistributions in binary form must reproduce the above copyright
|
12
|
+
notice, this list of conditions and the following disclaimer in the
|
13
|
+
documentation and/or other materials provided with the distribution.
|
14
|
+
|
15
|
+
* Neither the name of the FRM Project, Martin K. Rhoads, nor the names
|
16
|
+
of its contributors may be used to endorse or promote products
|
17
|
+
derived from this software without specific prior written
|
18
|
+
permission.
|
19
|
+
|
20
|
+
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
|
21
|
+
IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
|
22
|
+
THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
23
|
+
PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
|
24
|
+
CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
25
|
+
EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
26
|
+
PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
27
|
+
PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
28
|
+
LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
29
|
+
NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
30
|
+
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
data/Rakefile
CHANGED
@@ -1,2 +1,21 @@
|
|
1
1
|
require 'bundler'
|
2
2
|
Bundler::GemHelper.install_tasks
|
3
|
+
|
4
|
+
fpm_base = File.dirname __FILE__
|
5
|
+
|
6
|
+
namespace :bump do
|
7
|
+
|
8
|
+
desc "bump the patch version number"
|
9
|
+
task :patch do
|
10
|
+
version_file_path = File.join fpm_base, 'lib', 'frm', 'version.rb'
|
11
|
+
current_version_file = File.read version_file_path
|
12
|
+
current_version_file =~ /VERSION[^\d]+(\d+)\.(\d+)\.(\d+)(\.([^'"]*))?/
|
13
|
+
major,minor,patch = $1, $2, $3
|
14
|
+
new_version = [$1,$2,$3.to_i+1].join('.')
|
15
|
+
new_version_file = current_version_file.sub /VERSION\s*=.*/, %Q{VERSION = "#{new_version}"}
|
16
|
+
File.open(version_file_path, 'w') {|f| f.write(new_version_file) }
|
17
|
+
puts "bumping version to #{new_version}"
|
18
|
+
end
|
19
|
+
|
20
|
+
end
|
21
|
+
|
data/bin/fpm
ADDED
@@ -0,0 +1,91 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
# This is the CLI interface into Effin Repo Manager
|
3
|
+
|
4
|
+
require 'optparse'
|
5
|
+
|
6
|
+
# This hash will hold all of the options
|
7
|
+
# parsed from the command-line by
|
8
|
+
# OptionParser.
|
9
|
+
options = {}
|
10
|
+
|
11
|
+
packages = []
|
12
|
+
|
13
|
+
def print_and_exit(message)
|
14
|
+
puts
|
15
|
+
puts message
|
16
|
+
puts
|
17
|
+
puts `#{__FILE__} -h`
|
18
|
+
exit 1
|
19
|
+
end
|
20
|
+
|
21
|
+
optparse = OptionParser.new do|opts|
|
22
|
+
opts.banner = "Usage: frm.rb [options] package1 [package2]B ..."
|
23
|
+
|
24
|
+
options[:access_key] = nil
|
25
|
+
opts.on( '-a', '--access-key ACCESS_KEY', 'S3 public access key' ) do |key|
|
26
|
+
options[:access_key] = key
|
27
|
+
end
|
28
|
+
|
29
|
+
|
30
|
+
options[:secret_key] = nil
|
31
|
+
opts.on( '-s', '--secret-key SECRET_KEY', 'S3 private access key' ) do |key|
|
32
|
+
options[:secret_key] = key
|
33
|
+
end
|
34
|
+
|
35
|
+
options[:bucket] = nil
|
36
|
+
opts.on( '-b', '--bucket BUCKET', 'S3 bucket' ) do |bucket|
|
37
|
+
options[:bucket] = bucket
|
38
|
+
end
|
39
|
+
|
40
|
+
options[:prefix] = nil
|
41
|
+
opts.on( '-p', '--prefix PREFIX', 'S3 prefix of repostory' ) do |prefix|
|
42
|
+
options[:prefix] = prefix
|
43
|
+
end
|
44
|
+
|
45
|
+
|
46
|
+
# This displays the help screen, all programs are
|
47
|
+
# assumed to have this option.
|
48
|
+
opts.on( '-h', '--help', 'Display this screen' ) do
|
49
|
+
puts opts
|
50
|
+
exit
|
51
|
+
end
|
52
|
+
end
|
53
|
+
|
54
|
+
optparse.parse!
|
55
|
+
|
56
|
+
|
57
|
+
ARGV.each do |package|
|
58
|
+
packages << package
|
59
|
+
end
|
60
|
+
|
61
|
+
|
62
|
+
# verify that the required inputs are set
|
63
|
+
%w{access_key secret_key bucket prefix }.each do |input|
|
64
|
+
print_and_exit "you must specify the #{input} parameter!!!" if options.values_at(input.to_sym) == [nil]
|
65
|
+
end
|
66
|
+
|
67
|
+
# verify that we have at least one package to install
|
68
|
+
print_and_exit "you need to specify at least one package to publish!!!" if packages.empty?
|
69
|
+
|
70
|
+
packages.each do |package|
|
71
|
+
print_and_exit "package '#{package}' does not exits!!!" unless File.exists?(package)
|
72
|
+
print_and_exit "package '#{package}' does not appear to be a valid deb" unless system("dpkg --field #{package} > /dev/null 2>&1 ")
|
73
|
+
end
|
74
|
+
|
75
|
+
|
76
|
+
# if we have gotten this far it means that all required parameters have been set, so let's begin
|
77
|
+
|
78
|
+
|
79
|
+
# chdir to the top level of the code
|
80
|
+
Dir.chdir(File.dirname(File.dirname(__FILE__)))
|
81
|
+
|
82
|
+
# require the necessary FRM libs
|
83
|
+
require File.join Dir.pwd, 'lib', 'deb'
|
84
|
+
|
85
|
+
puts "creating release..."
|
86
|
+
package_release = FRM::PackageRelease.new(packages)
|
87
|
+
|
88
|
+
puts "pushing release..."
|
89
|
+
release_pusher = FRM::ReleasePusher.new(package_release,options[:access_key],options[:secret_key],options[:bucket],options[:prefix])
|
90
|
+
|
91
|
+
puts "looks like everything ran ok!"
|
data/lib/frm/deb.rb
ADDED
@@ -0,0 +1,327 @@
|
|
1
|
+
DEFAULT_HOST = 's3-us-west-1.amazonaws.com' # stupid hack to point to
|
2
|
+
# the right region
|
3
|
+
|
4
|
+
module FRM
|
5
|
+
|
6
|
+
|
7
|
+
class Base
|
8
|
+
my_dir = File.dirname __FILE__
|
9
|
+
require File.join my_dir, 's3'
|
10
|
+
require 'zlib'
|
11
|
+
require 'tempfile'
|
12
|
+
require 'digest/md5'
|
13
|
+
require 'digest/sha1'
|
14
|
+
require 'digest/sha2'
|
15
|
+
|
16
|
+
def compute_md5(string)
|
17
|
+
Digest::MD5.hexdigest(string)
|
18
|
+
end
|
19
|
+
|
20
|
+
def compute_sha1(string)
|
21
|
+
Digest::SHA1.hexdigest(string)
|
22
|
+
end
|
23
|
+
|
24
|
+
def compute_sha2(string)
|
25
|
+
Digest::SHA2.hexdigest(string)
|
26
|
+
end
|
27
|
+
|
28
|
+
# TODO:
|
29
|
+
# there has to be a better way to use gpg withen ruby. found many
|
30
|
+
# broken solutions :\
|
31
|
+
def gpg_clearsign(message)
|
32
|
+
`echo "#{message}" | gpg --clearsign`
|
33
|
+
end
|
34
|
+
|
35
|
+
# TODO: same as above
|
36
|
+
def gpg_detached(message)
|
37
|
+
`echo "#{message}" | gpg -abs`
|
38
|
+
end
|
39
|
+
|
40
|
+
|
41
|
+
def generate_gzip_pipe(contents)
|
42
|
+
read_buffer, write_buffer = IO.pipe
|
43
|
+
gzip_writer = Zlib::GzipWriter.new write_buffer
|
44
|
+
gzip_writer.mtime = 1 # ensure that the header is determinstic
|
45
|
+
gzip_writer.write contents
|
46
|
+
gzip_writer.close
|
47
|
+
read_buffer
|
48
|
+
end
|
49
|
+
|
50
|
+
def gunzip_pipe(gziped_pipe)
|
51
|
+
gzip_reader = Zlib::GzipReader.new gziped_pipe
|
52
|
+
unzipped_string = gzip_reader.read
|
53
|
+
gzip_reader.close
|
54
|
+
return unzipped_string
|
55
|
+
end
|
56
|
+
|
57
|
+
def parse_package_stub(read_buffer)
|
58
|
+
package = {}
|
59
|
+
stub = ""
|
60
|
+
while line = read_buffer.gets
|
61
|
+
return nil if line.strip.empty?
|
62
|
+
raise "bad input" unless (match = line.match /^\w+\-?\w+?: /)
|
63
|
+
stub << line
|
64
|
+
key = match[0].delete ': ' # if match
|
65
|
+
value = match.post_match.strip
|
66
|
+
package[key] = value
|
67
|
+
if key == 'Description'
|
68
|
+
while (line = read_buffer.gets).strip != ""
|
69
|
+
package['Description'] << line
|
70
|
+
stub << line
|
71
|
+
end
|
72
|
+
package['Description'].rstrip!
|
73
|
+
return package, stub
|
74
|
+
end
|
75
|
+
end
|
76
|
+
nil
|
77
|
+
end
|
78
|
+
|
79
|
+
def merge_package_file(in_pipe,out_pipe,package_list)
|
80
|
+
sorted_list = package_list.sort { |a,b| a['Package'] <=> b['Package'] }
|
81
|
+
while (next_stub = parse_package_stub in_pipe)
|
82
|
+
STDERR.puts "next_stub[0] = #{next_stub[0]}"
|
83
|
+
end
|
84
|
+
end
|
85
|
+
end
|
86
|
+
|
87
|
+
|
88
|
+
class Package < Base
|
89
|
+
attr_accessor :repo_filename
|
90
|
+
attr_reader :path, :content, :md5, :sha1, :sha2 , :size
|
91
|
+
def initialize(path)
|
92
|
+
@path = path
|
93
|
+
raise "Can not find file '#{path}'" unless File.exists?(path)
|
94
|
+
begin
|
95
|
+
@content = File.read(path)
|
96
|
+
rescue Object => o
|
97
|
+
STDERR.puts "Could not open file '#{path}'. Exiting..."
|
98
|
+
STDERR.puts o.inspect
|
99
|
+
STDERR.puts o.backtrace
|
100
|
+
raise "Could not open file '#{path}'. Exiting..."
|
101
|
+
end
|
102
|
+
@size = File.size(@path)
|
103
|
+
@md5 = compute_md5(@content)
|
104
|
+
@sha1 = compute_sha1(@content)
|
105
|
+
@sha2 = compute_sha2(@content)
|
106
|
+
end
|
107
|
+
end
|
108
|
+
|
109
|
+
class PackageRelease < Base
|
110
|
+
attr_reader :packages, :standards_version, :priority, :package_file, :gzipped_package_file, :release_file, :short_release_file, :component
|
111
|
+
def initialize(packages={},component='main/binary-amd64')
|
112
|
+
@component = component
|
113
|
+
@standards_version = standards_version
|
114
|
+
@priority = priority
|
115
|
+
@packages = []
|
116
|
+
packages.each { |package| @packages << Package.new(package) }
|
117
|
+
@package_file = generate_package_file
|
118
|
+
@gzipped_package_file = generate_gzip_pipe(@package_file).read
|
119
|
+
@short_release_file = generate_short_release_file
|
120
|
+
@release_file = generate_release_file
|
121
|
+
end
|
122
|
+
|
123
|
+
private
|
124
|
+
|
125
|
+
def generate_release_file()
|
126
|
+
partial_release_file = "Origin: apt.cloudscaling.com
|
127
|
+
Label: apt repository natty
|
128
|
+
Codename: natty
|
129
|
+
Date: Thu, 22 Dec 2011 00:29:55 UTC
|
130
|
+
Architectures: amd64
|
131
|
+
Components: main universe multiverse
|
132
|
+
Description: Cloudscaling APT repository
|
133
|
+
MD5Sum:
|
134
|
+
#{compute_md5(@package_file)} #{@package_file.size} #{@component}/Packages
|
135
|
+
#{compute_md5(@gzipped_package_file)} #{@gzipped_package_file.size} #{@component}/Packages.gz
|
136
|
+
#{compute_md5(@short_release_file)} #{@short_release_file.size} #{@component}/Release
|
137
|
+
SHA1:
|
138
|
+
#{compute_sha1(@package_file)} #{@package_file.size} #{@component}/Packages
|
139
|
+
#{compute_sha1(@gzipped_package_file)} #{@gzipped_package_file.size} #{@component}/Packages.gz
|
140
|
+
#{compute_sha1(@short_release_file)} #{@short_release_file.size} #{@component}/Release
|
141
|
+
SHA256:
|
142
|
+
#{compute_sha2(@package_file)} #{@package_file.size} #{@component}/Packages
|
143
|
+
#{compute_sha2(@gzipped_package_file)} #{@gzipped_package_file.size} #{@component}/Packages.gz
|
144
|
+
#{compute_sha2(@short_release_file)} #{@short_release_file.size} #{@component}/Release
|
145
|
+
"
|
146
|
+
return partial_release_file
|
147
|
+
end
|
148
|
+
|
149
|
+
def generate_short_release_file
|
150
|
+
"Component: main
|
151
|
+
Origin: apt.cloudscaling.com
|
152
|
+
Label: apt repository natty
|
153
|
+
Architecture: amd64
|
154
|
+
Description: Cloudscaling APT repository
|
155
|
+
"
|
156
|
+
end
|
157
|
+
|
158
|
+
|
159
|
+
def filename(package)
|
160
|
+
filename = File.basename package.path
|
161
|
+
shortname = `dpkg --field #{package.path} Package`.chomp
|
162
|
+
first_letter = shortname[0]
|
163
|
+
package.repo_filename = "pool/main/#{first_letter}/#{shortname}/#{filename}"
|
164
|
+
end
|
165
|
+
|
166
|
+
def generate_package_file()
|
167
|
+
package_file = ''
|
168
|
+
@packages.each { |package| package_file << generate_package_stub(package) }
|
169
|
+
return package_file
|
170
|
+
end
|
171
|
+
|
172
|
+
def generate_package_stub(package)
|
173
|
+
package_stub = ''
|
174
|
+
package_stub << `dpkg --field #{package.path}`
|
175
|
+
package_stub << "Filename: #{filename(package)}\n"
|
176
|
+
package_stub << "Size: #{package.size}\n"
|
177
|
+
package_stub << "MD5sum: #{package.md5}\n"
|
178
|
+
package_stub << "SHA1: #{package.sha1}\n"
|
179
|
+
package_stub << "SHA256: #{package.sha2}\n"
|
180
|
+
package_stub << "\n"
|
181
|
+
return package_stub
|
182
|
+
end
|
183
|
+
end
|
184
|
+
|
185
|
+
class ReleasePusher < Base
|
186
|
+
def initialize(package_release,access_key,secret_key,bucket,prefix,server='s3-us-west-1.amazonaws.com')
|
187
|
+
@bucket = bucket
|
188
|
+
@prefix = prefix
|
189
|
+
@s3 = FRM::S3.new(access_key,secret_key,server)
|
190
|
+
push_packages(package_release.packages)
|
191
|
+
push_release_files(package_release)
|
192
|
+
end
|
193
|
+
|
194
|
+
private
|
195
|
+
|
196
|
+
|
197
|
+
def push_release_files(package_release)
|
198
|
+
# TODO: un-hardcode this
|
199
|
+
release_path = @prefix + "/dists/natty/Release"
|
200
|
+
@s3.put(release_path,package_release.release_file,@bucket)
|
201
|
+
|
202
|
+
in_release_path = @prefix + "/dists/natty/InRelease"
|
203
|
+
@s3.put(in_release_path,gpg_clearsign(package_release.release_file),@bucket)
|
204
|
+
|
205
|
+
gpg_release_path = @prefix + "/dists/natty/Release.gpg"
|
206
|
+
@s3.put(gpg_release_path,gpg_detached(package_release.release_file),@bucket)
|
207
|
+
|
208
|
+
release_file_path = @prefix + "/dists/natty/" + package_release.component
|
209
|
+
@s3.put(release_file_path + '/Release',package_release.short_release_file,@bucket)
|
210
|
+
@s3.put(release_file_path + '/Packages',package_release.package_file,@bucket)
|
211
|
+
@s3.put(release_file_path + '/Packages.gz',package_release.gzipped_package_file,@bucket)
|
212
|
+
end
|
213
|
+
|
214
|
+
|
215
|
+
def push_packages(packages)
|
216
|
+
packages.each { |package| push_package(package) }
|
217
|
+
end
|
218
|
+
|
219
|
+
def push_package(package)
|
220
|
+
remote_path = @prefix + '/' + package.repo_filename
|
221
|
+
@s3.put(remote_path,package.content,@bucket)
|
222
|
+
end
|
223
|
+
|
224
|
+
|
225
|
+
end
|
226
|
+
|
227
|
+
|
228
|
+
|
229
|
+
class Deb < Base
|
230
|
+
|
231
|
+
def initialize()
|
232
|
+
end
|
233
|
+
|
234
|
+
def generate_package_file(in_packages=[])
|
235
|
+
packages = in_packages.dup
|
236
|
+
package_file = ''
|
237
|
+
packages.each { |package| package_file << generate_package_stub(package) }
|
238
|
+
return package_file
|
239
|
+
end
|
240
|
+
|
241
|
+
|
242
|
+
def generate_package_stub(in_package={})
|
243
|
+
package = in_package.dup
|
244
|
+
package_stub = ''
|
245
|
+
description = package.delete('Description') || "no description given"
|
246
|
+
path_to_deb = package.delete 'path_to_deb'
|
247
|
+
section = package.delete 'section'
|
248
|
+
package["Filename"] = "pool/#{section}/#{package['Package'][0]}/#{package['Package']}/#{package['Package']}_#{package['Version']}_#{package['Architecture']}.deb"
|
249
|
+
package["Size"] = File.new(path_to_deb).size
|
250
|
+
package["MD5sum"] = self.compute_md5 File.read path_to_deb
|
251
|
+
package["SHA1"] = compute_sha1 File.read path_to_deb
|
252
|
+
package["SHA256"] = compute_sha2 File.read path_to_deb
|
253
|
+
package["Description"] = description
|
254
|
+
package.each { |key,value| package_stub << generate_package_line(key,value) }
|
255
|
+
package_stub << "\n"
|
256
|
+
return package_stub
|
257
|
+
end
|
258
|
+
|
259
|
+
|
260
|
+
def generate_package_release
|
261
|
+
return "Component: main
|
262
|
+
Origin: apt.cloudscaling.com
|
263
|
+
Label: apt repository natty
|
264
|
+
Architecture: amd64
|
265
|
+
Description: Cloudscaling APT repository
|
266
|
+
"
|
267
|
+
end
|
268
|
+
|
269
|
+
|
270
|
+
def generate_release
|
271
|
+
return "Origin: apt.cloudscaling.com
|
272
|
+
Label: apt repository natty
|
273
|
+
Codename: natty
|
274
|
+
Date: Thu, 22 Dec 2011 00:29:55 UTC
|
275
|
+
Architectures: amd64
|
276
|
+
Components: main universe multiverse
|
277
|
+
Description: Cloudscaling APT repository
|
278
|
+
MD5Sum:
|
279
|
+
a4b943ff89790ccdc186875dad67827b 5813 main/binary-amd64/Packages
|
280
|
+
004fd3f868ebbe7501fb2e1c0c54e2a7 2148 main/binary-amd64/Packages.gz
|
281
|
+
79dd2fee35fba7255dcd40e1f6529591 134 main/binary-amd64/Release
|
282
|
+
d41d8cd98f00b204e9800998ecf8427e 0 universe/binary-amd64/Packages
|
283
|
+
7029066c27ac6f5ef18d660d5741979a 20 universe/binary-amd64/Packages.gz
|
284
|
+
018c8e37146b908a6bde46012a83d4ba 138 universe/binary-amd64/Release
|
285
|
+
d41d8cd98f00b204e9800998ecf8427e 0 multiverse/binary-amd64/Packages
|
286
|
+
7029066c27ac6f5ef18d660d5741979a 20 multiverse/binary-amd64/Packages.gz
|
287
|
+
4680f88c741bad22529909db5be4f608 140 multiverse/binary-amd64/Release
|
288
|
+
SHA1:
|
289
|
+
6e03924030eab56cb9735a52ec710537e682bcfc 5813 main/binary-amd64/Packages
|
290
|
+
5f2989bae96e148cb5f18accc4357305926ab1e1 2148 main/binary-amd64/Packages.gz
|
291
|
+
6d932af9af761f418e5374f73dcd09badb4fe57e 134 main/binary-amd64/Release
|
292
|
+
da39a3ee5e6b4b0d3255bfef95601890afd80709 0 universe/binary-amd64/Packages
|
293
|
+
46c6643f07aa7f6bfe7118de926b86defc5087c4 20 universe/binary-amd64/Packages.gz
|
294
|
+
4d428e7ad434df47cffc40cabf8e238ee76ea434 138 universe/binary-amd64/Release
|
295
|
+
da39a3ee5e6b4b0d3255bfef95601890afd80709 0 multiverse/binary-amd64/Packages
|
296
|
+
46c6643f07aa7f6bfe7118de926b86defc5087c4 20 multiverse/binary-amd64/Packages.gz
|
297
|
+
c8a7d2eb24ece57d460106506fcff99cb2ada015 140 multiverse/binary-amd64/Release
|
298
|
+
SHA256:
|
299
|
+
dd8283f06beb4a5fc06ac62d3ae098e5ba2717daef2a15b5f3e9233eb64e0227 5813 main/binary-amd64/Packages
|
300
|
+
b197c5a3c1fe6a6d286e9f066a0cade289e3a2fc485c90407179951634788aa8 2148 main/binary-amd64/Packages.gz
|
301
|
+
690b44df6fe65f40f260b73394e87804df78c9ccf13999889259faeed3eec40d 134 main/binary-amd64/Release
|
302
|
+
e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855 0 universe/binary-amd64/Packages
|
303
|
+
59869db34853933b239f1e2219cf7d431da006aa919635478511fabbfc8849d2 20 universe/binary-amd64/Packages.gz
|
304
|
+
32f35b1fc2bdc5a11b53abeadaaa77771b15acb5305777484bf4390d697ae5bd 138 universe/binary-amd64/Release
|
305
|
+
e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855 0 multiverse/binary-amd64/Packages
|
306
|
+
59869db34853933b239f1e2219cf7d431da006aa919635478511fabbfc8849d2 20 multiverse/binary-amd64/Packages.gz
|
307
|
+
f29816e3a4f90a8b4c688fdb2ac3056d5fb7349857c9ea8da2fbccf8e931baca 140 multiverse/binary-amd64/Release"
|
308
|
+
end
|
309
|
+
|
310
|
+
|
311
|
+
def generate_package_line(key='',value='')
|
312
|
+
valid_options = %w{Package Version Architecture Maintainer Standards-Version Homepage Priority Depends Filename Size SHA256 SHA1 MD5sum Description}
|
313
|
+
raise "Bogus option passed: #{key}" unless valid_options.include?(key)
|
314
|
+
|
315
|
+
case key
|
316
|
+
when 'Depends'
|
317
|
+
return "Depends: #{value.join(', ')}\n"
|
318
|
+
when 'Maintainer'
|
319
|
+
return "Maintainer: <#{value}>\n"
|
320
|
+
else
|
321
|
+
return "#{key}: #{value}\n"
|
322
|
+
end
|
323
|
+
end
|
324
|
+
|
325
|
+
end
|
326
|
+
|
327
|
+
end
|
data/lib/frm/s3.rb
ADDED
@@ -0,0 +1,89 @@
|
|
1
|
+
my_dir = File.dirname __FILE__
|
2
|
+
STDERR.puts "#{File.join my_dir, 's3'}"
|
3
|
+
require File.join my_dir, 'base'
|
4
|
+
|
5
|
+
|
6
|
+
module FRM
|
7
|
+
class S3 < Base
|
8
|
+
attr_reader :max_retries
|
9
|
+
@connection
|
10
|
+
def initialize(access_key_id,secret_access_key,server='s3.amazonaws.com')
|
11
|
+
require 'aws/s3'
|
12
|
+
@max_retries = 10
|
13
|
+
@connection = AWS::S3::Base.establish_connection!(:access_key_id => access_key_id,
|
14
|
+
:secret_access_key => secret_access_key,
|
15
|
+
:server => server )
|
16
|
+
end
|
17
|
+
|
18
|
+
def key?(key,bucket)
|
19
|
+
AWS::S3::S3Object.exists?(key,bucket)
|
20
|
+
end
|
21
|
+
|
22
|
+
def put(key,value,bucket)
|
23
|
+
@max_retries.times do |i|
|
24
|
+
begin
|
25
|
+
AWS::S3::S3Object.store(key,value,bucket,:server => 's3-us-west-1.amazonaws.com',:access => :public_read)
|
26
|
+
return true
|
27
|
+
rescue Object => o
|
28
|
+
print_retry(__method__,o)
|
29
|
+
end
|
30
|
+
raise "could not put object!!!" if i == (@max_retries - 1)
|
31
|
+
end
|
32
|
+
raise "could not put object!!!"
|
33
|
+
end
|
34
|
+
|
35
|
+
def get(key,bucket)
|
36
|
+
@max_retries.times do |i|
|
37
|
+
begin
|
38
|
+
value = AWS::S3::S3Object.value(key,bucket)
|
39
|
+
return value
|
40
|
+
rescue Object => o
|
41
|
+
print_retry(__method__,o)
|
42
|
+
end
|
43
|
+
raise "could not get object!!!" if i == (@max_retries - 1)
|
44
|
+
end
|
45
|
+
raise "could not get object!!!"
|
46
|
+
end
|
47
|
+
|
48
|
+
def get_stream(key,bucket)
|
49
|
+
@max_retries.times do |i|
|
50
|
+
begin
|
51
|
+
stream = AWS::S3::S3Object.stream(key,bucket)
|
52
|
+
return stream
|
53
|
+
rescue Object => o
|
54
|
+
print_retry(__method__,o)
|
55
|
+
end
|
56
|
+
raise "could not get object!!!" if i == (@max_retries - 1)
|
57
|
+
end
|
58
|
+
raise "could not get object!!!"
|
59
|
+
end
|
60
|
+
|
61
|
+
def delete(key,bucket)
|
62
|
+
begin
|
63
|
+
AWS::S3::S3Object.delete(key,bucket)
|
64
|
+
true
|
65
|
+
rescue Object => o
|
66
|
+
print_retry(__method__,o)
|
67
|
+
end
|
68
|
+
end
|
69
|
+
|
70
|
+
def move(old_key,new_key,vucket)
|
71
|
+
begin
|
72
|
+
AWS::S3::S3Object.rename(old_key,new_key,bucket)
|
73
|
+
return
|
74
|
+
rescue Object => o
|
75
|
+
print_retry(__method__,o)
|
76
|
+
end
|
77
|
+
end
|
78
|
+
|
79
|
+
protected
|
80
|
+
|
81
|
+
def print_retry(action,error)
|
82
|
+
STDERR.puts "coudld not #{action} object because of:"
|
83
|
+
STDERR.puts error.inspect
|
84
|
+
STDERR.puts ", retrying..."
|
85
|
+
sleep 2
|
86
|
+
end
|
87
|
+
|
88
|
+
end
|
89
|
+
end
|
data/lib/frm/version.rb
CHANGED
data/test/deb_test.rb
ADDED
@@ -0,0 +1,457 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
|
3
|
+
require 'minitest/autorun'
|
4
|
+
|
5
|
+
my_dir = File.dirname __FILE__
|
6
|
+
require File.join my_dir, 'deb'
|
7
|
+
|
8
|
+
class TestReleasePusher < MiniTest::Unit::TestCase
|
9
|
+
def setup
|
10
|
+
@tempfile1 = File.open('/tmp/foo_1.2.68_amd64.deb','w+') { |f| f.write 'foo' }
|
11
|
+
@tempfile2 = File.open('/tmp/bar_1.2.3.4_amd64.deb','w+') { |f| f.write 'bar' }
|
12
|
+
@tempfile3 = File.open('/tmp/martin_1.2.3.4_amd64.deb','w+') { |f| f.write 'martin' }
|
13
|
+
|
14
|
+
hashes = [{
|
15
|
+
"Package" => "foo",
|
16
|
+
"Version" => "1.2.68",
|
17
|
+
"Architecture" => "amd64",
|
18
|
+
"Maintainer" => "support@cloudscaling.com",
|
19
|
+
"Homepage" => "http://www.cloudscaling.com",
|
20
|
+
"Priority" => "extra",
|
21
|
+
"Depends" => %w{one two three},
|
22
|
+
"section" => "main",
|
23
|
+
"path_to_deb" => '/tmp/foo_1.2.68_amd64.deb',
|
24
|
+
"Description" => 'some
|
25
|
+
multiline
|
26
|
+
description'
|
27
|
+
},
|
28
|
+
{
|
29
|
+
"Package" => "bar",
|
30
|
+
"Version" => "1.2.3.4",
|
31
|
+
"Architecture" => "amd64",
|
32
|
+
"Maintainer" => "support@cloudscaling.com",
|
33
|
+
"Homepage" => "http://www.cloudscaling.com",
|
34
|
+
"Priority" => "extra",
|
35
|
+
"Depends" => %w{one two three},
|
36
|
+
"section" => "main",
|
37
|
+
"path_to_deb" => '/tmp/bar_1.2.3.4_amd64.deb'
|
38
|
+
},
|
39
|
+
{
|
40
|
+
"Package" => "martin",
|
41
|
+
"Version" => "1.2.3.4",
|
42
|
+
"Architecture" => "amd64",
|
43
|
+
"Maintainer" => "support@cloudscaling.com",
|
44
|
+
"Homepage" => "http://www.cloudscaling.com",
|
45
|
+
"Priority" => "extra",
|
46
|
+
"section" => "main",
|
47
|
+
"path_to_deb" => '/tmp/martin_1.2.3.4_amd64.deb'
|
48
|
+
},
|
49
|
+
{
|
50
|
+
"Package" => "cs-chef",
|
51
|
+
"Version" => "1.2.3.4",
|
52
|
+
"Architecture" => "amd64",
|
53
|
+
"Maintainer" => "support@cloudscaling.com",
|
54
|
+
"Homepage" => "http://www.cloudscaling.com",
|
55
|
+
"Priority" => "extra",
|
56
|
+
"section" => "main",
|
57
|
+
"path_to_deb" => '/tmp/debs/cs-chef-0.9.1-1782-all.deb'
|
58
|
+
}
|
59
|
+
]
|
60
|
+
|
61
|
+
@package_release = FRM::PackageRelease.new(hashes)
|
62
|
+
@release_pusher = FRM::ReleasePusher.new(@package_release,'abcd','1234',\
|
63
|
+
'some-bucket','testing/tmp/martin/foo')
|
64
|
+
end
|
65
|
+
|
66
|
+
def test
|
67
|
+
puts "@release_pusher.inspect = #{@release_pusher.inspect}"
|
68
|
+
end
|
69
|
+
|
70
|
+
end
|
71
|
+
|
72
|
+
class TestPackageRelease < MiniTest::Unit::TestCase
|
73
|
+
def setup
|
74
|
+
@tempfile1 = File.open('/tmp/foo_1.2.68_amd64.deb','w+') { |f| f.write 'foo' }
|
75
|
+
@tempfile2 = File.open('/tmp/bar_1.2.3.4_amd64.deb','w+') { |f| f.write 'bar' }
|
76
|
+
|
77
|
+
hashes = [{
|
78
|
+
"Package" => "foo",
|
79
|
+
"Version" => "1.2.68",
|
80
|
+
"Architecture" => "amd64",
|
81
|
+
"Maintainer" => "support@cloudscaling.com",
|
82
|
+
"Homepage" => "http://www.cloudscaling.com",
|
83
|
+
"Priority" => "extra",
|
84
|
+
"Depends" => %w{one two three},
|
85
|
+
"section" => "main",
|
86
|
+
"path_to_deb" => '/tmp/foo_1.2.68_amd64.deb',
|
87
|
+
"Description" => 'some
|
88
|
+
multiline
|
89
|
+
description'
|
90
|
+
},
|
91
|
+
{
|
92
|
+
"Package" => "bar",
|
93
|
+
"Version" => "1.2.3.4",
|
94
|
+
"Architecture" => "amd64",
|
95
|
+
"Maintainer" => "support@cloudscaling.com",
|
96
|
+
"Homepage" => "http://www.cloudscaling.com",
|
97
|
+
"Priority" => "extra",
|
98
|
+
"Depends" => %w{one two three},
|
99
|
+
"section" => "main",
|
100
|
+
"path_to_deb" => '/tmp/bar_1.2.3.4_amd64.deb'
|
101
|
+
}
|
102
|
+
]
|
103
|
+
|
104
|
+
@package_release = FRM::PackageRelease.new(hashes)
|
105
|
+
end
|
106
|
+
|
107
|
+
def test()
|
108
|
+
correct_output = "Package: foo
|
109
|
+
Version: 1.2.68
|
110
|
+
Architecture: amd64
|
111
|
+
Maintainer: <support@cloudscaling.com>
|
112
|
+
Standards-Version: 3.9.1
|
113
|
+
Homepage: http://www.cloudscaling.com
|
114
|
+
Priority: extra
|
115
|
+
Depends: one, two, three
|
116
|
+
Filename: pool/main/f/foo/foo_1.2.68_amd64.deb
|
117
|
+
Size: 3
|
118
|
+
MD5sum: acbd18db4cc2f85cedef654fccc4a4d8
|
119
|
+
SHA1: 0beec7b5ea3f0fdbc95d0dd47f3c5bc275da8a33
|
120
|
+
SHA256: 2c26b46b68ffc68ff99b453c1d30413413422d706483bfa0f98a5e886266e7ae
|
121
|
+
Description: some
|
122
|
+
multiline
|
123
|
+
description
|
124
|
+
|
125
|
+
Package: bar
|
126
|
+
Version: 1.2.3.4
|
127
|
+
Architecture: amd64
|
128
|
+
Maintainer: <support@cloudscaling.com>
|
129
|
+
Standards-Version: 3.9.1
|
130
|
+
Homepage: http://www.cloudscaling.com
|
131
|
+
Priority: extra
|
132
|
+
Depends: one, two, three
|
133
|
+
Filename: pool/main/b/bar/bar_1.2.3.4_amd64.deb
|
134
|
+
Size: 3
|
135
|
+
MD5sum: 37b51d194a7513e45b56f6524f2d51f2
|
136
|
+
SHA1: 62cdb7020ff920e5aa642c3d4066950dd1f01f4d
|
137
|
+
SHA256: fcde2b2edba56bf408601fb721fe9b5c338d10ee429ea04fae5511b68fbf8fb9
|
138
|
+
Description: no description given
|
139
|
+
|
140
|
+
"
|
141
|
+
assert @package_release.package_file == correct_output
|
142
|
+
end
|
143
|
+
|
144
|
+
def test_generate_short_release_file
|
145
|
+
correct_short_release_file = "Component: main
|
146
|
+
Origin: apt.cloudscaling.com
|
147
|
+
Label: apt repository natty
|
148
|
+
Architecture: amd64
|
149
|
+
Description: Cloudscaling APT repository
|
150
|
+
"
|
151
|
+
assert @package_release.short_release_file == correct_short_release_file
|
152
|
+
end
|
153
|
+
|
154
|
+
def test_generate_release
|
155
|
+
# skip 'need to finish generate_release function'
|
156
|
+
correct_release_file = "Origin: apt.cloudscaling.com
|
157
|
+
Label: apt repository natty
|
158
|
+
Codename: natty
|
159
|
+
Date: Thu, 22 Dec 2011 00:29:55 UTC
|
160
|
+
Architectures: amd64
|
161
|
+
Components: main universe multiverse
|
162
|
+
Description: Cloudscaling APT repository
|
163
|
+
MD5Sum:
|
164
|
+
32aed966f2f629d6229d14cd37da740e 896 main/binary-amd64/Packages
|
165
|
+
a2ea734a1d863873d0acd98845bd0573 438 main/binary-amd64/Packages.gz
|
166
|
+
79dd2fee35fba7255dcd40e1f6529591 134 main/binary-amd64/Release
|
167
|
+
SHA1:
|
168
|
+
b2f872140a4e651609c1ce7538dba871a4ad49de 896 main/binary-amd64/Packages
|
169
|
+
86b1fc7c8905cf35a9ff2544bb277c332e93b7d1 438 main/binary-amd64/Packages.gz
|
170
|
+
6d932af9af761f418e5374f73dcd09badb4fe57e 134 main/binary-amd64/Release
|
171
|
+
SHA256:
|
172
|
+
14139ad7300259e51e2c0d75891966d10f9382adbda61c7348990ccf125e4d4f 896 main/binary-amd64/Packages
|
173
|
+
67014ee7cc96108af726aae5636d26225c2cd833301765e44cf6cb6ea7719698 438 main/binary-amd64/Packages.gz
|
174
|
+
690b44df6fe65f40f260b73394e87804df78c9ccf13999889259faeed3eec40d 134 main/binary-amd64/Release
|
175
|
+
"
|
176
|
+
assert @package_release.release_file == correct_release_file
|
177
|
+
end
|
178
|
+
|
179
|
+
end
|
180
|
+
|
181
|
+
|
182
|
+
class TestPackage < MiniTest::Unit::TestCase
|
183
|
+
def setup
|
184
|
+
@tempfile1 = File.open('/tmp/foo','w+') { |f| f.write 'foo' }
|
185
|
+
@tempfile2 = File.open('/tmp/bar','w+') { |f| f.write 'bar' }
|
186
|
+
|
187
|
+
@hash = {
|
188
|
+
"Package" => "foo",
|
189
|
+
"Version" => "1.2.68",
|
190
|
+
"Architecture" => "amd64",
|
191
|
+
"Maintainer" => "support@cloudscaling.com",
|
192
|
+
"Homepage" => "http://www.cloudscaling.com",
|
193
|
+
"Priority" => "extra",
|
194
|
+
"Depends" => %w{one two three},
|
195
|
+
"section" => "main",
|
196
|
+
"path_to_deb" => '/tmp/foo',
|
197
|
+
"Description" => 'some
|
198
|
+
multiline
|
199
|
+
description'
|
200
|
+
}
|
201
|
+
|
202
|
+
@package1 = FRM::Package.new(@hash)
|
203
|
+
end
|
204
|
+
|
205
|
+
def test()
|
206
|
+
assert @package1.name == 'foo'
|
207
|
+
assert @package1.content == 'foo'
|
208
|
+
end
|
209
|
+
|
210
|
+
def test_bad_file()
|
211
|
+
bad_hash = {
|
212
|
+
"Package" => "foo",
|
213
|
+
"Version" => "1.2.68",
|
214
|
+
"Architecture" => "amd64",
|
215
|
+
"Maintainer" => "support@cloudscaling.com",
|
216
|
+
"Homepage" => "http://www.cloudscaling.com",
|
217
|
+
"Priority" => "extra",
|
218
|
+
"Depends" => %w{one two three},
|
219
|
+
"section" => "main",
|
220
|
+
"path_to_deb" => '/some/bad/path',
|
221
|
+
"Description" => 'some
|
222
|
+
multiline
|
223
|
+
description'
|
224
|
+
}
|
225
|
+
assert_raises(RuntimeError) { FRM::Package.new(bad_hash) }
|
226
|
+
end
|
227
|
+
|
228
|
+
def test_good_file()
|
229
|
+
assert @package1.content == 'foo'
|
230
|
+
end
|
231
|
+
|
232
|
+
def test_hashes()
|
233
|
+
assert @package1.md5 == 'acbd18db4cc2f85cedef654fccc4a4d8'
|
234
|
+
assert @package1.sha1 == '0beec7b5ea3f0fdbc95d0dd47f3c5bc275da8a33'
|
235
|
+
assert @package1.sha2 == '2c26b46b68ffc68ff99b453c1d30413413422d706483bfa0f98a5e886266e7ae'
|
236
|
+
|
237
|
+
end
|
238
|
+
|
239
|
+
|
240
|
+
end
|
241
|
+
|
242
|
+
|
243
|
+
class TestDeb < MiniTest::Unit::TestCase
|
244
|
+
|
245
|
+
def setup
|
246
|
+
@deb = FRM::Deb.new()
|
247
|
+
@tempfile1 = File.open('/tmp/foo_1.2.68_amd64.deb','w+') { |f| f.write 'foo' }
|
248
|
+
@tempfile2 = File.open('/tmp/bar_1.2.3.4_amd64.deb','w+') { |f| f.write 'bar' }
|
249
|
+
|
250
|
+
@hash = [
|
251
|
+
{
|
252
|
+
"Package" => "foo",
|
253
|
+
"Version" => "1.2.68",
|
254
|
+
"Architecture" => "amd64",
|
255
|
+
"Maintainer" => "support@cloudscaling.com",
|
256
|
+
"Homepage" => "http://www.cloudscaling.com",
|
257
|
+
"Priority" => "extra",
|
258
|
+
"Depends" => %w{one two three},
|
259
|
+
"section" => "main",
|
260
|
+
"path_to_deb" => '/tmp/foo_1.2.68_amd64.deb',
|
261
|
+
"Description" => 'some
|
262
|
+
multiline
|
263
|
+
description'
|
264
|
+
},
|
265
|
+
{
|
266
|
+
"Package" => "bar",
|
267
|
+
"Version" => "1.2.3.4",
|
268
|
+
"Architecture" => "amd64",
|
269
|
+
"Maintainer" => "support@cloudscaling.com",
|
270
|
+
"Homepage" => "http://www.cloudscaling.com",
|
271
|
+
"Priority" => "extra",
|
272
|
+
"Depends" => %w{one two three},
|
273
|
+
"section" => "main",
|
274
|
+
"path_to_deb" => '/tmp/bar_1.2.3.4_amd64.deb'
|
275
|
+
}
|
276
|
+
]
|
277
|
+
end
|
278
|
+
|
279
|
+
def teardown
|
280
|
+
File.delete '/tmp/foo_1.2.68_amd64.deb' if File.exists? '/tmp/foo_1.2.68_amd64.deb'
|
281
|
+
File.delete '/tmp/bar_1.2.3.4_amd64.deb' if File.exists? '/tmp/bar_1.2.3.4_amd64.deb'
|
282
|
+
end
|
283
|
+
|
284
|
+
|
285
|
+
def test_generate_package_stub
|
286
|
+
correct_output = "Package: foo
|
287
|
+
Version: 1.2.68
|
288
|
+
Architecture: amd64
|
289
|
+
Maintainer: <support@cloudscaling.com>
|
290
|
+
Homepage: http://www.cloudscaling.com
|
291
|
+
Priority: extra
|
292
|
+
Depends: one, two, three
|
293
|
+
Filename: pool/main/f/foo/foo_1.2.68_amd64.deb
|
294
|
+
Size: 3
|
295
|
+
MD5sum: acbd18db4cc2f85cedef654fccc4a4d8
|
296
|
+
SHA1: 0beec7b5ea3f0fdbc95d0dd47f3c5bc275da8a33
|
297
|
+
SHA256: 2c26b46b68ffc68ff99b453c1d30413413422d706483bfa0f98a5e886266e7ae
|
298
|
+
Description: some
|
299
|
+
multiline
|
300
|
+
description
|
301
|
+
|
302
|
+
"
|
303
|
+
|
304
|
+
duplicate_hash = @hash[0].dup
|
305
|
+
assert @deb.generate_package_stub(duplicate_hash) == correct_output
|
306
|
+
assert @hash[0] == duplicate_hash
|
307
|
+
end
|
308
|
+
|
309
|
+
|
310
|
+
def test_generate_package_file
|
311
|
+
correct_output = "Package: foo
|
312
|
+
Version: 1.2.68
|
313
|
+
Architecture: amd64
|
314
|
+
Maintainer: <support@cloudscaling.com>
|
315
|
+
Homepage: http://www.cloudscaling.com
|
316
|
+
Priority: extra
|
317
|
+
Depends: one, two, three
|
318
|
+
Filename: pool/main/f/foo/foo_1.2.68_amd64.deb
|
319
|
+
Size: 3
|
320
|
+
MD5sum: acbd18db4cc2f85cedef654fccc4a4d8
|
321
|
+
SHA1: 0beec7b5ea3f0fdbc95d0dd47f3c5bc275da8a33
|
322
|
+
SHA256: 2c26b46b68ffc68ff99b453c1d30413413422d706483bfa0f98a5e886266e7ae
|
323
|
+
Description: some
|
324
|
+
multiline
|
325
|
+
description
|
326
|
+
|
327
|
+
Package: bar
|
328
|
+
Version: 1.2.3.4
|
329
|
+
Architecture: amd64
|
330
|
+
Maintainer: <support@cloudscaling.com>
|
331
|
+
Homepage: http://www.cloudscaling.com
|
332
|
+
Priority: extra
|
333
|
+
Depends: one, two, three
|
334
|
+
Filename: pool/main/b/bar/bar_1.2.3.4_amd64.deb
|
335
|
+
Size: 3
|
336
|
+
MD5sum: 37b51d194a7513e45b56f6524f2d51f2
|
337
|
+
SHA1: 62cdb7020ff920e5aa642c3d4066950dd1f01f4d
|
338
|
+
SHA256: fcde2b2edba56bf408601fb721fe9b5c338d10ee429ea04fae5511b68fbf8fb9
|
339
|
+
Description: no description given
|
340
|
+
|
341
|
+
"
|
342
|
+
assert @deb.generate_package_file(@hash) == correct_output
|
343
|
+
end
|
344
|
+
|
345
|
+
def test_gzip
|
346
|
+
input = generate_random_string
|
347
|
+
gziped_pipe = @deb.generate_gzip_pipe(input)
|
348
|
+
output = @deb.gunzip_pipe gziped_pipe
|
349
|
+
assert input == output
|
350
|
+
end
|
351
|
+
|
352
|
+
|
353
|
+
def test_md5
|
354
|
+
input = 'foo'
|
355
|
+
assert @deb.compute_md5(input) == 'acbd18db4cc2f85cedef654fccc4a4d8'
|
356
|
+
end
|
357
|
+
|
358
|
+
def test_sha1
|
359
|
+
input = 'foo'
|
360
|
+
assert @deb.compute_sha1(input) == '0beec7b5ea3f0fdbc95d0dd47f3c5bc275da8a33'
|
361
|
+
end
|
362
|
+
|
363
|
+
def test_sha256
|
364
|
+
input = 'foo'
|
365
|
+
assert @deb.compute_sha2(input) == '2c26b46b68ffc68ff99b453c1d30413413422d706483bfa0f98a5e886266e7ae'
|
366
|
+
end
|
367
|
+
|
368
|
+
def test_generate_package_release
|
369
|
+
package_release_file = "Component: main
|
370
|
+
Origin: apt.cloudscaling.com
|
371
|
+
Label: apt repository natty
|
372
|
+
Architecture: amd64
|
373
|
+
Description: Cloudscaling APT repository
|
374
|
+
"
|
375
|
+
assert @deb.generate_package_release == package_release_file
|
376
|
+
end
|
377
|
+
|
378
|
+
def test_generate_release
|
379
|
+
skip 'need to finish generate_release function'
|
380
|
+
release_file = "Origin: apt.cloudscaling.com
|
381
|
+
Label: apt repository natty
|
382
|
+
Codename: natty
|
383
|
+
Date: Thu, 22 Dec 2011 00:29:55 UTC
|
384
|
+
Architectures: amd64
|
385
|
+
;Components: main universe multiverse
|
386
|
+
Description: Cloudscaling APT repository
|
387
|
+
MD5Sum:
|
388
|
+
a4b943ff89790ccdc186875dad67827b 5813 main/binary-amd64/Packages
|
389
|
+
004fd3f868ebbe7501fb2e1c0c54e2a7 2148 main/binary-amd64/Packages.gz
|
390
|
+
79dd2fee35fba7255dcd40e1f6529591 134 main/binary-amd64/Release
|
391
|
+
SHA1:
|
392
|
+
6e03924030eab56cb9735a52ec710537e682bcfc 5813 main/binary-amd64/Packages
|
393
|
+
5f2989bae96e148cb5f18accc4357305926ab1e1 2148 main/binary-amd64/Packages.gz
|
394
|
+
6d932af9af761f418e5374f73dcd09badb4fe57e 134 main/binary-amd64/Release
|
395
|
+
SHA256:
|
396
|
+
dd8283f06beb4a5fc06ac62d3ae098e5ba2717daef2a15b5f3e9233eb64e0227 5813 main/binary-amd64/Packages
|
397
|
+
b197c5a3c1fe6a6d286e9f066a0cade289e3a2fc485c90407179951634788aa8 2148 main/binary-amd64/Packages.gz
|
398
|
+
690b44df6fe65f40f260b73394e87804df78c9ccf13999889259faeed3eec40d 134 main/binary-amd64/Release
|
399
|
+
"
|
400
|
+
assert @deb.generate_release == release_file
|
401
|
+
end
|
402
|
+
|
403
|
+
def generate_random_string
|
404
|
+
rand(36**rand(50)).to_s(36)
|
405
|
+
end
|
406
|
+
|
407
|
+
def test_parse_package_stub
|
408
|
+
input_stub = "Package: foo
|
409
|
+
Version: 1.2.68
|
410
|
+
Architecture: amd64
|
411
|
+
Maintainer: <support@cloudscaling.com>
|
412
|
+
Homepage: http://www.cloudscaling.com
|
413
|
+
Priority: extra
|
414
|
+
Depends: one, two, three
|
415
|
+
Filename: pool/main/f/foo/foo_1.2.68_amd64.deb
|
416
|
+
Size: 3
|
417
|
+
MD5sum: acbd18db4cc2f85cedef654fccc4a4d8
|
418
|
+
SHA1: 0beec7b5ea3f0fdbc95d0dd47f3c5bc275da8a33
|
419
|
+
SHA256: 2c26b46b68ffc68ff99b453c1d30413413422d706483bfa0f98a5e886266e7ae
|
420
|
+
Description: some
|
421
|
+
multiline
|
422
|
+
description
|
423
|
+
|
424
|
+
Package: bar
|
425
|
+
Version: 1.2.3.4
|
426
|
+
Architecture: amd64
|
427
|
+
Maintainer: <support@cloudscaling.com>
|
428
|
+
Homepage: http://www.cloudscaling.com
|
429
|
+
Priority: extra
|
430
|
+
Depends: one, two, three
|
431
|
+
Filename: pool/main/b/bar/bar_1.2.3.4_amd64.deb
|
432
|
+
Size: 3
|
433
|
+
MD5sum: 37b51d194a7513e45b56f6524f2d51f2
|
434
|
+
SHA1: 62cdb7020ff920e5aa642c3d4066950dd1f01f4d
|
435
|
+
SHA256: fcde2b2edba56bf408601fb721fe9b5c338d10ee429ea04fae5511b68fbf8fb9
|
436
|
+
Description: no description given
|
437
|
+
|
438
|
+
"
|
439
|
+
correct_hash = {"Package"=>"foo", "Version"=>"1.2.68", "Architecture"=>"amd64", "Maintainer"=>"<support@cloudscaling.com>", "Homepage"=>"http://www.cloudscaling.com", "Priority"=>"extra", "Depends"=>"one, two, three", "Filename"=>"pool/main/f/foo/foo_1.2.68_amd64.deb", "Size"=>"3", "MD5sum"=>"acbd18db4cc2f85cedef654fccc4a4d8", "SHA1"=>"0beec7b5ea3f0fdbc95d0dd47f3c5bc275da8a33", "SHA256"=>"2c26b46b68ffc68ff99b453c1d30413413422d706483bfa0f98a5e886266e7ae", "Description"=>"some multiline\n description"}
|
440
|
+
read_buffer, write_buffer = IO.pipe
|
441
|
+
write_buffer.write input_stub
|
442
|
+
write_buffer.close
|
443
|
+
assert @deb.parse_package_stub(read_buffer.dup)[0] == correct_hash
|
444
|
+
assert_raises(RuntimeError) { @deb.parse_package_stub File.open('/tmp/foo') }
|
445
|
+
end
|
446
|
+
|
447
|
+
|
448
|
+
def test_merge_package_file
|
449
|
+
package_file = File.open 'Packages.txt'
|
450
|
+
read_buffer, write_buffer = IO.pipe
|
451
|
+
|
452
|
+
@deb.merge_package_file(package_file,write_buffer,@hash)
|
453
|
+
|
454
|
+
end
|
455
|
+
|
456
|
+
|
457
|
+
end
|
data/test/deb_test2.rb
ADDED
@@ -0,0 +1,31 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
|
3
|
+
require 'minitest/autorun'
|
4
|
+
|
5
|
+
my_dir = File.dirname __FILE__
|
6
|
+
require File.join my_dir, 'deb'
|
7
|
+
|
8
|
+
class TestReleasePusher < MiniTest::Unit::TestCase
|
9
|
+
def setup
|
10
|
+
@tempfile1 = File.open('/tmp/foo_1.2.68_amd64.deb','w+') { |f| f.write 'foo' }
|
11
|
+
@tempfile2 = File.open('/tmp/bar_1.2.3.4_amd64.deb','w+') { |f| f.write 'bar' }
|
12
|
+
@tempfile3 = File.open('/tmp/martin_1.2.3.4_amd64.deb','w+') { |f| f.write 'martin' }
|
13
|
+
|
14
|
+
hashes = %w{
|
15
|
+
/home/martin/sheep/modules/substratum/debs/pod-services-0.5.0-967-amd64.deb
|
16
|
+
/home/martin/sheep/modules/substratum/debs/cs-chef-0.9.1-1782-all.deb
|
17
|
+
/home/martin/sheep/modules/substratum/debs/ruby1.9.2-1-amd64.deb
|
18
|
+
}
|
19
|
+
|
20
|
+
|
21
|
+
@package_release = FRM::PackageRelease.new(hashes)
|
22
|
+
@release_pusher = FRM::ReleasePusher.new(@package_release,'1234','abcd',\
|
23
|
+
'some-bucket','testing/tmp/frm')
|
24
|
+
end
|
25
|
+
|
26
|
+
def test
|
27
|
+
|
28
|
+
end
|
29
|
+
|
30
|
+
end
|
31
|
+
|
data/test/s3.rb
ADDED
@@ -0,0 +1,56 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
|
3
|
+
require 'minitest/autorun'
|
4
|
+
my_dir = File.dirname __FILE__
|
5
|
+
require File.join my_dir, 's3'
|
6
|
+
|
7
|
+
|
8
|
+
# this is a stupid hack to get the @@bucket region set properly
|
9
|
+
DEFAULT_HOST = 's3-us-west-1.amazonaws.com'
|
10
|
+
|
11
|
+
class TestFRM < MiniTest::Unit::TestCase
|
12
|
+
|
13
|
+
# these credentials only have access inside of cloudscaling-us-west-develop/testing/
|
14
|
+
@@access_key_id = 'abcd'
|
15
|
+
@@secret_key_id = '1234'
|
16
|
+
@@bucket = 'some-bucket'
|
17
|
+
@@prefix = 'testing/tmp/' + Time.now.strftime("%Y/%m/%d/%H:%M:%S ")
|
18
|
+
@@server = 's3-us-west-1.amazonaws.com'
|
19
|
+
@@timestamp = rand(9999).to_s
|
20
|
+
|
21
|
+
|
22
|
+
@@key = @@prefix + "testing-" + @@timestamp.to_s
|
23
|
+
@@value = "rand: " + @@timestamp
|
24
|
+
|
25
|
+
# we need minitest to run in order
|
26
|
+
def self.test_order
|
27
|
+
:alpha
|
28
|
+
end
|
29
|
+
|
30
|
+
def setup
|
31
|
+
@frm = FRM::S3.new(@@access_key_id,@@secret_key_id,@@server)
|
32
|
+
end
|
33
|
+
|
34
|
+
def test_aput
|
35
|
+
assert @frm.put @@key,@@value,@@bucket
|
36
|
+
end
|
37
|
+
|
38
|
+
def test_bkey?
|
39
|
+
assert @frm.key? @@key,@@bucket
|
40
|
+
end
|
41
|
+
|
42
|
+
def test_cget
|
43
|
+
assert_equal @@value, @frm.get(@@key,@@bucket)
|
44
|
+
end
|
45
|
+
|
46
|
+
def test_ddelete
|
47
|
+
assert @frm.delete @@key, @@bucket
|
48
|
+
end
|
49
|
+
|
50
|
+
# this is broken :(
|
51
|
+
def test_ekey?
|
52
|
+
skip 'need to debug key?'
|
53
|
+
refute @frm.key?(@@key,@@bucket)
|
54
|
+
end
|
55
|
+
|
56
|
+
end
|
metadata
CHANGED
@@ -5,8 +5,8 @@ version: !ruby/object:Gem::Version
|
|
5
5
|
segments:
|
6
6
|
- 0
|
7
7
|
- 0
|
8
|
-
-
|
9
|
-
version: 0.0.
|
8
|
+
- 2
|
9
|
+
version: 0.0.2
|
10
10
|
platform: ruby
|
11
11
|
authors:
|
12
12
|
- Martin Rhoads
|
@@ -21,8 +21,8 @@ dependencies: []
|
|
21
21
|
description: FRM makes it easy to build package repositories on S3
|
22
22
|
email:
|
23
23
|
- ermal14@gmail.com
|
24
|
-
executables:
|
25
|
-
|
24
|
+
executables:
|
25
|
+
- fpm
|
26
26
|
extensions: []
|
27
27
|
|
28
28
|
extra_rdoc_files: []
|
@@ -30,11 +30,17 @@ extra_rdoc_files: []
|
|
30
30
|
files:
|
31
31
|
- .gitignore
|
32
32
|
- Gemfile
|
33
|
+
- LICENSE
|
33
34
|
- Rakefile
|
35
|
+
- bin/fpm
|
34
36
|
- frm.gemspec
|
35
|
-
- frm/.gitignore
|
36
37
|
- lib/frm.rb
|
38
|
+
- lib/frm/deb.rb
|
39
|
+
- lib/frm/s3.rb
|
37
40
|
- lib/frm/version.rb
|
41
|
+
- test/deb_test.rb
|
42
|
+
- test/deb_test2.rb
|
43
|
+
- test/s3.rb
|
38
44
|
has_rdoc: true
|
39
45
|
homepage: https://github.com/ermal14/frm
|
40
46
|
licenses: []
|
@@ -67,5 +73,7 @@ rubygems_version: 1.3.7
|
|
67
73
|
signing_key:
|
68
74
|
specification_version: 3
|
69
75
|
summary: Effin Repo Manager
|
70
|
-
test_files:
|
71
|
-
|
76
|
+
test_files:
|
77
|
+
- test/deb_test.rb
|
78
|
+
- test/deb_test2.rb
|
79
|
+
- test/s3.rb
|
data/frm/.gitignore
DELETED