import (
"encoding/json"
"errors"
+ "fmt"
+ "io"
"io/ioutil"
"os"
+ "path/filepath"
"gerrit.o-ran-sc.org/r/aiml-fw/aihp/ips/kserve-adapter/pkg/commons/logger"
)
+const (
+ VALUES_YAML = "values.yaml"
+ CHART_YAML = "Chart.yaml"
+
+ SERVING_VERSION_ALPHA = "serving.kubeflow.org/v1alpha2"
+ SERVING_VERSION_BETA = "serving.kubeflow.org/v1beta1"
+ RESOURCE_ALPHA = "'resources/xapp-inf-alpha'"
+ RESOURCE_BETA = "'resources/xapp-inf-beta'"
+)
+
+type HelmChartBuilder interface {
+ PackageChart() (err error)
+}
+
type ChartBuilder struct {
+ config Config
+ schema Schema
+ chartWorkspacePath string
+ chartName string
+ chartVersion string
+}
+
+func NewChartBuilder(configFile string, schemaFile string) *ChartBuilder {
+ chartBuilder := &ChartBuilder{}
+ var err error
+
+ chartBuilder.config, err = chartBuilder.parseConfigFile(configFile)
+ if err != nil {
+ logger.Logging(logger.ERROR, err.Error())
+ return nil
+ }
+
+ if chartBuilder.config.XappName == "" || chartBuilder.config.Version == "" {
+ logger.Logging(logger.ERROR, fmt.Sprintf("some value is empty : xAppName = %s, Version = %s", chartBuilder.config.XappName, chartBuilder.config.Version))
+ return nil
+ }
+
+ chartBuilder.schema, err = chartBuilder.parseSchemaFile(schemaFile)
+ if err != nil {
+ logger.Logging(logger.ERROR, err.Error())
+ return nil
+ }
+
+ chartBuilder.chartName = chartBuilder.config.XappName
+ chartBuilder.chartVersion = chartBuilder.config.Version
+ chartBuilder.chartWorkspacePath = os.Getenv("CHART_WORKSPACE_PATH") + "/" + chartBuilder.chartName + "-" + chartBuilder.chartVersion
+
+ _, err = os.Stat(chartBuilder.chartWorkspacePath)
+ if err != nil {
+ if !os.IsNotExist(err) {
+ os.RemoveAll(chartBuilder.chartWorkspacePath)
+ os.Mkdir(chartBuilder.chartWorkspacePath, os.FileMode(644))
+ }
+ }
+
+ resourceVersionMap := map[string]string{
+ SERVING_VERSION_ALPHA: RESOURCE_ALPHA,
+ SERVING_VERSION_BETA: RESOURCE_BETA,
+ }
+
+ apiVersion := chartBuilder.config.InferenceService.ApiVersion
+ resource := resourceVersionMap[apiVersion]
+ err = chartBuilder.copyDirectory("data/"+resource, chartBuilder.chartWorkspacePath+"/"+chartBuilder.chartName)
+ if err != nil {
+ logger.Logging(logger.ERROR, err.Error())
+ return nil
+ }
+
+ return chartBuilder
+
}
-func NewChartBuilder() ChartBuilder {
- return ChartBuilder{}
+func (c *ChartBuilder) copyFile(src string, dest string) (err error) {
+ srcFile, err := os.Open(src)
+ if err != nil {
+ return
+ }
+ defer srcFile.Close()
+
+ destFile, err := os.Create(dest)
+ if err != nil {
+ return
+ }
+ defer func() {
+ if e := destFile.Close(); e != nil {
+ err = e
+ }
+ }()
+
+ _, err = io.Copy(destFile, srcFile)
+ if err != nil {
+ return
+ }
+ err = destFile.Sync()
+ if err != nil {
+ return
+ }
+ srcInfo, err := os.Stat(src)
+ if err != nil {
+ return
+ }
+
+ err = os.Chmod(dest, srcInfo.Mode())
+ if err != nil {
+ return
+ }
+ return
+}
+
+func (c *ChartBuilder) copyDirectory(src string, dest string) (err error) {
+ src = filepath.Clean(src)
+ dest = filepath.Clean(dest)
+
+ srcInfo, err := os.Stat(src)
+ if err != nil {
+ return
+ }
+ if !srcInfo.IsDir() {
+ return fmt.Errorf("src(%s) is not a directory", src)
+ }
+
+ _, err = os.Stat(dest)
+ if err != nil && !os.IsNotExist(err) {
+ return
+ }
+ if err == nil {
+ return fmt.Errorf("destination(%s) is already exists", dest)
+ }
+ err = os.MkdirAll(dest, srcInfo.Mode())
+ if err != nil {
+ return
+ }
+ entries, err := ioutil.ReadDir(src)
+ if err != nil {
+ return
+ }
+
+ for _, entry := range entries {
+ srcPath := filepath.Join(src, entry.Name())
+ destPath := filepath.Join(dest, entry.Name())
+
+ if entry.IsDir() {
+ err = c.copyDirectory(srcPath, destPath)
+ if err != nil {
+ return
+ }
+ } else {
+ if entry.Mode()&os.ModeSymlink != 0 {
+ continue
+ }
+ err = c.copyFile(srcPath, destPath)
+ if err != nil {
+ return
+ }
+ }
+ }
+ return
}
func (c *ChartBuilder) PackageChart() (err error) {
package helm
import (
+ "io/ioutil"
+ "os"
"testing"
"github.com/stretchr/testify/assert"
)
func TestParseConfigFile(t *testing.T) {
- chartBuilder := NewChartBuilder()
+ chartBuilder := NewChartBuilder("data/sample_config.json", "data/sample_schema.json")
config, err := chartBuilder.parseConfigFile("data/sample_config.json")
assert.Nil(t, err)
}
func TestParseSchemaFile(t *testing.T) {
- chartBuilder := NewChartBuilder()
+ chartBuilder := NewChartBuilder("data/sample_config.json", "data/sample_schema.json")
schema, err := chartBuilder.parseSchemaFile("data/sample_schema.json")
assert.Nil(t, err)
}
func TestHelmLint(t *testing.T) {
- chartBuilder := NewChartBuilder()
+ chartBuilder := NewChartBuilder("data/sample_config.json", "data/sample_schema.json")
err := chartBuilder.helmLint()
assert.Nil(t, err)
}
func TestAppendConfigToValuesYaml(t *testing.T) {
- chartBuilder := NewChartBuilder()
+ chartBuilder := NewChartBuilder("data/sample_config.json", "data/sample_schema.json")
+
err := chartBuilder.appendConfigToValuesYaml()
assert.Nil(t, err)
}
func TestChangeChartNameVersion(t *testing.T) {
- chartBuilder := NewChartBuilder()
+ chartBuilder := NewChartBuilder("data/sample_config.json", "data/sample_schema.json")
err := chartBuilder.changeChartNameVersion()
assert.Nil(t, err)
}
func TestPackageChart(t *testing.T) {
- chartBuilder := NewChartBuilder()
+ chartBuilder := NewChartBuilder("data/sample_config.json", "data/sample_schema.json")
err := chartBuilder.PackageChart()
assert.Nil(t, err)
}
+
+func TestCopyFile(t *testing.T) {
+ chartBuilder := NewChartBuilder("data/sample_config.json", "data/sample_schema.json")
+ SRC_FILE := "data/sample_config.json"
+ DEST_FILE := "data/sample_config_copy.json"
+ err := chartBuilder.copyFile(SRC_FILE, DEST_FILE)
+ defer os.RemoveAll(DEST_FILE)
+
+ assert.Nil(t, err)
+
+ srcBytes, _ := ioutil.ReadFile(SRC_FILE)
+ destBytes, _ := ioutil.ReadFile(DEST_FILE)
+
+ assert.Equal(t, srcBytes, destBytes)
+}
+
+func TestCopyDirectory(t *testing.T) {
+ chartBuilder := NewChartBuilder("data/sample_config.json", "data/sample_schema.json")
+
+ SRC_DIR := "data/resources/std"
+ DEST_DIR := "data/resources/std-copy"
+
+ err := chartBuilder.copyDirectory(SRC_DIR, DEST_DIR)
+ defer os.RemoveAll(DEST_DIR)
+ assert.Nil(t, err)
+
+ srcFiles, _ := ioutil.ReadDir(SRC_DIR)
+ destFiles, _ := ioutil.ReadDir(DEST_DIR)
+
+ assert.Equal(t, len(srcFiles), len(destFiles))
+
+ for i, srcFile := range srcFiles {
+ for j, destFile := range destFiles {
+ if i == j {
+ srcFileInfo, _ := ioutil.ReadFile(srcFile.Name())
+ destFileInfo, _ := ioutil.ReadFile(destFile.Name())
+ assert.Equal(t, srcFileInfo, destFileInfo)
+ }
+ }
+ }
+}