github.com/ouraigua/jenkins-library@v0.0.0-20231028010029-fbeaf2f3aa9b/pkg/cpi/commonUtils.go (about) 1 package cpi 2 3 import ( 4 "encoding/json" 5 "fmt" 6 "io" 7 "mime" 8 "net/http" 9 "os" 10 "path/filepath" 11 12 "github.com/SAP/jenkins-library/pkg/log" 13 14 "github.com/Jeffail/gabs/v2" 15 piperhttp "github.com/SAP/jenkins-library/pkg/http" 16 "github.com/pkg/errors" 17 ) 18 19 // CommonUtils for CPI 20 type CommonUtils interface { 21 GetBearerToken() (string, error) 22 } 23 24 // HttpCPIUtils for CPI 25 type HttpCPIUtils interface { 26 HandleHTTPFileDownloadResponse() error 27 } 28 29 // HTTPUploadUtils for CPI 30 type HTTPUploadUtils interface { 31 HandleHTTPFileUploadResponse() error 32 HandleHTTPGetRequestResponse() (string, error) 33 } 34 35 // TokenParameters struct 36 type TokenParameters struct { 37 TokenURL, Username, Password string 38 Client piperhttp.Sender 39 } 40 41 // HttpParameters struct 42 type HttpFileDownloadRequestParameters struct { 43 ErrMessage, FileDownloadPath string 44 Response *http.Response 45 } 46 47 // HTTPFileUploadRequestParameters struct 48 type HttpFileUploadRequestParameters struct { 49 ErrMessage, FilePath, HTTPMethod, HTTPURL, SuccessMessage string 50 Response *http.Response 51 HTTPErr error 52 } 53 54 // ServiceKey contains information about a CPI service key 55 type ServiceKey struct { 56 OAuth OAuth `json:"oauth"` 57 } 58 59 // OAuth is inside a CPI service key and contains more needed information 60 type OAuth struct { 61 Host string `json:"url"` 62 OAuthTokenProviderURL string `json:"tokenurl"` 63 ClientID string `json:"clientid"` 64 ClientSecret string `json:"clientsecret"` 65 } 66 67 // ReadCpiServiceKey unmarshalls the give json service key string. 68 func ReadCpiServiceKey(serviceKeyJSON string) (cpiServiceKey ServiceKey, err error) { 69 // parse 70 err = json.Unmarshal([]byte(serviceKeyJSON), &cpiServiceKey) 71 if err != nil { 72 err = errors.Wrap(err, "error unmarshalling serviceKey") 73 return 74 } 75 76 log.Entry().Info("CPI serviceKey read successfully") 77 return 78 } 79 80 // GetBearerToken -Provides the bearer token for making CPI OData calls 81 func (tokenParameters TokenParameters) GetBearerToken() (string, error) { 82 83 httpClient := tokenParameters.Client 84 85 clientOptions := piperhttp.ClientOptions{ 86 Username: tokenParameters.Username, 87 Password: tokenParameters.Password, 88 } 89 httpClient.SetOptions(clientOptions) 90 91 header := make(http.Header) 92 header.Add("Accept", "application/json") 93 tokenFinalURL := fmt.Sprintf("%s?grant_type=client_credentials", tokenParameters.TokenURL) 94 method := "POST" 95 resp, httpErr := httpClient.SendRequest(method, tokenFinalURL, nil, header, nil) 96 if httpErr != nil { 97 return "", errors.Wrapf(httpErr, "HTTP %v request to %v failed with error", method, tokenFinalURL) 98 } 99 if resp != nil && resp.Body != nil { 100 defer resp.Body.Close() 101 } 102 103 if resp == nil { 104 return "", errors.Errorf("did not retrieve a HTTP response") 105 } 106 107 if resp.StatusCode != 200 { 108 return "", errors.Errorf("did not retrieve a valid HTTP response code: %v", httpErr) 109 } 110 111 bodyText, readErr := io.ReadAll(resp.Body) 112 if readErr != nil { 113 return "", errors.Wrap(readErr, "HTTP response body could not be read") 114 } 115 jsonResponse, parsingErr := gabs.ParseJSON([]byte(bodyText)) 116 if parsingErr != nil { 117 return "", errors.Wrapf(parsingErr, "HTTP response body could not be parsed as JSON: %v", string(bodyText)) 118 } 119 token := jsonResponse.Path("access_token").Data().(string) 120 return token, nil 121 } 122 123 // HandleHTTPFileDownloadResponse - Handle the file download response for http multipart response 124 func (httpFileDownloadRequestParameters HttpFileDownloadRequestParameters) HandleHTTPFileDownloadResponse() error { 125 response := httpFileDownloadRequestParameters.Response 126 contentDisposition := response.Header.Get("Content-Disposition") 127 disposition, params, err := mime.ParseMediaType(contentDisposition) 128 if err != nil { 129 return errors.Wrapf(err, "failed to read filename from http response headers, Content-Disposition %s", disposition) 130 } 131 filename := params["filename"] 132 133 if response != nil && response.Body != nil { 134 defer response.Body.Close() 135 } 136 137 if response.StatusCode == 200 { 138 workspaceRelativePath := httpFileDownloadRequestParameters.FileDownloadPath 139 err = os.MkdirAll(workspaceRelativePath, 0755) 140 // handling error while creating a workspce directoy for file download, if one not exist already! 141 if err != nil { 142 return errors.Wrapf(err, "Failed to create workspace directory") 143 } 144 zipFileName := filepath.Join(workspaceRelativePath, filename) 145 file, err := os.Create(zipFileName) 146 // handling error while creating a file in the filesystem 147 if err != nil { 148 return errors.Wrap(err, "failed to create zip archive of api proxy") 149 } 150 _, err = io.Copy(file, response.Body) 151 if err != nil { 152 return err 153 } 154 return nil 155 } 156 responseBody, readErr := io.ReadAll(response.Body) 157 if readErr != nil { 158 return errors.Wrapf(readErr, "HTTP response body could not be read, Response status code: %v", response.StatusCode) 159 } 160 log.Entry().Errorf("a HTTP error occurred! Response body: %v, Response status code : %v", responseBody, response.StatusCode) 161 return errors.Errorf("%s, Response Status code: %v", httpFileDownloadRequestParameters.ErrMessage, response.StatusCode) 162 } 163 164 // HandleHTTPFileUploadResponse - Handle the file upload response 165 func (httpFileUploadRequestParameters HttpFileUploadRequestParameters) HandleHTTPFileUploadResponse() error { 166 response := httpFileUploadRequestParameters.Response 167 httpErr := httpFileUploadRequestParameters.HTTPErr 168 if response != nil && response.Body != nil { 169 defer response.Body.Close() 170 } 171 172 if response == nil { 173 return errors.Errorf("did not retrieve a HTTP response: %v", httpErr) 174 } 175 responseCode := response.StatusCode 176 177 if (responseCode == http.StatusOK) || (responseCode == http.StatusCreated) { 178 log.Entry(). 179 WithField("Created Artifact", httpFileUploadRequestParameters.FilePath). 180 Info(httpFileUploadRequestParameters.SuccessMessage) 181 return nil 182 } 183 if httpErr != nil { 184 responseBody, readErr := io.ReadAll(response.Body) 185 if readErr != nil { 186 return errors.Wrapf(readErr, "HTTP response body could not be read, Response status code: %v", response.StatusCode) 187 } 188 log.Entry().Errorf("a HTTP error occurred! Response body: %v, Response status code: %v", string(responseBody), response.StatusCode) 189 return errors.Wrapf(httpErr, "HTTP %v request to %v failed with error: %v", httpFileUploadRequestParameters.HTTPMethod, httpFileUploadRequestParameters.HTTPURL, string(responseBody)) 190 } 191 return errors.Errorf("%s, Response Status code: %v", httpFileUploadRequestParameters.ErrMessage, response.StatusCode) 192 } 193 194 // HandleHTTPGetRequestResponse - Handle the GET Request response data 195 func (httpGetRequestParameters HttpFileUploadRequestParameters) HandleHTTPGetRequestResponse() (string, error) { 196 response := httpGetRequestParameters.Response 197 httpErr := httpGetRequestParameters.HTTPErr 198 if response != nil && response.Body != nil { 199 defer response.Body.Close() 200 } 201 202 if response == nil { 203 return "", errors.Errorf("did not retrieve a HTTP response: %v", httpErr) 204 } 205 if response.StatusCode == http.StatusOK { 206 responseBody, readErr := io.ReadAll(response.Body) 207 if readErr != nil { 208 return "", errors.Wrapf(readErr, "HTTP response body could not be read, response status code: %v", response.StatusCode) 209 } 210 return string(responseBody), nil 211 } 212 if httpErr != nil { 213 responseBody, readErr := io.ReadAll(response.Body) 214 if readErr != nil { 215 return "", errors.Wrapf(readErr, "HTTP response body could not be read, Response status code: %v", response.StatusCode) 216 } 217 log.Entry().Errorf("a HTTP error occurred! Response body: %v, Response status code: %v", string(responseBody), response.StatusCode) 218 return "", errors.Wrapf(httpErr, "HTTP %v request to %v failed with error: %v", httpGetRequestParameters.HTTPMethod, httpGetRequestParameters.HTTPURL, string(responseBody)) 219 } 220 return "", errors.Errorf("%s, Response Status code: %v", httpGetRequestParameters.ErrMessage, response.StatusCode) 221 }