This commit is contained in:
admju
2024-09-09 14:17:02 +00:00
parent 550675a4aa
commit 13025746e6
32 changed files with 1597 additions and 664 deletions

View File

@@ -1,159 +1,162 @@
package helm
import (
"fmt"
"strconv"
"os"
"os/exec"
"strings"
"errors"
"path/filepath"
"encoding/json"
log "oc-deploy/log_wrapper"
)
type HelmChart struct {
Bin string
Name string
Chart string
Version string
Url string
Workspace string
Opts string
Values string
FileValues string
}
type installInfoOutput struct {
Description string `json:"description"`
Notes string `json:"notes"`
Status string `json:"status"`
}
type installOutput struct {
Info installInfoOutput `json:"info"`
}
func (this HelmChart) Install() (string, error) {
bin := this.Bin
existe, err := this.exists()
if err != nil {
return "", err
}
if existe {
return "Existe déjà", nil
}
ficChart := this.Chart
// Recherche locale
if _, err := os.Stat(ficChart); err != nil {
} else {
// Recherche voa le Workspace
ficChart := filepath.Join(this.Workspace, this.Chart)
if _, err := os.Stat(ficChart); err == nil {
} else {
if this.Url != "" {
fmt.Println("============ 52 Télechargement", this.Url)
}
}
}
msg := fmt.Sprintf("%s install %s %s %s --output json", bin, this.Name, ficChart, this.Opts)
if this.Version != "" {
msg = fmt.Sprintf("%s --version %s", msg, this.Version)
}
if this.FileValues != "" {
fic := filepath.Join(this.Workspace, this.FileValues)
if _, err := os.Stat(fic); err != nil {
log.Log().Warn().Msg(fic)
} else {
msg = fmt.Sprintf("%s --values %s", msg, fic)
}
}
msg = strings.Replace(msg, " ", " ", -1)
log.Log().Debug().Msg(msg)
cmd_args := strings.Split(msg, " ")
cmd := exec.Command(cmd_args[0], cmd_args[1:]...)
stdout, err := cmd.CombinedOutput()
if err != nil {
res := string(stdout)
res = strings.TrimSuffix(res, "\n")
return "", errors.New(res)
}
var objmap installOutput
err = json.Unmarshal(stdout, &objmap)
if err != nil {
return "", err
}
res := objmap.Info.Status
return res, nil
}
func (this HelmChart) Uninstall() (string, error) {
bin := this.Bin
log.Log().Info().Msg(" >> Chart : " + this.Name)
existe, err := this.exists()
if err != nil {
return "", err
}
if ! existe {
return "Non présent", nil
}
msg := fmt.Sprintf("%s uninstall %s", bin, this.Name)
log.Log().Debug().Msg(msg)
cmd := exec.Command(bin, "uninstall", this.Name)
stdout, err := cmd.CombinedOutput()
return string(stdout), err
}
// ../bin/helm list --filter phpmyadminm --short
func (this HelmChart) exists() (bool, error) {
bin := this.Bin
msg := fmt.Sprintf("%s list --filter %s --no-headers", bin, this.Name)
log.Log().Debug().Msg(msg)
cmd_args := strings.Split(msg, " ")
cmd := exec.Command(cmd_args[0], cmd_args[1:]...)
stdout, err := cmd.CombinedOutput()
if err != nil {
log.Log().Debug().Msg(string(stdout))
return false, errors.New(string(stdout))
}
res := string(stdout)
res = strings.TrimSuffix(res, "\n")
log.Log().Debug().Msg(string(stdout))
log.Log().Debug().Msg(strconv.FormatBool(res != ""))
return res != "", nil
}
func (this HelmChart) GetRessources() (map[string]string, error) {
hs := HelmStatus{Name: this.Name}
hs.New(this.Bin)
data, _ := hs.getRessources()
return data, nil
}
package helm
import (
"fmt"
"strconv"
"os"
"strings"
"errors"
"path/filepath"
"encoding/json"
log "oc-deploy/log_wrapper"
)
type HelmChart struct {
Bin string
Name string
Chart string
Version string
Url string
Workspace string
Opts string
Values string
FileValues string
}
type installInfoOutput struct {
Description string `json:"description"`
Notes string `json:"notes"`
Status string `json:"status"`
}
type installOutput struct {
Info installInfoOutput `json:"info"`
}
func (this HelmCommand) ChartInstall(data HelmChart) (string, error) {
bin := this.Bin
existe, err := this.chartExists(data)
if err != nil {
return "", err
}
if existe {
return "Existe déjà", nil
}
ficChart := data.Chart
// Recherche locale
if _, err := os.Stat(ficChart); err != nil {
} else {
// Recherche voa le Workspace
ficChart := filepath.Join(data.Workspace, data.Chart)
if _, err := os.Stat(ficChart); err == nil {
} else {
if data.Url != "" {
fmt.Println("============ 52 Télechargement", data.Url)
}
}
}
msg := fmt.Sprintf("%s install %s %s %s --output json", bin, data.Name, ficChart, data.Opts)
if data.Version != "" {
msg = fmt.Sprintf("%s --version %s", msg, data.Version)
}
if data.FileValues != "" {
fic := filepath.Join(data.Workspace, data.FileValues)
if _, err := os.Stat(fic); err != nil {
log.Log().Warn().Msg(fic)
} else {
msg = fmt.Sprintf("%s --values %s", msg, fic)
}
}
msg = strings.Replace(msg, " ", " ", -1)
log.Log().Debug().Msg(msg)
cmd_args := strings.Split(msg, " ")
cmd := this.Exec(cmd_args[0], cmd_args[1:]...)
stdout, err := cmd.CombinedOutput()
if err != nil {
res := string(stdout)
res = strings.TrimSuffix(res, "\n")
return "", errors.New(res)
}
var objmap installOutput
err = json.Unmarshal(stdout, &objmap)
if err != nil {
return "", err
}
res := objmap.Info.Status
return res, nil
}
func (this HelmCommand) ChartUninstall(data HelmChart) (string, error) {
bin := this.Bin
log.Log().Info().Msg(" >> Chart : " + data.Name)
existe, err := this.chartExists(data)
if err != nil {
return "", err
}
if ! existe {
return "Non présent", nil
}
msg := fmt.Sprintf("%s uninstall %s", bin, data.Name)
log.Log().Debug().Msg(msg)
cmd_args := strings.Split(msg, " ")
cmd := this.Exec(cmd_args[0], cmd_args[1:]...)
stdout, err := cmd.CombinedOutput()
res := string(stdout)
res = strings.TrimSuffix(res, "\n")
log.Log().Debug().Msg(res)
return res, err
}
// ../bin/helm list --filter phpmyadminm --short
func (this HelmCommand) chartExists(data HelmChart) (bool, error) {
bin := this.Bin
msg := fmt.Sprintf("%s list --filter %s --no-headers", bin, data.Name)
log.Log().Debug().Msg(msg)
cmd_args := strings.Split(msg, " ")
cmd := this.Exec(cmd_args[0], cmd_args[1:]...)
stdout, err := cmd.CombinedOutput()
if err != nil {
log.Log().Debug().Msg(string(stdout))
return false, errors.New(string(stdout))
}
res := string(stdout)
res = strings.TrimSuffix(res, "\n")
log.Log().Debug().Msg(string(stdout))
log.Log().Debug().Msg(strconv.FormatBool(res != ""))
return res != "", nil
}
// func (this HelmChart) GetRessources() (map[string]string, error) {
// hs := HelmStatus{Name: this.Name}
// hs.New(this.Bin)
// data, _ := hs.getRessources()
// return data, nil
// }

30
src/helm/chart_test.go Normal file
View File

@@ -0,0 +1,30 @@
package helm
import (
"testing"
"github.com/stretchr/testify/assert"
)
func TestHelmChartExists(t *testing.T){
cmd := getCmdHelm(true, `oc-catalog default 1 2024-09-06 16:01:49.17368605 +0200 CEST deployed oc-catalog-0.1.0 1.0`)
data := HelmChart{Name: "oc-catalog"}
res, err := cmd.chartExists(data)
assert.Nilf(t, err, "error message %s", err)
assert.Truef(t, res, "TestHelmVersion error")
}
func TestHelmChartNotExists(t *testing.T){
cmd := getCmdHelm(true, "\n")
data := HelmChart{Name: "phpmyadmin"}
res, err := cmd.chartExists(data)
assert.Nilf(t, err, "error message %s", err)
assert.Falsef(t, res, "TestHelmVersion error")
}

View File

@@ -1,16 +0,0 @@
package helm
import (
)
type HelmCommandInterface interface {
Status(string) (string, error)
AddRepository(HelmRepo) (string, error)
}
type HelmCommandData struct {
Bin string
}
type RealHelmCommand HelmCommandData

22
src/helm/helm.go Normal file
View File

@@ -0,0 +1,22 @@
package helm
import (
"os/exec"
)
type HelmCommand struct {
Bin string
Exec func(string,...string) commandExecutor
}
////
type commandExecutor interface {
Output() ([]byte, error)
CombinedOutput() ([]byte, error)
}
func (this *HelmCommand) New() {
this.Exec = func(name string, arg ...string) commandExecutor {
return exec.Command(name, arg...)
}
}

View File

@@ -1,8 +1,9 @@
package helm
import (
"os"
"testing"
"os"
"strings"
"testing"
"path/filepath"
)
@@ -11,14 +12,73 @@ var TEST_SRC_DIR = filepath.Join("../../test", "helm")
var TEST_BIN_DIR = filepath.Join("../../test", "bin")
func TestMain(m *testing.M) {
folderPath := TEST_DEST_DIR
folderPath := TEST_DEST_DIR
os.RemoveAll(folderPath)
os.MkdirAll(folderPath, os.ModePerm)
os.RemoveAll(folderPath)
os.MkdirAll(folderPath, os.ModePerm)
// call flag.Parse() here if TestMain uses flags
exitCode := m.Run()
// call flag.Parse() here if TestMain uses flags
exitCode := m.Run()
os.RemoveAll(folderPath)
os.Exit(exitCode)
}
os.RemoveAll(folderPath)
os.Exit(exitCode)
}
// Mock
type MockCommandExecutor struct {
// Used to stub the return of the Output method
// Could add other properties depending on testing needs
output string
}
// Implements the commandExecutor interface
func (m *MockCommandExecutor) Output() ([]byte, error) {
return []byte(m.output), nil
}
func (m *MockCommandExecutor) CombinedOutput() ([]byte, error) {
return []byte(m.output), nil
}
//
func getCmdHelm(mock bool, output string) (HelmCommand) {
if mock == true {
mock := func(name string, args ...string) commandExecutor {
return &MockCommandExecutor{output: output}
}
cmd := HelmCommand{Bin: "mock", Exec: mock}
return cmd
} else {
bin := filepath.Join(TEST_BIN_DIR, "helm")
os.Chmod(bin, 0700)
cmd := HelmCommand{Bin: bin}
cmd.New()
return cmd
}
}
func getCmdsHelm(mock bool, outputs map[string]string) (HelmCommand) {
if mock == true {
mock := func(name string, args ...string) commandExecutor {
cmd := strings.TrimSuffix(strings.Join(args," "), " ")
output := outputs[cmd]
return &MockCommandExecutor{output: output}
}
cmd := HelmCommand{Bin: "mock", Exec: mock}
return cmd
} else {
bin := filepath.Join(TEST_BIN_DIR, "helm")
os.Chmod(bin, 0700)
cmd := HelmCommand{Bin: bin}
cmd.New()
return cmd
}
}

View File

@@ -1,96 +1,98 @@
package helm
import (
"fmt"
"strings"
"os/exec"
"encoding/json"
log "oc-deploy/log_wrapper"
"oc-deploy/utils"
)
type HelmRepo struct {
Name string
Repository string // Url du dépôt
ForceUpdate bool
Opts string
}
func (this RealHelmCommand) AddRepository(repo HelmRepo) (string, error) {
helm_bin := this.Bin
force_update := "--force-update=false"
if repo.ForceUpdate {
force_update = "--force-update=true"
} else {
list, _ := this.ListRepository()
if utils.StringInSlice(repo.Name, list) {
return "Existe déjà", nil
}
}
msg := fmt.Sprintf("%s repo add %s %s %s %s", helm_bin, repo.Name, repo.Repository, force_update, repo.Opts)
log.Log().Debug().Msg(msg)
cmd_args := strings.Split(msg, " ")
cmd := exec.Command(cmd_args[0], cmd_args[1:]...)
stdout, err := cmd.CombinedOutput()
res := string(stdout)
res = strings.TrimSuffix(res, "\n")
return res, err
}
type parseList struct {
Name string `json:"name"`
}
func (this RealHelmCommand) ListRepository() ([]string, error) {
helm_bin := this.Bin
res := make([]string, 0, 0)
msg := fmt.Sprintf("%s repo list -o json", helm_bin)
log.Log().Debug().Msg(msg)
cmd_args := strings.Split(msg, " ")
cmd := exec.Command(cmd_args[0], cmd_args[1:]...)
stdout, err := cmd.CombinedOutput()
if err != nil {
return res, err
}
var objmap []parseList
err = json.Unmarshal([]byte(stdout), &objmap)
if err != nil {
return res, err
}
for _, ele := range objmap {
res = append(res, ele.Name)
}
return res, err
}
// helm repo remove [NAME]
func (this RealHelmCommand) RemoveRepository(repo HelmRepo) (string, error) {
helm_bin := this.Bin
msg := fmt.Sprintf("%s repo remove %s", helm_bin, repo.Name)
log.Log().Debug().Msg(msg)
cmd := exec.Command(helm_bin, "repo", "remove", repo.Name)
stdout, err := cmd.CombinedOutput()
res := string(stdout)
res = strings.TrimSuffix(res, "\n")
return res, err
}
package helm
import (
"fmt"
"strings"
"encoding/json"
log "oc-deploy/log_wrapper"
"oc-deploy/utils"
)
type HelmRepo struct {
Name string
Repository string // Url du dépôt
ForceUpdate bool
Opts string
}
func (this HelmCommand) AddRepository(repo HelmRepo) (string, error) {
helm_bin := this.Bin
force_update := "--force-update=false"
if repo.ForceUpdate {
force_update = "--force-update=true"
} else {
list, _ := this.ListRepository()
if utils.StringInSlice(repo.Name, list) {
return "Existe déjà", nil
}
}
msg := fmt.Sprintf("%s repo add %s %s %s %s", helm_bin, repo.Name, repo.Repository, force_update, repo.Opts)
log.Log().Debug().Msg(msg)
msg = strings.TrimSuffix(msg, " ")
cmd_args := strings.Split(msg, " ")
cmd := this.Exec(cmd_args[0], cmd_args[1:]...)
stdout, err := cmd.CombinedOutput()
res := string(stdout)
res = strings.TrimSuffix(res, "\n")
return res, err
}
type parseList struct {
Name string `json:"name"`
}
func (this HelmCommand) ListRepository() ([]string, error) {
helm_bin := this.Bin
res := make([]string, 0, 0)
msg := fmt.Sprintf("%s repo list -o json", helm_bin)
log.Log().Debug().Msg(msg)
cmd_args := strings.Split(msg, " ")
cmd := this.Exec(cmd_args[0], cmd_args[1:]...)
stdout, err := cmd.CombinedOutput()
if err != nil {
return res, err
}
var objmap []parseList
err = json.Unmarshal(stdout, &objmap)
if err != nil {
return res, err
}
for _, ele := range objmap {
res = append(res, ele.Name)
}
return res, err
}
// helm repo remove [NAME]
func (this HelmCommand) RemoveRepository(repo HelmRepo) (string, error) {
helm_bin := this.Bin
msg := fmt.Sprintf("%s repo remove %s", helm_bin, repo.Name)
log.Log().Debug().Msg(msg)
cmd_args := strings.Split(msg, " ")
cmd := this.Exec(cmd_args[0], cmd_args[1:]...)
stdout, err := cmd.CombinedOutput()
res := string(stdout)
res = strings.TrimSuffix(res, "\n")
return res, err
}

View File

@@ -1,39 +1,72 @@
package helm
import (
"fmt"
// "os"
// "path/filepath"
"testing"
"github.com/stretchr/testify/assert"
)
func TestHelmRepoAdd(t *testing.T) {
repo := HelmRepo{
Bin: "./helm",
Name: "repooc",
Repository: "https://url",
ForceUpdate: true,
Opts: ""}
fmt.Println(" TestHelmRepoAdd ", repo)
res, err := repo.AddRepository()
fmt.Println("TestHelmRepoAdd.24", res, err)
}
// helm : not found
func TestHelmRepoAddErr(t *testing.T) {
repo := HelmRepo{
Bin: "./helm",
Name: "repooc",
Repository: "https://url",
ForceUpdate: true,
Opts: ""}
_, err := repo.AddRepository()
assert.NotNilf(t, err, "error message %s", "./helm")
}
package helm
import (
"testing"
"github.com/stretchr/testify/assert"
)
func TestHelmListRepository(t *testing.T){
cmd := getCmdHelm(true, `[{"name":"bitnami","url":"https://charts.bitnami.com/bitnami"}]`)
res, err := cmd.ListRepository()
assert.Nilf(t, err, "error message %s", err)
assert.Equal(t, "bitnami", res[0], "TestHelmVersion error")
}
func TestHelmRemoveRepository(t *testing.T){
cmd := getCmdHelm(true, `"bitnami" has been removed from your repositories`)
repo := HelmRepo{Name: "bitnami"}
res, err := cmd.RemoveRepository(repo)
assert.Nilf(t, err, "error message %s", err)
assert.Equal(t, `"bitnami" has been removed from your repositories`, res, "TestHelmRemoveRepository error")
}
func TestHelmRemoveRepository2(t *testing.T){
cmd := getCmdHelm(true, `Error: no repositories configured`)
repo := HelmRepo{Name: "bitnami"}
res, err := cmd.RemoveRepository(repo)
assert.Nilf(t, err, "error message %s", err)
assert.Equal(t, `Error: no repositories configured`, res, "TestHelmRemoveRepository error")
}
func TestHelmAddRepositoryNew(t *testing.T){
cmd_output := map[string]string{
"repo list -o json": `[{"name":"repo1","url":"https://repo.com"}]`,
"repo add repo2 https://repo2.com --force-update=false": `"repo2" has been added to your repositories"`,
}
cmd := getCmdsHelm(true, cmd_output)
repo := HelmRepo{Name: "repo2", Repository: "https://repo2.com", ForceUpdate: false}
res, err := cmd.AddRepository(repo)
assert.Nilf(t, err, "error message %s", err)
assert.Equal(t, `"repo2" has been added to your repositories"`, res, "TestHelmAddRepositoryNew error")
}
func TestHelmAddRepositoryExists(t *testing.T){
cmd_output := map[string]string{
"repo list -o json": `[{"name":"repo1","url":"https://repo.com"}]`,
"version --short": "v3.15.4+gfa9efb0",
}
cmd := getCmdsHelm(true, cmd_output)
repo := HelmRepo{Name: "repo1", Repository: "https://repo.com", ForceUpdate: false}
res, err := cmd.AddRepository(repo)
assert.Nilf(t, err, "error message %s", err)
assert.Equal(t, `Existe déjà`, res, "TestHelmRemoveRepository error")
}

View File

@@ -4,20 +4,6 @@ import (
// "fmt"
"encoding/json"
)
type HelmStatus struct {
Name string // Nom
command HelmCommandInterface
}
func (this *HelmStatus) New(bin string) {
this.command = RealHelmCommand{Bin: bin}
}
func (this *HelmStatus) NewMock(mock HelmCommandInterface) {
this.command = mock
}
////
type parseStatusInfoResourcesMetadata struct {
@@ -57,11 +43,11 @@ type parseStatus struct {
Info parseStatusInfo `json:"info"`
}
func (this HelmStatus) getRessources() (map[string]string, error) {
func (this HelmCommand) GetRessources(data HelmChart) (map[string]string, error) {
res := make(map[string]string)
status, err := this.command.Status(this.Name)
status, err := this.Status(data)
if err != nil {
return res, err
}

View File

@@ -9,20 +9,16 @@ import (
"github.com/stretchr/testify/assert"
)
type MockCommandStatus HelmCommandData
func TestHelmRessources(t *testing.T){
func TestHelmStatus(t *testing.T){
hs := HelmStatus{Name: "oc-catalog"}
hs.NewMock(MockCommandStatus{})
data, _ := hs.getRessources()
assert.Equal(t, "StatefulSet", data["oc-catalog-oc-catalog"], "TestHelmStatus error")
}
// Mock
func (this MockCommandStatus) Status(name string) (string, error) {
fileName := filepath.Join(TEST_SRC_DIR, "helm_status.json")
data, _ := os.ReadFile(fileName)
return string(data), nil
}
res_json, _ := os.ReadFile(fileName)
cmd := getCmdHelm(true, string(res_json))
data := HelmChart{Name: "test1"}
res, err := cmd.GetRessources(data)
assert.Nilf(t, err, "error message %s", err)
assert.Equal(t, "StatefulSet", res["oc-catalog-oc-catalog"], "TestHelmStatus error")
}

View File

@@ -3,22 +3,25 @@ package helm
import (
"fmt"
"strings"
"errors"
"os/exec"
"errors"
log "oc-deploy/log_wrapper"
)
func (this RealHelmCommand) Status(name string) (string, error) {
// type HelmData struct {
// Name string
// }
func (this HelmCommand) Status(data HelmChart) (string, error) {
helm_bin := this.Bin
msg := fmt.Sprintf("%s status %s --show-resources -o json", helm_bin, name)
msg := fmt.Sprintf("%s status %s --show-resources -o json", helm_bin, data.Name)
log.Log().Debug().Msg(msg)
cmd_args := strings.Split(msg, " ")
cmd := exec.Command(cmd_args[0], cmd_args[1:]...)
cmd := this.Exec(cmd_args[0], cmd_args[1:]...)
stdout, err := cmd.CombinedOutput()
if err != nil {
log.Log().Debug().Msg(string(stdout))
@@ -27,4 +30,3 @@ func (this RealHelmCommand) Status(name string) (string, error) {
return string(stdout), nil
}

View File

@@ -1,20 +1,20 @@
package helm
import (
"strings"
"os/exec"
)
func Version(path string) (string, error) {
cmd := exec.Command(path, "version", "--short")
stdout, err := cmd.CombinedOutput()
if err != nil {
return "", err
}
res := string(stdout)
res = strings.TrimSuffix(res, "\n")
return res, nil
}
package helm
import (
"strings"
)
func (this HelmCommand) GetVersion() (string, error) {
cmd := this.Exec(this.Bin, "version", "--short")
stdout, err := cmd.CombinedOutput()
if err != nil {
return "", err
}
res := string(stdout)
res = strings.TrimSuffix(res, "\n")
return res, nil
}

View File

@@ -1,22 +1,18 @@
package helm
import (
"os"
"path/filepath"
"testing"
"github.com/stretchr/testify/assert"
)
func TestHelmVersion(t *testing.T){
bin := filepath.Join(TEST_BIN_DIR, "helm")
os.Chmod(bin, 0700)
assert.FileExists(t, bin, "TestHelmVersion error")
version, err := Version(bin)
assert.Nilf(t, err, "error message %s", bin)
assert.Equal(t, "v3.15.4+gfa9efb0", version, "TestHelmVersion error")
}
package helm
import (
"testing"
"github.com/stretchr/testify/assert"
)
func TestHelmVersion(t *testing.T){
cmd := getCmdHelm(true, "v3.15.4+gfa9efb0\n")
version, err := cmd.GetVersion()
assert.Nilf(t, err, "error message %s", err)
assert.Equal(t, "v3.15.4+gfa9efb0", version, "TestHelmVersion error")
}