components-contrib/internal/wasm/wasm.go

78 lines
2.0 KiB
Go

package wasm
import (
"context"
"errors"
"fmt"
"net/url"
"os"
"path"
"strings"
"github.com/dapr/components-contrib/metadata"
)
type InitMetadata struct {
// URL is how to load a `%.wasm` file that implements a command, usually
// compiled to target WASI.
//
// If no scheme is present, this defaults to oci://, referencing an OCI
// image. The wasm is identified be ENTRYPOINT and any other files in the
// corresponding layers will be mounted read-only as the root file system.
//
// Other valid schemes are file:// for a local file or http[s]:// for one
// retrieved via HTTP. In these cases, no filesystem will be mounted.
URL string `mapstructure:"url"`
// Guest is WebAssembly binary implementing the guest, loaded from URL.
Guest []byte `mapstructure:"-"`
// GuestName is module name of the guest, loaded from URL.
GuestName string `mapstructure:"-"`
}
// GetInitMetadata returns InitMetadata from the input metadata.
func GetInitMetadata(ctx context.Context, md metadata.Base) (*InitMetadata, error) {
// Note: the ctx will be used for other schemes such as HTTP and OCI.
var m InitMetadata
// Decode the metadata
err := metadata.DecodeMetadata(md.Properties, &m)
if err != nil {
return nil, err
}
if m.URL == "" {
return nil, errors.New("missing url")
}
firstColon := strings.IndexByte(m.URL, ':')
if firstColon == -1 {
return nil, fmt.Errorf("invalid URL: %s", m.URL)
}
scheme := m.URL[:firstColon]
switch m.URL[:firstColon] {
case "oci":
return nil, fmt.Errorf("TODO %s", scheme)
case "http", "https":
_, err = url.Parse(m.URL)
if err != nil {
return nil, err
}
return nil, fmt.Errorf("TODO %s", scheme)
case "file":
guestPath := m.URL[7:]
m.Guest, err = os.ReadFile(guestPath)
if err != nil {
return nil, err
}
// Use the name of the wasm binary as the module name.
m.GuestName, _ = strings.CutSuffix(path.Base(guestPath), ".wasm")
default:
return nil, fmt.Errorf("unsupported URL scheme: %s", scheme)
}
return &m, nil
}