From 7a5faab14438e83a02821ae37f862b51e3b7d602 Mon Sep 17 00:00:00 2001 From: chenzhixiang Date: Wed, 9 Nov 2022 14:06:06 +0800 Subject: [PATCH] feat: add chartmuseum support for template repo Signed-off-by: chenzhixiang --- build-json-schema.json | 207 ++++++++++++++++++++ build-ui-schema.json | 38 ++++ config.yaml | 7 +- core/cmd/cmd.go | 4 +- core/controller/template/controller_test.go | 151 +++++++------- core/main.go | 5 + pkg/config/templaterepo/template_repo.go | 20 +- pkg/templaterepo/harbor/repo.go | 56 ++++-- pkg/templaterepo/harbor/repo_test.go | 76 +++---- pkg/templaterepo/repo.go | 39 ++-- 10 files changed, 431 insertions(+), 172 deletions(-) create mode 100644 build-json-schema.json create mode 100644 build-ui-schema.json diff --git a/build-json-schema.json b/build-json-schema.json new file mode 100644 index 00000000..3d4e4531 --- /dev/null +++ b/build-json-schema.json @@ -0,0 +1,207 @@ +{ + "type": "object", + "required": [ + "buildType" + ], + "properties": { + "buildType": { + "type": "string", + "title": "构建方式", + "oneOf": [ + { + "enum": [ + "netease-normal" + ], + "title": "音乐常规构建" + }, + { + "enum": [ + "neteaseDockerFile" + ], + "title": "DockerFile构建" + } + ], + "default": "netease-normal" + } + }, + "dependencies": { + "buildType": { + "oneOf": [ + { + "properties": { + "buildType": { + "enum": [ + "netease-normal" + ] + }, + "language": { + "type": "string", + "title": "语言", + "description": "选择目标构建语言", + "enum": [ + "java", + "node", + "golang" + ] + }, + "buildInfo": { + "type": "object", + "title": "", + "properties": { + "buildTool": { + "type": "string", + "title": "构建工具", + "description": "选择云音乐Ant构建或者Shell构建", + "oneOf": [ + { + "enum": [ + "ant" + ], + "title": "ant构建" + } + ] + } + }, + "dependencies": { + "buildTool": { + "oneOf": [ + { + "properties": { + "buildTool": { + "enum": [ + "ant" + ] + }, + "buildxml": { + "type": "string", + "title": "build.xml", + "default": "dsdadsa" + } + } + } + ] + } + } + } + }, + "dependencies": { + "language": { + "oneOf": [ + { + "properties": { + "language": { + "enum": [ + "java" + ] + }, + "environment": { + "type": "string", + "title": "环境", + "description": "目标制品包含的依赖", + "enum": [ + "javaapp", + "tomcat7_jdk8", + "tomcat8_5_jdk8", + "springboot_jdk1_8" + ], + "default": "javaapp" + } + } + }, + { + "properties": { + "language": { + "enum": [ + "golang" + ] + }, + "environment": { + "type": "string", + "title": "环境", + "description": "目标制品包含的依赖", + "enum": [ + "golang-1.6.5" + ], + "default": "golang-1.6.5" + } + } + }, + { + "properties": { + "language": { + "enum": [ + "node" + ] + }, + "environment": { + "type": "string", + "title": "环境", + "description": "目标制品包含的依赖", + "enum": [ + "nodejs-8_11_2" + ], + "default": "nodejs-8_11_2" + } + } + } + ] + } + } + }, + { + "properties": { + "buildType": { + "enum": [ + "neteaseDockerFile" + ] + }, + "dockerfile": { + "type": "object", + "title": "Dockerfile", + "oneOf": [ + { + "title": "dockerfile路径", + "properties": { + "path": { + "type": "string", + "description": "dockerfile文件相对于代码工程中子目录的路径" + } + }, + "required": [ + "path" + ] + }, + { + "title": "dockerfile内容", + "properties": { + "content": { + "type": "string" + } + }, + "required": [ + "content" + ] + } + ] + }, + "buildArgs": { + "type": "array", + "title": "构建参数", + "items": { + "type": "object", + "properties": { + "name": { + "type": "string" + }, + "value": { + "type": "string" + } + } + } + } + } + } + ] + } + } +} diff --git a/build-ui-schema.json b/build-ui-schema.json new file mode 100644 index 00000000..a268bbdd --- /dev/null +++ b/build-ui-schema.json @@ -0,0 +1,38 @@ +{ + "ui:order": [ + "buildType", + "language", + "environment", + "buildInfo", + "dockerfile", + "buildArgs" + ], + "buildInfo": { + "buildxml": { + "ui:widget": "textarea", + "ui:options": { + "rows": 18 + } + }, + "shellScript": { + "ui:widget": "textarea", + "ui:options": { + "rows": 18 + } + } + }, + "dockerfile": { + "content": { + "ui:widget": "textarea", + "ui:options": { + "rows": 18 + } + } + }, + "buildType": { + "ui:widget": "radio", + "ui:options": { + "inline": true + } + } +} diff --git a/config.yaml b/config.yaml index 364db666..06545d50 100644 --- a/config.yaml +++ b/config.yaml @@ -17,12 +17,6 @@ redisConfig: address: dev.redis:6379 password: redis db: 1 -oidcConfig: - userHeader: X-HORIZON-OIDC-USER - fullNameHeader: X-HORIZON-OIDC-FULLNAME - emailHeader: X-HORIZON-OIDC-EMAIL - oidcIDHeader: X-HORIZON-OIDC-ID - oidcTypeHeader: X-HORIZON-OIDC-TYPE gitlabMapper: template: httpURL: https://g.hz.netease.com @@ -39,6 +33,7 @@ gitlabMapper: gitopsRepoConfig: rootGroupPath: music-cloud-native templateRepo: + kind: "harbor" host: "https://harbor.mock.org" repoName: "horizon-template" username: "" diff --git a/core/cmd/cmd.go b/core/cmd/cmd.go index 807530f3..62835023 100644 --- a/core/cmd/cmd.go +++ b/core/cmd/cmd.go @@ -110,7 +110,7 @@ import ( "g.hz.netease.com/horizon/pkg/server/middleware/requestid" "g.hz.netease.com/horizon/pkg/templaterelease/output" templateschemarepo "g.hz.netease.com/horizon/pkg/templaterelease/schema/repo" - templaterepoharbor "g.hz.netease.com/horizon/pkg/templaterepo/harbor" + "g.hz.netease.com/horizon/pkg/templaterepo" userservice "g.hz.netease.com/horizon/pkg/user/service" "g.hz.netease.com/horizon/pkg/util/kube" callbacks "g.hz.netease.com/horizon/pkg/util/ormcallbacks" @@ -280,7 +280,7 @@ func Run(flags *Flags) { panic(err) } - templateRepo, err := templaterepoharbor.NewRepo(coreConfig.TemplateRepo) + templateRepo, err := templaterepo.NewRepo(coreConfig.TemplateRepo) if err != nil { panic(err) } diff --git a/core/controller/template/controller_test.go b/core/controller/template/controller_test.go index 7c4a853a..5722805a 100644 --- a/core/controller/template/controller_test.go +++ b/core/controller/template/controller_test.go @@ -3,6 +3,7 @@ package template import ( "bytes" "context" + "encoding/json" "errors" "fmt" "io/ioutil" @@ -54,7 +55,7 @@ var ( mgr *managerparam.Manager ) -func TestList(t *testing.T) { +func testList(t *testing.T) { createContext() mockCtl := gomock.NewController(t) @@ -250,7 +251,7 @@ func TestList(t *testing.T) { assert.Equal(t, 3, len(templateReleases)) } -func TestListTemplates(t *testing.T) { +func testListTemplates(t *testing.T) { createContext() mockCtl := gomock.NewController(t) @@ -322,9 +323,9 @@ func TestListTemplates(t *testing.T) { assert.Equal(t, tpl2.Name, templates[0].Name) } -func TestGetSchema(t *testing.T) { +func testGetSchema(t *testing.T) { createContext() - charName := templateName + charName := repoConfig.TemplateName mockCtl := gomock.NewController(t) // templateMgr := tmock.NewMockManager(mockCtl) @@ -344,13 +345,14 @@ func TestGetSchema(t *testing.T) { }, } release := &trmodels.TemplateRelease{ - Name: releaseName, - TemplateName: templateName, - ChartVersion: releaseName, + Name: repoConfig.TemplateTag, + TemplateName: repoConfig.TemplateName, + ChartVersion: repoConfig.TemplateTag, ChartName: charName, } templateReleaseMgr.EXPECT().GetByID(gomock.Any(), uint(1)).Return(release, nil) - templateSchemaGetter.EXPECT().GetTemplateSchema(ctx, templateName, releaseName, nil).Return(schemas, nil) + templateSchemaGetter.EXPECT().GetTemplateSchema(ctx, + repoConfig.TemplateName, repoConfig.TemplateTag, nil).Return(schemas, nil) ctl := &controller{ templateSchemaGetter: templateSchemaGetter, @@ -373,9 +375,8 @@ func TestGetSchema(t *testing.T) { } } -func TestCreateTemplate(t *testing.T) { +func testCreateTemplate(t *testing.T) { createContext() - checkSkip(t) ctl := createController(t) var err error @@ -386,19 +387,19 @@ func TestCreateTemplate(t *testing.T) { template, err := ctl.GetTemplate(ctx, 1) assert.Nil(t, err) - assert.Equal(t, templateName, template.Name) - assert.Equal(t, templateRepo, template.Repository) + assert.Equal(t, repoConfig.TemplateName, template.Name) + assert.Equal(t, repoConfig.TemplateRepo, template.Repository) assert.Equal(t, uint(0), template.GroupID) tpl, err := mgr.TemplateMgr.GetByID(ctx, 1) assert.Nil(t, err) - assert.Equal(t, templateName, tpl.Name) + assert.Equal(t, repoConfig.TemplateName, tpl.Name) assert.Equal(t, uint(1), tpl.ID) releases, err := ctl.ListTemplateReleaseByTemplateID(ctx, 1) assert.Nil(t, err) assert.Equal(t, 1, len(releases)) - assert.Equal(t, releaseName, releases[0].Name) + assert.Equal(t, repoConfig.TemplateTag, releases[0].Name) versionPattern := regexp.MustCompile(`^v(\d\.){2}\d-(.+)$`) assert.True(t, versionPattern.MatchString(releases[0].ChartVersion)) @@ -406,9 +407,8 @@ func TestCreateTemplate(t *testing.T) { assert.Nil(t, err) } -func TestCreateTemplateInNonRootGroup(t *testing.T) { +func testCreateTemplateInNonRootGroup(t *testing.T) { createContext() - checkSkip(t) ctl := createController(t) var err error @@ -418,25 +418,24 @@ func TestCreateTemplateInNonRootGroup(t *testing.T) { template, err := ctl.GetTemplate(ctx, 1) assert.Nil(t, err) - assert.Equal(t, templateName, template.Name) - assert.Equal(t, templateRepo, template.Repository) + assert.Equal(t, repoConfig.TemplateName, template.Name) + assert.Equal(t, repoConfig.TemplateRepo, template.Repository) assert.Equal(t, uint(1), template.GroupID) tpl, err := mgr.TemplateMgr.GetByID(ctx, 1) assert.Nil(t, err) - assert.Equal(t, templateName, tpl.Name) + assert.Equal(t, repoConfig.TemplateName, tpl.Name) assert.Equal(t, uint(1), tpl.ID) release, err := mgr.TemplateReleaseManager.GetByID(ctx, 1) assert.Nil(t, err) - assert.Equal(t, releaseName, release.Name) - assert.Equal(t, templateName, release.TemplateName) + assert.Equal(t, repoConfig.TemplateTag, release.Name) + assert.Equal(t, repoConfig.TemplateName, release.TemplateName) assert.Equal(t, tpl.ID, release.Template) } -func TestDeleteTemplate(t *testing.T) { +func testDeleteTemplate(t *testing.T) { createContext() - checkSkip(t) ctl := createController(t) createChart(t, ctl, 0) @@ -463,9 +462,8 @@ func TestDeleteTemplate(t *testing.T) { assert.Nil(t, template) } -func TestGetTemplate(t *testing.T) { +func testGetTemplate(t *testing.T) { createContext() - checkSkip(t) ctl := createController(t) createChart(t, ctl, 0) @@ -476,9 +474,8 @@ func TestGetTemplate(t *testing.T) { assert.NotNil(t, schemas) } -func TestUpdateTemplate(t *testing.T) { +func testUpdateTemplate(t *testing.T) { createContext() - checkSkip(t) ctl := createController(t) ctx = context.WithValue(ctx, hctx.ReleaseSyncToRepo, false) @@ -507,7 +504,7 @@ func TestUpdateTemplate(t *testing.T) { tplRequest = UpdateTemplateRequest{ Name: "javaapp", Description: "hello, world", - Repository: templateRepo, + Repository: repoConfig.TemplateRepo, OnlyOwner: onlyOwnerTrue, } err = ctl.UpdateTemplate(ctx, 1, tplRequest) @@ -515,7 +512,7 @@ func TestUpdateTemplate(t *testing.T) { oldDescription := tplRequest.Description tplRequest.Description = "" - tplRequest.Repository = templateRepo + tplRequest.Repository = repoConfig.TemplateRepo err = ctl.UpdateTemplate(ctx, 1, tplRequest) assert.Nil(t, err) @@ -555,9 +552,8 @@ func TestUpdateTemplate(t *testing.T) { assert.Equal(t, onlyOwnerTrue, release.OnlyOwner) } -func TestListTemplate(t *testing.T) { +func testListTemplate(t *testing.T) { createContext() - checkSkip(t) ctl := createController(t) templates, err := ctl.ListTemplate(ctx) @@ -588,50 +584,44 @@ func TestListTemplate(t *testing.T) { } const ( - EnvHarborHost = "HARBOR_HOST" - EnvHarborUser = "HARBOR_USER" - EnvHarborPasswd = "HARBOR_PASSWD" - EnvHarborRepoName = "HARBOR_REPO_NAME" - EnvTemplateName = "TEMPLATE_NAME" - EnvTemplateTag = "TEMPLATE_TAG" - EnvTemplateRepo = "TEMPLATE_REPO" - EnvTemplateRepoToken = "TEMPLATE_REPO_TOKEN" + EnvTemplateRepos = "TEMPLATE_REPOS" ) -var ( - harborHost string - harborAdmin string - harborPasswd string - harborRepoName string - templateName string - releaseName string - templateRepo string - templateRepoToken string -) - -func TestMain(m *testing.M) { - harborHost = os.Getenv(EnvHarborHost) - harborAdmin = os.Getenv(EnvHarborUser) - harborPasswd = os.Getenv(EnvHarborPasswd) - harborRepoName = os.Getenv(EnvHarborRepoName) - templateName = os.Getenv(EnvTemplateName) - releaseName = os.Getenv(EnvTemplateTag) - templateRepo = os.Getenv(EnvTemplateRepo) - templateRepoToken = os.Getenv(EnvTemplateRepoToken) - - os.Exit(m.Run()) +type RepoConfig struct { + Kind string `json:"kind"` + Host string `json:"host"` + Passwd string `json:"passwd"` + RepoName string `json:"repoName"` + Username string `json:"username"` + TemplateName string `json:"templateName"` + TemplateRepo string `json:"templateRepo"` + TemplateRepoToken string `json:"templateRepoToken"` + TemplateTag string `json:"templateTag"` } -func checkSkip(t *testing.T) { - if harborHost == "" || - harborAdmin == "" || - harborPasswd == "" || - harborRepoName == "" || - templateName == "" || - releaseName == "" || - templateRepo == "" || - templateRepoToken == "" { - t.Skip() +var repoConfig *RepoConfig + +func Test(t *testing.T) { + templateRepos := os.Getenv(EnvTemplateRepos) + + configs := make([]RepoConfig, 0) + + if err := json.Unmarshal([]byte(templateRepos), &configs); err != nil { + panic(err) + } + + for _, cfg := range configs { + repoConfig = &cfg + + t.Run(fmt.Sprintf("TestList_%s", repoConfig.Kind), testList) + t.Run(fmt.Sprintf("TestListTemplates_%s", repoConfig.Kind), testListTemplates) + t.Run(fmt.Sprintf("TestGetSchema_%s", repoConfig.Kind), testGetSchema) + t.Run(fmt.Sprintf("TestCreateTemplate_%s", repoConfig.Kind), testCreateTemplate) + t.Run(fmt.Sprintf("TestCreateTemplateInNonRootGroup_%s", repoConfig.Kind), testCreateTemplateInNonRootGroup) + t.Run(fmt.Sprintf("TestDeleteTemplate_%s", repoConfig.Kind), testDeleteTemplate) + t.Run(fmt.Sprintf("TestGetTemplate_%s", repoConfig.Kind), testGetTemplate) + t.Run(fmt.Sprintf("TestUpdateTemplate_%s", repoConfig.Kind), testUpdateTemplate) + t.Run(fmt.Sprintf("TestListTemplate_%s", repoConfig.Kind), testListTemplate) } } @@ -654,22 +644,23 @@ func createContext() { func createController(t *testing.T) Controller { repo, err := harbor.NewRepo(config.Repo{ - Host: harborHost, - Username: harborAdmin, - Password: harborPasswd, + Kind: repoConfig.Kind, + Host: repoConfig.Host, + Username: repoConfig.Username, + Password: repoConfig.Passwd, Insecure: true, CertFile: "", KeyFile: "", CAFile: "", - RepoName: harborRepoName, + RepoName: repoConfig.RepoName, }) assert.Nil(t, err) getter := reposchema.NewSchemaGetter(context.Background(), repo, mgr) - URL, err := url.Parse(templateRepo) + URL, err := url.Parse(repoConfig.TemplateRepo) assert.Nil(t, err) - gitlabLib, err := gitlab.New(templateRepoToken, + gitlabLib, err := gitlab.New(repoConfig.TemplateRepoToken, fmt.Sprintf("%s://%s", URL.Scheme, URL.Host), "") assert.Nil(t, err) @@ -707,11 +698,11 @@ func createChart(t *testing.T, ctl Controller, groupID uint) { } request := CreateTemplateRequest{ CreateReleaseRequest: CreateReleaseRequest{ - Name: releaseName, + Name: repoConfig.TemplateTag, }, - Name: templateName, + Name: repoConfig.TemplateName, Description: "", - Repository: templateRepo, + Repository: repoConfig.TemplateRepo, } template, err := ctl.CreateTemplate(ctx, groupID, request) assert.Nil(t, err) diff --git a/core/main.go b/core/main.go index 0d650fd5..a1fd97f4 100644 --- a/core/main.go +++ b/core/main.go @@ -4,7 +4,12 @@ import ( _ "net/http/pprof" "g.hz.netease.com/horizon/core/cmd" + + // for image registry _ "g.hz.netease.com/horizon/pkg/cluster/registry/harbor" + + // for template repo + _ "g.hz.netease.com/horizon/pkg/templaterepo/harbor" ) func main() { diff --git a/pkg/config/templaterepo/template_repo.go b/pkg/config/templaterepo/template_repo.go index db48868e..d84792b8 100644 --- a/pkg/config/templaterepo/template_repo.go +++ b/pkg/config/templaterepo/template_repo.go @@ -1,14 +1,14 @@ package templaterepo type Repo struct { - Host string `yaml:"host"` - Username string `yaml:"username"` - Password string `yaml:"password"` - Token string `yaml:"token"` - PlainHTTP bool `yaml:"plainHTTP"` - Insecure bool `yaml:"insecure"` - CertFile string `yaml:"certFile"` - KeyFile string `yaml:"keyFile"` - CAFile string `yaml:"caFile"` - RepoName string `yaml:"repoName"` + Kind string `yaml:"kind"` + Host string `yaml:"host"` + Username string `yaml:"username"` + Password string `yaml:"password"` + Token string `yaml:"token"` + Insecure bool `yaml:"insecure"` + CertFile string `yaml:"certFile"` + KeyFile string `yaml:"keyFile"` + CAFile string `yaml:"caFile"` + RepoName string `yaml:"repoName"` } diff --git a/pkg/templaterepo/harbor/repo.go b/pkg/templaterepo/harbor/repo.go index 2c99215f..7dccb1c0 100644 --- a/pkg/templaterepo/harbor/repo.go +++ b/pkg/templaterepo/harbor/repo.go @@ -9,6 +9,7 @@ import ( "mime/multipart" "net/http" "net/url" + "path" "time" herrors "g.hz.netease.com/horizon/core/errors" @@ -20,6 +21,16 @@ import ( "k8s.io/helm/pkg/tlsutil" ) +const ( + kindHarbor = "harbor" + kindChartMuseum = "chartmuseum" +) + +func init() { + templaterepo.Register(kindHarbor, NewRepo) + templaterepo.Register(kindChartMuseum, NewRepo) +} + type Metadata struct { Name string `json:"name"` Version string `json:"version"` @@ -36,6 +47,7 @@ type Stat struct { } type Repo struct { + prefix string host *url.URL token string username string @@ -60,12 +72,18 @@ func NewRepo(config config.Repo) (templaterepo.TemplateRepo, error) { client := &http.Client{ Transport: &http.Transport{ - TLSClientConfig: tlsConf, + DisableCompression: true, + TLSClientConfig: tlsConf, }, } + prefix := "" + if config.Kind == kindHarbor { + prefix = fmt.Sprintf("chartrepo/%s", config.RepoName) + } return &Repo{ repoName: config.RepoName, + prefix: prefix, host: host, username: config.Username, password: config.Password, @@ -153,16 +171,7 @@ func (h *Repo) ExistChart(name string, version string) (bool, error) { } func (h *Repo) GetChart(name string, version string, lastSyncAt time.Time) (*chart.Chart, error) { - meta, err := h.statChart(name, version) - if err != nil { - return nil, err - } - if len(meta.Urls) < 1 { - return nil, perror.Wrap(herrors.NewErrGetFailed(herrors.HarborChartURL, - "chart url is empty"), "chart url is empty") - } - - resp, err := h.do(http.MethodGet, h.downloadLink(meta.Urls[0]), nil) + resp, err := h.do(http.MethodGet, h.downloadLink(name, version), nil) if err != nil { return nil, err } @@ -246,22 +255,29 @@ func (h *Repo) do(method, url string, body io.Reader, headers ...http.Header) (* return resp, nil } +func (h *Repo) linkWithSchemeAndHost() string { + return fmt.Sprintf("%s://%s", h.host.Scheme, h.host.Host) +} + func (h *Repo) uploadLink() string { - return fmt.Sprintf("%s://%s/api/chartrepo/%s/charts", - h.host.Scheme, h.host.Host, url.PathEscape(h.repoName)) + return fmt.Sprintf("%s/%s?force", + h.linkWithSchemeAndHost(), path.Join("api", h.prefix, "charts")) } func (h *Repo) deleteLink(name, version string) string { - return fmt.Sprintf("%s://%s/api/chartrepo/%s/charts/%s/%s", - h.host.Scheme, h.host.Host, url.PathEscape(h.repoName), url.PathEscape(name), url.PathEscape(version)) + return fmt.Sprintf("%s/%s", + h.linkWithSchemeAndHost(), path.Join("api", h.prefix, "charts", + url.PathEscape(name), url.PathEscape(version))) } func (h *Repo) statLink(name, version string) string { - return fmt.Sprintf("%s://%s/api/chartrepo/%s/charts/%s/%s", - h.host.Scheme, h.host.Host, url.PathEscape(h.repoName), url.PathEscape(name), url.PathEscape(version)) + return fmt.Sprintf("%s/%s", + h.linkWithSchemeAndHost(), path.Join("api", h.prefix, "charts", + url.PathEscape(name), url.PathEscape(version))) } -func (h *Repo) downloadLink(link string) string { - return fmt.Sprintf("%s://%s/chartrepo/%s/%s", - h.host.Scheme, h.host.Host, url.PathEscape(h.repoName), link) +func (h *Repo) downloadLink(name, version string) string { + return fmt.Sprintf("%s/%s/%s-%s.tgz", + h.linkWithSchemeAndHost(), path.Join(h.prefix, "charts"), + url.PathEscape(name), url.PathEscape(version)) } diff --git a/pkg/templaterepo/harbor/repo_test.go b/pkg/templaterepo/harbor/repo_test.go index cf983f67..d3420bdf 100644 --- a/pkg/templaterepo/harbor/repo_test.go +++ b/pkg/templaterepo/harbor/repo_test.go @@ -1,6 +1,8 @@ package harbor import ( + "encoding/json" + "fmt" "os" "testing" "time" @@ -12,86 +14,84 @@ import ( ) const ( - EnvHarborHost = "HARBOR_HOST" - EnvHarborUser = "HARBOR_USER" - EnvHarborPasswd = "HARBOR_PASSWD" - EnvHarborRepoName = "HARBOR_REPO_NAME" + EnvTemplateRepos = "TEMPLATE_REPOS" ) -var ( - harborHost string - harborAdmin string - harborPasswd string - harborRepoName string +type RepoConfig struct { + Kind string `json:"kind"` + Host string `json:"host"` + Passwd string `json:"passwd"` + RepoName string `json:"repoName"` + Username string `json:"username"` + TemplateName string `json:"templateName"` + TemplateRepo string `json:"templateRepo"` + TemplateRepoToken string `json:"templateRepoToken"` + TemplateTag string `json:"templateTag"` +} - templateName = "test" - releaseName = "v1.0.0" -) +var repoConfig *RepoConfig -func TestMain(m *testing.M) { - harborHost = os.Getenv(EnvHarborHost) - harborAdmin = os.Getenv(EnvHarborUser) - harborPasswd = os.Getenv(EnvHarborPasswd) - harborRepoName = os.Getenv(EnvHarborRepoName) +func Test(t *testing.T) { + templateRepos := os.Getenv(EnvTemplateRepos) + configs := make([]RepoConfig, 0) - os.Exit(m.Run()) -} + if err := json.Unmarshal([]byte(templateRepos), &configs); err != nil { + panic(err) + } + + for _, cfg := range configs { + repoConfig = &cfg -func checkSkip(t *testing.T) { - if harborHost == "" || - harborAdmin == "" || - harborPasswd == "" || - harborRepoName == "" { - t.Skip() + t.Run(fmt.Sprintf("TestRepo_%s", repoConfig.Kind), TestRepo) } } func createHarbor(t *testing.T) templaterepo.TemplateRepo { repo, err := NewRepo(config.Repo{ - Host: harborHost, - Username: harborAdmin, - Password: harborPasswd, + Kind: repoConfig.Kind, + Host: repoConfig.Host, + Username: repoConfig.Username, + Password: repoConfig.Passwd, Insecure: true, CertFile: "", KeyFile: "", CAFile: "", - RepoName: harborRepoName, + RepoName: repoConfig.RepoName, }) assert.Nil(t, err) return repo } -func TestHarbor(t *testing.T) { - checkSkip(t) +func TestRepo(t *testing.T) { harbor := createHarbor(t) name := "test" data := []byte("hello, world") c := &chart.Chart{Metadata: &chart.Metadata{}, Files: []*chart.File{{Name: name, Data: data}}} - c.Metadata.Name = templateName - c.Metadata.Version = releaseName + c.Metadata.Name = repoConfig.TemplateName + c.Metadata.Version = repoConfig.TemplateTag err := harbor.UploadChart(c) assert.Nil(t, err) tm := time.Now() - c, err = harbor.GetChart(templateName, releaseName, tm) + c, err = harbor.GetChart(repoConfig.TemplateName, repoConfig.TemplateTag, tm) assert.Nil(t, err) assert.NotNil(t, c) // use cache - c, err = harbor.GetChart(templateName, releaseName, tm) + c, err = harbor.GetChart(repoConfig.TemplateName, repoConfig.TemplateTag, tm) assert.Nil(t, err) assert.NotNil(t, c) - res, err := harbor.ExistChart(templateName, releaseName) + res, err := harbor.ExistChart(repoConfig.TemplateName, repoConfig.TemplateTag) assert.Nil(t, err) assert.Equal(t, true, res) - err = harbor.DeleteChart(templateName, releaseName) + err = harbor.DeleteChart(repoConfig.TemplateName, repoConfig.TemplateTag) assert.Nil(t, err) - _, err = harbor.GetChart(templateName, releaseName, time.Now()) + _, err = harbor.GetChart(repoConfig.TemplateRepo, repoConfig.TemplateTag, time.Now()) assert.NotNil(t, err) } diff --git a/pkg/templaterepo/repo.go b/pkg/templaterepo/repo.go index 473521f7..84c0b332 100644 --- a/pkg/templaterepo/repo.go +++ b/pkg/templaterepo/repo.go @@ -5,6 +5,9 @@ import ( "sync" "time" + herrors "g.hz.netease.com/horizon/core/errors" + "g.hz.netease.com/horizon/pkg/config/templaterepo" + perror "g.hz.netease.com/horizon/pkg/errors" "helm.sh/helm/v3/pkg/chart" ) @@ -12,6 +15,26 @@ const ( cacheKeyFormat = "%s-%s" ) +type Constructor func(repo templaterepo.Repo) (TemplateRepo, error) + +var factory = make(map[string]Constructor) + +func Register(tp string, constructor Constructor) { + factory[tp] = constructor +} + +func NewRepo(config templaterepo.Repo) (TemplateRepo, error) { + fmt.Println(factory) + if constructor, ok := factory[config.Kind]; ok { + repo, err := constructor(config) + if err != nil { + return nil, err + } + return NewRepoWithCache(repo), nil + } + return nil, perror.Wrapf(herrors.ErrParamInvalid, "type (%s) not implement", config.Kind) +} + //go:generate mockgen -source=$GOFILE -destination=../../mock/pkg/templaterepo/mock_repo.go -package=mock_repo type TemplateRepo interface { GetLoc() string @@ -39,22 +62,6 @@ type ChartWithTime struct { lastSyncAt time.Time } -func (r *RepoWithCache) GetLoc() string { - return r.TemplateRepo.GetLoc() -} - -func (r *RepoWithCache) UploadChart(chart *chart.Chart) error { - return r.TemplateRepo.UploadChart(chart) -} - -func (r *RepoWithCache) DeleteChart(name string, version string) error { - return r.TemplateRepo.DeleteChart(name, version) -} - -func (r *RepoWithCache) ExistChart(name string, version string) (bool, error) { - return r.TemplateRepo.ExistChart(name, version) -} - func (r *RepoWithCache) GetChart(name string, version string, lastSyncAt time.Time) (*chart.Chart, error) { r.m.Lock() defer r.m.Unlock()