github.com/jfrog/jfrog-cli-core/v2@v2.51.0/artifactory/commands/replication/template.go (about) 1 package replication 2 3 import ( 4 "encoding/json" 5 "fmt" 6 "os" 7 8 "github.com/c-bata/go-prompt" 9 "github.com/jfrog/jfrog-cli-core/v2/utils/config" 10 "github.com/jfrog/jfrog-cli-core/v2/utils/ioutils" 11 "github.com/jfrog/jfrog-client-go/utils/errorutils" 12 "github.com/jfrog/jfrog-client-go/utils/log" 13 ) 14 15 const ( 16 // Strings for prompt questions 17 SelectConfigKeyMsg = "Select the next configuration key" + ioutils.PressTabMsg 18 19 // Template types 20 TemplateType = "templateType" 21 JobType = "jobType" 22 Create = "create" 23 Pull = "pull" 24 Push = "push" 25 26 // Common replication configuration JSON keys 27 ServerId = "serverId" 28 CronExp = "cronExp" 29 RepoKey = "repoKey" 30 TargetRepoKey = "targetRepoKey" 31 EnableEventReplication = "enableEventReplication" 32 Enabled = "enabled" 33 SyncDeletes = "syncDeletes" 34 SyncProperties = "syncProperties" 35 SyncStatistics = "syncStatistics" 36 // Deprecated 37 PathPrefix = "pathPrefix" 38 IncludePathPrefixPattern = "includePathPrefixPattern" 39 SocketTimeoutMillis = "socketTimeoutMillis" 40 DisableProxy = "disableProxy" 41 ) 42 43 type ReplicationTemplateCommand struct { 44 path string 45 } 46 47 func NewReplicationTemplateCommand() *ReplicationTemplateCommand { 48 return &ReplicationTemplateCommand{} 49 } 50 51 func (rtc *ReplicationTemplateCommand) SetTemplatePath(path string) *ReplicationTemplateCommand { 52 rtc.path = path 53 return rtc 54 } 55 56 func (rtc *ReplicationTemplateCommand) CommandName() string { 57 return "rt_replication_template" 58 } 59 60 func (rtc *ReplicationTemplateCommand) ServerDetails() (*config.ServerDetails, error) { 61 // Since it's a local command, usage won't be reported. 62 return nil, nil 63 } 64 65 func getArtifactoryServerIds() []prompt.Suggest { 66 suggest := make([]prompt.Suggest, 0) 67 if configurations, _ := config.GetAllServersConfigs(); configurations != nil { 68 for _, conf := range configurations { 69 suggest = append(suggest, prompt.Suggest{Text: conf.ServerId}) 70 } 71 } 72 return suggest 73 } 74 75 func (rtc *ReplicationTemplateCommand) Run() (err error) { 76 replicationTemplateQuestionnaire := &ioutils.InteractiveQuestionnaire{ 77 MandatoryQuestionsKeys: []string{JobType, RepoKey}, 78 QuestionsMap: questionMap, 79 } 80 err = replicationTemplateQuestionnaire.Perform() 81 if err != nil { 82 return err 83 } 84 resBytes, err := json.Marshal(replicationTemplateQuestionnaire.AnswersMap) 85 if err != nil { 86 return errorutils.CheckError(err) 87 } 88 if err = os.WriteFile(rtc.path, resBytes, 0644); err != nil { 89 return errorutils.CheckError(err) 90 } 91 log.Info(fmt.Sprintf("Replication creation config template successfully created at %s.", rtc.path)) 92 return nil 93 } 94 95 var questionMap = map[string]ioutils.QuestionInfo{ 96 ioutils.OptionalKey: { 97 Msg: "", 98 PromptPrefix: "Select the next property >", 99 AllowVars: false, 100 Writer: nil, 101 MapKey: "", 102 Callback: ioutils.OptionalKeyCallback, 103 }, 104 TemplateType: { 105 Options: []prompt.Suggest{ 106 {Text: Create, Description: "Template for creating a new replication"}, 107 }, 108 Msg: "", 109 PromptPrefix: "Select the template type >", 110 AllowVars: false, 111 Writer: nil, 112 MapKey: "", 113 Callback: nil, 114 }, 115 JobType: { 116 Options: []prompt.Suggest{ 117 {Text: Pull, Description: "Pull replication"}, 118 {Text: Push, Description: "Push replication"}, 119 }, 120 Msg: "", 121 PromptPrefix: "Select replication job type" + ioutils.PressTabMsg, 122 AllowVars: false, 123 Writer: nil, 124 MapKey: "", 125 Callback: jobTypeCallback, 126 }, 127 RepoKey: { 128 Msg: "", 129 PromptPrefix: "Enter source repo key >", 130 AllowVars: true, 131 Writer: ioutils.WriteStringAnswer, 132 MapKey: RepoKey, 133 Callback: nil, 134 }, 135 TargetRepoKey: { 136 Msg: "", 137 PromptPrefix: "Enter target repo key >", 138 AllowVars: true, 139 Writer: ioutils.WriteStringAnswer, 140 MapKey: TargetRepoKey, 141 Callback: nil, 142 }, 143 ServerId: { 144 Options: getArtifactoryServerIds(), 145 Msg: "", 146 PromptPrefix: "Enter target server id" + ioutils.PressTabMsg, 147 AllowVars: true, 148 Writer: ioutils.WriteStringAnswer, 149 MapKey: ServerId, 150 Callback: nil, 151 }, 152 CronExp: { 153 Msg: "", 154 PromptPrefix: "Enter cron expression for frequency (for example, 0 0 12 * * ? will replicate daily) >", 155 AllowVars: true, 156 Writer: ioutils.WriteStringAnswer, 157 MapKey: CronExp, 158 Callback: nil, 159 }, 160 EnableEventReplication: BoolToStringQuestionInfo, 161 Enabled: BoolToStringQuestionInfo, 162 SyncDeletes: BoolToStringQuestionInfo, 163 SyncProperties: BoolToStringQuestionInfo, 164 SyncStatistics: BoolToStringQuestionInfo, 165 IncludePathPrefixPattern: { 166 Msg: "", 167 PromptPrefix: "Enter include path prefix pattern >", 168 AllowVars: true, 169 Writer: ioutils.WriteStringAnswer, 170 MapKey: IncludePathPrefixPattern, 171 Callback: nil, 172 }, 173 SocketTimeoutMillis: { 174 Msg: "", 175 PromptPrefix: "Enter socket timeout millis >", 176 AllowVars: true, 177 Writer: ioutils.WriteStringAnswer, 178 MapKey: SocketTimeoutMillis, 179 Callback: nil, 180 }, 181 } 182 183 func jobTypeCallback(iq *ioutils.InteractiveQuestionnaire, jobType string) (string, error) { 184 if jobType == Pull { 185 iq.MandatoryQuestionsKeys = append(iq.MandatoryQuestionsKeys, CronExp) 186 } else { 187 iq.MandatoryQuestionsKeys = append(iq.MandatoryQuestionsKeys, TargetRepoKey, ServerId, CronExp) 188 } 189 iq.OptionalKeysSuggests = getAllPossibleOptionalRepoConfKeys() 190 return "", nil 191 } 192 193 func getAllPossibleOptionalRepoConfKeys(values ...string) []prompt.Suggest { 194 optionalKeys := []string{ioutils.SaveAndExit, Enabled, SyncDeletes, SyncProperties, SyncStatistics, PathPrefix, IncludePathPrefixPattern, EnableEventReplication, SocketTimeoutMillis} 195 if len(values) > 0 { 196 optionalKeys = append(optionalKeys, values...) 197 } 198 return ioutils.GetSuggestsFromKeys(optionalKeys, suggestionMap) 199 } 200 201 // Specific writers for repo templates, since all the values in the templates should be written as string. 202 var BoolToStringQuestionInfo = ioutils.QuestionInfo{ 203 Options: ioutils.GetBoolSuggests(), 204 AllowVars: true, 205 Writer: ioutils.WriteStringAnswer, 206 } 207 208 var suggestionMap = map[string]prompt.Suggest{ 209 ioutils.SaveAndExit: {Text: ioutils.SaveAndExit}, 210 ServerId: {Text: ServerId}, 211 RepoKey: {Text: RepoKey}, 212 TargetRepoKey: {Text: TargetRepoKey}, 213 CronExp: {Text: CronExp}, 214 EnableEventReplication: {Text: EnableEventReplication}, 215 Enabled: {Text: Enabled}, 216 SyncDeletes: {Text: SyncDeletes}, 217 SyncProperties: {Text: SyncProperties}, 218 SyncStatistics: {Text: SyncStatistics}, 219 PathPrefix: {Text: PathPrefix}, 220 IncludePathPrefixPattern: {Text: IncludePathPrefixPattern}, 221 SocketTimeoutMillis: {Text: SocketTimeoutMillis}, 222 DisableProxy: {Text: DisableProxy}, 223 }