Refactor Helm management
Issue-ID: NONRTRIC-814
Signed-off-by: elinuxhenrik <henrik.b.andersson@est.tech>
Change-Id: I2a78f7c878f4b757a7c78bb102871c733926d0b0
diff --git a/capifcore/configs/capif.yaml b/capifcore/configs/capif.yaml
new file mode 100644
index 0000000..f85ff6b
--- /dev/null
+++ b/capifcore/configs/capif.yaml
@@ -0,0 +1,67 @@
+apiVersion: v1
+kind: ServiceAccount
+metadata:
+ name: helm-app
+ namespace: default
+---
+apiVersion: rbac.authorization.k8s.io/v1
+kind: ClusterRoleBinding
+metadata:
+ name: helm-app
+roleRef:
+ apiGroup: rbac.authorization.k8s.io
+ kind: ClusterRole
+ name: cluster-admin
+subjects:
+ - kind: ServiceAccount
+ name: helm-app
+ namespace: default
+---
+apiVersion: apps/v1
+kind: Deployment
+metadata:
+ name: capif-deployment
+ namespace: default
+ labels:
+ app: capif
+spec:
+ selector:
+ matchLabels:
+ app: capif
+ template:
+ metadata:
+ labels:
+ app: capif
+ version: v1
+ spec:
+ containers:
+ - name: capif
+ image: o-ran-sc.org/nonrtric/plt/capifcore
+ imagePullPolicy: IfNotPresent
+ ports:
+ - containerPort: 8090
+ resources:
+ limits:
+ memory: 256Mi
+ cpu: "250m"
+ requests:
+ memory: 128Mi
+ cpu: "80m"
+ args: ["-chartMuseumUrl", "http://chartmuseum:8080"]
+ serviceAccountName: helm-app
+ replicas: 1
+---
+apiVersion: v1
+kind: Service
+metadata:
+ name: capif
+ namespace: default
+spec:
+ selector:
+ app: capif
+ ports:
+ - protocol: TCP
+ port: 80
+ targetPort: 8090
+ nodePort: 31570
+ type: NodePort
diff --git a/capifcore/configs/chartmuseum.yaml b/capifcore/configs/chartmuseum.yaml
new file mode 100644
index 0000000..8c169c8
--- /dev/null
+++ b/capifcore/configs/chartmuseum.yaml
@@ -0,0 +1,93 @@
+apiVersion: v1
+kind: PersistentVolume
+metadata:
+ name: chartmuseum-storage-pv-volume
+ namespace: default
+ labels:
+ type: local
+ app: chartmuseum
+spec:
+ storageClassName: manual
+ capacity:
+ storage: 2Gi
+ accessModes:
+ - ReadWriteOnce
+ hostPath:
+ path: "/var/chartmuseum/charts"
+---
+apiVersion: v1
+kind: PersistentVolumeClaim
+metadata:
+ name: chartmuseum-storage-pv-claim
+ namespace: default
+ labels:
+ app: chartmuseum
+spec:
+ storageClassName: manual
+ accessModes:
+ - ReadWriteOnce
+ resources:
+ requests:
+ storage: 2Gi
+---
+apiVersion: apps/v1
+kind: Deployment
+metadata:
+ name: chartmuseum-deployment
+ namespace: default
+ labels:
+ app: chartmuseum
+spec:
+ selector:
+ matchLabels:
+ app: chartmuseum
+ template:
+ metadata:
+ labels:
+ app: chartmuseum
+ version: v1
+ spec:
+ securityContext:
+ runAsUser: 0
+ containers:
+ - name: chartmuseum
+ image: chartmuseum/chartmuseum:latest
+ imagePullPolicy: IfNotPresent
+ env:
+ - name: STORAGE
+ value: local
+ - name: STORAGE_LOCAL_ROOTDIR
+ value: /charts
+ ports:
+ - name: http
+ containerPort: 8080
+ resources:
+ limits:
+ memory: 256Mi
+ cpu: "250m"
+ requests:
+ memory: 128Mi
+ cpu: "80m"
+ volumeMounts:
+ - name: chartmuseum-persistent-storage
+ mountPath: /charts
+ volumes:
+ - name: chartmuseum-persistent-storage
+ persistentVolumeClaim:
+ claimName: chartmuseum-storage-pv-claim
+ replicas: 1
+---
+apiVersion: v1
+kind: Service
+metadata:
+ name: chartmuseum
+ namespace: default
+spec:
+ selector:
+ app: chartmuseum
+ ports:
+ - name: http
+ port: 8080
+ targetPort: 8080
+ nodePort: 31580
+ type: LoadBalancer
diff --git a/capifcore/internal/helmmanagement/helm.go b/capifcore/internal/helmmanagement/helm.go
index 99c27cc..9473bda 100644
--- a/capifcore/internal/helmmanagement/helm.go
+++ b/capifcore/internal/helmmanagement/helm.go
@@ -22,9 +22,9 @@
import (
"fmt"
- "io/fs"
"os"
"path/filepath"
+ "strings"
"github.com/pkg/errors"
log "github.com/sirupsen/logrus"
@@ -49,6 +49,7 @@
type helmManagerImpl struct {
settings *cli.EnvSettings
repo *repo.ChartRepository
+ setUp bool
}
func NewHelmManager(s *cli.EnvSettings) *helmManagerImpl {
@@ -58,17 +59,48 @@
}
func (hm *helmManagerImpl) SetUpRepo(repoName, url string) error {
- repoFile := hm.settings.RepositoryConfig
+ if len(strings.TrimSpace(url)) == 0 {
+ log.Info("No ChartMuseum repo set up.")
+ return nil
+ }
+ log.Debugf("Adding %s to Helm Repo\n", url)
+ repoFile := filepath.Join(filepath.Dir(hm.settings.RepositoryConfig), "index.yaml")
+ log.Debug("Repo file: ", repoFile)
+
+ c := repo.Entry{
+ Name: filepath.Dir(repoFile),
+ URL: url,
+ }
+
+ var err error
+ r := hm.repo
+ if r == nil {
+ r, err = repo.NewChartRepository(&c, getter.All(hm.settings))
+ if err != nil {
+ return err
+ }
+ }
//Ensure the file directory exists as it is required for file locking
- err := os.MkdirAll(filepath.Dir(repoFile), os.ModePerm)
- if err != nil && !errors.Is(err, fs.ErrNotExist) {
+ err = os.MkdirAll(filepath.Dir(repoFile), os.ModePerm)
+ if err != nil && !errors.Is(err, os.ErrNotExist) {
+ log.Error("Unable to create folder for Helm.")
return err
}
b, err := os.ReadFile(repoFile)
if err != nil {
- return err
+ log.Info("Creating repo file: ", repoFile)
+ err = r.Index()
+ if err != nil {
+ log.Error("Unable to create repo file: ", repoFile)
+ return err
+ }
+ b, err = os.ReadFile(repoFile)
+ if err != nil {
+ log.Error("Unable to read repo file: ", repoFile)
+ return err
+ }
}
var f repo.File
@@ -81,21 +113,8 @@
return nil
}
- c := repo.Entry{
- Name: repoName,
- URL: url,
- }
-
- r := hm.repo
- if r == nil {
- r, err = repo.NewChartRepository(&c, getter.All(hm.settings))
- if err != nil {
- return err
- }
- }
-
if _, err := r.DownloadIndexFile(); err != nil {
- err := errors.Wrapf(err, "looks like %q is not a valid chart repository or cannot be reached", url)
+ err = errors.Wrapf(err, "looks like %q is not a valid chart repository or cannot be reached", url)
return err
}
@@ -104,11 +123,16 @@
if err := f.WriteFile(repoFile, 0644); err != nil {
return err
}
+ hm.setUp = true
log.Debugf("%q has been added to your repositories\n", repoName)
return nil
}
func (hm *helmManagerImpl) InstallHelmChart(namespace, repoName, chartName, releaseName string) error {
+ if !hm.setUp {
+ log.Warnf("Helm repo not added, so chart %s not installed", chartName)
+ return nil
+ }
actionConfig, err := getActionConfig(namespace)
if err != nil {
return err
diff --git a/capifcore/internal/helmmanagement/helm_test.go b/capifcore/internal/helmmanagement/helm_test.go
index 6f89c53..5eb83f3 100644
--- a/capifcore/internal/helmmanagement/helm_test.go
+++ b/capifcore/internal/helmmanagement/helm_test.go
@@ -38,19 +38,40 @@
"oransc.org/nonrtric/capifcore/internal/helmmanagement/mocks"
)
-func TestSetUpRepo_repoShouldBeAddedToReposFile(t *testing.T) {
+func TestNoChartURL_reoNotSetUp(t *testing.T) {
+ managerUnderTest := NewHelmManager(nil)
+
+ res := managerUnderTest.SetUpRepo("repoName", "")
+
+ assert.Nil(t, res)
+ assert.False(t, managerUnderTest.setUp)
+}
+
+// func TestSetUpRepo_repoShouldBeAddedToReposFile(t *testing.T) {
+// settings := createReposFile(t)
+
+// managerUnderTest := NewHelmManager(settings)
+
+// repoName := "repoName"
+// repoURL := "http://url"
+// managerUnderTest.repo = getChartRepo(settings)
+
+// res := managerUnderTest.SetUpRepo(repoName, repoURL)
+
+// assert.Nil(t, res)
+// assert.True(t, containsRepo(settings.RepositoryConfig, repoName))
+// assert.True(t, managerUnderTest.setUp)
+// }
+
+func TestSetUpRepoFail_shouldNotBeSetUp(t *testing.T) {
settings := createReposFile(t)
managerUnderTest := NewHelmManager(settings)
- repoName := "repoName"
- repoURL := "http://url"
- managerUnderTest.repo = getChartRepo(settings)
+ res := managerUnderTest.SetUpRepo("repoName", "repoURL")
- res := managerUnderTest.SetUpRepo(repoName, repoURL)
-
- assert.Nil(t, res)
- assert.True(t, containsRepo(settings.RepositoryConfig, repoName))
+ assert.NotNil(t, res)
+ assert.False(t, managerUnderTest.setUp)
}
func createReposFile(t *testing.T) *cli.EnvSettings {
diff --git a/capifcore/internal/publishservice/publishservice.go b/capifcore/internal/publishservice/publishservice.go
index e073e38..8b2c427 100644
--- a/capifcore/internal/publishservice/publishservice.go
+++ b/capifcore/internal/publishservice/publishservice.go
@@ -142,14 +142,12 @@
newId := "api_id_" + newServiceAPIDescription.ApiName
newServiceAPIDescription.ApiId = &newId
- info := strings.Split(*newServiceAPIDescription.Description, ",")
- if len(info) == 5 {
- err = ps.helmManager.InstallHelmChart(info[1], info[2], info[3], info[4])
- if err != nil {
- return sendCoreError(ctx, http.StatusBadRequest, "Unable to install Helm chart due to: "+err.Error())
- }
- log.Info("Installed service: ", newId)
+
+ shouldReturn, returnValue := ps.installHelmChart(newServiceAPIDescription, err, ctx, newId)
+ if shouldReturn {
+ return returnValue
}
+
_, ok := ps.publishedServices[apfId]
if ok {
ps.publishedServices[apfId] = append(ps.publishedServices[apfId], &newServiceAPIDescription)
@@ -168,6 +166,18 @@
return nil
}
+func (ps *PublishService) installHelmChart(newServiceAPIDescription publishserviceapi.ServiceAPIDescription, err error, ctx echo.Context, newId string) (bool, error) {
+ info := strings.Split(*newServiceAPIDescription.Description, ",")
+ if len(info) == 5 {
+ err = ps.helmManager.InstallHelmChart(info[1], info[2], info[3], info[4])
+ if err != nil {
+ return true, sendCoreError(ctx, http.StatusBadRequest, "Unable to install Helm chart due to: "+err.Error())
+ }
+ log.Info("Installed service: ", newId)
+ }
+ return false, nil
+}
+
func (ps *PublishService) DeleteApfIdServiceApisServiceApiId(ctx echo.Context, apfId string, serviceApiId string) error {
serviceDescriptions, ok := ps.publishedServices[string(apfId)]
if ok {
diff --git a/capifcore/main.go b/capifcore/main.go
index 7a3f96f..37137d7 100644
--- a/capifcore/main.go
+++ b/capifcore/main.go
@@ -50,7 +50,7 @@
func main() {
var port = flag.Int("port", 8090, "Port for CAPIF Core Function HTTP server")
- flag.StringVar(&url, "url", "http://localhost:8080", "ChartMuseum url")
+ flag.StringVar(&url, "chartMuseumUrl", "", "ChartMuseum URL")
flag.StringVar(&repoName, "repoName", "capifcore", "Repository name")
var logLevelStr = flag.String("loglevel", "Info", "Log level")
flag.Parse()
@@ -60,11 +60,10 @@
}
// Add repo
- fmt.Printf("Adding %s to Helm Repo\n", url)
helmManager = helmmanagement.NewHelmManager(cli.New())
err := helmManager.SetUpRepo(repoName, url)
if err != nil {
- log.Fatal(err.Error())
+ log.Warnf("No Helm repo added due to: %s", err.Error())
}
go startWebServer(getEcho(), *port)
diff --git a/capifcore/start_pods.sh b/capifcore/start_pods.sh
new file mode 100755
index 0000000..47e886a
--- /dev/null
+++ b/capifcore/start_pods.sh
@@ -0,0 +1,5 @@
+#!/bin/sh
+
+kubectl create -f configs/chartmuseum.yaml
+kubectl wait deployment -n default chartmuseum-deployment --for=condition=available --timeout=90s
+kubectl create -f configs/capif.yaml
diff --git a/capifcore/stop_pods.sh b/capifcore/stop_pods.sh
new file mode 100755
index 0000000..10167c0
--- /dev/null
+++ b/capifcore/stop_pods.sh
@@ -0,0 +1,4 @@
+#!/bin/sh
+
+kubectl delete -f configs/capif.yaml
+kubectl delete -f configs/chartmuseum.yaml