You've already forked sap-jenkins-library
							
							
				mirror of
				https://github.com/SAP/jenkins-library.git
				synced 2025-10-30 23:57:50 +02:00 
			
		
		
		
	IntegrationArtifactUpload Command (#2610)
* IntegrationArtifactUpload Command
This commit is contained in:
		
				
					committed by
					
						 GitHub
						GitHub
					
				
			
			
				
	
			
			
			
						parent
						
							484d9c2ec1
						
					
				
				
					commit
					06afce3005
				
			| @@ -113,5 +113,12 @@ func (c *httpMockCpis) SendRequest(method string, url string, r io.Reader, heade | ||||
| 		} | ||||
| 		return &res, nil | ||||
| 	} | ||||
| 	if c.CPIFunction == "" { | ||||
| 		c.CPIFunction = cpi.GetCPIFunctionNameByURLCheck(url, method, c.TestType) | ||||
| 		resp, error := cpi.GetCPIFunctionMockResponse(c.CPIFunction, c.TestType) | ||||
| 		c.CPIFunction = "" | ||||
| 		return resp, error | ||||
| 	} | ||||
|  | ||||
| 	return cpi.GetCPIFunctionMockResponse(c.CPIFunction, c.TestType) | ||||
| } | ||||
|   | ||||
							
								
								
									
										206
									
								
								cmd/integrationArtifactUpload.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										206
									
								
								cmd/integrationArtifactUpload.go
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,206 @@ | ||||
| package cmd | ||||
|  | ||||
| import ( | ||||
| 	"bytes" | ||||
| 	b64 "encoding/base64" | ||||
| 	"encoding/json" | ||||
| 	"fmt" | ||||
| 	"io/ioutil" | ||||
| 	"net/http" | ||||
|  | ||||
| 	"github.com/Jeffail/gabs/v2" | ||||
| 	"github.com/SAP/jenkins-library/pkg/command" | ||||
| 	"github.com/SAP/jenkins-library/pkg/cpi" | ||||
| 	piperhttp "github.com/SAP/jenkins-library/pkg/http" | ||||
| 	"github.com/SAP/jenkins-library/pkg/log" | ||||
| 	"github.com/SAP/jenkins-library/pkg/piperutils" | ||||
| 	"github.com/SAP/jenkins-library/pkg/telemetry" | ||||
| 	"github.com/pkg/errors" | ||||
| ) | ||||
|  | ||||
| type integrationArtifactUploadUtils interface { | ||||
| 	command.ExecRunner | ||||
|  | ||||
| 	// Add more methods here, or embed additional interfaces, or remove/replace as required. | ||||
| 	// The integrationArtifactUploadUtils interface should be descriptive of your runtime dependencies, | ||||
| 	// i.e. include everything you need to be able to mock in tests. | ||||
| 	// Unit tests shall be executable in parallel (not depend on global state), and don't (re-)test dependencies. | ||||
| } | ||||
|  | ||||
| type integrationArtifactUploadUtilsBundle struct { | ||||
| 	*command.Command | ||||
|  | ||||
| 	// Embed more structs as necessary to implement methods or interfaces you add to integrationArtifactUploadUtils. | ||||
| 	// Structs embedded in this way must each have a unique set of methods attached. | ||||
| 	// If there is no struct which implements the method you need, attach the method to | ||||
| 	// integrationArtifactUploadUtilsBundle and forward to the implementation of the dependency. | ||||
| } | ||||
|  | ||||
| func newIntegrationArtifactUploadUtils() integrationArtifactUploadUtils { | ||||
| 	utils := integrationArtifactUploadUtilsBundle{ | ||||
| 		Command: &command.Command{}, | ||||
| 	} | ||||
| 	// Reroute command output to logging framework | ||||
| 	utils.Stdout(log.Writer()) | ||||
| 	utils.Stderr(log.Writer()) | ||||
| 	return &utils | ||||
| } | ||||
|  | ||||
| func integrationArtifactUpload(config integrationArtifactUploadOptions, telemetryData *telemetry.CustomData) { | ||||
| 	// Utils can be used wherever the command.ExecRunner interface is expected. | ||||
| 	// It can also be used for example as a mavenExecRunner. | ||||
| 	httpClient := &piperhttp.Client{} | ||||
| 	fileUtils := &piperutils.Files{} | ||||
| 	// For HTTP calls import  piperhttp "github.com/SAP/jenkins-library/pkg/http" | ||||
| 	// and use a  &piperhttp.Client{} in a custom system | ||||
| 	// Example: step checkmarxExecuteScan.go | ||||
|  | ||||
| 	// Error situations should be bubbled up until they reach the line below which will then stop execution | ||||
| 	// through the log.Entry().Fatal() call leading to an os.Exit(1) in the end. | ||||
| 	err := runIntegrationArtifactUpload(&config, telemetryData, fileUtils, httpClient) | ||||
| 	if err != nil { | ||||
| 		log.Entry().WithError(err).Fatal("step execution failed") | ||||
| 	} | ||||
| } | ||||
|  | ||||
| func runIntegrationArtifactUpload(config *integrationArtifactUploadOptions, telemetryData *telemetry.CustomData, fileUtils piperutils.FileUtils, httpClient piperhttp.Sender) error { | ||||
| 	clientOptions := piperhttp.ClientOptions{} | ||||
| 	header := make(http.Header) | ||||
| 	header.Add("Accept", "application/json") | ||||
| 	iFlowStatusServiceURL := fmt.Sprintf("%s/api/v1/IntegrationDesigntimeArtifacts(Id='%s',Version='%s')", config.Host, config.IntegrationFlowID, config.IntegrationFlowVersion) | ||||
| 	tokenParameters := cpi.TokenParameters{TokenURL: config.OAuthTokenProviderURL, Username: config.Username, Password: config.Password, Client: httpClient} | ||||
| 	token, err := cpi.CommonUtils.GetBearerToken(tokenParameters) | ||||
| 	if err != nil { | ||||
| 		return errors.Wrap(err, "failed to fetch Bearer Token") | ||||
| 	} | ||||
| 	clientOptions.Token = fmt.Sprintf("Bearer %s", token) | ||||
| 	httpClient.SetOptions(clientOptions) | ||||
| 	httpMethod := "GET" | ||||
|  | ||||
| 	//Check availability of integration artefact in CPI design time | ||||
| 	iFlowStatusResp, httpErr := httpClient.SendRequest(httpMethod, iFlowStatusServiceURL, nil, header, nil) | ||||
|  | ||||
| 	if iFlowStatusResp != nil && iFlowStatusResp.Body != nil { | ||||
| 		defer iFlowStatusResp.Body.Close() | ||||
| 	} | ||||
| 	if iFlowStatusResp.StatusCode == 200 { | ||||
| 		return UpdateIntegrationArtifact(config, httpClient, fileUtils) | ||||
| 	} else if httpErr != nil && iFlowStatusResp.StatusCode == 404 { | ||||
| 		return UploadIntegrationArtifact(config, httpClient, fileUtils) | ||||
| 	} | ||||
|  | ||||
| 	if iFlowStatusResp == nil { | ||||
| 		return errors.Errorf("did not retrieve a HTTP response: %v", httpErr) | ||||
| 	} | ||||
|  | ||||
| 	if httpErr != nil { | ||||
| 		responseBody, readErr := ioutil.ReadAll(iFlowStatusResp.Body) | ||||
| 		if readErr != nil { | ||||
| 			return errors.Wrapf(readErr, "HTTP response body could not be read, Response status code: %v", iFlowStatusResp.StatusCode) | ||||
| 		} | ||||
| 		log.Entry().Errorf("a HTTP error occurred! Response body: %v, Response status code: %v", responseBody, iFlowStatusResp.StatusCode) | ||||
| 		return errors.Wrapf(httpErr, "HTTP %v request to %v failed with error: %v", httpMethod, iFlowStatusServiceURL, responseBody) | ||||
| 	} | ||||
| 	return errors.Errorf("Failed to check integration flow availability, Response Status code: %v", iFlowStatusResp.StatusCode) | ||||
| } | ||||
|  | ||||
| //UploadIntegrationArtifact - Upload new integration artifact | ||||
| func UploadIntegrationArtifact(config *integrationArtifactUploadOptions, httpClient piperhttp.Sender, fileUtils piperutils.FileUtils) error { | ||||
| 	httpMethod := "POST" | ||||
| 	uploadIflowStatusURL := fmt.Sprintf("%s/api/v1/IntegrationDesigntimeArtifacts", config.Host) | ||||
| 	header := make(http.Header) | ||||
| 	header.Add("content-type", "application/json") | ||||
| 	payload, jsonError := GetJSONPayloadAsByteArray(config, "create", fileUtils) | ||||
| 	if jsonError != nil { | ||||
| 		return errors.Wrapf(jsonError, "Failed to get json payload for file %v, failed with error", config.FilePath) | ||||
| 	} | ||||
|  | ||||
| 	uploadIflowStatusResp, httpErr := httpClient.SendRequest(httpMethod, uploadIflowStatusURL, payload, header, nil) | ||||
|  | ||||
| 	if uploadIflowStatusResp != nil && uploadIflowStatusResp.Body != nil { | ||||
| 		defer uploadIflowStatusResp.Body.Close() | ||||
| 	} | ||||
|  | ||||
| 	if uploadIflowStatusResp == nil { | ||||
| 		return errors.Errorf("did not retrieve a HTTP response: %v", httpErr) | ||||
| 	} | ||||
|  | ||||
| 	if uploadIflowStatusResp.StatusCode == http.StatusCreated { | ||||
| 		log.Entry(). | ||||
| 			WithField("IntegrationFlowID", config.IntegrationFlowID). | ||||
| 			Info("Successfully created integration flow artefact in CPI designtime") | ||||
| 		return nil | ||||
| 	} | ||||
| 	if httpErr != nil { | ||||
| 		responseBody, readErr := ioutil.ReadAll(uploadIflowStatusResp.Body) | ||||
| 		if readErr != nil { | ||||
| 			return errors.Wrapf(readErr, "HTTP response body could not be read, Response status code: %v", uploadIflowStatusResp.StatusCode) | ||||
| 		} | ||||
| 		log.Entry().Errorf("a HTTP error occurred! Response body: %v, Response status code: %v", responseBody, uploadIflowStatusResp.StatusCode) | ||||
| 		return errors.Wrapf(httpErr, "HTTP %v request to %v failed with error: %v", httpMethod, uploadIflowStatusURL, responseBody) | ||||
| 	} | ||||
| 	return errors.Errorf("Failed to create Integration Flow artefact, Response Status code: %v", uploadIflowStatusResp.StatusCode) | ||||
| } | ||||
|  | ||||
| //UpdateIntegrationArtifact - Update existing integration artifact | ||||
| func UpdateIntegrationArtifact(config *integrationArtifactUploadOptions, httpClient piperhttp.Sender, fileUtils piperutils.FileUtils) error { | ||||
| 	httpMethod := "POST" | ||||
| 	header := make(http.Header) | ||||
| 	header.Add("content-type", "application/json") | ||||
| 	updateIflowStatusURL := fmt.Sprintf("%s/api/v1/IntegrationDesigntimeArtifactSaveAsVersion?Id='%s'&SaveAsVersion='%s'", config.Host, config.IntegrationFlowID, config.IntegrationFlowVersion) | ||||
| 	payload, jsonError := GetJSONPayloadAsByteArray(config, "update", fileUtils) | ||||
| 	if jsonError != nil { | ||||
| 		return errors.Wrapf(jsonError, "Failed to get json payload for file %v, failed with error", config.FilePath) | ||||
| 	} | ||||
| 	updateIflowStatusResp, httpErr := httpClient.SendRequest(httpMethod, updateIflowStatusURL, payload, header, nil) | ||||
|  | ||||
| 	if updateIflowStatusResp != nil && updateIflowStatusResp.Body != nil { | ||||
| 		defer updateIflowStatusResp.Body.Close() | ||||
| 	} | ||||
|  | ||||
| 	if updateIflowStatusResp == nil { | ||||
| 		return errors.Errorf("did not retrieve a HTTP response: %v", httpErr) | ||||
| 	} | ||||
|  | ||||
| 	if updateIflowStatusResp.StatusCode == http.StatusOK { | ||||
| 		log.Entry(). | ||||
| 			WithField("IntegrationFlowID", config.IntegrationFlowID). | ||||
| 			Info("Successfully updated integration flow artefact in CPI designtime") | ||||
| 		return nil | ||||
| 	} | ||||
| 	if httpErr != nil { | ||||
| 		responseBody, readErr := ioutil.ReadAll(updateIflowStatusResp.Body) | ||||
| 		if readErr != nil { | ||||
| 			return errors.Wrapf(readErr, "HTTP response body could not be read, Response status code: %v", updateIflowStatusResp.StatusCode) | ||||
| 		} | ||||
| 		log.Entry().Errorf("a HTTP error occurred! Response body: %v, Response status code: %v", responseBody, updateIflowStatusResp.StatusCode) | ||||
| 		return errors.Wrapf(httpErr, "HTTP %v request to %v failed with error: %v", httpMethod, updateIflowStatusURL, responseBody) | ||||
| 	} | ||||
| 	return errors.Errorf("Failed to update Integration Flow artefact, Response Status code: %v", updateIflowStatusResp.StatusCode) | ||||
| } | ||||
|  | ||||
| //GetJSONPayloadAsByteArray -return http payload as byte array | ||||
| func GetJSONPayloadAsByteArray(config *integrationArtifactUploadOptions, mode string, fileUtils piperutils.FileUtils) (*bytes.Buffer, error) { | ||||
| 	fileContent, readError := fileUtils.FileRead(config.FilePath) | ||||
| 	if readError != nil { | ||||
| 		return nil, errors.Wrapf(readError, "Error reading file") | ||||
| 	} | ||||
| 	jsonObj := gabs.New() | ||||
| 	if mode == "create" { | ||||
| 		jsonObj.Set(config.IntegrationFlowID, "Name") | ||||
| 		jsonObj.Set(config.IntegrationFlowID, "Id") | ||||
| 		jsonObj.Set(config.PackageID, "PackageId") | ||||
| 		jsonObj.Set(b64.StdEncoding.EncodeToString(fileContent), "ArtifactContent") | ||||
| 	} else if mode == "update" { | ||||
| 		jsonObj.Set(b64.StdEncoding.EncodeToString(fileContent), "ArtifactContent") | ||||
| 	} else { | ||||
| 		return nil, fmt.Errorf("Unkown node: '%s'", mode) | ||||
| 	} | ||||
|  | ||||
| 	jsonBody, jsonErr := json.Marshal(jsonObj) | ||||
|  | ||||
| 	if jsonErr != nil { | ||||
| 		return nil, errors.Wrapf(jsonErr, "json payload is invalid for integration flow artifact %q", config.IntegrationFlowID) | ||||
| 	} | ||||
| 	return bytes.NewBuffer(jsonBody), nil | ||||
| } | ||||
							
								
								
									
										208
									
								
								cmd/integrationArtifactUpload_generated.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										208
									
								
								cmd/integrationArtifactUpload_generated.go
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,208 @@ | ||||
| // Code generated by piper's step-generator. DO NOT EDIT. | ||||
|  | ||||
| package cmd | ||||
|  | ||||
| import ( | ||||
| 	"fmt" | ||||
| 	"os" | ||||
| 	"time" | ||||
|  | ||||
| 	"github.com/SAP/jenkins-library/pkg/config" | ||||
| 	"github.com/SAP/jenkins-library/pkg/log" | ||||
| 	"github.com/SAP/jenkins-library/pkg/telemetry" | ||||
| 	"github.com/spf13/cobra" | ||||
| ) | ||||
|  | ||||
| type integrationArtifactUploadOptions struct { | ||||
| 	Username               string `json:"username,omitempty"` | ||||
| 	Password               string `json:"password,omitempty"` | ||||
| 	IntegrationFlowID      string `json:"integrationFlowId,omitempty"` | ||||
| 	IntegrationFlowVersion string `json:"integrationFlowVersion,omitempty"` | ||||
| 	IntegrationFlowName    string `json:"integrationFlowName,omitempty"` | ||||
| 	PackageID              string `json:"packageId,omitempty"` | ||||
| 	Host                   string `json:"host,omitempty"` | ||||
| 	OAuthTokenProviderURL  string `json:"oAuthTokenProviderUrl,omitempty"` | ||||
| 	FilePath               string `json:"filePath,omitempty"` | ||||
| } | ||||
|  | ||||
| // IntegrationArtifactUploadCommand Upload or Update an integration flow designtime artefact | ||||
| func IntegrationArtifactUploadCommand() *cobra.Command { | ||||
| 	const STEP_NAME = "integrationArtifactUpload" | ||||
|  | ||||
| 	metadata := integrationArtifactUploadMetadata() | ||||
| 	var stepConfig integrationArtifactUploadOptions | ||||
| 	var startTime time.Time | ||||
|  | ||||
| 	var createIntegrationArtifactUploadCmd = &cobra.Command{ | ||||
| 		Use:   STEP_NAME, | ||||
| 		Short: "Upload or Update an integration flow designtime artefact", | ||||
| 		Long:  `With this step you can either upload or update a integration flow designtime artifact using the OData API. Learn more about the SAP Cloud Integration remote API for updating an integration flow artifact [here](https://help.sap.com/viewer/368c481cd6954bdfa5d0435479fd4eaf/Cloud/en-US/83733a65c0214aa6acba035e8640bb5a.html).`, | ||||
| 		PreRunE: func(cmd *cobra.Command, _ []string) error { | ||||
| 			startTime = time.Now() | ||||
| 			log.SetStepName(STEP_NAME) | ||||
| 			log.SetVerbose(GeneralConfig.Verbose) | ||||
|  | ||||
| 			path, _ := os.Getwd() | ||||
| 			fatalHook := &log.FatalHook{CorrelationID: GeneralConfig.CorrelationID, Path: path} | ||||
| 			log.RegisterHook(fatalHook) | ||||
|  | ||||
| 			err := PrepareConfig(cmd, &metadata, STEP_NAME, &stepConfig, config.OpenPiperFile) | ||||
| 			if err != nil { | ||||
| 				log.SetErrorCategory(log.ErrorConfiguration) | ||||
| 				return err | ||||
| 			} | ||||
| 			log.RegisterSecret(stepConfig.Username) | ||||
| 			log.RegisterSecret(stepConfig.Password) | ||||
|  | ||||
| 			if len(GeneralConfig.HookConfig.SentryConfig.Dsn) > 0 { | ||||
| 				sentryHook := log.NewSentryHook(GeneralConfig.HookConfig.SentryConfig.Dsn, GeneralConfig.CorrelationID) | ||||
| 				log.RegisterHook(&sentryHook) | ||||
| 			} | ||||
|  | ||||
| 			return nil | ||||
| 		}, | ||||
| 		Run: func(_ *cobra.Command, _ []string) { | ||||
| 			telemetryData := telemetry.CustomData{} | ||||
| 			telemetryData.ErrorCode = "1" | ||||
| 			handler := func() { | ||||
| 				config.RemoveVaultSecretFiles() | ||||
| 				telemetryData.Duration = fmt.Sprintf("%v", time.Since(startTime).Milliseconds()) | ||||
| 				telemetryData.ErrorCategory = log.GetErrorCategory().String() | ||||
| 				telemetry.Send(&telemetryData) | ||||
| 			} | ||||
| 			log.DeferExitHandler(handler) | ||||
| 			defer handler() | ||||
| 			telemetry.Initialize(GeneralConfig.NoTelemetry, STEP_NAME) | ||||
| 			integrationArtifactUpload(stepConfig, &telemetryData) | ||||
| 			telemetryData.ErrorCode = "0" | ||||
| 			log.Entry().Info("SUCCESS") | ||||
| 		}, | ||||
| 	} | ||||
|  | ||||
| 	addIntegrationArtifactUploadFlags(createIntegrationArtifactUploadCmd, &stepConfig) | ||||
| 	return createIntegrationArtifactUploadCmd | ||||
| } | ||||
|  | ||||
| func addIntegrationArtifactUploadFlags(cmd *cobra.Command, stepConfig *integrationArtifactUploadOptions) { | ||||
| 	cmd.Flags().StringVar(&stepConfig.Username, "username", os.Getenv("PIPER_username"), "User to authenticate to the SAP Cloud Platform Integration Service") | ||||
| 	cmd.Flags().StringVar(&stepConfig.Password, "password", os.Getenv("PIPER_password"), "Password to authenticate to the SAP Cloud Platform Integration Service") | ||||
| 	cmd.Flags().StringVar(&stepConfig.IntegrationFlowID, "integrationFlowId", os.Getenv("PIPER_integrationFlowId"), "Specifies the ID of the Integration Flow artifact") | ||||
| 	cmd.Flags().StringVar(&stepConfig.IntegrationFlowVersion, "integrationFlowVersion", os.Getenv("PIPER_integrationFlowVersion"), "Specifies the version of the Integration Flow artifact") | ||||
| 	cmd.Flags().StringVar(&stepConfig.IntegrationFlowName, "integrationFlowName", os.Getenv("PIPER_integrationFlowName"), "Specifies the Name of the Integration Flow artifact") | ||||
| 	cmd.Flags().StringVar(&stepConfig.PackageID, "packageId", os.Getenv("PIPER_packageId"), "Specifies the ID of the Integration Package") | ||||
| 	cmd.Flags().StringVar(&stepConfig.Host, "host", os.Getenv("PIPER_host"), "Specifies the protocol and host address, including the port. Please provide in the format `<protocol>://<host>:<port>`. Supported protocols are `http` and `https`.") | ||||
| 	cmd.Flags().StringVar(&stepConfig.OAuthTokenProviderURL, "oAuthTokenProviderUrl", os.Getenv("PIPER_oAuthTokenProviderUrl"), "Specifies the oAuth Provider protocol and host address, including the port. Please provide in the format `<protocol>://<host>:<port>`. Supported protocols are `http` and `https`.") | ||||
| 	cmd.Flags().StringVar(&stepConfig.FilePath, "filePath", os.Getenv("PIPER_filePath"), "Specifies integration artifact relative file path.") | ||||
|  | ||||
| 	cmd.MarkFlagRequired("username") | ||||
| 	cmd.MarkFlagRequired("password") | ||||
| 	cmd.MarkFlagRequired("integrationFlowId") | ||||
| 	cmd.MarkFlagRequired("integrationFlowVersion") | ||||
| 	cmd.MarkFlagRequired("integrationFlowName") | ||||
| 	cmd.MarkFlagRequired("packageId") | ||||
| 	cmd.MarkFlagRequired("host") | ||||
| 	cmd.MarkFlagRequired("oAuthTokenProviderUrl") | ||||
| 	cmd.MarkFlagRequired("filePath") | ||||
| } | ||||
|  | ||||
| // retrieve step metadata | ||||
| func integrationArtifactUploadMetadata() config.StepData { | ||||
| 	var theMetaData = config.StepData{ | ||||
| 		Metadata: config.StepMetadata{ | ||||
| 			Name:        "integrationArtifactUpload", | ||||
| 			Aliases:     []config.Alias{}, | ||||
| 			Description: "Upload or Update an integration flow designtime artefact", | ||||
| 		}, | ||||
| 		Spec: config.StepSpec{ | ||||
| 			Inputs: config.StepInputs{ | ||||
| 				Parameters: []config.StepParameters{ | ||||
| 					{ | ||||
| 						Name: "username", | ||||
| 						ResourceRef: []config.ResourceReference{ | ||||
| 							{ | ||||
| 								Name:  "cpiCredentialsId", | ||||
| 								Param: "username", | ||||
| 								Type:  "secret", | ||||
| 							}, | ||||
| 						}, | ||||
| 						Scope:     []string{"PARAMETERS", "STAGES", "STEPS"}, | ||||
| 						Type:      "string", | ||||
| 						Mandatory: true, | ||||
| 						Aliases:   []config.Alias{}, | ||||
| 					}, | ||||
| 					{ | ||||
| 						Name: "password", | ||||
| 						ResourceRef: []config.ResourceReference{ | ||||
| 							{ | ||||
| 								Name:  "cpiCredentialsId", | ||||
| 								Param: "password", | ||||
| 								Type:  "secret", | ||||
| 							}, | ||||
| 						}, | ||||
| 						Scope:     []string{"PARAMETERS", "STAGES", "STEPS"}, | ||||
| 						Type:      "string", | ||||
| 						Mandatory: true, | ||||
| 						Aliases:   []config.Alias{}, | ||||
| 					}, | ||||
| 					{ | ||||
| 						Name:        "integrationFlowId", | ||||
| 						ResourceRef: []config.ResourceReference{}, | ||||
| 						Scope:       []string{"PARAMETERS", "STAGES", "STEPS"}, | ||||
| 						Type:        "string", | ||||
| 						Mandatory:   true, | ||||
| 						Aliases:     []config.Alias{}, | ||||
| 					}, | ||||
| 					{ | ||||
| 						Name:        "integrationFlowVersion", | ||||
| 						ResourceRef: []config.ResourceReference{}, | ||||
| 						Scope:       []string{"PARAMETERS", "STAGES", "STEPS"}, | ||||
| 						Type:        "string", | ||||
| 						Mandatory:   true, | ||||
| 						Aliases:     []config.Alias{}, | ||||
| 					}, | ||||
| 					{ | ||||
| 						Name:        "integrationFlowName", | ||||
| 						ResourceRef: []config.ResourceReference{}, | ||||
| 						Scope:       []string{"PARAMETERS", "STAGES", "STEPS"}, | ||||
| 						Type:        "string", | ||||
| 						Mandatory:   true, | ||||
| 						Aliases:     []config.Alias{}, | ||||
| 					}, | ||||
| 					{ | ||||
| 						Name:        "packageId", | ||||
| 						ResourceRef: []config.ResourceReference{}, | ||||
| 						Scope:       []string{"PARAMETERS", "STAGES", "STEPS"}, | ||||
| 						Type:        "string", | ||||
| 						Mandatory:   true, | ||||
| 						Aliases:     []config.Alias{}, | ||||
| 					}, | ||||
| 					{ | ||||
| 						Name:        "host", | ||||
| 						ResourceRef: []config.ResourceReference{}, | ||||
| 						Scope:       []string{"PARAMETERS", "STAGES", "STEPS"}, | ||||
| 						Type:        "string", | ||||
| 						Mandatory:   true, | ||||
| 						Aliases:     []config.Alias{}, | ||||
| 					}, | ||||
| 					{ | ||||
| 						Name:        "oAuthTokenProviderUrl", | ||||
| 						ResourceRef: []config.ResourceReference{}, | ||||
| 						Scope:       []string{"PARAMETERS", "STAGES", "STEPS"}, | ||||
| 						Type:        "string", | ||||
| 						Mandatory:   true, | ||||
| 						Aliases:     []config.Alias{}, | ||||
| 					}, | ||||
| 					{ | ||||
| 						Name:        "filePath", | ||||
| 						ResourceRef: []config.ResourceReference{}, | ||||
| 						Scope:       []string{"PARAMETERS", "STAGES", "STEPS"}, | ||||
| 						Type:        "string", | ||||
| 						Mandatory:   true, | ||||
| 						Aliases:     []config.Alias{}, | ||||
| 					}, | ||||
| 				}, | ||||
| 			}, | ||||
| 		}, | ||||
| 	} | ||||
| 	return theMetaData | ||||
| } | ||||
							
								
								
									
										17
									
								
								cmd/integrationArtifactUpload_generated_test.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										17
									
								
								cmd/integrationArtifactUpload_generated_test.go
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,17 @@ | ||||
| package cmd | ||||
|  | ||||
| import ( | ||||
| 	"testing" | ||||
|  | ||||
| 	"github.com/stretchr/testify/assert" | ||||
| ) | ||||
|  | ||||
| func TestIntegrationArtifactUploadCommand(t *testing.T) { | ||||
| 	t.Parallel() | ||||
|  | ||||
| 	testCmd := IntegrationArtifactUploadCommand() | ||||
|  | ||||
| 	// only high level testing performed - details are tested in step generation procedure | ||||
| 	assert.Equal(t, "integrationArtifactUpload", testCmd.Use, "command name incorrect") | ||||
|  | ||||
| } | ||||
							
								
								
									
										170
									
								
								cmd/integrationArtifactUpload_test.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										170
									
								
								cmd/integrationArtifactUpload_test.go
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,170 @@ | ||||
| package cmd | ||||
|  | ||||
| import ( | ||||
| 	"path/filepath" | ||||
| 	"testing" | ||||
|  | ||||
| 	"github.com/SAP/jenkins-library/pkg/mock" | ||||
| 	"github.com/stretchr/testify/assert" | ||||
| ) | ||||
|  | ||||
| type integrationArtifactUploadMockUtils struct { | ||||
| 	*mock.ExecMockRunner | ||||
| 	*mock.FilesMock | ||||
| } | ||||
|  | ||||
| func newIntegrationArtifactUploadTestsUtils() integrationArtifactUploadMockUtils { | ||||
| 	utils := integrationArtifactUploadMockUtils{ | ||||
| 		ExecMockRunner: &mock.ExecMockRunner{}, | ||||
| 		FilesMock:      &mock.FilesMock{}, | ||||
| 	} | ||||
| 	return utils | ||||
| } | ||||
|  | ||||
| func TestRunIntegrationArtifactUpload(t *testing.T) { | ||||
| 	t.Parallel() | ||||
|  | ||||
| 	t.Run("Successfull Integration Flow Create Test", func(t *testing.T) { | ||||
| 		filesMock := mock.FilesMock{} | ||||
| 		path := filepath.Join("tempDir", "iflow4.zip") | ||||
| 		filesMock.AddFile(path, []byte("dummy content")) | ||||
| 		exists, err := filesMock.FileExists(path) | ||||
| 		assert.NoError(t, err) | ||||
| 		assert.True(t, exists) | ||||
|  | ||||
| 		config := integrationArtifactUploadOptions{ | ||||
| 			Host:                   "https://demo", | ||||
| 			OAuthTokenProviderURL:  "https://demo/oauth/token", | ||||
| 			Username:               "demouser", | ||||
| 			Password:               "******", | ||||
| 			IntegrationFlowName:    "flow4", | ||||
| 			IntegrationFlowID:      "flow4", | ||||
| 			IntegrationFlowVersion: "1.0.4", | ||||
| 			PackageID:              "CICD", | ||||
| 			FilePath:               path, | ||||
| 		} | ||||
|  | ||||
| 		httpClient := httpMockCpis{CPIFunction: "", ResponseBody: ``, TestType: "PositiveAndCreateIntegrationDesigntimeArtifactResBody"} | ||||
|  | ||||
| 		err = runIntegrationArtifactUpload(&config, nil, &filesMock, &httpClient) | ||||
|  | ||||
| 		if assert.NoError(t, err) { | ||||
|  | ||||
| 			t.Run("check url", func(t *testing.T) { | ||||
| 				assert.Equal(t, "https://demo/api/v1/IntegrationDesigntimeArtifactSaveAsVersion?Id='flow4'&SaveAsVersion='1.0.4'", httpClient.URL) | ||||
| 			}) | ||||
|  | ||||
| 			t.Run("check method", func(t *testing.T) { | ||||
| 				assert.Equal(t, "POST", httpClient.Method) | ||||
| 			}) | ||||
| 		} | ||||
| 	}) | ||||
|  | ||||
| 	t.Run("Successfull Integration Flow Update Test", func(t *testing.T) { | ||||
|  | ||||
| 		files := mock.FilesMock{} | ||||
| 		path := filepath.Join("tempDir", "iflow4.zip") | ||||
| 		files.AddFile(path, []byte("dummy content")) | ||||
| 		exists, err := files.FileExists(path) | ||||
| 		assert.NoError(t, err) | ||||
| 		assert.True(t, exists) | ||||
| 		config := integrationArtifactUploadOptions{ | ||||
| 			Host:                   "https://demo", | ||||
| 			OAuthTokenProviderURL:  "https://demo/oauth/token", | ||||
| 			Username:               "demouser", | ||||
| 			Password:               "******", | ||||
| 			IntegrationFlowName:    "flow4", | ||||
| 			IntegrationFlowID:      "flow4", | ||||
| 			IntegrationFlowVersion: "1.0.4", | ||||
| 			PackageID:              "CICD", | ||||
| 			FilePath:               path, | ||||
| 		} | ||||
|  | ||||
| 		httpClient := httpMockCpis{CPIFunction: "", ResponseBody: ``, TestType: "PositiveAndUpdateIntegrationDesigntimeArtifactResBody"} | ||||
|  | ||||
| 		err = runIntegrationArtifactUpload(&config, nil, &files, &httpClient) | ||||
|  | ||||
| 		if assert.NoError(t, err) { | ||||
|  | ||||
| 			t.Run("check url", func(t *testing.T) { | ||||
| 				assert.Equal(t, "https://demo/api/v1/IntegrationDesigntimeArtifacts", httpClient.URL) | ||||
| 			}) | ||||
|  | ||||
| 			t.Run("check method", func(t *testing.T) { | ||||
| 				assert.Equal(t, "POST", httpClient.Method) | ||||
| 			}) | ||||
| 		} | ||||
| 	}) | ||||
|  | ||||
| 	t.Run("Failed case of Integration Flow Get Test", func(t *testing.T) { | ||||
|  | ||||
| 		config := integrationArtifactUploadOptions{ | ||||
| 			Host:                   "https://demo", | ||||
| 			OAuthTokenProviderURL:  "https://demo/oauth/token", | ||||
| 			Username:               "demouser", | ||||
| 			Password:               "******", | ||||
| 			IntegrationFlowName:    "flow4", | ||||
| 			IntegrationFlowID:      "flow4", | ||||
| 			IntegrationFlowVersion: "1.0.4", | ||||
| 			PackageID:              "CICD", | ||||
| 			FilePath:               "path", | ||||
| 		} | ||||
|  | ||||
| 		httpClient := httpMockCpis{CPIFunction: "", ResponseBody: ``, TestType: "NegativeAndGetIntegrationDesigntimeArtifactResBody"} | ||||
|  | ||||
| 		err := runIntegrationArtifactUpload(&config, nil, nil, &httpClient) | ||||
| 		assert.Error(t, err) | ||||
| 	}) | ||||
|  | ||||
| 	t.Run("Failed case of Integration Flow Update Test", func(t *testing.T) { | ||||
| 		files := mock.FilesMock{} | ||||
| 		path := filepath.Join("tempDir", "iflow4.zip") | ||||
| 		files.AddFile(path, []byte("dummy content")) | ||||
| 		exists, err := files.FileExists(path) | ||||
| 		assert.NoError(t, err) | ||||
| 		assert.True(t, exists) | ||||
|  | ||||
| 		config := integrationArtifactUploadOptions{ | ||||
| 			Host:                   "https://demo", | ||||
| 			OAuthTokenProviderURL:  "https://demo/oauth/token", | ||||
| 			Username:               "demouser", | ||||
| 			Password:               "******", | ||||
| 			IntegrationFlowName:    "flow4", | ||||
| 			IntegrationFlowID:      "flow4", | ||||
| 			IntegrationFlowVersion: "1.0.4", | ||||
| 			PackageID:              "CICD", | ||||
| 			FilePath:               path, | ||||
| 		} | ||||
|  | ||||
| 		httpClient := httpMockCpis{CPIFunction: "", ResponseBody: ``, TestType: "NegativeAndCreateIntegrationDesigntimeArtifactResBody"} | ||||
|  | ||||
| 		err = runIntegrationArtifactUpload(&config, nil, &files, &httpClient) | ||||
| 		assert.EqualError(t, err, "HTTP POST request to https://demo/api/v1/IntegrationDesigntimeArtifactSaveAsVersion?Id='flow4'&SaveAsVersion='1.0.4' failed with error: []: Internal error") | ||||
| 	}) | ||||
|  | ||||
| 	t.Run("Failed case of Integration Flow Create Test", func(t *testing.T) { | ||||
| 		filesMock := mock.FilesMock{} | ||||
| 		path := filepath.Join("tempDir", "iflow4.zip") | ||||
| 		filesMock.AddFile(path, []byte("dummy content")) | ||||
| 		exists, err := filesMock.FileExists(path) | ||||
| 		assert.NoError(t, err) | ||||
| 		assert.True(t, exists) | ||||
|  | ||||
| 		config := integrationArtifactUploadOptions{ | ||||
| 			Host:                   "https://demo", | ||||
| 			OAuthTokenProviderURL:  "https://demo/oauth/token", | ||||
| 			Username:               "demouser", | ||||
| 			Password:               "******", | ||||
| 			IntegrationFlowName:    "flow4", | ||||
| 			IntegrationFlowID:      "flow4", | ||||
| 			IntegrationFlowVersion: "1.0.4", | ||||
| 			PackageID:              "CICD", | ||||
| 			FilePath:               path, | ||||
| 		} | ||||
|  | ||||
| 		httpClient := httpMockCpis{CPIFunction: "", ResponseBody: ``, TestType: "NegativeAndUpdateIntegrationDesigntimeArtifactResBody"} | ||||
|  | ||||
| 		err = runIntegrationArtifactUpload(&config, nil, &filesMock, &httpClient) | ||||
| 		assert.EqualError(t, err, "HTTP POST request to https://demo/api/v1/IntegrationDesigntimeArtifacts failed with error: []: Internal error") | ||||
| 	}) | ||||
| } | ||||
| @@ -50,6 +50,7 @@ func GetAllStepMetadata() map[string]config.StepData { | ||||
| 		"integrationArtifactGetMplStatus":         integrationArtifactGetMplStatusMetadata(), | ||||
| 		"integrationArtifactGetServiceEndpoint":   integrationArtifactGetServiceEndpointMetadata(), | ||||
| 		"integrationArtifactUpdateConfiguration":  integrationArtifactUpdateConfigurationMetadata(), | ||||
| 		"integrationArtifactUpload":               integrationArtifactUploadMetadata(), | ||||
| 		"jsonApplyPatch":                          jsonApplyPatchMetadata(), | ||||
| 		"kanikoExecute":                           kanikoExecuteMetadata(), | ||||
| 		"karmaExecuteTests":                       karmaExecuteTestsMetadata(), | ||||
|   | ||||
| @@ -132,6 +132,7 @@ func Execute() { | ||||
| 	rootCmd.AddCommand(IntegrationArtifactGetMplStatusCommand()) | ||||
| 	rootCmd.AddCommand(IntegrationArtifactDownloadCommand()) | ||||
| 	rootCmd.AddCommand(AbapEnvironmentAssembleConfirmCommand()) | ||||
| 	rootCmd.AddCommand(IntegrationArtifactUploadCommand()) | ||||
|  | ||||
| 	addRootFlags(rootCmd) | ||||
| 	if err := rootCmd.Execute(); err != nil { | ||||
|   | ||||
							
								
								
									
										36
									
								
								documentation/docs/steps/integrationArtifactUpload.md
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										36
									
								
								documentation/docs/steps/integrationArtifactUpload.md
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,36 @@ | ||||
| # ${docGenStepName} | ||||
|  | ||||
| ## ${docGenDescription} | ||||
|  | ||||
| ## Prerequisites | ||||
|  | ||||
| ## ${docGenParameters} | ||||
|  | ||||
| ## ${docGenConfiguration} | ||||
|  | ||||
| ## ${docJenkinsPluginDependencies} | ||||
|  | ||||
| ## Example | ||||
|  | ||||
| Example configuration for the use in a `Jenkinsfile`. | ||||
|  | ||||
| ```groovy | ||||
| integrationArtifactUpload script: this | ||||
| ``` | ||||
|  | ||||
| Example for the use in a YAML configuration file (such as `.pipeline/config.yaml`). | ||||
|  | ||||
| ```yaml | ||||
| steps: | ||||
|   <...> | ||||
|   integrationArtifactUpload: | ||||
|     cpiCredentialsId: 'MY_CPI_OAUTH_CREDENTIALSID_IN_JENKINS' | ||||
|     integrationFlowId: 'MY_INTEGRATION_FLOW_ID' | ||||
|     integrationFlowVersion: 'MY_INTEGRATION_FLOW_VERSION' | ||||
|     integrationFlowName: 'MY_INTEGRATION_FLOW_Name' | ||||
|     packageId: 'MY_INTEGRATION_Package_ID' | ||||
|     filePath: 'MY_INTEGRATION_FLOW_Artifact_Relative_Path' | ||||
|     host: https://CPI_HOST_ITSPACES_URL | ||||
|     oAuthTokenProviderUrl: https://CPI_HOST_OAUTH_URL | ||||
|     downloadPath: /MY_INTEGRATION_FLOW_DOWNLOAD_PATH | ||||
| ``` | ||||
| @@ -106,6 +106,7 @@ nav: | ||||
|         - integrationArtifactGetMplStatus: steps/integrationArtifactGetMplStatus.md | ||||
|         - integrationArtifactGetServiceEndpoint: steps/integrationArtifactGetServiceEndpoint.md | ||||
|         - integrationArtifactUpdateConfiguration: steps/integrationArtifactUpdateConfiguration.md | ||||
|         - integrationArtifactUpload: steps/integrationArtifactUpload.md | ||||
|         - jenkinsMaterializeLog: steps/jenkinsMaterializeLog.md | ||||
|         - kanikoExecute: steps/kanikoExecute.md | ||||
|         - karmaExecuteTests: steps/karmaExecuteTests.md | ||||
|   | ||||
| @@ -35,23 +35,25 @@ func GetCPIFunctionMockResponse(functionName, testType string) (*http.Response, | ||||
| 		if testType == "Negative_With_ResponseBody" { | ||||
| 			return GetNegativeCaseHTTPResponseBodyAndErrorNil() | ||||
| 		} | ||||
| 		res := http.Response{ | ||||
| 			StatusCode: 404, | ||||
| 			Body: ioutil.NopCloser(bytes.NewReader([]byte(`{ | ||||
| 						"code": "Not Found", | ||||
| 						"message": { | ||||
| 						"@lang": "en", | ||||
| 						"#text": "Parameter key 'Parameter1' not found." | ||||
| 						} | ||||
| 					}`))), | ||||
| 		} | ||||
| 		return &res, errors.New("Not found - either wrong version for the given Id or wrong parameter key") | ||||
| 		return GetParameterKeyMissingResponseBody() | ||||
| 	case "IntegrationArtifactGetMplStatus": | ||||
| 		return GetIntegrationArtifactGetMplStatusCommandMockResponse(testType) | ||||
| 	case "IntegrationArtifactGetServiceEndpoint": | ||||
| 		return GetIntegrationArtifactGetServiceEndpointCommandMockResponse(testType) | ||||
| 	case "IntegrationArtifactDownload": | ||||
| 		return IntegrationArtifactDownloadCommandMockResponse(testType) | ||||
| 	case "GetIntegrationDesigntimeArtifact": | ||||
| 		return GetIntegrationDesigntimeArtifactMockResponse(testType) | ||||
| 	case "UploadIntegrationDesigntimeArtifact": | ||||
| 		return GetIntegrationDesigntimeArtifactMockResponse(testType) | ||||
| 	case "UploadIntegrationDesigntimeArtifactNegative": | ||||
| 		return GetRespBodyHTTPStatusServiceErrorResponse() | ||||
| 	case "UpdateIntegrationDesigntimeArtifactNegative": | ||||
| 		return GetRespBodyHTTPStatusServiceErrorResponse() | ||||
| 	case "UpdateIntegrationDesigntimeArtifact": | ||||
| 		return UpdateIntegrationDesigntimeArtifactMockResponse(testType) | ||||
| 	case "IntegrationDesigntimeArtifactUpdate": | ||||
| 		return IntegrationDesigntimeArtifactUpdateMockResponse(testType) | ||||
| 	default: | ||||
| 		res := http.Response{ | ||||
| 			StatusCode: 404, | ||||
| @@ -70,6 +72,21 @@ func GetEmptyHTTPResponseBodyAndErrorNil() (*http.Response, error) { | ||||
| 	return &res, nil | ||||
| } | ||||
|  | ||||
| //GetParameterKeyMissingResponseBody -Parameter key missing http respose body | ||||
| func GetParameterKeyMissingResponseBody() (*http.Response, error) { | ||||
| 	res := http.Response{ | ||||
| 		StatusCode: 404, | ||||
| 		Body: ioutil.NopCloser(bytes.NewReader([]byte(`{ | ||||
| 					"code": "Not Found", | ||||
| 					"message": { | ||||
| 					"@lang": "en", | ||||
| 					"#text": "Parameter key 'Parameter1' not found." | ||||
| 					} | ||||
| 				}`))), | ||||
| 	} | ||||
| 	return &res, errors.New("Not found - either wrong version for the given Id or wrong parameter key") | ||||
| } | ||||
|  | ||||
| //GetNegativeCaseHTTPResponseBodyAndErrorNil -Negative case http respose body | ||||
| func GetNegativeCaseHTTPResponseBodyAndErrorNil() (*http.Response, error) { | ||||
| 	res := http.Response{ | ||||
| @@ -189,11 +206,127 @@ func GetIntegrationArtifactGetServiceEndpointPositiveCaseRespBody() (*http.Respo | ||||
| 	return &resp, nil | ||||
| } | ||||
|  | ||||
| //GetRespBodyHTTPStatusOK -Provide http respose body for Http StatusOK | ||||
| func GetRespBodyHTTPStatusOK() (*http.Response, error) { | ||||
|  | ||||
| 	resp := http.Response{ | ||||
| 		StatusCode: 200, | ||||
| 		Body:       ioutil.NopCloser(bytes.NewReader([]byte(``))), | ||||
| 	} | ||||
| 	return &resp, nil | ||||
| } | ||||
|  | ||||
| //GetRespBodyHTTPStatusCreated -Provide http respose body for Http StatusOK | ||||
| func GetRespBodyHTTPStatusCreated() (*http.Response, error) { | ||||
|  | ||||
| 	resp := http.Response{ | ||||
| 		StatusCode: 201, | ||||
| 		Body:       ioutil.NopCloser(bytes.NewReader([]byte(``))), | ||||
| 	} | ||||
| 	return &resp, nil | ||||
| } | ||||
|  | ||||
| //GetRespBodyHTTPStatusServiceNotFound -Provide http respose body for Http URL not Found | ||||
| func GetRespBodyHTTPStatusServiceNotFound() (*http.Response, error) { | ||||
|  | ||||
| 	resp := http.Response{ | ||||
| 		StatusCode: 404, | ||||
| 		Body:       ioutil.NopCloser(bytes.NewReader([]byte(``))), | ||||
| 	} | ||||
| 	return &resp, errors.New("Integration Package not found") | ||||
| } | ||||
|  | ||||
| //GetRespBodyHTTPStatusServiceErrorResponse -Provide http respose body for server error | ||||
| func GetRespBodyHTTPStatusServiceErrorResponse() (*http.Response, error) { | ||||
|  | ||||
| 	resp := http.Response{ | ||||
| 		StatusCode: 500, | ||||
| 		Body:       ioutil.NopCloser(bytes.NewReader([]byte(``))), | ||||
| 	} | ||||
| 	return &resp, errors.New("Internal error") | ||||
| } | ||||
|  | ||||
| //IntegrationArtifactDownloadCommandMockResponse -Provide http respose body | ||||
| func IntegrationArtifactDownloadCommandMockResponse(testType string) (*http.Response, error) { | ||||
|  | ||||
| 	return GetMockResponseByTestTypeAndMockFunctionName("IntegrationArtifactDownloadCommandMockResponse", testType) | ||||
| } | ||||
|  | ||||
| //GetIntegrationDesigntimeArtifactMockResponse -Provide http respose body | ||||
| func GetIntegrationDesigntimeArtifactMockResponse(testType string) (*http.Response, error) { | ||||
|  | ||||
| 	return GetMockResponseByTestTypeAndMockFunctionName("GetIntegrationDesigntimeArtifactMockResponse", testType) | ||||
| } | ||||
|  | ||||
| //IntegrationDesigntimeArtifactUpdateMockResponse -Provide http respose body | ||||
| func IntegrationDesigntimeArtifactUpdateMockResponse(testType string) (*http.Response, error) { | ||||
|  | ||||
| 	return GetMockResponseByTestTypeAndMockFunctionName("IntegrationDesigntimeArtifactUpdateMockResponse", testType) | ||||
| } | ||||
|  | ||||
| //GetMockResponseByTestTypeAndMockFunctionName - Get mock response by testtype and mock function name | ||||
| func GetMockResponseByTestTypeAndMockFunctionName(mockFuntionName, testType string) (*http.Response, error) { | ||||
|  | ||||
| 	response, error := GetPositiveCaseResponseByTestType(testType) | ||||
|  | ||||
| 	switch mockFuntionName { | ||||
|  | ||||
| 	case "IntegrationDesigntimeArtifactUpdateMockResponse": | ||||
| 		if response == nil && error == nil { | ||||
|  | ||||
| 			res := http.Response{ | ||||
| 				StatusCode: 400, | ||||
| 				Body: ioutil.NopCloser(bytes.NewReader([]byte(`{ | ||||
| 							"code": "Bad Request", | ||||
| 							"message": { | ||||
| 							"@lang": "en", | ||||
| 							"#text": "invalid request" | ||||
| 							} | ||||
| 						}`))), | ||||
| 			} | ||||
| 			return &res, errors.New("Unable to get status of integration artifact, Response Status code:400") | ||||
| 		} | ||||
| 	case "GetIntegrationDesigntimeArtifactMockResponse": | ||||
| 		if response == nil && error == nil { | ||||
|  | ||||
| 			res := http.Response{ | ||||
| 				StatusCode: 400, | ||||
| 				Body: ioutil.NopCloser(bytes.NewReader([]byte(`{ | ||||
| 							"code": "Bad Request", | ||||
| 							"message": { | ||||
| 							"@lang": "en", | ||||
| 							"#text": "invalid request" | ||||
| 							} | ||||
| 						}`))), | ||||
| 			} | ||||
| 			return &res, errors.New("Unable to get status of integration artifact, Response Status code:400") | ||||
| 		} | ||||
|  | ||||
| 	case "IntegrationArtifactDownloadCommandMockResponse": | ||||
| 		if response == nil && error == nil { | ||||
|  | ||||
| 			res := http.Response{ | ||||
| 				StatusCode: 400, | ||||
| 				Body: ioutil.NopCloser(bytes.NewReader([]byte(`{ | ||||
| 							"code": "Bad Request", | ||||
| 							"message": { | ||||
| 							"@lang": "en", | ||||
| 							"#text": "invalid request" | ||||
| 							} | ||||
| 						}`))), | ||||
| 			} | ||||
| 			return &res, errors.New("Unable to download integration artifact, Response Status code:400") | ||||
| 		} | ||||
|  | ||||
| 	} | ||||
| 	return response, error | ||||
| } | ||||
|  | ||||
| //UpdateIntegrationDesigntimeArtifactMockResponse -Provide http respose body | ||||
| func UpdateIntegrationDesigntimeArtifactMockResponse(testType string) (*http.Response, error) { | ||||
|  | ||||
| 	response, error := GetRespBodyHTTPStatusCreated() | ||||
|  | ||||
| 	if response == nil && error == nil { | ||||
|  | ||||
| 		res := http.Response{ | ||||
| @@ -206,7 +339,7 @@ func IntegrationArtifactDownloadCommandMockResponse(testType string) (*http.Resp | ||||
| 					} | ||||
| 				}`))), | ||||
| 		} | ||||
| 		return &res, errors.New("Unable to download integration artifact, Response Status code:400") | ||||
| 		return &res, errors.New("Unable to get status of integration artifact, Response Status code:400") | ||||
| 	} | ||||
| 	return response, error | ||||
| } | ||||
| @@ -229,7 +362,80 @@ func GetPositiveCaseResponseByTestType(testType string) (*http.Response, error) | ||||
| 	switch testType { | ||||
| 	case "PositiveAndGetetIntegrationArtifactDownloadResBody": | ||||
| 		return IntegrationArtifactDownloadCommandMockResponsePositiveCaseRespBody() | ||||
| 	case "PositiveAndCreateIntegrationDesigntimeArtifactResBody": | ||||
| 		return GetRespBodyHTTPStatusOK() | ||||
| 	case "NegativeAndCreateIntegrationDesigntimeArtifactResBody": | ||||
| 		return GetRespBodyHTTPStatusOK() | ||||
| 	case "PositiveAndUpdateIntegrationDesigntimeArtifactResBody": | ||||
| 		return GetRespBodyHTTPStatusServiceNotFound() | ||||
| 	case "NegativeAndUpdateIntegrationDesigntimeArtifactResBody": | ||||
| 		return GetRespBodyHTTPStatusServiceNotFound() | ||||
| 	default: | ||||
| 		return nil, nil | ||||
| 	} | ||||
| } | ||||
|  | ||||
| //GetCPIFunctionNameByURLCheck - get postive response by test case type | ||||
| func GetCPIFunctionNameByURLCheck(url, method, testType string) string { | ||||
| 	switch url { | ||||
| 	case "https://demo/api/v1/IntegrationDesigntimeArtifacts(Id='flow4',Version='1.0.4')": | ||||
| 		return GetFunctionNameByTestTypeAndMethod(method, testType) | ||||
|  | ||||
| 	case "https://demo/api/v1/IntegrationDesigntimeArtifactSaveAsVersion?Id='flow4'&SaveAsVersion='1.0.4'": | ||||
| 		return GetFunctionNameByTestTypeAndMethod(method, testType) | ||||
|  | ||||
| 	case "https://demo/api/v1/IntegrationDesigntimeArtifacts": | ||||
| 		return GetFunctionNameByTestTypeAndMethod(method, testType) | ||||
|  | ||||
| 	default: | ||||
| 		return "" | ||||
| 	} | ||||
| } | ||||
|  | ||||
| //GetFunctionNameByTestTypeAndMethod -get function name by test tyep | ||||
| func GetFunctionNameByTestTypeAndMethod(method, testType string) string { | ||||
|  | ||||
| 	switch testType { | ||||
|  | ||||
| 	case "PositiveAndCreateIntegrationDesigntimeArtifactResBody": | ||||
| 		if method == "GET" { | ||||
| 			return "GetIntegrationDesigntimeArtifact" | ||||
| 		} | ||||
| 		if method == "POST" { | ||||
| 			return "UploadIntegrationDesigntimeArtifact" | ||||
| 		} | ||||
|  | ||||
| 	case "PositiveAndUpdateIntegrationDesigntimeArtifactResBody": | ||||
| 		if method == "GET" { | ||||
| 			return "IntegrationDesigntimeArtifactUpdate" | ||||
| 		} | ||||
| 		if method == "POST" { | ||||
| 			return "UpdateIntegrationDesigntimeArtifact" | ||||
| 		} | ||||
|  | ||||
| 	case "NegativeAndGetIntegrationDesigntimeArtifactResBody": | ||||
| 		if method == "GET" { | ||||
| 			return "GetIntegrationDesigntimeArtifact" | ||||
| 		} | ||||
|  | ||||
| 	case "NegativeAndCreateIntegrationDesigntimeArtifactResBody": | ||||
| 		if method == "GET" { | ||||
| 			return "GetIntegrationDesigntimeArtifact" | ||||
| 		} | ||||
| 		if method == "POST" { | ||||
| 			return "UploadIntegrationDesigntimeArtifactNegative" | ||||
| 		} | ||||
|  | ||||
| 	case "NegativeAndUpdateIntegrationDesigntimeArtifactResBody": | ||||
| 		if method == "GET" { | ||||
| 			return "GetIntegrationDesigntimeArtifact" | ||||
| 		} | ||||
| 		if method == "POST" { | ||||
| 			return "UpdateIntegrationDesigntimeArtifactNegative" | ||||
| 		} | ||||
| 	default: | ||||
| 		return "" | ||||
|  | ||||
| 	} | ||||
| 	return "" | ||||
| } | ||||
|   | ||||
							
								
								
									
										95
									
								
								resources/metadata/integrationArtifactUpload.yaml
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										95
									
								
								resources/metadata/integrationArtifactUpload.yaml
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,95 @@ | ||||
| metadata: | ||||
|   name: integrationArtifactUpload | ||||
|   description: Upload or Update an integration flow designtime artefact | ||||
|   longDescription: | | ||||
|     With this step you can either upload or update a integration flow designtime artifact using the OData API. Learn more about the SAP Cloud Integration remote API for updating an integration flow artifact [here](https://help.sap.com/viewer/368c481cd6954bdfa5d0435479fd4eaf/Cloud/en-US/83733a65c0214aa6acba035e8640bb5a.html). | ||||
|  | ||||
| spec: | ||||
|   inputs: | ||||
|     secrets: | ||||
|       - name: cpiCredentialsId | ||||
|         description: Jenkins credentials ID containing username and password for authentication to the SAP Cloud Platform Integration API's | ||||
|         type: jenkins | ||||
|     params: | ||||
|       - name: username | ||||
|         type: string | ||||
|         description: User to authenticate to the SAP Cloud Platform Integration Service | ||||
|         scope: | ||||
|           - PARAMETERS | ||||
|           - STAGES | ||||
|           - STEPS | ||||
|         mandatory: true | ||||
|         secret: true | ||||
|         resourceRef: | ||||
|           - name: cpiCredentialsId | ||||
|             type: secret | ||||
|             param: username | ||||
|       - name: password | ||||
|         type: string | ||||
|         description: Password to authenticate to the SAP Cloud Platform Integration Service | ||||
|         scope: | ||||
|           - PARAMETERS | ||||
|           - STAGES | ||||
|           - STEPS | ||||
|         mandatory: true | ||||
|         secret: true | ||||
|         resourceRef: | ||||
|           - name: cpiCredentialsId | ||||
|             type: secret | ||||
|             param: password | ||||
|       - name: integrationFlowId | ||||
|         type: string | ||||
|         description: Specifies the ID of the Integration Flow artifact | ||||
|         scope: | ||||
|           - PARAMETERS | ||||
|           - STAGES | ||||
|           - STEPS | ||||
|         mandatory: true | ||||
|       - name: integrationFlowVersion | ||||
|         type: string | ||||
|         description: Specifies the version of the Integration Flow artifact | ||||
|         scope: | ||||
|           - PARAMETERS | ||||
|           - STAGES | ||||
|           - STEPS | ||||
|         mandatory: true | ||||
|       - name: integrationFlowName | ||||
|         type: string | ||||
|         description: Specifies the Name of the Integration Flow artifact | ||||
|         scope: | ||||
|           - PARAMETERS | ||||
|           - STAGES | ||||
|           - STEPS | ||||
|         mandatory: true | ||||
|       - name: packageId | ||||
|         type: string | ||||
|         description: Specifies the ID of the Integration Package | ||||
|         scope: | ||||
|           - PARAMETERS | ||||
|           - STAGES | ||||
|           - STEPS | ||||
|         mandatory: true | ||||
|       - name: host | ||||
|         type: string | ||||
|         description: Specifies the protocol and host address, including the port. Please provide in the format `<protocol>://<host>:<port>`. Supported protocols are `http` and `https`. | ||||
|         scope: | ||||
|           - PARAMETERS | ||||
|           - STAGES | ||||
|           - STEPS | ||||
|         mandatory: true | ||||
|       - name: oAuthTokenProviderUrl | ||||
|         type: string | ||||
|         description: Specifies the oAuth Provider protocol and host address, including the port. Please provide in the format `<protocol>://<host>:<port>`. Supported protocols are `http` and `https`. | ||||
|         scope: | ||||
|           - PARAMETERS | ||||
|           - STAGES | ||||
|           - STEPS | ||||
|         mandatory: true | ||||
|       - name: filePath | ||||
|         type: string | ||||
|         description: Specifies integration artifact relative file path. | ||||
|         scope: | ||||
|           - PARAMETERS | ||||
|           - STAGES | ||||
|           - STEPS | ||||
|         mandatory: true | ||||
| @@ -178,6 +178,7 @@ public class CommonStepsTest extends BasePiperTest{ | ||||
|         'integrationArtifactGetMplStatus', //implementing new golang pattern without fields | ||||
|         'integrationArtifactGetServiceEndpoint', //implementing new golang pattern without fields | ||||
|         'integrationArtifactDownload', //implementing new golang pattern without fields | ||||
|         'integrationArtifactUpload', //implementing new golang pattern without fields | ||||
|     ] | ||||
|  | ||||
|     @Test | ||||
|   | ||||
							
								
								
									
										11
									
								
								vars/integrationArtifactUpload.groovy
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										11
									
								
								vars/integrationArtifactUpload.groovy
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,11 @@ | ||||
| import groovy.transform.Field | ||||
|  | ||||
| @Field String STEP_NAME = getClass().getName() | ||||
| @Field String METADATA_FILE = 'metadata/integrationArtifactUpload.yaml' | ||||
|  | ||||
| void call(Map parameters = [:]) { | ||||
|     List credentials = [ | ||||
|         [type: 'usernamePassword', id: 'cpiCredentialsId', env: ['PIPER_username', 'PIPER_password']] | ||||
|     ] | ||||
|     piperExecuteBin(parameters, STEP_NAME, METADATA_FILE, credentials) | ||||
| } | ||||
		Reference in New Issue
	
	Block a user