forked from SAP/jenkins-library
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathintegrationArtifactTriggerIntegrationTest.go
157 lines (136 loc) · 6.27 KB
/
integrationArtifactTriggerIntegrationTest.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
package cmd
import (
"bytes"
"fmt"
"io/ioutil"
"net/http"
"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 integrationArtifactTriggerIntegrationTestUtils interface {
command.ExecRunner
FileExists(filename string) (bool, error)
// Add more methods here, or embed additional interfaces, or remove/replace as required.
// The integrationArtifactTriggerIntegrationTestUtils 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 integrationArtifactTriggerIntegrationTestUtilsBundle struct {
*command.Command
*piperutils.Files
// Embed more structs as necessary to implement methods or interfaces you add to integrationArtifactTriggerIntegrationTestUtils.
// 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
// integrationArtifactTriggerIntegrationTestUtilsBundle and forward to the implementation of the dependency.
}
func newIntegrationArtifactTriggerIntegrationTestUtils() integrationArtifactTriggerIntegrationTestUtils {
utils := integrationArtifactTriggerIntegrationTestUtilsBundle{
Command: &command.Command{},
Files: &piperutils.Files{},
}
// Reroute command output to logging framework
utils.Stdout(log.Writer())
utils.Stderr(log.Writer())
return &utils
}
func integrationArtifactTriggerIntegrationTest(config integrationArtifactTriggerIntegrationTestOptions, telemetryData *telemetry.CustomData) {
// Utils can be used wherever the command.ExecRunner interface is expected.
// It can also be used for example as a mavenExecRunner.
utils := newIntegrationArtifactTriggerIntegrationTestUtils()
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 := runIntegrationArtifactTriggerIntegrationTest(&config, telemetryData, utils, httpClient)
if err != nil {
log.Entry().WithError(err).Fatal("step execution failed")
}
}
func runIntegrationArtifactTriggerIntegrationTest(config *integrationArtifactTriggerIntegrationTestOptions, telemetryData *telemetry.CustomData, utils integrationArtifactTriggerIntegrationTestUtils, httpClient piperhttp.Sender) error {
var commonPipelineEnvironment integrationArtifactGetServiceEndpointCommonPipelineEnvironment
var serviceEndpointUrl string
if len(config.IntegrationFlowServiceEndpointURL) > 0 {
serviceEndpointUrl = config.IntegrationFlowServiceEndpointURL
} else {
serviceEndpointUrl = commonPipelineEnvironment.custom.integrationFlowServiceEndpoint
if len(serviceEndpointUrl) == 0 {
log.SetErrorCategory(log.ErrorConfiguration)
return fmt.Errorf("IFlowServiceEndpointURL not set")
}
}
log.Entry().Info("The Service URL : ", serviceEndpointUrl)
// Here we trigger the iFlow Service Endpoint.
IFlowErr := callIFlowURL(config, telemetryData, utils, httpClient, serviceEndpointUrl)
if IFlowErr != nil {
log.SetErrorCategory(log.ErrorService)
return fmt.Errorf("failed to execute iFlow: %w", IFlowErr)
}
return nil
}
func callIFlowURL(config *integrationArtifactTriggerIntegrationTestOptions, telemetryData *telemetry.CustomData, utils integrationArtifactTriggerIntegrationTestUtils, httpIFlowClient piperhttp.Sender, serviceEndpointUrl string) error {
var fileBody []byte
var httpMethod string
var header http.Header
if len(config.MessageBodyPath) > 0 {
if len(config.ContentType) == 0 {
log.SetErrorCategory(log.ErrorConfiguration)
return fmt.Errorf("message body file %s given, but no ContentType", config.MessageBodyPath)
}
exists, err := utils.FileExists(config.MessageBodyPath)
if err != nil {
log.SetErrorCategory(log.ErrorUndefined)
// Always wrap non-descriptive errors to enrich them with context for when they appear in the log:
return fmt.Errorf("failed to check message body file %s: %w", config.MessageBodyPath, err)
}
if !exists {
log.SetErrorCategory(log.ErrorConfiguration)
return fmt.Errorf("message body file %s configured, but not found", config.MessageBodyPath)
}
var fileErr error
fileBody, fileErr = ioutil.ReadFile(config.MessageBodyPath)
if fileErr != nil {
log.SetErrorCategory(log.ErrorUndefined)
return fmt.Errorf("failed to read file %s: %w", config.MessageBodyPath, fileErr)
}
httpMethod = "POST"
header = make(http.Header)
header.Add("Content-Type", config.ContentType)
} else {
httpMethod = "GET"
}
serviceKey, err := cpi.ReadCpiServiceKey(config.IntegrationFlowServiceKey)
if err != nil {
return err
}
clientOptions := piperhttp.ClientOptions{}
tokenParameters := cpi.TokenParameters{TokenURL: serviceKey.OAuth.OAuthTokenProviderURL, Username: serviceKey.OAuth.ClientID, Password: serviceKey.OAuth.ClientSecret, Client: httpIFlowClient}
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)
clientOptions.MaxRetries = -1
httpIFlowClient.SetOptions(clientOptions)
iFlowResp, httpErr := httpIFlowClient.SendRequest(httpMethod, serviceEndpointUrl, bytes.NewBuffer(fileBody), header, nil)
if httpErr != nil {
return errors.Wrapf(httpErr, "HTTP %q request to %q failed with error", httpMethod, serviceEndpointUrl)
}
if iFlowResp == nil {
return errors.Errorf("did not retrieve any HTTP response")
}
if iFlowResp.StatusCode < 400 {
log.Entry().
WithField(config.IntegrationFlowID, serviceEndpointUrl).
Infof("successfully triggered %s with status code %d", serviceEndpointUrl, iFlowResp.StatusCode)
} else {
return fmt.Errorf("request %s failed with response code %d", serviceEndpointUrl, iFlowResp.StatusCode)
}
return nil
}