helm packaging, add chart_builder 30/11130/1
authorhoejoo.lee <hoejoo.lee@samsung.com>
Thu, 18 May 2023 10:57:29 +0000 (06:57 -0400)
committerhoejoo.lee <hoejoo.lee@samsung.com>
Thu, 18 May 2023 10:57:29 +0000 (06:57 -0400)
Change-Id: Ib1f4486b82b57b24bf8d2aef0e878f1ae79a7b89
Signed-off-by: hoejoo.lee <hoejoo.lee@samsung.com>
.gitignore [changed mode: 0644->0755]
config/kserve-adapter.yaml [new file with mode: 0755]
main.go
pkg/helm/chart_builder.go
pkg/helm/chart_builder_test.go
pkg/helm/data/resources/std/Chart.yaml
pkg/helm/data/sample_config.json
pkg/util/util.go [new file with mode: 0755]

old mode 100644 (file)
new mode 100755 (executable)
index 9c14461..a2d43a4
@@ -1,3 +1,6 @@
 # documentation
 .tox
 docs/_build/
+pkg/helm/data/sample-xapp-2.2.0/
+*.tgz
+mock*.go
diff --git a/config/kserve-adapter.yaml b/config/kserve-adapter.yaml
new file mode 100755 (executable)
index 0000000..d5459ec
--- /dev/null
@@ -0,0 +1,17 @@
+################################################################################
+#   Copyright (c) 2023 Samsung Electronics Co., Ltd. All Rights Reserved.      #
+#                                                                              #
+#   Licensed under the Apache License, Version 2.0 (the "License");            #
+#   you may not use this file except in compliance with the License.           #
+#   You may obtain a copy of the License at                                    #
+#                                                                              #
+#       http://www.apache.org/licenses/LICENSE-2.0                             #
+#                                                                              #
+#   Unless required by applicable law or agreed to in writing, software        #
+#   distributed under the License is distributed on an "AS IS" BASIS,          #
+#   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.   #
+#   See the License for the specific language governing permissions and        #
+#   limitations under the License.                                             #
+################################################################################
+"helm":
+  "retry": 1
diff --git a/main.go b/main.go
index 75c3378..689c324 100755 (executable)
--- a/main.go
+++ b/main.go
@@ -20,18 +20,27 @@ limitations under the License.
 package main
 
 import (
+       "flag"
        "os"
 
+       "github.com/spf13/viper"
        "gerrit.o-ran-sc.org/r/aiml-fw/aihp/ips/kserve-adapter/pkg/api"
        "gerrit.o-ran-sc.org/r/aiml-fw/aihp/ips/kserve-adapter/pkg/commons/logger"
 )
 
+const KSERVE_ADAPTER_CONFIG_FILE = "./config/kserve-adapter.yaml"
+
 var (
        apiServerPort string
 )
 
 func init() {
        apiServerPort = os.Getenv("API_SERVER_PORT")
+
+       var fileName *string
+       fileName = flag.String("f", KSERVE_ADAPTER_CONFIG_FILE, "Specify the configuration file.")
+       flag.Parse()
+       viper.SetConfigFile(*fileName)
 }
 
 func main() {
index 3318eb0..21484e7 100755 (executable)
@@ -29,6 +29,8 @@ import (
 
        "github.com/xeipuuv/gojsonschema"
        "gerrit.o-ran-sc.org/r/aiml-fw/aihp/ips/kserve-adapter/pkg/commons/logger"
+       "github.sec.samsung.net/RANIS/aiml-fw-aihp-ips-kserve-adapter/pkg/util"
+       "gopkg.in/yaml.v1"
 )
 
 const (
@@ -83,10 +85,17 @@ func NewChartBuilder(configFile string, schemaFile string) *ChartBuilder {
        _, err = os.Stat(chartBuilder.chartWorkspacePath)
        if err != nil {
                if !os.IsNotExist(err) {
-                       os.RemoveAll(chartBuilder.chartWorkspacePath)
+                       logger.Logging(logger.ERROR, err.Error())
+                       return nil
                }
        }
 
+       err = os.RemoveAll(chartBuilder.chartWorkspacePath)
+       if err != nil {
+               logger.Logging(logger.ERROR, err.Error())
+               return nil
+       }
+
        err = os.Mkdir(chartBuilder.chartWorkspacePath, os.FileMode(0744))
        if err != nil {
                logger.Logging(logger.ERROR, err.Error())
@@ -196,7 +205,29 @@ func (c *ChartBuilder) copyDirectory(src string, dest string) (err error) {
 }
 
 func (c *ChartBuilder) PackageChart() (err error) {
-       return errors.New("not yet implemented")
+       err = c.appendConfigToValuesYaml()
+       if err != nil {
+               return
+       }
+
+       err = c.changeChartNameVersion()
+       if err != nil {
+               return
+       }
+
+       err = c.helmLint()
+       if err != nil {
+               return
+       }
+
+       output, err := util.HelmExec(fmt.Sprintf("package %s/%s -d %s", c.chartWorkspacePath, c.chartName, c.chartWorkspacePath))
+       if err != nil {
+               logger.Logging(logger.ERROR, "%s-%s helm lint failed (Caused by : %s)", c.chartName, c.chartVersion, err.Error())
+               return
+       }
+       logger.Logging(logger.INFO, "result of helm lint : %s", string(output))
+
+       return
 }
 
 func (c *ChartBuilder) parseConfigFile(configFile string) (config Config, err error) {
@@ -235,15 +266,65 @@ func (c *ChartBuilder) parseSchemaFile(schemaFile string) (schema Schema, err er
 }
 
 func (c *ChartBuilder) helmLint() (err error) {
-       return errors.New("not yet implemented")
+
+       output, err := util.HelmExec(fmt.Sprintf("lint %s/%s", c.chartWorkspacePath, c.chartName))
+
+       if err != nil {
+               logger.Logging(logger.ERROR, err.Error())
+               logger.Logging(logger.ERROR, fmt.Sprintf("%s-%s helm lint failed (Caused by : %s)", c.chartName, c.chartVersion, err))
+       }
+       logger.Logging(logger.INFO, fmt.Sprintf("result of helm lint : %s", string(output)))
+       return
 }
 
 func (c *ChartBuilder) appendConfigToValuesYaml() (err error) {
-       return errors.New("not yet implemented")
+       valueYamlPath := os.Getenv(ENV_CHART_WORKSPACE_PATH) + "/" + c.chartName + "-" + c.chartVersion + "/" + c.chartName + "/" + VALUES_YAML
+       yamlFile, err := ioutil.ReadFile(valueYamlPath)
+       if err != nil {
+               return
+       }
+
+       data := make(map[interface{}]interface{})
+       err = yaml.Unmarshal(yamlFile, &data)
+       if err != nil {
+               return
+       }
+
+       data["engine"] = c.config.InferenceService.Engine
+       data["storageUri"] = c.config.InferenceService.StorageURI
+
+       //data["resources"] = c.config.
+       data["max_replicas"] = c.config.InferenceService.MaxReplicas
+       data["min_replicas"] = c.config.InferenceService.MinReplicas
+       data["name"] = c.config.XappName
+       data["fullname"] = c.config.XappName
+       data["ric_serviceaccount_name"] = c.config.SaName
+
+       ret, err := yaml.Marshal(&data)
+       if err != nil {
+               return
+       }
+
+       err = ioutil.WriteFile(valueYamlPath, ret, os.FileMode(0644))
+       if err != nil {
+               return
+       }
+       return
 }
 
 func (c *ChartBuilder) changeChartNameVersion() (err error) {
-       return errors.New("not yet implemented")
+       chartYamlPath := os.Getenv(ENV_CHART_WORKSPACE_PATH) + "/" + c.chartName + "/" + CHART_YAML
+       yamlFile, err := ioutil.ReadFile(chartYamlPath)
+
+       data := make(map[interface{}]interface{})
+       err = yaml.Unmarshal(yamlFile, &data)
+       if err != nil {
+               return
+       }
+
+       data["version"] = c.chartVersion
+       data["name"] = c.chartName
+       return
 }
 
 func (c *ChartBuilder) ValidateChartMaterials() (err error) {
index 8f47ecd..eabe211 100755 (executable)
 package helm
 
 import (
+       "flag"
        "io/ioutil"
        "os"
        "testing"
 
+       "github.com/spf13/viper"
        "github.com/stretchr/testify/assert"
 )
 
@@ -43,13 +45,17 @@ func TestParseSchemaFile(t *testing.T) {
 }
 
 func TestHelmLint(t *testing.T) {
+       os.Setenv("CHART_WORKSPACE_PATH", "./data")
        chartBuilder := NewChartBuilder("data/sample_config.json", "data/sample_schema.json")
-       err := chartBuilder.helmLint()
+       err := chartBuilder.appendConfigToValuesYaml()
+       assert.Nil(t, err)
 
+       err = chartBuilder.helmLint()
        assert.Nil(t, err)
 }
 
 func TestAppendConfigToValuesYaml(t *testing.T) {
+       os.Setenv("CHART_WORKSPACE_PATH", "./data")
        chartBuilder := NewChartBuilder("data/sample_config.json", "data/sample_schema.json")
 
        err := chartBuilder.appendConfigToValuesYaml()
@@ -58,6 +64,7 @@ func TestAppendConfigToValuesYaml(t *testing.T) {
 }
 
 func TestChangeChartNameVersion(t *testing.T) {
+       os.Setenv("CHART_WORKSPACE_PATH", "./data")
        chartBuilder := NewChartBuilder("data/sample_config.json", "data/sample_schema.json")
        err := chartBuilder.changeChartNameVersion()
 
@@ -65,10 +72,21 @@ func TestChangeChartNameVersion(t *testing.T) {
 }
 
 func TestPackageChart(t *testing.T) {
+
+       var fileName *string
+       fileName = flag.String("f", "../../config/kserve-adapter.yaml", "Specify the configuration file.")
+       flag.Parse()
+
+       viper.SetConfigFile(*fileName)
+
+       os.Setenv("CHART_WORKSPACE_PATH", "./data")
        chartBuilder := NewChartBuilder("data/sample_config.json", "data/sample_schema.json")
        err := chartBuilder.PackageChart()
 
        assert.Nil(t, err)
+       assert.FileExists(t, "./data/sample-xapp-2.2.0/inference-service-1.0.0.tgz")
+
+       defer os.RemoveAll("./data/sample-xapp-2.2.0/inference-service-1.0.0.tgz")
 }
 
 func TestCopyFile(t *testing.T) {
@@ -111,3 +129,12 @@ func TestCopyDirectory(t *testing.T) {
                }
        }
 }
+
+func TestValidateChartMaterials(t *testing.T) {
+       os.Setenv("CHART_WORKSPACE_PATH", ".")
+       chartBuilder := NewChartBuilder("data/sample_config.json", "data/sample_schema.json")
+       err := chartBuilder.ValidateChartMaterials()
+       defer os.RemoveAll(os.Getenv("CHART_WORKSPACE_PATH") + "/" + chartBuilder.chartName + "-" + chartBuilder.chartVersion)
+
+       assert.Nil(t, err)
+}
index edd6bd7..333e39e 100755 (executable)
@@ -1,21 +1,20 @@
-# ==================================================================================
-#
-#       Copyright (c) 2023 Samsung Electronics Co., Ltd. All Rights Reserved.
-#
-#   Licensed under the Apache License, Version 2.0 (the "License");
-#   you may not use this file except in compliance with the License.
-#   You may obtain a copy of the License at
-#
-#          http://www.apache.org/licenses/LICENSE-2.0
-#
-#   Unless required by applicable law or agreed to in writing, software
-#   distributed under the License is distributed on an "AS IS" BASIS,
-#   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-#   See the License for the specific language governing permissions and
-#   limitations under the License.
-#
-# ==================================================================================
+/*
+==================================================================================
+  Copyright (c) 2023 Samsung Electronics Co., Ltd. All Rights Reserved.
 
+  Licensed under the Apache License, Version 2.0 (the "License");
+  you may not use this file except in compliance with the License.
+  You may obtain a copy of the License at
+
+         http://www.apache.org/licenses/LICENSE-2.0
+
+  Unless required by applicable law or agreed to in writing, software
+  distributed under the License is distributed on an "AS IS" BASIS,
+  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  See the License for the specific language governing permissions and
+  limitations under the License.
+==================================================================================
+*/
 apiVersion: v1
 appVersion: "1.0"
 description: Standard Inference Service Helm Chart
index b665a13..00c8579 100755 (executable)
@@ -1,5 +1,5 @@
 {
-    "xapp_name": "sample_xapp",
+    "xapp_name": "sample-xapp",
     "xapp_type": "inferenceservice",
     "version": "2.2.0",
     "sa_name": "default",
diff --git a/pkg/util/util.go b/pkg/util/util.go
new file mode 100755 (executable)
index 0000000..3269357
--- /dev/null
@@ -0,0 +1,60 @@
+/*
+==================================================================================
+  Copyright (c) 2023 Samsung Electronics Co., Ltd. All Rights Reserved.
+
+  Licensed under the Apache License, Version 2.0 (the "License");
+  you may not use this file except in compliance with the License.
+  You may obtain a copy of the License at
+
+         http://www.apache.org/licenses/LICENSE-2.0
+
+  Unless required by applicable law or agreed to in writing, software
+  distributed under the License is distributed on an "AS IS" BASIS,
+  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  See the License for the specific language governing permissions and
+  limitations under the License.
+==================================================================================
+*/
+
+package util
+
+import (
+       "bytes"
+       "errors"
+       "fmt"
+       "os/exec"
+       "strings"
+       "time"
+
+       "github.sec.samsung.net/RANIS/aiml-fw-aihp-ips-kserve-adapter/pkg/commons/logger"
+)
+
+func Exec(args string) (out []byte, err error) {
+       cmd := exec.Command("/bin/sh", "-c", args)
+
+       var stdout bytes.Buffer
+       var stderr bytes.Buffer
+       cmd.Stdout = &stdout
+       cmd.Stderr = &stderr
+
+       logger.Logging(logger.INFO, fmt.Sprintf("Running command: %s", cmd.Args))
+       for i := 0; i < 3; i++ {
+               if err = cmd.Run(); err != nil {
+                       logger.Logging(logger.ERROR, fmt.Sprintf("Command failed : %v - %s, retrying", err.Error(), stderr.String()))
+                       time.Sleep(time.Duration(2) * time.Second)
+                       continue
+               }
+               break
+       }
+
+       if err == nil {
+               logger.Logging(logger.INFO, fmt.Sprintf("command success: %s", stdout.String()))
+               return stdout.Bytes(), nil
+       }
+
+       return stdout.Bytes(), errors.New(stderr.String())
+}
+
+var HelmExec = func(args string) (out []byte, err error) {
+       return Exec(strings.Join([]string{"helm", args}, " "))
+}