-
Notifications
You must be signed in to change notification settings - Fork 407
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
feat: wasi platform build #810
Changes from 4 commits
afa76e1
4a3482b
f6284ac
12b6129
9141b2f
3025e00
ee54bac
cfdef4f
727c5d1
120546a
16433a7
21330ab
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,66 @@ | ||
name: Integration test for wasi | ||
|
||
on: | ||
pull_request: | ||
branches: ["main"] | ||
|
||
jobs: | ||
wasi: | ||
strategy: | ||
fail-fast: false | ||
matrix: | ||
platform: | ||
- ubuntu-latest | ||
name: wasi | ||
runs-on: ${{ matrix.platform }} | ||
hown3d marked this conversation as resolved.
Show resolved
Hide resolved
|
||
|
||
steps: | ||
- uses: actions/checkout@v3 | ||
- uses: actions/setup-go@v3 | ||
with: | ||
go-version: 1.18 | ||
check-latest: true | ||
- name: setup tinygo | ||
shell: bash | ||
env: | ||
TINYGO_VERSION: 0.23.0 | ||
run: | | ||
wget https://github.com/tinygo-org/tinygo/releases/download/v"${TINYGO_VERSION}"/tinygo_${TINYGO_VERSION}_amd64.deb | ||
sudo dpkg -i tinygo_${TINYGO_VERSION}_amd64.deb | ||
- name: create crun wasmedge binary | ||
shell: bash | ||
run: | | ||
echo -e "Installing WasmEdge" | ||
if [ -f install.sh ]; then | ||
rm -f install.sh | ||
fi | ||
curl -L -o install.sh -q https://raw.githubusercontent.com/WasmEdge/WasmEdge/master/utils/install.sh | ||
sudo chmod a+x install.sh | ||
sudo bash ./install.sh --path="/usr/local" | ||
rm -rf install.sh | ||
|
||
echo -e "Building and installing crun" | ||
sudo apt install -y make git gcc build-essential pkgconf libtool libsystemd-dev \ | ||
libprotobuf-c-dev libcap-dev libseccomp-dev libyajl-dev \ | ||
go-md2man libtool autoconf python3 automake | ||
|
||
git clone https://github.com/containers/crun /tmp/crun | ||
cd /tmp/crun | ||
./autogen.sh | ||
./configure --with-wasmedge | ||
make | ||
|
||
- name: Build and run ko container | ||
shell: bash | ||
run: | | ||
set -euxo pipefail | ||
export KO_DOCKER_REPO=$(uuidgen |tr "[:upper:]" "[:lower:]") | ||
# Build and run the test/wasi binary, which should print "hello from wasi" | ||
testimg=$(go run ./ build ./test/wasi/ --platform="wasm/wasi") | ||
|
||
# run a nested podman container to use annotations (could be removed once docker is able to specify annotations on containers) | ||
docker run --priviliged \ | ||
-v /tmp/crun/crun:/usr/bin/crun \ | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Is there a way to just run crun directly, instead of having to run it in a container? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I think it's easier to run everything inside a container, because automatically creating OCI bundles is kinda clunky. This approach makes it a bit easier. |
||
quay.io/containers/podman:v4 \ | ||
podman run --runtime=/usr/bin/crun $testimg \ | ||
| grep "hello from wasi" |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,150 @@ | ||
// from https://github.com/google/go-containerregistry/blob/53739b507dcc56b7ff29ee17982d6c5179b77aaa/pkg/v1/mutate/oci.go | ||
|
||
package ociconv | ||
|
||
import ( | ||
"fmt" | ||
|
||
v1 "github.com/google/go-containerregistry/pkg/v1" | ||
"github.com/google/go-containerregistry/pkg/v1/empty" | ||
"github.com/google/go-containerregistry/pkg/v1/match" | ||
"github.com/google/go-containerregistry/pkg/v1/mutate" | ||
"github.com/google/go-containerregistry/pkg/v1/tarball" | ||
"github.com/google/go-containerregistry/pkg/v1/types" | ||
) | ||
|
||
// Drops docker specific properties | ||
// See: https://github.com/opencontainers/image-spec/blob/main/config.md | ||
func toOCIV1Config(config v1.Config) v1.Config { | ||
return v1.Config{ | ||
User: config.User, | ||
ExposedPorts: config.ExposedPorts, | ||
Env: config.Env, | ||
Entrypoint: config.Entrypoint, | ||
Cmd: config.Cmd, | ||
Volumes: config.Volumes, | ||
WorkingDir: config.WorkingDir, | ||
Labels: config.Labels, | ||
StopSignal: config.StopSignal, | ||
} | ||
} | ||
|
||
func toOCIV1ConfigFile(cf *v1.ConfigFile) *v1.ConfigFile { | ||
return &v1.ConfigFile{ | ||
Created: cf.Created, | ||
Author: cf.Author, | ||
Architecture: cf.Architecture, | ||
OS: cf.OS, | ||
OSVersion: cf.OSVersion, | ||
History: cf.History, | ||
RootFS: cf.RootFS, | ||
Config: toOCIV1Config(cf.Config), | ||
} | ||
} | ||
|
||
// OCIImage mutates the provided v1.Image to be OCI compliant v1.Image | ||
// Check image-spec to see which properties are ported and which are dropped. | ||
// https://github.com/opencontainers/image-spec/blob/main/config.md | ||
func OCIImage(base v1.Image) (v1.Image, error) { | ||
// Get original manifest | ||
m, err := base.Manifest() | ||
if err != nil { | ||
return nil, err | ||
} | ||
// Convert config | ||
cfg, err := base.ConfigFile() | ||
if err != nil { | ||
return nil, err | ||
} | ||
cfg = toOCIV1ConfigFile(cfg) | ||
|
||
layers, err := base.Layers() | ||
if err != nil { | ||
return nil, err | ||
} | ||
|
||
newLayers := []v1.Layer{} | ||
|
||
for _, layer := range layers { | ||
mediaType, err := layer.MediaType() | ||
if err != nil { | ||
return nil, err | ||
} | ||
switch mediaType { | ||
case types.DockerLayer: | ||
reader, err := layer.Compressed() | ||
if err != nil { | ||
return nil, fmt.Errorf("getting layer: %w", err) | ||
} | ||
layer, err = tarball.LayerFromReader(reader, tarball.WithMediaType(types.OCILayer)) | ||
if err != nil { | ||
return nil, fmt.Errorf("building layer: %w", err) | ||
} | ||
case types.DockerUncompressedLayer: | ||
reader, err := layer.Uncompressed() | ||
if err != nil { | ||
return nil, fmt.Errorf("getting layer: %w", err) | ||
} | ||
layer, err = tarball.LayerFromReader(reader, tarball.WithMediaType(types.OCIUncompressedLayer)) | ||
if err != nil { | ||
return nil, fmt.Errorf("building layer: %w", err) | ||
} | ||
} | ||
newLayers = append(newLayers, layer) | ||
} | ||
|
||
base, err = mutate.AppendLayers(empty.Image, newLayers...) | ||
if err != nil { | ||
return nil, err | ||
} | ||
|
||
base = mutate.MediaType(base, types.OCIManifestSchema1) | ||
base = mutate.ConfigMediaType(base, types.OCIConfigJSON) | ||
base = mutate.Annotations(base, m.Annotations).(v1.Image) | ||
base, err = mutate.ConfigFile(base, cfg) | ||
if err != nil { | ||
return nil, err | ||
} | ||
return base, nil | ||
} | ||
|
||
// OCIImageIndex mutates the provided v1.ImageIndex to be OCI compliant v1.ImageIndex | ||
func OCIImageIndex(base v1.ImageIndex) (v1.ImageIndex, error) { | ||
hown3d marked this conversation as resolved.
Show resolved
Hide resolved
|
||
base = mutate.IndexMediaType(base, types.OCIImageIndex) | ||
mn, err := base.IndexManifest() | ||
if err != nil { | ||
return nil, err | ||
} | ||
|
||
removals := []v1.Hash{} | ||
addendums := []mutate.IndexAddendum{} | ||
|
||
for _, manifest := range mn.Manifests { | ||
if !manifest.MediaType.IsImage() { | ||
// it is not an image, leave it as is | ||
continue | ||
} | ||
img, err := base.Image(manifest.Digest) | ||
if err != nil { | ||
return nil, err | ||
} | ||
img, err = OCIImage(img) | ||
if err != nil { | ||
return nil, err | ||
} | ||
mt, err := img.MediaType() | ||
if err != nil { | ||
return nil, err | ||
} | ||
removals = append(removals, manifest.Digest) | ||
addendums = append(addendums, mutate.IndexAddendum{Add: img, Descriptor: v1.Descriptor{ | ||
URLs: manifest.URLs, | ||
MediaType: mt, | ||
Annotations: manifest.Annotations, | ||
Platform: manifest.Platform, | ||
}}) | ||
} | ||
base = mutate.RemoveManifests(base, match.Digests(removals...)) | ||
base = mutate.AppendManifests(base, addendums...) | ||
return base, nil | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
❤️❤️❤️