Skip to content
This repository was archived by the owner on Mar 11, 2020. It is now read-only.

Commit 05a696f

Browse files
committedJan 21, 2017
Named volume packager transport. Full stream reader implementation.
Signed-off-by: Jeff Nickoloff <[email protected]>
1 parent 934c5e8 commit 05a696f

File tree

5 files changed

+86
-41
lines changed

5 files changed

+86
-41
lines changed
 

‎demo.vmdk

Whitespace-only changes.

‎junk.vmdk

Whitespace-only changes.

‎system/system.go

+77-36
Original file line numberDiff line numberDiff line change
@@ -3,12 +3,15 @@ package system
33
import (
44
"bytes"
55
"crypto/sha256"
6+
"encoding/binary"
67
"fmt"
78
"io"
89
"context"
10+
"os"
911
"strings"
1012
"github.com/docker/v2c/api"
1113
"github.com/docker/docker/api/types"
14+
"github.com/docker/docker/api/types/volume"
1215
"github.com/docker/docker/api/types/filters"
1316
"github.com/docker/docker/api/types/container"
1417
"github.com/docker/docker/api/types/network"
@@ -124,23 +127,40 @@ func RemoveProducts(is []string, f bool, p bool) ([]types.ImageDelete, error) {
124127
return result, nil
125128
}
126129

127-
func LaunchPackager(ctx context.Context, p api.Packager) (string, error) {
130+
func LaunchPackager(ctx context.Context, p api.Packager, input string) (string, error) {
128131
client, err := docker.NewEnvClient()
129132
if err != nil {
130133
return ``, err
131134
}
132135

136+
// verify absent and create a named volume
137+
volname := `v2c-transport`
138+
if _, err = client.VolumeInspect(gcontext.Background(), volname); err == nil {
139+
// TODO: Disable for release, but leave for testing
140+
//return ``, fmt.Errorf(`The v2c-transport volume already exists.`)
141+
return ``, nil
142+
}
143+
if _, err = client.VolumeCreate(gcontext.Background(), volume.VolumesCreateBody{
144+
Name: volname,
145+
Driver: `local`,
146+
}); err != nil {
147+
return ``, err
148+
}
149+
150+
fmt.Printf("Creating container for %v:%v\n", p.Repository, p.Tag)
133151
// Create
134152
createResult, err := client.ContainerCreate(gcontext.Background(),
135153
&container.Config{
136154
Image: fmt.Sprintf(`%v:%v`, p.Repository, p.Tag),
137155
},
138156
&container.HostConfig{
139157
NetworkMode: `none`,
158+
Binds: []string{
159+
fmt.Sprintf(`%s:/input/input.vmdk`, input),
160+
fmt.Sprintf(`%s:/v2c`, volname),
161+
},
140162
},
141-
&network.NetworkingConfig{
142-
143-
},
163+
&network.NetworkingConfig{},
144164
fmt.Sprintf("%x", sha256.Sum256([]byte(fmt.Sprintf("%v/%v", p.Repository, p.Tag)))),
145165
)
146166
if err != nil {
@@ -150,14 +170,26 @@ func LaunchPackager(ctx context.Context, p api.Packager) (string, error) {
150170
// Run
151171
err = client.ContainerStart(gcontext.Background(),
152172
createResult.ID,
153-
types.ContainerStartOptions{
154-
155-
},
173+
types.ContainerStartOptions{},
156174
)
157175
if err != nil {
158176
return ``, err
159177
}
160178

179+
// Wait for the container to stop
180+
code, err := client.ContainerWait(gcontext.Background(), createResult.ID)
181+
if err != nil {
182+
panic(err)
183+
}
184+
if code != 0 {
185+
logs, err := client.ContainerLogs(gcontext.Background(), createResult.ID, types.ContainerLogsOptions{})
186+
if err != nil && logs != nil{
187+
defer logs.Close()
188+
io.Copy(os.Stderr, logs)
189+
}
190+
return ``, fmt.Errorf(`The packager failed with code: %v`, code)
191+
}
192+
161193
// return container ID
162194
return createResult.ID, nil
163195
}
@@ -169,20 +201,18 @@ func LaunchDetective(ctx context.Context, pc string, c chan *bytes.Buffer, d api
169201
}
170202

171203
// Start a container from the image described by d
172-
// include Volumes From pc
173204

205+
fmt.Printf("Creating container for %v:%v\n", d.Repository, d.Tag)
174206
// Create
175207
createResult, err := client.ContainerCreate(gcontext.Background(),
176208
&container.Config{
177209
Image: fmt.Sprintf(`%v:%v`, d.Repository, d.Tag),
178210
},
179211
&container.HostConfig{
180-
VolumesFrom: []string{pc},
212+
Binds: []string{ `v2c-transport:/v2c:ro` },
181213
NetworkMode: `none`,
182214
},
183-
&network.NetworkingConfig{
184-
185-
},
215+
&network.NetworkingConfig{},
186216
fmt.Sprintf("%x", sha256.Sum256([]byte(fmt.Sprintf("%v/%v", d.Repository, d.Tag)))),
187217
)
188218
if err != nil {
@@ -199,33 +229,38 @@ func LaunchDetective(ctx context.Context, pc string, c chan *bytes.Buffer, d api
199229
// Run
200230
err = client.ContainerStart(gcontext.Background(),
201231
createResult.ID,
202-
types.ContainerStartOptions{
203-
204-
},
232+
types.ContainerStartOptions{},
205233
)
206234
if err != nil {
207235
panic(err)
208236
}
209237

210-
// Skip the first 8 bytes...
211-
// TODO: do something a bit more purposeful
212-
_, err = attachment.Reader.Discard(8)
213-
if err != nil {
214-
panic(err)
215-
}
216-
217-
// Read from attachment until conn is closed or eof or whatever...
238+
// Copy the buffer
218239
stdout := new(bytes.Buffer)
219-
_, err = io.Copy(stdout, attachment.Reader)
220-
if err != nil && err != io.EOF {
240+
for {
241+
if _, err = attachment.Reader.Discard(4); err != nil {
242+
break
243+
}
244+
var chunkSize uint32
245+
if err = binary.Read(attachment.Reader, binary.BigEndian, &chunkSize); err != nil {
246+
break
247+
}
248+
if _, err = io.CopyN(stdout, attachment.Reader, int64(chunkSize)); err != nil {
249+
break
250+
}
251+
}
252+
if err != io.EOF {
221253
panic(err)
222254
}
223255

256+
224257
// Wait for the container to stop
225-
code, err := client.ContainerWait(ctx, createResult.ID)
258+
var code int64
259+
code, err = client.ContainerWait(ctx, createResult.ID)
226260
if err != nil {
227261
panic(err)
228262
}
263+
229264
if code != 0 {
230265
fmt.Printf("No results for %v:%v code: %v\n", d.Repository, d.Tag ,code)
231266
stdout = nil
@@ -248,6 +283,7 @@ func LaunchProvisioner(ctx context.Context, in *bytes.Buffer, c chan *bytes.Buff
248283
panic(err)
249284
}
250285

286+
fmt.Printf("Creating container for %v:%v\n", p.Repository, p.Tag)
251287
// Start a container from the image described by p
252288
createResult, err := client.ContainerCreate(gcontext.Background(),
253289
&container.Config{
@@ -293,20 +329,25 @@ func LaunchProvisioner(ctx context.Context, in *bytes.Buffer, c chan *bytes.Buff
293329
}
294330
attachment.CloseWrite()
295331

296-
// Skip the first 8 bytes...
297-
// TODO: do something a bit more purposeful
298-
_, err = attachment.Reader.Discard(8)
299-
if err != nil {
300-
panic(err)
301-
}
302-
303-
// read from attachment until conn is closed or eof or whatever...
332+
// Copy the buffer
304333
stdout := new(bytes.Buffer)
305-
_, err = io.Copy(stdout, attachment.Reader)
306-
if err != nil && err != io.EOF {
334+
for {
335+
if _, err = attachment.Reader.Discard(4); err != nil {
336+
break
337+
}
338+
var chunkSize uint32
339+
if err = binary.Read(attachment.Reader, binary.BigEndian, &chunkSize); err != nil {
340+
break
341+
}
342+
if _, err = io.CopyN(stdout, attachment.Reader, int64(chunkSize)); err != nil {
343+
break
344+
}
345+
}
346+
if err != io.EOF {
307347
panic(err)
308348
}
309349

350+
310351
// Wait for the container to stop
311352
code, err := client.ContainerWait(ctx, createResult.ID)
312353
if err != nil {

‎workflow/default.go

+6-5
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,7 @@ func Build(ctx context.Context, target string) (string, error) {
3636
packager := choosePackager(components)
3737

3838
// Launch the Packager
39-
pc, err := system.LaunchPackager(ctx, packager)
39+
pc, err := system.LaunchPackager(ctx, packager, target)
4040
if err != nil {
4141
return ``, err
4242
}
@@ -55,9 +55,11 @@ func Build(ctx context.Context, target string) (string, error) {
5555
pCount := len(detected)
5656

5757
// Shutdown the Packager
58-
err = system.RemoveContainer(ctx, pc)
59-
if err != nil {
60-
return ``, err
58+
if len(pc) > 0 {
59+
err = system.RemoveContainer(ctx, pc)
60+
if err != nil {
61+
return ``, err
62+
}
6163
}
6264

6365
// Should quit early?
@@ -118,7 +120,6 @@ func Build(ctx context.Context, target string) (string, error) {
118120

119121
func launchProvisioners(ctx context.Context, components system.Components, c chan provisionerResponse, rs *[]detectiveResponse) error {
120122
for _, r := range *rs {
121-
// TODO: replace the following with a lookup for the detectiveResponse.Next
122123
var p api.Provisioner
123124
for _, p = range components.Provisioners {
124125
if s := fmt.Sprintf("%v:%v", p.Repository, p.Tag); s == r.Next {

‎workflow/visitors.go

+3
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,9 @@ func addProductMetadata() error {
1414
}
1515

1616
func applyOSCategory(c []manifest) error {
17+
if len(c) < 1 {
18+
return errors.New(`No operating system detected or provisioned.`)
19+
}
1720
if len(c) > 1 {
1821
return errors.New(`OS category contains multiple results.`)
1922
}

0 commit comments

Comments
 (0)
This repository has been archived.