github.com/jfrog/jfrog-cli-core/v2@v2.51.0/artifactory/commands/repository/template.go (about) 1 package repository 2 3 import ( 4 "encoding/json" 5 "errors" 6 "fmt" 7 "os" 8 "strings" 9 10 "github.com/c-bata/go-prompt" 11 "github.com/jfrog/jfrog-cli-core/v2/artifactory/commands/utils" 12 "github.com/jfrog/jfrog-cli-core/v2/utils/config" 13 "github.com/jfrog/jfrog-cli-core/v2/utils/ioutils" 14 "github.com/jfrog/jfrog-client-go/utils/errorutils" 15 "github.com/jfrog/jfrog-client-go/utils/log" 16 ) 17 18 type RepoTemplateCommand struct { 19 path string 20 } 21 22 const ( 23 // Strings for prompt questions 24 SelectConfigKeyMsg = "Select the next configuration key" + ioutils.PressTabMsg 25 26 TemplateType = "templateType" 27 Create = "create" 28 Update = "update" 29 30 MandatoryUrl = "mandatoryUrl" 31 32 // Common repository configuration JSON keys 33 Key = "key" 34 Rclass = "rclass" 35 PackageType = "packageType" 36 Description = "description" 37 Notes = "notes" 38 IncludePatterns = "includesPattern" 39 ExcludePatterns = "excludesPattern" 40 RepoLayoutRef = "repoLayoutRef" 41 ProjectKey = "projectKey" 42 Environment = "environment" 43 44 // Mutual local and remote repository configuration JSON keys 45 HandleReleases = "handleReleases" 46 HandleSnapshots = "handleSnapshots" 47 MaxUniqueSnapshots = "maxUniqueSnapshots" 48 SuppressPomConsistencyChecks = "suppressPomConsistencyChecks" 49 BlackedOut = "blackedOut" 50 XrayIndex = "xrayIndex" 51 PropertySets = "propertySets" 52 DownloadRedirect = "downloadRedirect" 53 BlockPushingSchema1 = "blockPushingSchema1" 54 55 // Mutual local and virtual repository configuration JSON keys 56 DebianTrivialLayout = "debianTrivialLayout" 57 OptionalIndexCompressionFormats = "optionalIndexCompressionFormats" 58 PrimaryKeyPairRef = "primaryKeyPairRef" 59 60 // Mutual remote and virtual repository configuration JSON keys 61 ExternalDependenciesEnabled = "externalDependenciesEnabled" 62 ExternalDependenciesPatterns = "externalDependenciesPatterns" 63 64 // Unique local repository configuration JSON keys 65 ChecksumPolicyType = "checksumPolicyType" 66 MaxUniqueTags = "maxUniqueTags" 67 SnapshotVersionBehavior = "snapshotVersionBehavior" 68 ArchiveBrowsingEnabled = "archiveBrowsingEnabled" 69 CalculateYumMetadata = "calculateYumMetadata" 70 YumRootDepth = "yumRootDepth" 71 DockerApiVersion = "dockerApiVersion" 72 EnableFileListsIndexing = "enableFileListsIndexing" 73 ForceNugetAuthentication = "forceNugetAuthentication" 74 75 // Unique remote repository configuration JSON keys 76 Url = "url" 77 Username = "username" 78 Password = "password" 79 Proxy = "proxy" 80 RemoteRepoChecksumPolicyType = "remoteRepoChecksumPolicyType" 81 HardFail = "hardFail" 82 Offline = "offline" 83 StoreArtifactsLocally = "storeArtifactsLocally" 84 SocketTimeoutMillis = "socketTimeoutMillis" 85 LocalAddress = "localAddress" 86 RetrievalCachePeriodSecs = "retrievalCachePeriodSecs" 87 FailedRetrievalCachePeriodSecs = "failedRetrievalCachePeriodSecs" 88 MissedRetrievalCachePeriodSecs = "missedRetrievalCachePeriodSecs" 89 UnusedArtifactsCleanupEnabled = "unusedArtifactsCleanupEnabled" 90 UnusedArtifactsCleanupPeriodHours = "unusedArtifactsCleanupPeriodHours" 91 AssumedOfflinePeriodSecs = "assumedOfflinePeriodSecs" 92 FetchJarsEagerly = "fetchJarsEagerly" 93 FetchSourcesEagerly = "fetchSourcesEagerly" 94 RejectInvalidJars = "rejectInvalidJars" 95 ShareConfiguration = "shareConfiguration" 96 SynchronizeProperties = "synchronizeProperties" 97 BlockMismatchingMimeTypes = "blockMismatchingMimeTypes" 98 AllowAnyHostAuth = "allowAnyHostAuth" 99 EnableCookieManagement = "enableCookieManagement" 100 BowerRegistryUrl = "bowerRegistryUrl" 101 ComposerRegistryUrl = "composerRegistryUrl" 102 PyPIRegistryUrl = "pyPIRegistryUrl" 103 VcsType = "vcsType" 104 VcsGitProvider = "vcsGitProvider" 105 VcsGitDownloadUrl = "vcsGitDownloadUrl" 106 BypassHeadRequests = "bypassHeadRequests" 107 ClientTlsCertificate = "clientTlsCertificate" 108 FeedContextPath = "feedContextPath" 109 DownloadContextPath = "downloadContextPath" 110 V3FeedUrl = "v3FeedUrl" 111 ContentSynchronisation = "contentSynchronisation" 112 ListRemoteFolderItems = "listRemoteFolderItems" 113 EnableTokenAuthentication = "enableTokenAuthentication" 114 PodsSpecsRepoUrl = "podsSpecsRepoUrl" 115 116 // Unique virtual repository configuration JSON keys 117 Repositories = "repositories" 118 ArtifactoryRequestsCanRetrieveRemoteArtifacts = "artifactoryRequestsCanRetrieveRemoteArtifacts" 119 KeyPair = "keyPair" 120 PomRepositoryReferencesCleanupPolicy = "pomRepositoryReferencesCleanupPolicy" 121 DefaultDeploymentRepo = "defaultDeploymentRepo" 122 ForceMavenAuthentication = "forceMavenAuthentication" 123 ExternalDependenciesRemoteRepo = "externalDependenciesRemoteRepo" 124 125 // rclasses 126 Local = "local" 127 Remote = "remote" 128 Virtual = "virtual" 129 Federated = "federated" 130 131 // PackageTypes 132 Generic = "generic" 133 Maven = "maven" 134 Gradle = "gradle" 135 Ivy = "ivy" 136 Sbt = "sbt" 137 Helm = "helm" 138 Cocoapods = "cocoapods" 139 Opkg = "opkg" 140 Rpm = "rpm" 141 Nuget = "nuget" 142 Cran = "cran" 143 Gems = "gems" 144 Npm = "npm" 145 Bower = "bower" 146 Debian = "debian" 147 Composer = "composer" 148 Pypi = "pypi" 149 Docker = "docker" 150 Vagrant = "vagrant" 151 Gitlfs = "gitlfs" 152 Go = "go" 153 Yum = "yum" 154 Conan = "conan" 155 Chef = "chef" 156 Puppet = "puppet" 157 Vcs = "vcs" 158 Alpine = "alpine" 159 Conda = "conda" 160 P2 = "p2" 161 Swift = "swift" 162 Terraform = "terraform" 163 Cargo = "cargo" 164 165 // Repo layout Refs 166 BowerDefaultRepoLayout = "bower-default" 167 buildDefaultRepoLayout = "build-default" 168 ComposerDefaultRepoLayout = "composer-default" 169 ConanDefaultRepoLayout = "conan-default" 170 GoDefaultRepoLayout = "go-default" 171 GradleDefaultRepoLayout = "maven-2-default" 172 IvyDefaultRepoLayout = "ivy-default" 173 Maven1DefaultRepoLayout = "maven-1-default" 174 Maven2DefaultRepoLayout = "maven-2-default" 175 NpmDefaultRepoLayout = "npm-default" 176 NugetDefaultRepoLayout = "nuget-default" 177 puppetDefaultRepoLayout = "puppet-default" 178 SbtDefaultRepoLayout = "sbt-default" 179 SimpleDefaultRepoLayout = "simple-default" 180 VcsDefaultRepoLayout = "vcs-default" 181 182 // Checksum Policies 183 ClientChecksumPolicy = "client-checksums" 184 ServerGeneratedChecksumsPolicy = "server-generated-checksums" 185 186 // Snapshot version behaviors 187 UniqueBehavior = "unique" 188 NonUniqueBehavior = "non-unique" 189 DeployerBehavior = "deployer" 190 191 // Optional index compression formats 192 Bz2Compression = "bz2" 193 LzmaCompression = "lzma" 194 XzCompression = "xz" 195 196 // Docker api versions 197 DockerApiV1 = "V1" 198 DockerApiV2 = "V2" 199 200 // Remote repo checksum policies 201 GenerateIfAbsentPolicy = "generate-if-absent" 202 FailPolicy = "fail" 203 IgnoreAndGeneratePolicy = "ignore-and-generate" 204 PassThruPolicy = "pass-thru" 205 206 // Vcs Types 207 Git = "GIT" 208 209 // Vcs git provider 210 GithubVcsProvider = "GITHUB" 211 BitbucketVcsProvider = "BITBUCKET" 212 OldstashVcsProvider = "OLDSTASH" 213 StashVcsProvider = "STASH" 214 ArtifactoryVcsProvider = "ARTIFACTORY" 215 CustomVcsProvider = "CUSTOM" 216 217 // POM repository references cleanup policies 218 DiscardActiveRefrencePolicy = "discard_active_reference" 219 DiscardAnyReferencePolicy = "discard_any_reference" 220 NothingPolicy = "nothing" 221 ) 222 223 var optionalSuggestsMap = map[string]prompt.Suggest{ 224 ioutils.SaveAndExit: {Text: ioutils.SaveAndExit}, 225 Description: {Text: Description}, 226 Notes: {Text: Notes}, 227 IncludePatterns: {Text: IncludePatterns}, 228 ExcludePatterns: {Text: ExcludePatterns}, 229 RepoLayoutRef: {Text: RepoLayoutRef}, 230 ProjectKey: {Text: ProjectKey}, 231 Environment: {Text: Environment}, 232 HandleReleases: {Text: HandleReleases}, 233 HandleSnapshots: {Text: HandleSnapshots}, 234 MaxUniqueSnapshots: {Text: MaxUniqueSnapshots}, 235 SuppressPomConsistencyChecks: {Text: SuppressPomConsistencyChecks}, 236 BlackedOut: {Text: BlackedOut}, 237 DownloadRedirect: {Text: DownloadRedirect}, 238 BlockPushingSchema1: {Text: BlockPushingSchema1}, 239 DebianTrivialLayout: {Text: DebianTrivialLayout}, 240 ExternalDependenciesEnabled: {Text: ExternalDependenciesEnabled}, 241 ExternalDependenciesPatterns: {Text: ExternalDependenciesPatterns}, 242 ChecksumPolicyType: {Text: ChecksumPolicyType}, 243 MaxUniqueTags: {Text: MaxUniqueTags}, 244 SnapshotVersionBehavior: {Text: SnapshotVersionBehavior}, 245 XrayIndex: {Text: XrayIndex}, 246 PropertySets: {Text: PropertySets}, 247 ArchiveBrowsingEnabled: {Text: ArchiveBrowsingEnabled}, 248 CalculateYumMetadata: {Text: CalculateYumMetadata}, 249 YumRootDepth: {Text: YumRootDepth}, 250 DockerApiVersion: {Text: DockerApiVersion}, 251 EnableFileListsIndexing: {Text: EnableFileListsIndexing}, 252 OptionalIndexCompressionFormats: {Text: OptionalIndexCompressionFormats}, 253 Url: {Text: Url}, 254 Username: {Text: Username}, 255 Password: {Text: Password}, 256 Proxy: {Text: Proxy}, 257 PrimaryKeyPairRef: {Text: PrimaryKeyPairRef}, 258 RemoteRepoChecksumPolicyType: {Text: RemoteRepoChecksumPolicyType}, 259 HardFail: {Text: HardFail}, 260 Offline: {Text: Offline}, 261 StoreArtifactsLocally: {Text: StoreArtifactsLocally}, 262 SocketTimeoutMillis: {Text: SocketTimeoutMillis}, 263 LocalAddress: {Text: LocalAddress}, 264 RetrievalCachePeriodSecs: {Text: RetrievalCachePeriodSecs}, 265 FailedRetrievalCachePeriodSecs: {Text: FailedRetrievalCachePeriodSecs}, 266 MissedRetrievalCachePeriodSecs: {Text: MissedRetrievalCachePeriodSecs}, 267 UnusedArtifactsCleanupEnabled: {Text: UnusedArtifactsCleanupEnabled}, 268 UnusedArtifactsCleanupPeriodHours: {Text: UnusedArtifactsCleanupPeriodHours}, 269 AssumedOfflinePeriodSecs: {Text: AssumedOfflinePeriodSecs}, 270 FetchJarsEagerly: {Text: FetchJarsEagerly}, 271 FetchSourcesEagerly: {Text: FetchSourcesEagerly}, 272 RejectInvalidJars: {Text: RejectInvalidJars}, 273 ShareConfiguration: {Text: ShareConfiguration}, 274 SynchronizeProperties: {Text: SynchronizeProperties}, 275 BlockMismatchingMimeTypes: {Text: BlockMismatchingMimeTypes}, 276 AllowAnyHostAuth: {Text: AllowAnyHostAuth}, 277 EnableCookieManagement: {Text: EnableCookieManagement}, 278 BowerRegistryUrl: {Text: BowerRegistryUrl}, 279 ComposerRegistryUrl: {Text: ComposerRegistryUrl}, 280 PyPIRegistryUrl: {Text: PyPIRegistryUrl}, 281 VcsType: {Text: VcsType}, 282 VcsGitProvider: {Text: VcsGitProvider}, 283 VcsGitDownloadUrl: {Text: VcsGitDownloadUrl}, 284 BypassHeadRequests: {Text: BypassHeadRequests}, 285 ClientTlsCertificate: {Text: ClientTlsCertificate}, 286 FeedContextPath: {Text: FeedContextPath}, 287 DownloadContextPath: {Text: DownloadContextPath}, 288 V3FeedUrl: {Text: V3FeedUrl}, 289 ContentSynchronisation: {Text: ContentSynchronisation}, 290 ListRemoteFolderItems: {Text: ListRemoteFolderItems}, 291 PodsSpecsRepoUrl: {Text: PodsSpecsRepoUrl}, 292 EnableTokenAuthentication: {Text: EnableTokenAuthentication}, 293 Repositories: {Text: Repositories}, 294 ArtifactoryRequestsCanRetrieveRemoteArtifacts: {Text: ArtifactoryRequestsCanRetrieveRemoteArtifacts}, 295 KeyPair: {Text: KeyPair}, 296 PomRepositoryReferencesCleanupPolicy: {Text: PomRepositoryReferencesCleanupPolicy}, 297 DefaultDeploymentRepo: {Text: DefaultDeploymentRepo}, 298 ForceMavenAuthentication: {Text: ForceMavenAuthentication}, 299 ForceNugetAuthentication: {Text: ForceNugetAuthentication}, 300 ExternalDependenciesRemoteRepo: {Text: ExternalDependenciesRemoteRepo}, 301 } 302 303 var baseLocalRepoConfKeys = []string{ 304 Description, Notes, IncludePatterns, ExcludePatterns, RepoLayoutRef, ProjectKey, Environment, BlackedOut, XrayIndex, 305 PropertySets, ArchiveBrowsingEnabled, OptionalIndexCompressionFormats, DownloadRedirect, BlockPushingSchema1, 306 } 307 308 var mavenGradleLocalRepoConfKeys = []string{ 309 MaxUniqueSnapshots, HandleReleases, HandleSnapshots, SuppressPomConsistencyChecks, SnapshotVersionBehavior, ChecksumPolicyType, 310 } 311 312 var rpmLocalRepoConfKeys = []string{ 313 YumRootDepth, CalculateYumMetadata, EnableFileListsIndexing, PrimaryKeyPairRef, 314 } 315 316 var nugetLocalRepoConfKeys = []string{ 317 MaxUniqueSnapshots, ForceNugetAuthentication, 318 } 319 320 var debianLocalRepoConfKeys = []string{ 321 DebianTrivialLayout, PrimaryKeyPairRef, 322 } 323 324 var dockerLocalRepoConfKeys = []string{ 325 DockerApiVersion, MaxUniqueTags, 326 } 327 328 var baseRemoteRepoConfKeys = []string{ 329 Username, Password, Proxy, Description, Notes, IncludePatterns, ExcludePatterns, RepoLayoutRef, ProjectKey, Environment, HardFail, Offline, 330 BlackedOut, XrayIndex, StoreArtifactsLocally, SocketTimeoutMillis, LocalAddress, RetrievalCachePeriodSecs, FailedRetrievalCachePeriodSecs, 331 MissedRetrievalCachePeriodSecs, UnusedArtifactsCleanupEnabled, UnusedArtifactsCleanupPeriodHours, AssumedOfflinePeriodSecs, 332 ShareConfiguration, SynchronizeProperties, BlockMismatchingMimeTypes, PropertySets, AllowAnyHostAuth, EnableCookieManagement, 333 BypassHeadRequests, ClientTlsCertificate, DownloadRedirect, BlockPushingSchema1, ContentSynchronisation, 334 } 335 336 var mavenGradleRemoteRepoConfKeys = []string{ 337 FetchJarsEagerly, FetchSourcesEagerly, RemoteRepoChecksumPolicyType, HandleReleases, HandleSnapshots, 338 SuppressPomConsistencyChecks, RejectInvalidJars, 339 } 340 341 var cocoapodsRemoteRepoConfKeys = []string{ 342 PodsSpecsRepoUrl, 343 } 344 345 var opkgRemoteRepoConfKeys = []string{ 346 ListRemoteFolderItems, 347 } 348 349 var rpmRemoteRepoConfKeys = []string{ 350 ListRemoteFolderItems, 351 } 352 353 var nugetRemoteRepoConfKeys = []string{ 354 FeedContextPath, DownloadContextPath, V3FeedUrl, ForceNugetAuthentication, 355 } 356 357 var gemsRemoteRepoConfKeys = []string{ 358 ListRemoteFolderItems, 359 } 360 361 var npmRemoteRepoConfKeys = []string{ 362 ListRemoteFolderItems, 363 } 364 365 var bowerRemoteRepoConfKeys = []string{ 366 BowerRegistryUrl, 367 } 368 369 var debianRemoteRepoConfKeys = []string{ 370 ListRemoteFolderItems, 371 } 372 373 var composerRemoteRepoConfKeys = []string{ 374 ComposerRegistryUrl, 375 } 376 377 var pypiRemoteRepoConfKeys = []string{ 378 PyPIRegistryUrl, ListRemoteFolderItems, 379 } 380 381 var dockerRemoteRepoConfKeys = []string{ 382 ExternalDependenciesEnabled, ExternalDependenciesPatterns, EnableTokenAuthentication, 383 } 384 385 var gitlfsRemoteRepoConfKeys = []string{ 386 ListRemoteFolderItems, 387 } 388 389 var vcsRemoteRepoConfKeys = []string{ 390 VcsGitProvider, VcsType, MaxUniqueSnapshots, VcsGitDownloadUrl, ListRemoteFolderItems, 391 } 392 393 var baseVirtualRepoConfKeys = []string{ 394 Repositories, Description, Notes, IncludePatterns, ExcludePatterns, RepoLayoutRef, ProjectKey, Environment, ArtifactoryRequestsCanRetrieveRemoteArtifacts, 395 DefaultDeploymentRepo, OptionalIndexCompressionFormats, PrimaryKeyPairRef, 396 } 397 398 var mavenGradleVirtualRepoConfKeys = []string{ 399 ForceMavenAuthentication, PomRepositoryReferencesCleanupPolicy, KeyPair, 400 } 401 402 var nugetVirtualRepoConfKeys = []string{ 403 ForceNugetAuthentication, 404 } 405 406 var npmVirtualRepoConfKeys = []string{ 407 ExternalDependenciesEnabled, ExternalDependenciesPatterns, ExternalDependenciesRemoteRepo, 408 } 409 410 var bowerVirtualRepoConfKeys = []string{ 411 ExternalDependenciesEnabled, ExternalDependenciesPatterns, ExternalDependenciesRemoteRepo, 412 } 413 414 var debianVirtualRepoConfKeys = []string{ 415 DebianTrivialLayout, 416 } 417 418 var goVirtualRepoConfKeys = []string{ 419 ExternalDependenciesEnabled, ExternalDependenciesPatterns, 420 } 421 422 var commonPkgTypes = []string{ 423 Maven, Gradle, Ivy, Sbt, Helm, Rpm, Nuget, Cran, Gems, Npm, Bower, Debian, Pypi, Docker, Gitlfs, Go, Conan, 424 Chef, Puppet, Alpine, Generic, 425 } 426 427 var localRepoAdditionalPkgTypes = []string{ 428 Cocoapods, Opkg, Composer, Vagrant, Yum, 429 } 430 431 var remoteRepoAdditionalPkgTypes = []string{ 432 Cocoapods, Opkg, Composer, Conda, P2, Vcs, Yum, 433 } 434 435 var virtualRepoAdditionalPkgTypes = []string{ 436 Conda, P2, Yum, 437 } 438 439 var federatedRepoAdditionalPkgTypes = []string{ 440 Vagrant, Opkg, Conda, Composer, Cocoapods, 441 } 442 443 var pkgTypeSuggestsMap = map[string]prompt.Suggest{ 444 Generic: {Text: Generic}, 445 Maven: {Text: Maven}, 446 Gradle: {Text: Gradle}, 447 Ivy: {Text: Ivy}, 448 Sbt: {Text: Sbt}, 449 Helm: {Text: Helm}, 450 Cocoapods: {Text: Cocoapods}, 451 Opkg: {Text: Opkg}, 452 Rpm: {Text: Rpm}, 453 Nuget: {Text: Nuget}, 454 Cran: {Text: Cran}, 455 Gems: {Text: Gems}, 456 Npm: {Text: Npm}, 457 Bower: {Text: Bower}, 458 Debian: {Text: Debian}, 459 Composer: {Text: Composer}, 460 Pypi: {Text: Pypi}, 461 Docker: {Text: Docker}, 462 Vagrant: {Text: Vagrant}, 463 Gitlfs: {Text: Gitlfs}, 464 Go: {Text: Go}, 465 Yum: {Text: Yum}, 466 Conan: {Text: Conan}, 467 Chef: {Text: Chef}, 468 Puppet: {Text: Puppet}, 469 Vcs: {Text: Vcs}, 470 Conda: {Text: Conda}, 471 P2: {Text: P2}, 472 Alpine: {Text: Alpine}, 473 } 474 475 func NewRepoTemplateCommand() *RepoTemplateCommand { 476 return &RepoTemplateCommand{} 477 } 478 479 func (rtc *RepoTemplateCommand) SetTemplatePath(path string) *RepoTemplateCommand { 480 rtc.path = path 481 return rtc 482 } 483 484 func (rtc *RepoTemplateCommand) ServerDetails() (*config.ServerDetails, error) { 485 // Since it's a local command, usage won't be reported. 486 return nil, nil 487 } 488 489 func (rtc *RepoTemplateCommand) Run() (err error) { 490 err = utils.ValidateTemplatePath(rtc.path) 491 if err != nil { 492 return 493 } 494 repoTemplateQuestionnaire := &ioutils.InteractiveQuestionnaire{ 495 MandatoryQuestionsKeys: []string{TemplateType, Key, Rclass}, 496 QuestionsMap: questionMap, 497 } 498 err = repoTemplateQuestionnaire.Perform() 499 if err != nil { 500 return err 501 } 502 resBytes, err := json.Marshal(repoTemplateQuestionnaire.AnswersMap) 503 if err != nil { 504 return errorutils.CheckError(err) 505 } 506 if err = os.WriteFile(rtc.path, resBytes, 0644); err != nil { 507 return errorutils.CheckError(err) 508 } 509 log.Info(fmt.Sprintf("Repository configuration template successfully created at %s.", rtc.path)) 510 511 return nil 512 } 513 514 func (rtc *RepoTemplateCommand) CommandName() string { 515 return "rt_repo_template" 516 } 517 518 func rclassCallback(iq *ioutils.InteractiveQuestionnaire, rclass string) (string, error) { 519 var pkgTypes = commonPkgTypes 520 switch rclass { 521 case Remote: 522 // For create template url is mandatory, for update we will allow url as an optional key 523 if _, ok := iq.AnswersMap[TemplateType]; !ok { 524 return "", errors.New("package type is missing in configuration map") 525 } 526 if iq.AnswersMap[TemplateType] == Create { 527 _, err := iq.AskQuestion(iq.QuestionsMap[MandatoryUrl]) 528 if err != nil { 529 return "", err 530 } 531 } 532 pkgTypes = append(pkgTypes, remoteRepoAdditionalPkgTypes...) 533 case Local: 534 pkgTypes = append(pkgTypes, localRepoAdditionalPkgTypes...) 535 case Virtual: 536 pkgTypes = append(pkgTypes, virtualRepoAdditionalPkgTypes...) 537 case Federated: 538 pkgTypes = append(pkgTypes, federatedRepoAdditionalPkgTypes...) 539 default: 540 return "", errors.New("unsupported rclass") 541 } 542 // PackageType is also mandatory. Since the possible types depend on which rcalss was chosen, we ask the question here. 543 var pkgTypeQuestion = ioutils.QuestionInfo{ 544 Options: ioutils.GetSuggestsFromKeys(pkgTypes, pkgTypeSuggestsMap), 545 Msg: "", 546 PromptPrefix: "Select the repository's package type" + ioutils.PressTabMsg, 547 AllowVars: false, 548 Writer: ioutils.WriteStringAnswer, 549 MapKey: PackageType, 550 Callback: pkgTypeCallback, 551 } 552 return iq.AskQuestion(pkgTypeQuestion) 553 } 554 555 func pkgTypeCallback(iq *ioutils.InteractiveQuestionnaire, pkgType string) (string, error) { 556 // Each combination of (rclass,packageType) has its own optional configuration keys. 557 // We set the questionnaire's optionalKeys suggests according to the selected combination. 558 if _, ok := iq.AnswersMap[Rclass]; !ok { 559 return "", errors.New("rclass is missing in configuration map") 560 } 561 switch iq.AnswersMap[Rclass] { 562 case Local: 563 iq.OptionalKeysSuggests = getLocalRepoConfKeys(pkgType) 564 case Remote: 565 // For update template we need to allow url as an optional key 566 if _, ok := iq.AnswersMap[TemplateType]; !ok { 567 return "", errors.New("package type is missing in configuration map") 568 } 569 iq.OptionalKeysSuggests = getRemoteRepoConfKeys(pkgType, fmt.Sprint(iq.AnswersMap[TemplateType])) 570 case Virtual: 571 iq.OptionalKeysSuggests = getVirtualRepoConfKeys(pkgType) 572 case Federated: 573 iq.OptionalKeysSuggests = getLocalRepoConfKeys(pkgType) 574 default: 575 return "", errors.New("unsupported rclass was configured") 576 } 577 // We don't need the templateType value in the final configuration 578 delete(iq.AnswersMap, TemplateType) 579 return "", nil 580 } 581 582 // Repo key must have a prefix of "<projectKey>-". This callback adds the prefix to the repo key if it is missing. 583 func projectKeyCallback(iq *ioutils.InteractiveQuestionnaire, projectKey string) (string, error) { 584 if _, ok := iq.AnswersMap[Key]; !ok { 585 return "", errorutils.CheckErrorf("repository key is missing in configuration map") 586 } 587 requiredProjectPrefix := projectKey + "-" 588 currentRepoKey, ok := iq.AnswersMap[Key].(string) 589 if !ok { 590 return "", errorutils.CheckErrorf("template syntax error: the value for the repository key is not a string type") 591 } 592 593 if !strings.HasPrefix(currentRepoKey, requiredProjectPrefix) { 594 newRepoKey := requiredProjectPrefix + currentRepoKey 595 log.Info("Repository key should start with the projectKey followed by a dash. Modifying repo key to: '" + newRepoKey + "'.") 596 iq.AnswersMap[Key] = newRepoKey 597 } 598 return "", nil 599 } 600 601 func getLocalRepoConfKeys(pkgType string) []prompt.Suggest { 602 optionalKeys := []string{ioutils.SaveAndExit} 603 optionalKeys = append(optionalKeys, baseLocalRepoConfKeys...) 604 switch pkgType { 605 case Maven, Gradle: 606 optionalKeys = append(optionalKeys, mavenGradleLocalRepoConfKeys...) 607 case Rpm: 608 optionalKeys = append(optionalKeys, rpmLocalRepoConfKeys...) 609 case Nuget: 610 optionalKeys = append(optionalKeys, nugetLocalRepoConfKeys...) 611 case Debian: 612 optionalKeys = append(optionalKeys, debianLocalRepoConfKeys...) 613 case Docker: 614 optionalKeys = append(optionalKeys, dockerLocalRepoConfKeys...) 615 } 616 return ioutils.GetSuggestsFromKeys(optionalKeys, optionalSuggestsMap) 617 } 618 619 func getRemoteRepoConfKeys(pkgType, templateType string) []prompt.Suggest { 620 optionalKeys := []string{ioutils.SaveAndExit} 621 if templateType == Update { 622 optionalKeys = append(optionalKeys, Url) 623 } 624 optionalKeys = append(optionalKeys, baseRemoteRepoConfKeys...) 625 switch pkgType { 626 case Maven, Gradle: 627 optionalKeys = append(optionalKeys, mavenGradleRemoteRepoConfKeys...) 628 case Cocoapods: 629 optionalKeys = append(optionalKeys, cocoapodsRemoteRepoConfKeys...) 630 case Opkg: 631 optionalKeys = append(optionalKeys, opkgRemoteRepoConfKeys...) 632 case Rpm: 633 optionalKeys = append(optionalKeys, rpmRemoteRepoConfKeys...) 634 case Nuget: 635 optionalKeys = append(optionalKeys, nugetRemoteRepoConfKeys...) 636 case Gems: 637 optionalKeys = append(optionalKeys, gemsRemoteRepoConfKeys...) 638 case Npm: 639 optionalKeys = append(optionalKeys, npmRemoteRepoConfKeys...) 640 case Bower: 641 optionalKeys = append(optionalKeys, bowerRemoteRepoConfKeys...) 642 case Debian: 643 optionalKeys = append(optionalKeys, debianRemoteRepoConfKeys...) 644 case Composer: 645 optionalKeys = append(optionalKeys, composerRemoteRepoConfKeys...) 646 case Pypi: 647 optionalKeys = append(optionalKeys, pypiRemoteRepoConfKeys...) 648 case Docker: 649 optionalKeys = append(optionalKeys, dockerRemoteRepoConfKeys...) 650 case Gitlfs: 651 optionalKeys = append(optionalKeys, gitlfsRemoteRepoConfKeys...) 652 case Vcs: 653 optionalKeys = append(optionalKeys, vcsRemoteRepoConfKeys...) 654 } 655 return ioutils.GetSuggestsFromKeys(optionalKeys, optionalSuggestsMap) 656 } 657 658 func getVirtualRepoConfKeys(pkgType string) []prompt.Suggest { 659 optionalKeys := []string{ioutils.SaveAndExit} 660 optionalKeys = append(optionalKeys, baseVirtualRepoConfKeys...) 661 switch pkgType { 662 case Maven, Gradle: 663 optionalKeys = append(optionalKeys, mavenGradleVirtualRepoConfKeys...) 664 case Nuget: 665 optionalKeys = append(optionalKeys, nugetVirtualRepoConfKeys...) 666 case Npm: 667 optionalKeys = append(optionalKeys, npmVirtualRepoConfKeys...) 668 case Bower: 669 optionalKeys = append(optionalKeys, bowerVirtualRepoConfKeys...) 670 case Debian: 671 optionalKeys = append(optionalKeys, debianVirtualRepoConfKeys...) 672 case Go: 673 optionalKeys = append(optionalKeys, goVirtualRepoConfKeys...) 674 } 675 return ioutils.GetSuggestsFromKeys(optionalKeys, optionalSuggestsMap) 676 } 677 678 func contentSynchronisationCallBack(iq *ioutils.InteractiveQuestionnaire, answer string) (value string, err error) { 679 // contentSynchronisation has an object value with 4 bool fields. 680 // We ask for the rest of the values and writes the values in comma separated list. 681 if err != nil { 682 return "", nil 683 } 684 answer += "," + ioutils.AskFromList("", "Insert the value for statistic.enable >", false, ioutils.GetBoolSuggests(), "") 685 // cs.Statistics.Enabled, err = strconv.ParseBool(enabled) 686 if err != nil { 687 return "", nil 688 } 689 answer += "," + ioutils.AskFromList("", "Insert the value for properties.enable >", false, ioutils.GetBoolSuggests(), "") 690 // cs.Properties.Enabled, err = strconv.ParseBool(enabled) 691 if err != nil { 692 return "", nil 693 } 694 answer += "," + ioutils.AskFromList("", "Insert the value for source.originAbsenceDetection >", false, ioutils.GetBoolSuggests(), "") 695 // cs.Source.OriginAbsenceDetection, err = strconv.ParseBool(enabled) 696 if err != nil { 697 return "", nil 698 } 699 iq.AnswersMap[ContentSynchronisation] = answer 700 return "", nil 701 } 702 703 // Specific writers for repo templates, since all the values in the templates should be written as string 704 var BoolToStringQuestionInfo = ioutils.QuestionInfo{ 705 Options: ioutils.GetBoolSuggests(), 706 AllowVars: true, 707 Writer: ioutils.WriteStringAnswer, 708 } 709 710 var IntToStringQuestionInfo = ioutils.QuestionInfo{ 711 Options: nil, 712 AllowVars: true, 713 Writer: ioutils.WriteStringAnswer, 714 } 715 716 var StringListToStringQuestionInfo = ioutils.QuestionInfo{ 717 Msg: ioutils.CommaSeparatedListMsg, 718 Options: nil, 719 AllowVars: true, 720 Writer: ioutils.WriteStringAnswer, 721 } 722 723 var questionMap = map[string]ioutils.QuestionInfo{ 724 TemplateType: { 725 Options: []prompt.Suggest{ 726 {Text: Create, Description: "Template for creating a new repository"}, 727 {Text: Update, Description: "Template for updating an existing repository"}, 728 }, 729 Msg: "", 730 PromptPrefix: "Select the template type" + ioutils.PressTabMsg, 731 AllowVars: false, 732 Writer: ioutils.WriteStringAnswer, 733 MapKey: TemplateType, 734 Callback: nil, 735 }, 736 ioutils.OptionalKey: { 737 Msg: "", 738 PromptPrefix: SelectConfigKeyMsg, 739 AllowVars: false, 740 Writer: nil, 741 MapKey: "", 742 Callback: ioutils.OptionalKeyCallback, 743 }, 744 Key: { 745 Msg: "", 746 PromptPrefix: "Insert the repository key >", 747 AllowVars: true, 748 Writer: ioutils.WriteStringAnswer, 749 MapKey: Key, 750 Callback: nil, 751 }, 752 Rclass: { 753 Options: []prompt.Suggest{ 754 {Text: Local, Description: "A physical, locally-managed repository into which you can deploy artifacts"}, 755 {Text: Remote, Description: "A caching proxy for a repository managed at a remote URL"}, 756 {Text: Virtual, Description: "An Aggregation of several repositories with the same package type under a common URL."}, 757 {Text: Federated, Description: "A Federation is a collection of repositories of Federated type in different JPDs that are automatically configured for full bi-directional mirroring."}, 758 }, 759 Msg: "", 760 PromptPrefix: "Select the repository class" + ioutils.PressTabMsg, 761 AllowVars: false, 762 Writer: ioutils.WriteStringAnswer, 763 MapKey: Rclass, 764 Callback: rclassCallback, 765 }, 766 MandatoryUrl: { 767 Msg: "", 768 PromptPrefix: "Insert the remote repository URL >", 769 AllowVars: true, 770 Writer: ioutils.WriteStringAnswer, 771 MapKey: Url, 772 Callback: nil, 773 }, 774 Url: ioutils.FreeStringQuestionInfo, 775 Description: ioutils.FreeStringQuestionInfo, 776 Notes: ioutils.FreeStringQuestionInfo, 777 IncludePatterns: StringListToStringQuestionInfo, 778 ExcludePatterns: StringListToStringQuestionInfo, 779 RepoLayoutRef: { 780 Options: []prompt.Suggest{ 781 {Text: BowerDefaultRepoLayout}, 782 {Text: buildDefaultRepoLayout}, 783 {Text: ComposerDefaultRepoLayout}, 784 {Text: ConanDefaultRepoLayout}, 785 {Text: GoDefaultRepoLayout}, 786 {Text: GradleDefaultRepoLayout}, 787 {Text: IvyDefaultRepoLayout}, 788 {Text: Maven1DefaultRepoLayout}, 789 {Text: Maven2DefaultRepoLayout}, 790 {Text: NpmDefaultRepoLayout}, 791 {Text: NugetDefaultRepoLayout}, 792 {Text: puppetDefaultRepoLayout}, 793 {Text: SbtDefaultRepoLayout}, 794 {Text: SimpleDefaultRepoLayout}, 795 {Text: VcsDefaultRepoLayout}, 796 }, 797 AllowVars: true, 798 Writer: ioutils.WriteStringAnswer, 799 }, 800 ProjectKey: { 801 Options: nil, 802 AllowVars: false, 803 Writer: ioutils.WriteStringAnswer, 804 Callback: projectKeyCallback, 805 }, 806 Environment: { 807 PromptPrefix: "Insert the name of the environment to assign to >", 808 AllowVars: true, 809 MapKey: environmentsKey, 810 Writer: ioutils.WriteStringAnswer, 811 }, 812 HandleReleases: BoolToStringQuestionInfo, 813 HandleSnapshots: BoolToStringQuestionInfo, 814 MaxUniqueSnapshots: IntToStringQuestionInfo, 815 SuppressPomConsistencyChecks: BoolToStringQuestionInfo, 816 BlackedOut: BoolToStringQuestionInfo, 817 DownloadRedirect: BoolToStringQuestionInfo, 818 BlockPushingSchema1: BoolToStringQuestionInfo, 819 DebianTrivialLayout: BoolToStringQuestionInfo, 820 ExternalDependenciesEnabled: BoolToStringQuestionInfo, 821 ExternalDependenciesPatterns: StringListToStringQuestionInfo, 822 ChecksumPolicyType: { 823 Options: []prompt.Suggest{ 824 {Text: ClientChecksumPolicy}, 825 {Text: ServerGeneratedChecksumsPolicy}, 826 }, 827 AllowVars: true, 828 Writer: ioutils.WriteStringAnswer, 829 }, 830 MaxUniqueTags: IntToStringQuestionInfo, 831 SnapshotVersionBehavior: { 832 Options: []prompt.Suggest{ 833 {Text: UniqueBehavior}, 834 {Text: NonUniqueBehavior}, 835 {Text: DeployerBehavior}, 836 }, 837 AllowVars: true, 838 Writer: ioutils.WriteStringAnswer, 839 }, 840 XrayIndex: BoolToStringQuestionInfo, 841 PropertySets: StringListToStringQuestionInfo, 842 ArchiveBrowsingEnabled: BoolToStringQuestionInfo, 843 CalculateYumMetadata: BoolToStringQuestionInfo, 844 YumRootDepth: IntToStringQuestionInfo, 845 DockerApiVersion: { 846 Options: []prompt.Suggest{ 847 {Text: DockerApiV1}, 848 {Text: DockerApiV2}, 849 }, 850 AllowVars: true, 851 Writer: ioutils.WriteStringAnswer, 852 }, 853 EnableFileListsIndexing: BoolToStringQuestionInfo, 854 OptionalIndexCompressionFormats: { 855 Msg: "Enter a comma separated list of values from " + strings.Join([]string{Bz2Compression, LzmaCompression, XzCompression}, ","), 856 Options: nil, 857 AllowVars: true, 858 Writer: ioutils.WriteStringAnswer, 859 }, 860 PrimaryKeyPairRef: ioutils.FreeStringQuestionInfo, 861 Username: ioutils.FreeStringQuestionInfo, 862 Password: ioutils.FreeStringQuestionInfo, 863 Proxy: ioutils.FreeStringQuestionInfo, 864 RemoteRepoChecksumPolicyType: { 865 Options: []prompt.Suggest{ 866 {Text: GenerateIfAbsentPolicy}, 867 {Text: FailPolicy}, 868 {Text: IgnoreAndGeneratePolicy}, 869 {Text: PassThruPolicy}, 870 }, 871 AllowVars: true, 872 Writer: ioutils.WriteStringAnswer, 873 }, 874 HardFail: BoolToStringQuestionInfo, 875 Offline: BoolToStringQuestionInfo, 876 StoreArtifactsLocally: BoolToStringQuestionInfo, 877 SocketTimeoutMillis: IntToStringQuestionInfo, 878 LocalAddress: ioutils.FreeStringQuestionInfo, 879 RetrievalCachePeriodSecs: IntToStringQuestionInfo, 880 FailedRetrievalCachePeriodSecs: IntToStringQuestionInfo, 881 MissedRetrievalCachePeriodSecs: IntToStringQuestionInfo, 882 UnusedArtifactsCleanupEnabled: BoolToStringQuestionInfo, 883 UnusedArtifactsCleanupPeriodHours: IntToStringQuestionInfo, 884 AssumedOfflinePeriodSecs: IntToStringQuestionInfo, 885 FetchJarsEagerly: BoolToStringQuestionInfo, 886 FetchSourcesEagerly: BoolToStringQuestionInfo, 887 RejectInvalidJars: BoolToStringQuestionInfo, 888 ShareConfiguration: BoolToStringQuestionInfo, 889 SynchronizeProperties: BoolToStringQuestionInfo, 890 BlockMismatchingMimeTypes: BoolToStringQuestionInfo, 891 AllowAnyHostAuth: BoolToStringQuestionInfo, 892 EnableCookieManagement: BoolToStringQuestionInfo, 893 BowerRegistryUrl: ioutils.FreeStringQuestionInfo, 894 ComposerRegistryUrl: ioutils.FreeStringQuestionInfo, 895 PyPIRegistryUrl: ioutils.FreeStringQuestionInfo, 896 VcsType: { 897 Options: []prompt.Suggest{ 898 {Text: Git}, 899 }, 900 AllowVars: true, 901 Writer: ioutils.WriteStringAnswer, 902 }, 903 VcsGitProvider: { 904 Options: []prompt.Suggest{ 905 {Text: GithubVcsProvider}, 906 {Text: BitbucketVcsProvider}, 907 {Text: OldstashVcsProvider}, 908 {Text: StashVcsProvider}, 909 {Text: ArtifactoryVcsProvider}, 910 {Text: CustomVcsProvider}, 911 }, 912 AllowVars: true, 913 Writer: ioutils.WriteStringAnswer, 914 }, 915 VcsGitDownloadUrl: ioutils.FreeStringQuestionInfo, 916 BypassHeadRequests: BoolToStringQuestionInfo, 917 ClientTlsCertificate: ioutils.FreeStringQuestionInfo, 918 FeedContextPath: ioutils.FreeStringQuestionInfo, 919 DownloadContextPath: ioutils.FreeStringQuestionInfo, 920 V3FeedUrl: ioutils.FreeStringQuestionInfo, 921 ListRemoteFolderItems: BoolToStringQuestionInfo, 922 EnableTokenAuthentication: BoolToStringQuestionInfo, 923 PodsSpecsRepoUrl: ioutils.FreeStringQuestionInfo, 924 ContentSynchronisation: { 925 Options: ioutils.GetBoolSuggests(), 926 AllowVars: true, 927 Writer: nil, 928 Callback: contentSynchronisationCallBack, 929 }, 930 Repositories: StringListToStringQuestionInfo, 931 ArtifactoryRequestsCanRetrieveRemoteArtifacts: BoolToStringQuestionInfo, 932 KeyPair: ioutils.FreeStringQuestionInfo, 933 PomRepositoryReferencesCleanupPolicy: { 934 Options: []prompt.Suggest{ 935 {Text: DiscardActiveRefrencePolicy}, 936 {Text: DiscardAnyReferencePolicy}, 937 {Text: NothingPolicy}, 938 }, 939 AllowVars: true, 940 Writer: ioutils.WriteStringAnswer, 941 }, 942 DefaultDeploymentRepo: ioutils.FreeStringQuestionInfo, 943 ForceMavenAuthentication: BoolToStringQuestionInfo, 944 ForceNugetAuthentication: BoolToStringQuestionInfo, 945 ExternalDependenciesRemoteRepo: ioutils.FreeStringQuestionInfo, 946 }