mirror of
https://github.com/SAP/jenkins-library.git
synced 2024-12-14 11:03:09 +02:00
f27cb4e482
* ApiProxyUpload Command * Code Review Fixes * CodeReview Changes * CodeReview Fixes * YAML fixes * CodeReview Fix * Code Review Fixes * CodeReview Fixes * Code Climate Fixes * Code Review Fixes * Code Review Fixes Co-authored-by: Roland Stengel <r.stengel@sap.com> Co-authored-by: Oliver Feldmann <oliver.feldmann@sap.com>
192 lines
6.3 KiB
Go
192 lines
6.3 KiB
Go
package cpi
|
|
|
|
import (
|
|
"encoding/json"
|
|
"fmt"
|
|
"io"
|
|
"io/ioutil"
|
|
"mime"
|
|
"net/http"
|
|
"os"
|
|
"path/filepath"
|
|
|
|
"github.com/SAP/jenkins-library/pkg/log"
|
|
|
|
"github.com/Jeffail/gabs/v2"
|
|
piperhttp "github.com/SAP/jenkins-library/pkg/http"
|
|
"github.com/pkg/errors"
|
|
)
|
|
|
|
//CommonUtils for CPI
|
|
type CommonUtils interface {
|
|
GetBearerToken() (string, error)
|
|
}
|
|
|
|
//HttpCPIUtils for CPI
|
|
type HttpCPIUtils interface {
|
|
HandleHTTPFileDownloadResponse() error
|
|
}
|
|
|
|
//HTTPUploadUtils for CPI
|
|
type HTTPUploadUtils interface {
|
|
HandleHTTPFileUploadResponse() error
|
|
}
|
|
|
|
//TokenParameters struct
|
|
type TokenParameters struct {
|
|
TokenURL, Username, Password string
|
|
Client piperhttp.Sender
|
|
}
|
|
|
|
//HttpParameters struct
|
|
type HttpFileDownloadRequestParameters struct {
|
|
ErrMessage, FileDownloadPath string
|
|
Response *http.Response
|
|
}
|
|
|
|
//HTTPFileUploadRequestParameters struct
|
|
type HttpFileUploadRequestParameters struct {
|
|
ErrMessage, FilePath, HTTPMethod, HTTPURL, SuccessMessage string
|
|
Response *http.Response
|
|
HTTPErr error
|
|
}
|
|
|
|
// ServiceKey contains information about a CPI service key
|
|
type ServiceKey struct {
|
|
OAuth OAuth `json:"oauth"`
|
|
}
|
|
|
|
// OAuth is inside a CPI service key and contains more needed information
|
|
type OAuth struct {
|
|
Host string `json:"url"`
|
|
OAuthTokenProviderURL string `json:"tokenurl"`
|
|
ClientID string `json:"clientid"`
|
|
ClientSecret string `json:"clientsecret"`
|
|
}
|
|
|
|
// ReadCpiServiceKey unmarshalls the give json service key string.
|
|
func ReadCpiServiceKey(serviceKeyJSON string) (cpiServiceKey ServiceKey, err error) {
|
|
// parse
|
|
err = json.Unmarshal([]byte(serviceKeyJSON), &cpiServiceKey)
|
|
if err != nil {
|
|
err = errors.Wrap(err, "error unmarshalling serviceKey")
|
|
return
|
|
}
|
|
|
|
log.Entry().Info("CPI serviceKey read successfully")
|
|
return
|
|
}
|
|
|
|
// GetBearerToken -Provides the bearer token for making CPI OData calls
|
|
func (tokenParameters TokenParameters) GetBearerToken() (string, error) {
|
|
|
|
httpClient := tokenParameters.Client
|
|
|
|
clientOptions := piperhttp.ClientOptions{
|
|
Username: tokenParameters.Username,
|
|
Password: tokenParameters.Password,
|
|
}
|
|
httpClient.SetOptions(clientOptions)
|
|
|
|
header := make(http.Header)
|
|
header.Add("Accept", "application/json")
|
|
tokenFinalURL := fmt.Sprintf("%s?grant_type=client_credentials", tokenParameters.TokenURL)
|
|
method := "POST"
|
|
resp, httpErr := httpClient.SendRequest(method, tokenFinalURL, nil, header, nil)
|
|
if httpErr != nil {
|
|
return "", errors.Wrapf(httpErr, "HTTP %v request to %v failed with error", method, tokenFinalURL)
|
|
}
|
|
if resp != nil && resp.Body != nil {
|
|
defer resp.Body.Close()
|
|
}
|
|
|
|
if resp == nil {
|
|
return "", errors.Errorf("did not retrieve a HTTP response")
|
|
}
|
|
|
|
if resp.StatusCode != 200 {
|
|
return "", errors.Errorf("did not retrieve a valid HTTP response code: %v", httpErr)
|
|
}
|
|
|
|
bodyText, readErr := ioutil.ReadAll(resp.Body)
|
|
if readErr != nil {
|
|
return "", errors.Wrap(readErr, "HTTP response body could not be read")
|
|
}
|
|
jsonResponse, parsingErr := gabs.ParseJSON([]byte(bodyText))
|
|
if parsingErr != nil {
|
|
return "", errors.Wrapf(parsingErr, "HTTP response body could not be parsed as JSON: %v", string(bodyText))
|
|
}
|
|
token := jsonResponse.Path("access_token").Data().(string)
|
|
return token, nil
|
|
}
|
|
|
|
// HandleHTTPFileDownloadResponse - Handle the file download response for http multipart response
|
|
func (httpFileDownloadRequestParameters HttpFileDownloadRequestParameters) HandleHTTPFileDownloadResponse() error {
|
|
response := httpFileDownloadRequestParameters.Response
|
|
contentDisposition := response.Header.Get("Content-Disposition")
|
|
disposition, params, err := mime.ParseMediaType(contentDisposition)
|
|
if err != nil {
|
|
return errors.Wrapf(err, "failed to read filename from http response headers, Content-Disposition %s", disposition)
|
|
}
|
|
filename := params["filename"]
|
|
|
|
if response != nil && response.Body != nil {
|
|
defer response.Body.Close()
|
|
}
|
|
|
|
if response.StatusCode == 200 {
|
|
workspaceRelativePath := httpFileDownloadRequestParameters.FileDownloadPath
|
|
err = os.MkdirAll(workspaceRelativePath, 0755)
|
|
// handling error while creating a workspce directoy for file download, if one not exist already!
|
|
if err != nil {
|
|
return errors.Wrapf(err, "Failed to create workspace directory")
|
|
}
|
|
zipFileName := filepath.Join(workspaceRelativePath, filename)
|
|
file, err := os.Create(zipFileName)
|
|
// handling error while creating a file in the filesystem
|
|
if err != nil {
|
|
return errors.Wrap(err, "failed to create zip archive of api proxy")
|
|
}
|
|
_, err = io.Copy(file, response.Body)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
return nil
|
|
}
|
|
responseBody, readErr := ioutil.ReadAll(response.Body)
|
|
if readErr != nil {
|
|
return errors.Wrapf(readErr, "HTTP response body could not be read, Response status code: %v", response.StatusCode)
|
|
}
|
|
log.Entry().Errorf("a HTTP error occurred! Response body: %v, Response status code : %v", responseBody, response.StatusCode)
|
|
return errors.Errorf("%s, Response Status code: %v", httpFileDownloadRequestParameters.ErrMessage, response.StatusCode)
|
|
}
|
|
|
|
// HandleHTTPFileUploadResponse - Handle the file upload response
|
|
func (httpFileUploadRequestParameters HttpFileUploadRequestParameters) HandleHTTPFileUploadResponse() error {
|
|
response := httpFileUploadRequestParameters.Response
|
|
httpErr := httpFileUploadRequestParameters.HTTPErr
|
|
if response != nil && response.Body != nil {
|
|
defer response.Body.Close()
|
|
}
|
|
|
|
if response == nil {
|
|
return errors.Errorf("did not retrieve a HTTP response: %v", httpErr)
|
|
}
|
|
|
|
if response.StatusCode == http.StatusOK {
|
|
log.Entry().
|
|
WithField("Created Artifact", httpFileUploadRequestParameters.FilePath).
|
|
Info(httpFileUploadRequestParameters.SuccessMessage)
|
|
return nil
|
|
}
|
|
if httpErr != nil {
|
|
responseBody, readErr := ioutil.ReadAll(response.Body)
|
|
if readErr != nil {
|
|
return errors.Wrapf(readErr, "HTTP response body could not be read, Response status code: %v", response.StatusCode)
|
|
}
|
|
log.Entry().Errorf("a HTTP error occurred! Response body: %v, Response status code: %v", string(responseBody), response.StatusCode)
|
|
return errors.Wrapf(httpErr, "HTTP %v request to %v failed with error: %v", httpFileUploadRequestParameters.HTTPMethod, httpFileUploadRequestParameters.HTTPURL, string(responseBody))
|
|
}
|
|
return errors.Errorf("%s, Response Status code: %v", httpFileUploadRequestParameters.ErrMessage, response.StatusCode)
|
|
}
|