-
Notifications
You must be signed in to change notification settings - Fork 404
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
Conversation
Signed-off-by: Höhl, Lukas <[email protected]>
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.
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
@@ -689,6 +705,8 @@ func (g *gobuild) configForImportPath(ip string) Config { | |||
return config | |||
} | |||
|
|||
const wasmLayerAnnotationKey = "module.wasm.image/variant" |
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.
Is this annotation documented anywhere? What expects to read it?
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.
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 |
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.
Can you link to where this expectation is documented? I'd also just love to learn more about runtimes that run these things.
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.
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.
@@ -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" { |
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.
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"
}
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.
Yes, this is a good idea. The constant comparison with platform string was kinda hacky anyway.
pkg/build/gobuild.go
Outdated
// 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) |
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.
Why's this necessary?
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.
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
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.
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... 🤔
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.
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.
pkg/commands/config.go
Outdated
@@ -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 { |
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.
Does this mean that if a user passes --platform=linux/amd64,wasm/wasi
, that they'll only get the wasi image?
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.
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.
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.
I've filed a request for clarification here: solo-io/wasm#291
cc @squillace 👀 |
Co-authored-by: Jason Hall <[email protected]>
Co-authored-by: Jason Hall <[email protected]>
Co-authored-by: Jason Hall <[email protected]>
Signed-off-by: Höhl, Lukas <[email protected]>
Signed-off-by: Höhl, Lukas <[email protected]>
Codecov Report
@@ 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
Continue to review full report at Codecov.
|
Signed-off-by: Höhl, Lukas <[email protected]>
I tried to declutter the build package a bit to provide a more readable structure. 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. |
Signed-off-by: Höhl, Lukas <[email protected]>
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 In other words, I agree restructuring |
Yes, that's reasonable. I think I'll go for the restructuring first because that makes implementing wasi support a bit easier and cleaner. |
I did manage to find some time to reiterate on this feature, and I created a new branch to start of fresh. |
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]