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: add wasm transformer example #54

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 7 additions & 0 deletions maven-helmchartgen-wasm/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
# How to build this WASM Transformer

1. Ensure you have the [TinyGo](https://tinygo.org/) compiler installed. Move2Kube WASM modules currently do not support WASI modules built by the Go compiler.
2. Run the following command:
```
$ tinygo build -o helmchartgen.wasm -target=wasi transformer.go
```
Binary file added maven-helmchartgen-wasm/helmchartgen.wasm
Binary file not shown.
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
apiVersion: v2
description: A Helm Chart generated by Move2Kube for <~ .ServiceName ~>
keywords:
- <~ .ServiceName ~>
name: <~ .ServiceName ~>
version: 0.1.0
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@

---
apiVersion: apps/v1
kind: Deployment
metadata:
annotations:
move2kube.konveyor.io/service.expose: "true"
creationTimestamp: null
labels:
move2kube.konveyor.io/service: <~ .ServiceName ~>
name: <~ .ServiceName ~>
spec:
progressDeadlineSeconds: 600
replicas: 2
revisionHistoryLimit: 10
selector:
matchLabels:
move2kube.konveyor.io/service: <~ .ServiceName ~>
strategy:
rollingUpdate:
maxSurge: 25%
maxUnavailable: 25%
type: RollingUpdate
template:
metadata:
annotations:
move2kube.konveyor.io/service.expose: "true"
creationTimestamp: null
labels:
move2kube.konveyor.io/service: <~ .ServiceName ~>
name: <~ .ServiceName ~>
spec:
containers:
- image: {{ .Values.registryurl }}/{{ .Values.registrynamespace }}/<~ .ServiceName ~>:latest
imagePullPolicy: Always
name: <~ .ServiceName ~>
ports:
- containerPort: 8080
protocol: TCP
resources: {}
terminationMessagePath: /dev/termination-log
terminationMessagePolicy: File
dnsPolicy: ClusterFirst
restartPolicy: Always
schedulerName: default-scheduler
securityContext: {}
terminationGracePeriodSeconds: 30
status: {}

...
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@

---
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
creationTimestamp: null
labels:
move2kube.konveyor.io/service: <~ .ServiceName ~>
name: <~ .ServiceName ~>
spec:
rules:
- host: '{{ .Values.ingresshostdomain }}'
http:
paths:
- backend:
service:
name: <~ .ServiceName ~>
port:
name: port-8080
path: /gateway
pathType: Prefix
status:
loadBalancer: {}

...
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@

---
apiVersion: v1
kind: Service
metadata:
annotations:
move2kube.konveyor.io/service.expose: "true"
creationTimestamp: null
labels:
move2kube.konveyor.io/service: <~ .ServiceName ~>
name: <~ .ServiceName ~>
spec:
ports:
- name: port-8080
port: 8080
protocol: TCP
targetPort: 8080
selector:
move2kube.konveyor.io/service: <~ .ServiceName ~>
sessionAffinity: None
type: ClusterIP
status:
loadBalancer: {}

...
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
ingresshostdomain: put.the.hostdomain.of.ingress.here
registryurl: put.the.image.registry.url.here
registrynamespace: put.the.registry.namespace.here
imagetag: put.the.image.tag.here
165 changes: 165 additions & 0 deletions maven-helmchartgen-wasm/transformer.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,165 @@
package main

import (
"encoding/json"
"fmt"
"os"
"path/filepath"
"regexp"
"strings"
"unsafe"
)

var artifactRegex = regexp.MustCompile(`<artifactId>(\w+)</artifactId>`)

const PomFile = "pom.xml"

var input []byte = make([]byte, 2048)

// Reads a null-terminated string (ala C strings) from the provided pointer
func readPtr(dataPointer *int32) string {
nth := 0
var dataStr strings.Builder
pointer := uintptr(unsafe.Pointer(dataPointer))
for {
s := *(*int32)(unsafe.Pointer(pointer + uintptr(nth)))
if byte(s) == 0 {
break
}

dataStr.WriteByte(byte(s))
nth++
}

return dataStr.String()
}

//export directoryDetect
func directoryDetect(dataPointer *int32) *int32 {
dir := readPtr(dataPointer)
dataFilePath := filepath.Join(dir, PomFile)

transform_return_data := make(map[string]interface{})
if _, err := os.Stat(dataFilePath); err == nil {
serviceName := getServiceName(dataFilePath)
transform_return_data = map[string]interface{}{
serviceName: []map[string]interface{}{
{
"paths": map[string]interface{}{
"ServiceDirectories": []string{dir},
"ServiceRootDirectory": []string{dir},
"pomFiles": []string{dataFilePath},
},
},
},
}
transform_return_data_byt, err := json.Marshal(transform_return_data)
if err != nil {
fmt.Println(err)
os.Exit(1)
}
r := make([]int32, 2)
r[0] = int32(uintptr(unsafe.Pointer(&(transform_return_data_byt[0]))))
r[1] = int32(len(transform_return_data_byt))

return &r[0]
} else {
fmt.Printf("wasm stat failed: %v\n", err)
}

transform_return_data = nil
transform_return_data_byt, err := json.Marshal(transform_return_data)
if err != nil {
fmt.Println(err)
os.Exit(1)
}
r := make([]int32, 2)
r[0] = int32(uintptr(unsafe.Pointer(&(transform_return_data_byt[0]))))
r[1] = int32(len(transform_return_data_byt))

return &r[0]
}

//export transform
func transform(dataPointer *int32) *int32 {
rawData := readPtr(dataPointer)

var data map[string]interface{}
err := json.Unmarshal([]byte(rawData), &data)
if err != nil {
panic(err)
}
newArtifacts := data["newArtifacts"].([]interface{})

pathMappings := []map[string]interface{}{}
artifacts := []map[string]interface{}{}
pathTemplate := "{{ SourceRel .ServiceFsPath }}"
for _, v := range newArtifacts {
v := v.(map[string]interface{})
serviceName := v["configs"].(map[string]interface{})["Service"].(map[string]interface{})["ServiceName"].(string)
paths := v["paths"].(map[string]interface{})
dirs := paths["ServiceDirectories"].([]interface{})
dir := dirs[0].(string)

// Create a path template for the service
pathTemplateName := strings.ReplaceAll(serviceName, "-", "") + "path"
tplPathData := map[string]interface{}{
"ServiceFsPath": dir,
"PathTemplateName": pathTemplateName,
}
pathMappings = append(pathMappings, map[string]interface{}{
"type": "PathTemplate",
"sourcePath": pathTemplate,
"templateConfig": tplPathData,
})
// Since the helm chart uses the same templating character {{ }} as Golang templates,
// we use `SpecialTemplate` type here where the templating character is <~ ~>.
// The `Template` type can be used for all normal cases
pathMappings = append(pathMappings, map[string]interface{}{
"type": "SpecialTemplate",
"destinationPath": "{{ ." + pathTemplateName + " }}",
"templateConfig": map[string]interface{}{
"ServiceFsPath": dir,
"ServiceName": serviceName,
},
})
pathMappings = append(pathMappings, map[string]interface{}{
"type": "Source",
"sourcePath": "{{ ." + pathTemplateName + " }}",
"destinationPath": "{{ ." + pathTemplateName + " }}",
})
}
transform_return_data := map[string]interface{}{
"pathMappings": pathMappings,
"artifacts": artifacts,
}
transform_return_data_byt, err := json.Marshal(transform_return_data)
if err != nil {
fmt.Println(err)
os.Exit(1)
}
r := make([]int32, 2)
r[0] = int32(uintptr(unsafe.Pointer(&(transform_return_data_byt[0]))))
r[1] = int32(len(transform_return_data_byt))

return &r[0]
}

// getServiceName extracts service name from pom file
func getServiceName(filePath string) string {
data, err := os.ReadFile(filePath)
if err != nil {
fmt.Println("Error reading file:", err)
return ""
}
lines := strings.Split(string(data), "\n")
for _, line := range lines {
m := artifactRegex.FindStringSubmatch(line)
if len(m) != 0 {
return m[1]
}
}
return ""
}

func main() {}
18 changes: 18 additions & 0 deletions maven-helmchartgen-wasm/transformer.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
apiVersion: move2kube.konveyor.io/v1alpha1
kind: Transformer
metadata:
name: HelmChartGenerator
labels:
move2kube.konveyor.io/built-in: false
spec:
class: WASM
directoryDetect:
levels: -1
consumes:
Service:
merge: false
override:
matchLabels:
move2kube.konveyor.io/built-in: "true"
config:
wasm_module: helmchartgen.wasm
Loading