Last active
March 12, 2018 14:42
-
-
Save StefanScherer/c55fd0ae752687c806f8d5fb40cadc78 to your computer and use it in GitHub Desktop.
packer 1.2.1 produces 0 byte vmdk
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
in/ | |
*.tar |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/bin/bash | |
docker build -t gotar . | |
docker create gotar | |
docker cp $(docker ps -ql):/go/src/app/dirtobox . |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package main | |
import ( | |
"archive/tar" | |
"compress/flate" | |
"encoding/json" | |
"fmt" | |
"io" | |
"log" | |
"os" | |
"path/filepath" | |
"runtime" | |
"github.com/klauspost/pgzip" | |
) | |
var ( | |
// ErrInvalidCompressionLevel is returned when the compression level passed | |
// to gzip is not in the expected range. See compress/flate for details. | |
ErrInvalidCompressionLevel = fmt.Errorf( | |
"Invalid compression level. Expected an integer from -1 to 9.") | |
) | |
// Copies a file by copying the contents of the file to another place. | |
func CopyContents(dst, src string) error { | |
srcF, err := os.Open(src) | |
if err != nil { | |
return err | |
} | |
defer srcF.Close() | |
dstDir, _ := filepath.Split(dst) | |
if dstDir != "" { | |
err := os.MkdirAll(dstDir, 0755) | |
if err != nil { | |
return err | |
} | |
} | |
dstF, err := os.Create(dst) | |
if err != nil { | |
return err | |
} | |
defer dstF.Close() | |
if _, err := io.Copy(dstF, srcF); err != nil { | |
return err | |
} | |
return nil | |
} | |
// Creates a (hard) link to a file, ensuring that all parent directories also exist. | |
func LinkFile(dst, src string) error { | |
dstDir, _ := filepath.Split(dst) | |
if dstDir != "" { | |
err := os.MkdirAll(dstDir, 0755) | |
if err != nil { | |
return err | |
} | |
} | |
if err := os.Link(src, dst); err != nil { | |
return err | |
} | |
return nil | |
} | |
// DirToBox takes the directory and compresses it into a Vagrant-compatible | |
// box. This function does not perform checks to verify that dir is | |
// actually a proper box. This is an expected precondition. | |
func DirToBox(dst, dir string, level int) error { | |
log.Printf("Turning dir into box: %s => %s", dir, dst) | |
// Make the containing directory, if it does not already exist | |
err := os.MkdirAll(filepath.Dir(dst), 0755) | |
if err != nil { | |
return err | |
} | |
dstF, err := os.Create(dst) | |
if err != nil { | |
return err | |
} | |
defer dstF.Close() | |
var dstWriter io.WriteCloser = dstF | |
if level != flate.NoCompression { | |
log.Printf("Compressing with gzip compression level: %d", level) | |
gzipWriter, err := makePgzipWriter(dstWriter, level) | |
if err != nil { | |
return err | |
} | |
defer gzipWriter.Close() | |
dstWriter = gzipWriter | |
} | |
tarWriter := tar.NewWriter(dstWriter) | |
defer tarWriter.Close() | |
// This is the walk func that tars each of the files in the dir | |
tarWalk := func(path string, info os.FileInfo, prevErr error) error { | |
// If there was a prior error, return it | |
if prevErr != nil { | |
return prevErr | |
} | |
// Skip directories | |
if info.IsDir() { | |
log.Printf("Skipping directory '%s' for box '%s'", path, dst) | |
return nil | |
} | |
log.Printf("Box add: '%s' to '%s'", path, dst) | |
f, err := os.Open(path) | |
if err != nil { | |
return err | |
} | |
defer f.Close() | |
header, err := tar.FileInfoHeader(info, "") | |
if err != nil { | |
return err | |
} | |
// We have to set the Name explicitly because it is supposed to | |
// be a relative path to the root. Otherwise, the tar ends up | |
// being a bunch of files in the root, even if they're actually | |
// nested in a dir in the original "dir" param. | |
header.Name, err = filepath.Rel(dir, path) | |
if err != nil { | |
return err | |
} | |
fmt.Println("Compressing: %s", header.Name) | |
if err := tarWriter.WriteHeader(header); err != nil { | |
return err | |
} | |
if _, err := io.Copy(tarWriter, f); err != nil { | |
return err | |
} | |
return nil | |
} | |
// Tar.gz everything up | |
return filepath.Walk(dir, tarWalk) | |
} | |
// WriteMetadata writes the "metadata.json" file for a Vagrant box. | |
func WriteMetadata(dir string, contents interface{}) error { | |
if _, err := os.Stat(filepath.Join(dir, "metadata.json")); os.IsNotExist(err) { | |
f, err := os.Create(filepath.Join(dir, "metadata.json")) | |
if err != nil { | |
return err | |
} | |
defer f.Close() | |
enc := json.NewEncoder(f) | |
return enc.Encode(contents) | |
} | |
return nil | |
} | |
func makePgzipWriter(output io.WriteCloser, compressionLevel int) (io.WriteCloser, error) { | |
gzipWriter, err := pgzip.NewWriterLevel(output, compressionLevel) | |
if err != nil { | |
return nil, ErrInvalidCompressionLevel | |
} | |
gzipWriter.SetConcurrency(500000, runtime.GOMAXPROCS(-1)) | |
return gzipWriter, nil | |
} | |
func main() { | |
DirToBox("out.tar", "in", 0) | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
FROM golang:1.10 | |
WORKDIR /go/src/app | |
COPY . . | |
RUN go get -d -v ./... | |
RUN GOOS=darwin go build dirtobox.go |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment