Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add support for Windows (cross compiled) #108

Merged
merged 43 commits into from
Mar 22, 2024

Conversation

pmengelbert
Copy link
Contributor

Very rough, mostly looking to get feedback. To test (of course with the re-built frontend):

docker build -f test/fixtures/moby-containerd.yml --target=windows/zip --output=_zip .

Copy link
Member

@cpuguy83 cpuguy83 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

For tests, I'd like to move over to using the new integration test suite.
Additionally I really don't want to be building containerd (or runc) on every test run.

This is part of why I'm pushing for inline sources (#98).
We can test that a spec does everything we expect it to without having to build a bunch of projects.

We can of course add an e2e suite (later) that double checks real projects, but probably I'd only run it either on merge or before releases.

@pmengelbert
Copy link
Contributor Author

pmengelbert commented Feb 7, 2024 via email

@pmengelbert pmengelbert requested a review from a team as a code owner March 9, 2024 23:25
@cpuguy83
Copy link
Member

Looks like the rebase on this was incomplete.
Code is not compiling.

@pmengelbert
Copy link
Contributor Author

Looks like the rebase on this was incomplete. Code is not compiling.

Working on it now

)

var (
varCacheAptMount = llb.AddMount("/var/cache/apt", llb.Scratch(), llb.AsPersistentCacheDir("dalec-windows-var-cache-apt", llb.CacheMountLocked))
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

For these to work, we also need to remove /etc/apt/apt.conf.d/docker-clean from the base image.
You should be able to acheive this by mounting over the file, like llb.AddMount("/etc/apt/apt.conf.d/docker-clean", llb.Scratch())

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Just a thought, you could have all this stored as a RunOpt.

Copy link
Contributor Author

@pmengelbert pmengelbert Mar 15, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

  • (Peter) Fix this

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

done

Comment on lines 1 to 98
# syntax=ghcr.io/azure/dalec/frontend:latest

# TODO: The spec is not currently setting the revision in the containerd version
# This should be fixed before this spec is used to build a real package.

args:
CONTAINERD_COMMIT: 7c3aca7a610df76212171d200ca3811ff6096eb8
REVISION: 1
VERSION: "1.7.13"
HCS_SHIM_REPO: https://github.com/Microsoft/hcsshim.git

name: moby-containerd
description: |
Industry-standard container runtime
containerd is an industry-standard container runtime with an emphasis on
simplicity, robustness and portability. It is available as a daemon for Linux
and Windows, which can manage the complete container lifecycle of its host
system: image transfer and storage, container execution and supervision,
low-level storage and network attachments, etc.
.
containerd is designed to be embedded into a larger system, rather than being
used directly by developers or end-users.
website: https://containerd.io/
version: ${VERSION}
revision: ${REVISION}
vendor: Moby

targets: # Distro specific build requirements
windows:
dependencies:
build:
golang-1.20:

packager: Microsoft <[email protected]>
license: Apache 2.0
sources:
containerd:
git:
url: https://github.com/containerd/containerd.git
commit: "${CONTAINERD_COMMIT}"
hcsshim:
path: /build/_out
image:
ref: mcr.microsoft.com/oss/go/microsoft/golang:1.20
cmd:
dir: /build/containerd
steps:
- command: |
apt update && apt install -y jq
shim_mod_dir="$(
go mod download -json github.com/Microsoft/hcsshim | jq -r '.Dir'
)"
chmod +w -R "$shim_mod_dir"
mv "$shim_mod_dir"/* /build/_out
cd /build/_out
go mod vendor
mounts:
- dest: /build/containerd/go.mod
spec:
path: /go.mod
git:
url: https://github.com/containerd/containerd.git
commit: "${CONTAINERD_COMMIT}"


build:
env:
CGO_ENABLED: 1
GOOS: windows
GOGC: "off"
GOPROXY: "off"
GOFLAGS: -trimpath
VERSION: ${VERSION}
COMMIT: ${CONTAINERD_COMMIT}
GOROOT: /usr/lib/go-1.20
CC: x86_64-w64-mingw32-gcc
steps:
- command: |
set -e
export PATH="${GOROOT}/bin:${PATH}"
cd containerd
make VERSION="$VERSION" REVISION="$COMMIT" DESTDIR=./bin binaries
rm -f bin/containerd-stress.exe
- command: |
set -e
export PATH="${GOROOT}/bin:${PATH}"
cd hcsshim
GO111MODULE=on go build \
-mod=vendor \
-o bin/containerd-shim-runhcs-v1.exe \
./cmd/containerd-shim-runhcs-v1

artifacts:
binaries:
hcsshim/bin/containerd-shim-runhcs-v1.exe:
containerd/bin/containerd.exe:
containerd/bin/ctr.exe:
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can we move this to an integration test?

We do have a (somewhat) generic test function that could possible be reused here.
It may need an extra option or something since we can't really test any container output at this time.

Copy link
Contributor Author

@pmengelbert pmengelbert Mar 11, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

  • Move yaml fixtures to integration test suit

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

done

@pmengelbert
Copy link
Contributor Author

Just pushed a few changes. We should have a working container target, but I haven't migrated the test yet.

Copy link
Member

@cpuguy83 cpuguy83 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think we need to validate the spec for runtime dependencies for Windows, since TMK, we don't really have any way to support that.

frontend/windows/handler.go Outdated Show resolved Hide resolved
)

var (
varCacheAptMount = llb.AddMount("/var/cache/apt", llb.Scratch(), llb.AsPersistentCacheDir("dalec-windows-var-cache-apt", llb.CacheMountLocked))
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Just a thought, you could have all this stored as a RunOpt.


func SpecToSourcesLLB(spec *dalec.Spec, sOpt dalec.SourceOpts) (map[string]llb.State, error) {
m := make(map[string]llb.State, len(spec.Sources))
keys := dalec.SortMapKeys(spec.Sources)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This sorting isn't doing anything since it is putting everything back into a map.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The calls to AsState don't matter? I was thinking that because we're manipulating LLB we want to do them in the same order so we don't get cache misses. LMK if that doesn't matter here.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The states are all separate from each other and do not interact at all until we actually copy them to a merged llb.State.

Copy link
Contributor Author

@pmengelbert pmengelbert Mar 18, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

  • Remove sorting here

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

done

f(ei)
}

func SpecToSourcesLLB(spec *dalec.Spec, sOpt dalec.SourceOpts) (map[string]llb.State, error) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can we unexport this?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

done

frontend/windows/handle_zip.go Outdated Show resolved Hide resolved
Creates the broad structure for a windows target. Modeled after the
mariner target.

Signed-off-by: Peter Engelbert <[email protected]>
Inspired by github.com/Azure/moby-packaging

Signed-off-by: Peter Engelbert <[email protected]>
This will be used for testing during the development of the target.

Signed-off-by: Peter Engelbert <[email protected]>
Signed-off-by: Peter Engelbert <[email protected]>
Signed-off-by: Peter Engelbert <[email protected]>
Currently this has only been tested for the moby-containerd spec in
test/fixtures.

Signed-off-by: Peter Engelbert <[email protected]>
Signed-off-by: Peter Engelbert <[email protected]>
Signed-off-by: Peter Engelbert <[email protected]>
Signed-off-by: Peter Engelbert <[email protected]>
Signed-off-by: Peter Engelbert <[email protected]>
Signed-off-by: Peter Engelbert <[email protected]>
This reverts commit 251a6b1.
Please the linter

Signed-off-by: Peter Engelbert <[email protected]>
image.go Outdated Show resolved Hide resolved
source.go Show resolved Hide resolved
Signed-off-by: Peter Engelbert <[email protected]>
Signed-off-by: Peter Engelbert <[email protected]>

Refactor

Signed-off-by: Peter Engelbert <[email protected]>

Revert "Refactor"

This reverts commit 9ac4675b4c3d3c19539266b5f20d76f97e9d6b84.
This reverts parts of commit 845d6a1.

Signed-off-by: Peter Engelbert <[email protected]>
return &img, nil
}

func getBaseOutputImage(spec *dalec.Spec, target, defaultBase string) string {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Let's make this exported.
Then we can pass in the output of this as in input to BuildImageConfig, which removes a function paramerter for BuildImageConfig.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

done

test/windows_test.go Show resolved Hide resolved
Dockerfile Outdated
@@ -4,8 +4,8 @@ FROM go AS frontend-build
WORKDIR /build
COPY . .
ENV CGO_ENABLED=0 GOFLAGS=-trimpath
ARG TARGETARCH TARGETOS
ENV GOOS=${TARGETOS} GOARCH=${TARGETARCH}
ARG TARGETARCH TARGETOS GOFLAGS
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What's the purpose of this?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The purpose of this is to make it easier to build the binaries with debug symbols and without optimizations. I find it helpful to compile a debug version, and then attach to the frontend process with a debugger. I had been manually editing the Dockerfile to add -gcflags=all="-N -l" in the go compilation commands. I kept accidentally checking in the changes. It also got annoying having to add it over and over.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think this would need to go above the ENV line with GOFLAGS with the default value for the arg as -trimpath.

source.go Outdated
states[sourceName] = patchSource(worker, sourceState, states, patches, withConstraints(opts))

var nestedPath string
if SourceIsDir(spec.Sources[sourceName]) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is new behavior that is not mimicked in the rpm patcher.
Was there a particular reason to add it?

Copy link
Contributor

@adamperlin adamperlin Mar 21, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think the reason it was added here (correct me if I'm wrong @pmengelbert) is because specToSourcesLLB takes the extra step of nesting a source within a directory in the LLB itself. I.e., the LLB contains the directory as well as the contents. I think that nesting step could be moved out of spectToSourcesLLB (if indeed it is needed), so we don't have to handle that behavior here. Otherwise, we could use patch -d which I believe is how it works in the rpm patcher?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@adamperlin yes that's correct. I went back and changed specToSourcesLLB so that it doesn't nest the sources in the directories. Now that's happening in the RunOpt that mounts the sources. I restored the two patching functions (the public and private) to the original versions. This is much cleaner. Thanks for pointing this out @cpuguy83.

This is done

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is not done. Working on it now.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Now this is done.

case 1:
platform = bc.TargetPlatforms[0]
default:
return ocispecs.Platform{}, fmt.Errorf("multiple targets for a windows build, only amd64 is supported")
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This error mentions amd64 but doesn't validate it.
Also I'm not sure why it would matter since we aren't trying to run anything.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We are making sure there are not multiple platforms specified. Because only one platform is supported (windows/amd64), if there is more than one platform requested by the user, the request cannot be satisfied.

The amd64 mention was an attempt at providing additional information. The idea was to tell the user, "try again, but only with amd64".

I improved the error message. LMK if you want something different.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

done unless you want me to change it again.

Dockerfile Outdated
Comment on lines 6 to 8
ENV CGO_ENABLED=0 GOFLAGS=-trimpath
ARG TARGETARCH TARGETOS
ENV GOOS=${TARGETOS} GOARCH=${TARGETARCH}
ARG TARGETARCH TARGETOS GOFLAGS
ENV GOOS=${TARGETOS} GOARCH=${TARGETARCH} GOFLAGS=${GOFLAGS}
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
ENV CGO_ENABLED=0 GOFLAGS=-trimpath
ARG TARGETARCH TARGETOS
ENV GOOS=${TARGETOS} GOARCH=${TARGETARCH}
ARG TARGETARCH TARGETOS GOFLAGS
ENV GOOS=${TARGETOS} GOARCH=${TARGETARCH} GOFLAGS=${GOFLAGS}
ENV CGO_ENABLED=0
ARG TARGETARCH TARGETOS GOFLAGS=-trimpath

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

done

Makes running the frontend in a container much easier

Signed-off-by: Peter Engelbert <[email protected]>
The files are actually copied to their new locations, rather than
linked. This will likely change in the future when Windows-in-buildkit
reaches stable status.

Signed-off-by: Peter Engelbert <[email protected]>
@cpuguy83 cpuguy83 merged commit ee11e7b into Azure:main Mar 22, 2024
9 checks passed
@cpuguy83
Copy link
Member

Great work, @pmengelbert.
Thanks for working through the constant back and forth on the review on this one.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants