Skip to content

Commit 55c8609

Browse files
authored
support for bulk repo creation (#94)
1 parent 34d79ad commit 55c8609

File tree

4 files changed

+438
-38
lines changed

4 files changed

+438
-38
lines changed

artifactory/commands/repository/repository.go

Lines changed: 115 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,8 @@ import (
44
"encoding/json"
55
"errors"
66
"fmt"
7+
"github.com/jfrog/gofrog/version"
8+
"github.com/jfrog/jfrog-client-go/utils/log"
79
"strconv"
810
"strings"
911

@@ -36,51 +38,134 @@ func (rc *RepoCommand) TemplatePath() string {
3638
return rc.templatePath
3739
}
3840

41+
type repoCreateUpdateHandler interface {
42+
Execute(repoConfigMaps []map[string]interface{}, servicesManager artifactory.ArtifactoryServicesManager, isUpdate bool) error
43+
}
44+
45+
type (
46+
MultipleRepositoryHandler struct{}
47+
SingleRepositoryHandler struct{}
48+
)
49+
3950
func (rc *RepoCommand) PerformRepoCmd(isUpdate bool) (err error) {
40-
repoConfigMap, err := utils.ConvertTemplateToMap(rc)
51+
configs, err := utils.ConvertTemplateToMaps(rc)
4152
if err != nil {
4253
return err
4354
}
44-
// All the values in the template are strings
45-
// Go over the confMap and write the values with the correct type using the writersMap
46-
for key, value := range repoConfigMap {
47-
if err = utils.ValidateMapEntry(key, value, writersMap); err != nil {
48-
return
49-
}
50-
if err = writersMap[key](&repoConfigMap, key, fmt.Sprint(value)); err != nil {
51-
return
55+
56+
var (
57+
repoConfigMaps []map[string]interface{}
58+
strategy repoCreateUpdateHandler
59+
)
60+
61+
switch configType := configs.(type) {
62+
case []map[string]interface{}:
63+
repoConfigMaps = configType
64+
strategy = &MultipleRepositoryHandler{}
65+
case map[string]interface{}:
66+
repoConfigMaps = []map[string]interface{}{configType}
67+
strategy = &SingleRepositoryHandler{}
68+
default:
69+
return fmt.Errorf("unexpected repository configuration type: %T", configType)
70+
}
71+
72+
var missingKeys []string
73+
for _, repoConfigMap := range repoConfigMaps {
74+
if key, ok := repoConfigMap["key"]; !ok || key == "" {
75+
missingKeys = append(missingKeys, fmt.Sprintf("%v\n", repoConfigMap))
5276
}
5377
}
54-
// Write a JSON with the correct values
55-
content, err := json.Marshal(repoConfigMap)
78+
79+
if len(missingKeys) > 0 {
80+
return fmt.Errorf("'key' is missing in the following configs\n: %v", missingKeys)
81+
}
82+
83+
servicesManager, err := rtUtils.CreateServiceManager(rc.serverDetails, -1, 0, false)
5684
if err != nil {
5785
return err
5886
}
5987

60-
servicesManager, err := rtUtils.CreateServiceManager(rc.serverDetails, -1, 0, false)
88+
return strategy.Execute(repoConfigMaps, servicesManager, isUpdate)
89+
}
90+
91+
func (m *MultipleRepositoryHandler) Execute(repoConfigMaps []map[string]interface{}, servicesManager artifactory.ArtifactoryServicesManager, isUpdate bool) error {
92+
content, err := json.Marshal(repoConfigMaps)
6193
if err != nil {
6294
return err
6395
}
64-
// Rclass and packageType are mandatory keys in our templates
65-
// Using their values we'll pick the suitable handler from one of the handler maps to create/update a repository
66-
var handlerFunc func(servicesManager artifactory.ArtifactoryServicesManager, jsonConfig []byte, isUpdate bool) error
67-
packageType := fmt.Sprint(repoConfigMap[PackageType])
68-
switch repoConfigMap[Rclass] {
69-
case Local:
70-
handlerFunc = localRepoHandlers[packageType]
71-
case Remote:
72-
handlerFunc = remoteRepoHandlers[packageType]
73-
case Virtual:
74-
handlerFunc = virtualRepoHandlers[packageType]
75-
case Federated:
76-
handlerFunc = federatedRepoHandlers[packageType]
77-
default:
78-
return errorutils.CheckErrorf("unsupported rclass: %s", repoConfigMap[Rclass])
96+
return multipleRepoHandler(servicesManager, content, isUpdate)
97+
}
98+
99+
func (s *SingleRepositoryHandler) Execute(repoConfigMaps []map[string]interface{}, servicesManager artifactory.ArtifactoryServicesManager, isUpdate bool) error {
100+
// Go over the confMap and write the values with the correct type using the writersMap
101+
for _, repoConfigMap := range repoConfigMaps {
102+
for key, value := range repoConfigMap {
103+
if err := utils.ValidateMapEntry(key, value, writersMap); err != nil {
104+
return err
105+
}
106+
if err := writersMap[key](&repoConfigMap, key, fmt.Sprint(value)); err != nil {
107+
return err
108+
}
109+
}
110+
111+
content, err := json.Marshal(repoConfigMap)
112+
if err != nil {
113+
return err
114+
}
115+
116+
// Rclass and packageType are mandatory keys in our templates
117+
// Using their values we'll pick the suitable handler from one of the handler maps to create/update a repository
118+
var handlerFunc func(servicesManager artifactory.ArtifactoryServicesManager, jsonConfig []byte, isUpdate bool) error
119+
packageType := fmt.Sprint(repoConfigMap[PackageType])
120+
switch repoConfigMap[Rclass] {
121+
case Local:
122+
handlerFunc = localRepoHandlers[packageType]
123+
case Remote:
124+
handlerFunc = remoteRepoHandlers[packageType]
125+
case Virtual:
126+
handlerFunc = virtualRepoHandlers[packageType]
127+
case Federated:
128+
handlerFunc = federatedRepoHandlers[packageType]
129+
default:
130+
return errorutils.CheckErrorf("unsupported rclass: %s", repoConfigMap[Rclass])
131+
}
132+
if handlerFunc == nil {
133+
return errors.New("unsupported package type: " + packageType)
134+
}
135+
136+
if err := handlerFunc(servicesManager, content, isUpdate); err != nil {
137+
return err
138+
}
79139
}
80-
if handlerFunc == nil {
81-
return errors.New("unsupported package type: " + packageType)
140+
return nil
141+
}
142+
143+
func multipleRepoHandler(servicesManager artifactory.ArtifactoryServicesManager, jsonConfig []byte, isUpdate bool) (err error) {
144+
artifactoryVersion, err := servicesManager.GetVersion()
145+
if err != nil {
146+
return errorutils.CheckErrorf("failed to get Artifactory rtVersion: %s", err.Error())
82147
}
83-
return handlerFunc(servicesManager, content, isUpdate)
148+
rtVersion := version.NewVersion(artifactoryVersion)
149+
if isUpdate {
150+
if !rtVersion.AtLeast("7.104.2") {
151+
return errorutils.CheckErrorf("bulk repository updation is supported from Artifactory rtVersion 7.104.2, current rtVersion: %v", artifactoryVersion)
152+
}
153+
} else {
154+
if !rtVersion.AtLeast("7.84.3") {
155+
return errorutils.CheckErrorf("bulk repository creation is supported from Artifactory rtVersion 7.84.3, current rtVersion: %v", artifactoryVersion)
156+
}
157+
}
158+
159+
log.Debug("creating/updating repositories in batch...")
160+
161+
err = servicesManager.CreateUpdateRepositoriesInBatch(jsonConfig, isUpdate)
162+
if err != nil {
163+
return err
164+
}
165+
166+
log.Info("Successfully created/updated the repositories")
167+
168+
return nil
84169
}
85170

86171
var writersMap = map[string]ioutils.AnswerWriter{

0 commit comments

Comments
 (0)