Skip to content

Commit

Permalink
Fix PATH for Windows, add more comments, support kodata for Windows, and
Browse files Browse the repository at this point in the history
rebase
  • Loading branch information
imjasonh committed Jun 22, 2021
1 parent a466c4e commit 49ee391
Showing 1 changed file with 55 additions and 65 deletions.
120 changes: 55 additions & 65 deletions pkg/build/gobuild.go
Original file line number Diff line number Diff line change
Expand Up @@ -162,7 +162,6 @@ func moduleInfo(ctx context.Context, dir string) (*modules, error) {

for {
var info modInfo

err := dec.Decode(&info)
if err == io.EOF {
// all done
Expand Down Expand Up @@ -416,48 +415,29 @@ func appFilename(importpath string) string {
return base
}

func tarAddDirectories(tw *tar.Writer, dir string, creationTime v1.Time) error {
if dir == "." || dir == string(filepath.Separator) {
return nil
}

// Write parent directories first
if err := tarAddDirectories(tw, filepath.Dir(dir), creationTime); err != nil {
return err
}

// write the directory header to the tarball archive
if err := tw.WriteHeader(&tar.Header{
Name: dir,
Typeflag: tar.TypeDir,
// Use a fixed Mode, so that this isn't sensitive to the directory and umask
// under which it was created. Additionally, windows can only set 0222,
// 0444, or 0666, none of which are executable.
Mode: 0555,
ModTime: creationTime.Time,
}); err != nil {
return err
}

return nil
}

// userOwnerAndGroupSID is a magic value needed to make the binary executable
// in a Windows container.
//
// owner: BUILTIN/Users group: BUILTIN/Users ($sddlValue="O:BUG:BU")
const UserOwnerAndGroupSID = "AQAAgBQAAAAkAAAAAAAAAAAAAAABAgAAAAAABSAAAAAhAgAAAQIAAAAAAAUgAAAAIQIAAA=="
const userOwnerAndGroupSID = "AQAAgBQAAAAkAAAAAAAAAAAAAAABAgAAAAAABSAAAAAhAgAAAQIAAAAAAAUgAAAAIQIAAA=="

func tarBinary(name, binary string, creationTime v1.Time, platform *v1.Platform) (*bytes.Buffer, error) {
buf := bytes.NewBuffer(nil)
tw := tar.NewWriter(buf)
defer tw.Close()

// write the parent directories to the tarball archive
// Write the parent directories to the tarball archive.
// For Windows, the layer must contain a Hives/ directory, and the root
// of the actual filesystem goes in a Files/ directory.
// For Linux, the binary goes into /ko-app/
dirs := []string{"ko-app"}
if platform.OS == "windows" {
dirs = []string{
"Hives",
"Files",
"Files/ko-app",
}
name = "Files" + name + ".exe"
}
for _, dir := range dirs {
if err := tw.WriteHeader(&tar.Header{
Expand Down Expand Up @@ -493,10 +473,10 @@ func tarBinary(name, binary string, creationTime v1.Time, platform *v1.Platform)
ModTime: creationTime.Time,
}
if platform.OS == "windows" {
// This is for some reason needed for Windows to be able to
// execute the binary.
// This magic value is for some reason needed for Windows to be
// able to execute the binary.
header.PAXRecords = map[string]string{
"MSWINDOWS.rawsd": UserOwnerAndGroupSID,
"MSWINDOWS.rawsd": userOwnerAndGroupSID,
}
}
// write the header to the tarball archive
Expand Down Expand Up @@ -593,14 +573,27 @@ func (g *gobuild) tarKoData(ref reference, platform *v1.Platform) (*bytes.Buffer

creationTime := g.kodataCreationTime

// Write the parent directories to the tarball archive.
// For Windows, the layer must contain a Hives/ directory, and the root
// of the actual filesystem goes in a Files/ directory.
// For Linux, kodata starts at /var/run/ko.
chroot := kodataRoot
dirs := []string{
"/var",
"/var/run",
"/var/run/ko",
}
if platform.OS == "windows" {
chroot = "Files" + kodataRoot
dirs = []string{
"Hives",
"Files",
"Files/var",
"Files/var/run",
"Files/var/run/ko",
}
}
parts := strings.Split(chroot, "/")
for i := range parts {
dir := strings.Join(parts[:i+1], "/")
// Add an entry for the root directory of our walk.
for _, dir := range dirs {
if err := tw.WriteHeader(&tar.Header{
Name: dir,
Typeflag: tar.TypeDir,
Expand All @@ -610,9 +603,10 @@ func (g *gobuild) tarKoData(ref reference, platform *v1.Platform) (*bytes.Buffer
Mode: 0555,
ModTime: creationTime.Time,
}); err != nil {
return nil, err
return nil, fmt.Errorf("writing dir %q: %v", dir, err)
}
}

return buf, walkRecursive(tw, root, chroot, creationTime)
}

Expand Down Expand Up @@ -640,34 +634,28 @@ func (g *gobuild) buildOne(ctx context.Context, s string, base v1.Image, platfor

var layers []mutate.Addendum

// TODO: skip kodata for windows images for now...
if platform.OS != "windows" {
// Create a layer from the kodata directory under this import path.
dataLayerBuf, err := g.tarKoData(ref, platform)
if err != nil {
return nil, err
}
dataLayerBytes := dataLayerBuf.Bytes()
dataLayer, err := tarball.LayerFromOpener(func() (io.ReadCloser, error) {
return ioutil.NopCloser(bytes.NewBuffer(dataLayerBytes)), nil
}, tarball.WithCompressedCaching)
if err != nil {
return nil, err
}
layers = append(layers, mutate.Addendum{
Layer: dataLayer,
History: v1.History{
Author: "ko",
CreatedBy: "ko publish " + ref.String(),
Comment: "kodata contents, at $KO_DATA_PATH",
},
})
// Create a layer from the kodata directory under this import path.
dataLayerBuf, err := g.tarKoData(ref, platform)
if err != nil {
return nil, err
}
dataLayerBytes := dataLayerBuf.Bytes()
dataLayer, err := tarball.LayerFromOpener(func() (io.ReadCloser, error) {
return ioutil.NopCloser(bytes.NewBuffer(dataLayerBytes)), nil
}, tarball.WithCompressedCaching)
if err != nil {
return nil, err
}
layers = append(layers, mutate.Addendum{
Layer: dataLayer,
History: v1.History{
Author: "ko",
CreatedBy: "ko publish " + ref.String(),
Comment: "kodata contents, at $KO_DATA_PATH",
},
})

appPath := path.Join("/ko-app", appFilename(ref.Path()))
if platform.OS == "windows" {
appPath = "Files" + appPath + ".exe"
}

// Construct a tarball with the binary and produce a layer.
binaryLayerBuf, err := tarBinary(appPath, file, v1.Time{}, platform)
Expand Down Expand Up @@ -707,13 +695,15 @@ func (g *gobuild) buildOne(ctx context.Context, s string, base v1.Image, platfor
}

cfg = cfg.DeepCopy()
cfg.Config.Cmd = nil
cfg.Config.Entrypoint = []string{appPath}
if platform.OS == "windows" {
cfg.Config.Entrypoint = []string{`C:\ko-app\` + appFilename(ref.Path()) + ".exe"}
updatePath(cfg, `C:\ko-app`)
cfg.Config.Env = append(cfg.Config.Env, `KO_DATA_PATH=C:\var\run\ko`)
} else {
appPath = `C:\ko-app`
cfg.Config.Env = append(cfg.Config.Env, "KO_DATA_PATH="+kodataRoot)
}
updatePath(cfg, appPath)
cfg.Config.Env = append(cfg.Config.Env, "KO_DATA_PATH="+kodataRoot)
cfg.Author = "github.com/google/ko"

if cfg.Config.Labels == nil {
Expand Down

0 comments on commit 49ee391

Please sign in to comment.