diff --git a/maven-helmchartgen-wasm/README.md b/maven-helmchartgen-wasm/README.md new file mode 100644 index 0000000..21c3c14 --- /dev/null +++ b/maven-helmchartgen-wasm/README.md @@ -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 +``` \ No newline at end of file diff --git a/maven-helmchartgen-wasm/helmchartgen.wasm b/maven-helmchartgen-wasm/helmchartgen.wasm new file mode 100755 index 0000000..ad4ce64 Binary files /dev/null and b/maven-helmchartgen-wasm/helmchartgen.wasm differ diff --git a/maven-helmchartgen-wasm/templates/helm-chart/{{ .ServiceName }}/Chart.yaml b/maven-helmchartgen-wasm/templates/helm-chart/{{ .ServiceName }}/Chart.yaml new file mode 100644 index 0000000..445ec7e --- /dev/null +++ b/maven-helmchartgen-wasm/templates/helm-chart/{{ .ServiceName }}/Chart.yaml @@ -0,0 +1,6 @@ +apiVersion: v2 +description: A Helm Chart generated by Move2Kube for <~ .ServiceName ~> +keywords: + - <~ .ServiceName ~> +name: <~ .ServiceName ~> +version: 0.1.0 diff --git a/maven-helmchartgen-wasm/templates/helm-chart/{{ .ServiceName }}/templates/{{ .ServiceName }}-deployment.yaml b/maven-helmchartgen-wasm/templates/helm-chart/{{ .ServiceName }}/templates/{{ .ServiceName }}-deployment.yaml new file mode 100644 index 0000000..0cc7e94 --- /dev/null +++ b/maven-helmchartgen-wasm/templates/helm-chart/{{ .ServiceName }}/templates/{{ .ServiceName }}-deployment.yaml @@ -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: {} + +... diff --git a/maven-helmchartgen-wasm/templates/helm-chart/{{ .ServiceName }}/templates/{{ .ServiceName }}-ingress.yaml b/maven-helmchartgen-wasm/templates/helm-chart/{{ .ServiceName }}/templates/{{ .ServiceName }}-ingress.yaml new file mode 100644 index 0000000..158fc50 --- /dev/null +++ b/maven-helmchartgen-wasm/templates/helm-chart/{{ .ServiceName }}/templates/{{ .ServiceName }}-ingress.yaml @@ -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: {} + +... diff --git a/maven-helmchartgen-wasm/templates/helm-chart/{{ .ServiceName }}/templates/{{ .ServiceName }}-service.yaml b/maven-helmchartgen-wasm/templates/helm-chart/{{ .ServiceName }}/templates/{{ .ServiceName }}-service.yaml new file mode 100644 index 0000000..899fb5b --- /dev/null +++ b/maven-helmchartgen-wasm/templates/helm-chart/{{ .ServiceName }}/templates/{{ .ServiceName }}-service.yaml @@ -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: {} + +... diff --git a/maven-helmchartgen-wasm/templates/helm-chart/{{ .ServiceName }}/values.yaml b/maven-helmchartgen-wasm/templates/helm-chart/{{ .ServiceName }}/values.yaml new file mode 100644 index 0000000..64b4881 --- /dev/null +++ b/maven-helmchartgen-wasm/templates/helm-chart/{{ .ServiceName }}/values.yaml @@ -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 diff --git a/maven-helmchartgen-wasm/transformer.go b/maven-helmchartgen-wasm/transformer.go new file mode 100644 index 0000000..97caa89 --- /dev/null +++ b/maven-helmchartgen-wasm/transformer.go @@ -0,0 +1,165 @@ +package main + +import ( + "encoding/json" + "fmt" + "os" + "path/filepath" + "regexp" + "strings" + "unsafe" +) + +var artifactRegex = regexp.MustCompile(`(\w+)`) + +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() {} diff --git a/maven-helmchartgen-wasm/transformer.yaml b/maven-helmchartgen-wasm/transformer.yaml new file mode 100644 index 0000000..4ab84d1 --- /dev/null +++ b/maven-helmchartgen-wasm/transformer.yaml @@ -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