Skip to content

Commit

Permalink
Merge pull request #571 from buildpacks/feature/469-windows-create-bu…
Browse files Browse the repository at this point in the history
…ilder

Support windows images for create-builder
  • Loading branch information
jromero authored May 5, 2020
2 parents 70d22be + 470787a commit 87030a1
Show file tree
Hide file tree
Showing 47 changed files with 1,154 additions and 351 deletions.
13 changes: 9 additions & 4 deletions .github/workflows/build.yml
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ jobs:
strategy:
fail-fast: false
matrix:
os: [macos, linux, windows]
os: [macos, linux, windows-lcow, windows-wcow]
include:
- os: macos
runner: macos-latest
Expand All @@ -25,10 +25,14 @@ jobs:
runner: ubuntu-latest
no_docker: "false"
pack_bin: pack
- os: windows
- os: windows-lcow
runner: [self-hosted, windows]
no_docker: "false"
pack_bin: pack.exe
- os: windows-wcow
runner: windows-latest
no_docker: "false"
pack_bin: pack.exe
runs-on: ${{ matrix.runner }}
env:
PACK_BIN: ${{ matrix.pack_bin }}
Expand All @@ -50,7 +54,7 @@ jobs:
echo "::add-path::$(go env GOPATH)/bin"
- name: Verify
# disabled for windows due to format verification failing
if: matrix.os != 'windows'
if: ${{ !contains(matrix.os, 'windows') }}
run: make verify
- name: Test
env:
Expand Down Expand Up @@ -91,7 +95,8 @@ jobs:
- name: Download artifacts - windows
uses: actions/download-artifact@v1
with:
name: pack-windows
name: pack-windows-lcow
path: pack-windows
- name: Package artifacts - macos
run: |
chmod +x pack-macos/pack
Expand Down
89 changes: 59 additions & 30 deletions acceptance/acceptance_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -300,6 +300,8 @@ func testWithoutSpecificBuilderRequirement(
"pack does not support 'package-buildpack'",
)

h.SkipIf(t, dockerHostOS() == "windows", "These tests are not yet compatible with Windows-based containers")

var err error
tmpDir, err = ioutil.TempDir("", "package-buildpack-tests")
h.AssertNil(t, err)
Expand Down Expand Up @@ -553,13 +555,31 @@ func testAcceptance(
runImageMirror = value
})

when("creating a windows builder", func() {
it.Before(func() {
h.SkipIf(t, dockerHostOS() != "windows", "The current Docker daemon does not support Windows-based containers")
})

it("succeeds", func() {
builderName := createBuilder(t, runImageMirror, configDir, packCreateBuilderPath, lifecyclePath, lifecycleDescriptor)
defer h.DockerRmi(dockerCli, builderName)

inspect, _, err := dockerCli.ImageInspectWithRaw(context.TODO(), builderName)
h.AssertNil(t, err)

h.AssertEq(t, inspect.Os, "windows")
})
})

when("builder is created", func() {
var (
builderName string
tmpDir string
)

it.Before(func() {
h.SkipIf(t, dockerHostOS() == "windows", "These tests are not yet compatible with Windows-based containers")

var err error
tmpDir, err = ioutil.TempDir("", "package-buildpack-tests")
h.AssertNil(t, err)
Expand Down Expand Up @@ -1672,43 +1692,42 @@ func createBuilder(t *testing.T, runImageMirror, configDir, packPath, lifecycleP
h.AssertNil(t, err)
}

// CREATE PACKAGE
packageImageName := packageBuildpackAsImage(t,
packPath,
filepath.Join(configDir, "package.toml"),
lifecycleDescriptor,
[]string{"simple-layers-buildpack"},
)

// RENDER builder.toml
cfgData := fillTemplate(t, filepath.Join(configDir, "builder.toml"), map[string]interface{}{
"package_name": packageImageName,
})
err = ioutil.WriteFile(filepath.Join(tmpDir, "builder.toml"), []byte(cfgData), os.ModePerm)
h.AssertNil(t, err)

builderConfigFile, err := os.OpenFile(filepath.Join(tmpDir, "builder.toml"), os.O_RDWR|os.O_APPEND, os.ModePerm)
h.AssertNil(t, err)
var packageImageName string
var packageId string
if dockerHostOS() != "windows" {
// CREATE PACKAGE
packageImageName = packageBuildpackAsImage(t,
packPath,
filepath.Join(configDir, "package.toml"),
lifecycleDescriptor,
[]string{"simple-layers-buildpack"},
)

// ADD run-image-mirrors
_, err = builderConfigFile.Write([]byte(fmt.Sprintf("run-image-mirrors = [\"%s\"]\n", runImageMirror)))
h.AssertNil(t, err)
packageId = "simple/layers"
}

// ADD lifecycle
_, err = builderConfigFile.Write([]byte("[lifecycle]\n"))
h.AssertNil(t, err)

var lifecycleURI string
var lifecycleVersion string
if lifecyclePath != "" {
t.Logf("adding lifecycle path '%s' to builder config", lifecyclePath)
_, err = builderConfigFile.Write([]byte(fmt.Sprintf("uri = \"%s\"\n", strings.ReplaceAll(lifecyclePath, `\`, `\\`))))
h.AssertNil(t, err)
lifecycleURI = strings.ReplaceAll(lifecyclePath, `\`, `\\`)
} else {
t.Logf("adding lifecycle version '%s' to builder config", lifecycleDescriptor.Info.Version.String())
_, err = builderConfigFile.Write([]byte(fmt.Sprintf("version = \"%s\"\n", lifecycleDescriptor.Info.Version.String())))
h.AssertNil(t, err)
lifecycleVersion = lifecycleDescriptor.Info.Version.String()
}

builderConfigFile.Close()
// RENDER builder.toml
cfgData := fillTemplate(t, filepath.Join(configDir, "builder.toml"), map[string]interface{}{
"package_image_name": packageImageName,
"package_id": packageId,
"run_image_mirror": runImageMirror,
"lifecycle_uri": lifecycleURI,
"lifecycle_version": lifecycleVersion,
})

err = ioutil.WriteFile(filepath.Join(tmpDir, "builder.toml"), []byte(cfgData), os.ModePerm)
h.AssertNil(t, err)

// NAME BUILDER
bldr := registryConfig.RepoName("test/builder-" + h.RandString(10))
Expand Down Expand Up @@ -1793,10 +1812,12 @@ func createStack(t *testing.T, dockerCli client.CommonAPIClient, runImageMirror
t.Helper()
t.Log("creating stack images...")

if err := createStackImage(dockerCli, runImage, filepath.Join("testdata", "mock_stack", "run")); err != nil {
stackBaseDir := filepath.Join("testdata", "mock_stack", dockerHostOS())

if err := createStackImage(dockerCli, runImage, filepath.Join(stackBaseDir, "run")); err != nil {
return err
}
if err := createStackImage(dockerCli, buildImage, filepath.Join("testdata", "mock_stack", "build")); err != nil {
if err := createStackImage(dockerCli, buildImage, filepath.Join(stackBaseDir, "build")); err != nil {
return err
}

Expand Down Expand Up @@ -1991,6 +2012,14 @@ func fillTemplate(t *testing.T, templatePath string, data map[string]interface{}
return expectedOutput.String()
}

func dockerHostOS() string {
daemonInfo, err := dockerCli.Info(context.TODO())
if err != nil {
panic(err.Error())
}
return daemonInfo.OSType
}

// taskKey creates a key from the prefix and all arguments to be unique
func taskKey(prefix string, args ...string) string {
hash := sha256.New()
Expand Down
5 changes: 3 additions & 2 deletions acceptance/testdata/mock_stack/create-stack.sh
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
#!/usr/bin/env bash

dir="$(cd $(dirname $0) && pwd)"
os=$(docker info --format '{{json .}}' | jq -r .OSType)

docker build --tag pack-test/build "$dir"/build
docker build --tag pack-test/run "$dir"/run
docker build --tag pack-test/build "$dir"/$os/build
docker build --tag pack-test/run "$dir"/$os/run
14 changes: 14 additions & 0 deletions acceptance/testdata/mock_stack/windows/build/Dockerfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
FROM mcr.microsoft.com/windows/nanoserver:1809

# placeholder values until correct values are deteremined
ENV CNB_USER_ID=0
ENV CNB_GROUP_ID=0

USER ContainerAdministrator

RUN net users /ADD pack /passwordreq:no /expires:never

LABEL io.buildpacks.stack.id=pack.test.stack
LABEL io.buildpacks.stack.mixins="[\"mixinA\", \"build:mixinTwo\", \"netcat\", \"mixin3\"]"

USER pack
14 changes: 14 additions & 0 deletions acceptance/testdata/mock_stack/windows/run/Dockerfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
FROM mcr.microsoft.com/windows/nanoserver:1809

# placeholder values until correct values are deteremined
ENV CNB_USER_ID=0
ENV CNB_GROUP_ID=0

USER ContainerAdministrator

RUN net users /ADD pack /passwordreq:no /expires:never

LABEL io.buildpacks.stack.id=pack.test.stack
LABEL io.buildpacks.stack.mixins="[\"mixinA\", \"netcat\", \"mixin3\"]"

USER pack
1 change: 1 addition & 0 deletions acceptance/testdata/pack_fixtures/.gitattributes
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
*.txt text eol=lf
17 changes: 14 additions & 3 deletions acceptance/testdata/pack_fixtures/builder.toml
Original file line number Diff line number Diff line change
Expand Up @@ -11,13 +11,17 @@
# noop-buildpack-2 has the same id but a different version compared to noop-buildpack
uri = "noop-buildpack-2.tgz"

{{- if .package_image_name}}
[[buildpacks]]
image = "{{ .package_name }}"
image = "{{.package_image_name}}"
{{- end}}

[[order]]
{{- if .package_id}}
[[order.group]]
id = "simple/layers"
id = "{{.package_id}}"
# intentionlly missing version to test support
{{- end}}

[[order.group]]
id = "read/env"
Expand All @@ -28,5 +32,12 @@
id = "pack.test.stack"
build-image = "pack-test/build"
run-image = "pack-test/run"
run-image-mirrors = ["{{.run_image_mirror}}"]

# run-image-mirror and lifecycle are appended by acceptance tests
[lifecycle]
{{- if .lifecycle_uri}}
uri = "{{.lifecycle_uri}}"
{{- end}}
{{- if .lifecycle_version}}
version = "{{.lifecycle_version}}"
{{- end}}
43 changes: 43 additions & 0 deletions acceptance/testdata/pack_previous_fixtures_overrides/builder.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
[[buildpacks]]
id = "read/env"
version = "read-env-version"
uri = "read-env-buildpack.tgz"

[[buildpacks]]
# intentionally missing id/version as they are optional
uri = "noop-buildpack.tgz"

[[buildpacks]]
# noop-buildpack-2 has the same id but a different version compared to noop-buildpack
uri = "noop-buildpack-2.tgz"

{{- if .package_image_name}}
[[buildpacks]]
image = "{{.package_image_name}}"
{{- end}}

[[order]]
{{- if .package_id}}
[[order.group]]
id = "{{.package_id}}"
# intentionlly missing version to test support
{{- end}}

[[order.group]]
id = "read/env"
version = "read-env-version"
optional = true

[stack]
id = "pack.test.stack"
build-image = "pack-test/build"
run-image = "pack-test/run"
run-image-mirrors = ["{{.run_image_mirror}}"]

[lifecycle]
{{- if .lifecycle_uri}}
uri = "{{.lifecycle_uri}}"
{{- end}}
{{- if .lifecycle_version}}
version = "{{.lifecycle_version}}"
{{- end}}
11 changes: 8 additions & 3 deletions build.go
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ import (
"github.com/buildpacks/pack/internal/buildpack"
"github.com/buildpacks/pack/internal/buildpackage"
"github.com/buildpacks/pack/internal/dist"
"github.com/buildpacks/pack/internal/layer"
"github.com/buildpacks/pack/internal/paths"
"github.com/buildpacks/pack/internal/stack"
"github.com/buildpacks/pack/internal/stringset"
Expand Down Expand Up @@ -104,7 +105,7 @@ func (c *Client) Build(ctx context.Context, opts BuildOptions) error {
return err
}

fetchedBPs, order, err := c.processBuildpacks(ctx, bldr.Buildpacks(), bldr.Order(), opts.Buildpacks, opts.NoPull, opts.Publish, opts.Registry)
fetchedBPs, order, err := c.processBuildpacks(ctx, bldr.Image(), bldr.Buildpacks(), bldr.Order(), opts.Buildpacks, opts.NoPull, opts.Publish, opts.Registry)
if err != nil {
return err
}
Expand Down Expand Up @@ -396,7 +397,7 @@ func (c *Client) processProxyConfig(config *ProxyConfig) ProxyConfig {
// ----------
// - group:
// - A
func (c *Client) processBuildpacks(ctx context.Context, builderBPs []dist.BuildpackInfo, builderOrder dist.Order, declaredBPs []string, noPull bool, publish bool, registry string) (fetchedBPs []dist.Buildpack, order dist.Order, err error) {
func (c *Client) processBuildpacks(ctx context.Context, builderImage imgutil.Image, builderBPs []dist.BuildpackInfo, builderOrder dist.Order, declaredBPs []string, noPull bool, publish bool, registry string) (fetchedBPs []dist.Buildpack, order dist.Order, err error) {
order = dist.Order{{Group: []dist.BuildpackRef{}}}
for _, bp := range declaredBPs {
locatorType, err := buildpack.GetLocatorType(bp, builderBPs)
Expand Down Expand Up @@ -453,7 +454,11 @@ func (c *Client) processBuildpacks(ctx context.Context, builderBPs []dist.Buildp
return fetchedBPs, order, errors.Wrapf(err, "extracting buildpacks from %s", style.Symbol(bp))
}
} else {
mainBP, err = dist.BuildpackFromRootBlob(blob)
layerWriterFactory, err := layer.NewWriterFactory(builderImage)
if err != nil {
return fetchedBPs, order, errors.Wrapf(err, "get tar writer factory for image %s", style.Symbol(builderImage.Name()))
}
mainBP, err = dist.BuildpackFromRootBlob(blob, layerWriterFactory)
if err != nil {
return fetchedBPs, order, errors.Wrapf(err, "creating buildpack from %s", style.Symbol(bp))
}
Expand Down
7 changes: 6 additions & 1 deletion create_builder.go
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ import (
"github.com/buildpacks/pack/internal/builder"
"github.com/buildpacks/pack/internal/dist"
"github.com/buildpacks/pack/internal/image"
"github.com/buildpacks/pack/internal/layer"
"github.com/buildpacks/pack/internal/style"
)

Expand Down Expand Up @@ -101,7 +102,11 @@ func (c *Client) CreateBuilder(ctx context.Context, opts CreateBuilderOptions) e
return errors.Wrapf(err, "downloading buildpack from %s", style.Symbol(b.URI))
}

fetchedBp, err := dist.BuildpackFromRootBlob(blob)
layerWriterFactory, err := layer.NewWriterFactory(bldr.Image())
if err != nil {
return errors.Wrapf(err, "get tar writer factory for image %s", style.Symbol(bldr.Name()))
}
fetchedBp, err := dist.BuildpackFromRootBlob(blob, layerWriterFactory)
if err != nil {
return errors.Wrapf(err, "creating buildpack from %s", style.Symbol(b.URI))
}
Expand Down
4 changes: 2 additions & 2 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,8 @@ require (
github.com/Masterminds/semver v1.5.0
github.com/Microsoft/hcsshim v0.8.7 // indirect
github.com/apex/log v1.1.2
github.com/buildpacks/imgutil v0.0.0-20200313170640-a02052f47d62
github.com/buildpacks/lifecycle v0.7.1
github.com/buildpacks/imgutil v0.0.0-20200424215026-dfdc82949704
github.com/buildpacks/lifecycle v0.7.2
github.com/containerd/containerd v1.3.3 // indirect
github.com/containerd/continuity v0.0.0-20200107194136-26c1120b8d41 // indirect
github.com/dgodd/dockerdial v1.0.1
Expand Down
Loading

0 comments on commit 87030a1

Please sign in to comment.