github.com/cobalt77/jfrog-client-go@v0.14.5/artifactory/services/props.go (about) 1 package services 2 3 import ( 4 "net/http" 5 "net/url" 6 "path" 7 "strings" 8 9 rthttpclient "github.com/cobalt77/jfrog-client-go/artifactory/httpclient" 10 "github.com/cobalt77/jfrog-client-go/artifactory/services/utils" 11 "github.com/cobalt77/jfrog-client-go/auth" 12 clientutils "github.com/cobalt77/jfrog-client-go/utils" 13 "github.com/cobalt77/jfrog-client-go/utils/errorutils" 14 "github.com/cobalt77/jfrog-client-go/utils/io/content" 15 "github.com/cobalt77/jfrog-client-go/utils/log" 16 "github.com/jfrog/gofrog/parallel" 17 ) 18 19 type PropsService struct { 20 client *rthttpclient.ArtifactoryHttpClient 21 ArtDetails auth.ServiceDetails 22 Threads int 23 } 24 25 func NewPropsService(client *rthttpclient.ArtifactoryHttpClient) *PropsService { 26 return &PropsService{client: client} 27 } 28 29 func (ps *PropsService) GetArtifactoryDetails() auth.ServiceDetails { 30 return ps.ArtDetails 31 } 32 33 func (ps *PropsService) SetArtifactoryDetails(rt auth.ServiceDetails) { 34 ps.ArtDetails = rt 35 } 36 37 func (ps *PropsService) IsDryRun() bool { 38 return false 39 } 40 41 func (ps *PropsService) GetThreads() int { 42 return ps.Threads 43 } 44 45 func (ps *PropsService) SetProps(propsParams PropsParams) (int, error) { 46 log.Info("Setting properties...") 47 totalSuccess, err := ps.performRequest(propsParams, false) 48 if err == nil { 49 log.Info("Done setting properties.") 50 } 51 return totalSuccess, err 52 } 53 54 func (ps *PropsService) DeleteProps(propsParams PropsParams) (int, error) { 55 log.Info("Deleting properties...") 56 totalSuccess, err := ps.performRequest(propsParams, true) 57 if err == nil { 58 log.Info("Done deleting properties.") 59 } 60 return totalSuccess, err 61 } 62 63 type PropsParams struct { 64 Reader *content.ContentReader 65 Props string 66 } 67 68 func (sp *PropsParams) GetReader() *content.ContentReader { 69 return sp.Reader 70 } 71 72 func (sp *PropsParams) GetProps() string { 73 return sp.Props 74 } 75 76 func (ps *PropsService) performRequest(propsParams PropsParams, isDelete bool) (int, error) { 77 var encodedParam string 78 if !isDelete { 79 props, err := utils.ParseProperties(propsParams.GetProps(), utils.JoinCommas) 80 if err != nil { 81 return 0, err 82 } 83 encodedParam = props.ToEncodedString() 84 } else { 85 propList := strings.Split(propsParams.GetProps(), ",") 86 for _, prop := range propList { 87 encodedParam += url.QueryEscape(prop) + "," 88 } 89 // Remove trailing comma 90 if strings.HasSuffix(encodedParam, ",") { 91 encodedParam = encodedParam[:len(encodedParam)-1] 92 } 93 94 } 95 96 successCounters := make([]int, ps.GetThreads()) 97 producerConsumer := parallel.NewBounedRunner(ps.GetThreads(), false) 98 errorsQueue := clientutils.NewErrorsQueue(1) 99 reader := propsParams.GetReader() 100 go func() { 101 for resultItem := new(utils.ResultItem); reader.NextRecord(resultItem) == nil; resultItem = new(utils.ResultItem) { 102 relativePath := resultItem.GetItemRelativePath() 103 setPropsTask := func(threadId int) error { 104 var err error 105 logMsgPrefix := clientutils.GetLogMsgPrefix(threadId, ps.IsDryRun()) 106 107 restApi := path.Join("api", "storage", relativePath) 108 setPropertiesUrl, err := utils.BuildArtifactoryUrl(ps.GetArtifactoryDetails().GetUrl(), restApi, make(map[string]string)) 109 if err != nil { 110 return err 111 } 112 setPropertiesUrl += "?properties=" + encodedParam 113 114 var resp *http.Response 115 if isDelete { 116 resp, _, err = ps.sendDeleteRequest(logMsgPrefix, relativePath, setPropertiesUrl) 117 } else { 118 resp, _, err = ps.sendPutRequest(logMsgPrefix, relativePath, setPropertiesUrl) 119 } 120 121 if err != nil { 122 return err 123 } 124 if err = errorutils.CheckResponseStatus(resp, http.StatusNoContent); err != nil { 125 return errorutils.CheckError(err) 126 } 127 successCounters[threadId]++ 128 return nil 129 } 130 131 producerConsumer.AddTaskWithError(setPropsTask, errorsQueue.AddError) 132 } 133 defer producerConsumer.Done() 134 if err := reader.GetError(); err != nil { 135 errorsQueue.AddError(err) 136 } 137 reader.Reset() 138 }() 139 140 producerConsumer.Run() 141 totalSuccess := 0 142 for _, v := range successCounters { 143 totalSuccess += v 144 } 145 return totalSuccess, errorsQueue.GetError() 146 } 147 148 func (ps *PropsService) sendDeleteRequest(logMsgPrefix, relativePath, setPropertiesUrl string) (resp *http.Response, body []byte, err error) { 149 log.Info(logMsgPrefix+"Deleting properties on:", relativePath) 150 log.Debug(logMsgPrefix+"Sending delete properties request:", setPropertiesUrl) 151 httpClientsDetails := ps.GetArtifactoryDetails().CreateHttpClientDetails() 152 resp, body, err = ps.client.SendDelete(setPropertiesUrl, nil, &httpClientsDetails) 153 return 154 } 155 156 func (ps *PropsService) sendPutRequest(logMsgPrefix, relativePath, setPropertiesUrl string) (resp *http.Response, body []byte, err error) { 157 log.Info(logMsgPrefix+"Setting properties on:", relativePath) 158 log.Debug(logMsgPrefix+"Sending set properties request:", setPropertiesUrl) 159 httpClientsDetails := ps.GetArtifactoryDetails().CreateHttpClientDetails() 160 resp, body, err = ps.client.SendPut(setPropertiesUrl, nil, &httpClientsDetails) 161 return 162 } 163 164 func NewPropsParams() PropsParams { 165 return PropsParams{} 166 }