fpm-fry 0.7.2.1 → 0.8.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/lib/fpm/fry/client.rb +26 -12
- data/lib/fpm/fry/command/cook.rb +77 -71
- data/lib/fpm/fry/command.rb +1 -1
- metadata +20 -5
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 5c84a20f83300f3f9793e0680dc5573be7e579303df7420ef9872855824ffcc8
|
4
|
+
data.tar.gz: 3dd82f0cc8368c27ed708fee9ac233901004bd8fca5b14fac0d5d911c2a8499a
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 1954a12b44d375a0f07b664eb5eaf705ef772b4e67ec8fd4723675e0bbfc888006a2997cb4d3826cd1cd5fc71dc08051aa38e4b8fca1ae0e8f6b7dd50e8b8b2a
|
7
|
+
data.tar.gz: 23f211f530e0ddd1eda1fffc77bfddbec8d397c9746096b22cb95875c8a60daf6e829d8d9533728eabe65aa4e49de6a74af2ec521ed8e51ced483cf58b464e76
|
data/lib/fpm/fry/client.rb
CHANGED
@@ -22,6 +22,10 @@ class FPM::Fry::Client
|
|
22
22
|
include FPM::Fry::WithData
|
23
23
|
end
|
24
24
|
|
25
|
+
class ContainerDeletionFailed < StandardError
|
26
|
+
include FPM::Fry::WithData
|
27
|
+
end
|
28
|
+
|
25
29
|
# Raised when trying to read file that can't be read e.g. because it's a
|
26
30
|
# directory.
|
27
31
|
class NotAFile < StandardError
|
@@ -111,7 +115,7 @@ class FPM::Fry::Client
|
|
111
115
|
)
|
112
116
|
end
|
113
117
|
rescue Excon::Error => e
|
114
|
-
|
118
|
+
logger.error("unexpected response when reading resource: url: #{url}, error: #{e}")
|
115
119
|
raise
|
116
120
|
end
|
117
121
|
if [404,500].include? res.status
|
@@ -165,14 +169,14 @@ class FPM::Fry::Client
|
|
165
169
|
end
|
166
170
|
|
167
171
|
def copy(name, resource, map, options = {})
|
168
|
-
ex = FPM::Fry::Tar::Extractor.new(logger:
|
172
|
+
ex = FPM::Fry::Tar::Extractor.new(logger: logger)
|
169
173
|
base = File.dirname(resource)
|
170
174
|
read(name, resource) do | entry |
|
171
175
|
file = File.join(base, entry.full_name).chomp('/')
|
172
176
|
file = file.sub(%r"\A\./",'')
|
173
177
|
to = map[file]
|
174
178
|
next unless to
|
175
|
-
|
179
|
+
logger.debug("Copy",name: file, to: to)
|
176
180
|
ex.extract_entry(to, entry, options)
|
177
181
|
end
|
178
182
|
end
|
@@ -182,11 +186,11 @@ class FPM::Fry::Client
|
|
182
186
|
res = agent.get(path: url, expects: [200, 204])
|
183
187
|
return JSON.parse(res.body)
|
184
188
|
rescue Excon::Error => e
|
185
|
-
|
189
|
+
logger.error("could not retrieve changes for: #{name}, url: #{url}, error: #{e}")
|
186
190
|
raise
|
187
191
|
end
|
188
192
|
|
189
|
-
def pull(image)
|
193
|
+
def pull(image, platform: nil)
|
190
194
|
last_status = ""
|
191
195
|
streamer = lambda do |chunk, remaining_bytes, total_bytes|
|
192
196
|
chunk.each_line do |line|
|
@@ -204,7 +208,9 @@ class FPM::Fry::Client
|
|
204
208
|
end
|
205
209
|
end
|
206
210
|
end
|
207
|
-
|
211
|
+
query = {'fromImage' => image}
|
212
|
+
query['platform'] = platform if platform
|
213
|
+
agent.post(path: url('images','create'), query: query, :response_block => streamer)
|
208
214
|
end
|
209
215
|
|
210
216
|
def delete(image)
|
@@ -220,27 +226,35 @@ class FPM::Fry::Client
|
|
220
226
|
)
|
221
227
|
data = JSON.parse(res.body)
|
222
228
|
if res.status != 201
|
223
|
-
|
229
|
+
logger.error(data["message"])
|
224
230
|
if res.status == 404
|
225
|
-
|
231
|
+
logger.info("execute docker pull #{image} first or specify --pull argument for fpm-fry")
|
226
232
|
end
|
227
233
|
raise ContainerCreationFailed.new("could not create container from #{image}", message: data["message"])
|
228
234
|
end
|
229
235
|
data['Id']
|
230
236
|
rescue Excon::Error => e
|
231
|
-
|
237
|
+
logger.error("could not create container from #{image}, url: #{url}, error: #{e}")
|
232
238
|
raise
|
233
239
|
end
|
234
240
|
|
235
241
|
def destroy(container)
|
236
242
|
return unless container
|
243
|
+
|
237
244
|
url = self.url('containers', container)
|
238
|
-
agent.delete(
|
245
|
+
res = agent.delete(
|
239
246
|
path: url,
|
240
|
-
expects: [204]
|
247
|
+
expects: [204, 409]
|
241
248
|
)
|
249
|
+
return unless res.status == 409
|
250
|
+
data = JSON.parse(res.body) rescue ({"message" => "could not parse response body: '#{res.body}'"})
|
251
|
+
if data["message"] =~ /removal of container .* is already in progress/
|
252
|
+
logger.info(data["message"])
|
253
|
+
else
|
254
|
+
raise ContainerDeletionFailed.new("could not destroy container #{container}", data)
|
255
|
+
end
|
242
256
|
rescue Excon::Error => e
|
243
|
-
|
257
|
+
logger.error("could not destroy container: #{container}, url: #{url}, error: #{e}")
|
244
258
|
raise
|
245
259
|
end
|
246
260
|
|
data/lib/fpm/fry/command/cook.rb
CHANGED
@@ -2,6 +2,10 @@ require 'fpm/fry/command'
|
|
2
2
|
module FPM; module Fry
|
3
3
|
class Command::Cook < Command
|
4
4
|
|
5
|
+
class BuildFailed < StandardError
|
6
|
+
include FPM::Fry::WithData
|
7
|
+
end
|
8
|
+
|
5
9
|
option '--keep', :flag, 'Keep the container after build'
|
6
10
|
option '--overwrite', :flag, 'Overwrite package', default: true
|
7
11
|
option '--verbose', :flag, 'Verbose output', default: false
|
@@ -20,7 +24,7 @@ module FPM; module Fry
|
|
20
24
|
parameter 'image', 'Docker image to build from'
|
21
25
|
parameter '[recipe]', 'Recipe file to cook', default: 'recipe.rb'
|
22
26
|
|
23
|
-
def initialize(invocation_path, ctx = {}
|
27
|
+
def initialize(invocation_path, ctx = {})
|
24
28
|
@tls = nil
|
25
29
|
require 'digest'
|
26
30
|
require 'fileutils'
|
@@ -205,86 +209,88 @@ module FPM; module Fry
|
|
205
209
|
end
|
206
210
|
|
207
211
|
def pull_base_image!
|
208
|
-
client.pull(image)
|
212
|
+
client.pull(image, platform: platform)
|
209
213
|
rescue Excon::Error
|
210
214
|
logger.error "could not pull base image #{image}"
|
211
215
|
raise
|
212
216
|
end
|
213
217
|
|
214
218
|
def build!
|
215
|
-
|
216
|
-
|
217
|
-
|
218
|
-
|
219
|
-
|
220
|
-
|
221
|
-
|
222
|
-
|
223
|
-
|
224
|
-
|
225
|
-
args[:query] = { platform: platform } if platform
|
226
|
-
res = client.post(args)
|
227
|
-
JSON.parse(res.body)
|
228
|
-
rescue Excon::Error
|
229
|
-
logger.error "could not create #{build_image}, url: #{url}"
|
230
|
-
raise
|
231
|
-
end
|
232
|
-
container = body['Id']
|
233
|
-
begin
|
234
|
-
begin
|
235
|
-
url = client.url('containers',container,'start')
|
236
|
-
client.post(
|
237
|
-
headers: {
|
238
|
-
'Content-Type' => 'application/json'
|
239
|
-
},
|
240
|
-
path: url,
|
241
|
-
expects: [204],
|
242
|
-
body: JSON.generate({})
|
243
|
-
)
|
244
|
-
rescue Excon::Error
|
245
|
-
logger.error "could not start container #{container}, url: #{url}"
|
246
|
-
raise
|
247
|
-
end
|
219
|
+
container = create_build_container
|
220
|
+
start_build_container(container)
|
221
|
+
attach_to_build_container_and_stream_logs(container)
|
222
|
+
wait_for_build_container_to_shut_down(container)
|
223
|
+
yield container
|
224
|
+
ensure
|
225
|
+
unless keep?
|
226
|
+
client.destroy(container) if container
|
227
|
+
end
|
228
|
+
end
|
248
229
|
|
249
|
-
|
250
|
-
|
251
|
-
|
252
|
-
|
253
|
-
|
254
|
-
|
255
|
-
|
256
|
-
|
257
|
-
|
258
|
-
|
259
|
-
|
260
|
-
|
261
|
-
|
262
|
-
|
263
|
-
|
264
|
-
|
265
|
-
|
230
|
+
def create_build_container
|
231
|
+
url = client.url('containers','create')
|
232
|
+
args = {
|
233
|
+
headers: {
|
234
|
+
'Content-Type' => 'application/json'
|
235
|
+
},
|
236
|
+
path: url,
|
237
|
+
expects: [201],
|
238
|
+
body: JSON.generate({"Image" => build_image})
|
239
|
+
}
|
240
|
+
args[:query] = { platform: platform } if platform
|
241
|
+
res = client.post(args)
|
242
|
+
JSON.parse(res.body)['Id']
|
243
|
+
rescue Excon::Error
|
244
|
+
logger.error "could not create #{build_image}, url: #{url}"
|
245
|
+
raise
|
246
|
+
end
|
266
247
|
|
267
|
-
|
268
|
-
|
269
|
-
|
270
|
-
|
271
|
-
|
272
|
-
|
273
|
-
|
274
|
-
|
275
|
-
|
276
|
-
|
277
|
-
|
278
|
-
|
279
|
-
|
280
|
-
|
248
|
+
def start_build_container(container)
|
249
|
+
url = client.url('containers',container,'start')
|
250
|
+
client.post(
|
251
|
+
headers: {
|
252
|
+
'Content-Type' => 'application/json'
|
253
|
+
},
|
254
|
+
path: url,
|
255
|
+
expects: [204],
|
256
|
+
body: JSON.generate({})
|
257
|
+
)
|
258
|
+
rescue Excon::Error
|
259
|
+
logger.error "could not start container #{container}, url: #{url}"
|
260
|
+
raise
|
261
|
+
end
|
281
262
|
|
282
|
-
|
283
|
-
|
284
|
-
|
285
|
-
|
286
|
-
|
263
|
+
def attach_to_build_container_and_stream_logs(container)
|
264
|
+
url = client.url('containers',container,'attach?stderr=1&stdout=1&stream=1&logs=1')
|
265
|
+
client.post(
|
266
|
+
path: url,
|
267
|
+
body: '',
|
268
|
+
expects: [200],
|
269
|
+
middlewares: [
|
270
|
+
StreamParser.new(out,err),
|
271
|
+
Excon::Middleware::Expects,
|
272
|
+
Excon::Middleware::Instrumentor,
|
273
|
+
Excon::Middleware::Mock
|
274
|
+
]
|
275
|
+
)
|
276
|
+
rescue Excon::Error
|
277
|
+
logger.error "could not attach to container #{container}, url: #{url}"
|
278
|
+
raise
|
279
|
+
end
|
280
|
+
|
281
|
+
def wait_for_build_container_to_shut_down(container)
|
282
|
+
res = client.post(
|
283
|
+
path: client.url('containers',container,'wait'),
|
284
|
+
expects: [200],
|
285
|
+
body: ''
|
286
|
+
)
|
287
|
+
json = JSON.parse(res.body)
|
288
|
+
if json["StatusCode"] != 0
|
289
|
+
raise BuildFailed.new("Build script failed with non zero exit code", json)
|
287
290
|
end
|
291
|
+
rescue Excon::Error
|
292
|
+
logger.error "could not wait successfully for container #{container}, url: #{url}"
|
293
|
+
raise
|
288
294
|
end
|
289
295
|
|
290
296
|
def input_package(container)
|
data/lib/fpm/fry/command.rb
CHANGED
@@ -23,7 +23,7 @@ module FPM; module Fry
|
|
23
23
|
extend Forwardable
|
24
24
|
def_delegators :ui, :out, :err, :logger, :tmpdir
|
25
25
|
|
26
|
-
def initialize(invocation_path, ctx = {}
|
26
|
+
def initialize(invocation_path, ctx = {})
|
27
27
|
super
|
28
28
|
@ui = ctx.fetch(:ui){ UI.new(tmpdir: dir) }
|
29
29
|
@client = ctx[:client]
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: fpm-fry
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.8.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Maxime Lagresle
|
@@ -10,10 +10,11 @@ authors:
|
|
10
10
|
- Hannes Georg
|
11
11
|
- Julian Tabel
|
12
12
|
- Dennis Konert
|
13
|
+
- Bruno Escherl
|
13
14
|
autorequire:
|
14
15
|
bindir: bin
|
15
16
|
cert_chain: []
|
16
|
-
date: 2024-
|
17
|
+
date: 2024-12-12 00:00:00.000000000 Z
|
17
18
|
dependencies:
|
18
19
|
- !ruby/object:Gem::Dependency
|
19
20
|
name: excon
|
@@ -35,14 +36,28 @@ dependencies:
|
|
35
36
|
requirements:
|
36
37
|
- - "~>"
|
37
38
|
- !ruby/object:Gem::Version
|
38
|
-
version: '1.
|
39
|
+
version: '1.16'
|
39
40
|
type: :runtime
|
40
41
|
prerelease: false
|
41
42
|
version_requirements: !ruby/object:Gem::Requirement
|
42
43
|
requirements:
|
43
44
|
- - "~>"
|
44
45
|
- !ruby/object:Gem::Version
|
45
|
-
version: '1.
|
46
|
+
version: '1.16'
|
47
|
+
- !ruby/object:Gem::Dependency
|
48
|
+
name: clamp
|
49
|
+
requirement: !ruby/object:Gem::Requirement
|
50
|
+
requirements:
|
51
|
+
- - ">"
|
52
|
+
- !ruby/object:Gem::Version
|
53
|
+
version: 1.1.0
|
54
|
+
type: :runtime
|
55
|
+
prerelease: false
|
56
|
+
version_requirements: !ruby/object:Gem::Requirement
|
57
|
+
requirements:
|
58
|
+
- - ">"
|
59
|
+
- !ruby/object:Gem::Version
|
60
|
+
version: 1.1.0
|
46
61
|
description: deep-fried package builder
|
47
62
|
email: dennis.konert@new-work.se
|
48
63
|
executables:
|
@@ -121,7 +136,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
121
136
|
- !ruby/object:Gem::Version
|
122
137
|
version: '0'
|
123
138
|
requirements: []
|
124
|
-
rubygems_version: 3.
|
139
|
+
rubygems_version: 3.5.22
|
125
140
|
signing_key:
|
126
141
|
specification_version: 4
|
127
142
|
summary: FPM Fry
|