Implementation of onboard client 49/10949/1
authorYouhwan Seol <yh.seol@samsung.com>
Tue, 21 Feb 2023 04:06:15 +0000 (13:06 +0900)
committerYouhwan Seol <yh.seol@samsung.com>
Tue, 18 Apr 2023 12:27:38 +0000 (21:27 +0900)
Change-Id: I93f5c30b441d320db5b014c30c40a9a145214377
Signed-off-by: Youhwan Seol <yh.seol@samsung.com>
go.mod
go.sum
pkg/api/commons/url/url.go
pkg/client/onboard/client.go [new file with mode: 0644]
pkg/client/onboard/utils.go [new file with mode: 0644]

diff --git a/go.mod b/go.mod
index c886fdf..6d697f3 100755 (executable)
--- a/go.mod
+++ b/go.mod
@@ -5,6 +5,7 @@ go 1.19
 require (
        github.com/gin-gonic/gin v1.8.2
        github.com/stretchr/testify v1.8.1
+       github.com/pkg/errors v0.9.1
 )
 
 require (
diff --git a/go.sum b/go.sum
index 7aee98d..726edeb 100755 (executable)
--- a/go.sum
+++ b/go.sum
@@ -41,6 +41,8 @@ github.com/modern-go/reflect2 v1.0.2/go.mod h1:yWuevngMOJpCy52FWWMvUC8ws7m/LJsjY
 github.com/pelletier/go-toml/v2 v2.0.6 h1:nrzqCb7j9cDFj2coyLNLaZuJTLjWjlaz6nvTvIwycIU=
 github.com/pelletier/go-toml/v2 v2.0.6/go.mod h1:eumQOmlWiOPt5WriQQqoM5y18pDHwha2N+QD+EUNTek=
 github.com/pkg/diff v0.0.0-20210226163009-20ebb0f2a09e/go.mod h1:pJLUxLENpZxwdsKMEsNbx1VGcRFpLqf3715MtcvvzbA=
+github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4=
+github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
 github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
 github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
 github.com/rogpeppe/go-internal v1.6.1/go.mod h1:xXDCJY+GAPziupqXw64V24skbSoqbTEfhy4qGm1nDQc=
index 79578a2..1ad15bc 100644 (file)
@@ -39,3 +39,9 @@ func Status() string { return "/status" }
 
 // Info returns the status url as a type of string.
 func Info() string { return "/info" }
+
+// IPSName returns the name url as a type of string.
+func IPSName() string { return "/{name}" }
+
+// Version returns the version url as a type of string.
+func Version() string { return "/ver" }
diff --git a/pkg/client/onboard/client.go b/pkg/client/onboard/client.go
new file mode 100644 (file)
index 0000000..8833cb6
--- /dev/null
@@ -0,0 +1,71 @@
+/*
+==================================================================================
+
+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 onboard
+
+import (
+       "os"
+
+       "gerrit.o-ran-sc.org/r/aiml-fw/aihp/ips/kserve-adapter/pkg/commons/logger"
+)
+
+type Command interface {
+       Get(name string) error
+       Download(name string, version string) (string, error)
+}
+
+type Executor struct {
+       Command
+}
+
+var (
+       onboarderIP   string
+       onboarderPort string
+)
+
+func init() {
+       onboarderIP = os.Getenv("ONBOARDER_IP")
+       onboarderPort = os.Getenv("ONBOARDER_PORT")
+}
+
+func (Executor) Get(name string) (err error) {
+       logger.Logging(logger.DEBUG, "IN")
+       defer logger.Logging(logger.DEBUG, "OUT")
+
+       targetURL := buildURL(name, "")
+
+       _, err = requestToOnboard(targetURL)
+       if err != nil {
+               return
+       }
+       return
+}
+
+func (Executor) Download(name string, version string) (path string, err error) {
+       logger.Logging(logger.DEBUG, "IN")
+       defer logger.Logging(logger.DEBUG, "OUT")
+
+       targetURL := buildURL(name, version)
+
+       path, err = fetchHelmPackageFromOnboard(targetURL)
+       if err != nil {
+               return
+       }
+       return
+}
diff --git a/pkg/client/onboard/utils.go b/pkg/client/onboard/utils.go
new file mode 100644 (file)
index 0000000..aff2cb0
--- /dev/null
@@ -0,0 +1,175 @@
+/*
+==================================================================================
+
+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 onboard
+
+import (
+       "archive/tar"
+       "compress/gzip"
+       "io"
+       "net/http"
+       netUrl "net/url"
+       "os"
+       "path/filepath"
+       "strings"
+
+       "gerrit.o-ran-sc.org/r/aiml-fw/aihp/ips/kserve-adapter/pkg/api/commons/url"
+       "github.com/pkg/errors"
+
+       "gerrit.o-ran-sc.org/r/aiml-fw/aihp/ips/kserve-adapter/pkg/commons/logger"
+)
+
+func fetchHelmPackageFromOnboard(url string) (path string, err error) {
+       logger.Logging(logger.DEBUG, "IN")
+       defer logger.Logging(logger.DEBUG, "OUT")
+
+       resp, err := requestToOnboard(url)
+       if err != nil {
+               return
+       }
+       defer resp.Body.Close()
+
+       path = "/tmp"
+
+       err = Untar(path, resp.Body)
+       if err != nil {
+               return
+       }
+       return
+}
+
+func buildURL(name string, version string) string {
+       logger.Logging(logger.DEBUG, "IN")
+       defer logger.Logging(logger.DEBUG, "OUT")
+
+       targetURL := netUrl.URL{
+               Scheme: "http",
+               Host:   onboarderIP + ":" + onboarderPort,
+               Path:   url.Onboard(),
+       }
+
+       if name != "" {
+               targetURL.Path += url.IPSName() + "/" + name
+
+               if version != "" {
+                       targetURL.Path += url.Version() + "/" + version
+
+               }
+       }
+
+       return targetURL.String()
+}
+
+func requestToOnboard(url string) (*http.Response, error) {
+       logger.Logging(logger.DEBUG, "IN")
+       defer logger.Logging(logger.DEBUG, "OUT")
+
+       resp, err := http.Get(url)
+       if err != nil {
+               logger.Logging(logger.ERROR, err.Error())
+               // TODO : define errors
+               return nil, errors.Wrap(err, "internal server error")
+       }
+
+       if resp.StatusCode != http.StatusOK {
+               // TODO : define errors
+               err = errors.New("internal server error")
+               logger.Logging(logger.ERROR, err.Error())
+               return nil, err
+       }
+       return resp, err
+}
+
+func Untar(dst string, r io.Reader) error {
+       logger.Logging(logger.DEBUG, "IN")
+       defer logger.Logging(logger.DEBUG, "OUT")
+
+       gzr, err := gzip.NewReader(r)
+       if err != nil {
+               logger.Logging(logger.ERROR, err.Error())
+               return err
+       }
+       defer gzr.Close()
+
+       tr := tar.NewReader(gzr)
+
+       for {
+               header, err := tr.Next()
+
+               switch {
+               case err == io.EOF:
+                       logger.Logging(logger.ERROR, err.Error())
+                       return nil
+               case err != nil:
+                       logger.Logging(logger.ERROR, err.Error())
+                       return err
+               case header == nil:
+                       continue
+               }
+
+               target := filepath.Join(dst, header.Name)
+
+               switch header.Typeflag {
+               case tar.TypeDir:
+                       err := mkdirectory(target)
+                       if err != nil {
+                               logger.Logging(logger.ERROR, err.Error())
+                               return err
+                       }
+               case tar.TypeReg:
+                       paths := strings.Split(target, "/")
+                       if len(paths) != 0 {
+                               var path string
+                               for idx := range paths {
+                                       if !strings.Contains(paths[idx], ".") {
+                                               path = filepath.Join(path, paths[idx])
+                                       }
+                               }
+                               err = mkdirectory(path)
+                               if err != nil {
+                                       logger.Logging(logger.ERROR, err.Error())
+                                       return err
+                               }
+                       }
+                       f, err := os.OpenFile(target, os.O_CREATE|os.O_RDWR, os.FileMode(header.Mode))
+                       if err != nil {
+                               logger.Logging(logger.ERROR, err.Error())
+                               return err
+                       }
+                       _, err = io.Copy(f, tr)
+                       if err != nil {
+                               logger.Logging(logger.ERROR, err.Error())
+                               return err
+                       }
+                       f.Close()
+               }
+       }
+}
+
+func mkdirectory(name string) (err error) {
+       _, err = os.Stat(name)
+       if err != nil {
+               err = os.MkdirAll(name, 0755)
+               if err != nil {
+                       logger.Logging(logger.ERROR, err.Error())
+                       return
+               }
+       }
+       return
+}