manifest-builder 0.5.8 → 0.5.10
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 +4 -4
- data/Gemfile.lock +3 -3
- data/lib/cicd/builder/manifest/version.rb +1 -1
- data/manifest-builder.gemspec +1 -1
- data/tests/infinite-etag.rb +166 -0
- metadata +4 -3
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: e60728ab2daaf198e0540b734c90ef98133e6e76
|
4
|
+
data.tar.gz: b1a51a36abf4c4dee729cf74f50f6f4b93d43bd3
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 5189f9610b02429a865ed37e417f5d332e228d7eec4e0856347871a9eeb4bfc2dc3566d9302d0c79eb31fa21b8a3c3fea003a641d48b5076fbd068b98bff383a
|
7
|
+
data.tar.gz: 49749634786c6eeb406a3a3c98cc6b85c7fc1288a02cec37b51b6674a60d2b2bae2bb56ffb78a3cf837e6430917aafb4cb2e9dc75da7d39219e76b0fff445ff9
|
data/Gemfile.lock
CHANGED
@@ -1,10 +1,10 @@
|
|
1
1
|
PATH
|
2
2
|
remote: .
|
3
3
|
specs:
|
4
|
-
manifest-builder (0.5.
|
4
|
+
manifest-builder (0.5.10)
|
5
5
|
archive-tar-minitar (= 0.5.2)
|
6
6
|
chefrepo-builder (>= 0.9.27, < 1.1)
|
7
|
-
cicd-builder (>= 0.9.
|
7
|
+
cicd-builder (>= 0.9.40, < 1.1)
|
8
8
|
json (>= 1.8.1, < 1.9)
|
9
9
|
s3etag (>= 0.0.1, < 0.1.0)
|
10
10
|
|
@@ -18,7 +18,7 @@ PATH
|
|
18
18
|
PATH
|
19
19
|
remote: ../cicd-builder
|
20
20
|
specs:
|
21
|
-
cicd-builder (0.9.
|
21
|
+
cicd-builder (0.9.40)
|
22
22
|
artifactory (>= 2.2.1, < 2.3)
|
23
23
|
awesome_print (>= 1.6, < 2.0)
|
24
24
|
aws-sdk (>= 2.0, < 2.1)
|
data/manifest-builder.gemspec
CHANGED
@@ -17,7 +17,7 @@ Gem::Specification.new do |gem|
|
|
17
17
|
gem.test_files = gem.files.grep(%r{^(test|spec|features)/})
|
18
18
|
gem.require_paths = ['lib']
|
19
19
|
|
20
|
-
gem.add_dependency 'cicd-builder', '>= 0.9.
|
20
|
+
gem.add_dependency 'cicd-builder', '>= 0.9.40', '< 1.1'
|
21
21
|
gem.add_dependency 'chefrepo-builder', '>= 0.9.27', '< 1.1'
|
22
22
|
# gem.add_dependency 'ansiblerepo-builder', '>= 0.3.7', '< 0.5'
|
23
23
|
gem.add_dependency 'json', '>= 1.8.1', '< 1.9'
|
@@ -0,0 +1,166 @@
|
|
1
|
+
require 'aws-sdk-core'
|
2
|
+
require 'aws-sdk-resources'
|
3
|
+
require 'uri'
|
4
|
+
|
5
|
+
# ---------------------------------------------------------------------------------------------------------------
|
6
|
+
def getS3()
|
7
|
+
region = ENV['AWS_REGION'] || ::Aws.config[:region] || 'us-east-1'
|
8
|
+
unless @s3
|
9
|
+
# noinspection RubyArgCount
|
10
|
+
@s3 = ::Aws::S3::Client.new(region: region)
|
11
|
+
end
|
12
|
+
unless @s3 and ((@s3.config.access_key_id and @s3.config.secret_access_key) or @s3.config.credentials)
|
13
|
+
@logger.warn "Unable to find AWS credentials in standard locations:
|
14
|
+
ENV['AWS_ACCESS_KEY'] and ENV['AWS_SECRET_ACCESS_KEY']
|
15
|
+
Aws.config[:credentials]
|
16
|
+
Shared credentials file, ~/.aws/credentials
|
17
|
+
EC2 Instance profile
|
18
|
+
"
|
19
|
+
if ENV['AWS_PROFILE']
|
20
|
+
@logger.info "Trying profile '#{ENV['AWS_PROFILE']}' explicitly"
|
21
|
+
creds = Aws::SharedCredentials.new( path: File.expand_path('~/.aws/credentials'), profile: ENV['AWS_PROFILE'] )
|
22
|
+
if creds.loadable?
|
23
|
+
# noinspection RubyArgCount
|
24
|
+
@s3 = ::Aws::S3::Client.new(region: region, credentials: creds)
|
25
|
+
end
|
26
|
+
else
|
27
|
+
@logger.warn 'No AWS_PROFILE defined'
|
28
|
+
end
|
29
|
+
end
|
30
|
+
unless @s3 and ((@s3.config.access_key_id and @s3.config.secret_access_key) or @s3.config.credentials)
|
31
|
+
raise 'Unable to find AWS credentials!'
|
32
|
+
end
|
33
|
+
@s3
|
34
|
+
end
|
35
|
+
|
36
|
+
# ---------------------------------------------------------------------------------------------------------------
|
37
|
+
def getBucket(name = nil)
|
38
|
+
@s3 = getS3()
|
39
|
+
begin
|
40
|
+
::Aws::S3::Bucket.new(name: name || ENV['AWS_S3_BUCKET'], client: @s3)
|
41
|
+
rescue Aws::S3::Errors::NotFound
|
42
|
+
@vars[:return_code] = Errors::BUCKET
|
43
|
+
nil
|
44
|
+
rescue Exception => e
|
45
|
+
@logger.error "S3 Bucket resource API error: #{e.class.name} #{e.message}"
|
46
|
+
raise e
|
47
|
+
end
|
48
|
+
end
|
49
|
+
|
50
|
+
# ---------------------------------------------------------------------------------------------------------------
|
51
|
+
def getObjects(artifact, path)
|
52
|
+
parts = URI(path).path.gsub(%r'^#{File::SEPARATOR}', '').split(File::SEPARATOR)
|
53
|
+
name = parts.shift
|
54
|
+
bucket = getBucket(name)
|
55
|
+
key = File.join(parts, '')
|
56
|
+
@logger.info "S3://#{name}:#{key} URL: #{path} #{artifact}"
|
57
|
+
objects = []
|
58
|
+
bucket.objects(prefix: key).each do |object|
|
59
|
+
if artifact.empty? or (not artifact.empty? and object.key =~ %r'#{key}#{artifact}')
|
60
|
+
objects << object
|
61
|
+
end
|
62
|
+
end
|
63
|
+
@logger.debug "S3://#{name}:#{key} has #{objects.size} objects"
|
64
|
+
return key, name, objects
|
65
|
+
end
|
66
|
+
|
67
|
+
# ---------------------------------------------------------------------------------------------------------------
|
68
|
+
def calcLocalETag(etag, local, size = nil)
|
69
|
+
if size == nil
|
70
|
+
stat = File.stat(local)
|
71
|
+
size = stat.size
|
72
|
+
end
|
73
|
+
@logger.debug "Calculate etag to match #{etag}"
|
74
|
+
match = etag.match(%r'-(\d+)$')
|
75
|
+
check = if match
|
76
|
+
require 's3etag'
|
77
|
+
parts = match[1].to_i
|
78
|
+
chunk = size.to_f / parts.to_f
|
79
|
+
mbs = (chunk.to_f / 1024 /1024 + 0.5).to_i
|
80
|
+
part_size = mbs * 1024 * 1024
|
81
|
+
chkit = S3Etag.calc(file: local, threshold: part_size, min_part_size: part_size, max_parts: parts)
|
82
|
+
@logger.debug "S3Etag Calculated #{chkit} : (#{size} / #{part_size}) <= #{parts}"
|
83
|
+
chunks = size / part_size
|
84
|
+
while chkit != etag and chunks <= parts and chunks > 0 and (size > part_size)
|
85
|
+
# Go one larger if a modulus remains and we have the right number of parts
|
86
|
+
mbs += 1
|
87
|
+
part_size = mbs * 1024 * 1024
|
88
|
+
chunks = size.to_f / part_size
|
89
|
+
chkit = S3Etag.calc(file: local, threshold: part_size, min_part_size: part_size, max_parts: parts)
|
90
|
+
@logger.debug "S3Etag Calculated #{chkit} : (#{size} / #{part_size}) <= #{parts}"
|
91
|
+
end
|
92
|
+
raise "Unable to match etag #{etag}!" if chkit != etag
|
93
|
+
chkit
|
94
|
+
else
|
95
|
+
Digest::MD5.file(local).hexdigest
|
96
|
+
end
|
97
|
+
end
|
98
|
+
|
99
|
+
# ---------------------------------------------------------------------------------------------------------------
|
100
|
+
def shouldDownload?(etag, local, object)
|
101
|
+
if File.exists?(local)
|
102
|
+
@logger.debug "\t\tchecking etag on #{local}"
|
103
|
+
stat = File.stat(local)
|
104
|
+
check = calcLocalETag(etag, local, stat.size)
|
105
|
+
if etag != check or object.size != stat.size or object.last_modified > stat.mtime
|
106
|
+
@logger.debug "\t\t#{etag} != \"#{check}\" #{object.size} != #{stat.size} #{object.last_modified} > #{stat.mtime}"
|
107
|
+
true
|
108
|
+
else
|
109
|
+
@logger.debug "\t\tmatched #{etag}"
|
110
|
+
false
|
111
|
+
end
|
112
|
+
else
|
113
|
+
true
|
114
|
+
end
|
115
|
+
end
|
116
|
+
|
117
|
+
# ---------------------------------------------------------------------------------------------------------------
|
118
|
+
def doDownload(etag, local, object)
|
119
|
+
@logger.info "\t\tdownload #{object.size} bytes"
|
120
|
+
response = object.get(:response_target => local)
|
121
|
+
File.utime(response.last_modified, response.last_modified, local)
|
122
|
+
@logger.info "\t\tdone"
|
123
|
+
check = calcLocalETag(etag, local)
|
124
|
+
if check.eql?(etag)
|
125
|
+
false
|
126
|
+
else
|
127
|
+
@logger.info "\tETag different: #{etag} != #{check}"
|
128
|
+
true
|
129
|
+
end
|
130
|
+
end
|
131
|
+
|
132
|
+
|
133
|
+
class FakeLogger
|
134
|
+
def initialize
|
135
|
+
|
136
|
+
end
|
137
|
+
|
138
|
+
def method_missing(*args)
|
139
|
+
puts "#{args[0]}: #{args[1..-1].join(' ')}"
|
140
|
+
end
|
141
|
+
end
|
142
|
+
|
143
|
+
@logger = FakeLogger.new()
|
144
|
+
artifact, path = ['', 'https://s3.amazonaws.com/wgen-sto-artifacts/release/com/amplify/learning/enrollment/1.3.0-265']
|
145
|
+
local_dir = File.join('/tmp', 'enrollment', '')
|
146
|
+
Dir.mkdir(local_dir, 0700) unless File.directory?(local_dir)
|
147
|
+
artifacts = []
|
148
|
+
|
149
|
+
key, name, objects = getObjects(artifact, path)
|
150
|
+
# 1 or more objects on the key/ path
|
151
|
+
if objects.size > 0
|
152
|
+
objects.each do |object|
|
153
|
+
@logger.info "\tchecking #{object.key}"
|
154
|
+
local = File.join(local_dir, File.basename(object.key))
|
155
|
+
etag = object.etag.gsub(%r/['"]/, '')
|
156
|
+
download = shouldDownload?(etag, local, object)
|
157
|
+
if download
|
158
|
+
changed = doDownload(etag, local, object)
|
159
|
+
else
|
160
|
+
@logger.info "\t\tunchanged"
|
161
|
+
end
|
162
|
+
artifacts << local
|
163
|
+
end
|
164
|
+
else
|
165
|
+
@logger.fatal "Artifact not found: s3://#{name}/#{key}#{artifact}"
|
166
|
+
end
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: manifest-builder
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.5.
|
4
|
+
version: 0.5.10
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Christo De Lange
|
@@ -16,7 +16,7 @@ dependencies:
|
|
16
16
|
requirements:
|
17
17
|
- - ">="
|
18
18
|
- !ruby/object:Gem::Version
|
19
|
-
version: 0.9.
|
19
|
+
version: 0.9.40
|
20
20
|
- - "<"
|
21
21
|
- !ruby/object:Gem::Version
|
22
22
|
version: '1.1'
|
@@ -26,7 +26,7 @@ dependencies:
|
|
26
26
|
requirements:
|
27
27
|
- - ">="
|
28
28
|
- !ruby/object:Gem::Version
|
29
|
-
version: 0.9.
|
29
|
+
version: 0.9.40
|
30
30
|
- - "<"
|
31
31
|
- !ruby/object:Gem::Version
|
32
32
|
version: '1.1'
|
@@ -235,6 +235,7 @@ files:
|
|
235
235
|
- manifest-builder.gemspec
|
236
236
|
- spec/builder_spec.rb
|
237
237
|
- spec/spec_helper.rb
|
238
|
+
- tests/infinite-etag.rb
|
238
239
|
homepage: https://rubygems.org/gems/manifest-builder
|
239
240
|
licenses:
|
240
241
|
- Apachev2
|