github.com/jfrog/jfrog-cli-go@v1.22.1-0.20200318093948-4826ef344ffd/artifactory/commands/repository/template.go (about)

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