Compare commits
	
		
			20 Commits
		
	
	
		
			feat/chart
			...
			c7f8503fb6
		
	
	| Author | SHA1 | Date | |
|---|---|---|---|
|  | c7f8503fb6 | ||
|  | 4bce096e1f | ||
|  | 75b7b94a50 | ||
|  | 13025746e6 | ||
|  | 550675a4aa | ||
|  | a1af83689d | ||
|  | 53a614bd7e | ||
|  | da9aab90eb | ||
|  | 052e6f1368 | ||
|  | dddd5d1831 | ||
|  | a7a5465a22 | ||
|  | 48301bf82e | ||
|  | d12d3e31bf | ||
|  | 9e267becca | ||
|  | 756638fe21 | ||
|  | 11a4d5cc90 | ||
|  | 26404e5892 | ||
|  | 9cf954776f | ||
|  | 11f56722f7 | ||
|  | 4ae5926b01 | 
							
								
								
									
										1
									
								
								.gitignore
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										1
									
								
								.gitignore
									
									
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -0,0 +1 @@ | ||||
| bin | ||||
							
								
								
									
										7
									
								
								offline/default_value_1.0.yml
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										7
									
								
								offline/default_value_1.0.yml
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,7 @@ | ||||
| --- | ||||
|  | ||||
| globals: | ||||
|  | ||||
| composant1: | ||||
|  | ||||
| composant2: | ||||
							
								
								
									
										3
									
								
								offline/latest.yml
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										3
									
								
								offline/latest.yml
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,3 @@ | ||||
| --- | ||||
|  | ||||
| version: 1.0 | ||||
							
								
								
									
										41
									
								
								offline/oc_1.0.yml
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										41
									
								
								offline/oc_1.0.yml
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,41 @@ | ||||
| --- | ||||
| # Définition d'une version | ||||
|  | ||||
| version: 1.0 | ||||
|  | ||||
| tools: | ||||
|   - name: kubectl | ||||
|     url: https://dl.k8s.io/release/%s/bin/linux/amd64/kubectl | ||||
|     version: v1.30.3 | ||||
|   - name: helm | ||||
|     url: https://get.helm.sh/helm-%s-linux-amd64.tar.gz | ||||
|     version: v3.15.4 | ||||
|  | ||||
| # helm install my-release <repo>/<chart> | ||||
| opencloud: | ||||
|   - repository: | ||||
|       name: bitnami | ||||
|       url: https://charts.bitnami.com/bitnami      # Repository des Charts | ||||
|     charts: | ||||
|       - name: wordpress | ||||
|         chart: bitnami/wordpress | ||||
|         version: 23.1.0 | ||||
|         values: {} | ||||
|         helm_opts: --wait-for-jobs | ||||
|         helm_filevalues: values-init.yml | ||||
|  | ||||
|       - name: phpmyadmin | ||||
|         chart: bitnami/phpmyadmin | ||||
|         version: 17.0.4 | ||||
|         values: {} | ||||
|  | ||||
|   - charts: | ||||
|      - name: mongo | ||||
|        chart:  ../oc-mongo/mongo | ||||
|   | ||||
|   - charts: | ||||
|       - name: myfirstrelease | ||||
|         chart: myfirstchart-0.1.0.tgz | ||||
|         url: https://zzzz/myfirstchart-0.1.0.tgz | ||||
|  | ||||
| # helm install myfirstrelease myfirstchart-0.1.0.tgz | ||||
							
								
								
									
										5
									
								
								src/.gitignore
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										5
									
								
								src/.gitignore
									
									
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -0,0 +1,5 @@ | ||||
| go.sum | ||||
| *_ | ||||
| .coverage.* | ||||
| .*.log | ||||
| workspace_* | ||||
							
								
								
									
										79
									
								
								src/Makefile
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										79
									
								
								src/Makefile
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,79 @@ | ||||
|  | ||||
| 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             Dependency download' | ||||
|  | ||||
| 		@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} | ||||
|  | ||||
| get-deps: | ||||
| 	@go mod tidy | ||||
|  | ||||
| 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_* | ||||
|  | ||||
| .PHONY: test | ||||
| test_%: | ||||
| 	go test oc-deploy/$(subst test_,,$@) -coverprofile=.coverage.out -v | ||||
| 	@go tool cover -html=.coverage.out -o .coverage.html | ||||
|  | ||||
| test: | ||||
| 	@go test ./... -coverprofile=.coverage.out -v | ||||
| 	go tool cover -html=.coverage.out -o .coverage.html | ||||
							
								
								
									
										42
									
								
								src/chart/conf.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										42
									
								
								src/chart/conf.go
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,42 @@ | ||||
| package chart | ||||
|  | ||||
| import ( | ||||
|     "os" | ||||
|     "gopkg.in/yaml.v2" | ||||
| ) | ||||
|  | ||||
| type ChartData struct { | ||||
|     Name string `yaml:"name"` | ||||
|     Chart string `yaml:"chart"` | ||||
|     Url string `yaml:"url"` | ||||
|     Version string `yaml:"version"` | ||||
|  | ||||
|     Opts string `yaml:"helm_opts"` | ||||
|     Values string `yaml:"helm_values"` | ||||
|     FileValues string `yaml:"helm_filevalues"` | ||||
| } | ||||
|  | ||||
| type repoData struct { | ||||
|     Name string `yaml:"name"` | ||||
|     Url string `yaml:"url"` | ||||
|     ForceUpdate bool `yaml:"forceupdate"` | ||||
| } | ||||
|  | ||||
| type ChartRepoData struct { | ||||
|     Repository repoData `yaml:"repository"` | ||||
|     Charts []ChartData `yaml:"charts"` | ||||
| } | ||||
|  | ||||
| type chartsRepoData struct { | ||||
|     Charts []ChartRepoData `yaml:"opencloud"` | ||||
| } | ||||
|  | ||||
| func FromConfigFile(filename string) ([]ChartRepoData, error) { | ||||
|     yamlFile, _ := os.ReadFile(filename) | ||||
|     var data chartsRepoData | ||||
|     err := yaml.Unmarshal(yamlFile, &data) | ||||
|     if err != nil { | ||||
|         return data.Charts, err | ||||
|     } | ||||
|     return data.Charts, nil | ||||
| } | ||||
							
								
								
									
										39
									
								
								src/chart/conf_test.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										39
									
								
								src/chart/conf_test.go
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,39 @@ | ||||
| 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, "bitnami", data[0].Repository.Name, "FromConfigFile error") | ||||
|     assert.Equal(t, "https://charts.bitnami.com/bitnami", data[0].Repository.Url, "FromConfigFile error") | ||||
|  | ||||
|     wordpress := data[0].Charts[0] | ||||
|     assert.Equal(t, "wordpress", wordpress.Name, "FromConfigFile error") | ||||
|     assert.Equal(t, "bitnami/wordpress", wordpress.Chart, "FromConfigFile error") | ||||
|     assert.Equal(t, "23.1.0", wordpress.Version, "FromConfigFile error") | ||||
|  | ||||
|     phpmyadmin := data[0].Charts[1] | ||||
|     assert.Equal(t, "phpmyadmin", phpmyadmin.Name, "FromConfigFile error") | ||||
|     assert.Equal(t, "bitnami/phpmyadmin", phpmyadmin.Chart,"FromConfigFile error") | ||||
|     assert.Equal(t, "17.0.4", phpmyadmin.Version, "FromConfigFile error") | ||||
|  | ||||
|     data1 := data[1] | ||||
|     assert.Equal(t, "", data1.Repository.Name, "FromConfigFile error") | ||||
|     assert.Equal(t, "", data1.Repository.Url, "FromConfigFile error") | ||||
|  | ||||
|     myfirstrelease := data1.Charts[0] | ||||
|     assert.Equal(t, "myfirstrelease", myfirstrelease.Name, "FromConfigFile error") | ||||
|     assert.Equal(t, "https://zzzz/myfirstchart-0.1.0.tgz", myfirstrelease.Url, "FromConfigFile error") | ||||
|  | ||||
| } | ||||
							
								
								
									
										23
									
								
								src/chart/main_test.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										23
									
								
								src/chart/main_test.go
									
									
									
									
									
										Normal file
									
								
							| @@ -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) | ||||
| } | ||||
							
								
								
									
										85
									
								
								src/cmd/args.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										85
									
								
								src/cmd/args.go
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,85 @@ | ||||
| // 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 | ||||
|     modules []string | ||||
| ) | ||||
|  | ||||
|  | ||||
| func cobraInstallCmd() *cobra.Command { | ||||
|   return &cobra.Command{ | ||||
|     Use:   "install", | ||||
|     Short: "install", | ||||
|     Long: `deploy Charts`, | ||||
|     Args: cobra.MaximumNArgs(0), | ||||
|     RunE: func(cmd *cobra.Command, args []string) error { | ||||
|       return InstallCmd(context, version, modules) | ||||
|     }, | ||||
|     Example: "oc-deploy install --version 1.0 --context ex1", | ||||
|   } | ||||
| } | ||||
|  | ||||
| func cobraUninstallCmd() *cobra.Command{ | ||||
|   return &cobra.Command{ | ||||
|     Use:   "uninstall", | ||||
|     Short: "undeploy", | ||||
|     Long: `Undeploy`, | ||||
|     Args: cobra.MaximumNArgs(0), | ||||
|     RunE: func(cmd *cobra.Command, args []string) error { | ||||
|       return UninstallCmd(context) | ||||
|     }, | ||||
|     Example: "oc-deploy uninstall --context ex1", | ||||
|   } | ||||
| } | ||||
|  | ||||
|  | ||||
| func cobraGenerateCmd() *cobra.Command{ | ||||
|   return &cobra.Command{ | ||||
|     Use:   "generate", | ||||
|     Short: "generate", | ||||
|     Long: "Value", | ||||
|     Args: cobra.MaximumNArgs(0), | ||||
|     RunE: func(cmd *cobra.Command, args []string) error { | ||||
|         return GenerateCmd(context, version) | ||||
|     }, | ||||
|     Example: "oc-deploy generate --version 1.0 --context ex1", | ||||
|   } | ||||
| } | ||||
|  | ||||
| func Execute() { | ||||
|  | ||||
|     log.Log().Debug().Msg("Execute") | ||||
|  | ||||
|     var rootCmd = &cobra.Command{Use: "oc-deploy"} | ||||
|  | ||||
|     var cmdInstall = cobraInstallCmd() | ||||
|     var cmdUninstall = cobraUninstallCmd() | ||||
|     var cmdGenerate = cobraGenerateCmd() | ||||
|  | ||||
|     cmdInstall.Flags().StringVarP(&context, "context", "c", "opencloud", "Nom du context") | ||||
|     cmdInstall.Flags().StringVarP(&version, "version", "v", "latest", "Version") | ||||
|     cmdInstall.Flags().StringArrayVarP(&modules, "modules", "m", []string{}, "modules, ...") | ||||
|  | ||||
|     cmdUninstall.Flags().StringVarP(&context, "context", "c", "opencloud", "Nom du context") | ||||
|  | ||||
|     cmdGenerate.Flags().StringVarP(&context, "context", "c", "opencloud", "Nom du context") | ||||
|     cmdGenerate.Flags().StringVarP(&version, "version", "v", "latest", "Version") | ||||
|  | ||||
|     rootCmd.AddCommand(cmdInstall) | ||||
|     rootCmd.AddCommand(cmdUninstall) | ||||
|     rootCmd.AddCommand(cmdGenerate) | ||||
|  | ||||
|     cobra.CheckErr(rootCmd.Execute()) | ||||
|  | ||||
| } | ||||
							
								
								
									
										9
									
								
								src/cmd/args_test.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										9
									
								
								src/cmd/args_test.go
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,9 @@ | ||||
| package cmd | ||||
|  | ||||
| import ( | ||||
|     "testing" | ||||
| ) | ||||
|  | ||||
| func TestExecute(t *testing.T) { | ||||
|     Execute() | ||||
| } | ||||
							
								
								
									
										28
									
								
								src/cmd/generateCmd.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										28
									
								
								src/cmd/generateCmd.go
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,28 @@ | ||||
| package cmd | ||||
|  | ||||
| import ( | ||||
|  | ||||
|     log "oc-deploy/log_wrapper" | ||||
|  | ||||
|     "oc-deploy/versionOc" | ||||
|     "oc-deploy/generate" | ||||
| ) | ||||
|  | ||||
| func GenerateCmd(project string, version string) error { | ||||
|     log.Log().Info().Msg("Generate >> ") | ||||
|  | ||||
|     version, err := versionOc.GetFromFile(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) | ||||
|  | ||||
|     return err | ||||
| } | ||||
							
								
								
									
										51
									
								
								src/cmd/installCmd.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										51
									
								
								src/cmd/installCmd.go
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,51 @@ | ||||
| package cmd | ||||
|  | ||||
| import ( | ||||
|     "fmt" | ||||
|     log "oc-deploy/log_wrapper" | ||||
|  | ||||
|     "oc-deploy/install" | ||||
| ) | ||||
|  | ||||
| func InstallCmd(context string, version string, modules []string) error { | ||||
|     log.Log().Info().Msg("Install >> ") | ||||
|  | ||||
|     log.Log().Info().Msg("  << Contexte  : " + context) | ||||
|     if len(modules) > 0 { | ||||
|         log.Log().Info().Msg(fmt.Sprintf("  << Modules   : %s", modules)) | ||||
|     } | ||||
|  | ||||
|     workspace := fmt.Sprintf("workspace_%s", context) | ||||
|     obj := install.InstallClass{Workspace: workspace, Version: version} | ||||
|  | ||||
|     file, err := obj.NewInstall() | ||||
|     if err != nil { | ||||
|         log.Log().Fatal().Msg("  >> " + err.Error()) | ||||
|     } | ||||
|     log.Log().Info().Msg(fmt.Sprintf("  << Version   : %s", obj.Version)) | ||||
|     log.Log().Info().Msg(fmt.Sprintf("  >> Config    : %s", file)) | ||||
|  | ||||
|     err = obj.Tools() | ||||
|     if err != nil { | ||||
|         log.Log().Fatal().Msg("  >> " + err.Error()) | ||||
|     } | ||||
|  | ||||
|     obj.SetCommands() | ||||
|  | ||||
|     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.InstallCharts(modules) | ||||
|     if err != nil { | ||||
|         log.Log().Fatal().Msg("  >> " + err.Error()) | ||||
|     } | ||||
|  | ||||
|     return err | ||||
| } | ||||
							
								
								
									
										41
									
								
								src/cmd/installCmd_test.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										41
									
								
								src/cmd/installCmd_test.go
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,41 @@ | ||||
| package cmd | ||||
|  | ||||
| import ( | ||||
|     "bytes" | ||||
|     "github.com/spf13/cobra" | ||||
|  | ||||
|     "testing" | ||||
|  | ||||
|     "github.com/stretchr/testify/assert" | ||||
| ) | ||||
|  | ||||
| func TestInstallCommand(t *testing.T) { | ||||
|     cmd := cobraInstallCmd() | ||||
|  | ||||
|     inMock := false | ||||
|     cmd.RunE = func(cmd *cobra.Command, args []string) error { | ||||
|         inMock = true | ||||
|         return nil | ||||
|     } | ||||
|  | ||||
|     cmd.Execute() | ||||
|     assert.Truef(t, inMock, "TestInstallCommand") | ||||
| } | ||||
|  | ||||
| func TestInstallCommandErr(t *testing.T) { | ||||
|     cmd := cobraUninstallCmd() | ||||
|  | ||||
|     inMock := false | ||||
|     cmd.RunE = func(cmd *cobra.Command, args []string) error { | ||||
|         inMock = true | ||||
|         return nil | ||||
|     } | ||||
|  | ||||
|     cmd.SetArgs([]string{"bad"}) | ||||
|     b := bytes.NewBufferString("") | ||||
|     cmd.SetOut(b) | ||||
|  | ||||
|     err := cmd.Execute() | ||||
|     assert.Falsef(t, inMock, "TestInstallCommand args") | ||||
|     assert.NotNilf(t, err, "TestInstallCommand args") | ||||
| } | ||||
							
								
								
									
										45
									
								
								src/cmd/uninstallCmd.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										45
									
								
								src/cmd/uninstallCmd.go
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,45 @@ | ||||
| package cmd | ||||
|  | ||||
| import ( | ||||
|     "fmt" | ||||
|     // "strings" | ||||
|     // "github.com/spf13/cobra" | ||||
|  | ||||
|     log "oc-deploy/log_wrapper" | ||||
|  | ||||
|     // "oc-deploy/versionOc" | ||||
|     "oc-deploy/install" | ||||
| ) | ||||
|  | ||||
| func UninstallCmd(context string) error { | ||||
|     log.Log().Info().Msg("Uninstall >> ") | ||||
|  | ||||
|     log.Log().Info().Msg("  << Contexte  : " + context) | ||||
|  | ||||
|     workspace := fmt.Sprintf("workspace_%s", context) | ||||
|     obj := install.InstallClass{Workspace: workspace} | ||||
|  | ||||
|     file, err := obj.NewUninstall() | ||||
|     if err != nil { | ||||
|         log.Log().Fatal().Msg("  >> " + err.Error()) | ||||
|     } | ||||
|     log.Log().Info().Msg(fmt.Sprintf("  << Version   : %s", obj.Version)) | ||||
|     log.Log().Info().Msg(fmt.Sprintf("  >> Config    : %s", file)) | ||||
|  | ||||
|     err = obj.Tools() | ||||
|     if err != nil { | ||||
|         log.Log().Fatal().Msg("  >> " + err.Error()) | ||||
|     } | ||||
|  | ||||
|     err = obj.K8s(context) | ||||
|     if err != nil { | ||||
|         log.Log().Fatal().Msg("  >> " + err.Error()) | ||||
|     } | ||||
|  | ||||
|     err = obj.UninstallCharts() | ||||
|     if err != nil { | ||||
|         log.Log().Fatal().Msg("  >> " + err.Error()) | ||||
|     } | ||||
|  | ||||
|     return err | ||||
| } | ||||
							
								
								
									
										41
									
								
								src/cmd/uninstallCmd_test.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										41
									
								
								src/cmd/uninstallCmd_test.go
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,41 @@ | ||||
| package cmd | ||||
|  | ||||
| import ( | ||||
|     "bytes" | ||||
|     "github.com/spf13/cobra" | ||||
|  | ||||
|     "testing" | ||||
|  | ||||
|     "github.com/stretchr/testify/assert" | ||||
| ) | ||||
|  | ||||
| func TestUninstallCommand(t *testing.T) { | ||||
|     cmd := cobraUninstallCmd() | ||||
|  | ||||
|     inMock := false | ||||
|     cmd.RunE = func(cmd *cobra.Command, args []string) error { | ||||
|         inMock = true | ||||
|         return nil | ||||
|     } | ||||
|  | ||||
|     cmd.Execute() | ||||
|     assert.Truef(t, inMock, "TestUninstallCommand") | ||||
| } | ||||
|  | ||||
| func TestUninstallCommandErr(t *testing.T) { | ||||
|     cmd := cobraUninstallCmd() | ||||
|  | ||||
|     inMock := false | ||||
|     cmd.RunE = func(cmd *cobra.Command, args []string) error { | ||||
|         inMock = true | ||||
|         return nil | ||||
|     } | ||||
|  | ||||
|     cmd.SetArgs([]string{"bad"}) | ||||
|     b := bytes.NewBufferString("") | ||||
|     cmd.SetOut(b) | ||||
|  | ||||
|     err := cmd.Execute() | ||||
|     assert.Falsef(t, inMock, "TestUninstallCommand args") | ||||
|     assert.NotNilf(t, err, "TestUninstallCommand args") | ||||
| } | ||||
							
								
								
									
										22
									
								
								src/generate/generate.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										22
									
								
								src/generate/generate.go
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,22 @@ | ||||
| package generate | ||||
|  | ||||
| import ( | ||||
|     "fmt" | ||||
|     "oc-deploy/utils" | ||||
| ) | ||||
|  | ||||
| type GenerateClass struct { | ||||
|     Version string | ||||
|     Workspace 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 | ||||
| } | ||||
							
								
								
									
										25
									
								
								src/go.mod
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										25
									
								
								src/go.mod
									
									
									
									
									
										Normal file
									
								
							| @@ -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 | ||||
| ) | ||||
							
								
								
									
										162
									
								
								src/helm/chart.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										162
									
								
								src/helm/chart.go
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,162 @@ | ||||
| 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
									
								
							
							
						
						
									
										30
									
								
								src/helm/chart_test.go
									
									
									
									
									
										Normal 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") | ||||
| } | ||||
							
								
								
									
										22
									
								
								src/helm/helm.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										22
									
								
								src/helm/helm.go
									
									
									
									
									
										Normal 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...) | ||||
| 	} | ||||
| } | ||||
							
								
								
									
										17
									
								
								src/helm/helm_test.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										17
									
								
								src/helm/helm_test.go
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,17 @@ | ||||
| package helm | ||||
|  | ||||
|  | ||||
| import ( | ||||
|     "testing" | ||||
|  | ||||
|     "github.com/stretchr/testify/assert" | ||||
| ) | ||||
|  | ||||
| func TestHelm(t *testing.T) { | ||||
| 	cmd := HelmCommand{} | ||||
| 	cmd.New() | ||||
|  | ||||
|     assert.NotNilf(t, cmd.Exec, "TestHelm %s", "New") | ||||
|  | ||||
| 	cmd.Exec("pwd") | ||||
| } | ||||
							
								
								
									
										84
									
								
								src/helm/main_test.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										84
									
								
								src/helm/main_test.go
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,84 @@ | ||||
| package helm | ||||
|  | ||||
| import ( | ||||
|     "os" | ||||
|     "strings" | ||||
|     "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) | ||||
| } | ||||
|  | ||||
| // 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 | ||||
|     } | ||||
| } | ||||
							
								
								
									
										98
									
								
								src/helm/repo.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										98
									
								
								src/helm/repo.go
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,98 @@ | ||||
| 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 | ||||
| } | ||||
							
								
								
									
										72
									
								
								src/helm/repo_test.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										72
									
								
								src/helm/repo_test.go
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,72 @@ | ||||
| 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") | ||||
| } | ||||
							
								
								
									
										70
									
								
								src/helm/ressources.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										70
									
								
								src/helm/ressources.go
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,70 @@ | ||||
| package helm | ||||
|  | ||||
| import ( | ||||
| 	// "fmt" | ||||
|     "encoding/json" | ||||
| ) | ||||
| //// | ||||
|  | ||||
| type parseStatusInfoResourcesMetadata struct { | ||||
|     Name string  `json:"name"` | ||||
| } | ||||
|  | ||||
| // type parseStatusInfoResourcesPod struct { | ||||
| //     Api string  `json:"apiVersion"` | ||||
| // } | ||||
|  | ||||
| type parseStatusInfoResourcesStatefulSet struct { | ||||
|     Api string  `json:"apiVersion"` | ||||
|     Kind string  `json:"kind"` | ||||
|     Metadata parseStatusInfoResourcesMetadata  `json:"metadata"` | ||||
| } | ||||
|  | ||||
| type parseStatusInfoResourcesDeployment struct { | ||||
|     Api string  `json:"apiVersion"` | ||||
|     Kind string  `json:"kind"` | ||||
|     Metadata parseStatusInfoResourcesMetadata  `json:"metadata"` | ||||
| } | ||||
|  | ||||
| type parseStatusInfoResources struct { | ||||
|     // Pod []parseStatusInfoResourcesPod  `json:"v1/Pod(related)"` | ||||
|     StatefulSet []parseStatusInfoResourcesStatefulSet `json:"v1/StatefulSet"` | ||||
|     Deployment []parseStatusInfoResourcesDeployment `json:"v1/Deployment"` | ||||
| } | ||||
|  | ||||
| type parseStatusInfo struct { | ||||
|     Status string  `json:"status"` | ||||
|     Resources parseStatusInfoResources  `json:"Resources"` | ||||
| } | ||||
|  | ||||
|  | ||||
| type parseStatus struct { | ||||
|     Name string  `json:"name"` | ||||
|     Info parseStatusInfo  `json:"info"` | ||||
| } | ||||
|  | ||||
| func  (this HelmCommand) GetRessources(data HelmChart) (map[string]string, error) { | ||||
|  | ||||
| 	res := make(map[string]string) | ||||
|  | ||||
| 	status, err := this.Status(data) | ||||
| 	if err != nil { | ||||
| 		return res, err | ||||
| 	} | ||||
|  | ||||
| 	var objmap parseStatus | ||||
|  | ||||
| 	err = json.Unmarshal([]byte(status), &objmap) | ||||
| 	if err != nil { | ||||
| 		return res, err | ||||
| 	} | ||||
|  | ||||
| 	for _, ele := range objmap.Info.Resources.StatefulSet { | ||||
| 		res[ele.Metadata.Name] = ele.Kind | ||||
| 	} | ||||
| 	for _, ele := range objmap.Info.Resources.Deployment { | ||||
| 		res[ele.Metadata.Name] = ele.Kind | ||||
| 	} | ||||
|  | ||||
| 	return res, nil | ||||
| } | ||||
							
								
								
									
										24
									
								
								src/helm/ressources_test.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										24
									
								
								src/helm/ressources_test.go
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,24 @@ | ||||
| package helm | ||||
|  | ||||
| import ( | ||||
|     "os" | ||||
|     "path/filepath" | ||||
|  | ||||
|     "testing" | ||||
|  | ||||
|     "github.com/stretchr/testify/assert" | ||||
| ) | ||||
|  | ||||
| func TestHelmRessources(t *testing.T){ | ||||
|  | ||||
|     fileName := filepath.Join(TEST_SRC_DIR, "helm_status.json") | ||||
| 	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") | ||||
| } | ||||
							
								
								
									
										32
									
								
								src/helm/status.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										32
									
								
								src/helm/status.go
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,32 @@ | ||||
| package helm | ||||
|  | ||||
| import ( | ||||
|     "fmt" | ||||
|     "strings" | ||||
| 	"errors" | ||||
|  | ||||
|     log "oc-deploy/log_wrapper" | ||||
| ) | ||||
|  | ||||
| // 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, 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 "", errors.New(string(stdout)) | ||||
|     } | ||||
|  | ||||
|     return string(stdout), nil | ||||
| } | ||||
							
								
								
									
										20
									
								
								src/helm/version.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										20
									
								
								src/helm/version.go
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,20 @@ | ||||
| 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 | ||||
| } | ||||
							
								
								
									
										18
									
								
								src/helm/version_test.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										18
									
								
								src/helm/version_test.go
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,18 @@ | ||||
| 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") | ||||
| } | ||||
|  | ||||
							
								
								
									
										104
									
								
								src/install/common.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										104
									
								
								src/install/common.go
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,104 @@ | ||||
| package install | ||||
|  | ||||
| import ( | ||||
|     "fmt" | ||||
|     "errors" | ||||
|  | ||||
|     log "oc-deploy/log_wrapper" | ||||
|     "oc-deploy/tool" | ||||
|     "oc-deploy/kubectl" | ||||
|     "oc-deploy/helm" | ||||
| ) | ||||
|  | ||||
| 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) SetCommands() { | ||||
|     helm_bin, _ := this.getToolBin("helm") | ||||
|     this.commandHelm = helm.HelmCommand{Bin: helm_bin} | ||||
|     this.commandHelm.New() | ||||
|  | ||||
|     kubectl_bin, _ := this.getToolBin("kubectl") | ||||
|     this.commandKubectl = kubectl.KubectlCommand{Bin: kubectl_bin} | ||||
|     this.commandKubectl.New() | ||||
| } | ||||
|  | ||||
| // func (this *InstallClass) SetCommandsMock(mock helm.HelmCommandInterface) { | ||||
| // 	this.commandHelm = mock | ||||
| // } | ||||
|  | ||||
| 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) K8s(context string) (error) { | ||||
|  | ||||
|     kube := this.commandKubectl | ||||
|  | ||||
|     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 | ||||
| } | ||||
							
								
								
									
										150
									
								
								src/install/install.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										150
									
								
								src/install/install.go
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,150 @@ | ||||
| package install | ||||
|  | ||||
| import ( | ||||
|     "fmt" | ||||
|     "sync" | ||||
|     "os" | ||||
|  | ||||
|     log "oc-deploy/log_wrapper" | ||||
|     "oc-deploy/utils" | ||||
|     "oc-deploy/tool" | ||||
|     "oc-deploy/chart" | ||||
|     "oc-deploy/helm" | ||||
|     "oc-deploy/kubectl" | ||||
|     "oc-deploy/versionOc" | ||||
| ) | ||||
|  | ||||
| type InstallClass struct { | ||||
|     Version string | ||||
|     Workspace string | ||||
|  | ||||
|     tools []tool.ToolData | ||||
|     toolsBin map[string]string | ||||
|     charts []chart.ChartRepoData | ||||
|  | ||||
|     commandHelm helm.HelmCommand | ||||
|     commandKubectl kubectl.KubectlCommand | ||||
| } | ||||
|  | ||||
| func (this *InstallClass) NewInstall() (string, error) { | ||||
|  | ||||
|     // Extraction du fichier de version | ||||
|     dst := fmt.Sprintf("%s/oc.yml", this.Workspace) | ||||
|     log.Log().Debug().Msg(fmt.Sprintf("Check du fichier de version : %s", dst)) | ||||
|     if _, err := os.Stat(dst); err == nil { | ||||
|         log.Log().Debug().Msg("Existe déjà") | ||||
|         version, err := versionOc.GetFromFile(dst) | ||||
|         if err != nil { | ||||
|             return "", err | ||||
|         } | ||||
|         this.Version = version | ||||
|     } else { | ||||
|         log.Log().Debug().Msg("Téléchargement du fichier de version") | ||||
|         // version, fileversion, err := versionOc.Get(this.Version) | ||||
|         version, fileversion, err := versionOc.GetFromOnline(this.Version) | ||||
|         if err != nil { | ||||
|             return "", err | ||||
|         } | ||||
|         this.Version = version | ||||
|  | ||||
|         err = utils.CopyContentFile(fileversion, dst) | ||||
|         if err != nil { | ||||
|             return "", err | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     // Lecture du fichier de conf | ||||
|     var err error | ||||
|     this.tools, err = tool.FromConfigFile(dst) | ||||
|     if err != nil { | ||||
|         return dst, err | ||||
|     } | ||||
|     this.charts, _ = chart.FromConfigFile(dst) | ||||
|     if err != nil { | ||||
|         return dst, err | ||||
|     } | ||||
|  | ||||
|     bin_path, _ := this.getToolBin("helm") | ||||
|     fmt.Println("Install 67 bin_path", bin_path) | ||||
|  | ||||
|     return dst, nil | ||||
| } | ||||
|  | ||||
|  | ||||
| func (this *InstallClass) ChartRepo() (error) { | ||||
|  | ||||
|     for _, v := range this.charts { | ||||
|         if v.Repository.Name != "" { | ||||
|             log.Log().Info().Msg(fmt.Sprintf("  >> Helm Repo : %s", v.Repository.Name)) | ||||
|             repo := helm.HelmRepo{Name: v.Repository.Name, | ||||
|                                   Repository: v.Repository.Url, | ||||
|                                   ForceUpdate: v.Repository.ForceUpdate} | ||||
|             res, err := this.commandHelm.AddRepository(repo) | ||||
|             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) InstallCharts(modules []string) (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 { | ||||
|             if len(modules) == 0 || utils.StringInSlice(v1.Name, modules) { | ||||
|                 wg.Add(1) | ||||
|  | ||||
|                 go func() { | ||||
|                     defer wg.Done() | ||||
|                     this.installChart(v1) | ||||
|                 } () | ||||
|             } | ||||
|         } | ||||
|     } | ||||
|     wg.Wait() | ||||
|     return nil | ||||
| } | ||||
|  | ||||
| func (this *InstallClass) installChart(chart chart.ChartData) { | ||||
|  | ||||
|     log.Log().Info().Msg(fmt.Sprintf("  << Chart     : %s ", chart.Name)) | ||||
|  | ||||
|     data := helm.HelmChart{Name: chart.Name, | ||||
|                            Chart: chart.Chart, | ||||
|                            Url: chart.Url, | ||||
|                            Version: chart.Version, | ||||
|                            Workspace: this.Workspace, | ||||
|                            Opts: chart.Opts, | ||||
|                            Values: chart.Values, | ||||
|                            FileValues: chart.FileValues} | ||||
|  | ||||
|  | ||||
|     res, err := this.commandHelm.ChartInstall(data) | ||||
|     if err != nil { | ||||
|         log.Log().Error().Msg(fmt.Sprintf("  >>             %s %s (%s)", data.Name, "KO", err)) | ||||
|         return | ||||
|     } | ||||
|     log.Log().Info().Msg(fmt.Sprintf("  >>             %s (%s)", data.Name, res)) | ||||
|  | ||||
|     ressources, _ := this.commandHelm.GetRessources(data) | ||||
|  | ||||
|     for key, value := range ressources { | ||||
|         obj := kubectl.KubectlObject{Name: key, Kind: value} | ||||
|         err := this.commandKubectl.Wait(obj) | ||||
|         if err != nil { | ||||
|             log.Log().Error().Msg(fmt.Sprintf("  >>             %s/%s KO (%s)", chart.Name, key, err)) | ||||
|         } else { | ||||
|             log.Log().Info().Msg(fmt.Sprintf("  >>             %s/%s OK", chart.Name, key)) | ||||
|         } | ||||
|  | ||||
|     } | ||||
|      | ||||
| } | ||||
							
								
								
									
										81
									
								
								src/install/uninstall.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										81
									
								
								src/install/uninstall.go
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,81 @@ | ||||
| package install | ||||
|  | ||||
| import ( | ||||
|     "fmt" | ||||
|     "os" | ||||
|     "sync" | ||||
|  | ||||
|     log "oc-deploy/log_wrapper" | ||||
|     "oc-deploy/versionOc" | ||||
|     "oc-deploy/tool" | ||||
|     "oc-deploy/chart" | ||||
|     "oc-deploy/helm" | ||||
| ) | ||||
|  | ||||
| func (this *InstallClass) NewUninstall() (string, error) { | ||||
|    dst := fmt.Sprintf("%s/oc.yml", this.Workspace) | ||||
|  | ||||
|    if _, err := os.Stat(dst); err != nil { | ||||
|        return dst, err | ||||
|    } | ||||
|  | ||||
|    version, err := versionOc.GetFromFile(dst) | ||||
|    if err != nil { | ||||
|        return "", err | ||||
|    } | ||||
|  | ||||
|    this.Version = version | ||||
|  | ||||
|    // Lecture du fichier de conf | ||||
|    this.tools, err = tool.FromConfigFile(dst) | ||||
|    if err != nil { | ||||
|        return dst, err | ||||
|    } | ||||
|    this.charts, _ = chart.FromConfigFile(dst) | ||||
|    if err != nil { | ||||
|        return dst, err | ||||
|    } | ||||
|  | ||||
|    return dst, nil | ||||
| } | ||||
|  | ||||
| func (this *InstallClass) UninstallCharts() (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.uninstallChart(helm_bin, kubectl_bin, v1) | ||||
|             } () | ||||
|         } | ||||
|     } | ||||
|     wg.Wait() | ||||
|     return nil | ||||
| } | ||||
|  | ||||
| func (this *InstallClass) uninstallChart(helm_bin string, kubectl_bin string, chart chart.ChartData) { | ||||
|  | ||||
|     log.Log().Info().Msg(fmt.Sprintf("  << Chart     : %s ", chart.Name)) | ||||
|  | ||||
|  | ||||
|     helm_cmd := helm.HelmCommand{Bin: helm_bin} | ||||
|     helm_cmd.New() | ||||
|  | ||||
|     data := helm.HelmChart{Name: chart.Name} | ||||
|  | ||||
|     // helmchart := helm.HelmChart{Bin: helm_bin, | ||||
|     //                             Name: chart.Name} | ||||
|  | ||||
|     res, err := helm_cmd.ChartUninstall(data) | ||||
|     if err != nil { | ||||
|         log.Log().Error().Msg(fmt.Sprintf("  >>              %s %s (%s)", data.Name, "KO", err)) | ||||
|         return | ||||
|     } | ||||
|     log.Log().Info().Msg(fmt.Sprintf("  >>             %s (%s)", data.Name, res)) | ||||
| } | ||||
							
								
								
									
										130
									
								
								src/kubectl/context.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										130
									
								
								src/kubectl/context.go
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,130 @@ | ||||
| package kubectl | ||||
|  | ||||
| import ( | ||||
|     "fmt" | ||||
|     "strings" | ||||
|     "errors" | ||||
|     "encoding/json" | ||||
|  | ||||
|     log "oc-deploy/log_wrapper" | ||||
| ) | ||||
|  | ||||
|  | ||||
| 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 KubectlCommand) GetCurrentContext() (string, error) { | ||||
| 	bin := this.Bin | ||||
|  | ||||
| 	msg := fmt.Sprintf("%s config current-context", bin) | ||||
| 	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 | ||||
| } | ||||
|  | ||||
| // currentContext, currentNamespace, currentServer | ||||
| func (this KubectlCommand) GetContext() (string, string, string, error) { | ||||
|  | ||||
| 	bin := this.Bin | ||||
|  | ||||
| 	msg := fmt.Sprintf("%s config view -o json", 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 "", "", "", errors.New(string(stdout)) | ||||
| 	} | ||||
|  | ||||
|     var objmap kubeConfig | ||||
|  | ||||
|     err = json.Unmarshal(stdout, &objmap) | ||||
|     if err != nil { | ||||
|         return "", "", "", err | ||||
|     } | ||||
|     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 KubectlCommand) UseContext(newContext string) (error) { | ||||
|  | ||||
| 	bin := this.Bin | ||||
|  | ||||
| 	msg := fmt.Sprintf("%s config use-context %s", bin, newContext) | ||||
| 	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 errors.New(string(stdout)) | ||||
|     } | ||||
|  | ||||
|     return nil | ||||
| } | ||||
|  | ||||
| func (this KubectlCommand) Check() (error) { | ||||
| 	bin := this.Bin | ||||
|  | ||||
| 	msg := fmt.Sprintf("%s cluster-info", 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 { | ||||
|         log.Log().Debug().Msg(string(stdout)) | ||||
|         return errors.New("Kube non disponible") | ||||
|     } | ||||
|  | ||||
|     return nil | ||||
| } | ||||
							
								
								
									
										86
									
								
								src/kubectl/context_test.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										86
									
								
								src/kubectl/context_test.go
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,86 @@ | ||||
| package kubectl | ||||
|  | ||||
|  | ||||
| import ( | ||||
| 	"os" | ||||
| 	"path/filepath" | ||||
| 	"errors" | ||||
|  | ||||
|     "testing" | ||||
|  | ||||
|     "github.com/stretchr/testify/assert" | ||||
| ) | ||||
|  | ||||
| var MOCK_ENABLE = true | ||||
|  | ||||
| func TestKubectCurrentContext(t *testing.T) { | ||||
|  | ||||
| 	cmd := getCmdKubectl(MOCK_ENABLE, "minikube") | ||||
|  | ||||
|     res, err := cmd.GetCurrentContext() | ||||
|  | ||||
|     assert.Nilf(t, err, "error message %s", err) | ||||
|     assert.Equal(t, "minikube", res, "TestKubectCurrentContext error") | ||||
| } | ||||
|  | ||||
| func TestKubectContext(t *testing.T) { | ||||
|  | ||||
|     fileName := filepath.Join(TEST_SRC_DIR, "context.json") | ||||
| 	cmd_json, _ := os.ReadFile(fileName) | ||||
|  | ||||
| 	cmd := getCmdKubectl(MOCK_ENABLE, string(cmd_json)) | ||||
|  | ||||
|     currentContext, currentNamespace, currentServer, err := cmd.GetContext() | ||||
|  | ||||
|     assert.Nilf(t, err, "error message %s", err) | ||||
|     assert.Equal(t, "minikube", currentContext, "TestKubectContext error") | ||||
|     assert.Equal(t, "default", currentNamespace, "TestKubectContext error") | ||||
|     assert.Equal(t, "https://127.0.0.1:38039", currentServer, "TestKubectContext error") | ||||
| } | ||||
|  | ||||
| func TestKubectUseContext(t *testing.T) { | ||||
|  | ||||
| 	cmd := getCmdKubectl(MOCK_ENABLE, `Switched to context "minikube".`) | ||||
|  | ||||
|     err := cmd.UseContext("minikube") | ||||
|  | ||||
|     assert.Nilf(t, err, "error message %s", err) | ||||
| } | ||||
|  | ||||
| func TestKubectUseContextErr(t *testing.T) { | ||||
|  | ||||
| 	error := errors.New("exit 1") | ||||
| 	cmd := getCmdKubectlError(MOCK_ENABLE, `error: no context exists with the name: "minikube2"`, error) | ||||
|  | ||||
|     err := cmd.UseContext("minikube2") | ||||
|  | ||||
|     assert.NotNilf(t, err, "error message %s", err) | ||||
| } | ||||
|  | ||||
| func TestKubectCheck(t *testing.T) { | ||||
|  | ||||
| 	cmd_txt := ` | ||||
| 	Kubernetes control plane is running at https://127.0.0.1:38039 | ||||
| CoreDNS is running at https://127.0.0.1:38039/api/v1/namespaces/kube-system/services/kube-dns:dns/proxy | ||||
|  | ||||
| To further debug and diagnose cluster problems, use 'kubectl cluster-info dump'. | ||||
| ` | ||||
| 	// error := errors.New("exit 1") | ||||
| 	cmd := getCmdKubectl(MOCK_ENABLE, cmd_txt) | ||||
|  | ||||
|     err := cmd.Check() | ||||
|  | ||||
|     assert.Nilf(t, err, "error message %s", err) | ||||
| } | ||||
|  | ||||
| func TestKubectCheckErr(t *testing.T) { | ||||
|  | ||||
| 	cmd_txt := "" | ||||
|  | ||||
| 	error := errors.New("exit 1") | ||||
| 	cmd := getCmdKubectlError(MOCK_ENABLE, cmd_txt, error) | ||||
|  | ||||
|     err := cmd.Check() | ||||
|  | ||||
|     assert.NotNilf(t, err, "error message %s", "TestKubectCheckErr") | ||||
| } | ||||
							
								
								
									
										40
									
								
								src/kubectl/deployment.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										40
									
								
								src/kubectl/deployment.go
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,40 @@ | ||||
| package kubectl | ||||
|  | ||||
| import ( | ||||
| 	"fmt" | ||||
| 	"strings" | ||||
| 	"errors" | ||||
|     "encoding/json" | ||||
|  | ||||
|     log "oc-deploy/log_wrapper" | ||||
| ) | ||||
|  | ||||
| func (this KubectlCommand) getDeployment(data KubectlObject) (map[string]any, error) { | ||||
| 	bin := this.Bin | ||||
|  | ||||
| 	msg := fmt.Sprintf("%s get deployment %s -o json", bin, data.Name) | ||||
| 	log.Log().Debug().Msg(msg) | ||||
|  | ||||
| 	m := make(map[string]any) | ||||
|  | ||||
| 	cmd_args := strings.Split(msg, " ") | ||||
| 	cmd := this.Exec(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"] = data.Name | ||||
| 	m["kind"] = kind | ||||
| 	m["replicas"] = status.Replicas | ||||
| 	m["UnavailableReplicas"] = status.UnavailableReplicas | ||||
|  | ||||
|     return m, nil | ||||
| } | ||||
							
								
								
									
										29
									
								
								src/kubectl/deployment_test.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										29
									
								
								src/kubectl/deployment_test.go
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,29 @@ | ||||
| package kubectl | ||||
|  | ||||
| import ( | ||||
| 	"os" | ||||
| 	"path/filepath" | ||||
|  | ||||
|     "testing" | ||||
|  | ||||
|     "github.com/stretchr/testify/assert" | ||||
| ) | ||||
|  | ||||
| func TestKubectDeployment(t *testing.T) { | ||||
|  | ||||
|     fileName := filepath.Join(TEST_SRC_DIR, "deployment.json") | ||||
| 	cmd_json, _ := os.ReadFile(fileName) | ||||
|  | ||||
| 	cmd := getCmdKubectl(true, string(cmd_json)) | ||||
|  | ||||
|  | ||||
| 	data := KubectlObject{Name: "dep1", Kind: "Deployment"} | ||||
|  | ||||
|     res, err := cmd.getDeployment(data) | ||||
|  | ||||
| 	// map[string]interface {}(map[string]interface {}{"UnavailableReplicas":0, "kind":"Deployment", "name":"dep1", "replicas":1}) | ||||
|     assert.Nilf(t, err, "error message %s", err) | ||||
|     assert.Equal(t, "Deployment", res["kind"], "TestKubectDeployment error") | ||||
|     assert.Equal(t, 1, res["replicas"], "TestKubectDeployment error") | ||||
| } | ||||
|  | ||||
							
								
								
									
										22
									
								
								src/kubectl/kubectl.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										22
									
								
								src/kubectl/kubectl.go
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,22 @@ | ||||
| package kubectl | ||||
|  | ||||
| import ( | ||||
|     "os/exec" | ||||
| ) | ||||
|  | ||||
| type KubectlCommand struct { | ||||
|     Bin string | ||||
| 	Exec func(string,...string) commandExecutor | ||||
| } | ||||
|  | ||||
| //// | ||||
| type commandExecutor interface { | ||||
|     Output() ([]byte, error) | ||||
|     CombinedOutput() ([]byte, error) | ||||
| } | ||||
|  | ||||
| func (this *KubectlCommand) New() { | ||||
| 	this.Exec = func(name string, arg ...string) commandExecutor { | ||||
| 		return exec.Command(name, arg...) | ||||
| 	} | ||||
| } | ||||
							
								
								
									
										17
									
								
								src/kubectl/kubectl_test.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										17
									
								
								src/kubectl/kubectl_test.go
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,17 @@ | ||||
| package kubectl | ||||
|  | ||||
|  | ||||
| import ( | ||||
|     "testing" | ||||
|  | ||||
|     "github.com/stretchr/testify/assert" | ||||
| ) | ||||
|  | ||||
| func TestKubectl(t *testing.T) { | ||||
| 	cmd := KubectlCommand{} | ||||
| 	cmd.New() | ||||
|  | ||||
|     assert.NotNilf(t, cmd.Exec, "TestKubectl %s", "New") | ||||
|  | ||||
| 	cmd.Exec("pwd") | ||||
| } | ||||
							
								
								
									
										104
									
								
								src/kubectl/main_test.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										104
									
								
								src/kubectl/main_test.go
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,104 @@ | ||||
| package kubectl | ||||
|  | ||||
| import ( | ||||
|     "os" | ||||
|     "strings" | ||||
|     "testing" | ||||
|     "path/filepath" | ||||
| ) | ||||
|  | ||||
| var TEST_DEST_DIR = "../wrk_kubectl" | ||||
| var TEST_SRC_DIR = filepath.Join("../../test", "kubectl") | ||||
| 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) | ||||
| } | ||||
|  | ||||
| // Mock | ||||
|  | ||||
| type MockCommandExecutor struct { | ||||
|     // Used to stub the return of the Output method | ||||
|     // Could add other properties depending on testing needs | ||||
|     output string | ||||
|     err error | ||||
| } | ||||
|  | ||||
| // Implements the commandExecutor interface | ||||
| func (m *MockCommandExecutor) Output() ([]byte, error) { | ||||
|     return []byte(m.output), m.err | ||||
| } | ||||
|  | ||||
| func (m *MockCommandExecutor) CombinedOutput() ([]byte, error) { | ||||
|     return []byte(m.output), m.err | ||||
| } | ||||
|  | ||||
| // | ||||
|  | ||||
| func getCmdKubectl(mock bool, output string) (KubectlCommand) { | ||||
|     if mock == true { | ||||
|  | ||||
|         mock := func(name string, args ...string) commandExecutor { | ||||
|             return &MockCommandExecutor{output: output} | ||||
|         } | ||||
|      | ||||
|         cmd := KubectlCommand{Bin: "mock", Exec: mock} | ||||
|         return cmd | ||||
|     } else { | ||||
|         bin := filepath.Join(TEST_BIN_DIR, "kubectl") | ||||
|         os.Chmod(bin, 0700) | ||||
|  | ||||
|         cmd := KubectlCommand{Bin: bin} | ||||
|         cmd.New() | ||||
|         return cmd | ||||
|     } | ||||
| } | ||||
|  | ||||
| func getCmdsKubectl(mock bool, outputs map[string]string) (KubectlCommand) { | ||||
|     if mock == true { | ||||
|  | ||||
|         mock := func(name string, args ...string) commandExecutor { | ||||
|             cmd := strings.TrimSuffix(strings.Join(args," "), " ") | ||||
|             output := outputs[cmd] | ||||
|             return &MockCommandExecutor{output: output} | ||||
|         } | ||||
|      | ||||
|         cmd := KubectlCommand{Bin: "mock", Exec: mock} | ||||
|         return cmd | ||||
|     } else { | ||||
|         bin := filepath.Join(TEST_BIN_DIR, "kubectl") | ||||
|         os.Chmod(bin, 0700) | ||||
|  | ||||
|         cmd := KubectlCommand{Bin: bin} | ||||
|         cmd.New() | ||||
|         return cmd | ||||
|     } | ||||
| } | ||||
|  | ||||
| func getCmdKubectlError(mock bool, output string, err error) (KubectlCommand) { | ||||
|     if mock == true { | ||||
|  | ||||
|         mock := func(name string, args ...string) commandExecutor { | ||||
|             return &MockCommandExecutor{output: output, err: err} | ||||
|         } | ||||
|      | ||||
|         cmd := KubectlCommand{Bin: "mock", Exec: mock} | ||||
|         return cmd | ||||
|     } else { | ||||
|         bin := filepath.Join(TEST_BIN_DIR, "kubectl") | ||||
|         os.Chmod(bin, 0700) | ||||
|  | ||||
|         cmd := KubectlCommand{Bin: bin} | ||||
|         cmd.New() | ||||
|         return cmd | ||||
|     } | ||||
| } | ||||
							
								
								
									
										56
									
								
								src/kubectl/object.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										56
									
								
								src/kubectl/object.go
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,56 @@ | ||||
| package kubectl | ||||
|  | ||||
| import ( | ||||
|     "fmt" | ||||
|     "time" | ||||
|     "errors" | ||||
|  | ||||
|     log "oc-deploy/log_wrapper" | ||||
| ) | ||||
|  | ||||
|  | ||||
| type KubectlObject struct { | ||||
|     Name string | ||||
|     Kind 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 KubectlCommand) Get(data KubectlObject) (map[string]any, error) { | ||||
|     if data.Kind == "Deployment" {return this.getDeployment(data)} | ||||
|     if data.Kind == "StatefulSet" {return this.getStatefulSet(data)} | ||||
|     return make(map[string]any), fmt.Errorf("Kind %s inconnu", data.Kind) | ||||
| } | ||||
|  | ||||
| func (this KubectlCommand) Wait(data KubectlObject) (error) { | ||||
|  | ||||
|     boucle := 10 | ||||
|     sleep := 10000 * time.Millisecond | ||||
|  | ||||
|     for _ = range boucle { | ||||
|  | ||||
|         log.Log().Debug().Msg(fmt.Sprintf("Check Deployement %s", data.Name)) | ||||
|  | ||||
|         m, err := this.Get(data) | ||||
|         if err != nil { | ||||
|             return err | ||||
|         } | ||||
|         ko := m["UnavailableReplicas"].(int) | ||||
|         if ko == 0 { | ||||
|             return nil | ||||
|         } | ||||
|  | ||||
|         log.Log().Info().Msg(fmt.Sprintf("  >>             %s (Unavailable : %d)...", data.Name, ko)) | ||||
|         time.Sleep(sleep) | ||||
|  | ||||
|     } | ||||
|     return errors.New("Temps d'attente dépassé") | ||||
| } | ||||
							
								
								
									
										28
									
								
								src/kubectl/stateful_test.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										28
									
								
								src/kubectl/stateful_test.go
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,28 @@ | ||||
| package kubectl | ||||
|  | ||||
| import ( | ||||
| 	"os" | ||||
| 	"path/filepath" | ||||
|  | ||||
|     "testing" | ||||
|  | ||||
|     "github.com/stretchr/testify/assert" | ||||
| ) | ||||
|  | ||||
| func TestKubectStatefulset(t *testing.T) { | ||||
|  | ||||
|     fileName := filepath.Join(TEST_SRC_DIR, "statefulset.json") | ||||
| 	cmd_json, _ := os.ReadFile(fileName) | ||||
|  | ||||
| 	cmd := getCmdKubectl(true, string(cmd_json)) | ||||
|  | ||||
|  | ||||
| 	data := KubectlObject{Name: "dep1", Kind: "Statefulset"} | ||||
|  | ||||
|     res, err := cmd.getDeployment(data) | ||||
|  | ||||
| 	// map[string]interface {}(map[string]interface {}{"UnavailableReplicas":0, "kind":"StatefulSet", "name":"dep1", "replicas":1}) | ||||
|     assert.Nilf(t, err, "error message %s", err) | ||||
|     assert.Equal(t, "StatefulSet", res["kind"], "TestKubectDeployment error") | ||||
|     assert.Equal(t, 1, res["replicas"], "TestKubectDeployment error") | ||||
| } | ||||
							
								
								
									
										43
									
								
								src/kubectl/statefulset.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										43
									
								
								src/kubectl/statefulset.go
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,43 @@ | ||||
| package kubectl | ||||
|  | ||||
| import ( | ||||
| 	"fmt" | ||||
| 	"strings" | ||||
| 	"errors" | ||||
|     "encoding/json" | ||||
|  | ||||
|     log "oc-deploy/log_wrapper" | ||||
| ) | ||||
|  | ||||
| func (this KubectlCommand) getStatefulSet(data KubectlObject) (map[string]any, error) { | ||||
|  | ||||
| 	bin := this.Bin | ||||
| 	name := data.Name | ||||
|  | ||||
| 	msg := fmt.Sprintf("%s get statefulset %s -o json", bin, name) | ||||
| 	log.Log().Debug().Msg(msg) | ||||
|  | ||||
| 	m := make(map[string]any) | ||||
|  | ||||
| 	cmd_args := strings.Split(msg, " ") | ||||
| 	cmd := this.Exec(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 | ||||
| } | ||||
|  | ||||
							
								
								
									
										29
									
								
								src/kubectl/version.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										29
									
								
								src/kubectl/version.go
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,29 @@ | ||||
| package kubectl | ||||
|  | ||||
| import ( | ||||
|     "encoding/json" | ||||
| ) | ||||
|  | ||||
| type toolClientVersion struct { | ||||
|     GitVersion string `json:"gitVersion"` | ||||
| } | ||||
|  | ||||
| type toolVersion struct { | ||||
|     ClientVersion toolClientVersion `json:"clientVersion"` | ||||
| } | ||||
|  | ||||
| func (this KubectlCommand) GetVersion() (string, error) { | ||||
|  | ||||
|     cmd := this.Exec(this.Bin, "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 | ||||
| } | ||||
							
								
								
									
										33
									
								
								src/kubectl/version_test.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										33
									
								
								src/kubectl/version_test.go
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,33 @@ | ||||
| package kubectl | ||||
|  | ||||
| import ( | ||||
|     "testing" | ||||
|  | ||||
|     "github.com/stretchr/testify/assert" | ||||
| ) | ||||
|  | ||||
| func TestKubectlVersion(t *testing.T) { | ||||
|  | ||||
|     cmd_json := ` | ||||
|         { | ||||
|         "clientVersion": { | ||||
|             "major": "1", | ||||
|             "minor": "30", | ||||
|             "gitVersion": "v1.30.3", | ||||
|             "gitCommit": "6fc0a69044f1ac4c13841ec4391224a2df241460", | ||||
|             "gitTreeState": "clean", | ||||
|             "buildDate": "2024-07-16T23:54:40Z", | ||||
|             "goVersion": "go1.22.5", | ||||
|             "compiler": "gc", | ||||
|             "platform": "linux/amd64" | ||||
|         }, | ||||
|         "kustomizeVersion": "v5.0.4-0.20230601165947-6ce0bf390ce3" | ||||
|         }` | ||||
| 	cmd := getCmdKubectl(true, cmd_json) | ||||
|  | ||||
|     version, err := cmd.GetVersion() | ||||
|  | ||||
|     assert.Nilf(t, err, "error message %s", err) | ||||
|     assert.Equal(t, "v1.30.3", version, "TestkubectlVersion error") | ||||
| } | ||||
|  | ||||
							
								
								
									
										50
									
								
								src/log_wrapper/log_wrapper.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										50
									
								
								src/log_wrapper/log_wrapper.go
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,50 @@ | ||||
| package log_wrapper | ||||
|  | ||||
| // https://github.com/rs/zerolog/issues/150 | ||||
|  | ||||
| import ( | ||||
|     "os" | ||||
|     "path/filepath" | ||||
|     "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(filename string) bool { | ||||
|  | ||||
|     ficlog := filepath.Join(filename + ".log") | ||||
|     fAll, _ := os.OpenFile(ficlog, 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 | ||||
| } | ||||
							
								
								
									
										21
									
								
								src/log_wrapper/log_wrapper_test.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										21
									
								
								src/log_wrapper/log_wrapper_test.go
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,21 @@ | ||||
| package log_wrapper | ||||
|  | ||||
| import ( | ||||
| 	// "os" | ||||
| 	"path/filepath" | ||||
| 	// "errors" | ||||
|  | ||||
|     "testing" | ||||
|  | ||||
|     "github.com/stretchr/testify/assert" | ||||
| ) | ||||
|  | ||||
| func TestLogWrapper(t *testing.T) { | ||||
| 	ficlog := filepath.Join(TEST_DEST_DIR, "test") | ||||
| 	InitLog(ficlog) | ||||
|  | ||||
| 	Log().Info().Msg("KKK") | ||||
| 	Log().Error().Msg("KKK") | ||||
|  | ||||
| 	assert.FileExists(t, ficlog + ".log", "TestLogWrapper") | ||||
| } | ||||
							
								
								
									
										21
									
								
								src/log_wrapper/main_test.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										21
									
								
								src/log_wrapper/main_test.go
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,21 @@ | ||||
| package log_wrapper | ||||
|  | ||||
| import ( | ||||
|     "os" | ||||
|     "testing" | ||||
| ) | ||||
|  | ||||
| var TEST_DEST_DIR = "../wrk_log" | ||||
|  | ||||
| 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) | ||||
| } | ||||
							
								
								
									
										19
									
								
								src/main.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										19
									
								
								src/main.go
									
									
									
									
									
										Normal file
									
								
							| @@ -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") | ||||
|  | ||||
| } | ||||
							
								
								
									
										9
									
								
								src/occonst/main_test.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										9
									
								
								src/occonst/main_test.go
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,9 @@ | ||||
| package occonst | ||||
|  | ||||
| import ( | ||||
| 	"testing" | ||||
| ) | ||||
|  | ||||
|  | ||||
| func TestMain(m *testing.M) { | ||||
| } | ||||
							
								
								
									
										6
									
								
								src/occonst/variables.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										6
									
								
								src/occonst/variables.go
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,6 @@ | ||||
| package occonst | ||||
|  | ||||
| var ONLINE_URL = "https://cloud.o-forge.io" | ||||
| var ONLINE_VERSION = "core/oc-deploy" | ||||
|  | ||||
| var OFFLINE_DIR = "../../offline" | ||||
							
								
								
									
										21
									
								
								src/tool/conf.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										21
									
								
								src/tool/conf.go
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,21 @@ | ||||
| package tool | ||||
|  | ||||
| import ( | ||||
|     "os" | ||||
|     "gopkg.in/yaml.v2" | ||||
| ) | ||||
|  | ||||
| type toolsData struct { | ||||
|     Tools []ToolData `yaml:"tools"` | ||||
| } | ||||
|  | ||||
| // Lecture de la liste des outils | ||||
| func FromConfigFile(filename string) ([]ToolData, error) { | ||||
|     yamlFile, _ := os.ReadFile(filename) | ||||
|     var data toolsData | ||||
|     err := yaml.Unmarshal(yamlFile, &data) | ||||
|     if err != nil { | ||||
|         return data.Tools, nil | ||||
|     } | ||||
|     return data.Tools, nil | ||||
| } | ||||
							
								
								
									
										18
									
								
								src/tool/conf_test.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										18
									
								
								src/tool/conf_test.go
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,18 @@ | ||||
| package tool | ||||
|  | ||||
| import ( | ||||
|     "path/filepath" | ||||
|  | ||||
|     "testing" | ||||
|  | ||||
|     "github.com/stretchr/testify/assert" | ||||
| ) | ||||
|  | ||||
| func TestToolConf(t *testing.T) { | ||||
|  | ||||
|     src := filepath.Join(TEST_SRC_DIR, "oc.yml") | ||||
|  | ||||
|     data, err := FromConfigFile(src) | ||||
|     assert.Equal(t, "kubectl", data[0].Name, "TestToolConf error") | ||||
|     assert.Nilf(t, err, "error message %s", src) | ||||
| } | ||||
							
								
								
									
										57
									
								
								src/tool/helm.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										57
									
								
								src/tool/helm.go
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,57 @@ | ||||
| package tool | ||||
|  | ||||
| import ( | ||||
|    "fmt" | ||||
|    "os" | ||||
|  | ||||
|    "oc-deploy/utils" | ||||
|    "oc-deploy/helm" | ||||
| ) | ||||
|  | ||||
| type HelmInstall struct { | ||||
|     obj ToolData | ||||
|     tmp string | ||||
| } | ||||
|  | ||||
| func (this HelmInstall) Get() (ToolData) { | ||||
|     return this.obj | ||||
| } | ||||
|  | ||||
| func (this HelmInstall) Download() (error) { | ||||
|  | ||||
|     bin_dir := this.obj.Bin | ||||
|     err2 := os.MkdirAll(bin_dir, os.ModePerm) | ||||
|     if err2 != nil { | ||||
|         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) | ||||
|     if err1 != nil { | ||||
|         return err1 | ||||
|     } | ||||
|  | ||||
|     os.Remove(tmp_file)  | ||||
|  | ||||
|     bin_file := fmt.Sprintf("%s/%s", bin_dir, this.obj.Name) | ||||
|  | ||||
|     errChmod := os.Chmod(bin_file, 0755) | ||||
|     if errChmod != nil {return errChmod} | ||||
|  | ||||
|     return nil | ||||
| } | ||||
|  | ||||
| /////////////// | ||||
| func (this HelmInstall) Version(path string) (string, error) { | ||||
|     cmd := helm.HelmCommand{Bin: path} | ||||
|     cmd.New() | ||||
|     return cmd.GetVersion() | ||||
| } | ||||
							
								
								
									
										62
									
								
								src/tool/helm_test.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										62
									
								
								src/tool/helm_test.go
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,62 @@ | ||||
| package tool | ||||
|  | ||||
| import ( | ||||
|     "os" | ||||
|     "path/filepath" | ||||
|  | ||||
|     "testing" | ||||
|  | ||||
|     "github.com/stretchr/testify/assert" | ||||
|     "github.com/jarcoal/httpmock" | ||||
| ) | ||||
|  | ||||
| func TestToolHelm(t *testing.T) { | ||||
|  | ||||
|     httpmock.Activate() | ||||
|     defer httpmock.DeactivateAndReset() | ||||
|  | ||||
|     data := ToolData{Bin: TEST_DEST_DIR,  | ||||
|                      Name: "helm", | ||||
|                      Version: "1.0", | ||||
|                      Url: "http://test/%s"} | ||||
|  | ||||
|     fileName := filepath.Join(TEST_SRC_DIR, "helm.tgz") | ||||
|     httpRes, _ := os.ReadFile(fileName) | ||||
|                   | ||||
|     httpmock.RegisterResponder("GET", "http://test/1.0", | ||||
|       httpmock.NewBytesResponder(200, httpRes)) | ||||
|                 | ||||
|     install := HelmInstall{obj: data, tmp: TEST_DEST_DIR} | ||||
|  | ||||
|     data2 := install.Get() | ||||
|     assert.Equal(t, data.Name, data2.Name, "TestToolHelm error") | ||||
|     assert.Equal(t, data.Version, data2.Version, "TestToolHelm error") | ||||
|  | ||||
|     err := install.Download() | ||||
|     assert.Nilf(t, err, "error message %s", "Download") | ||||
|  | ||||
|     dest := filepath.Join(TEST_DEST_DIR, "helm") | ||||
|     assert.FileExists(t, dest, "TestToolHelm Download error") | ||||
|  | ||||
|     version, _ := install.Version(dest) | ||||
|     assert.Equal(t, "1.0", version, "TestToolHelm error") | ||||
|  | ||||
| } | ||||
|  | ||||
|  | ||||
| func TestToolHelmErr(t *testing.T) { | ||||
|  | ||||
|     data := ToolData{Bin: TEST_DEST_DIR,  | ||||
|                      Name: "test", | ||||
|                      Version: "1.0", | ||||
|                      Url: "http://test/%s"} | ||||
|  | ||||
|     install := HelmInstall{obj: data} | ||||
|  | ||||
|     data2 := install.Get() | ||||
|     assert.Equal(t,  data.Name, data2.Name, "TestToolHelm error") | ||||
|  | ||||
|     err := install.Download() | ||||
|  | ||||
|     assert.NotNilf(t, err, "error message %s", "Download") | ||||
| } | ||||
							
								
								
									
										43
									
								
								src/tool/kubectl.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										43
									
								
								src/tool/kubectl.go
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,43 @@ | ||||
| package tool | ||||
|  | ||||
| import ( | ||||
|    "fmt" | ||||
|    "os" | ||||
|    "path/filepath" | ||||
|  | ||||
|    log "oc-deploy/log_wrapper" | ||||
|    "oc-deploy/utils" | ||||
|    "oc-deploy/kubectl" | ||||
| ) | ||||
|  | ||||
| type KubectlInstall struct { | ||||
|     obj ToolData | ||||
| } | ||||
|  | ||||
| func (this KubectlInstall) Get() (ToolData) { | ||||
|     return this.obj | ||||
| } | ||||
|  | ||||
| func (this KubectlInstall) 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 KubectlInstall) Version(path string) (string, error) { | ||||
|     cmd := kubectl.KubectlCommand{Bin: path} | ||||
|     cmd.New() | ||||
|     return cmd.GetVersion() | ||||
| } | ||||
							
								
								
									
										79
									
								
								src/tool/kubectl_test.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										79
									
								
								src/tool/kubectl_test.go
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,79 @@ | ||||
| package tool | ||||
|  | ||||
| import ( | ||||
|     "fmt" | ||||
|     "path/filepath" | ||||
|     "testing" | ||||
|  | ||||
|     "github.com/stretchr/testify/assert" | ||||
|     "github.com/jarcoal/httpmock" | ||||
| ) | ||||
|  | ||||
| func TestToolKubectl(t *testing.T) { | ||||
|  | ||||
|     httpmock.Activate() | ||||
|     defer httpmock.DeactivateAndReset() | ||||
|  | ||||
|     data := ToolData{Bin: TEST_DEST_DIR,  | ||||
|                      Name: "kubectl", | ||||
|                      Version: "1.0", | ||||
|                      Url: "http://test/%s"} | ||||
|  | ||||
|     binContent := `#!/bin/sh | ||||
| cat <<EOF | ||||
| { | ||||
|   "clientVersion": { | ||||
|     "major": "1", | ||||
|     "minor": "30", | ||||
|     "gitVersion": "v1.30.3", | ||||
|     "gitCommit": "6fc0a69044f1ac4c13841ec4391224a2df241460", | ||||
|     "gitTreeState": "clean", | ||||
|     "buildDate": "2024-07-16T23:54:40Z", | ||||
|     "goVersion": "go1.22.5", | ||||
|     "compiler": "gc", | ||||
|     "platform": "linux/amd64" | ||||
|   }, | ||||
|   "kustomizeVersion": "v5.0.4-0.20230601165947-6ce0bf390ce3" | ||||
| } | ||||
| EOF | ||||
| ` | ||||
|                   | ||||
|     httpmock.RegisterResponder("GET", "http://test/1.0", | ||||
|       httpmock.NewStringResponder(200, binContent)) | ||||
|                 | ||||
|     install := KubectlInstall{obj: data} | ||||
|  | ||||
|     data2 := install.Get() | ||||
|     assert.Equal(t, data.Name, data2.Name, "TestToolKubectl error") | ||||
|     assert.Equal(t, data.Version, data2.Version, "TestToolKubectl error") | ||||
|  | ||||
|     err := install.Download() | ||||
|     assert.Nilf(t, err, "error message %s", "Download") | ||||
|  | ||||
|     dest := filepath.Join(TEST_DEST_DIR, "kubectl") | ||||
|     assert.FileExists(t, dest, "TestToolKubectl Download error") | ||||
|  | ||||
|     version, err1 := install.Version(dest) | ||||
|     assert.Equal(t, "v1.30.3", version, "TestToolKubectl error") | ||||
|  | ||||
|     fmt.Println(" err1 ", err1) | ||||
|  | ||||
| } | ||||
|  | ||||
|  | ||||
| func TestToolKubectlErr(t *testing.T) { | ||||
|  | ||||
|     data := ToolData{Bin: TEST_DEST_DIR,  | ||||
|                      Name: "test", | ||||
|                      Version: "1.0", | ||||
|                      Url: "http://test/%s"} | ||||
|  | ||||
|     install := KubectlInstall{obj: data} | ||||
|  | ||||
|     data2 := install.Get() | ||||
|     assert.Equal(t,  data.Name, data2.Name, "TestToolKubectl error") | ||||
|  | ||||
|     err := install.Download() | ||||
|  | ||||
|     assert.NotNilf(t, err, "error message %s", "Download") | ||||
| } | ||||
							
								
								
									
										23
									
								
								src/tool/main_test.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										23
									
								
								src/tool/main_test.go
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,23 @@ | ||||
| package tool | ||||
|  | ||||
| import ( | ||||
|     "os" | ||||
|     "testing" | ||||
|     "path/filepath" | ||||
| ) | ||||
|  | ||||
| var TEST_DEST_DIR = "../wrk_tool" | ||||
| var TEST_SRC_DIR = filepath.Join("../../test", "tool") | ||||
|  | ||||
| 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) | ||||
| } | ||||
							
								
								
									
										79
									
								
								src/tool/tool.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										79
									
								
								src/tool/tool.go
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,79 @@ | ||||
| package tool | ||||
|  | ||||
| import ( | ||||
|     "fmt" | ||||
|     "os" | ||||
|     "os/exec" | ||||
|     "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 = KubectlInstall{obj: data} | ||||
|     case "helm": | ||||
|         f = HelmInstall{obj: data, tmp: "/tmp"} | ||||
|     default: | ||||
|         return f, fmt.Errorf("Outil Inconnu : %s", data.Name) | ||||
|     } | ||||
|  | ||||
|     return f, nil | ||||
| } | ||||
							
								
								
									
										53
									
								
								src/utils/copyFile.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										53
									
								
								src/utils/copyFile.go
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,53 @@ | ||||
| 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 | ||||
| } | ||||
|  | ||||
| func CopyContentFile(content string, dst string) (error) { | ||||
|  | ||||
|     folderPath := filepath.Dir(dst) | ||||
|     os.MkdirAll(folderPath, os.ModePerm) | ||||
|  | ||||
|     fout, errCreate := os.Create(dst) | ||||
|     if errCreate != nil { | ||||
|         return errCreate | ||||
|     } | ||||
|     defer fout.Close() | ||||
|  | ||||
|     _, errCopy := fout.WriteString(content) | ||||
|     if errCopy != nil { | ||||
|         return errCopy | ||||
|    } | ||||
|    return nil | ||||
| } | ||||
							
								
								
									
										57
									
								
								src/utils/copyFile_test.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										57
									
								
								src/utils/copyFile_test.go
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,57 @@ | ||||
| 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) | ||||
| } | ||||
|  | ||||
| func TestCopyContentFile(t *testing.T) { | ||||
|     content := "TestCopyContentFileExist" | ||||
|     dest := filepath.Join(TEST_DEST_DIR, "fichier1") | ||||
|  | ||||
|     err := CopyContentFile(content, dest) | ||||
|  | ||||
|     assert.Nilf(t, err, "error message") | ||||
|     assert.FileExists(t, dest, "CopyFile error") | ||||
| } | ||||
							
								
								
									
										71
									
								
								src/utils/download.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										71
									
								
								src/utils/download.go
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,71 @@ | ||||
| package utils | ||||
|  | ||||
| import ( | ||||
|     "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 { | ||||
|         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 | ||||
| } | ||||
							
								
								
									
										51
									
								
								src/utils/download_test.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										51
									
								
								src/utils/download_test.go
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,51 @@ | ||||
| package utils | ||||
|  | ||||
| import ( | ||||
|     "os" | ||||
|     "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") | ||||
| } | ||||
|  | ||||
| func TestExtractTarGz(t *testing.T) { | ||||
|  | ||||
|   dest := filepath.Join(TEST_DEST_DIR, "extract") | ||||
| 	os.MkdirAll(dest, os.ModePerm) | ||||
|  | ||||
|   src := filepath.Join(TEST_SRC_DIR, "fichier1.tgz") | ||||
|   file, _ := os.Open(src) | ||||
|  | ||||
|   err := ExtractTarGz(dest, file) | ||||
|   assert.Nilf(t, err, "error message %s", src) | ||||
|   assert.FileExists(t, filepath.Join(dest, "fichier1"), "TestExtractTarGz error") | ||||
| } | ||||
|  | ||||
| func TestExtractTarGzErr(t *testing.T) { | ||||
|  | ||||
|     dest := filepath.Join(TEST_DEST_DIR, "extract") | ||||
|  | ||||
|     src := filepath.Join(TEST_SRC_DIR, "fichier1") | ||||
|     file, _ := os.Open(src) | ||||
|  | ||||
|     err := ExtractTarGz(dest, file) | ||||
|     assert.NotNilf(t, err, "error message %s", src) | ||||
| } | ||||
							
								
								
									
										25
									
								
								src/utils/main_test.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										25
									
								
								src/utils/main_test.go
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,25 @@ | ||||
| package utils | ||||
|  | ||||
| // https://pkg.go.dev/github.com/stretchr/testify/assert | ||||
|  | ||||
| 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) | ||||
| } | ||||
							
								
								
									
										10
									
								
								src/utils/slice.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										10
									
								
								src/utils/slice.go
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,10 @@ | ||||
| package utils | ||||
|  | ||||
| func StringInSlice(a string, list []string) bool { | ||||
|     for _, b := range list { | ||||
|         if b == a { | ||||
|             return true | ||||
|         } | ||||
|     } | ||||
|     return false | ||||
| } | ||||
							
								
								
									
										22
									
								
								src/utils/slice_test.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										22
									
								
								src/utils/slice_test.go
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,22 @@ | ||||
| package utils | ||||
|  | ||||
| import ( | ||||
|     "testing" | ||||
|     "github.com/stretchr/testify/assert" | ||||
| ) | ||||
|  | ||||
| func TestSliceInStringExist(t *testing.T) { | ||||
|     liste := []string{"text1", "text2"} | ||||
|  | ||||
|     res := StringInSlice("text1", liste) | ||||
|  | ||||
|     assert.Truef(t, res, "error message %s", "text1") | ||||
| } | ||||
|  | ||||
| func TestSliceInStringNotExist(t *testing.T) { | ||||
|     liste := []string{"text1", "text2"} | ||||
|  | ||||
|     res := StringInSlice("text3", liste) | ||||
|  | ||||
|     assert.Falsef(t, res, "error message %s", "text3") | ||||
| } | ||||
							
								
								
									
										23
									
								
								src/versionOc/main_test.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										23
									
								
								src/versionOc/main_test.go
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,23 @@ | ||||
| package versionOc | ||||
|  | ||||
| import ( | ||||
| 	"os" | ||||
| 	"testing" | ||||
|     "path/filepath" | ||||
| ) | ||||
|  | ||||
| var TEST_DEST_DIR = "../wrk_versionOc" | ||||
| var TEST_SRC_DIR = filepath.Join("../../test", "versionOc") | ||||
|  | ||||
| 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) | ||||
| } | ||||
							
								
								
									
										71
									
								
								src/versionOc/offline.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										71
									
								
								src/versionOc/offline.go
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,71 @@ | ||||
| // Package :  | ||||
| package versionOc | ||||
|  | ||||
| import ( | ||||
|     "fmt" | ||||
|     "os" | ||||
|     "errors" | ||||
|     "io" | ||||
|     "path/filepath" | ||||
|     "gopkg.in/yaml.v2" | ||||
|     log "oc-deploy/log_wrapper" | ||||
|     "oc-deploy/occonst" | ||||
| ) | ||||
|  | ||||
| type versionInput struct { | ||||
|     Version string  `yaml:"version"` | ||||
| } | ||||
|  | ||||
| // Get : Retourne la version | ||||
| func GetFromOffline(version string) (string, string, error) { | ||||
|  | ||||
|     version2 := version | ||||
|     if version == "latest" { | ||||
|         versionLatest, err := readLatestFromOffline() | ||||
|         if err != nil { | ||||
|             return "", "", err | ||||
|         } | ||||
|         version2 = versionLatest | ||||
|     } | ||||
|  | ||||
|     ficversion := fmt.Sprintf("oc_%s.yml", version2) | ||||
|     src := filepath.Join(occonst.OFFLINE_DIR, ficversion) | ||||
|     if _, err := os.Stat(src); err != nil { | ||||
|         log.Log().Debug().Msg(err.Error()) | ||||
|         return "", "", errors.New("Version non disponible") | ||||
|     } | ||||
|  | ||||
|     fin, err := os.Open(src) | ||||
|     if err != nil { | ||||
|         return "", "", err | ||||
|     } | ||||
|     defer fin.Close() | ||||
|     byteValue, err := io.ReadAll(fin) | ||||
|  | ||||
|     return version2, string(byteValue), nil | ||||
| } | ||||
|  | ||||
| // readLatestFile : Lit le numéro de la version dans le fichier lastest.yml | ||||
| func readLatestFromOffline() (string, error) { | ||||
|     src := filepath.Join(occonst.OFFLINE_DIR, "latest.yml") | ||||
|  | ||||
|     fin, err := os.Open(src) | ||||
|     if err != nil { | ||||
|         return "", err | ||||
|     } | ||||
|     defer fin.Close() | ||||
|  | ||||
|     byteValue, err := io.ReadAll(fin) | ||||
|     if err != nil { | ||||
|         return "", err | ||||
|     } | ||||
|  | ||||
|     var objmap versionInput | ||||
|  | ||||
|     err = yaml.Unmarshal(byteValue, &objmap) | ||||
|     if err != nil { | ||||
|         return "", err | ||||
|     } | ||||
|  | ||||
|     return objmap.Version, nil | ||||
| } | ||||
							
								
								
									
										27
									
								
								src/versionOc/offline_test.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										27
									
								
								src/versionOc/offline_test.go
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,27 @@ | ||||
| package versionOc | ||||
|  | ||||
| import ( | ||||
|     "path/filepath" | ||||
|  | ||||
|     "testing" | ||||
|  | ||||
|     "github.com/stretchr/testify/assert" | ||||
|  | ||||
|     "oc-deploy/occonst" | ||||
| ) | ||||
|  | ||||
| func TestGetOffline(t *testing.T) { | ||||
|  | ||||
|     _, _, err := GetFromOffline("99.1") | ||||
|     assert.NotNilf(t, err, "error message %s", err) | ||||
| } | ||||
|  | ||||
| func TestGetLatest(t *testing.T) { | ||||
|  | ||||
|     occonst.OFFLINE_DIR = filepath.Join(TEST_SRC_DIR, "offline") | ||||
|  | ||||
|     version, _, err := GetFromOffline("latest") | ||||
|     assert.Nilf(t, err, "error message %s", err) | ||||
|     assert.Equal(t, "99.1", version, "TestGetFromFile error") | ||||
|  | ||||
| } | ||||
							
								
								
									
										104
									
								
								src/versionOc/online.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										104
									
								
								src/versionOc/online.go
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,104 @@ | ||||
| package versionOc | ||||
|  | ||||
| import ( | ||||
|     "fmt" | ||||
|     "io" | ||||
|     "errors" | ||||
|     "net/http" | ||||
|     "encoding/json" | ||||
|     "encoding/base64" | ||||
|  | ||||
|     "oc-deploy/occonst" | ||||
|     log "oc-deploy/log_wrapper" | ||||
| ) | ||||
|  | ||||
|  | ||||
| func GetFromOnline(version string) (string, string, error) { | ||||
|  | ||||
|     version2 := version | ||||
|     if version == "latest" { | ||||
|         versionLatest, err := readLatestFromOnline() | ||||
|         if err != nil { | ||||
|             return "", "", err | ||||
|         } | ||||
|         version2 = versionLatest | ||||
|     } | ||||
|  | ||||
|     content, err := getFileVersion(version2) | ||||
|     if err != nil { | ||||
|         log.Log().Debug().Msg(err.Error()) | ||||
|         return "", "", errors.New("Version non disponible") | ||||
|     } | ||||
|  | ||||
|     return version2, content, nil | ||||
| } | ||||
|  | ||||
| type releaseStruct struct { | ||||
|     Id int `json:"id"` | ||||
|     Name string `json:"name"` | ||||
| } | ||||
|  | ||||
| type ocJsonStruct struct { | ||||
|     Value string `json:"value"` | ||||
| } | ||||
|  | ||||
| // Cherche dans Online la dernière version (non draft, non pre-releases) | ||||
| func readLatestFromOnline() (string, error) { | ||||
|  | ||||
|     url := fmt.Sprintf("%s/api/v1/repos/%s/releases/latest", | ||||
|                         occonst.ONLINE_URL, | ||||
|                         occonst.ONLINE_VERSION) | ||||
|  | ||||
|     res, err := http.Get(url) | ||||
|     if err != nil { | ||||
|         return "", err | ||||
|     } | ||||
|     body, err := io.ReadAll(res.Body) | ||||
|     if err != nil { | ||||
|         return "", err | ||||
|     } | ||||
|  | ||||
|     var data releaseStruct | ||||
|  | ||||
|     err = json.Unmarshal(body, &data) | ||||
|     if err != nil { | ||||
|         return "", err | ||||
|     } | ||||
|  | ||||
|     return data.Name, err | ||||
| } | ||||
|  | ||||
| // Récupère le fichier version de la version | ||||
| func getFileVersion(version string) (string, error) { | ||||
|  | ||||
|     url := fmt.Sprintf("%s/%s/releases/download/%s/oc.json", | ||||
|                         occonst.ONLINE_URL, | ||||
|                         occonst.ONLINE_VERSION, | ||||
|                         version) | ||||
|  | ||||
|     res, err := http.Get(url) | ||||
|     if err != nil { | ||||
|         return "", err | ||||
|     } | ||||
|     body, err := io.ReadAll(res.Body) | ||||
|     if err != nil { | ||||
|         return "", err | ||||
|     } | ||||
|  | ||||
|     if string(body) == "Not Found\n" { | ||||
|         return "", fmt.Errorf("Not found %s", version) | ||||
|     } | ||||
|  | ||||
|     var data ocJsonStruct | ||||
|     err = json.Unmarshal(body, &data) | ||||
|     if err != nil { | ||||
|         return "", err | ||||
|     } | ||||
|  | ||||
|     data64, err64 := base64.StdEncoding.DecodeString(data.Value) | ||||
|     if err64 != nil { | ||||
|         return "", err64 | ||||
|     } | ||||
|  | ||||
|     return string(data64), nil | ||||
| } | ||||
							
								
								
									
										62
									
								
								src/versionOc/online_test.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										62
									
								
								src/versionOc/online_test.go
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,62 @@ | ||||
| package versionOc | ||||
|  | ||||
| import ( | ||||
|     "fmt" | ||||
|     "testing" | ||||
|     // "encoding/base64" | ||||
|  | ||||
|     "oc-deploy/occonst" | ||||
|  | ||||
|     "github.com/stretchr/testify/assert" | ||||
|     "github.com/jarcoal/httpmock" | ||||
| ) | ||||
|  | ||||
| //  | ||||
| func TestGetOnline(t *testing.T) { | ||||
|  | ||||
|     httpmock.Activate() | ||||
|     defer httpmock.DeactivateAndReset() | ||||
|  | ||||
|     version := "99.1" | ||||
|     url := fmt.Sprintf("%s/%s/releases/download/%s/oc.json", | ||||
|                         occonst.ONLINE_URL, | ||||
|                         occonst.ONLINE_VERSION, | ||||
|                         version) | ||||
|      | ||||
|     httpmock.RegisterResponder("GET", url, | ||||
|       httpmock.NewStringResponder(200, `{"value": "e30K"}`)) | ||||
|  | ||||
|     res, _, err := GetFromOnline(version) | ||||
|     assert.Nilf(t, err, "error message %s", err) | ||||
|     assert.Equal(t, version, res, "TestGetOnline error") | ||||
| } | ||||
|  | ||||
| func TestGetOnlineLatest(t *testing.T) { | ||||
|  | ||||
|     httpmock.Activate() | ||||
|     defer httpmock.DeactivateAndReset() | ||||
|  | ||||
|     // version := "99.1" | ||||
|     url := fmt.Sprintf("%s/api/v1/repos/%s/releases/latest", | ||||
|                         occonst.ONLINE_URL, | ||||
|                         occonst.ONLINE_VERSION) | ||||
|      | ||||
|     httpmock.RegisterResponder("GET", url, | ||||
|       httpmock.NewStringResponder(200, `{"name": "99.0", "id": 2}`)) | ||||
|  | ||||
|     version := "99.0" | ||||
|     url2 := fmt.Sprintf("%s/%s/releases/download/%s/oc.json", | ||||
|                           occonst.ONLINE_URL, | ||||
|                           occonst.ONLINE_VERSION, | ||||
|                           version) | ||||
|    | ||||
|     httpmock.RegisterResponder("GET", url2, | ||||
|         httpmock.NewStringResponder(200, `{"value": "e30K"}`)) | ||||
|  | ||||
|  | ||||
|     version, _, err := GetFromOnline("latest") | ||||
|     assert.Nilf(t, err, "error message %s", err) | ||||
|     assert.Equal(t, "99.0", version, "TestGetFromFile error") | ||||
|     fmt.Println("TestGetOnlineLatest ", version, err) | ||||
|  | ||||
| } | ||||
							
								
								
									
										30
									
								
								src/versionOc/versionOc.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										30
									
								
								src/versionOc/versionOc.go
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,30 @@ | ||||
| // Package :  | ||||
| package versionOc | ||||
|  | ||||
| import ( | ||||
|     "os" | ||||
|     "io" | ||||
|     "gopkg.in/yaml.v2" | ||||
| ) | ||||
|  | ||||
| func GetFromFile(fileversion string) (string, error) { | ||||
|     fin, err := os.Open(fileversion) | ||||
|     if err != nil { | ||||
|         return "", err | ||||
|     } | ||||
|     defer fin.Close() | ||||
|  | ||||
|     byteValue, err := io.ReadAll(fin) | ||||
|     if err != nil { | ||||
|         return "", err | ||||
|     } | ||||
|  | ||||
|     var objmap versionInput | ||||
|  | ||||
|     err = yaml.Unmarshal(byteValue, &objmap) | ||||
|     if err != nil { | ||||
|         return "", err | ||||
|     } | ||||
|  | ||||
|     return objmap.Version, nil | ||||
| } | ||||
							
								
								
									
										34
									
								
								src/versionOc/versionOc_test.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										34
									
								
								src/versionOc/versionOc_test.go
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,34 @@ | ||||
| package versionOc | ||||
|  | ||||
| import ( | ||||
|     "path/filepath" | ||||
|  | ||||
|     "testing" | ||||
|  | ||||
|     "github.com/stretchr/testify/assert" | ||||
| ) | ||||
|  | ||||
| func TestGetFromFile(t *testing.T) { | ||||
|  | ||||
|     ocyaml := filepath.Join(TEST_SRC_DIR, "oc.yml") | ||||
|     version, err := GetFromFile(ocyaml) | ||||
|  | ||||
|     assert.Nilf(t, err, "error message %s", ocyaml) | ||||
|     assert.Equal(t, "99.0", version, "TestGetFromFile error") | ||||
| } | ||||
|  | ||||
| func TestGetFromFileErr(t *testing.T) { | ||||
|  | ||||
|     ocyaml := filepath.Join(TEST_SRC_DIR, "inconnu.yml") | ||||
|     _, err := GetFromFile(ocyaml) | ||||
|  | ||||
|     assert.NotNilf(t, err, "error message %s", ocyaml) | ||||
| } | ||||
|  | ||||
| func TestGetFromFileErr2(t *testing.T) { | ||||
|  | ||||
|     ocyaml := filepath.Join(TEST_SRC_DIR, "oc_error.yml") | ||||
|     _, err := GetFromFile(ocyaml) | ||||
|  | ||||
|     assert.NotNilf(t, err, "error message %s", ocyaml) | ||||
| } | ||||
							
								
								
									
										
											BIN
										
									
								
								test/bin/helm
									
									
									
									
									
										Executable file
									
								
							
							
						
						
									
										
											BIN
										
									
								
								test/bin/helm
									
									
									
									
									
										Executable file
									
								
							
										
											Binary file not shown.
										
									
								
							
							
								
								
									
										
											BIN
										
									
								
								test/bin/kubectl
									
									
									
									
									
										Executable file
									
								
							
							
						
						
									
										
											BIN
										
									
								
								test/bin/kubectl
									
									
									
									
									
										Executable file
									
								
							
										
											Binary file not shown.
										
									
								
							
							
								
								
									
										21
									
								
								test/chart/oc.yml
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										21
									
								
								test/chart/oc.yml
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,21 @@ | ||||
| --- | ||||
|  | ||||
| opencloud: | ||||
|   - repository: | ||||
|       name: bitnami | ||||
|       url: 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: {} | ||||
|  | ||||
|   - charts: | ||||
|       - name: myfirstrelease | ||||
|         chart: myfirstchart-0.1.0.tgz | ||||
|         url: https://zzzz/myfirstchart-0.1.0.tgz | ||||
							
								
								
									
										663
									
								
								test/helm/helm_status.json
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										663
									
								
								test/helm/helm_status.json
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,663 @@ | ||||
| { | ||||
|   "name": "oc-catalog", | ||||
|   "info": { | ||||
|     "first_deployed": "2024-09-05T19:06:44.16497388+02:00", | ||||
|     "last_deployed": "2024-09-05T19:06:44.16497388+02:00", | ||||
|     "deleted": "", | ||||
|     "description": "Install complete", | ||||
|     "status": "deployed", | ||||
|     "resources": { | ||||
|       "v1/Pod(related)": [ | ||||
|         { | ||||
|           "apiVersion": "v1", | ||||
|           "items": [ | ||||
|             { | ||||
|               "apiVersion": "v1", | ||||
|               "kind": "Pod", | ||||
|               "metadata": { | ||||
|                 "annotations": { | ||||
|                   "cni.projectcalico.org/containerID": "bc524c3ff4a2fceaeb9a996a9324807c0fddfc4c3e02cd59d73a9945d27d5f1b", | ||||
|                   "cni.projectcalico.org/podIP": "10.42.2.10/32", | ||||
|                   "cni.projectcalico.org/podIPs": "10.42.2.10/32" | ||||
|                 }, | ||||
|                 "creationTimestamp": "2024-09-05T17:06:44Z", | ||||
|                 "generateName": "oc-catalog-oc-catalog-", | ||||
|                 "labels": { | ||||
|                   "app": "oc-catalog", | ||||
|                   "apps.kubernetes.io/pod-index": "0", | ||||
|                   "controller-revision-hash": "oc-catalog-oc-catalog-7d7859dd76", | ||||
|                   "statefulset.kubernetes.io/pod-name": "oc-catalog-oc-catalog-0" | ||||
|                 }, | ||||
|                 "managedFields": [ | ||||
|                   { | ||||
|                     "apiVersion": "v1", | ||||
|                     "fieldsType": "FieldsV1", | ||||
|                     "fieldsV1": { | ||||
|                       "f:metadata": { | ||||
|                         "f:annotations": { | ||||
|                           ".": {}, | ||||
|                           "f:cni.projectcalico.org/containerID": {}, | ||||
|                           "f:cni.projectcalico.org/podIP": {}, | ||||
|                           "f:cni.projectcalico.org/podIPs": {} | ||||
|                         } | ||||
|                       } | ||||
|                     }, | ||||
|                     "manager": "calico", | ||||
|                     "operation": "Update", | ||||
|                     "subresource": "status", | ||||
|                     "time": "2024-09-05T17:06:44Z" | ||||
|                   }, | ||||
|                   { | ||||
|                     "apiVersion": "v1", | ||||
|                     "fieldsType": "FieldsV1", | ||||
|                     "fieldsV1": { | ||||
|                       "f:metadata": { | ||||
|                         "f:generateName": {}, | ||||
|                         "f:labels": { | ||||
|                           ".": {}, | ||||
|                           "f:app": {}, | ||||
|                           "f:apps.kubernetes.io/pod-index": {}, | ||||
|                           "f:controller-revision-hash": {}, | ||||
|                           "f:statefulset.kubernetes.io/pod-name": {} | ||||
|                         }, | ||||
|                         "f:ownerReferences": { | ||||
|                           ".": {}, | ||||
|                           "k:{\"uid\":\"10aa222e-dc37-451e-a5ee-e88f88b4e136\"}": {} | ||||
|                         } | ||||
|                       }, | ||||
|                       "f:spec": { | ||||
|                         "f:containers": { | ||||
|                           "k:{\"name\":\"oc-catalog\"}": { | ||||
|                             ".": {}, | ||||
|                             "f:env": { | ||||
|                               ".": {}, | ||||
|                               "k:{\"name\":\"MONGO_DATABASE\"}": { | ||||
|                                 ".": {}, | ||||
|                                 "f:name": {}, | ||||
|                                 "f:value": {} | ||||
|                               }, | ||||
|                               "k:{\"name\":\"MONGO_URI\"}": { | ||||
|                                 ".": {}, | ||||
|                                 "f:name": {}, | ||||
|                                 "f:value": {} | ||||
|                               } | ||||
|                             }, | ||||
|                             "f:image": {}, | ||||
|                             "f:imagePullPolicy": {}, | ||||
|                             "f:name": {}, | ||||
|                             "f:ports": { | ||||
|                               ".": {}, | ||||
|                               "k:{\"containerPort\":8080,\"protocol\":\"TCP\"}": { | ||||
|                                 ".": {}, | ||||
|                                 "f:containerPort": {}, | ||||
|                                 "f:protocol": {} | ||||
|                               } | ||||
|                             }, | ||||
|                             "f:resources": {}, | ||||
|                             "f:terminationMessagePath": {}, | ||||
|                             "f:terminationMessagePolicy": {} | ||||
|                           } | ||||
|                         }, | ||||
|                         "f:dnsPolicy": {}, | ||||
|                         "f:enableServiceLinks": {}, | ||||
|                         "f:hostname": {}, | ||||
|                         "f:imagePullSecrets": { | ||||
|                           ".": {}, | ||||
|                           "k:{\"name\":\"regcred\"}": {} | ||||
|                         }, | ||||
|                         "f:restartPolicy": {}, | ||||
|                         "f:schedulerName": {}, | ||||
|                         "f:securityContext": {}, | ||||
|                         "f:subdomain": {}, | ||||
|                         "f:terminationGracePeriodSeconds": {} | ||||
|                       } | ||||
|                     }, | ||||
|                     "manager": "kube-controller-manager", | ||||
|                     "operation": "Update", | ||||
|                     "time": "2024-09-05T17:06:44Z" | ||||
|                   }, | ||||
|                   { | ||||
|                     "apiVersion": "v1", | ||||
|                     "fieldsType": "FieldsV1", | ||||
|                     "fieldsV1": { | ||||
|                       "f:status": { | ||||
|                         "f:conditions": { | ||||
|                           "k:{\"type\":\"ContainersReady\"}": { | ||||
|                             ".": {}, | ||||
|                             "f:lastProbeTime": {}, | ||||
|                             "f:lastTransitionTime": {}, | ||||
|                             "f:status": {}, | ||||
|                             "f:type": {} | ||||
|                           }, | ||||
|                           "k:{\"type\":\"Initialized\"}": { | ||||
|                             ".": {}, | ||||
|                             "f:lastProbeTime": {}, | ||||
|                             "f:lastTransitionTime": {}, | ||||
|                             "f:status": {}, | ||||
|                             "f:type": {} | ||||
|                           }, | ||||
|                           "k:{\"type\":\"Ready\"}": { | ||||
|                             ".": {}, | ||||
|                             "f:lastProbeTime": {}, | ||||
|                             "f:lastTransitionTime": {}, | ||||
|                             "f:status": {}, | ||||
|                             "f:type": {} | ||||
|                           } | ||||
|                         }, | ||||
|                         "f:containerStatuses": {}, | ||||
|                         "f:hostIP": {}, | ||||
|                         "f:phase": {}, | ||||
|                         "f:podIP": {}, | ||||
|                         "f:podIPs": { | ||||
|                           ".": {}, | ||||
|                           "k:{\"ip\":\"10.42.2.10\"}": { | ||||
|                             ".": {}, | ||||
|                             "f:ip": {} | ||||
|                           } | ||||
|                         }, | ||||
|                         "f:startTime": {} | ||||
|                       } | ||||
|                     }, | ||||
|                     "manager": "kubelet", | ||||
|                     "operation": "Update", | ||||
|                     "subresource": "status", | ||||
|                     "time": "2024-09-05T17:06:46Z" | ||||
|                   } | ||||
|                 ], | ||||
|                 "name": "oc-catalog-oc-catalog-0", | ||||
|                 "namespace": "default", | ||||
|                 "ownerReferences": [ | ||||
|                   { | ||||
|                     "apiVersion": "apps/v1", | ||||
|                     "blockOwnerDeletion": true, | ||||
|                     "controller": true, | ||||
|                     "kind": "StatefulSet", | ||||
|                     "name": "oc-catalog-oc-catalog", | ||||
|                     "uid": "10aa222e-dc37-451e-a5ee-e88f88b4e136" | ||||
|                   } | ||||
|                 ], | ||||
|                 "resourceVersion": "7811984", | ||||
|                 "uid": "f2b3e7d0-68de-4f60-a8b7-75446ee3ebf1" | ||||
|               }, | ||||
|               "spec": { | ||||
|                 "containers": [ | ||||
|                   { | ||||
|                     "env": [ | ||||
|                       { | ||||
|                         "name": "MONGO_DATABASE", | ||||
|                         "value": "DC_myDC" | ||||
|                       }, | ||||
|                       { | ||||
|                         "name": "MONGO_URI", | ||||
|                         "value": "mongodb://mongo:27017" | ||||
|                       } | ||||
|                     ], | ||||
|                     "image": "harbor.dtf/dev/oc-catalog:1.0", | ||||
|                     "imagePullPolicy": "IfNotPresent", | ||||
|                     "name": "oc-catalog", | ||||
|                     "ports": [ | ||||
|                       { | ||||
|                         "containerPort": 8080, | ||||
|                         "protocol": "TCP" | ||||
|                       } | ||||
|                     ], | ||||
|                     "resources": {}, | ||||
|                     "terminationMessagePath": "/dev/termination-log", | ||||
|                     "terminationMessagePolicy": "File", | ||||
|                     "volumeMounts": [ | ||||
|                       { | ||||
|                         "mountPath": "/var/run/secrets/kubernetes.io/serviceaccount", | ||||
|                         "name": "kube-api-access-lpks6", | ||||
|                         "readOnly": true | ||||
|                       } | ||||
|                     ] | ||||
|                   } | ||||
|                 ], | ||||
|                 "dnsPolicy": "ClusterFirst", | ||||
|                 "enableServiceLinks": true, | ||||
|                 "hostname": "oc-catalog-oc-catalog-0", | ||||
|                 "imagePullSecrets": [ | ||||
|                   { | ||||
|                     "name": "regcred" | ||||
|                   } | ||||
|                 ], | ||||
|                 "nodeName": "rke2-worker1", | ||||
|                 "preemptionPolicy": "PreemptLowerPriority", | ||||
|                 "priority": 0, | ||||
|                 "restartPolicy": "Always", | ||||
|                 "schedulerName": "default-scheduler", | ||||
|                 "securityContext": {}, | ||||
|                 "serviceAccount": "default", | ||||
|                 "serviceAccountName": "default", | ||||
|                 "subdomain": "oc-catalog-oc-catalog", | ||||
|                 "terminationGracePeriodSeconds": 30, | ||||
|                 "tolerations": [ | ||||
|                   { | ||||
|                     "effect": "NoExecute", | ||||
|                     "key": "node.kubernetes.io/not-ready", | ||||
|                     "operator": "Exists", | ||||
|                     "tolerationSeconds": 300 | ||||
|                   }, | ||||
|                   { | ||||
|                     "effect": "NoExecute", | ||||
|                     "key": "node.kubernetes.io/unreachable", | ||||
|                     "operator": "Exists", | ||||
|                     "tolerationSeconds": 300 | ||||
|                   } | ||||
|                 ], | ||||
|                 "volumes": [ | ||||
|                   { | ||||
|                     "name": "kube-api-access-lpks6", | ||||
|                     "projected": { | ||||
|                       "defaultMode": 420, | ||||
|                       "sources": [ | ||||
|                         { | ||||
|                           "serviceAccountToken": { | ||||
|                             "expirationSeconds": 3607, | ||||
|                             "path": "token" | ||||
|                           } | ||||
|                         }, | ||||
|                         { | ||||
|                           "configMap": { | ||||
|                             "items": [ | ||||
|                               { | ||||
|                                 "key": "ca.crt", | ||||
|                                 "path": "ca.crt" | ||||
|                               } | ||||
|                             ], | ||||
|                             "name": "kube-root-ca.crt" | ||||
|                           } | ||||
|                         }, | ||||
|                         { | ||||
|                           "downwardAPI": { | ||||
|                             "items": [ | ||||
|                               { | ||||
|                                 "fieldRef": { | ||||
|                                   "apiVersion": "v1", | ||||
|                                   "fieldPath": "metadata.namespace" | ||||
|                                 }, | ||||
|                                 "path": "namespace" | ||||
|                               } | ||||
|                             ] | ||||
|                           } | ||||
|                         } | ||||
|                       ] | ||||
|                     } | ||||
|                   } | ||||
|                 ] | ||||
|               }, | ||||
|               "status": { | ||||
|                 "conditions": [ | ||||
|                   { | ||||
|                     "lastProbeTime": null, | ||||
|                     "lastTransitionTime": "2024-09-05T17:06:44Z", | ||||
|                     "status": "True", | ||||
|                     "type": "Initialized" | ||||
|                   }, | ||||
|                   { | ||||
|                     "lastProbeTime": null, | ||||
|                     "lastTransitionTime": "2024-09-05T17:06:46Z", | ||||
|                     "status": "True", | ||||
|                     "type": "Ready" | ||||
|                   }, | ||||
|                   { | ||||
|                     "lastProbeTime": null, | ||||
|                     "lastTransitionTime": "2024-09-05T17:06:46Z", | ||||
|                     "status": "True", | ||||
|                     "type": "ContainersReady" | ||||
|                   }, | ||||
|                   { | ||||
|                     "lastProbeTime": null, | ||||
|                     "lastTransitionTime": "2024-09-05T17:06:44Z", | ||||
|                     "status": "True", | ||||
|                     "type": "PodScheduled" | ||||
|                   } | ||||
|                 ], | ||||
|                 "containerStatuses": [ | ||||
|                   { | ||||
|                     "containerID": "containerd://b50252d915ab1bdf1ade5c9afff589e8f6b7cd98e1c507eb5f398c390d7f120c", | ||||
|                     "image": "harbor.dtf/dev/oc-catalog:1.0", | ||||
|                     "imageID": "harbor.dtf/dev/oc-catalog@sha256:b4e135ecc4e69b93636118f42e436eb0948f9781ffbec4911bb944b79fd415b3", | ||||
|                     "lastState": {}, | ||||
|                     "name": "oc-catalog", | ||||
|                     "ready": true, | ||||
|                     "restartCount": 0, | ||||
|                     "started": true, | ||||
|                     "state": { | ||||
|                       "running": { | ||||
|                         "startedAt": "2024-09-05T17:06:46Z" | ||||
|                       } | ||||
|                     } | ||||
|                   } | ||||
|                 ], | ||||
|                 "hostIP": "172.17.40.249", | ||||
|                 "phase": "Running", | ||||
|                 "podIP": "10.42.2.10", | ||||
|                 "podIPs": [ | ||||
|                   { | ||||
|                     "ip": "10.42.2.10" | ||||
|                   } | ||||
|                 ], | ||||
|                 "qosClass": "BestEffort", | ||||
|                 "startTime": "2024-09-05T17:06:44Z" | ||||
|               } | ||||
|             } | ||||
|           ], | ||||
|           "kind": "PodList", | ||||
|           "metadata": { | ||||
|             "resourceVersion": "8001092" | ||||
|           } | ||||
|         } | ||||
|       ], | ||||
|       "v1/Service": [ | ||||
|         { | ||||
|           "apiVersion": "v1", | ||||
|           "kind": "Service", | ||||
|           "metadata": { | ||||
|             "annotations": { | ||||
|               "meta.helm.sh/release-name": "oc-catalog", | ||||
|               "meta.helm.sh/release-namespace": "default" | ||||
|             }, | ||||
|             "creationTimestamp": "2024-09-05T17:06:44Z", | ||||
|             "labels": { | ||||
|               "app.kubernetes.io/managed-by": "Helm" | ||||
|             }, | ||||
|             "managedFields": [ | ||||
|               { | ||||
|                 "apiVersion": "v1", | ||||
|                 "fieldsType": "FieldsV1", | ||||
|                 "fieldsV1": { | ||||
|                   "f:metadata": { | ||||
|                     "f:annotations": { | ||||
|                       ".": {}, | ||||
|                       "f:meta.helm.sh/release-name": {}, | ||||
|                       "f:meta.helm.sh/release-namespace": {} | ||||
|                     }, | ||||
|                     "f:labels": { | ||||
|                       ".": {}, | ||||
|                       "f:app.kubernetes.io/managed-by": {} | ||||
|                     } | ||||
|                   }, | ||||
|                   "f:spec": { | ||||
|                     "f:externalTrafficPolicy": {}, | ||||
|                     "f:internalTrafficPolicy": {}, | ||||
|                     "f:ports": { | ||||
|                       ".": {}, | ||||
|                       "k:{\"port\":8087,\"protocol\":\"TCP\"}": { | ||||
|                         ".": {}, | ||||
|                         "f:port": {}, | ||||
|                         "f:protocol": {}, | ||||
|                         "f:targetPort": {} | ||||
|                       } | ||||
|                     }, | ||||
|                     "f:selector": {}, | ||||
|                     "f:sessionAffinity": {}, | ||||
|                     "f:type": {} | ||||
|                   } | ||||
|                 }, | ||||
|                 "manager": "helm", | ||||
|                 "operation": "Update", | ||||
|                 "time": "2024-09-05T17:06:44Z" | ||||
|               } | ||||
|             ], | ||||
|             "name": "oc-catalog-oc-catalog", | ||||
|             "namespace": "default", | ||||
|             "resourceVersion": "7811955", | ||||
|             "uid": "bb9f6cd3-298c-4d98-9f6a-59cbd70ddac2" | ||||
|           }, | ||||
|           "spec": { | ||||
|             "clusterIP": "10.43.6.251", | ||||
|             "clusterIPs": [ | ||||
|               "10.43.6.251" | ||||
|             ], | ||||
|             "externalTrafficPolicy": "Cluster", | ||||
|             "internalTrafficPolicy": "Cluster", | ||||
|             "ipFamilies": [ | ||||
|               "IPv4" | ||||
|             ], | ||||
|             "ipFamilyPolicy": "SingleStack", | ||||
|             "ports": [ | ||||
|               { | ||||
|                 "nodePort": 32692, | ||||
|                 "port": 8087, | ||||
|                 "protocol": "TCP", | ||||
|                 "targetPort": 8080 | ||||
|               } | ||||
|             ], | ||||
|             "selector": { | ||||
|               "app": "oc-catalog" | ||||
|             }, | ||||
|             "sessionAffinity": "None", | ||||
|             "type": "NodePort" | ||||
|           }, | ||||
|           "status": { | ||||
|             "loadBalancer": {} | ||||
|           } | ||||
|         } | ||||
|       ], | ||||
|       "v1/StatefulSet": [ | ||||
|         { | ||||
|           "apiVersion": "apps/v1", | ||||
|           "kind": "StatefulSet", | ||||
|           "metadata": { | ||||
|             "annotations": { | ||||
|               "meta.helm.sh/release-name": "oc-catalog", | ||||
|               "meta.helm.sh/release-namespace": "default" | ||||
|             }, | ||||
|             "creationTimestamp": "2024-09-05T17:06:44Z", | ||||
|             "generation": 1, | ||||
|             "labels": { | ||||
|               "app": "oc-catalog", | ||||
|               "app.kubernetes.io/managed-by": "Helm" | ||||
|             }, | ||||
|             "managedFields": [ | ||||
|               { | ||||
|                 "apiVersion": "apps/v1", | ||||
|                 "fieldsType": "FieldsV1", | ||||
|                 "fieldsV1": { | ||||
|                   "f:metadata": { | ||||
|                     "f:annotations": { | ||||
|                       ".": {}, | ||||
|                       "f:meta.helm.sh/release-name": {}, | ||||
|                       "f:meta.helm.sh/release-namespace": {} | ||||
|                     }, | ||||
|                     "f:labels": { | ||||
|                       ".": {}, | ||||
|                       "f:app": {}, | ||||
|                       "f:app.kubernetes.io/managed-by": {} | ||||
|                     } | ||||
|                   }, | ||||
|                   "f:spec": { | ||||
|                     "f:persistentVolumeClaimRetentionPolicy": { | ||||
|                       ".": {}, | ||||
|                       "f:whenDeleted": {}, | ||||
|                       "f:whenScaled": {} | ||||
|                     }, | ||||
|                     "f:podManagementPolicy": {}, | ||||
|                     "f:replicas": {}, | ||||
|                     "f:revisionHistoryLimit": {}, | ||||
|                     "f:selector": {}, | ||||
|                     "f:serviceName": {}, | ||||
|                     "f:template": { | ||||
|                       "f:metadata": { | ||||
|                         "f:labels": { | ||||
|                           ".": {}, | ||||
|                           "f:app": {} | ||||
|                         } | ||||
|                       }, | ||||
|                       "f:spec": { | ||||
|                         "f:containers": { | ||||
|                           "k:{\"name\":\"oc-catalog\"}": { | ||||
|                             ".": {}, | ||||
|                             "f:env": { | ||||
|                               ".": {}, | ||||
|                               "k:{\"name\":\"MONGO_DATABASE\"}": { | ||||
|                                 ".": {}, | ||||
|                                 "f:name": {}, | ||||
|                                 "f:value": {} | ||||
|                               }, | ||||
|                               "k:{\"name\":\"MONGO_URI\"}": { | ||||
|                                 ".": {}, | ||||
|                                 "f:name": {}, | ||||
|                                 "f:value": {} | ||||
|                               } | ||||
|                             }, | ||||
|                             "f:image": {}, | ||||
|                             "f:imagePullPolicy": {}, | ||||
|                             "f:name": {}, | ||||
|                             "f:ports": { | ||||
|                               ".": {}, | ||||
|                               "k:{\"containerPort\":8080,\"protocol\":\"TCP\"}": { | ||||
|                                 ".": {}, | ||||
|                                 "f:containerPort": {}, | ||||
|                                 "f:protocol": {} | ||||
|                               } | ||||
|                             }, | ||||
|                             "f:resources": {}, | ||||
|                             "f:terminationMessagePath": {}, | ||||
|                             "f:terminationMessagePolicy": {} | ||||
|                           } | ||||
|                         }, | ||||
|                         "f:dnsPolicy": {}, | ||||
|                         "f:imagePullSecrets": { | ||||
|                           ".": {}, | ||||
|                           "k:{\"name\":\"regcred\"}": {} | ||||
|                         }, | ||||
|                         "f:restartPolicy": {}, | ||||
|                         "f:schedulerName": {}, | ||||
|                         "f:securityContext": {}, | ||||
|                         "f:terminationGracePeriodSeconds": {} | ||||
|                       } | ||||
|                     }, | ||||
|                     "f:updateStrategy": { | ||||
|                       "f:rollingUpdate": { | ||||
|                         ".": {}, | ||||
|                         "f:partition": {} | ||||
|                       }, | ||||
|                       "f:type": {} | ||||
|                     } | ||||
|                   } | ||||
|                 }, | ||||
|                 "manager": "helm", | ||||
|                 "operation": "Update", | ||||
|                 "time": "2024-09-05T17:06:44Z" | ||||
|               }, | ||||
|               { | ||||
|                 "apiVersion": "apps/v1", | ||||
|                 "fieldsType": "FieldsV1", | ||||
|                 "fieldsV1": { | ||||
|                   "f:status": { | ||||
|                     "f:availableReplicas": {}, | ||||
|                     "f:collisionCount": {}, | ||||
|                     "f:currentReplicas": {}, | ||||
|                     "f:currentRevision": {}, | ||||
|                     "f:observedGeneration": {}, | ||||
|                     "f:readyReplicas": {}, | ||||
|                     "f:replicas": {}, | ||||
|                     "f:updateRevision": {}, | ||||
|                     "f:updatedReplicas": {} | ||||
|                   } | ||||
|                 }, | ||||
|                 "manager": "kube-controller-manager", | ||||
|                 "operation": "Update", | ||||
|                 "subresource": "status", | ||||
|                 "time": "2024-09-05T17:06:46Z" | ||||
|               } | ||||
|             ], | ||||
|             "name": "oc-catalog-oc-catalog", | ||||
|             "namespace": "default", | ||||
|             "resourceVersion": "7811987", | ||||
|             "uid": "10aa222e-dc37-451e-a5ee-e88f88b4e136" | ||||
|           }, | ||||
|           "spec": { | ||||
|             "persistentVolumeClaimRetentionPolicy": { | ||||
|               "whenDeleted": "Retain", | ||||
|               "whenScaled": "Retain" | ||||
|             }, | ||||
|             "podManagementPolicy": "OrderedReady", | ||||
|             "replicas": 1, | ||||
|             "revisionHistoryLimit": 10, | ||||
|             "selector": { | ||||
|               "matchLabels": { | ||||
|                 "app": "oc-catalog" | ||||
|               } | ||||
|             }, | ||||
|             "serviceName": "oc-catalog-oc-catalog", | ||||
|             "template": { | ||||
|               "metadata": { | ||||
|                 "creationTimestamp": null, | ||||
|                 "labels": { | ||||
|                   "app": "oc-catalog" | ||||
|                 } | ||||
|               }, | ||||
|               "spec": { | ||||
|                 "containers": [ | ||||
|                   { | ||||
|                     "env": [ | ||||
|                       { | ||||
|                         "name": "MONGO_DATABASE", | ||||
|                         "value": "DC_myDC" | ||||
|                       }, | ||||
|                       { | ||||
|                         "name": "MONGO_URI", | ||||
|                         "value": "mongodb://mongo:27017" | ||||
|                       } | ||||
|                     ], | ||||
|                     "image": "harbor.dtf/dev/oc-catalog:1.0", | ||||
|                     "imagePullPolicy": "IfNotPresent", | ||||
|                     "name": "oc-catalog", | ||||
|                     "ports": [ | ||||
|                       { | ||||
|                         "containerPort": 8080, | ||||
|                         "protocol": "TCP" | ||||
|                       } | ||||
|                     ], | ||||
|                     "resources": {}, | ||||
|                     "terminationMessagePath": "/dev/termination-log", | ||||
|                     "terminationMessagePolicy": "File" | ||||
|                   } | ||||
|                 ], | ||||
|                 "dnsPolicy": "ClusterFirst", | ||||
|                 "imagePullSecrets": [ | ||||
|                   { | ||||
|                     "name": "regcred" | ||||
|                   } | ||||
|                 ], | ||||
|                 "restartPolicy": "Always", | ||||
|                 "schedulerName": "default-scheduler", | ||||
|                 "securityContext": {}, | ||||
|                 "terminationGracePeriodSeconds": 30 | ||||
|               } | ||||
|             }, | ||||
|             "updateStrategy": { | ||||
|               "rollingUpdate": { | ||||
|                 "partition": 0 | ||||
|               }, | ||||
|               "type": "RollingUpdate" | ||||
|             } | ||||
|           }, | ||||
|           "status": { | ||||
|             "availableReplicas": 1, | ||||
|             "collisionCount": 0, | ||||
|             "currentReplicas": 1, | ||||
|             "currentRevision": "oc-catalog-oc-catalog-7d7859dd76", | ||||
|             "observedGeneration": 1, | ||||
|             "readyReplicas": 1, | ||||
|             "replicas": 1, | ||||
|             "updateRevision": "oc-catalog-oc-catalog-7d7859dd76", | ||||
|             "updatedReplicas": 1 | ||||
|           } | ||||
|         } | ||||
|       ] | ||||
|     } | ||||
|   }, | ||||
|   "config": { | ||||
|     "image": { | ||||
|       "repository": "harbor.dtf/dev/oc-catalog", | ||||
|       "tag": "1.0" | ||||
|     } | ||||
|   }, | ||||
|   "manifest": "---\n# Source: oc-catalog/templates/service.yml\napiVersion: v1\nkind: Service\nmetadata:\n  name: oc-catalog-oc-catalog\nspec:\n  selector:\n    app: oc-catalog\n  ports:\n    - protocol: TCP\n      port: 8087\n      targetPort: 8080\n  type: NodePort\n---\n# Source: oc-catalog/templates/statefulset.yml\napiVersion: apps/v1\nkind: StatefulSet\nmetadata:\n  name: oc-catalog-oc-catalog\n  labels:\n    app: oc-catalog\nspec:\n  serviceName: \"oc-catalog-oc-catalog\"\n  replicas: 1\n  selector:\n    matchLabels:\n      app: oc-catalog\n  template:\n    metadata:\n      labels:\n        app: oc-catalog\n    spec:\n      containers:\n      - name: oc-catalog\n        image: \"harbor.dtf/dev/oc-catalog:1.0\"\n        ports:\n        - containerPort: 8080\n        env:\n        - name: MONGO_DATABASE\n          value: \"DC_myDC\"\n        - name: MONGO_URI\n          value: \"mongodb://mongo:27017\"\n      imagePullSecrets:\n        - name: regcred\n", | ||||
|   "version": 1, | ||||
|   "namespace": "default" | ||||
| } | ||||
							
								
								
									
										54
									
								
								test/kubectl/context.json
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										54
									
								
								test/kubectl/context.json
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,54 @@ | ||||
| { | ||||
|     "kind": "Config", | ||||
|     "apiVersion": "v1", | ||||
|     "preferences": {}, | ||||
|     "clusters": [ | ||||
|         { | ||||
|             "name": "minikube", | ||||
|             "cluster": { | ||||
|                 "server": "https://127.0.0.1:38039", | ||||
|                 "certificate-authority": "/home/admeju/.minikube/ca.crt", | ||||
|                 "extensions": [ | ||||
|                     { | ||||
|                         "name": "cluster_info", | ||||
|                         "extension": { | ||||
|                             "last-update": "Tue, 10 Sep 2024 10:32:04 UTC", | ||||
|                             "provider": "minikube.sigs.k8s.io", | ||||
|                             "version": "v1.33.1" | ||||
|                         } | ||||
|                     } | ||||
|                 ] | ||||
|             } | ||||
|         } | ||||
|     ], | ||||
|     "users": [ | ||||
|         { | ||||
|             "name": "minikube", | ||||
|             "user": { | ||||
|                 "client-certificate": "/home/admeju/.minikube/profiles/minikube/client.crt", | ||||
|                 "client-key": "/home/admeju/.minikube/profiles/minikube/client.key" | ||||
|             } | ||||
|         } | ||||
|     ], | ||||
|     "contexts": [ | ||||
|         { | ||||
|             "name": "minikube", | ||||
|             "context": { | ||||
|                 "cluster": "minikube", | ||||
|                 "user": "minikube", | ||||
|                 "namespace": "default", | ||||
|                 "extensions": [ | ||||
|                     { | ||||
|                         "name": "context_info", | ||||
|                         "extension": { | ||||
|                             "last-update": "Tue, 10 Sep 2024 10:32:04 UTC", | ||||
|                             "provider": "minikube.sigs.k8s.io", | ||||
|                             "version": "v1.33.1" | ||||
|                         } | ||||
|                     } | ||||
|                 ] | ||||
|             } | ||||
|         } | ||||
|     ], | ||||
|     "current-context": "minikube" | ||||
| } | ||||
							
								
								
									
										312
									
								
								test/kubectl/deployment.json
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										312
									
								
								test/kubectl/deployment.json
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,312 @@ | ||||
| { | ||||
|     "apiVersion": "apps/v1", | ||||
|     "kind": "Deployment", | ||||
|     "metadata": { | ||||
|         "annotations": { | ||||
|             "deployment.kubernetes.io/revision": "1", | ||||
|             "meta.helm.sh/release-name": "phpmyadmin", | ||||
|             "meta.helm.sh/release-namespace": "default" | ||||
|         }, | ||||
|         "creationTimestamp": "2024-09-06T12:29:16Z", | ||||
|         "generation": 1, | ||||
|         "labels": { | ||||
|             "app.kubernetes.io/instance": "phpmyadmin", | ||||
|             "app.kubernetes.io/managed-by": "Helm", | ||||
|             "app.kubernetes.io/name": "phpmyadmin", | ||||
|             "app.kubernetes.io/version": "5.2.1", | ||||
|             "helm.sh/chart": "phpmyadmin-17.0.4" | ||||
|         }, | ||||
|         "name": "phpmyadmin", | ||||
|         "namespace": "default", | ||||
|         "resourceVersion": "87308", | ||||
|         "uid": "b8518be1-1dd0-45a1-80f3-ddb835a56a5d" | ||||
|     }, | ||||
|     "spec": { | ||||
|         "progressDeadlineSeconds": 600, | ||||
|         "replicas": 1, | ||||
|         "revisionHistoryLimit": 10, | ||||
|         "selector": { | ||||
|             "matchLabels": { | ||||
|                 "app.kubernetes.io/instance": "phpmyadmin", | ||||
|                 "app.kubernetes.io/name": "phpmyadmin" | ||||
|             } | ||||
|         }, | ||||
|         "strategy": { | ||||
|             "rollingUpdate": { | ||||
|                 "maxSurge": "25%", | ||||
|                 "maxUnavailable": "25%" | ||||
|             }, | ||||
|             "type": "RollingUpdate" | ||||
|         }, | ||||
|         "template": { | ||||
|             "metadata": { | ||||
|                 "creationTimestamp": null, | ||||
|                 "labels": { | ||||
|                     "app.kubernetes.io/instance": "phpmyadmin", | ||||
|                     "app.kubernetes.io/managed-by": "Helm", | ||||
|                     "app.kubernetes.io/name": "phpmyadmin", | ||||
|                     "app.kubernetes.io/version": "5.2.1", | ||||
|                     "helm.sh/chart": "phpmyadmin-17.0.4" | ||||
|                 } | ||||
|             }, | ||||
|             "spec": { | ||||
|                 "affinity": { | ||||
|                     "podAntiAffinity": { | ||||
|                         "preferredDuringSchedulingIgnoredDuringExecution": [ | ||||
|                             { | ||||
|                                 "podAffinityTerm": { | ||||
|                                     "labelSelector": { | ||||
|                                         "matchLabels": { | ||||
|                                             "app.kubernetes.io/instance": "phpmyadmin", | ||||
|                                             "app.kubernetes.io/name": "phpmyadmin" | ||||
|                                         } | ||||
|                                     }, | ||||
|                                     "topologyKey": "kubernetes.io/hostname" | ||||
|                                 }, | ||||
|                                 "weight": 1 | ||||
|                             } | ||||
|                         ] | ||||
|                     } | ||||
|                 }, | ||||
|                 "automountServiceAccountToken": false, | ||||
|                 "containers": [ | ||||
|                     { | ||||
|                         "env": [ | ||||
|                             { | ||||
|                                 "name": "BITNAMI_DEBUG", | ||||
|                                 "value": "false" | ||||
|                             }, | ||||
|                             { | ||||
|                                 "name": "DATABASE_PORT_NUMBER", | ||||
|                                 "value": "3306" | ||||
|                             }, | ||||
|                             { | ||||
|                                 "name": "DATABASE_HOST" | ||||
|                             }, | ||||
|                             { | ||||
|                                 "name": "PHPMYADMIN_ALLOW_NO_PASSWORD", | ||||
|                                 "value": "true" | ||||
|                             }, | ||||
|                             { | ||||
|                                 "name": "PHPMYADMIN_ALLOW_ARBITRARY_SERVER", | ||||
|                                 "value": "true" | ||||
|                             }, | ||||
|                             { | ||||
|                                 "name": "DATABASE_ENABLE_SSL", | ||||
|                                 "value": "no" | ||||
|                             } | ||||
|                         ], | ||||
|                         "image": "docker.io/bitnami/phpmyadmin:5.2.1-debian-12-r36", | ||||
|                         "imagePullPolicy": "IfNotPresent", | ||||
|                         "livenessProbe": { | ||||
|                             "failureThreshold": 6, | ||||
|                             "initialDelaySeconds": 30, | ||||
|                             "periodSeconds": 10, | ||||
|                             "successThreshold": 1, | ||||
|                             "tcpSocket": { | ||||
|                                 "port": "http" | ||||
|                             }, | ||||
|                             "timeoutSeconds": 30 | ||||
|                         }, | ||||
|                         "name": "phpmyadmin", | ||||
|                         "ports": [ | ||||
|                             { | ||||
|                                 "containerPort": 8080, | ||||
|                                 "name": "http", | ||||
|                                 "protocol": "TCP" | ||||
|                             }, | ||||
|                             { | ||||
|                                 "containerPort": 8443, | ||||
|                                 "name": "https", | ||||
|                                 "protocol": "TCP" | ||||
|                             } | ||||
|                         ], | ||||
|                         "readinessProbe": { | ||||
|                             "failureThreshold": 6, | ||||
|                             "httpGet": { | ||||
|                                 "path": "/", | ||||
|                                 "port": "http", | ||||
|                                 "scheme": "HTTP" | ||||
|                             }, | ||||
|                             "initialDelaySeconds": 30, | ||||
|                             "periodSeconds": 10, | ||||
|                             "successThreshold": 1, | ||||
|                             "timeoutSeconds": 30 | ||||
|                         }, | ||||
|                         "resources": { | ||||
|                             "limits": { | ||||
|                                 "cpu": "375m", | ||||
|                                 "ephemeral-storage": "2Gi", | ||||
|                                 "memory": "384Mi" | ||||
|                             }, | ||||
|                             "requests": { | ||||
|                                 "cpu": "250m", | ||||
|                                 "ephemeral-storage": "50Mi", | ||||
|                                 "memory": "256Mi" | ||||
|                             } | ||||
|                         }, | ||||
|                         "securityContext": { | ||||
|                             "allowPrivilegeEscalation": false, | ||||
|                             "capabilities": { | ||||
|                                 "drop": [ | ||||
|                                     "ALL" | ||||
|                                 ] | ||||
|                             }, | ||||
|                             "privileged": false, | ||||
|                             "readOnlyRootFilesystem": true, | ||||
|                             "runAsGroup": 1001, | ||||
|                             "runAsNonRoot": true, | ||||
|                             "runAsUser": 1001, | ||||
|                             "seccompProfile": { | ||||
|                                 "type": "RuntimeDefault" | ||||
|                             } | ||||
|                         }, | ||||
|                         "terminationMessagePath": "/dev/termination-log", | ||||
|                         "terminationMessagePolicy": "File", | ||||
|                         "volumeMounts": [ | ||||
|                             { | ||||
|                                 "mountPath": "/opt/bitnami/apache/conf", | ||||
|                                 "name": "empty-dir", | ||||
|                                 "subPath": "apache-conf-dir" | ||||
|                             }, | ||||
|                             { | ||||
|                                 "mountPath": "/opt/bitnami/apache/logs", | ||||
|                                 "name": "empty-dir", | ||||
|                                 "subPath": "apache-logs-dir" | ||||
|                             }, | ||||
|                             { | ||||
|                                 "mountPath": "/opt/bitnami/apache/var/run", | ||||
|                                 "name": "empty-dir", | ||||
|                                 "subPath": "apache-tmp-dir" | ||||
|                             }, | ||||
|                             { | ||||
|                                 "mountPath": "/opt/bitnami/php/etc", | ||||
|                                 "name": "empty-dir", | ||||
|                                 "subPath": "php-conf-dir" | ||||
|                             }, | ||||
|                             { | ||||
|                                 "mountPath": "/opt/bitnami/php/tmp", | ||||
|                                 "name": "empty-dir", | ||||
|                                 "subPath": "php-tmp-dir" | ||||
|                             }, | ||||
|                             { | ||||
|                                 "mountPath": "/opt/bitnami/php/var", | ||||
|                                 "name": "empty-dir", | ||||
|                                 "subPath": "php-var-dir" | ||||
|                             }, | ||||
|                             { | ||||
|                                 "mountPath": "/tmp", | ||||
|                                 "name": "empty-dir", | ||||
|                                 "subPath": "tmp-dir" | ||||
|                             }, | ||||
|                             { | ||||
|                                 "mountPath": "/opt/bitnami/phpmyadmin", | ||||
|                                 "name": "empty-dir", | ||||
|                                 "subPath": "app-base-dir" | ||||
|                             } | ||||
|                         ] | ||||
|                     } | ||||
|                 ], | ||||
|                 "dnsPolicy": "ClusterFirst", | ||||
|                 "hostAliases": [ | ||||
|                     { | ||||
|                         "hostnames": [ | ||||
|                             "status.localhost" | ||||
|                         ], | ||||
|                         "ip": "127.0.0.1" | ||||
|                     } | ||||
|                 ], | ||||
|                 "initContainers": [ | ||||
|                     { | ||||
|                         "args": [ | ||||
|                             "-ec", | ||||
|                             "#!/bin/bash\n\n. /opt/bitnami/scripts/liblog.sh\n. /opt/bitnami/scripts/libfs.sh\n\ninfo \"Copying base dir to empty dir\"\n# In order to not break the application functionality (such as upgrades or plugins) we need\n# to make the base directory writable, so we need to copy it to an empty dir volume\ncp -r --preserve=mode /opt/bitnami/phpmyadmin /emptydir/app-base-dir\n\ninfo \"Copying symlinks to stdout/stderr\"\n# We copy the logs folder because it has symlinks to stdout and stderr\nif ! is_dir_empty /opt/bitnami/apache/logs; then\n  cp -r /opt/bitnami/apache/logs /emptydir/apache-logs-dir\nfi\ninfo \"Copying php var directory\"\n# PhpMyAdmin will fail to start if the php var folder is not populated\nif ! is_dir_empty /opt/bitnami/php/var; then\n  cp -r /opt/bitnami/php/var /emptydir/php-var-dir\nfi\ninfo \"Copy operation completed\"\n" | ||||
|                         ], | ||||
|                         "command": [ | ||||
|                             "/bin/bash" | ||||
|                         ], | ||||
|                         "image": "docker.io/bitnami/phpmyadmin:5.2.1-debian-12-r36", | ||||
|                         "imagePullPolicy": "IfNotPresent", | ||||
|                         "name": "prepare-base-dir", | ||||
|                         "resources": { | ||||
|                             "limits": { | ||||
|                                 "cpu": "375m", | ||||
|                                 "ephemeral-storage": "2Gi", | ||||
|                                 "memory": "384Mi" | ||||
|                             }, | ||||
|                             "requests": { | ||||
|                                 "cpu": "250m", | ||||
|                                 "ephemeral-storage": "50Mi", | ||||
|                                 "memory": "256Mi" | ||||
|                             } | ||||
|                         }, | ||||
|                         "securityContext": { | ||||
|                             "allowPrivilegeEscalation": false, | ||||
|                             "capabilities": { | ||||
|                                 "drop": [ | ||||
|                                     "ALL" | ||||
|                                 ] | ||||
|                             }, | ||||
|                             "privileged": false, | ||||
|                             "readOnlyRootFilesystem": true, | ||||
|                             "runAsGroup": 1001, | ||||
|                             "runAsNonRoot": true, | ||||
|                             "runAsUser": 1001, | ||||
|                             "seccompProfile": { | ||||
|                                 "type": "RuntimeDefault" | ||||
|                             } | ||||
|                         }, | ||||
|                         "terminationMessagePath": "/dev/termination-log", | ||||
|                         "terminationMessagePolicy": "File", | ||||
|                         "volumeMounts": [ | ||||
|                             { | ||||
|                                 "mountPath": "/emptydir", | ||||
|                                 "name": "empty-dir" | ||||
|                             } | ||||
|                         ] | ||||
|                     } | ||||
|                 ], | ||||
|                 "restartPolicy": "Always", | ||||
|                 "schedulerName": "default-scheduler", | ||||
|                 "securityContext": { | ||||
|                     "fsGroup": 1001, | ||||
|                     "fsGroupChangePolicy": "Always" | ||||
|                 }, | ||||
|                 "serviceAccount": "phpmyadmin", | ||||
|                 "serviceAccountName": "phpmyadmin", | ||||
|                 "terminationGracePeriodSeconds": 30, | ||||
|                 "volumes": [ | ||||
|                     { | ||||
|                         "emptyDir": {}, | ||||
|                         "name": "empty-dir" | ||||
|                     } | ||||
|                 ] | ||||
|             } | ||||
|         } | ||||
|     }, | ||||
|     "status": { | ||||
|         "availableReplicas": 1, | ||||
|         "conditions": [ | ||||
|             { | ||||
|                 "lastTransitionTime": "2024-09-06T12:29:17Z", | ||||
|                 "lastUpdateTime": "2024-09-06T12:30:08Z", | ||||
|                 "message": "ReplicaSet \"phpmyadmin-7f7bbf7bd7\" has successfully progressed.", | ||||
|                 "reason": "NewReplicaSetAvailable", | ||||
|                 "status": "True", | ||||
|                 "type": "Progressing" | ||||
|             }, | ||||
|             { | ||||
|                 "lastTransitionTime": "2024-09-09T11:54:00Z", | ||||
|                 "lastUpdateTime": "2024-09-09T11:54:00Z", | ||||
|                 "message": "Deployment has minimum availability.", | ||||
|                 "reason": "MinimumReplicasAvailable", | ||||
|                 "status": "True", | ||||
|                 "type": "Available" | ||||
|             } | ||||
|         ], | ||||
|         "observedGeneration": 1, | ||||
|         "readyReplicas": 1, | ||||
|         "replicas": 1, | ||||
|         "updatedReplicas": 1 | ||||
|     } | ||||
| } | ||||
							
								
								
									
										332
									
								
								test/kubectl/statefulset.json
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										332
									
								
								test/kubectl/statefulset.json
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,332 @@ | ||||
| { | ||||
|     "apiVersion": "apps/v1", | ||||
|     "kind": "StatefulSet", | ||||
|     "metadata": { | ||||
|         "annotations": { | ||||
|             "meta.helm.sh/release-name": "wordpress", | ||||
|             "meta.helm.sh/release-namespace": "default" | ||||
|         }, | ||||
|         "creationTimestamp": "2024-09-09T12:29:35Z", | ||||
|         "generation": 1, | ||||
|         "labels": { | ||||
|             "app.kubernetes.io/component": "primary", | ||||
|             "app.kubernetes.io/instance": "wordpress", | ||||
|             "app.kubernetes.io/managed-by": "Helm", | ||||
|             "app.kubernetes.io/name": "mariadb", | ||||
|             "app.kubernetes.io/version": "11.4.2", | ||||
|             "helm.sh/chart": "mariadb-19.0.3" | ||||
|         }, | ||||
|         "name": "wordpress-mariadb", | ||||
|         "namespace": "default", | ||||
|         "resourceVersion": "92784", | ||||
|         "uid": "82197de7-3b4f-4225-b1a2-58e8ac0fad44" | ||||
|     }, | ||||
|     "spec": { | ||||
|         "persistentVolumeClaimRetentionPolicy": { | ||||
|             "whenDeleted": "Retain", | ||||
|             "whenScaled": "Retain" | ||||
|         }, | ||||
|         "podManagementPolicy": "OrderedReady", | ||||
|         "replicas": 1, | ||||
|         "revisionHistoryLimit": 10, | ||||
|         "selector": { | ||||
|             "matchLabels": { | ||||
|                 "app.kubernetes.io/component": "primary", | ||||
|                 "app.kubernetes.io/instance": "wordpress", | ||||
|                 "app.kubernetes.io/name": "mariadb" | ||||
|             } | ||||
|         }, | ||||
|         "serviceName": "wordpress-mariadb", | ||||
|         "template": { | ||||
|             "metadata": { | ||||
|                 "annotations": { | ||||
|                     "checksum/configuration": "0fdca6295cb246435ed7edb5801c3445ca97c878dcce94b652f2fec128efd78a" | ||||
|                 }, | ||||
|                 "creationTimestamp": null, | ||||
|                 "labels": { | ||||
|                     "app.kubernetes.io/component": "primary", | ||||
|                     "app.kubernetes.io/instance": "wordpress", | ||||
|                     "app.kubernetes.io/managed-by": "Helm", | ||||
|                     "app.kubernetes.io/name": "mariadb", | ||||
|                     "app.kubernetes.io/version": "11.4.2", | ||||
|                     "helm.sh/chart": "mariadb-19.0.3" | ||||
|                 } | ||||
|             }, | ||||
|             "spec": { | ||||
|                 "affinity": { | ||||
|                     "podAntiAffinity": { | ||||
|                         "preferredDuringSchedulingIgnoredDuringExecution": [ | ||||
|                             { | ||||
|                                 "podAffinityTerm": { | ||||
|                                     "labelSelector": { | ||||
|                                         "matchLabels": { | ||||
|                                             "app.kubernetes.io/component": "primary", | ||||
|                                             "app.kubernetes.io/instance": "wordpress", | ||||
|                                             "app.kubernetes.io/name": "mariadb" | ||||
|                                         } | ||||
|                                     }, | ||||
|                                     "topologyKey": "kubernetes.io/hostname" | ||||
|                                 }, | ||||
|                                 "weight": 1 | ||||
|                             } | ||||
|                         ] | ||||
|                     } | ||||
|                 }, | ||||
|                 "automountServiceAccountToken": false, | ||||
|                 "containers": [ | ||||
|                     { | ||||
|                         "env": [ | ||||
|                             { | ||||
|                                 "name": "BITNAMI_DEBUG", | ||||
|                                 "value": "false" | ||||
|                             }, | ||||
|                             { | ||||
|                                 "name": "MARIADB_ROOT_PASSWORD", | ||||
|                                 "valueFrom": { | ||||
|                                     "secretKeyRef": { | ||||
|                                         "key": "mariadb-root-password", | ||||
|                                         "name": "wordpress-mariadb" | ||||
|                                     } | ||||
|                                 } | ||||
|                             }, | ||||
|                             { | ||||
|                                 "name": "MARIADB_USER", | ||||
|                                 "value": "bn_wordpress" | ||||
|                             }, | ||||
|                             { | ||||
|                                 "name": "MARIADB_PASSWORD", | ||||
|                                 "valueFrom": { | ||||
|                                     "secretKeyRef": { | ||||
|                                         "key": "mariadb-password", | ||||
|                                         "name": "wordpress-mariadb" | ||||
|                                     } | ||||
|                                 } | ||||
|                             }, | ||||
|                             { | ||||
|                                 "name": "MARIADB_DATABASE", | ||||
|                                 "value": "bitnami_wordpress" | ||||
|                             } | ||||
|                         ], | ||||
|                         "image": "docker.io/bitnami/mariadb:11.4.2-debian-12-r2", | ||||
|                         "imagePullPolicy": "IfNotPresent", | ||||
|                         "livenessProbe": { | ||||
|                             "exec": { | ||||
|                                 "command": [ | ||||
|                                     "/bin/bash", | ||||
|                                     "-ec", | ||||
|                                     "password_aux=\"${MARIADB_ROOT_PASSWORD:-}\"\nif [[ -f \"${MARIADB_ROOT_PASSWORD_FILE:-}\" ]]; then\n    password_aux=$(cat \"$MARIADB_ROOT_PASSWORD_FILE\")\nfi\nmysqladmin status -uroot -p\"${password_aux}\"\n" | ||||
|                                 ] | ||||
|                             }, | ||||
|                             "failureThreshold": 3, | ||||
|                             "initialDelaySeconds": 120, | ||||
|                             "periodSeconds": 10, | ||||
|                             "successThreshold": 1, | ||||
|                             "timeoutSeconds": 1 | ||||
|                         }, | ||||
|                         "name": "mariadb", | ||||
|                         "ports": [ | ||||
|                             { | ||||
|                                 "containerPort": 3306, | ||||
|                                 "name": "mysql", | ||||
|                                 "protocol": "TCP" | ||||
|                             } | ||||
|                         ], | ||||
|                         "readinessProbe": { | ||||
|                             "exec": { | ||||
|                                 "command": [ | ||||
|                                     "/bin/bash", | ||||
|                                     "-ec", | ||||
|                                     "password_aux=\"${MARIADB_ROOT_PASSWORD:-}\"\nif [[ -f \"${MARIADB_ROOT_PASSWORD_FILE:-}\" ]]; then\n    password_aux=$(cat \"$MARIADB_ROOT_PASSWORD_FILE\")\nfi\nmysqladmin ping -uroot -p\"${password_aux}\"\n" | ||||
|                                 ] | ||||
|                             }, | ||||
|                             "failureThreshold": 3, | ||||
|                             "initialDelaySeconds": 30, | ||||
|                             "periodSeconds": 10, | ||||
|                             "successThreshold": 1, | ||||
|                             "timeoutSeconds": 1 | ||||
|                         }, | ||||
|                         "resources": { | ||||
|                             "limits": { | ||||
|                                 "cpu": "375m", | ||||
|                                 "ephemeral-storage": "2Gi", | ||||
|                                 "memory": "384Mi" | ||||
|                             }, | ||||
|                             "requests": { | ||||
|                                 "cpu": "250m", | ||||
|                                 "ephemeral-storage": "50Mi", | ||||
|                                 "memory": "256Mi" | ||||
|                             } | ||||
|                         }, | ||||
|                         "securityContext": { | ||||
|                             "allowPrivilegeEscalation": false, | ||||
|                             "capabilities": { | ||||
|                                 "drop": [ | ||||
|                                     "ALL" | ||||
|                                 ] | ||||
|                             }, | ||||
|                             "privileged": false, | ||||
|                             "readOnlyRootFilesystem": true, | ||||
|                             "runAsGroup": 1001, | ||||
|                             "runAsNonRoot": true, | ||||
|                             "runAsUser": 1001, | ||||
|                             "seLinuxOptions": {}, | ||||
|                             "seccompProfile": { | ||||
|                                 "type": "RuntimeDefault" | ||||
|                             } | ||||
|                         }, | ||||
|                         "terminationMessagePath": "/dev/termination-log", | ||||
|                         "terminationMessagePolicy": "File", | ||||
|                         "volumeMounts": [ | ||||
|                             { | ||||
|                                 "mountPath": "/bitnami/mariadb", | ||||
|                                 "name": "data" | ||||
|                             }, | ||||
|                             { | ||||
|                                 "mountPath": "/opt/bitnami/mariadb/conf/my.cnf", | ||||
|                                 "name": "config", | ||||
|                                 "subPath": "my.cnf" | ||||
|                             }, | ||||
|                             { | ||||
|                                 "mountPath": "/tmp", | ||||
|                                 "name": "empty-dir", | ||||
|                                 "subPath": "tmp-dir" | ||||
|                             }, | ||||
|                             { | ||||
|                                 "mountPath": "/opt/bitnami/mariadb/conf", | ||||
|                                 "name": "empty-dir", | ||||
|                                 "subPath": "app-conf-dir" | ||||
|                             }, | ||||
|                             { | ||||
|                                 "mountPath": "/opt/bitnami/mariadb/tmp", | ||||
|                                 "name": "empty-dir", | ||||
|                                 "subPath": "app-tmp-dir" | ||||
|                             }, | ||||
|                             { | ||||
|                                 "mountPath": "/opt/bitnami/mariadb/logs", | ||||
|                                 "name": "empty-dir", | ||||
|                                 "subPath": "app-logs-dir" | ||||
|                             } | ||||
|                         ] | ||||
|                     } | ||||
|                 ], | ||||
|                 "dnsPolicy": "ClusterFirst", | ||||
|                 "initContainers": [ | ||||
|                     { | ||||
|                         "args": [ | ||||
|                             "-ec", | ||||
|                             "#!/bin/bash\n\n. /opt/bitnami/scripts/libfs.sh\n# We copy the logs folder because it has symlinks to stdout and stderr\nif ! is_dir_empty /opt/bitnami/mariadb/logs; then\n  cp -r /opt/bitnami/mariadb/logs /emptydir/app-logs-dir\nfi\n" | ||||
|                         ], | ||||
|                         "command": [ | ||||
|                             "/bin/bash" | ||||
|                         ], | ||||
|                         "image": "docker.io/bitnami/mariadb:11.4.2-debian-12-r2", | ||||
|                         "imagePullPolicy": "IfNotPresent", | ||||
|                         "name": "preserve-logs-symlinks", | ||||
|                         "resources": { | ||||
|                             "limits": { | ||||
|                                 "cpu": "375m", | ||||
|                                 "ephemeral-storage": "2Gi", | ||||
|                                 "memory": "384Mi" | ||||
|                             }, | ||||
|                             "requests": { | ||||
|                                 "cpu": "250m", | ||||
|                                 "ephemeral-storage": "50Mi", | ||||
|                                 "memory": "256Mi" | ||||
|                             } | ||||
|                         }, | ||||
|                         "securityContext": { | ||||
|                             "allowPrivilegeEscalation": false, | ||||
|                             "capabilities": { | ||||
|                                 "drop": [ | ||||
|                                     "ALL" | ||||
|                                 ] | ||||
|                             }, | ||||
|                             "privileged": false, | ||||
|                             "readOnlyRootFilesystem": true, | ||||
|                             "runAsGroup": 1001, | ||||
|                             "runAsNonRoot": true, | ||||
|                             "runAsUser": 1001, | ||||
|                             "seLinuxOptions": {}, | ||||
|                             "seccompProfile": { | ||||
|                                 "type": "RuntimeDefault" | ||||
|                             } | ||||
|                         }, | ||||
|                         "terminationMessagePath": "/dev/termination-log", | ||||
|                         "terminationMessagePolicy": "File", | ||||
|                         "volumeMounts": [ | ||||
|                             { | ||||
|                                 "mountPath": "/emptydir", | ||||
|                                 "name": "empty-dir" | ||||
|                             } | ||||
|                         ] | ||||
|                     } | ||||
|                 ], | ||||
|                 "restartPolicy": "Always", | ||||
|                 "schedulerName": "default-scheduler", | ||||
|                 "securityContext": { | ||||
|                     "fsGroup": 1001, | ||||
|                     "fsGroupChangePolicy": "Always" | ||||
|                 }, | ||||
|                 "serviceAccount": "wordpress-mariadb", | ||||
|                 "serviceAccountName": "wordpress-mariadb", | ||||
|                 "terminationGracePeriodSeconds": 30, | ||||
|                 "volumes": [ | ||||
|                     { | ||||
|                         "emptyDir": {}, | ||||
|                         "name": "empty-dir" | ||||
|                     }, | ||||
|                     { | ||||
|                         "configMap": { | ||||
|                             "defaultMode": 420, | ||||
|                             "name": "wordpress-mariadb" | ||||
|                         }, | ||||
|                         "name": "config" | ||||
|                     } | ||||
|                 ] | ||||
|             } | ||||
|         }, | ||||
|         "updateStrategy": { | ||||
|             "type": "RollingUpdate" | ||||
|         }, | ||||
|         "volumeClaimTemplates": [ | ||||
|             { | ||||
|                 "apiVersion": "v1", | ||||
|                 "kind": "PersistentVolumeClaim", | ||||
|                 "metadata": { | ||||
|                     "creationTimestamp": null, | ||||
|                     "labels": { | ||||
|                         "app.kubernetes.io/component": "primary", | ||||
|                         "app.kubernetes.io/instance": "wordpress", | ||||
|                         "app.kubernetes.io/name": "mariadb" | ||||
|                     }, | ||||
|                     "name": "data" | ||||
|                 }, | ||||
|                 "spec": { | ||||
|                     "accessModes": [ | ||||
|                         "ReadWriteOnce" | ||||
|                     ], | ||||
|                     "resources": { | ||||
|                         "requests": { | ||||
|                             "storage": "8Gi" | ||||
|                         } | ||||
|                     }, | ||||
|                     "volumeMode": "Filesystem" | ||||
|                 }, | ||||
|                 "status": { | ||||
|                     "phase": "Pending" | ||||
|                 } | ||||
|             } | ||||
|         ] | ||||
|     }, | ||||
|     "status": { | ||||
|         "availableReplicas": 1, | ||||
|         "collisionCount": 0, | ||||
|         "currentReplicas": 1, | ||||
|         "currentRevision": "wordpress-mariadb-599b74c5bc", | ||||
|         "observedGeneration": 1, | ||||
|         "readyReplicas": 1, | ||||
|         "replicas": 1, | ||||
|         "updateRevision": "wordpress-mariadb-599b74c5bc", | ||||
|         "updatedReplicas": 1 | ||||
|     } | ||||
| } | ||||
							
								
								
									
										
											BIN
										
									
								
								test/tool/helm.tgz
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										
											BIN
										
									
								
								test/tool/helm.tgz
									
									
									
									
									
										Normal file
									
								
							
										
											Binary file not shown.
										
									
								
							
							
								
								
									
										7
									
								
								test/tool/oc.yml
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										7
									
								
								test/tool/oc.yml
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,7 @@ | ||||
| --- | ||||
|  | ||||
| tools: | ||||
|   - name: kubectl | ||||
|     url: https://dl.k8s.io/release/%s/bin/linux/amd64/kubectl | ||||
|     version: v1.30.3 | ||||
|  | ||||
							
								
								
									
										1
									
								
								test/utils/fichier1
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										1
									
								
								test/utils/fichier1
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1 @@ | ||||
| Fichier1 | ||||
							
								
								
									
										
											BIN
										
									
								
								test/utils/fichier1.tgz
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										
											BIN
										
									
								
								test/utils/fichier1.tgz
									
									
									
									
									
										Normal file
									
								
							
										
											Binary file not shown.
										
									
								
							
							
								
								
									
										3
									
								
								test/versionOc/oc.yml
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										3
									
								
								test/versionOc/oc.yml
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,3 @@ | ||||
| --- | ||||
|  | ||||
| version: 99.0 | ||||
							
								
								
									
										1
									
								
								test/versionOc/oc_error.yml
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										1
									
								
								test/versionOc/oc_error.yml
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1 @@ | ||||
| N'est pas un fichier | ||||
							
								
								
									
										3
									
								
								test/versionOc/offline/latest.yml
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										3
									
								
								test/versionOc/offline/latest.yml
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,3 @@ | ||||
| --- | ||||
|  | ||||
| version: 99.1 | ||||
							
								
								
									
										1
									
								
								test/versionOc/offline/oc_99.1.yml
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										1
									
								
								test/versionOc/offline/oc_99.1.yml
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1 @@ | ||||
| --- | ||||
		Reference in New Issue
	
	Block a user