diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..ba077a4 --- /dev/null +++ b/.gitignore @@ -0,0 +1 @@ +bin diff --git a/src/.gitignore b/src/.gitignore new file mode 100644 index 0000000..f472c12 --- /dev/null +++ b/src/.gitignore @@ -0,0 +1,5 @@ +go.sum +*_ +.coverage.* +.*.log +workspace_* diff --git a/src/Makefile b/src/Makefile new file mode 100644 index 0000000..b744a41 --- /dev/null +++ b/src/Makefile @@ -0,0 +1,73 @@ + +BIN_NAME := oc-deploy + +BIN_OPTS := + +################## + +SOURCES := $(wildcard *.go) $(wildcard */*.go) +BIN_DIR = ../bin/ + +PLUGINS := $(wildcard ../plugins/*/*.go) +OBJS := ${PLUGINS:.go=.so} + +%.so: %.go + go build -buildmode=plugin -o $@ $< + +help: + @echo + @echo 'Usage:' + @echo ' make build Génère les exécutables.' + @echo ' make get-deps runs dep ensure, mostly used for ci.' + + @echo ' make run BIN_OPTS=... Go run' + @echo ' make run_install BIN_OPTS=... Go run' + @echo ' make run_uninstall BIN_OPTS=... Go run' + @echo ' make exec BIN_OPTS=... exécutable' + @echo ' make exec_install BIN_OPTS=... exécutable' + @echo ' make exec_uninstall BIN_OPTS=... exécutable' + @echo ' make test Test.' + + @echo ' make test Test' + @echo ' make clean Clean the directory tree.' + @echo + +${BIN_DIR}/${BIN_NAME}: ${SOURCES} $(OBJS) + go build -o ${BIN_DIR}/${BIN_NAME} + +build: ${BIN_DIR}/${BIN_NAME} + +run: $(OBJS) + @go run main.go ${BIN_OPTS} + +run_generate: $(OBJS) + @go run main.go generate ${BIN_OPTS} + +run_install: $(OBJS) + @go run main.go install ${BIN_OPTS} + +run_uninstall: $(OBJS) + @go run main.go uninstall ${BIN_OPTS} + +exec: ${BIN_DIR}/${BIN_NAME} $(OBJS) + @${BIN_DIR}/${BIN_NAME} ${BIN_OPTS} + +exec_install: ${BIN_DIR}/${BIN_NAME} $(OBJS) + @${BIN_DIR}/${BIN_NAME} install ${BIN_OPTS} + +exec_uninstall: ${BIN_DIR}/${BIN_NAME} $(OBJS) + @${BIN_DIR}/${BIN_NAME} uninstall ${BIN_OPTS} + +clean: + @test ! -e ${BIN_DIR}/${BIN_NAME} || rm ${BIN_DIR}/${BIN_NAME} + @test ! -e .coverage.out || rm .coverage.out + @test ! -e .coverage.html || rm .coverage.html + @test ! -e go.sum || rm go.sum + @test ! -e .oc-deploy.log || rm .oc-deploy.log + @rm -rf workspace_* + @go mod tidy + +.PHONY: test +test: + @go test ./... -coverprofile=.coverage.out -v + go tool cover -html=.coverage.out -o .coverage.html diff --git a/src/README.md b/src/README.md new file mode 100644 index 0000000..b279d6a --- /dev/null +++ b/src/README.md @@ -0,0 +1,75 @@ +# Helm + +[![Build Status](https://github.com/helm/helm/workflows/release/badge.svg)](https://github.com/helm/helm/actions?workflow=release) +[![Go Report Card](https://goreportcard.com/badge/github.com/helm/helm)](https://goreportcard.com/report/github.com/helm/helm) +[![GoDoc](https://img.shields.io/static/v1?label=godoc&message=reference&color=blue)](https://pkg.go.dev/helm.sh/helm/v3) +[![CII Best Practices](https://bestpractices.coreinfrastructure.org/projects/3131/badge)](https://bestpractices.coreinfrastructure.org/projects/3131) + +Helm is a tool for managing Charts. Charts are packages of pre-configured Kubernetes resources. + +Use Helm to: + +- Find and use [popular software packaged as Helm Charts](https://artifacthub.io/packages/search?kind=0) to run in Kubernetes +- Share your own applications as Helm Charts +- Create reproducible builds of your Kubernetes applications +- Intelligently manage your Kubernetes manifest files +- Manage releases of Helm packages + +## Helm in a Handbasket + +Helm is a tool that streamlines installing and managing Kubernetes applications. +Think of it like apt/yum/homebrew for Kubernetes. + +- Helm renders your templates and communicates with the Kubernetes API +- Helm runs on your laptop, CI/CD, or wherever you want it to run. +- Charts are Helm packages that contain at least two things: + - A description of the package (`Chart.yaml`) + - One or more templates, which contain Kubernetes manifest files +- Charts can be stored on disk, or fetched from remote chart repositories + (like Debian or RedHat packages) + +## Install + +Binary downloads of the Helm client can be found on [the Releases page](https://github.com/helm/helm/releases/latest). + +Unpack the `helm` binary and add it to your PATH and you are good to go! + +If you want to use a package manager: + +- [Homebrew](https://brew.sh/) users can use `brew install helm`. +- [Chocolatey](https://chocolatey.org/) users can use `choco install kubernetes-helm`. +- [Scoop](https://scoop.sh/) users can use `scoop install helm`. +- [Snapcraft](https://snapcraft.io/) users can use `snap install helm --classic` + +To rapidly get Helm up and running, start with the [Quick Start Guide](https://helm.sh/docs/intro/quickstart/). + +See the [installation guide](https://helm.sh/docs/intro/install/) for more options, +including installing pre-releases. + +## Docs + +Get started with the [Quick Start guide](https://helm.sh/docs/intro/quickstart/) or plunge into the [complete documentation](https://helm.sh/docs) + +## Roadmap + +The [Helm roadmap uses GitHub milestones](https://github.com/helm/helm/milestones) to track the progress of the project. + +## Community, discussion, contribution, and support + +You can reach the Helm community and developers via the following channels: + +- [Kubernetes Slack](https://kubernetes.slack.com): + - [#helm-users](https://kubernetes.slack.com/messages/helm-users) + - [#helm-dev](https://kubernetes.slack.com/messages/helm-dev) + - [#charts](https://kubernetes.slack.com/messages/charts) +- Mailing List: + - [Helm Mailing List](https://lists.cncf.io/g/cncf-helm) +- Developer Call: Thursdays at 9:30-10:00 Pacific ([meeting details](https://github.com/helm/community/blob/master/communication.md#meetings)) + +### Contribution + +If you're interested in contributing, please refer to the [Contributing Guide](CONTRIBUTING.md) **before submitting a pull request**. + +### Code of conduct + +Participation in the Helm community is governed by the [Code of Conduct](code-of-conduct.md). diff --git a/src/chart/conf.go b/src/chart/conf.go new file mode 100644 index 0000000..a6b1e3a --- /dev/null +++ b/src/chart/conf.go @@ -0,0 +1,34 @@ +package chart + +import ( + "os" + "gopkg.in/yaml.v2" +) + +type ChartData struct { + Name string `yaml:"name"` + Chart string `yaml:"chart"` + Version string `yaml:"version"` + + Opts string `yaml:"helm_opts"` + Values string `yaml:"helm_values"` + FileValues string `yaml:"helm_filevalues"` + +} + +type ChartRepoData struct { + Name string `yaml:"name"` + Repository string `yaml:"repository"` + Charts []ChartData `yaml:"charts"` +} + +type chartsRepoData struct { + Charts []ChartRepoData `yaml:"opencloud"` +} + +func FromConfigFile(filename string) ([]ChartRepoData) { + yamlFile, _ := os.ReadFile(filename) + var data chartsRepoData + yaml.Unmarshal(yamlFile, &data) + return data.Charts +} diff --git a/src/chart/conf_test.go b/src/chart/conf_test.go new file mode 100644 index 0000000..05e1b71 --- /dev/null +++ b/src/chart/conf_test.go @@ -0,0 +1,30 @@ +package chart + +// https://pkg.go.dev/github.com/stretchr/testify/assert + +import ( + "testing" + "path/filepath" + "github.com/stretchr/testify/assert" +) + + +func TestReadConfChart(t *testing.T){ + src := filepath.Join(TEST_SRC_DIR, "oc.yml") + + assert.FileExists(t, src, "FromConfigFile error") + + data := FromConfigFile(src) + assert.Equal(t, data[0].Name, "bitnami", "FromConfigFile error") + assert.Equal(t, data[0].Repository, "https://charts.bitnami.com/bitnami", "FromConfigFile error") + + wordpress := data[0].Charts[0] + assert.Equal(t, wordpress.Name, "wordpress", "FromConfigFile error") + assert.Equal(t, wordpress.Chart, "bitnami/wordpress", "FromConfigFile error") + assert.Equal(t, wordpress.Version, "23.1.0", "FromConfigFile error") + + phpmyadmin := data[0].Charts[1] + assert.Equal(t, phpmyadmin.Name, "phpmyadmin", "FromConfigFile error") + assert.Equal(t, phpmyadmin.Chart, "bitnami/phpmyadmin", "FromConfigFile error") + assert.Equal(t, phpmyadmin.Version, "17.0.4", "FromConfigFile error") +} diff --git a/src/chart/main_test.go b/src/chart/main_test.go new file mode 100644 index 0000000..3b82b4a --- /dev/null +++ b/src/chart/main_test.go @@ -0,0 +1,23 @@ +package chart + +import ( + "os" + "testing" + "path/filepath" +) + +var TEST_DEST_DIR = "../wrk_chart" +var TEST_SRC_DIR = filepath.Join("../../test", "chart") + +func TestMain(m *testing.M) { + folderPath := TEST_DEST_DIR + + os.RemoveAll(folderPath) + os.MkdirAll(folderPath, os.ModePerm) + + // call flag.Parse() here if TestMain uses flags + exitCode := m.Run() + + os.RemoveAll(folderPath) + os.Exit(exitCode) +} \ No newline at end of file diff --git a/src/cmd/args.go b/src/cmd/args.go new file mode 100644 index 0000000..fed9fd3 --- /dev/null +++ b/src/cmd/args.go @@ -0,0 +1,71 @@ +// Package cmd : Parse les arguments + +// Arguments : version ==> version d'OpenCloud +// Argument : projet ==> nom du projet +package cmd + +import ( + "github.com/spf13/cobra" + + log "oc-deploy/log_wrapper" +) + +var ( + context string + version string +) + +func Execute() { + + log.Log().Debug().Msg("Execute") + + var rootCmd = &cobra.Command{Use: "oc-deploy"} + + var cmdInstall = &cobra.Command{ + Use: "install", + Short: "deploy", + Long: `deploy Charts`, + Args: cobra.MaximumNArgs(0), + Run: func(cmd *cobra.Command, args []string) { + InstallCmd(context, version) + }, + Example: "oc-deploy install --version 1.0 --context ex1", + } + + var cmdUninstall = &cobra.Command{ + Use: "uninstall", + Short: "undeploy", + Long: `Undeploy`, + Args: cobra.MaximumNArgs(0), + Run: func(cmd *cobra.Command, args []string) { + UninstallCmd(context, version) + }, + Example: "oc-deploy uninstall --context ex1", + } + + var cmdGenerate = &cobra.Command{ + Use: "generate", + Short: "generate", + Long: "Value", + Args: cobra.MaximumNArgs(0), + Run: func(cmd *cobra.Command, args []string) { + GenerateCmd(context, version) + }, + Example: "oc-deploy generate --version 1.0 --context ex1", + } + + cmdInstall.Flags().StringVarP(&context, "context", "p", "opencloud", "Nom du projet") + cmdInstall.Flags().StringVarP(&version, "version", "v", "latest", "Version") + + cmdUninstall.Flags().StringVarP(&context, "context", "p", "opencloud", "Nom du projet") + + cmdGenerate.Flags().StringVarP(&context, "context", "p", "opencloud", "Nom du projet") + cmdGenerate.Flags().StringVarP(&version, "version", "v", "latest", "Version") + + rootCmd.AddCommand(cmdInstall) + rootCmd.AddCommand(cmdUninstall) + rootCmd.AddCommand(cmdGenerate) + + cobra.CheckErr(rootCmd.Execute()) + +} \ No newline at end of file diff --git a/src/cmd/generateCmd.go b/src/cmd/generateCmd.go new file mode 100644 index 0000000..22d38aa --- /dev/null +++ b/src/cmd/generateCmd.go @@ -0,0 +1,27 @@ +package cmd + +import ( + + log "oc-deploy/log_wrapper" + + "oc-deploy/versionOc" + "oc-deploy/generate" +) + +func GenerateCmd(project string, version string) { + log.Log().Info().Msg("Generate >> ") + + version, err := versionOc.Get(version) + if err != nil { + log.Log().Fatal().Msg("OpenCloud >> " + err.Error()) + } + log.Log().Info().Msg(" >> Version : " + version) + + obj := generate.GenerateClass{Workspace: "workspace_" + project, Version: version} + fic, err := obj.New() + if err != nil { + log.Log().Fatal().Msg(" >> " + err.Error()) + } + log.Log().Info().Msg(" >> Value : " + fic) + +} \ No newline at end of file diff --git a/src/cmd/installCmd.go b/src/cmd/installCmd.go new file mode 100644 index 0000000..dfcaf4b --- /dev/null +++ b/src/cmd/installCmd.go @@ -0,0 +1,51 @@ +package cmd + +import ( + "fmt" + log "oc-deploy/log_wrapper" + + "oc-deploy/versionOc" + "oc-deploy/install" +) + +func InstallCmd(context string, version string) { + log.Log().Info().Msg("Install >> ") + + log.Log().Info().Msg(" << Contexte : " + context) + + version, err := versionOc.Get(version) + log.Log().Info().Msg(" << Version : " + version) + if err != nil { + log.Log().Fatal().Msg(" >> " + err.Error()) + } + + workspace := fmt.Sprintf("workspace_%s", context) + obj := install.InstallClass{Workspace: workspace, Version: version} + + file, err := obj.New() + if err != nil { + log.Log().Fatal().Msg(" >> " + err.Error()) + } + log.Log().Info().Msg(" >> Config : " + file ) + + err = obj.Tools() + if err != nil { + log.Log().Fatal().Msg(" >> " + err.Error()) + } + + err = obj.ChartRepo() + if err != nil { + log.Log().Fatal().Msg(" >> " + err.Error()) + } + + err = obj.K8s(context) + if err != nil { + log.Log().Fatal().Msg(" >> " + err.Error()) + } + + err = obj.Charts() + if err != nil { + log.Log().Fatal().Msg(" >> " + err.Error()) + } + +} \ No newline at end of file diff --git a/src/cmd/uninstallCmd.go b/src/cmd/uninstallCmd.go new file mode 100644 index 0000000..c59753f --- /dev/null +++ b/src/cmd/uninstallCmd.go @@ -0,0 +1,34 @@ +package cmd + +import ( + // "fmt" + // "strings" + // "github.com/spf13/cobra" + + log "oc-deploy/log_wrapper" + + "oc-deploy/versionOc" + "oc-deploy/install" +) + +func UninstallCmd(context string, version string) { + log.Log().Info().Msg("Install >> ") + + log.Log().Info().Msg(" << Contexte : " + context) + + version, err := versionOc.Get(version) + log.Log().Info().Msg(" << Version : " + version) + if err != nil { + log.Log().Fatal().Msg(" >> " + err.Error()) + } + + obj := install.UninstallClass{Workspace: "workspace_" + context, Version: version} + obj.New() + + // fic, err := obj.New() + // if err != nil { + // log.Log().Fatal().Msg(" >> " + err.Error()) + // } + // log.Log().Info().Msg(" >> Value : " + fic) + +} \ No newline at end of file diff --git a/src/generate/generate.go b/src/generate/generate.go new file mode 100644 index 0000000..38f7662 --- /dev/null +++ b/src/generate/generate.go @@ -0,0 +1,23 @@ +package generate + +import ( + "fmt" + "oc-deploy/utils" +) + +type GenerateClass struct { + Version string + Workspace string + url string +} + +func (this GenerateClass) New() (string, error) { + src := fmt.Sprintf("../offline/default_value_%s.yml", this.Version) + dst := fmt.Sprintf("%s/default_value.yml", this.Workspace) + + err := utils.CopyFile(src, dst) + if err != nil { + return "", err + } + return src, nil +} diff --git a/src/go.mod b/src/go.mod new file mode 100644 index 0000000..e15d104 --- /dev/null +++ b/src/go.mod @@ -0,0 +1,25 @@ +module oc-deploy + +go 1.22.0 + +require ( + github.com/jarcoal/httpmock v1.3.1 + github.com/rs/zerolog v1.33.0 + github.com/spf13/cobra v1.8.1 + github.com/stretchr/testify v1.9.0 + gopkg.in/yaml.v2 v2.4.0 +) + +require ( + github.com/davecgh/go-spew v1.1.1 // indirect + github.com/inconshreveable/mousetrap v1.1.0 // indirect + github.com/kr/pretty v0.3.1 // indirect + github.com/mattn/go-colorable v0.1.13 // indirect + github.com/mattn/go-isatty v0.0.20 // indirect + github.com/pmezard/go-difflib v1.0.0 // indirect + github.com/rogpeppe/go-internal v1.11.0 // indirect + github.com/spf13/pflag v1.0.5 // indirect + golang.org/x/sys v0.22.0 // indirect + gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c // indirect + gopkg.in/yaml.v3 v3.0.1 // indirect +) diff --git a/src/helm/chart.go b/src/helm/chart.go new file mode 100644 index 0000000..2201209 --- /dev/null +++ b/src/helm/chart.go @@ -0,0 +1,121 @@ +package helm + +import ( + "fmt" + "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 + 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 + } + + msg := fmt.Sprintf("%s install %s %s %s --output json", bin, this.Name, this.Chart, 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 + + json.Unmarshal(stdout, &objmap) + + res := objmap.Info.Status + + return res, nil +} + +func (this HelmChart) Uninstall() (string, error) { + bin := this.Bin + + log.Log().Info().Msg(" >> Chart : " + this.Name) + + 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 { + return false, errors.New(string(stdout)) + } + + res := string(stdout) + res = strings.TrimSuffix(res, "\n") + + log.Log().Debug().Msg(string(stdout)) + + return res != "", nil +} diff --git a/src/helm/main_test.go b/src/helm/main_test.go new file mode 100644 index 0000000..7fa572c --- /dev/null +++ b/src/helm/main_test.go @@ -0,0 +1,24 @@ +package helm + +import ( + "os" + "testing" + "path/filepath" +) + +var TEST_DEST_DIR = "../wrk_helm" +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 + + os.RemoveAll(folderPath) + os.MkdirAll(folderPath, os.ModePerm) + + // call flag.Parse() here if TestMain uses flags + exitCode := m.Run() + + os.RemoveAll(folderPath) + os.Exit(exitCode) +} \ No newline at end of file diff --git a/src/helm/repo.go b/src/helm/repo.go new file mode 100644 index 0000000..0b9da56 --- /dev/null +++ b/src/helm/repo.go @@ -0,0 +1,53 @@ +package helm + +import ( + "fmt" + "strings" + "os/exec" + + log "oc-deploy/log_wrapper" +) + +type HelmRepo struct { + Bin string // Chemin vers le binaire + Name string + Repository string // Url du dépôt + ForceUpdate bool + Opts string +} + +func (this HelmRepo) AddRepository() (string, error) { + helm_bin := this.Bin + + force_update := "--force-update=false" + if this.ForceUpdate { + force_update = "--force-update=true" + } + + msg := fmt.Sprintf("%s repo add %s %s %s %s", helm_bin, this.Name, this.Repository, force_update, this.Opts) + log.Log().Debug().Msg(msg) + + cmd := exec.Command(helm_bin, "repo", "add", this.Name, this.Repository, force_update) + stdout, err := cmd.CombinedOutput() + + res := string(stdout) + res = strings.TrimSuffix(res, "\n") + + return res, err +} + +// helm repo remove [NAME] +func (this HelmRepo) RemoveRepository() (string, error) { + helm_bin := this.Bin + + msg := fmt.Sprintf("%s repo remove %s", helm_bin, this.Name) + log.Log().Debug().Msg(msg) + + cmd := exec.Command(helm_bin, "repo", "remove", this.Name) + stdout, err := cmd.CombinedOutput() + + res := string(stdout) + res = strings.TrimSuffix(res, "\n") + + return res, err +} diff --git a/src/helm/repo_test.go b/src/helm/repo_test.go new file mode 100644 index 0000000..9cedc24 --- /dev/null +++ b/src/helm/repo_test.go @@ -0,0 +1,23 @@ +package helm + +import ( + // "os" + // "path/filepath" + + "testing" + + // "github.com/stretchr/testify/assert" +) + +func TestHelmRepoAdd(t *testing.T){ + // fmt.Println(" TestVersion ", TEST_BIN_DIR) + + // 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, version, "v3.15.4+gfa9efb0", "TestHelmVersion error") +} \ No newline at end of file diff --git a/src/helm/version.go b/src/helm/version.go new file mode 100644 index 0000000..8c9eb21 --- /dev/null +++ b/src/helm/version.go @@ -0,0 +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 +} diff --git a/src/helm/version_test.go b/src/helm/version_test.go new file mode 100644 index 0000000..1b9a081 --- /dev/null +++ b/src/helm/version_test.go @@ -0,0 +1,22 @@ +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, version, "v3.15.4+gfa9efb0", "TestHelmVersion error") +} \ No newline at end of file diff --git a/src/install/install.go b/src/install/install.go new file mode 100644 index 0000000..4045607 --- /dev/null +++ b/src/install/install.go @@ -0,0 +1,200 @@ +package install + +import ( + "fmt" + "errors" + "sync" + // "time" + + log "oc-deploy/log_wrapper" + "oc-deploy/utils" + "oc-deploy/tool" + "oc-deploy/helm" + "oc-deploy/chart" + "oc-deploy/kubectl" +) + +type InstallClass struct { + Version string + Workspace string + + versionFile string + tools []tool.ToolData + toolsBin map[string]string + charts []chart.ChartRepoData +} + +func (this *InstallClass) New() (string, error) { + + // Extraction du fichier de version + log.Log().Debug().Msg("Téléchargement du fichier de version") + src := fmt.Sprintf("../offline/oc_%s.yml", this.Version) + dst := fmt.Sprintf("%s/oc.yml", this.Workspace) + + err := utils.CopyFile(src, dst) + if err != nil { + return "", err + } + + // Lecture du fichier de conf + this.versionFile = dst + + this.tools = tool.FromConfigFile(this.versionFile) + + this.charts = chart.FromConfigFile(this.versionFile) + + return dst, nil +} + +func (this *InstallClass) Tools() (error) { + + var mem []tool.ToolClass + + for _, v := range this.tools { + + tool2 := tool.ToolClass{} + v.Bin = this.Workspace + err := tool2.New(v) + if err != nil { + return err + } + mem = append(mem,tool2) + } + + this.toolsBin = make(map[string]string) + + for _, p := range mem { + data := p.Obj.Get() + log.Log().Info().Msg(fmt.Sprintf(" >> Outils : %s", data.Name)) + err := p.Locate() + if err != nil { + log.Log().Info().Msg(fmt.Sprintf(" << %s ", err)) + return err + } + log.Log().Info().Msg(fmt.Sprintf(" << %s ", p.Path)) + version, err1 := p.Version() + if err1 != nil { + log.Log().Info().Msg(fmt.Sprintf(" << %s ", err1)) + return err1 + } + log.Log().Info().Msg(fmt.Sprintf(" << %s ", version)) + + this.toolsBin[data.Name] = p.Path + } + + return nil +} + +func (this *InstallClass) getToolBin(name string) (string, error) { + for key, value := range this.toolsBin { + if key == name { + return value, nil + } + } + + return "", errors.New("Error") +} + +func (this *InstallClass) ChartRepo() (error) { + + bin_path, _ := this.getToolBin("helm") + + for _, v := range this.charts { + log.Log().Info().Msg(fmt.Sprintf(" >> Helm Repo : %s", v.Name)) + repo := helm.HelmRepo{Bin: bin_path, + Name: v.Name, + Repository: v.Repository, + ForceUpdate: true} + res, err := repo.AddRepository() + if err != nil { + log.Log().Info().Msg(fmt.Sprintf(" << %s ", err)) + return err + } + log.Log().Info().Msg(fmt.Sprintf(" << %s ", res)) + + } + return nil +} + +func (this *InstallClass) K8s(context string) (error) { + bin_path, _ := this.getToolBin("kubectl") + + kube := kubectl.KubeContext{Bin: bin_path} + + err := kube.UseContext(context) + if err != nil { + log.Log().Info().Msg(fmt.Sprintf(" << Kube : %s ", err)) + return err + } + + currentcontext, namespace, server, err := kube.GetContext() + if err != nil { + log.Log().Info().Msg(fmt.Sprintf(" << Kube : %s ", err)) + return err + } + log.Log().Info().Msg(fmt.Sprintf(" << Kube : %s ", currentcontext)) + + log.Log().Info().Msg(fmt.Sprintf(" << : %s ", namespace)) + log.Log().Info().Msg(fmt.Sprintf(" << : %s ", server)) + + err = kube.Check() + if err != nil { + log.Log().Info().Msg(fmt.Sprintf(" << : %s ", err)) + return err + } + log.Log().Info().Msg(fmt.Sprintf(" << : %s ", "OK")) + + return nil +} + +func (this *InstallClass) Charts() (error) { + helm_bin, _ := this.getToolBin("helm") + kubectl_bin, _ := this.getToolBin("kubectl") + + var wg sync.WaitGroup + + for _, v := range this.charts { + for _, v1 := range v.Charts { + wg.Add(1) + + go func() { + defer wg.Done() + this.worker(helm_bin, kubectl_bin, v1) + } () + + } + } + wg.Wait() + return nil +} + +func (this *InstallClass) worker(helm_bin string, kubectl_bin string, chart chart.ChartData) { + + log.Log().Info().Msg(fmt.Sprintf(" << Chart : %s ", chart.Name)) + + helmchart := helm.HelmChart{Bin: helm_bin, + Name: chart.Name, + Chart: chart.Chart, + Version: chart.Version, + Workspace: this.Workspace, + Opts: chart.Opts, + Values: chart.Values, + FileValues: chart.FileValues} + + obj := kubectl.KubeObject{Bin: kubectl_bin, + Name: chart.Name} + + res, err := helmchart.Install() + if err != nil { + log.Log().Error().Msg(fmt.Sprintf(" >> %s %s (%s)", helmchart.Name, "KO", err)) + return + } + log.Log().Info().Msg(fmt.Sprintf(" >> %s (%s)", helmchart.Name, res)) + + err = obj.Wait() + if err != nil { + log.Log().Error().Msg(fmt.Sprintf(" >> %s %s (%s)", chart.Name, "KO", err)) + } else { + log.Log().Info().Msg(fmt.Sprintf(" >> %s %s", chart.Name, "OK")) + } +} diff --git a/src/install/uninstall.go b/src/install/uninstall.go new file mode 100644 index 0000000..d5f24f5 --- /dev/null +++ b/src/install/uninstall.go @@ -0,0 +1,18 @@ +package install + +import ( + // "fmt" + // "os" + // "io" + // "path/filepath" + // log "oc-deploy/log_wrapper" +) + +type UninstallClass struct { + Version string + Workspace string +} + +func (this UninstallClass) New() { + +} diff --git a/src/kubectl/context.go b/src/kubectl/context.go new file mode 100644 index 0000000..7b99706 --- /dev/null +++ b/src/kubectl/context.go @@ -0,0 +1,108 @@ +package kubectl + +import ( + // "fmt" + "strings" + "errors" + "os/exec" + "encoding/json" + log "oc-deploy/log_wrapper" +) + +type KubeContext struct { + Bin string // Chemin vers le binaire +} + + +type kubeConfig struct { + CurrentContext string `json:"current-context"` + Contexts [] kubeConfigContexts `json:"contexts"` + Clusters [] kubeConfigClusters `json:"clusters"` +} + +type kubeConfigContexts struct { + Name string `json:"name"` + Context kubeConfigContext `json:"context"` +} + +type kubeConfigContext struct { + Cluster string `json:"cluster"` + User string `json:"user"` + Namespace string `json:"namespace"` +} + +type kubeConfigCluster struct { + Server string `json:"server"` +} + +type kubeConfigClusters struct { + Name string `json:"name"` + Cluster kubeConfigCluster `json:"cluster"` +} + +func (this KubeContext) GetCurrentContext() (string, error) { + + cmd := exec.Command(this.Bin, "config", "current-context") + stdout, err := cmd.CombinedOutput() + + res := string(stdout) + res = strings.TrimSuffix(res, "\n") + + return res, err +} + +// Current Context +// namespace, server +func (this KubeContext) GetContext() (string, string, string, error) { + + cmd := exec.Command(this.Bin, "config", "view", "-o", "json") + stdout, _ := cmd.CombinedOutput() + + var objmap kubeConfig + + json.Unmarshal(stdout, &objmap) + currentContext := objmap.CurrentContext + + currentCluster := "" + currentNamespace := "" + for _, v := range objmap.Contexts { + if v.Name == currentContext { + currentNamespace = v.Context.Namespace + currentCluster = v.Context.Cluster + } + } + + currentServer := "" + for _, v := range objmap.Clusters { + if v.Name == currentCluster { + currentServer = v.Cluster.Server + } + } + + return currentContext, currentNamespace, currentServer, nil +} + +func (this KubeContext) UseContext(newContext string) (error) { + + cmd := exec.Command(this.Bin, "config", "use-context", newContext) + stdout, err := cmd.CombinedOutput() + + if err != nil { + log.Log().Debug().Msg(string(stdout)) + return errors.New(string(stdout)) + } + + return nil +} + +func (this KubeContext) Check() (error) { + + cmd := exec.Command(this.Bin, "cluster-info") + stdout, err := cmd.CombinedOutput() + if err != nil { + log.Log().Debug().Msg(string(stdout)) + return errors.New("Kube non disponible") + } + + return nil +} diff --git a/src/kubectl/object.go b/src/kubectl/object.go new file mode 100644 index 0000000..7ad6eec --- /dev/null +++ b/src/kubectl/object.go @@ -0,0 +1,82 @@ +package kubectl + +import ( + "fmt" + "strings" + "errors" + "time" + "os/exec" + "encoding/json" + log "oc-deploy/log_wrapper" +) + +type KubeObject struct { + Bin string // Chemin vers le binaire + Name string +} + +type getOutput struct { + Kind string `json:"kind"` + Status getStatusOutput `json:"status"` +} + +type getStatusOutput struct { + Replicas int `json:"replicas"` + UnavailableReplicas int `json:"unavailableReplicas"` +} + +func (this KubeObject) Get() (map[string]any, error) { + bin := this.Bin + name := this.Name + + msg := fmt.Sprintf("%s get deployment %s -o json", bin, name) + log.Log().Debug().Msg(msg) + + m := make(map[string]any) + + cmd_args := strings.Split(msg, " ") + + cmd := exec.Command(cmd_args[0], cmd_args[1:]...) + stdout, err := cmd.CombinedOutput() + if err != nil { + return m, errors.New(string(stdout)) + } + + var objmap getOutput + + json.Unmarshal(stdout, &objmap) + + kind := objmap.Kind + status := objmap.Status + + m["name"] = name + m["kind"] = kind + m["replicas"] = status.Replicas + m["UnavailableReplicas"] = status.UnavailableReplicas + + return m, nil +} + +func (this KubeObject) Wait() (error) { + + boucle := 10 + sleep := 10000 * time.Millisecond + + for _ = range boucle { + + log.Log().Debug().Msg(fmt.Sprintf("Check Deployement %s", this.Name)) + + m, err := this.Get() + if err != nil { + return err + } + ko := m["UnavailableReplicas"].(int) + if ko == 0 { + return nil + } + + time.Sleep(sleep) + + } + return errors.New("Temps d'attente dépassé") +} \ No newline at end of file diff --git a/src/kubectl/version.go b/src/kubectl/version.go new file mode 100644 index 0000000..2dc4726 --- /dev/null +++ b/src/kubectl/version.go @@ -0,0 +1,31 @@ +package kubectl + +import ( + "os/exec" + "encoding/json" +) + +type toolClientVersion struct { + GitVersion string `json:"gitVersion"` +} + +type toolVersion struct { + ClientVersion toolClientVersion `json:"clientVersion"` +} + +func Version(path string) (string, error) { + + cmd := exec.Command(path, "version", "-o", "json", "--client=true") + stdout, err := cmd.CombinedOutput() + + if err != nil { + return "", err + } + + var objmap toolVersion + + json.Unmarshal(stdout, &objmap) + res := objmap.ClientVersion.GitVersion + + return res, nil +} diff --git a/src/log_wrapper/log_wrapper.go b/src/log_wrapper/log_wrapper.go new file mode 100644 index 0000000..1029052 --- /dev/null +++ b/src/log_wrapper/log_wrapper.go @@ -0,0 +1,48 @@ +package log_wrapper + +// https://github.com/rs/zerolog/issues/150 + +import ( + "os" + "github.com/rs/zerolog" +) + +var mainLogVar zerolog.Logger + +type FilteredWriter struct { + w zerolog.LevelWriter + level zerolog.Level +} + +func (w *FilteredWriter) Write(p []byte) (n int, err error) { + return w.w.Write(p) +} +func (w *FilteredWriter) WriteLevel(level zerolog.Level, p []byte) (n int, err error) { + if level == w.level { + return w.w.WriteLevel(level, p) + } + return len(p), nil +} + +func Log() *zerolog.Logger { + return &mainLogVar +} + +func InitLog(serverName string) bool { + + fAll, _ := os.OpenFile("./" + serverName + ".log", os.O_APPEND|os.O_CREATE|os.O_RDWR, 0644) + output := zerolog.ConsoleWriter{Out: os.Stdout} + + writerInfo := zerolog.MultiLevelWriter(output) + writerError := zerolog.MultiLevelWriter(output) + writerFatal := zerolog.MultiLevelWriter(output) + filteredWriteInfo := &FilteredWriter{writerInfo, zerolog.InfoLevel} + filteredWriterError := &FilteredWriter{writerError, zerolog.ErrorLevel} + filteredWriterFatal := &FilteredWriter{writerFatal, zerolog.FatalLevel} + + w := zerolog.MultiLevelWriter(fAll, filteredWriteInfo, filteredWriterError, filteredWriterFatal) + + mainLogVar = zerolog.New(w).With().Timestamp().Logger() + + return true +} diff --git a/src/main.go b/src/main.go new file mode 100644 index 0000000..daee0be --- /dev/null +++ b/src/main.go @@ -0,0 +1,19 @@ +package main + +import ( + "oc-deploy/cmd" + log "oc-deploy/log_wrapper" +) + +func main() { + + log.InitLog(".oc-deploy") + + log.Log().Debug().Msg("Start") + log.Log().Info().Msg("oc-deploy :") + + cmd.Execute() + + log.Log().Debug().Msg("End") + +} diff --git a/src/tool/conf.go b/src/tool/conf.go new file mode 100644 index 0000000..a8b6b73 --- /dev/null +++ b/src/tool/conf.go @@ -0,0 +1,17 @@ +package tool + +import ( + "os" + "gopkg.in/yaml.v2" +) + +type toolsData struct { + Tools []ToolData `yaml:"tools"` +} + +func FromConfigFile(filename string) ([]ToolData) { + yamlFile, _ := os.ReadFile(filename) + var data toolsData + yaml.Unmarshal(yamlFile, &data) + return data.Tools +} diff --git a/src/tool/helm.go b/src/tool/helm.go new file mode 100644 index 0000000..33ac173 --- /dev/null +++ b/src/tool/helm.go @@ -0,0 +1,53 @@ +package tool + +import ( + "fmt" + "os" + +// log "oc-deploy/log_wrapper" + "oc-deploy/utils" + "oc-deploy/helm" +) + +type HelmInstallData struct { + obj ToolData + tmp string +} + +func (this HelmInstallData) Get() (ToolData) { + return this.obj +} + +func (this HelmInstallData) Download() (error) { + + bin_dir := this.obj.Bin + err2 := os.MkdirAll(bin_dir, os.ModePerm) + if err2 != nil { + fmt.Println(err2) + return err2 + } + + tmp_file := fmt.Sprintf("%s/oc-deploy-%s", this.tmp, this.obj.Name) + url := fmt.Sprintf(this.obj.Url, this.obj.Version) + + err := utils.DownloadFromUrl(tmp_file, url, 0777) + if err != nil { + return err + } + + r, _ := os.Open(tmp_file) + err1 := utils.ExtractTarGz(bin_dir, r) + + os.Remove(tmp_file) + + bin_file := fmt.Sprintf("%s/%s", bin_dir, this.obj.Name) + + os.Chmod(bin_file, 0755) + + return err1 +} + +/////////////// +func (this HelmInstallData) Version(path string) (string, error) { + return helm.Version(path) +} \ No newline at end of file diff --git a/src/tool/kubectl.go b/src/tool/kubectl.go new file mode 100644 index 0000000..150ef0c --- /dev/null +++ b/src/tool/kubectl.go @@ -0,0 +1,41 @@ +package tool + +import ( + "fmt" + "os" + "path/filepath" + + log "oc-deploy/log_wrapper" + "oc-deploy/utils" + "oc-deploy/kubectl" +) + +type KubecltInstallData struct { + obj ToolData +} + +func (this KubecltInstallData) Get() (ToolData) { + return this.obj +} + +func (this KubecltInstallData) Download() (error) { + + bin_dir := this.obj.Bin + bin := filepath.Join(bin_dir, this.obj.Name) + url := fmt.Sprintf(this.obj.Url, this.obj.Version) + + log.Log().Debug().Msg(fmt.Sprintf("Téléchargement : %s, %s", bin, url)) + os.MkdirAll(bin_dir, os.ModePerm) + + err := utils.DownloadFromUrl(bin, url, 0777) + if err != nil {return err} + + os.Chmod(bin, 0755) + + return nil +} + +/////////////// +func (this KubecltInstallData) Version(path string) (string, error) { + return kubectl.Version(path) +} diff --git a/src/tool/tool.go b/src/tool/tool.go new file mode 100644 index 0000000..4c75c75 --- /dev/null +++ b/src/tool/tool.go @@ -0,0 +1,80 @@ +package tool + +import ( + "fmt" + "os" + "os/exec" + "errors" + "path/filepath" +) + +type ToolData struct { + Name string `yaml:"name"` + Url string `yaml:"url"` + Version string `yaml:"version"` + Bin string +} + +type ToolClass struct { + Obj Forme + Path string +} + +type Forme interface { + Download() error + Version(string) (string, error) + Get() ToolData +} + +////////// +func (this *ToolClass) New(data ToolData) (error) { + f, err := factory(data) + if err != nil { + return err + } + this.Obj = f + return nil +} + +func (this *ToolClass) Locate() (error) { + + obj := this.Obj + data := obj.Get() + path := filepath.Join(data.Bin, data.Name) + + if _, err := os.Stat(path); err != nil { + path2, _ := exec.LookPath(data.Name) + if path2 != "" { + path = path2 + } else { + err = obj.Download() + if err != nil { + return err + } + } + } + + this.Path = path + return nil +} + +func (this *ToolClass) Version() (string, error) { + obj := (this.Obj) + return obj.Version(this.Path) +} + +////////// +func factory(data ToolData) (Forme, error) { + var f Forme + + switch data.Name { + case "kubectl": + f = KubecltInstallData{obj: data} + case "helm": + f = HelmInstallData{obj: data, tmp: "/tmp"} + default: + return f, errors.New(fmt.Sprintf("Outil Inconnu : %s", data.Name)) + } + + return f, nil +} diff --git a/src/utils/copyFile.go b/src/utils/copyFile.go new file mode 100644 index 0000000..dd0dcd4 --- /dev/null +++ b/src/utils/copyFile.go @@ -0,0 +1,35 @@ +package utils + +import ( + "os" + "io" + "path/filepath" +) + +func CopyFile(src string, dst string) (error) { + + if _, err := os.Stat(src); err != nil { + return err + } + + fin, errOpen := os.Open(src) + if errOpen != nil { + return errOpen + } + defer fin.Close() + + folderPath := filepath.Dir(dst) + os.MkdirAll(folderPath, os.ModePerm) + + fout, errCreate := os.Create(dst) + if errCreate != nil { + return errCreate + } + defer fout.Close() + + _, errCopy := io.Copy(fout, fin) + if errCopy != nil { + return errCopy + } + return nil +} \ No newline at end of file diff --git a/src/utils/copyFile_test.go b/src/utils/copyFile_test.go new file mode 100644 index 0000000..cb73c42 --- /dev/null +++ b/src/utils/copyFile_test.go @@ -0,0 +1,47 @@ +package utils + +// https://pkg.go.dev/github.com/stretchr/testify/assert#Nilf + +import ( + "testing" + "path/filepath" + "github.com/stretchr/testify/assert" +) + +func TestCopyFileExist(t *testing.T){ + src := filepath.Join(TEST_SRC_DIR, "fichier1") + dest := filepath.Join(TEST_DEST_DIR, "fichier1") + + err := CopyFile(src, dest) + + assert.Nilf(t, err, "error message %s", src) + assert.FileExists(t, dest, "CopyFile error") +} + +func TestCopyErrSrcFileNotExist(t *testing.T) { + src := filepath.Join(TEST_SRC_DIR, "inconnu") + dest := filepath.Join(TEST_DEST_DIR, "inconnu") + + err := CopyFile(src, dest) + + assert.NotNilf(t, err, "CopyFile error %s", src) +} + +func TestCopyFileErrCreate(t *testing.T){ + src := filepath.Join(TEST_SRC_DIR, "fichier1") + dest := filepath.Join("/INCONNU", "fichier1") + + err := CopyFile(src, dest) + + assert.NotNilf(t, err, "error message %s", src) + assert.NoFileExists(t, dest, "CopyFile error") +} + +func TestCopyErrSrcWrite(t *testing.T) { + src := "/" + dest := filepath.Join(TEST_DEST_DIR, "inconnu") + + err := CopyFile(src, dest) + + assert.NotNilf(t, err, "CopyFile error %s", src) +} diff --git a/src/utils/download.go b/src/utils/download.go new file mode 100644 index 0000000..39374ff --- /dev/null +++ b/src/utils/download.go @@ -0,0 +1,72 @@ +package utils + +import ( + // "fmt" + "os" + "io" + "path" + "net/http" + "archive/tar" + "compress/gzip" +) + +func DownloadFromUrl(dest string, url string, chmod os.FileMode) error { + + resp, err := http.Get(url) + if err != nil { + return err + } + defer resp.Body.Close() + + out, err := os.Create(dest) + defer out.Close() + if err != nil { + return err + } + + _, err = io.Copy(out, resp.Body) + if err != nil { + return err + } + + os.Chmod(dest, chmod) + + return nil +} + + +func ExtractTarGz(dest string, gzipStream io.Reader) error { + uncompressedStream, err := gzip.NewReader(gzipStream) + if err != nil { + return err + } + + tarReader := tar.NewReader(uncompressedStream) + + for true { + header, err := tarReader.Next() + + if err == io.EOF { + break + } + + switch header.Typeflag { + case tar.TypeDir: + // if err := os.Mkdir(dest + "/" + header.Name, 0755); err != nil { + // return err + // } + case tar.TypeReg: + outName := dest + "/" + path.Base( header.Name) + outFile, _ := os.Create(outName) + if err != nil { + return err + } + if _, err := io.Copy(outFile, tarReader); err != nil { + return err + } + outFile.Close() + } + + } + return nil +} diff --git a/src/utils/download_test.go b/src/utils/download_test.go new file mode 100644 index 0000000..9bfa427 --- /dev/null +++ b/src/utils/download_test.go @@ -0,0 +1,28 @@ +package utils + +// https://pkg.go.dev/github.com/stretchr/testify/assert#Nilf + +import ( + "path/filepath" + + "testing" + + "github.com/stretchr/testify/assert" + "github.com/jarcoal/httpmock" +) + +func TestDownload(t *testing.T){ + httpmock.Activate() + defer httpmock.DeactivateAndReset() + + url := "http://test.download.com" + + httpmock.RegisterResponder("GET", url, + httpmock.NewStringResponder(200, `CONTENU_URL`)) + + dest := filepath.Join(TEST_DEST_DIR, "url") + + err := DownloadFromUrl(dest, url, 777) + assert.Nilf(t, err, "error message %s", url) + assert.FileExists(t, dest, "DownloadFromUrl error") +} diff --git a/src/utils/main_test.go b/src/utils/main_test.go new file mode 100644 index 0000000..41d4414 --- /dev/null +++ b/src/utils/main_test.go @@ -0,0 +1,23 @@ +package utils + +import ( + "os" + "testing" + "path/filepath" +) + +var TEST_DEST_DIR = "../wrk_utils" +var TEST_SRC_DIR = filepath.Join("../../test", "utils") + +func TestMain(m *testing.M) { + folderPath := TEST_DEST_DIR + + os.RemoveAll(folderPath) + os.MkdirAll(folderPath, os.ModePerm) + + // call flag.Parse() here if TestMain uses flags + exitCode := m.Run() + + os.RemoveAll(folderPath) + os.Exit(exitCode) +} \ No newline at end of file diff --git a/src/versionOc/versionOc.go b/src/versionOc/versionOc.go new file mode 100644 index 0000000..ae6ee3c --- /dev/null +++ b/src/versionOc/versionOc.go @@ -0,0 +1,58 @@ +// Package : +package versionOc + +import ( + "fmt" + "os" + "errors" + "io/ioutil" + "gopkg.in/yaml.v2" + log "oc-deploy/log_wrapper" +) + +type versionInput struct { + Version string `yaml:"version"` +} + +// Get : Retourne la version +func Get(version string) (string, error) { + + version2 := version + if version == "latest" { + versionLatest, err := readLatestFile() + if err != nil { + return "", err + } + version2 = versionLatest + } + + src := fmt.Sprintf("../offline/oc_%s.yml", version2) + if _, err := os.Stat(src); err != nil { + log.Log().Debug().Msg(err.Error()) + return "", errors.New("Version non disponible") + } + + return version2, nil +} + +// readLatestFile : Lit le numéro de la version dans le fichier lastest.yml +func readLatestFile() (string, error) { + src := "../offline/latest.yml" + + fin, err := os.Open(src) + if err != nil { + return "", err + } + defer fin.Close() + + byteValue, err := ioutil.ReadAll(fin) + if err != nil { + return "", err + } + + var objmap versionInput + + yaml.Unmarshal(byteValue, &objmap) + + return objmap.Version, nil +} \ No newline at end of file diff --git a/test/bin/helm b/test/bin/helm new file mode 100755 index 0000000..a656d56 Binary files /dev/null and b/test/bin/helm differ diff --git a/test/bin/kubectl b/test/bin/kubectl new file mode 100644 index 0000000..b98b785 Binary files /dev/null and b/test/bin/kubectl differ diff --git a/test/chart/oc.yml b/test/chart/oc.yml new file mode 100644 index 0000000..446cec5 --- /dev/null +++ b/test/chart/oc.yml @@ -0,0 +1,15 @@ +--- + +opencloud: + - name: bitnami + repository: https://charts.bitnami.com/bitnami # Repository des Charts + charts: + - name: wordpress + chart: bitnami/wordpress + version: 23.1.0 + values: {} + + - name: phpmyadmin + chart: bitnami/phpmyadmin + version: 17.0.4 + values: {} diff --git a/test/utils/fichier1 b/test/utils/fichier1 new file mode 100644 index 0000000..957bdea --- /dev/null +++ b/test/utils/fichier1 @@ -0,0 +1 @@ +Fichier1 \ No newline at end of file