github.com/jfrog/jfrog-cli-core/v2@v2.51.0/artifactory/commands/replication/create.go (about) 1 package replication 2 3 import ( 4 "encoding/json" 5 "fmt" 6 "strings" 7 8 "github.com/jfrog/jfrog-cli-core/v2/artifactory/commands/utils" 9 rtUtils "github.com/jfrog/jfrog-cli-core/v2/artifactory/utils" 10 "github.com/jfrog/jfrog-cli-core/v2/utils/config" 11 "github.com/jfrog/jfrog-cli-core/v2/utils/coreutils" 12 "github.com/jfrog/jfrog-cli-core/v2/utils/ioutils" 13 "github.com/jfrog/jfrog-client-go/artifactory/services" 14 "github.com/jfrog/jfrog-client-go/utils/errorutils" 15 "github.com/jfrog/jfrog-client-go/utils/io/fileutils" 16 ) 17 18 type ReplicationCreateCommand struct { 19 serverDetails *config.ServerDetails 20 templatePath string 21 vars string 22 } 23 24 func NewReplicationCreateCommand() *ReplicationCreateCommand { 25 return &ReplicationCreateCommand{} 26 } 27 28 func (rcc *ReplicationCreateCommand) SetTemplatePath(path string) *ReplicationCreateCommand { 29 rcc.templatePath = path 30 return rcc 31 } 32 33 func (rcc *ReplicationCreateCommand) SetVars(vars string) *ReplicationCreateCommand { 34 rcc.vars = vars 35 return rcc 36 } 37 38 func (rcc *ReplicationCreateCommand) SetServerDetails(serverDetails *config.ServerDetails) *ReplicationCreateCommand { 39 rcc.serverDetails = serverDetails 40 return rcc 41 } 42 43 func (rcc *ReplicationCreateCommand) ServerDetails() (*config.ServerDetails, error) { 44 return rcc.serverDetails, nil 45 } 46 47 func (rcc *ReplicationCreateCommand) CommandName() string { 48 return "rt_replication_create" 49 } 50 51 func (rcc *ReplicationCreateCommand) Run() (err error) { 52 content, err := fileutils.ReadFile(rcc.templatePath) 53 if errorutils.CheckError(err) != nil { 54 return 55 } 56 // Replace vars string-by-string if needed 57 if len(rcc.vars) > 0 { 58 templateVars := coreutils.SpecVarsStringToMap(rcc.vars) 59 content = coreutils.ReplaceVars(content, templateVars) 60 } 61 // Unmarshal template to a map 62 var replicationConfigMap map[string]interface{} 63 err = json.Unmarshal(content, &replicationConfigMap) 64 if errorutils.CheckError(err) != nil { 65 return 66 } 67 // All the values in the template are strings 68 // Go over the confMap and write the values with the correct type using the writersMap 69 serverId := "" 70 for key, value := range replicationConfigMap { 71 if err = utils.ValidateMapEntry(key, value, writersMap); err != nil { 72 return 73 } 74 if key == "serverId" { 75 serverId = fmt.Sprint(value) 76 } else { 77 err := writersMap[key](&replicationConfigMap, key, fmt.Sprint(value)) 78 if err != nil { 79 return err 80 } 81 } 82 } 83 err = fillMissingDefaultValue(replicationConfigMap) 84 if err != nil { 85 return err 86 } 87 // Write a JSON with the correct values 88 content, err = json.Marshal(replicationConfigMap) 89 if errorutils.CheckError(err) != nil { 90 return 91 } 92 var params services.CreateReplicationParams 93 err = json.Unmarshal(content, ¶ms) 94 if errorutils.CheckError(err) != nil { 95 return 96 } 97 98 setPathPrefixBackwardCompatibility(¶ms) 99 servicesManager, err := rtUtils.CreateServiceManager(rcc.serverDetails, -1, 0, false) 100 if err != nil { 101 return err 102 } 103 // In case 'serverId' is not found, pull replication will be assumed. 104 if serverId != "" { 105 if targetRepo, ok := replicationConfigMap["targetRepoKey"]; ok { 106 if err = updateArtifactoryInfo(¶ms, serverId, fmt.Sprint(targetRepo)); err != nil { 107 return err 108 } 109 } else { 110 return errorutils.CheckErrorf("expected 'targetRepoKey' field in the json template file.") 111 } 112 } 113 return servicesManager.CreateReplication(params) 114 } 115 116 func fillMissingDefaultValue(replicationConfigMap map[string]interface{}) error { 117 if _, ok := replicationConfigMap["socketTimeoutMillis"]; !ok { 118 err := writersMap["socketTimeoutMillis"](&replicationConfigMap, "socketTimeoutMillis", "15000") 119 if err != nil { 120 return err 121 } 122 } 123 if _, ok := replicationConfigMap["syncProperties"]; !ok { 124 err := writersMap["syncProperties"](&replicationConfigMap, "syncProperties", "true") 125 if err != nil { 126 return err 127 } 128 } 129 return nil 130 } 131 132 // Make the pathPrefix parameter equals to the includePathPrefixPattern to support Artifactory < 7.27.4 133 func setPathPrefixBackwardCompatibility(params *services.CreateReplicationParams) { 134 if params.IncludePathPrefixPattern == "" { 135 params.IncludePathPrefixPattern = params.PathPrefix 136 return 137 } 138 if params.PathPrefix == "" { 139 params.PathPrefix = params.IncludePathPrefixPattern 140 } 141 } 142 143 func updateArtifactoryInfo(param *services.CreateReplicationParams, serverId, targetRepo string) error { 144 singleConfig, err := config.GetSpecificConfig(serverId, true, false) 145 if err != nil { 146 return err 147 } 148 param.Url, param.Password, param.Username = strings.TrimSuffix(singleConfig.GetArtifactoryUrl(), "/")+"/"+targetRepo, singleConfig.GetPassword(), singleConfig.GetUser() 149 return nil 150 } 151 152 var writersMap = map[string]ioutils.AnswerWriter{ 153 ServerId: ioutils.WriteStringAnswer, 154 RepoKey: ioutils.WriteStringAnswer, 155 TargetRepoKey: ioutils.WriteStringAnswer, 156 CronExp: ioutils.WriteStringAnswer, 157 EnableEventReplication: ioutils.WriteBoolAnswer, 158 Enabled: ioutils.WriteBoolAnswer, 159 SyncDeletes: ioutils.WriteBoolAnswer, 160 SyncProperties: ioutils.WriteBoolAnswer, 161 SyncStatistics: ioutils.WriteBoolAnswer, 162 PathPrefix: ioutils.WriteStringAnswer, 163 IncludePathPrefixPattern: ioutils.WriteStringAnswer, 164 SocketTimeoutMillis: ioutils.WriteIntAnswer, 165 DisableProxy: ioutils.WriteBoolAnswer, 166 }