github.com/jfrog/jfrog-cli-core/v2@v2.51.0/artifactory/commands/generic/upload.go (about) 1 package generic 2 3 import ( 4 "errors" 5 6 buildInfo "github.com/jfrog/build-info-go/entities" 7 8 ioutils "github.com/jfrog/gofrog/io" 9 "github.com/jfrog/jfrog-cli-core/v2/artifactory/utils" 10 "github.com/jfrog/jfrog-cli-core/v2/common/build" 11 "github.com/jfrog/jfrog-cli-core/v2/common/spec" 12 "github.com/jfrog/jfrog-client-go/artifactory/services" 13 rtServicesUtils "github.com/jfrog/jfrog-client-go/artifactory/services/utils" 14 clientUtils "github.com/jfrog/jfrog-client-go/utils" 15 "github.com/jfrog/jfrog-client-go/utils/errorutils" 16 ioUtils "github.com/jfrog/jfrog-client-go/utils/io" 17 "github.com/jfrog/jfrog-client-go/utils/io/content" 18 "github.com/jfrog/jfrog-client-go/utils/log" 19 "strconv" 20 "time" 21 ) 22 23 type UploadCommand struct { 24 GenericCommand 25 uploadConfiguration *utils.UploadConfiguration 26 buildConfiguration *build.BuildConfiguration 27 progress ioUtils.ProgressMgr 28 } 29 30 func NewUploadCommand() *UploadCommand { 31 return &UploadCommand{GenericCommand: *NewGenericCommand()} 32 } 33 34 func (uc *UploadCommand) SetBuildConfiguration(buildConfiguration *build.BuildConfiguration) *UploadCommand { 35 uc.buildConfiguration = buildConfiguration 36 return uc 37 } 38 39 func (uc *UploadCommand) UploadConfiguration() *utils.UploadConfiguration { 40 return uc.uploadConfiguration 41 } 42 43 func (uc *UploadCommand) SetUploadConfiguration(uploadConfiguration *utils.UploadConfiguration) *UploadCommand { 44 uc.uploadConfiguration = uploadConfiguration 45 return uc 46 } 47 48 func (uc *UploadCommand) SetProgress(progress ioUtils.ProgressMgr) { 49 uc.progress = progress 50 } 51 52 func (uc *UploadCommand) ShouldPrompt() bool { 53 return uc.syncDelete() && !uc.Quiet() 54 } 55 56 func (uc *UploadCommand) syncDelete() bool { 57 return !uc.DryRun() && uc.SyncDeletesPath() != "" 58 } 59 60 func (uc *UploadCommand) CommandName() string { 61 return "rt_upload" 62 } 63 64 func (uc *UploadCommand) Run() error { 65 return uc.upload() 66 } 67 68 // Uploads the artifacts in the specified local path pattern to the specified target path. 69 // Returns the total number of artifacts successfully uploaded. 70 func (uc *UploadCommand) upload() (err error) { 71 // Init progress bar if needed 72 if uc.progress != nil { 73 uc.progress.InitProgressReaders() 74 } 75 // In case of sync-delete get the user to confirm first, and save the operation timestamp. 76 syncDeletesProp := "" 77 if uc.syncDelete() { 78 timestamp := strconv.FormatInt(time.Now().UnixNano()/int64(time.Millisecond), 10) 79 syncDeletesProp = "sync.deletes.timestamp=" + timestamp 80 } 81 82 // Create Service Manager: 83 uc.uploadConfiguration.MinChecksumDeploySize, err = utils.GetMinChecksumDeploySize() 84 if err != nil { 85 return 86 } 87 serverDetails, err := uc.ServerDetails() 88 if errorutils.CheckError(err) != nil { 89 return 90 } 91 servicesManager, err := utils.CreateUploadServiceManager(serverDetails, uc.uploadConfiguration.Threads, uc.retries, uc.retryWaitTimeMilliSecs, uc.DryRun(), uc.progress) 92 if err != nil { 93 return 94 } 95 96 addVcsProps := false 97 buildProps := "" 98 // Build Info Collection: 99 toCollect, err := uc.buildConfiguration.IsCollectBuildInfo() 100 if err != nil { 101 return 102 } 103 if toCollect && !uc.DryRun() { 104 addVcsProps = true 105 buildProps, err = build.CreateBuildPropsFromConfiguration(uc.buildConfiguration) 106 if err != nil { 107 return err 108 } 109 } 110 111 var errorOccurred = false 112 var uploadParamsArray []services.UploadParams 113 // Create UploadParams for all File-Spec groups. 114 for i := 0; i < len(uc.Spec().Files); i++ { 115 file := uc.Spec().Get(i) 116 file.TargetProps = clientUtils.AddProps(file.TargetProps, file.Props) 117 file.TargetProps = clientUtils.AddProps(file.TargetProps, syncDeletesProp) 118 file.Props += syncDeletesProp 119 uploadParams, err := getUploadParams(file, uc.uploadConfiguration, buildProps, addVcsProps) 120 if err != nil { 121 errorOccurred = true 122 log.Error(err) 123 continue 124 } 125 uploadParamsArray = append(uploadParamsArray, uploadParams) 126 } 127 128 // Perform upload. 129 // In case of build-info collection or a detailed summary request, we use the upload service which provides results file reader, 130 // otherwise we use the upload service which provides only general counters. 131 var successCount, failCount int 132 var artifactsDetailsReader *content.ContentReader = nil 133 if uc.DetailedSummary() || toCollect { 134 var summary *rtServicesUtils.OperationSummary 135 summary, err = servicesManager.UploadFilesWithSummary(uploadParamsArray...) 136 if err != nil { 137 errorOccurred = true 138 log.Error(err) 139 } 140 if summary != nil { 141 artifactsDetailsReader = summary.ArtifactsDetailsReader 142 defer ioutils.Close(artifactsDetailsReader, &err) 143 // If 'detailed summary' was requested, then the reader should not be closed here. 144 // It will be closed after it will be used to generate the summary. 145 if uc.DetailedSummary() { 146 uc.result.SetReader(summary.TransferDetailsReader) 147 } else { 148 err = summary.TransferDetailsReader.Close() 149 if err != nil { 150 errorOccurred = true 151 log.Error(err) 152 } 153 } 154 successCount = summary.TotalSucceeded 155 failCount = summary.TotalFailed 156 } 157 } else { 158 successCount, failCount, err = servicesManager.UploadFiles(uploadParamsArray...) 159 if err != nil { 160 errorOccurred = true 161 log.Error(err) 162 } 163 } 164 uc.result.SetSuccessCount(successCount) 165 uc.result.SetFailCount(failCount) 166 if errorOccurred { 167 err = errors.New("upload finished with errors. Review the logs for more information") 168 return 169 } 170 if failCount > 0 { 171 return 172 } 173 174 // Handle sync-deletes 175 if uc.syncDelete() { 176 err = uc.handleSyncDeletes(syncDeletesProp) 177 if err != nil { 178 return 179 } 180 } 181 182 // Build info 183 if !uc.DryRun() && toCollect { 184 var buildArtifacts []buildInfo.Artifact 185 buildArtifacts, err = rtServicesUtils.ConvertArtifactsDetailsToBuildInfoArtifacts(artifactsDetailsReader) 186 if err != nil { 187 return 188 } 189 return build.PopulateBuildArtifactsAsPartials(buildArtifacts, uc.buildConfiguration, buildInfo.Generic) 190 } 191 return 192 } 193 194 func getUploadParams(f *spec.File, configuration *utils.UploadConfiguration, buildProps string, addVcsProps bool) (uploadParams services.UploadParams, err error) { 195 uploadParams = services.NewUploadParams() 196 uploadParams.CommonParams, err = f.ToCommonParams() 197 if err != nil { 198 return 199 } 200 uploadParams.Deb = configuration.Deb 201 uploadParams.MinChecksumDeploy = configuration.MinChecksumDeploySize 202 uploadParams.MinSplitSize = configuration.MinSplitSizeMB * rtServicesUtils.SizeMiB 203 uploadParams.SplitCount = configuration.SplitCount 204 uploadParams.AddVcsProps = addVcsProps 205 uploadParams.BuildProps = buildProps 206 uploadParams.Archive = f.Archive 207 uploadParams.TargetPathInArchive = f.TargetPathInArchive 208 209 uploadParams.Recursive, err = f.IsRecursive(true) 210 if err != nil { 211 return 212 } 213 214 uploadParams.Regexp, err = f.IsRegexp(false) 215 if err != nil { 216 return 217 } 218 219 uploadParams.Ant, err = f.IsAnt(false) 220 if err != nil { 221 return 222 } 223 224 uploadParams.IncludeDirs, err = f.IsIncludeDirs(false) 225 if err != nil { 226 return 227 } 228 229 uploadParams.Flat, err = f.IsFlat(true) 230 if err != nil { 231 return 232 } 233 234 uploadParams.ExplodeArchive, err = f.IsExplode(false) 235 if err != nil { 236 return 237 } 238 239 uploadParams.Symlink, err = f.IsSymlinks(false) 240 if err != nil { 241 return 242 } 243 244 return 245 } 246 247 func (uc *UploadCommand) handleSyncDeletes(syncDeletesProp string) (err error) { 248 servicesManager, err := utils.CreateServiceManager(uc.serverDetails, uc.retries, uc.retryWaitTimeMilliSecs, false) 249 if err != nil { 250 return err 251 } 252 deleteSpec := createDeleteSpecForSync(uc.SyncDeletesPath(), syncDeletesProp) 253 deleteParams, err := getDeleteParams(deleteSpec.Get(0)) 254 if err != nil { 255 return err 256 } 257 resultItems, err := servicesManager.GetPathsToDelete(deleteParams) 258 if err != nil { 259 return err 260 } 261 defer ioutils.Close(resultItems, &err) 262 _, err = servicesManager.DeleteFiles(resultItems) 263 return err 264 } 265 266 func createDeleteSpecForSync(deletePattern string, syncDeletesProp string) *spec.SpecFiles { 267 return spec.NewBuilder(). 268 Pattern(deletePattern). 269 ExcludeProps(syncDeletesProp). 270 Recursive(true). 271 BuildSpec() 272 }