-
Notifications
You must be signed in to change notification settings - Fork 11
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat: add custom wasm transformer samples (#56)
* feat: add custom wasm transformer samples chore: add a .gitignore Signed-off-by: Harikrishnan Balagopal <[email protected]> * fixup! feat: add custom wasm transformer samples Signed-off-by: Harikrishnan Balagopal <[email protected]> * chore: better package name Signed-off-by: Harikrishnan Balagopal <[email protected]> * chore: remove some comments Signed-off-by: Harikrishnan Balagopal <[email protected]> * fixup! chore: remove some comments Signed-off-by: Harikrishnan Balagopal <[email protected]> * chore: better parameter names Signed-off-by: Harikrishnan Balagopal <[email protected]> --------- Signed-off-by: Harikrishnan Balagopal <[email protected]>
- Loading branch information
1 parent
501f3c9
commit a91025e
Showing
25 changed files
with
660,559 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
.DS_Store |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,8 @@ | ||
# Custom WASM Transformers | ||
|
||
These samples show how custom WASM/WASI modules can be run as custom transformers in Move2Kube. The samples are designed for the browser version of Move2Kube. The transformers have been built and zipped for convenience. | ||
|
||
You can try these samples out at https://move2kube.konveyor.io/experimental | ||
|
||
- The `language-platforms.zip` sample has also been copied here for convenience. | ||
- The `wasm-java-helm-chart.zip` sample is a port of the Starlark transformer https://github.com/konveyor/move2kube-transformers/tree/main/add-custom-files-directories-in-custom-locations to Golang/WASM/WASI |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,4 @@ | ||
.PHONY: build | ||
build: | ||
cd wasm-gen-svc-acc/gen-svc-acc/ && make build && cd - && rm -f wasm-gen-svc-acc.zip && zip -r wasm-gen-svc-acc.zip wasm-gen-svc-acc | ||
cd wasm-java-helm-chart/add-custom-files-dirs/ && make build && cd - && rm -f wasm-java-helm-chart.zip && zip -r wasm-java-helm-chart.zip wasm-java-helm-chart |
Binary file not shown.
Binary file not shown.
4 changes: 4 additions & 0 deletions
4
custom-wasm-transformers/samples/wasm-gen-svc-acc/gen-svc-acc/Makefile
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,4 @@ | ||
.PHONY: build | ||
build: | ||
tinygo build -o maintiny.wasm -target=wasi main.go | ||
wasm2wat maintiny.wasm > maintiny.wat |
5 changes: 5 additions & 0 deletions
5
custom-wasm-transformers/samples/wasm-gen-svc-acc/gen-svc-acc/go.mod
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,5 @@ | ||
module mydomain.com/mypackage | ||
|
||
go 1.21.6 | ||
|
||
require gopkg.in/yaml.v3 v3.0.1 // indirect |
3 changes: 3 additions & 0 deletions
3
custom-wasm-transformers/samples/wasm-gen-svc-acc/gen-svc-acc/go.sum
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,3 @@ | ||
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= | ||
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= | ||
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= |
241 changes: 241 additions & 0 deletions
241
custom-wasm-transformers/samples/wasm-gen-svc-acc/gen-svc-acc/main.go
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,241 @@ | ||
package main | ||
|
||
import ( | ||
"encoding/json" | ||
"fmt" | ||
"os" | ||
"path/filepath" | ||
"strings" | ||
"unsafe" | ||
|
||
"gopkg.in/yaml.v3" | ||
) | ||
|
||
// PathMappingType refers to the Path Mapping type | ||
type PathMappingType string | ||
|
||
const ( | ||
// DefaultPathMappingType allows normal copy with overwrite | ||
DefaultPathMappingType PathMappingType = "Default" // Normal Copy with overwrite | ||
// TemplatePathMappingType allows copy of source to destination and applying of template | ||
TemplatePathMappingType PathMappingType = "Template" // Source path when relative, is relative to yaml file location | ||
// SourcePathMappingType allows for copying of source directory to another directory | ||
SourcePathMappingType PathMappingType = "Source" // Source path becomes relative to source directory | ||
// DeletePathMappingType allows for deleting of files or folder directory | ||
DeletePathMappingType PathMappingType = "Delete" // Delete path becomes relative to source directory | ||
// ModifiedSourcePathMappingType allows for copying of deltas wrt source | ||
ModifiedSourcePathMappingType PathMappingType = "SourceDiff" // Source path becomes relative to source directory | ||
// PathTemplatePathMappingType allows for path template registration | ||
PathTemplatePathMappingType PathMappingType = "PathTemplate" // Path Template type | ||
// SpecialTemplatePathMappingType allows copy of source to destination and applying of template with custom delimiter | ||
SpecialTemplatePathMappingType PathMappingType = "SpecialTemplate" // Source path when relative, is relative to yaml file location | ||
) | ||
|
||
// Artifact represents the artifact that can be passed between transformers | ||
type Artifact struct { | ||
Name string `yaml:"name,omitempty" json:"name,omitempty"` | ||
Type string `yaml:"type,omitempty" json:"type,omitempty"` | ||
// ProcessWith metav1.LabelSelector `yaml:"processWith,omitempty" json:"processWith,omitempty"` // Selector for choosing transformers that should process this artifact, empty is everything | ||
|
||
Paths map[string][]string `yaml:"paths,omitempty" json:"paths,omitempty" m2kpath:"normal"` | ||
Configs map[string]interface{} `yaml:"configs,omitempty" json:"configs,omitempty"` // Could be IR or template config or any custom configuration | ||
} | ||
|
||
// PathMapping is the mapping between source and intermediate files and output files | ||
type PathMapping struct { | ||
Type PathMappingType `yaml:"type,omitempty" json:"type,omitempty"` // Default - Normal copy | ||
SrcPath string `yaml:"sourcePath" json:"sourcePath" m2kpath:"normal"` | ||
DestPath string `yaml:"destinationPath" json:"destinationPath" m2kpath:"normal"` // Relative to output directory | ||
TemplateConfig interface{} `yaml:"templateConfig" json:"templateConfig"` | ||
} | ||
|
||
type TransformInput struct { | ||
NewArtifacts []Artifact `yaml:"newArtifacts,omitempty" json:"newArtifacts,omitempty"` | ||
AlreadySeenArtifacts []Artifact `yaml:"alreadySeenArtifacts,omitempty" json:"alreadySeenArtifacts,omitempty"` | ||
} | ||
|
||
type TransformOutput struct { | ||
NewPathMappings []PathMapping `yaml:"newPathMappings,omitempty" json:"newPathMappings,omitempty"` | ||
NewArtifacts []Artifact `yaml:"newArtifacts,omitempty" json:"newArtifacts,omitempty"` | ||
} | ||
|
||
// https://github.com/tinygo-org/tinygo/issues/411#issuecomment-503066868 | ||
var keyToAllocatedBytes = map[uint32][]byte{} | ||
var nextKey uint32 = 41 | ||
|
||
// https://github.com/ejcx/wazero/blob/40f59a877bcdb4949eba51f9e1dee3deaba1ff83/examples/allocation/tinygo/testdata/greet.go#L64C1-L68C2 | ||
// ptrToString returns a string from WebAssembly compatible numeric types | ||
// representing its pointer and length. | ||
func ptrToString(ptr uint32, size uint32) string { | ||
return unsafe.String((*byte)(unsafe.Pointer(uintptr(ptr))), size) | ||
} | ||
|
||
//go:export myAllocate | ||
func myAllocate(size uint32) *byte { | ||
nextKey += 1 | ||
newArr := make([]byte, size) | ||
keyToAllocatedBytes[nextKey] = newArr | ||
return &newArr[0] | ||
} | ||
|
||
func saveBytes(ptrBytes []byte) uint32 { | ||
nextKey += 1 | ||
keyToAllocatedBytes[nextKey] = ptrBytes | ||
ptr := &ptrBytes[0] | ||
return uint32(uintptr(unsafe.Pointer(ptr))) | ||
} | ||
|
||
func Transform( | ||
newArtifacts []Artifact, | ||
alreadySeenArtifacts []Artifact, | ||
) ([]PathMapping, []Artifact, error) { | ||
pathMappings := []PathMapping{} | ||
artifacts := []Artifact{} | ||
|
||
for _, newArtifact := range newArtifacts { | ||
if len(newArtifact.Paths) == 0 { | ||
fmt.Println("[DEBUG] newArtifact.Paths is nil/empty") | ||
continue | ||
} | ||
if len(newArtifact.Paths["KubernetesYamls"]) == 0 { | ||
fmt.Println("[DEBUG] newArtifact.Paths[KubernetesYamls] is nil/empty") | ||
continue | ||
} | ||
yamlsPath := newArtifact.Paths["KubernetesYamls"][0] | ||
fmt.Printf("[DEBUG] newArtifact yamlsPath: '%s'\n", yamlsPath) | ||
serviceName := newArtifact.Name | ||
artifacts = append(artifacts, newArtifact) | ||
|
||
yamlsBasePath := filepath.Base(yamlsPath) | ||
// Create a custom path template for the service, whose values gets filled and can be used in other pathmappings | ||
pathTemplateName := serviceName + yamlsBasePath | ||
pathTemplateName = strings.ReplaceAll(pathTemplateName, "-", "") | ||
tplPathData := map[string]string{"PathTemplateName": pathTemplateName} | ||
pathMappings = append(pathMappings, PathMapping{ | ||
Type: "PathTemplate", | ||
SrcPath: "{{ OutputRel \"" + yamlsPath + "\" }}", | ||
TemplateConfig: tplPathData, | ||
}) | ||
fileList, err := os.ReadDir(yamlsPath) | ||
if err != nil { | ||
return nil, nil, fmt.Errorf("failed to read the directory '%s' . Error: %w", yamlsPath, err) | ||
} | ||
fmt.Printf("[DEBUG] newArtifact fileList: '%d'\n", len(fileList)) | ||
for _, f := range fileList { | ||
filePath := filepath.Join(yamlsPath, f.Name()) | ||
fmt.Printf("[DEBUG] filePath: '%s'\n", filePath) | ||
inputBytes, err := os.ReadFile(filePath) | ||
if err != nil { | ||
fmt.Printf("[ERROR] read file filePath: '%s' . Error: %q\n", filePath, err) | ||
continue | ||
} | ||
// inputYaml := string(inputBytes) | ||
yamlData := map[string]interface{}{} | ||
if err := yaml.Unmarshal(inputBytes, &yamlData); err != nil { | ||
fmt.Printf("[ERROR] yaml unmarshal filePath: '%s' . Error: %q\n", filePath, err) | ||
continue | ||
} | ||
if yamlData["kind"] != "Deployment" { | ||
fmt.Println("kind does not exist/kind is not Deployment") | ||
continue | ||
} | ||
__svc_name, ok := yamlData["metadata"].(map[string]interface{}) | ||
if !ok { | ||
fmt.Println("metadata is missing") | ||
continue | ||
} | ||
svc_name, ok := __svc_name["name"].(string) | ||
if !ok { | ||
fmt.Println("name is missing") | ||
continue | ||
} | ||
fmt.Printf("[DEBUG] svc_name %s\n", svc_name) | ||
svcAccYamlData := map[string]interface{}{ | ||
"apiVersion": "v1", | ||
"kind": "ServiceAccount", | ||
"metadata": map[string]interface{}{ | ||
"name": svc_name + "-svc-account", | ||
}, | ||
} | ||
sBytes, err := yaml.Marshal(svcAccYamlData) | ||
if err != nil { | ||
fmt.Printf("[ERROR] yaml marshal error: %q\n", err) | ||
continue | ||
} | ||
svcAccFilePath := filepath.Join(yamlsPath, svc_name+"-svc-account.yaml") | ||
if err := os.WriteFile(svcAccFilePath, sBytes, 0644); err != nil { | ||
fmt.Printf("[ERROR] write file %s error: %q\n", svcAccFilePath, err) | ||
continue | ||
} | ||
pathMappings = append(pathMappings, | ||
PathMapping{ | ||
Type: "", | ||
SrcPath: yamlsPath, | ||
DestPath: "{{ ." + pathTemplateName + " }}", | ||
}, | ||
PathMapping{ | ||
Type: "Default", | ||
SrcPath: svcAccFilePath, | ||
DestPath: "{{ ." + pathTemplateName + " }}", | ||
}, | ||
) | ||
} | ||
} | ||
return pathMappings, artifacts, nil | ||
} | ||
|
||
//go:export RunDirectoryDetect | ||
func RunDirectoryDetect( | ||
inputJsonPtr uint32, | ||
inputJsonLen uint32, | ||
outputJsonPtrPtr uint32, | ||
outputJsonLenPtr uint32, | ||
) (successOrError int32) { | ||
fmt.Println("mycustomtransformer: RunDirectoryDetect start") | ||
defer fmt.Println("mycustomtransformer: RunDirectoryDetect end") | ||
return 0 | ||
} | ||
|
||
//go:export RunTransform | ||
func RunTransform( | ||
inputJsonPtr uint32, | ||
inputJsonLen uint32, | ||
outputJsonPtrPtr uint32, | ||
outputJsonLenPtr uint32, | ||
) (successOrError int32) { | ||
fmt.Println("mycustomtransformer: RunTransform start") | ||
defer fmt.Println("mycustomtransformer: RunTransform end") | ||
transformInputJson := ptrToString(inputJsonPtr, inputJsonLen) | ||
input := TransformInput{} | ||
if err := json.Unmarshal([]byte(transformInputJson), &input); err != nil { | ||
fmt.Println("mycustomtransformer: failed to unmarshal") | ||
return -1 | ||
} | ||
ps, as, err := Transform(input.NewArtifacts, input.AlreadySeenArtifacts) | ||
if err != nil { | ||
fmt.Printf("mycustomtransformer: failed to transform. Error: %q\n", err) | ||
return -1 | ||
} | ||
output := TransformOutput{ | ||
NewPathMappings: ps, | ||
NewArtifacts: as, | ||
} | ||
outputJson, err := json.Marshal(output) | ||
if err != nil { | ||
fmt.Println("mycustomtransformer: failed to marshal") | ||
return -1 | ||
} | ||
ptr := saveBytes(outputJson) | ||
ptrr := (*uint32)(unsafe.Pointer(uintptr(outputJsonPtrPtr))) | ||
*ptrr = ptr | ||
ptrl := (*uint32)(unsafe.Pointer(uintptr(outputJsonLenPtr))) | ||
*ptrl = uint32(len(outputJson)) | ||
return 0 | ||
} | ||
|
||
func main() { | ||
// wasmexport hasn't been implemented yet | ||
// https://github.com/golang/go/issues/42372a | ||
args := os.Args | ||
fmt.Printf("args: %+v\n", args) | ||
} |
Binary file added
BIN
+1.92 MB
custom-wasm-transformers/samples/wasm-gen-svc-acc/gen-svc-acc/maintiny.wasm
Binary file not shown.
Oops, something went wrong.