github.com/filecoin-project/bacalhau@v0.3.23-0.20230228154132-45c989550ace/pkg/executor/wasm/loader.go (about) 1 package wasm 2 3 import ( 4 "context" 5 "fmt" 6 "os" 7 "path/filepath" 8 9 "github.com/filecoin-project/bacalhau/pkg/model" 10 "github.com/filecoin-project/bacalhau/pkg/storage" 11 "github.com/rs/zerolog/log" 12 "github.com/tetratelabs/wazero" 13 "golang.org/x/exp/maps" 14 ) 15 16 func LoadModule(ctx context.Context, runtime wazero.Runtime, path string) (wazero.CompiledModule, error) { 17 bytes, err := os.ReadFile(path) 18 if err != nil { 19 return nil, err 20 } 21 22 module, err := runtime.CompileModule(ctx, bytes) 23 if err != nil { 24 return nil, err 25 } 26 27 return module, nil 28 } 29 30 func LoadRemoteModule( 31 ctx context.Context, 32 runtime wazero.Runtime, 33 provider storage.StorageProvider, 34 spec model.StorageSpec, 35 ) (wazero.CompiledModule, error) { 36 volumes, err := storage.ParallelPrepareStorage(ctx, provider, []model.StorageSpec{spec}) 37 if err != nil { 38 return nil, err 39 } 40 volume := maps.Values(volumes)[0] 41 42 programPath := volume.Source 43 info, err := os.Stat(programPath) 44 if err != nil { 45 return nil, err 46 } 47 48 // We expect the input to be a single WASM file. It is common however for 49 // IPFS implementations to wrap files into a directory. So we make a special 50 // case here – if the input is a single file in a directory, we will assume 51 // this is the program file and load it. 52 if info.IsDir() { 53 files, err := os.ReadDir(programPath) 54 if err != nil { 55 return nil, err 56 } 57 58 if len(files) != 1 { 59 return nil, fmt.Errorf("should be %d file in %s but there are %d", 1, programPath, len(files)) 60 } 61 programPath = filepath.Join(programPath, files[0].Name()) 62 } 63 64 log.Ctx(ctx).Debug().Msgf("Loading WASM module from %q", programPath) 65 return LoadModule(ctx, runtime, programPath) 66 }