From cd7894f4728227fe16486a263c5ad88b07181127 Mon Sep 17 00:00:00 2001 From: Meng JiaFeng Date: Sun, 9 Oct 2022 18:00:09 +0800 Subject: [PATCH] feat: add more ut in plugininstaller Signed-off-by: Meng JiaFeng --- .../pkg/plugin/gitlabcedocker/options_test.go | 1 - internal/pkg/plugininstaller/ci/option.go | 18 +- .../pkg/plugininstaller/ci/option_test.go | 219 ++++++++++++++++++ .../pkg/plugininstaller/ci/validate_test.go | 45 ++++ .../pkg/plugininstaller/common/repo_test.go | 64 +++++ internal/pkg/plugininstaller/common/state.go | 42 ---- internal/pkg/plugininstaller/helm/state.go | 16 +- .../plugininstaller/jenkins/plugins_test.go | 45 +++- .../pkg/plugininstaller/jenkins/validate.go | 4 +- .../plugininstaller/jenkins/validate_test.go | 92 +++++++- pkg/util/helm/state.go | 78 ------- pkg/util/helm/state_test.go | 148 ------------ pkg/util/k8s/state.go | 20 ++ 13 files changed, 499 insertions(+), 293 deletions(-) create mode 100644 internal/pkg/plugininstaller/ci/option_test.go delete mode 100644 internal/pkg/plugininstaller/common/state.go delete mode 100644 pkg/util/helm/state.go delete mode 100644 pkg/util/helm/state_test.go diff --git a/internal/pkg/plugin/gitlabcedocker/options_test.go b/internal/pkg/plugin/gitlabcedocker/options_test.go index de78cb906..9bcd20906 100644 --- a/internal/pkg/plugin/gitlabcedocker/options_test.go +++ b/internal/pkg/plugin/gitlabcedocker/options_test.go @@ -47,6 +47,5 @@ var _ = Describe("Options", func() { Expect(OptsBuild).To(Equal(OptsExpect)) }) - }) }) diff --git a/internal/pkg/plugininstaller/ci/option.go b/internal/pkg/plugininstaller/ci/option.go index e0d3822a8..bba8718cb 100644 --- a/internal/pkg/plugininstaller/ci/option.go +++ b/internal/pkg/plugininstaller/ci/option.go @@ -11,6 +11,7 @@ import ( "github.com/devstream-io/devstream/internal/pkg/plugininstaller" "github.com/devstream-io/devstream/internal/pkg/plugininstaller/common" "github.com/devstream-io/devstream/pkg/util/file" + "github.com/devstream-io/devstream/pkg/util/log" "github.com/devstream-io/devstream/pkg/util/scm/git" "github.com/devstream-io/devstream/pkg/util/template" "github.com/devstream-io/devstream/pkg/util/types" @@ -42,14 +43,17 @@ func (opt *Options) buildGitMap() (gitMap git.GitFileContentMap, err error) { ciConfig := opt.CIConfig switch { case ciConfig.LocalPath != "": - gitMap, err = ciConfig.getFromLocation(opt.ProjectRepo.Repo) + gitMap, err = ciConfig.getFromLocal(opt.ProjectRepo.Repo) case ciConfig.RemoteURL != "": gitMap, err = ciConfig.getFromURL(opt.ProjectRepo.Repo) case ciConfig.Content != "": gitMap, err = ciConfig.getFromContent(opt.ProjectRepo.Repo) } if len(gitMap) == 0 { - return nil, errors.New("can't get valid Jenkinsfile, please check your config") + if err != nil { + log.Warnf("ci get file failed: %+v", err) + } + return nil, errors.New("can't get valid ci file, please check your config") } return gitMap, err } @@ -65,7 +69,7 @@ func (c *CIConfig) getFromURL(appName string) (git.GitFileContentMap, error) { return gitFileMap, nil } -func (c *CIConfig) getFromLocation(appName string) (git.GitFileContentMap, error) { +func (c *CIConfig) getFromLocal(appName string) (git.GitFileContentMap, error) { gitFileMap := make(git.GitFileContentMap) info, err := os.Stat(c.LocalPath) if err != nil { @@ -80,7 +84,7 @@ func (c *CIConfig) getFromLocation(appName string) (git.GitFileContentMap, error } // process file gitFilePath := getCIFilePath(c.Type) - if c.Type == ciGitHubWorkConfigLocation { + if c.Type == ciGitHubType { gitFilePath = filepath.Join(gitFilePath, filepath.Base(c.LocalPath)) } content, err := template.New().FromLocalFile(c.LocalPath).SetDefaultRender(appName, c.Vars).Render() @@ -91,8 +95,12 @@ func (c *CIConfig) getFromLocation(appName string) (git.GitFileContentMap, error return gitFileMap, nil } -func (c *CIConfig) getFromContent(content string) (git.GitFileContentMap, error) { +func (c *CIConfig) getFromContent(appName string) (git.GitFileContentMap, error) { gitFileMap := make(git.GitFileContentMap) + content, err := template.New().FromContent(c.Content).SetDefaultRender(appName, c.Vars).Render() + if err != nil { + return nil, err + } gitFileMap[getCIFilePath(c.Type)] = []byte(content) return gitFileMap, nil } diff --git a/internal/pkg/plugininstaller/ci/option_test.go b/internal/pkg/plugininstaller/ci/option_test.go new file mode 100644 index 000000000..5f4d2f421 --- /dev/null +++ b/internal/pkg/plugininstaller/ci/option_test.go @@ -0,0 +1,219 @@ +package ci + +import ( + "fmt" + "net/http" + "os" + "path" + + . "github.com/onsi/ginkgo/v2" + . "github.com/onsi/gomega" + "github.com/onsi/gomega/ghttp" + + "github.com/devstream-io/devstream/internal/pkg/plugininstaller" + "github.com/devstream-io/devstream/internal/pkg/plugininstaller/common" +) + +var _ = Describe("Options struct", func() { + Context("NewOptions method", func() { + var ( + rawOptions plugininstaller.RawOptions + ) + When("options is valid", func() { + BeforeEach(func() { + rawOptions = plugininstaller.RawOptions{ + "ci": map[string]interface{}{ + "type": "gitlab", + "content": "test", + }, + } + }) + It("should not raise error", func() { + _, err := NewOptions(rawOptions) + Expect(err).Error().ShouldNot(HaveOccurred()) + }) + }) + }) + + Context("buildGitMap method", func() { + var ( + opts *Options + repo *common.Repo + ) + BeforeEach(func() { + opts = &Options{} + repo = &common.Repo{ + Owner: "test", + Repo: "test_repo", + Branch: "test_branch", + RepoType: "gitlab", + } + opts.ProjectRepo = repo + }) + When("all ci config is empty", func() { + BeforeEach(func() { + opts.CIConfig = &CIConfig{} + }) + It("should raise error", func() { + _, err := opts.buildGitMap() + Expect(err).Error().Should(HaveOccurred()) + }) + }) + When("LocalPath field is setted with github ci files", func() { + var ( + localDir, localFile string + testContent []byte + ) + BeforeEach(func() { + tempDir := GinkgoT().TempDir() + localDir = fmt.Sprintf("%s/%s", tempDir, ciGitHubWorkConfigLocation) + err := os.MkdirAll(localDir, os.ModePerm) + Expect(err).Error().ShouldNot(HaveOccurred()) + tempFile, err := os.CreateTemp(localDir, "testFile") + Expect(err).Error().ShouldNot(HaveOccurred()) + localFile = tempFile.Name() + testContent = []byte("_test") + err = os.WriteFile(localFile, testContent, 0755) + Expect(err).Error().ShouldNot(HaveOccurred()) + }) + When("LocalPath is directory", func() { + BeforeEach(func() { + opts.CIConfig = &CIConfig{ + Type: ciGitHubType, + LocalPath: localDir, + } + }) + It("should get all files content", func() { + gitMap, err := opts.buildGitMap() + Expect(err).Error().ShouldNot(HaveOccurred()) + Expect(gitMap).ShouldNot(BeEmpty()) + expectedKey := fmt.Sprintf("%s/%s", ciGitHubWorkConfigLocation, path.Base(localFile)) + v, ok := gitMap[expectedKey] + Expect(ok).Should(BeTrue()) + Expect(v).Should(Equal(testContent)) + }) + }) + When("localPath is file", func() { + BeforeEach(func() { + opts.CIConfig = &CIConfig{ + Type: ciGitHubType, + LocalPath: localFile, + } + }) + It("should get file content", func() { + gitMap, err := opts.buildGitMap() + Expect(err).Error().ShouldNot(HaveOccurred()) + Expect(gitMap).ShouldNot(BeEmpty()) + expectedKey := fmt.Sprintf("%s/%s", ciGitHubWorkConfigLocation, path.Base(localFile)) + v, ok := gitMap[expectedKey] + Expect(ok).Should(BeTrue()) + Expect(v).Should(Equal(testContent)) + }) + }) + }) + When("Content field is setted", func() { + var ( + testContent string + ) + BeforeEach(func() { + testContent = "testJenkins" + opts.CIConfig = &CIConfig{ + Type: ciJenkinsType, + Content: testContent, + } + }) + It("should return gitmap", func() { + gitMap, err := opts.buildGitMap() + Expect(err).Error().ShouldNot(HaveOccurred()) + Expect(len(gitMap)).Should(Equal(1)) + v, ok := gitMap[ciJenkinsConfigLocation] + Expect(ok).Should(BeTrue()) + Expect(v).Should(Equal([]byte(testContent))) + }) + }) + + When("RemoteURL field is setted", func() { + var ( + templateVal string + s *ghttp.Server + ) + BeforeEach(func() { + s = ghttp.NewServer() + testContent := "testGitlabCI [[ .App ]]" + templateVal = "template variable" + s.RouteToHandler("GET", "/", func(w http.ResponseWriter, r *http.Request) { + fmt.Fprint(w, testContent) + }) + opts.CIConfig = &CIConfig{ + Type: ciGitLabType, + RemoteURL: s.URL(), + Vars: map[string]interface{}{ + "App": templateVal, + }, + } + }) + AfterEach(func() { + s.Close() + }) + It("should get gitmap", func() { + gitMap, err := opts.buildGitMap() + Expect(err).Error().ShouldNot(HaveOccurred()) + Expect(len(gitMap)).Should(Equal(1)) + v, ok := gitMap[ciGitLabConfigLocation] + Expect(ok).Should(BeTrue()) + Expect(string(v)).Should(Equal(fmt.Sprintf("testGitlabCI %s", templateVal))) + }) + }) + }) + + Context("FillDefaultValue method", func() { + var ( + defaultOpts, opts *Options + ) + BeforeEach(func() { + opts = &Options{} + defaultCIConfig := &CIConfig{ + Type: ciGitHubType, + RemoteURL: "http://www.test.com", + } + defaultRepo := &common.Repo{ + Owner: "test", + Repo: "test_repo", + Branch: "test_branch", + RepoType: "gitlab", + } + defaultOpts = &Options{ + CIConfig: defaultCIConfig, + ProjectRepo: defaultRepo, + } + }) + When("ci config and repo are all empty", func() { + It("should set default value", func() { + opts.FillDefaultValue(defaultOpts) + Expect(opts.CIConfig).ShouldNot(BeNil()) + Expect(opts.ProjectRepo).ShouldNot(BeNil()) + Expect(opts.CIConfig.RemoteURL).Should(Equal("http://www.test.com")) + Expect(opts.ProjectRepo.Repo).Should(Equal("test_repo")) + }) + }) + When("ci config and repo has some value", func() { + BeforeEach(func() { + opts.CIConfig = &CIConfig{ + RemoteURL: "http://exist.com", + } + opts.ProjectRepo = &common.Repo{ + Branch: "new_branch", + } + }) + It("should update empty value", func() { + opts.FillDefaultValue(defaultOpts) + Expect(opts.CIConfig).ShouldNot(BeNil()) + Expect(opts.ProjectRepo).ShouldNot(BeNil()) + Expect(opts.CIConfig.RemoteURL).Should(Equal("http://exist.com")) + Expect(opts.CIConfig.Type).Should(Equal(ciGitHubType)) + Expect(opts.ProjectRepo.Branch).Should(Equal("new_branch")) + Expect(opts.ProjectRepo.Repo).Should(Equal("test_repo")) + }) + }) + }) +}) diff --git a/internal/pkg/plugininstaller/ci/validate_test.go b/internal/pkg/plugininstaller/ci/validate_test.go index d9e163c84..7da7ecd6e 100644 --- a/internal/pkg/plugininstaller/ci/validate_test.go +++ b/internal/pkg/plugininstaller/ci/validate_test.go @@ -5,6 +5,7 @@ import ( . "github.com/onsi/gomega" "github.com/devstream-io/devstream/internal/pkg/plugininstaller/ci" + "github.com/devstream-io/devstream/internal/pkg/plugininstaller/common" ) var _ = Describe("Validate func", func() { @@ -60,6 +61,23 @@ var _ = Describe("Validate func", func() { _, err = ci.Validate(repoCiConflictOption) Expect(err).Should(HaveOccurred()) + ciTypeNotExistOptions := map[string]any{ + "ci": map[string]any{ + "localPath": "workflows/Jenkinsfile", + "type": "gg", + }, + "projectRepo": map[string]any{ + "baseURL": "http://127.0.0.1:30020", + "branch": "main", + "org": "", + "owner": "test_user", + "repo": "test", + "repoType": "gitlab", + }, + } + _, err = ci.Validate(ciTypeNotExistOptions) + Expect(err).Should(HaveOccurred()) + }) }) When("options is valid", func() { @@ -99,3 +117,30 @@ var _ = Describe("Validate func", func() { }) }) }) + +var _ = Describe("SetDefaultConfig func", func() { + var defaultOpts *ci.Options + BeforeEach(func() { + defaultCIConfig := &ci.CIConfig{ + Type: "github", + RemoteURL: "http://www.test.com", + } + defaultRepo := &common.Repo{ + Owner: "test", + Repo: "test_repo", + Branch: "test_branch", + RepoType: "gitlab", + } + defaultOpts = &ci.Options{ + CIConfig: defaultCIConfig, + ProjectRepo: defaultRepo, + } + }) + It("should work normal", func() { + defaultFunc := ci.SetDefaultConfig(defaultOpts) + rawOptions := map[string]interface{}{} + opts, err := defaultFunc(rawOptions) + Expect(err).Error().ShouldNot(HaveOccurred()) + Expect(len(opts)).Should(Equal(2)) + }) +}) diff --git a/internal/pkg/plugininstaller/common/repo_test.go b/internal/pkg/plugininstaller/common/repo_test.go index f6b766e48..16d3487a2 100644 --- a/internal/pkg/plugininstaller/common/repo_test.go +++ b/internal/pkg/plugininstaller/common/repo_test.go @@ -1,6 +1,8 @@ package common import ( + "fmt" + . "github.com/onsi/ginkgo/v2" . "github.com/onsi/gomega" ) @@ -46,6 +48,68 @@ var _ = Describe("Repo Struct", func() { Expect(owner).Should(Equal(org)) }) }) + + Context("getBranch method", func() { + When("repo is gitlab and branch is empty", func() { + BeforeEach(func() { + repo.Branch = "" + repo.RepoType = "gitlab" + }) + It("should return master branch", func() { + branch := repo.getBranch() + Expect(branch).Should(Equal("master")) + }) + }) + When("repo is github and branch is empty", func() { + BeforeEach(func() { + repo.Branch = "" + repo.RepoType = "github" + }) + It("should return main branch", func() { + branch := repo.getBranch() + Expect(branch).Should(Equal("main")) + }) + }) + }) + + Context("getRepoDownloadURL method", func() { + It("should return url", func() { + githubURL := repo.getRepoDownloadURL() + Expect(githubURL).Should(Equal("https://codeload.github.com/test_org/test_repo/zip/refs/heads/test_branch")) + }) + }) + + Context("BuildURL method", func() { + When("repo is empty", func() { + BeforeEach(func() { + repo.RepoType = "not_exist" + }) + It("should return empty url", func() { + url := repo.BuildURL() + Expect(url).Should(BeEmpty()) + }) + }) + When("repo is github", func() { + BeforeEach(func() { + repo.RepoType = "github" + }) + It("should return github url", func() { + url := repo.BuildURL() + Expect(url).Should(Equal(fmt.Sprintf("https://github.com/%s/%s", repo.Org, repo.Repo))) + }) + }) + When("repo is gitlab", func() { + BeforeEach(func() { + repo.RepoType = "gitlab" + repo.BaseURL = "http://test.com" + repo.Org = "" + }) + It("should return gitlab url", func() { + url := repo.BuildURL() + Expect(url).Should(Equal(fmt.Sprintf("%s/%s/%s.git", repo.BaseURL, repo.Owner, repo.Repo))) + }) + }) + }) }) var _ = Describe("NewRepoFromURL func", func() { diff --git a/internal/pkg/plugininstaller/common/state.go b/internal/pkg/plugininstaller/common/state.go deleted file mode 100644 index 621aa74c9..000000000 --- a/internal/pkg/plugininstaller/common/state.go +++ /dev/null @@ -1,42 +0,0 @@ -package common - -import ( - "github.com/devstream-io/devstream/internal/pkg/statemanager" - "github.com/devstream-io/devstream/pkg/util/helm" - "github.com/devstream-io/devstream/pkg/util/k8s" - "github.com/devstream-io/devstream/pkg/util/log" -) - -func GetPluginAllK8sState(nameSpace string, anFilter, labelFilter map[string]string) (statemanager.ResourceState, error) { - // 1. init kube client - kubeClient, err := k8s.NewClient() - if err != nil { - return nil, err - } - - // 2. get all related resource - allResource, err := kubeClient.GetResourceStatus(nameSpace, anFilter, labelFilter) - if err != nil { - log.Debugf("helm status: get status failed: %s", err) - return nil, err - } - - // 3. transfer resources status to workflows - state := &helm.InstanceState{} - for _, dep := range allResource.Deployment { - state.Workflows.AddDeployment(dep.Name, dep.Ready) - } - for _, sts := range allResource.StatefulSet { - state.Workflows.AddStatefulset(sts.Name, sts.Ready) - } - for _, ds := range allResource.DaemonSet { - state.Workflows.AddDaemonset(ds.Name, ds.Ready) - } - - retMap, err := state.ToStringInterfaceMap() - if err != nil { - return nil, err - } - log.Debugf("Return map: %v.", retMap) - return retMap, nil -} diff --git a/internal/pkg/plugininstaller/helm/state.go b/internal/pkg/plugininstaller/helm/state.go index 28d126baf..e4c69a343 100644 --- a/internal/pkg/plugininstaller/helm/state.go +++ b/internal/pkg/plugininstaller/helm/state.go @@ -2,9 +2,10 @@ package helm import ( "github.com/devstream-io/devstream/internal/pkg/plugininstaller" - "github.com/devstream-io/devstream/internal/pkg/plugininstaller/common" "github.com/devstream-io/devstream/internal/pkg/statemanager" "github.com/devstream-io/devstream/pkg/util/helm" + "github.com/devstream-io/devstream/pkg/util/k8s" + "github.com/devstream-io/devstream/pkg/util/log" ) // GetPluginAllState will get the State of k8s Deployment, DaemonSet and StatefulSet resources @@ -14,9 +15,20 @@ func GetPluginAllState(options plugininstaller.RawOptions) (statemanager.Resourc return nil, err } + kubeClient, err := k8s.NewClient() + if err != nil { + log.Debugf("helm init k8s client to get state failed: %+v", err) + return nil, err + } + anFilter := map[string]string{ helm.GetAnnotationName(): opts.GetReleaseName(), } labelFilter := map[string]string{} - return common.GetPluginAllK8sState(opts.GetNamespace(), anFilter, labelFilter) + allResourceState, err := kubeClient.GetResourceStatus(opts.GetNamespace(), anFilter, labelFilter) + if err != nil { + log.Debugf("helm get resource state failed: %+v", err) + return nil, err + } + return allResourceState.ToStringInterfaceMap() } diff --git a/internal/pkg/plugininstaller/jenkins/plugins_test.go b/internal/pkg/plugininstaller/jenkins/plugins_test.go index 9a81400c9..5b92c2d53 100644 --- a/internal/pkg/plugininstaller/jenkins/plugins_test.go +++ b/internal/pkg/plugininstaller/jenkins/plugins_test.go @@ -1,6 +1,8 @@ package jenkins import ( + "errors" + . "github.com/onsi/ginkgo/v2" . "github.com/onsi/gomega" @@ -12,11 +14,24 @@ type mockSuccessPluginsConfig struct{} func (m *mockSuccessPluginsConfig) GetDependentPlugins() (plugins []*jenkins.JenkinsPlugin) { return } -func (m *mockSuccessPluginsConfig) PreConfig(jenkins.JenkinsAPI) (config *jenkins.RepoCascConfig, err error) { - return +func (m *mockSuccessPluginsConfig) PreConfig(jenkins.JenkinsAPI) (*jenkins.RepoCascConfig, error) { + return &jenkins.RepoCascConfig{ + RepoType: "gitlab", + CredentialID: "test", + }, nil } func (m *mockSuccessPluginsConfig) UpdateJenkinsFileRenderVars(*jenkins.JenkinsFileRenderInfo) {} +type mockErrorPluginsConfig struct{} + +func (m *mockErrorPluginsConfig) GetDependentPlugins() (plugins []*jenkins.JenkinsPlugin) { + return +} +func (m *mockErrorPluginsConfig) PreConfig(jenkins.JenkinsAPI) (*jenkins.RepoCascConfig, error) { + return nil, errors.New("test_error") +} +func (m *mockErrorPluginsConfig) UpdateJenkinsFileRenderVars(*jenkins.JenkinsFileRenderInfo) {} + var _ = Describe("installPlugins func", func() { var ( mockClient *mockSuccessJenkinsClient @@ -36,14 +51,26 @@ var _ = Describe("preConfigPlugins func", func() { var ( mockClient *mockSuccessJenkinsClient s *mockSuccessPluginsConfig + f *mockErrorPluginsConfig ) - BeforeEach(func() { - mockClient = &mockSuccessJenkinsClient{} - s = &mockSuccessPluginsConfig{} + When("cascConfig is valid", func() { + BeforeEach(func() { + mockClient = &mockSuccessJenkinsClient{} + s = &mockSuccessPluginsConfig{} + }) + It("should work normal", func() { + err := preConfigPlugins(mockClient, []pluginConfigAPI{s}) + Expect(err).Error().ShouldNot(HaveOccurred()) + }) }) - It("should work normal", func() { - err := preConfigPlugins(mockClient, []pluginConfigAPI{s}) - Expect(err).Error().ShouldNot(HaveOccurred()) + When("cascConfig is not valid", func() { + BeforeEach(func() { + mockClient = &mockSuccessJenkinsClient{} + f = &mockErrorPluginsConfig{} + }) + It("should return error", func() { + err := preConfigPlugins(mockClient, []pluginConfigAPI{f}) + Expect(err).Error().Should(HaveOccurred()) + }) }) - }) diff --git a/internal/pkg/plugininstaller/jenkins/validate.go b/internal/pkg/plugininstaller/jenkins/validate.go index 993407abc..cc2ffaf19 100644 --- a/internal/pkg/plugininstaller/jenkins/validate.go +++ b/internal/pkg/plugininstaller/jenkins/validate.go @@ -97,15 +97,13 @@ func ValidateJobConfig(options plugininstaller.RawOptions) (plugininstaller.RawO if os.Getenv(github.TokenEnvKey) == "" { return nil, fmt.Errorf("jenkins-pipeline github should set env %s", github.TokenEnvKey) } - default: - return nil, fmt.Errorf("jenkins-pipeline doesn't support repo type %s", opts.ProjectRepo.RepoType) } // check jenkins job name if strings.Contains(opts.Pipeline.JobName, "/") { strs := strings.Split(opts.Pipeline.JobName, "/") if len(strs) != 2 || len(strs[0]) == 0 || len(strs[1]) == 0 { - return nil, fmt.Errorf("jobName illegal: %s", opts.Pipeline.JobName) + return nil, fmt.Errorf("jenkins jobName illegal: %s", opts.Pipeline.JobName) } } diff --git a/internal/pkg/plugininstaller/jenkins/validate_test.go b/internal/pkg/plugininstaller/jenkins/validate_test.go index 8ebeb9071..cd53f6e7e 100644 --- a/internal/pkg/plugininstaller/jenkins/validate_test.go +++ b/internal/pkg/plugininstaller/jenkins/validate_test.go @@ -1,8 +1,11 @@ package jenkins import ( + "fmt" "os" + "github.com/devstream-io/devstream/pkg/util/scm/github" + "github.com/devstream-io/devstream/pkg/util/scm/gitlab" . "github.com/onsi/ginkgo/v2" . "github.com/onsi/gomega" ) @@ -79,14 +82,42 @@ var _ = Describe("generateRandomSecretToken func", func() { var _ = Describe("ValidateJobConfig func", func() { var ( - jenkinsUser, jenkinsURL, jenkinsFilePath, projectURL string - options map[string]interface{} + githubToken, gitlabToken string + ) + BeforeEach(func() { + githubToken = os.Getenv(github.TokenEnvKey) + gitlabToken = os.Getenv(gitlab.TokenEnvKey) + err := os.Unsetenv(github.TokenEnvKey) + Expect(err).Error().ShouldNot(HaveOccurred()) + err = os.Unsetenv(gitlab.TokenEnvKey) + Expect(err).Error().ShouldNot(HaveOccurred()) + }) + AfterEach(func() { + if githubToken != "" { + os.Setenv(github.TokenEnvKey, githubToken) + } + if gitlabToken != "" { + os.Setenv(gitlab.TokenEnvKey, gitlabToken) + } + }) + var ( + jenkinsUser, jenkinsURL, jenkinsFilePath, projectURL, repoType string + options, projectRepo, pipeline map[string]interface{} ) BeforeEach(func() { jenkinsUser = "test" jenkinsURL = "http://test.jenkins.com/" projectURL = "https://test.gitlab.com/test/test_project" jenkinsFilePath = "http://raw.content.com/Jenkinsfile" + pipeline = map[string]interface{}{ + "jenkinsfilePath": jenkinsFilePath, + "jobName": "test", + } + projectRepo = map[string]interface{}{ + "owner": "test_owner", + "org": "test_org", + "repo": "test_repo", + } options = map[string]interface{}{ "jenkins": map[string]interface{}{ "url": jenkinsURL, @@ -95,9 +126,8 @@ var _ = Describe("ValidateJobConfig func", func() { "scm": map[string]interface{}{ "cloneURL": projectURL, }, - "pipeline": map[string]interface{}{ - "jenkinsfilePath": jenkinsFilePath, - }, + "pipeline": pipeline, + "projectRepo": projectRepo, } }) When("Input field miss", func() { @@ -117,4 +147,56 @@ var _ = Describe("ValidateJobConfig func", func() { Expect(err).Error().Should(HaveOccurred()) }) }) + When("repo type is gitlab and gitlab env is not configured", func() { + BeforeEach(func() { + repoType = "gitlab" + projectRepo["repoType"] = repoType + options["projectRepo"] = projectRepo + }) + It("should return error", func() { + _, err := ValidateJobConfig(options) + Expect(err).Error().Should(HaveOccurred()) + Expect(err.Error()).Should(Equal(fmt.Sprintf("jenkins-pipeline gitlab should set env %s", gitlab.TokenEnvKey))) + }) + }) + When("repo type is github and github env is not configured", func() { + BeforeEach(func() { + repoType = "github" + projectRepo["repoType"] = repoType + options["projectRepo"] = projectRepo + }) + It("should return error", func() { + _, err := ValidateJobConfig(options) + Expect(err).Error().Should(HaveOccurred()) + Expect(err.Error()).Should(Equal(fmt.Sprintf("jenkins-pipeline github should set env %s", github.TokenEnvKey))) + }) + }) + When("jobName is not valid", func() { + BeforeEach(func() { + pipeline["jobName"] = "folder/not_exist/jobName" + options["pipeline"] = pipeline + repoType = "github" + projectRepo["repoType"] = repoType + options["projectRepo"] = projectRepo + os.Setenv(github.TokenEnvKey, "test_env") + }) + It("should return error", func() { + _, err := ValidateJobConfig(options) + Expect(err).Error().Should(HaveOccurred()) + Expect(err.Error()).Should(Equal(fmt.Sprintf("jenkins jobName illegal: %s", pipeline["jobName"]))) + }) + }) + When("all params is right", func() { + BeforeEach(func() { + options["pipeline"] = pipeline + repoType = "github" + projectRepo["repoType"] = repoType + options["projectRepo"] = projectRepo + os.Setenv(github.TokenEnvKey, "test_env") + }) + It("should return nil error", func() { + _, err := ValidateJobConfig(options) + Expect(err).Error().ShouldNot(HaveOccurred()) + }) + }) }) diff --git a/pkg/util/helm/state.go b/pkg/util/helm/state.go deleted file mode 100644 index 2ea66ac4d..000000000 --- a/pkg/util/helm/state.go +++ /dev/null @@ -1,78 +0,0 @@ -package helm - -import ( - "bytes" - - "gopkg.in/yaml.v3" -) - -type InstanceState struct { - Workflows Workflows -} - -func (is *InstanceState) ToStringInterfaceMap() (map[string]interface{}, error) { - var buf bytes.Buffer - encoder := yaml.NewEncoder(&buf) - defer encoder.Close() - encoder.SetIndent(2) - err := encoder.Encode(&is.Workflows) - if err != nil { - return nil, err - } - wfs := buf.String() - - return map[string]interface{}{ - "workflows": wfs, - }, nil -} - -type Workflows struct { - Deployments []Deployment `yaml:"deployments,omitempty"` - Daemonsets []Daemonset `yaml:"daemonsets,omitempty"` - Statefulsets []Statefulset `yaml:"statefulsets,omitempty"` -} - -func (w *Workflows) AddDeployment(name string, ready bool) { - if w.Deployments == nil { - w.Deployments = make([]Deployment, 0) - } - w.Deployments = append(w.Deployments, Deployment{ - Name: name, - Ready: ready, - }) -} - -func (w *Workflows) AddDaemonset(name string, ready bool) { - if w.Daemonsets == nil { - w.Daemonsets = make([]Daemonset, 0) - } - w.Daemonsets = append(w.Daemonsets, Daemonset{ - Name: name, - Ready: ready, - }) -} - -func (w *Workflows) AddStatefulset(name string, ready bool) { - if w.Statefulsets == nil { - w.Statefulsets = make([]Statefulset, 0) - } - w.Statefulsets = append(w.Statefulsets, Statefulset{ - Name: name, - Ready: ready, - }) -} - -type Deployment struct { - Name string `yaml:"name"` - Ready bool `yaml:"ready"` -} - -type Daemonset struct { - Name string `yaml:"name"` - Ready bool `yaml:"ready"` -} - -type Statefulset struct { - Name string `yaml:"name"` - Ready bool `yaml:"ready"` -} diff --git a/pkg/util/helm/state_test.go b/pkg/util/helm/state_test.go deleted file mode 100644 index 117f4937b..000000000 --- a/pkg/util/helm/state_test.go +++ /dev/null @@ -1,148 +0,0 @@ -package helm - -import ( - "bytes" - "testing" - - "github.com/stretchr/testify/require" - - "gopkg.in/yaml.v3" -) - -func TestInstanceState_ToStringInterfaceMap(t *testing.T) { - wf := Workflows{ - Deployments: []Deployment{{"Deployment", true}, {"Deployment2", false}}, - Daemonsets: []Daemonset{{"Daemonset", true}}, - Statefulsets: []Statefulset{{"Statefulset", true}}, - } - var buf bytes.Buffer - encoder := yaml.NewEncoder(&buf) - defer encoder.Close() - encoder.SetIndent(2) - err := encoder.Encode(&wf) - require.NoError(t, err) - - wfs := buf.String() - - tests := []struct { - name string - Workflows Workflows - want map[string]interface{} - }{ - // TODO: Add test cases. - {"base", wf, map[string]interface{}{"workflows": wfs}}, - // {"base encode error", nil, map[string]interface{}{"workflows": struct{}{}}}, - } - for _, tt := range tests { - t.Run(tt.name, func(t *testing.T) { - is := &InstanceState{ - Workflows: tt.Workflows, - } - got, err := is.ToStringInterfaceMap() - require.NoErrorf(t, err, "InstanceState.ToStringInterfaceMap() error = %v", err) - require.Equalf(t, got, tt.want, "InstanceState.ToStringInterfaceMap() = %v, want %v", got, tt.want) - }) - } -} - -func TestWorkflows_AddDeployment(t *testing.T) { - one, two := Deployment{"Deployment", true}, Deployment{"Deployment2", false} - want, want2 := []Deployment{one}, []Deployment{one, two} - wf := Workflows{ - Deployments: []Deployment{}, - Daemonsets: []Daemonset{}, - Statefulsets: []Statefulset{}, - } - wf2 := Workflows{ - Deployments: []Deployment{one}, - Daemonsets: []Daemonset{}, - Statefulsets: []Statefulset{}, - } - var wf3 Workflows - tests := []struct { - name string - wfs Workflows - element Deployment - want []Deployment - }{ - // TODO: Add test cases. - {"base empty", wf, one, want}, - {"base not empty", wf2, two, want2}, - {"base nil", wf3, one, want}, - } - for _, tt := range tests { - t.Run(tt.name, func(t *testing.T) { - tt.wfs.AddDeployment(tt.element.Name, tt.element.Ready) - got, want := tt.wfs.Deployments, tt.want - require.Equalf(t, got, want, "Workflows.AddDeployment() = %v, want %v", got, tt.want) - }) - } -} - -func TestWorkflows_AddDaemonset(t *testing.T) { - one, two := Daemonset{"Daemonset", true}, Daemonset{"Daemonset2", false} - want, want2 := []Daemonset{one}, []Daemonset{one, two} - wf := Workflows{ - Deployments: []Deployment{}, - Daemonsets: []Daemonset{}, - Statefulsets: []Statefulset{}, - } - wf2 := Workflows{ - Deployments: []Deployment{}, - Daemonsets: []Daemonset{one}, - Statefulsets: []Statefulset{}, - } - var wf3 Workflows - tests := []struct { - name string - wfs Workflows - element Daemonset - want []Daemonset - }{ - // TODO: Add test cases. - {"base empty", wf, one, want}, - {"base not empty", wf2, two, want2}, - {"base nil", wf3, one, want}, - } - for _, tt := range tests { - t.Run(tt.name, func(t *testing.T) { - tt.wfs.AddDaemonset(tt.element.Name, tt.element.Ready) - got, want := tt.wfs.Daemonsets, tt.want - require.Equalf(t, got, want, "Workflows.AddDaemonSet() = %v, want %v", got, tt.want) - }) - } -} - -func TestWorkflows_AddStatefulset(t *testing.T) { - one, two := Statefulset{"Statefulset", true}, Statefulset{"Statefulset", false} - want, want2 := []Statefulset{one}, []Statefulset{one, two} - wf := Workflows{ - Deployments: []Deployment{}, - Daemonsets: []Daemonset{}, - Statefulsets: []Statefulset{}, - } - wf2 := Workflows{ - Deployments: []Deployment{}, - Daemonsets: []Daemonset{}, - Statefulsets: []Statefulset{one}, - } - var wf3 Workflows - tests := []struct { - name string - wfs Workflows - element Statefulset - want []Statefulset - }{ - // TODO: Add test cases. - {"base empty", wf, one, want}, - {"base not empty", wf2, two, want2}, - {"base nil", wf3, one, want}, - } - for _, tt := range tests { - t.Run(tt.name, func(t *testing.T) { - tt.wfs.AddStatefulset(tt.element.Name, tt.element.Ready) - got, want := tt.wfs.Statefulsets, tt.want - require.Equalf(t, got, want, "Workflows.AddDaemonSet() = %v, want %v", got, tt.want) - }) - } -} diff --git a/pkg/util/k8s/state.go b/pkg/util/k8s/state.go index 32a6e1b43..5214142b3 100644 --- a/pkg/util/k8s/state.go +++ b/pkg/util/k8s/state.go @@ -1,6 +1,10 @@ package k8s import ( + "bytes" + + "gopkg.in/yaml.v3" + "github.com/devstream-io/devstream/pkg/util/log" ) @@ -88,3 +92,19 @@ func filterByAnnotation(anInfo map[string]string, anFilter map[string]string) bo } return true } + +func (s *AllResourceStatus) ToStringInterfaceMap() (map[string]interface{}, error) { + var buf bytes.Buffer + encoder := yaml.NewEncoder(&buf) + defer encoder.Close() + encoder.SetIndent(2) + err := encoder.Encode(s) + if err != nil { + return nil, err + } + wfs := buf.String() + + return map[string]interface{}{ + "workflows": wfs, + }, nil +}