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

feat: wasi platform build #738

Closed
wants to merge 8 commits into from
Closed

feat: wasi platform build #738

wants to merge 8 commits into from

Conversation

hown3d
Copy link

@hown3d hown3d commented Jun 30, 2022

This PR implements the scenario described in #675 by using tinygo as the builder for target WASI.

Documentation is not yet done, but can be created if this feature is wanted.

SBOM generation is currently not implemented, since tinygo doesn't produce the same buildInfo that go does.

Signed-off-by: Höhl, Lukas [email protected]

Signed-off-by: Höhl, Lukas <[email protected]>
@imjasonh imjasonh self-requested a review June 30, 2022 13:27
Copy link
Member

@imjasonh imjasonh left a comment

Choose a reason for hiding this comment

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

First of all, this is great. Thank you for putting in the time to hack on this, I think wasm is really exciting and I'm excited that ko might work with it.

I need some time to play with it before I'm confident this works (I believe you, I just don't know enough yet about the platform's expectations to know by looking).

I'd also like to think through what the UX of building a multiplatform image is, when one of those platforms is wasm. Historically, ko has only built for platforms provided by the base image, and in this case we're adding a new platform that isn't provided by any base image, but should still show up in the final image. So that's going to be weird, but nothing we can't address with enough integration tests and docs.

Thanks again for sending this, let me chew on it and play around with it a bit, but this looks really promising so far.

pkg/build/gobuild.go Outdated Show resolved Hide resolved
pkg/build/gobuild.go Outdated Show resolved Hide resolved
@@ -689,6 +705,8 @@ func (g *gobuild) configForImportPath(ip string) Config {
return config
}

const wasmLayerAnnotationKey = "module.wasm.image/variant"
Copy link
Member

Choose a reason for hiding this comment

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

Is this annotation documented anywhere? What expects to read it?

Copy link
Author

Choose a reason for hiding this comment

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

Specification of this annotation are here: https://github.com/solo-io/wasm/blob/master/spec/spec-compat.md

crun also has an experimental annotation run.oci.handler which can be used to specifiy the handler for the container (e.g. wasm, wasm-smart). More in https://man.archlinux.org/man/crun.1.en

appPath := path.Join(appDir, appFilename(ref.Path()))
var filename string
if platform.String() == "wasm/wasi" {
// module.wasm.image/variant=compat-smart expects the entrypoint binary to be of form .wasm
Copy link
Member

Choose a reason for hiding this comment

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

Can you link to where this expectation is documented? I'd also just love to learn more about runtimes that run these things.

Copy link
Author

Choose a reason for hiding this comment

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

I'm currently focusing on the implementation in crun: https://github.com/containers/crun/blob/main/src/libcrun/handlers/handler-utils.c

https://github.com/containers/crun/blob/65028ce3057180395a1826d8c0906f9ff299030a/src/libcrun/custom-handler.c#L208 will check all the registered handlers by calling wasm_can_handle_container function from handler-utils.c.

pkg/build/gobuild.go Outdated Show resolved Hide resolved
@@ -784,7 +817,7 @@ func (g *gobuild) buildOne(ctx context.Context, refStr string, base v1.Image, pl
cfg.Config.Entrypoint = []string{`C:\ko-app\` + appFilename(ref.Path())}
updatePath(cfg, `C:\ko-app`)
cfg.Config.Env = append(cfg.Config.Env, `KO_DATA_PATH=C:\var\run\ko`)
} else {
} else if platform.String() != "wasm/wasi" {
Copy link
Member

Choose a reason for hiding this comment

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

If we keep doing this comparison, I wonder if it warrants having a helper method isWasi(platform) (and isWindows(platform)) to make this easier to read.

Then we can also avoid the string comparison without bloating the callsite:

func isWasi(p v1.Platform) bool {
  return p.OS == "wasm" && p.Architecture == "wasi"
}

Copy link
Author

Choose a reason for hiding this comment

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

Yes, this is a good idea. The constant comparison with platform string was kinda hacky anyway.

Comment on lines 945 to 950
// user specified a platform, so force this platform, even if it fails
var platform *v1.Platform
if len(g.platformMatcher.platforms) == 1 {
platform = &g.platformMatcher.platforms[0]
}
res, err = g.buildOne(ctx, s, baseImage, platform)
Copy link
Member

Choose a reason for hiding this comment

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

Why's this necessary?

Copy link
Author

@hown3d hown3d Jun 30, 2022

Choose a reason for hiding this comment

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

platform had been set to nil otherwise, which would remove the possibility to check for the platform string in the build function: https://github.com/hown3d/ko/blob/ceac5e5fcea61bea80231a689bb990cce3198827/pkg/build/gobuild.go#L274

Copy link
Member

Choose a reason for hiding this comment

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

Ah okay. In that case, I think we can remove this check here: https://github.com/hown3d/ko/blob/ceac5e5fcea61bea80231a689bb990cce3198827/pkg/build/gobuild.go#L722

This does make me wonder how ko will behave (before and after this change) when asked to build on top of a single-platform image that isn't linux/amd64, with --platform unset... 🤔

Copy link
Author

@hown3d hown3d Jun 30, 2022

Choose a reason for hiding this comment

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

I created a single platform image (no OS or Architecture set) here: https://quay.io/repository/hown3d/ko-wasm-tests/manifest/sha256:2374307703312554852605270f7979f1057e4d6b98bcb9f5f7cf4cabf9ca8b4f and used it as as the base image. The result was that, the new image didn't have architecture and os set aswell.

@@ -98,6 +99,15 @@ func getBaseImage(bo *options.BuildOptions) build.GetBase {
if bo.InsecureRegistry {
nameOpts = append(nameOpts, name.Insecure)
}

// look for wasm/wasi platform
for _, p := range bo.Platforms {
Copy link
Member

Choose a reason for hiding this comment

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

Does this mean that if a user passes --platform=linux/amd64,wasm/wasi, that they'll only get the wasi image?

Copy link
Author

Choose a reason for hiding this comment

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

Ah good argument, haven't thought about providing multiple architectures with wasi. I'll figure out, if there's a good way when using wasi in multiple platforms.

Copy link
Member

Choose a reason for hiding this comment

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

I've filed a request for clarification here: solo-io/wasm#291

@imjasonh
Copy link
Member

cc @squillace 👀

Lukas and others added 5 commits June 30, 2022 16:09
@codecov-commenter
Copy link

Codecov Report

Merging #738 (3f9801f) into main (691da5a) will decrease coverage by 0.45%.
The diff coverage is 61.78%.

@@            Coverage Diff             @@
##             main     #738      +/-   ##
==========================================
- Coverage   51.52%   51.07%   -0.46%     
==========================================
  Files          44       45       +1     
  Lines        3276     3350      +74     
==========================================
+ Hits         1688     1711      +23     
- Misses       1377     1417      +40     
- Partials      211      222      +11     
Impacted Files Coverage Δ
pkg/commands/config.go 56.09% <33.33%> (-1.80%) ⬇️
pkg/build/gobuild.go 57.85% <50.94%> (-3.60%) ⬇️
pkg/build/platform/platform.go 91.11% <91.11%> (ø)
pkg/commands/build.go 56.25% <0.00%> (-5.05%) ⬇️
pkg/commands/options/validate.go 0.00% <0.00%> (ø)
pkg/commands/options/build.go 69.56% <0.00%> (+0.69%) ⬆️

Continue to review full report at Codecov.

Legend - Click here to learn more
Δ = absolute <relative> (impact), ø = not affected, ? = missing data
Powered by Codecov. Last update 691da5a...3f9801f. Read the comment docs.

@hown3d
Copy link
Author

hown3d commented Jul 6, 2022

I tried to declutter the build package a bit to provide a more readable structure.
The current build package is huge and it's hard to understand what build (building binary), Build (top level build), BuildAll (image building, this is extremely confusing when build func builds the binary) and BuildOne do.

Thats why I moved everything regarding platform matching inside a platform package, config structs into a config package and binary building into a binary package.

@imjasonh
Copy link
Member

imjasonh commented Jul 6, 2022

I tried to declutter the build package a bit to provide a more readable structure. The current build package is huge and it's hard to understand what build (building binary), Build (top level build), BuildAll (image building, this is extremely confusing when build func builds the binary) and BuildOne do.

Thats why I moved everything regarding platform matching inside a platform package, config structs into a config package and binary building into a binary package.

This isn't a bad change, but it does make the PR quite a lot bigger and harder to follow. It also makes previously unexported methods exported, and we should probably hide more things in internal so that we don't get external dependencies on them.

In other words, I agree restructuring pkg/build sounds like a worthwhile endeavor, but I think there's more to talk about there, and it distracts from the goal of adding wasi support. Can we do a separate restructuring PR, then use it to add wasi? Or would you prefer to add wasi first, leaving the structure as-is?

@hown3d
Copy link
Author

hown3d commented Jul 6, 2022

Yes, that's reasonable. I think I'll go for the restructuring first because that makes implementing wasi support a bit easier and cleaner.

@hown3d
Copy link
Author

hown3d commented Sep 3, 2022

I did manage to find some time to reiterate on this feature, and I created a new branch to start of fresh.
I'll open a second pull request with the new changes.

@hown3d hown3d closed this Sep 3, 2022
@hown3d hown3d mentioned this pull request Sep 3, 2022
@hown3d hown3d deleted the wasi branch September 9, 2022 14:04
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.

3 participants