1
0
mirror of https://github.com/SAP/jenkins-library.git synced 2025-01-20 05:19:40 +02:00

integrationArtifactTransport Command (#4131)

* integrationArtifactTransport Command

* CodeReview Fix

* CodeReview Fix

* codereview fix

* Update documentation/docs/steps/integrationArtifactTransport.md

Co-authored-by: Srinikitha Kondreddy <srinikitha.kondreddy@sap.com>

* Update documentation/docs/steps/integrationArtifactTransport.md

Co-authored-by: Srinikitha Kondreddy <srinikitha.kondreddy@sap.com>

* CodeReview Fixes

* CodeReview FIxes

* CodeReview Fix

* Doc Fixes

* Update documentation/docs/steps/integrationArtifactTransport.md

Co-authored-by: Linda Siebert <39100394+LindaSieb@users.noreply.github.com>

* Doc fixes

* Doc Fixes

* CodeReview Fixes

* Doc Fixes

Co-authored-by: Linda Siebert <linda.siebert@sap.com>
Co-authored-by: Srinikitha Kondreddy <srinikitha.kondreddy@sap.com>
Co-authored-by: Linda Siebert <39100394+LindaSieb@users.noreply.github.com>
This commit is contained in:
Mayur Belur Mohan 2022-12-20 16:45:36 +05:30 committed by GitHub
parent 4ae97a8a73
commit a65df9ced6
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
11 changed files with 696 additions and 1 deletions

View File

@ -0,0 +1,227 @@
package cmd
import (
"bytes"
"encoding/json"
"fmt"
"io/ioutil"
"math/rand"
"net/http"
"time"
"github.com/Jeffail/gabs/v2"
"github.com/SAP/jenkins-library/pkg/apim"
piperhttp "github.com/SAP/jenkins-library/pkg/http"
"github.com/SAP/jenkins-library/pkg/log"
"github.com/SAP/jenkins-library/pkg/telemetry"
"github.com/pkg/errors"
)
func integrationArtifactTransport(config integrationArtifactTransportOptions, telemetryData *telemetry.CustomData) {
httpClient := &piperhttp.Client{}
err := runIntegrationArtifactTransport(&config, telemetryData, httpClient)
if err != nil {
log.Entry().WithError(err).Fatal("step execution failed")
}
}
func runIntegrationArtifactTransport(config *integrationArtifactTransportOptions, telemetryData *telemetry.CustomData, httpClient piperhttp.Sender) error {
apimData := apim.Bundle{APIServiceKey: config.CasServiceKey, Client: httpClient}
err := apim.Utils.InitAPIM(&apimData)
if err != nil {
return err
}
return CreateIntegrationArtifactTransportRequest(config, apimData)
}
//CreateIntegrationArtifactTransportRequest - Create a transport request for Integration Package
func CreateIntegrationArtifactTransportRequest(config *integrationArtifactTransportOptions, apistruct apim.Bundle) error {
httpMethod := http.MethodPost
httpClient := apistruct.Client
createTransportRequestURL := fmt.Sprintf("%s/v1/contentResources/export", apistruct.Host)
header := make(http.Header)
header.Add("content-type", "application/json")
payload, jsonError := GetCPITransportReqPayload(config)
if jsonError != nil {
return errors.Wrapf(jsonError, "Failed to get json payload for file %v, failed with error", config.IntegrationPackageID)
}
createTransportRequestResp, httpErr := httpClient.SendRequest(httpMethod, createTransportRequestURL, payload, header, nil)
if httpErr != nil {
return errors.Wrapf(httpErr, "HTTP %v request to %v failed with error", httpMethod, createTransportRequestURL)
}
if createTransportRequestResp != nil && createTransportRequestResp.Body != nil {
defer createTransportRequestResp.Body.Close()
}
if createTransportRequestResp == nil {
return errors.Errorf("did not retrieve a HTTP response")
}
if createTransportRequestResp.StatusCode == http.StatusAccepted {
log.Entry().
WithField("IntegrationPackageID", config.IntegrationPackageID).
Info("successfully created the integration package transport request")
bodyText, readErr := ioutil.ReadAll(createTransportRequestResp.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))
}
processId := jsonResponse.Path("processId").Data().(string)
if processId != "" {
error := pollTransportStatus(processId, retryCount, config, httpClient, apistruct.Host)
return error
}
return errors.New("Invalid process id")
}
responseBody, readErr := ioutil.ReadAll(createTransportRequestResp.Body)
if readErr != nil {
return errors.Wrapf(readErr, "HTTP response body could not be read, response status code: %v", createTransportRequestResp.StatusCode)
}
log.Entry().Errorf("a HTTP error occurred! Response body: %v, Response status code : %v", string(responseBody), createTransportRequestResp.StatusCode)
return errors.Errorf("integration flow deployment failed, response Status code: %v", createTransportRequestResp.StatusCode)
}
//pollTransportStatus - Poll the integration package transport processing, return status or error details
func pollTransportStatus(processId string, remainingRetries int, config *integrationArtifactTransportOptions, httpClient piperhttp.Sender, apiHost string) error {
if remainingRetries <= 0 {
return errors.New("failed to start integration artifact after retrying several times")
}
transportStatus, err := getIntegrationTransportProcessingStatus(config, httpClient, apiHost, processId)
if err != nil {
return err
}
//with specific delay between each retry
if (transportStatus == "RUNNING") || (transportStatus == "INITIAL") {
// Calling Sleep method
sleepTime := int(retryCount * 3)
time.Sleep(time.Duration(sleepTime) * time.Second)
remainingRetries--
return pollTransportStatus(processId, retryCount, config, httpClient, apiHost)
}
//if artifact transport completed, then just return
if transportStatus == "FINISHED" {
return nil
}
//if error return immediately with error details
if transportStatus == "ERROR" || transportStatus == "ABORTED" {
resp, err := getIntegrationTransportError(config, httpClient, apiHost, processId)
if err != nil {
return err
}
return errors.New(resp)
}
return nil
}
//GetJSONPayload -return http payload as byte array
func GetCPITransportReqPayload(config *integrationArtifactTransportOptions) (*bytes.Buffer, error) {
jsonObj := gabs.New()
jsonObj.Set(rand.Intn(5000), "id")
jsonObj.Set("MonitoringTeam", "requestor")
jsonObj.Set("1.0.0", "version")
jsonObj.Set("TransportManagementService", "exportMode")
jsonObj.Set("MTAR", "exportMediaType")
jsonObj.Set("Integration Artifact transport request for TransportManagementService", "description")
jsonResourceObj := gabs.New()
jsonResourceObj.Set(config.IntegrationPackageID, "id")
jsonResourceObj.Set(config.ResourceID, "resourceID")
jsonResourceObj.Set("d9c3fe08ceeb47a2991e53049f2ed766", "contentType")
jsonResourceObj.Set("package", "subType")
jsonResourceObj.Set(config.Name, "name")
jsonResourceObj.Set("CloudIntegration", "type")
jsonResourceObj.Set(config.Version, "version")
jsonObj.ArrayAppend(jsonResourceObj, "contentResources")
jsonBody, jsonErr := json.Marshal(jsonObj)
if jsonErr != nil {
return nil, errors.Wrapf(jsonErr, "Transport request payload is invalid for integration package artifact %q", config.IntegrationPackageID)
}
return bytes.NewBuffer(jsonBody), nil
}
//getIntegrationTransportProcessingStatus - Get integration package transport request processing Status
func getIntegrationTransportProcessingStatus(config *integrationArtifactTransportOptions, httpClient piperhttp.Sender, apiHost string, processId string) (string, error) {
httpMethod := "GET"
header := make(http.Header)
header.Add("content-type", "application/json")
header.Add("Accept", "application/json")
transportProcStatusURL := fmt.Sprintf("%s/v1/operations/%s", apiHost, processId)
transportProcStatusResp, httpErr := httpClient.SendRequest(httpMethod, transportProcStatusURL, nil, header, nil)
if transportProcStatusResp != nil && transportProcStatusResp.Body != nil {
defer transportProcStatusResp.Body.Close()
}
if transportProcStatusResp == nil {
return "", errors.Errorf("did not retrieve a HTTP response: %v", httpErr)
}
if (transportProcStatusResp.StatusCode == http.StatusOK) || (transportProcStatusResp.StatusCode == http.StatusAccepted) {
log.Entry().
WithField("IntegrationPackageID", config.IntegrationPackageID).
Info("successfully processed the integration package transport response status")
bodyText, readErr := ioutil.ReadAll(transportProcStatusResp.Body)
if readErr != nil {
return "", errors.Wrapf(readErr, "HTTP response body could not be read, response status code: %v", transportProcStatusResp.StatusCode)
}
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))
}
contentTransporStatus := jsonResponse.Path("state").Data().(string)
return contentTransporStatus, nil
}
if httpErr != nil {
return getHTTPErrorMessage(httpErr, transportProcStatusResp, httpMethod, transportProcStatusURL)
}
return "", errors.Errorf("failed to get transport request processing status, response Status code: %v", transportProcStatusResp.StatusCode)
}
//getTransportError - Get integration package transport failures error details
func getIntegrationTransportError(config *integrationArtifactTransportOptions, httpClient piperhttp.Sender, apiHost string, processId string) (string, error) {
httpMethod := "GET"
header := make(http.Header)
header.Add("content-type", "application/json")
errorStatusURL := fmt.Sprintf("%s/v1/operations/%s/logs", apiHost, processId)
errorStatusResp, httpErr := httpClient.SendRequest(httpMethod, errorStatusURL, nil, header, nil)
if errorStatusResp != nil && errorStatusResp.Body != nil {
defer errorStatusResp.Body.Close()
}
if errorStatusResp == nil {
return "", errors.Errorf("did not retrieve a HTTP response: %v", httpErr)
}
if errorStatusResp.StatusCode == http.StatusOK {
log.Entry().
WithField("IntegrationPackageId", config.IntegrationPackageID).
Info("Successfully retrieved deployment failures error details")
responseBody, readErr := ioutil.ReadAll(errorStatusResp.Body)
if readErr != nil {
return "", errors.Wrapf(readErr, "HTTP response body could not be read, response status code: %v", errorStatusResp.StatusCode)
}
log.Entry().Errorf("a HTTP error occurred! Response body: %v, Response status code: %v", string(responseBody), errorStatusResp.StatusCode)
errorDetails := string(responseBody)
return errorDetails, nil
}
if httpErr != nil {
return getHTTPErrorMessage(httpErr, errorStatusResp, httpMethod, errorStatusURL)
}
return "", errors.Errorf("failed to get Integration Package transport error details, response Status code: %v", errorStatusResp.StatusCode)
}

View File

@ -0,0 +1,203 @@
// 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/splunk"
"github.com/SAP/jenkins-library/pkg/telemetry"
"github.com/SAP/jenkins-library/pkg/validation"
"github.com/spf13/cobra"
)
type integrationArtifactTransportOptions struct {
CasServiceKey string `json:"casServiceKey,omitempty"`
IntegrationPackageID string `json:"integrationPackageId,omitempty"`
ResourceID string `json:"resourceID,omitempty"`
Name string `json:"name,omitempty"`
Version string `json:"version,omitempty"`
}
// IntegrationArtifactTransportCommand Integration Package transport using the SAP Content Agent Service
func IntegrationArtifactTransportCommand() *cobra.Command {
const STEP_NAME = "integrationArtifactTransport"
metadata := integrationArtifactTransportMetadata()
var stepConfig integrationArtifactTransportOptions
var startTime time.Time
var logCollector *log.CollectorHook
var splunkClient *splunk.Splunk
telemetryClient := &telemetry.Telemetry{}
var createIntegrationArtifactTransportCmd = &cobra.Command{
Use: STEP_NAME,
Short: "Integration Package transport using the SAP Content Agent Service",
Long: `With this step you can trigger an Integration Package transport from SAP Integration Suite using SAP Content Agent Service and SAP Cloud Transport Management Service. For more information about doing an Integration Package transport using SAP Content Agent Service see the documentation [here](https://help.sap.com/docs/CONTENT_AGENT_SERVICE/ae1a4f2d150d468d9ff56e13f9898e07/8e274fdd41da45a69ff919c0af8c6127.html).`,
PreRunE: func(cmd *cobra.Command, _ []string) error {
startTime = time.Now()
log.SetStepName(STEP_NAME)
log.SetVerbose(GeneralConfig.Verbose)
GeneralConfig.GitHubAccessTokens = ResolveAccessTokens(GeneralConfig.GitHubTokens)
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.CasServiceKey)
if len(GeneralConfig.HookConfig.SentryConfig.Dsn) > 0 {
sentryHook := log.NewSentryHook(GeneralConfig.HookConfig.SentryConfig.Dsn, GeneralConfig.CorrelationID)
log.RegisterHook(&sentryHook)
}
if len(GeneralConfig.HookConfig.SplunkConfig.Dsn) > 0 {
splunkClient = &splunk.Splunk{}
logCollector = &log.CollectorHook{CorrelationID: GeneralConfig.CorrelationID}
log.RegisterHook(logCollector)
}
if err = log.RegisterANSHookIfConfigured(GeneralConfig.CorrelationID); err != nil {
log.Entry().WithError(err).Warn("failed to set up SAP Alert Notification Service log hook")
}
validation, err := validation.New(validation.WithJSONNamesForStructFields(), validation.WithPredefinedErrorMessages())
if err != nil {
return err
}
if err = validation.ValidateStruct(stepConfig); err != nil {
log.SetErrorCategory(log.ErrorConfiguration)
return err
}
return nil
},
Run: func(_ *cobra.Command, _ []string) {
stepTelemetryData := telemetry.CustomData{}
stepTelemetryData.ErrorCode = "1"
handler := func() {
config.RemoveVaultSecretFiles()
stepTelemetryData.Duration = fmt.Sprintf("%v", time.Since(startTime).Milliseconds())
stepTelemetryData.ErrorCategory = log.GetErrorCategory().String()
stepTelemetryData.PiperCommitHash = GitCommit
telemetryClient.SetData(&stepTelemetryData)
telemetryClient.Send()
if len(GeneralConfig.HookConfig.SplunkConfig.Dsn) > 0 {
splunkClient.Send(telemetryClient.GetData(), logCollector)
}
}
log.DeferExitHandler(handler)
defer handler()
telemetryClient.Initialize(GeneralConfig.NoTelemetry, STEP_NAME)
if len(GeneralConfig.HookConfig.SplunkConfig.Dsn) > 0 {
splunkClient.Initialize(GeneralConfig.CorrelationID,
GeneralConfig.HookConfig.SplunkConfig.Dsn,
GeneralConfig.HookConfig.SplunkConfig.Token,
GeneralConfig.HookConfig.SplunkConfig.Index,
GeneralConfig.HookConfig.SplunkConfig.SendLogs)
}
integrationArtifactTransport(stepConfig, &stepTelemetryData)
stepTelemetryData.ErrorCode = "0"
log.Entry().Info("SUCCESS")
},
}
addIntegrationArtifactTransportFlags(createIntegrationArtifactTransportCmd, &stepConfig)
return createIntegrationArtifactTransportCmd
}
func addIntegrationArtifactTransportFlags(cmd *cobra.Command, stepConfig *integrationArtifactTransportOptions) {
cmd.Flags().StringVar(&stepConfig.CasServiceKey, "casServiceKey", os.Getenv("PIPER_casServiceKey"), "Service key JSON string to access the CAS service instance")
cmd.Flags().StringVar(&stepConfig.IntegrationPackageID, "integrationPackageId", os.Getenv("PIPER_integrationPackageId"), "Specifies the ID of the integration package artifact.")
cmd.Flags().StringVar(&stepConfig.ResourceID, "resourceID", os.Getenv("PIPER_resourceID"), "Specifies the technical ID of the integration package artifact.")
cmd.Flags().StringVar(&stepConfig.Name, "name", os.Getenv("PIPER_name"), "Specifies the name of the integration package artifact.")
cmd.Flags().StringVar(&stepConfig.Version, "version", os.Getenv("PIPER_version"), "Specifies the version of the Integration Package artifact.")
cmd.MarkFlagRequired("casServiceKey")
cmd.MarkFlagRequired("integrationPackageId")
cmd.MarkFlagRequired("resourceID")
cmd.MarkFlagRequired("name")
cmd.MarkFlagRequired("version")
}
// retrieve step metadata
func integrationArtifactTransportMetadata() config.StepData {
var theMetaData = config.StepData{
Metadata: config.StepMetadata{
Name: "integrationArtifactTransport",
Aliases: []config.Alias{},
Description: "Integration Package transport using the SAP Content Agent Service",
},
Spec: config.StepSpec{
Inputs: config.StepInputs{
Secrets: []config.StepSecrets{
{Name: "casApiServiceKeyCredentialsId", Description: "Jenkins secret text credential ID containing the service key to the CAS service instance", Type: "jenkins"},
},
Parameters: []config.StepParameters{
{
Name: "casServiceKey",
ResourceRef: []config.ResourceReference{
{
Name: "casApiServiceKeyCredentialsId",
Param: "casServiceKey",
Type: "secret",
},
},
Scope: []string{"PARAMETERS"},
Type: "string",
Mandatory: true,
Aliases: []config.Alias{},
Default: os.Getenv("PIPER_casServiceKey"),
},
{
Name: "integrationPackageId",
ResourceRef: []config.ResourceReference{},
Scope: []string{"PARAMETERS", "GENERAL", "STAGES", "STEPS"},
Type: "string",
Mandatory: true,
Aliases: []config.Alias{},
Default: os.Getenv("PIPER_integrationPackageId"),
},
{
Name: "resourceID",
ResourceRef: []config.ResourceReference{},
Scope: []string{"PARAMETERS", "GENERAL", "STAGES", "STEPS"},
Type: "string",
Mandatory: true,
Aliases: []config.Alias{},
Default: os.Getenv("PIPER_resourceID"),
},
{
Name: "name",
ResourceRef: []config.ResourceReference{},
Scope: []string{"PARAMETERS", "GENERAL", "STAGES", "STEPS"},
Type: "string",
Mandatory: true,
Aliases: []config.Alias{},
Default: os.Getenv("PIPER_name"),
},
{
Name: "version",
ResourceRef: []config.ResourceReference{},
Scope: []string{"PARAMETERS", "GENERAL", "STAGES", "STEPS"},
Type: "string",
Mandatory: true,
Aliases: []config.Alias{},
Default: os.Getenv("PIPER_version"),
},
},
},
},
}
return theMetaData
}

View File

@ -0,0 +1,17 @@
package cmd
import (
"testing"
"github.com/stretchr/testify/assert"
)
func TestIntegrationArtifactTransportCommand(t *testing.T) {
t.Parallel()
testCmd := IntegrationArtifactTransportCommand()
// only high level testing performed - details are tested in step generation procedure
assert.Equal(t, "integrationArtifactTransport", testCmd.Use, "command name incorrect")
}

View File

@ -0,0 +1,128 @@
package cmd
import (
"fmt"
"testing"
"github.com/SAP/jenkins-library/pkg/apim"
apimhttp "github.com/SAP/jenkins-library/pkg/apim"
"github.com/SAP/jenkins-library/pkg/mock"
"github.com/stretchr/testify/assert"
)
type integrationArtifactTransportMockUtils struct {
*mock.ExecMockRunner
*mock.FilesMock
}
func newIntegrationArtifactTransportTestsUtils() integrationArtifactTransportMockUtils {
utils := integrationArtifactTransportMockUtils{
ExecMockRunner: &mock.ExecMockRunner{},
FilesMock: &mock.FilesMock{},
}
return utils
}
func TestRunIntegrationArtifactTransport(t *testing.T) {
t.Parallel()
t.Run("Create Transport Request Successful test", func(t *testing.T) {
config := getDefaultOptionsForIntegrationArtifactTransport()
httpClientMock := &apimhttp.HttpMockAPIM{StatusCode: 202, ResponseBody: `{"processId": "100", "state": "FINISHED"}`}
apim := apim.Bundle{APIServiceKey: config.CasServiceKey, Client: httpClientMock}
// test
err := CreateIntegrationArtifactTransportRequest(&config, apim)
// assert
if assert.NoError(t, err) {
t.Run("check url", func(t *testing.T) {
assert.Equal(t, "/v1/operations/100", httpClientMock.URL)
})
t.Run("check method", func(t *testing.T) {
assert.Equal(t, "GET", httpClientMock.Method)
})
}
})
t.Run("getIntegrationTransportProcessingStatus successful test", func(t *testing.T) {
config := getDefaultOptionsForIntegrationArtifactTransport()
httpClientMock := &apimhttp.HttpMockAPIM{StatusCode: 200, ResponseBody: `{"state": "FINISHED"}`}
// test
resp, err := getIntegrationTransportProcessingStatus(&config, httpClientMock, "demo", "100")
// assert
assert.Equal(t, "FINISHED", resp)
assert.NoError(t, err)
})
t.Run("getIntegrationTransportError successful test", func(t *testing.T) {
config := getDefaultOptionsForIntegrationArtifactTransport()
httpClientMock := &apimhttp.HttpMockAPIM{StatusCode: 200, ResponseBody: `{ "logs": [] }`}
// test
resp, err := getIntegrationTransportError(&config, httpClientMock, "demo", "100")
// assert
assert.Equal(t, "{ \"logs\": [] }", resp)
// assert
if assert.NoError(t, err) {
t.Run("check url", func(t *testing.T) {
assert.Equal(t, "demo/v1/operations/100/logs", httpClientMock.URL)
})
t.Run("check method", func(t *testing.T) {
assert.Equal(t, "GET", httpClientMock.Method)
})
}
})
t.Run("GetCPITransportReqPayload successful test", func(t *testing.T) {
config := getDefaultOptionsForIntegrationArtifactTransport()
// test
resp, err := GetCPITransportReqPayload(&config)
fmt.Println(resp.String())
// assert
expJson := `{"contentType":"d9c3fe08ceeb47a2991e53049f2ed766","id":"TestTransport","name":"TestTransport","resourceID":"d9c3fe08ceeb47a2991e53049f2ed766","subType":"package","type":"CloudIntegration","version":"1.0"}`
actJson := resp.String()
assert.Contains(t, actJson, expJson)
assert.NoError(t, err)
})
t.Run("Create Transport Request negative test1", func(t *testing.T) {
config := getDefaultOptionsForIntegrationArtifactTransport()
httpClientMock := &apimhttp.HttpMockAPIM{StatusCode: 202, ResponseBody: `{"processId": ""}`}
apim := apim.Bundle{APIServiceKey: config.CasServiceKey, Client: httpClientMock}
// test
err := CreateIntegrationArtifactTransportRequest(&config, apim)
assert.Equal(t, "/v1/contentResources/export", httpClientMock.URL)
assert.Equal(t, "POST", httpClientMock.Method)
assert.Error(t, err)
})
t.Run("Create Transport Request negative test2", func(t *testing.T) {
config := getDefaultOptionsForIntegrationArtifactTransport()
httpClientMock := &apimhttp.HttpMockAPIM{StatusCode: 400, ResponseBody: ``}
apim := apim.Bundle{APIServiceKey: config.CasServiceKey, Client: httpClientMock}
// test
err := CreateIntegrationArtifactTransportRequest(&config, apim)
assert.EqualError(t, err, "HTTP POST request to /v1/contentResources/export failed with error: Bad Request")
})
}
func getDefaultOptionsForIntegrationArtifactTransport() integrationArtifactTransportOptions {
apiServiceKey := `{
"oauth": {
"url": "https://demo",
"clientid": "sb-2d0622c9",
"clientsecret": "edb5c506=",
"tokenurl": "https://demo/oauth/token"
}
}`
return integrationArtifactTransportOptions{
CasServiceKey: apiServiceKey,
IntegrationPackageID: "TestTransport",
ResourceID: "d9c3fe08ceeb47a2991e53049f2ed766",
Name: "TestTransport",
Version: "1.0",
}
}

View File

@ -75,6 +75,7 @@ func GetAllStepMetadata() map[string]config.StepData {
"integrationArtifactGetMplStatus": integrationArtifactGetMplStatusMetadata(),
"integrationArtifactGetServiceEndpoint": integrationArtifactGetServiceEndpointMetadata(),
"integrationArtifactResource": integrationArtifactResourceMetadata(),
"integrationArtifactTransport": integrationArtifactTransportMetadata(),
"integrationArtifactTriggerIntegrationTest": integrationArtifactTriggerIntegrationTestMetadata(),
"integrationArtifactUnDeploy": integrationArtifactUnDeployMetadata(),
"integrationArtifactUpdateConfiguration": integrationArtifactUpdateConfigurationMetadata(),

View File

@ -192,6 +192,7 @@ func Execute() {
rootCmd.AddCommand(AnsSendEventCommand())
rootCmd.AddCommand(ApiProviderListCommand())
rootCmd.AddCommand(TmsUploadCommand())
rootCmd.AddCommand(IntegrationArtifactTransportCommand())
addRootFlags(rootCmd)

View File

@ -0,0 +1,45 @@
# ${docGenStepName}
## ${docGenDescription}
With this step, you can transport Integration Packages from SAP Integration Suite across various landscapes using SAP Content Agent Service.
SAP Integration Suite provides the ability to transport its content to other services. SAP Content Agent service enables you to assemble the content from various content providers (including SAP Integration Suite) in MTAR format. Later, this content is either available for download or can be exported to a configured transport queue, such as SAP Cloud Transport Management. This step, integrationArtifactTransport, only supports transporting Integration Packages from SAP Integration Suite. For more information on
configurations required for SAP Integration Suite, see [Content Assembly for SAP Integration Suite](https://help.sap.com/docs/CONTENT_AGENT_SERVICE/ae1a4f2d150d468d9ff56e13f9898e07/8e274fdd41da45a69ff919c0af8c6127.html)
To use the integrationArtifactTransport step, proceed as follows:
* [Create SAP Content Agent Service Destination](https://help.sap.com/docs/CONTENT_AGENT_SERVICE/ae1a4f2d150d468d9ff56e13f9898e07/a4da0c26ced74bbfbc60e7f607dc05ab.html).
* [Create Cloud Integration Destination](https://help.sap.com/docs/CONTENT_AGENT_SERVICE/ae1a4f2d150d468d9ff56e13f9898e07/c17c4004049d4d9dba373d72ce5610cd.html).
* [Create SAP Cloud Transport Management Destination](https://help.sap.com/docs/CONTENT_AGENT_SERVICE/ae1a4f2d150d468d9ff56e13f9898e07/b44463a657fa4be48ea2525b7eb6e7de.html).
* Transport Cloud Integration Content with SAP Content Agent Service as explained in the blog [TMS – Transport SAP Cloud Integration (CI/CPI) Content with Transport Management Service (TMS) and Content Agent Service (CAS)](https://blogs.sap.com/2022/03/25/transport-sap-cloud-integration-ci-cpi-content-with-transport-management-service-tms-and-content-agent-service-cas/)
* integrationArtifactTransport step only supports Integration Package transport
## Prerequisites
## ${docGenParameters}
## ${docGenConfiguration}
## ${docJenkinsPluginDependencies}
## Example
Configuration example for a `Jenkinsfile`:
```groovy
integrationArtifactTransport script: this
```
Configuration example for a YAML file (for example `.pipeline/config.yaml`):
```yaml
steps:
<...>
integrationArtifactTransport:
casApiServiceKeyCredentialsId: 'MY_API_SERVICE_KEY'
integrationPackageId: MY_INTEGRATION_PACKAGE_ID
resourceID: MY_INTEGRATION_RESOURCE_ID
name: MY_INTEGRATION_PACKAGE_NAME
version: MY_INTEGRATION_PACKAGE_VERSION
```

View File

@ -126,6 +126,7 @@ nav:
- integrationArtifactGetMplStatus: steps/integrationArtifactGetMplStatus.md
- integrationArtifactGetServiceEndpoint: steps/integrationArtifactGetServiceEndpoint.md
- integrationArtifactResource: steps/integrationArtifactResource.md
- integrationArtifactTransport: steps/integrationArtifactTransport.md
- integrationArtifactUnDeploy: steps/integrationArtifactUnDeploy.md
- integrationArtifactUpdateConfiguration: steps/integrationArtifactUpdateConfiguration.md
- integrationArtifactUpload: steps/integrationArtifactUpload.md

View File

@ -0,0 +1,60 @@
metadata:
name: integrationArtifactTransport
description: Integration Package transport using the SAP Content Agent Service
longDescription: |
With this step you can trigger an Integration Package transport from SAP Integration Suite using SAP Content Agent Service and SAP Cloud Transport Management Service. For more information about doing an Integration Package transport using SAP Content Agent Service see the documentation [here](https://help.sap.com/docs/CONTENT_AGENT_SERVICE/ae1a4f2d150d468d9ff56e13f9898e07/8e274fdd41da45a69ff919c0af8c6127.html).
spec:
inputs:
secrets:
- name: casApiServiceKeyCredentialsId
description: Jenkins secret text credential ID containing the service key to the CAS service instance
type: jenkins
params:
- name: casServiceKey
type: string
description: Service key JSON string to access the CAS service instance
scope:
- PARAMETERS
mandatory: true
secret: true
resourceRef:
- name: casApiServiceKeyCredentialsId
type: secret
param: casServiceKey
- name: integrationPackageId
type: string
description: Specifies the ID of the integration package artifact.
scope:
- PARAMETERS
- GENERAL
- STAGES
- STEPS
mandatory: true
- name: resourceID
type: string
description: Specifies the technical ID of the integration package artifact.
scope:
- PARAMETERS
- GENERAL
- STAGES
- STEPS
mandatory: true
- name: name
type: string
description: Specifies the name of the integration package artifact.
scope:
- PARAMETERS
- GENERAL
- STAGES
- STEPS
mandatory: true
- name: version
type: string
description: Specifies the version of the Integration Package artifact.
scope:
- PARAMETERS
- GENERAL
- STAGES
- STEPS
mandatory: true

View File

@ -193,6 +193,7 @@ public class CommonStepsTest extends BasePiperTest{
'integrationArtifactGetServiceEndpoint', //implementing new golang pattern without fields
'integrationArtifactDownload', //implementing new golang pattern without fields
'integrationArtifactUpload', //implementing new golang pattern without fields
'integrationArtifactTransport', //implementing new golang pattern without fields
'integrationArtifactTriggerIntegrationTest', //implementing new golang pattern without fields
'integrationArtifactUnDeploy', //implementing new golang pattern without fields
'integrationArtifactResource', //implementing new golang pattern without fields
@ -223,7 +224,7 @@ public class CommonStepsTest extends BasePiperTest{
'azureBlobUpload',
'awsS3Upload',
'ansSendEvent',
'apiProviderList', //implementing new golang pattern without fields
'apiProviderList', //implementing new golang pattern without fields
]
@Test

View File

@ -0,0 +1,11 @@
import groovy.transform.Field
@Field String STEP_NAME = getClass().getName()
@Field String METADATA_FILE = 'metadata/integrationArtifactTransport.yaml'
void call(Map parameters = [:]) {
List credentials = [
[type: 'token', id: 'casApiServiceKeyCredentialsId', env: ['PIPER_casServiceKey']]
]
piperExecuteBin(parameters, STEP_NAME, METADATA_FILE, credentials)
}