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  }