From: Youhwan Seol Date: Tue, 21 Feb 2023 04:06:15 +0000 (+0900) Subject: Implementation of onboard client X-Git-Tag: 1.0.0~33 X-Git-Url: https://gerrit.o-ran-sc.org/r/gitweb?a=commitdiff_plain;h=47645cb6328485d81932b407e4a418cff25ed250;p=aiml-fw%2Faihp%2Fips%2Fkserve-adapter.git Implementation of onboard client Change-Id: I93f5c30b441d320db5b014c30c40a9a145214377 Signed-off-by: Youhwan Seol --- diff --git a/go.mod b/go.mod index c886fdf..6d697f3 100755 --- 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 --- 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= diff --git a/pkg/api/commons/url/url.go b/pkg/api/commons/url/url.go index 79578a2..1ad15bc 100644 --- a/pkg/api/commons/url/url.go +++ b/pkg/api/commons/url/url.go @@ -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 index 0000000..8833cb6 --- /dev/null +++ b/pkg/client/onboard/client.go @@ -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 index 0000000..aff2cb0 --- /dev/null +++ b/pkg/client/onboard/utils.go @@ -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 +}