1
0
mirror of https://github.com/SAP/jenkins-library.git synced 2025-02-09 13:47:31 +02:00

IntegrationArtifactUnDeploy Command (#3018)

* IntegrationArtifactUnDeploy Command

* formatting fix

* Code Review Fixex

* Code Review Fixes

* remove unused code

* Formating fixes

* formatting fixes

* formatting fix

Co-authored-by: Oliver Feldmann <oliver.feldmann@sap.com>
This commit is contained in:
Mayur Belur Mohan 2021-08-02 19:57:16 +05:30 committed by GitHub
parent 6f32b437be
commit c283b9319d
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
12 changed files with 380 additions and 2 deletions

View File

@ -0,0 +1,74 @@
package cmd
import (
"fmt"
"io/ioutil"
"net/http"
"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/telemetry"
"github.com/pkg/errors"
)
func integrationArtifactUnDeploy(config integrationArtifactUnDeployOptions, 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{}
// 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 := runIntegrationArtifactUnDeploy(&config, telemetryData, httpClient)
if err != nil {
log.Entry().WithError(err).Fatal("step execution failed")
}
}
func runIntegrationArtifactUnDeploy(config *integrationArtifactUnDeployOptions, telemetryData *telemetry.CustomData, httpClient piperhttp.Sender) error {
clientOptions := piperhttp.ClientOptions{}
header := make(http.Header)
header.Add("Accept", "application/json")
serviceKey, err := cpi.ReadCpiServiceKey(config.APIServiceKey)
if err != nil {
return err
}
unDeployURL := fmt.Sprintf("%s/api/v1/IntegrationRuntimeArtifacts('%s')", serviceKey.OAuth.Host, config.IntegrationFlowID)
tokenParameters := cpi.TokenParameters{TokenURL: serviceKey.OAuth.OAuthTokenProviderURL, Username: serviceKey.OAuth.ClientID, Password: serviceKey.OAuth.ClientSecret, 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 := "DELETE"
unDeployResp, httpErr := httpClient.SendRequest(httpMethod, unDeployURL, nil, header, nil)
if httpErr != nil {
return errors.Wrapf(httpErr, "HTTP %v request to %v failed with error", httpMethod, unDeployURL)
}
if unDeployResp != nil && unDeployResp.Body != nil {
defer unDeployResp.Body.Close()
}
if unDeployResp == nil {
return errors.Errorf("did not retrieve a HTTP response")
}
if unDeployResp.StatusCode == http.StatusAccepted {
log.Entry().
WithField("IntegrationFlowID", config.IntegrationFlowID).
Info("successfully undeployed from integration runtime")
return nil
}
responseBody, readErr := ioutil.ReadAll(unDeployResp.Body)
if readErr != nil {
return errors.Wrapf(readErr, "HTTP response body could not be read, response status code: %v", unDeployResp.StatusCode)
}
log.Entry().Errorf("a HTTP error occurred! Response body: %v, Response status code : %v", responseBody, unDeployResp.StatusCode)
return errors.Errorf("integration flow undeployment failed, response Status code: %v", unDeployResp.StatusCode)
}

View File

@ -0,0 +1,148 @@
// 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/spf13/cobra"
)
type integrationArtifactUnDeployOptions struct {
APIServiceKey string `json:"apiServiceKey,omitempty"`
IntegrationFlowID string `json:"integrationFlowId,omitempty"`
}
// IntegrationArtifactUnDeployCommand Undeploy a integration flow
func IntegrationArtifactUnDeployCommand() *cobra.Command {
const STEP_NAME = "integrationArtifactUnDeploy"
metadata := integrationArtifactUnDeployMetadata()
var stepConfig integrationArtifactUnDeployOptions
var startTime time.Time
var logCollector *log.CollectorHook
var createIntegrationArtifactUnDeployCmd = &cobra.Command{
Use: STEP_NAME,
Short: "Undeploy a integration flow",
Long: `With this step you can undeploy a integration flow artifact in SAP Cloud integration runtime using OData API. Learn more about the SAP Cloud Integration remote API for undeploying an integration artifact [here](https://help.sap.com/viewer/368c481cd6954bdfa5d0435479fd4eaf/Cloud/en-US/d1679a80543f46509a7329243b595bdb.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.APIServiceKey)
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 {
logCollector = &log.CollectorHook{CorrelationID: GeneralConfig.CorrelationID}
log.RegisterHook(logCollector)
}
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)
if len(GeneralConfig.HookConfig.SplunkConfig.Dsn) > 0 {
splunk.Send(&telemetryData, logCollector)
}
}
log.DeferExitHandler(handler)
defer handler()
telemetry.Initialize(GeneralConfig.NoTelemetry, STEP_NAME)
if len(GeneralConfig.HookConfig.SplunkConfig.Dsn) > 0 {
splunk.Initialize(GeneralConfig.CorrelationID,
GeneralConfig.HookConfig.SplunkConfig.Dsn,
GeneralConfig.HookConfig.SplunkConfig.Token,
GeneralConfig.HookConfig.SplunkConfig.Index,
GeneralConfig.HookConfig.SplunkConfig.SendLogs)
}
integrationArtifactUnDeploy(stepConfig, &telemetryData)
telemetryData.ErrorCode = "0"
log.Entry().Info("SUCCESS")
},
}
addIntegrationArtifactUnDeployFlags(createIntegrationArtifactUnDeployCmd, &stepConfig)
return createIntegrationArtifactUnDeployCmd
}
func addIntegrationArtifactUnDeployFlags(cmd *cobra.Command, stepConfig *integrationArtifactUnDeployOptions) {
cmd.Flags().StringVar(&stepConfig.APIServiceKey, "apiServiceKey", os.Getenv("PIPER_apiServiceKey"), "Service key JSON string to access the Process Integration Runtime service instance of plan 'api'")
cmd.Flags().StringVar(&stepConfig.IntegrationFlowID, "integrationFlowId", os.Getenv("PIPER_integrationFlowId"), "Specifies the ID of the Integration Flow artifact")
cmd.MarkFlagRequired("apiServiceKey")
cmd.MarkFlagRequired("integrationFlowId")
}
// retrieve step metadata
func integrationArtifactUnDeployMetadata() config.StepData {
var theMetaData = config.StepData{
Metadata: config.StepMetadata{
Name: "integrationArtifactUnDeploy",
Aliases: []config.Alias{},
Description: "Undeploy a integration flow",
},
Spec: config.StepSpec{
Inputs: config.StepInputs{
Secrets: []config.StepSecrets{
{Name: "cpiApiServiceKeyCredentialsId", Description: "Jenkins secret text credential ID containing the service key to the Process Integration Runtime service instance of plan 'api'", Type: "jenkins"},
},
Parameters: []config.StepParameters{
{
Name: "apiServiceKey",
ResourceRef: []config.ResourceReference{
{
Name: "cpiApiServiceKeyCredentialsId",
Param: "apiServiceKey",
Type: "secret",
},
},
Scope: []string{"PARAMETERS"},
Type: "string",
Mandatory: true,
Aliases: []config.Alias{},
Default: os.Getenv("PIPER_apiServiceKey"),
},
{
Name: "integrationFlowId",
ResourceRef: []config.ResourceReference{},
Scope: []string{"PARAMETERS", "GENERAL", "STAGES", "STEPS"},
Type: "string",
Mandatory: true,
Aliases: []config.Alias{},
Default: os.Getenv("PIPER_integrationFlowId"),
},
},
},
},
}
return theMetaData
}

View File

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

View File

@ -0,0 +1,62 @@
package cmd
import (
"github.com/SAP/jenkins-library/pkg/mock"
"github.com/stretchr/testify/assert"
"testing"
)
type integrationArtifactUnDeployMockUtils struct {
*mock.ExecMockRunner
*mock.FilesMock
}
func TestRunIntegrationArtifactUnDeploy(t *testing.T) {
t.Parallel()
t.Run("Successful undeploy of integration flow test", func(t *testing.T) {
apiServiceKey := `{
"oauth": {
"url": "https://demo",
"clientid": "demouser",
"clientsecret": "******",
"tokenurl": "https://demo/oauth/token"
}
}`
config := integrationArtifactUnDeployOptions{
APIServiceKey: apiServiceKey,
IntegrationFlowID: "flow1",
}
httpClient := httpMockCpis{CPIFunction: "PositiveAndUnDeployIntegrationDesigntimeArtifact", ResponseBody: ``, TestType: "Positive"}
// test
err := runIntegrationArtifactUnDeploy(&config, nil, &httpClient)
// assert
assert.NoError(t, err)
})
t.Run("Failed undeploy of integration flow test", func(t *testing.T) {
apiServiceKey := `{
"oauth": {
"url": "https://demo",
"clientid": "demouser",
"clientsecret": "******",
"tokenurl": "https://demo/oauth/token"
}
}`
config := integrationArtifactUnDeployOptions{
APIServiceKey: apiServiceKey,
IntegrationFlowID: "flow1",
}
httpClient := httpMockCpis{CPIFunction: "FailedIntegrationRuntimeArtifactUnDeployment", ResponseBody: ``, TestType: "Negative"}
// test
err := runIntegrationArtifactUnDeploy(&config, nil, &httpClient)
// assert
assert.EqualError(t, err, "integration flow undeployment failed, response Status code: 400")
})
}

View File

@ -53,6 +53,7 @@ func GetAllStepMetadata() map[string]config.StepData {
"integrationArtifactGetMplStatus": integrationArtifactGetMplStatusMetadata(),
"integrationArtifactGetServiceEndpoint": integrationArtifactGetServiceEndpointMetadata(),
"integrationArtifactTriggerIntegrationTest": integrationArtifactTriggerIntegrationTestMetadata(),
"integrationArtifactUnDeploy": integrationArtifactUnDeployMetadata(),
"integrationArtifactUpdateConfiguration": integrationArtifactUpdateConfigurationMetadata(),
"integrationArtifactUpload": integrationArtifactUploadMetadata(),
"jsonApplyPatch": jsonApplyPatchMetadata(),

View File

@ -149,6 +149,7 @@ func Execute() {
rootCmd.AddCommand(AbapEnvironmentAssembleConfirmCommand())
rootCmd.AddCommand(IntegrationArtifactUploadCommand())
rootCmd.AddCommand(IntegrationArtifactTriggerIntegrationTestCommand())
rootCmd.AddCommand(IntegrationArtifactUnDeployCommand())
rootCmd.AddCommand(TerraformExecuteCommand())
rootCmd.AddCommand(ContainerExecuteStructureTestsCommand())
rootCmd.AddCommand(GaugeExecuteTestsCommand())

View File

@ -0,0 +1,29 @@
# ${docGenStepName}
## ${docGenDescription}
## Prerequisites
## ${docGenParameters}
## ${docGenConfiguration}
## ${docJenkinsPluginDependencies}
## Example
Example configuration for the use in a `Jenkinsfile`.
```groovy
integrationArtifactUnDeploy script: this
```
Example of a YAML configuration file (such as `.pipeline/config.yaml`).
```yaml
steps:
<...>
integrationArtifactUnDeploy:
cpiApiServiceKeyCredentialsId: 'MY_API_SERVICE_KEY'
integrationFlowId: 'MY_INTEGRATION_FLOW_ID'
```

View File

@ -107,6 +107,7 @@ nav:
- integrationArtifactDownload: steps/integrationArtifactDownload.md
- integrationArtifactGetMplStatus: steps/integrationArtifactGetMplStatus.md
- integrationArtifactGetServiceEndpoint: steps/integrationArtifactGetServiceEndpoint.md
- integrationArtifactUnDeploy: steps/integrationArtifactUnDeploy.md
- integrationArtifactUpdateConfiguration: steps/integrationArtifactUpdateConfiguration.md
- integrationArtifactUpload: steps/integrationArtifactUpload.md
- jenkinsMaterializeLog: steps/jenkinsMaterializeLog.md

View File

@ -14,9 +14,9 @@ import (
//GetCPIFunctionMockResponse -Generate mock response payload for different CPI functions
func GetCPIFunctionMockResponse(functionName, testType string) (*http.Response, error) {
switch functionName {
case "IntegrationArtifactDeploy":
case "IntegrationArtifactDeploy", "PositiveAndUnDeployIntegrationDesigntimeArtifact":
return GetEmptyHTTPResponseBodyAndErrorNil()
case "FailIntegrationDesigntimeArtifactDeployment":
case "FailIntegrationDesigntimeArtifactDeployment", "FailedIntegrationRuntimeArtifactUnDeployment":
return GetNegativeCaseHTTPResponseBodyAndErrorNil()
case "IntegrationArtifactUpdateConfiguration":
if testType == "Positive" {

View File

@ -0,0 +1,33 @@
metadata:
name: integrationArtifactUnDeploy
description: Undeploy a integration flow
longDescription: |
With this step you can undeploy a integration flow artifact in SAP Cloud integration runtime using OData API. Learn more about the SAP Cloud Integration remote API for undeploying an integration artifact [here](https://help.sap.com/viewer/368c481cd6954bdfa5d0435479fd4eaf/Cloud/en-US/d1679a80543f46509a7329243b595bdb.html)
spec:
inputs:
secrets:
- name: cpiApiServiceKeyCredentialsId
description: Jenkins secret text credential ID containing the service key to the Process Integration Runtime service instance of plan 'api'
type: jenkins
params:
- name: apiServiceKey
type: string
description: Service key JSON string to access the Process Integration Runtime service instance of plan 'api'
scope:
- PARAMETERS
mandatory: true
secret: true
resourceRef:
- name: cpiApiServiceKeyCredentialsId
type: secret
param: apiServiceKey
- name: integrationFlowId
type: string
description: Specifies the ID of the Integration Flow artifact
scope:
- PARAMETERS
- GENERAL
- STAGES
- STEPS
mandatory: true

View File

@ -185,6 +185,7 @@ public class CommonStepsTest extends BasePiperTest{
'integrationArtifactDownload', //implementing new golang pattern without fields
'integrationArtifactUpload', //implementing new golang pattern without fields
'integrationArtifactTriggerIntegrationTest', //implementing new golang pattern without fields
'integrationArtifactUnDeploy', //implementing new golang pattern without fields
'containerExecuteStructureTests', //implementing new golang pattern without fields
'transportRequestUploadSOLMAN', //implementing new golang pattern without fields
'transportRequestReqIDFromGit', //implementing new golang pattern without fields

View File

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