1
0
mirror of https://github.com/SAP/jenkins-library.git synced 2025-10-30 23:57:50 +02:00

CTS Upload Go (#2969)

CTS Upload Go
- add cpe
- adjust yaml docker, cpe, text
This commit is contained in:
Roland Stengel
2021-07-08 10:09:18 +02:00
committed by GitHub
parent d38a0f8430
commit 7e55556d7e
4 changed files with 142 additions and 55 deletions

View File

@@ -46,7 +46,9 @@ func newTransportRequestUploadCTSUtils() transportRequestUploadUtils {
return &utils
}
func transportRequestUploadCTS(config transportRequestUploadCTSOptions, telemetryData *telemetry.CustomData) {
func transportRequestUploadCTS(config transportRequestUploadCTSOptions,
telemetryData *telemetry.CustomData,
commonPipelineEnvironment *transportRequestUploadCTSCommonPipelineEnvironment) {
// Utils can be used wherever the command.ExecRunner interface is expected.
// It can also be used for example as a mavenExecRunner.
utils := newTransportRequestUploadCTSUtils()
@@ -57,7 +59,7 @@ func transportRequestUploadCTS(config transportRequestUploadCTSOptions, telemetr
// 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 := runTransportRequestUploadCTS(&config, &cts.UploadAction{}, telemetryData, utils)
err := runTransportRequestUploadCTS(&config, &cts.UploadAction{}, telemetryData, utils, commonPipelineEnvironment)
if err != nil {
log.Entry().WithError(err).Fatal("step execution failed")
}
@@ -67,7 +69,8 @@ func runTransportRequestUploadCTS(
config *transportRequestUploadCTSOptions,
action UploadAction,
telemetryData *telemetry.CustomData,
cmd command.ShellRunner) error {
cmd command.ShellRunner,
commonPipelineEnvironment *transportRequestUploadCTSCommonPipelineEnvironment) error {
log.Entry().Debugf("Entering 'runTransportRequestUpload' with config: %v", config)
@@ -91,5 +94,15 @@ func runTransportRequestUploadCTS(
action.WithConfigFile(config.DeployConfigFile)
action.WithDeployUser(config.OsDeployUser)
return action.Perform(cmd)
commonPipelineEnvironment.custom.transportRequestID = config.TransportRequestID
err := action.Perform(cmd)
if err == nil {
log.Entry().Infof("Upload of application '%s' to CTS succeeded (TransportRequestId: '%s').",
config.ApplicationName,
config.TransportRequestID,
)
}
return err
}

View File

@@ -5,10 +5,12 @@ package cmd
import (
"fmt"
"os"
"path/filepath"
"time"
"github.com/SAP/jenkins-library/pkg/config"
"github.com/SAP/jenkins-library/pkg/log"
"github.com/SAP/jenkins-library/pkg/piperenv"
"github.com/SAP/jenkins-library/pkg/splunk"
"github.com/SAP/jenkins-library/pkg/telemetry"
"github.com/spf13/cobra"
@@ -29,19 +31,48 @@ type transportRequestUploadCTSOptions struct {
NpmInstallOpts []string `json:"npmInstallOpts,omitempty"`
}
// TransportRequestUploadCTSCommand Uploads content to a transport request
type transportRequestUploadCTSCommonPipelineEnvironment struct {
custom struct {
transportRequestID string
}
}
func (p *transportRequestUploadCTSCommonPipelineEnvironment) persist(path, resourceName string) {
content := []struct {
category string
name string
value interface{}
}{
{category: "custom", name: "transportRequestId", value: p.custom.transportRequestID},
}
errCount := 0
for _, param := range content {
err := piperenv.SetResourceParameter(path, resourceName, filepath.Join(param.category, param.name), param.value)
if err != nil {
log.Entry().WithError(err).Error("Error persisting piper environment.")
errCount++
}
}
if errCount > 0 {
log.Entry().Fatal("failed to persist Piper environment")
}
}
// TransportRequestUploadCTSCommand Uploads a UI5 application from your project folder to the ABAP system via CTS connections.
func TransportRequestUploadCTSCommand() *cobra.Command {
const STEP_NAME = "transportRequestUploadCTS"
metadata := transportRequestUploadCTSMetadata()
var stepConfig transportRequestUploadCTSOptions
var startTime time.Time
var commonPipelineEnvironment transportRequestUploadCTSCommonPipelineEnvironment
var logCollector *log.CollectorHook
var createTransportRequestUploadCTSCmd = &cobra.Command{
Use: STEP_NAME,
Short: "Uploads content to a transport request",
Long: `Uploads content to a transport request.`,
Short: "Uploads a UI5 application from your project folder to the ABAP system via CTS connections.",
Long: `This step uploads a UI5 application from your project folder to the ABAP system via CTS connections.`,
PreRunE: func(cmd *cobra.Command, _ []string) error {
startTime = time.Now()
log.SetStepName(STEP_NAME)
@@ -76,6 +107,7 @@ func TransportRequestUploadCTSCommand() *cobra.Command {
telemetryData.ErrorCode = "1"
handler := func() {
config.RemoveVaultSecretFiles()
commonPipelineEnvironment.persist(GeneralConfig.EnvRootPath, "commonPipelineEnvironment")
telemetryData.Duration = fmt.Sprintf("%v", time.Since(startTime).Milliseconds())
telemetryData.ErrorCategory = log.GetErrorCategory().String()
telemetry.Send(&telemetryData)
@@ -93,7 +125,7 @@ func TransportRequestUploadCTSCommand() *cobra.Command {
GeneralConfig.HookConfig.SplunkConfig.Index,
GeneralConfig.HookConfig.SplunkConfig.SendLogs)
}
transportRequestUploadCTS(stepConfig, &telemetryData)
transportRequestUploadCTS(stepConfig, &telemetryData, &commonPipelineEnvironment)
telemetryData.ErrorCode = "0"
log.Entry().Info("SUCCESS")
},
@@ -104,18 +136,18 @@ func TransportRequestUploadCTSCommand() *cobra.Command {
}
func addTransportRequestUploadCTSFlags(cmd *cobra.Command, stepConfig *transportRequestUploadCTSOptions) {
cmd.Flags().StringVar(&stepConfig.Description, "description", `Deployed with Piper based on SAP Fiori tools`, "The description of the application. the desription is only taken into account for a new upload. In case of an update the description will not be updated.")
cmd.Flags().StringVar(&stepConfig.Endpoint, "endpoint", os.Getenv("PIPER_endpoint"), "The service endpoint")
cmd.Flags().StringVar(&stepConfig.Description, "description", `Deployed with Piper based on SAP Fiori tools`, "The description of the application. The desription is only taken into account for a new upload. In case of an update the description will not be updated.")
cmd.Flags().StringVar(&stepConfig.Endpoint, "endpoint", os.Getenv("PIPER_endpoint"), "The ODATA service endpoint")
cmd.Flags().StringVar(&stepConfig.Client, "client", os.Getenv("PIPER_client"), "The ABAP client")
cmd.Flags().StringVar(&stepConfig.Username, "username", os.Getenv("PIPER_username"), "The deploy user")
cmd.Flags().StringVar(&stepConfig.Password, "password", os.Getenv("PIPER_password"), "The password for the deploy user")
cmd.Flags().StringVar(&stepConfig.ApplicationName, "applicationName", os.Getenv("PIPER_applicationName"), "The name of the application.")
cmd.Flags().StringVar(&stepConfig.AbapPackage, "abapPackage", os.Getenv("PIPER_abapPackage"), "The ABAP package name of your application")
cmd.Flags().StringVar(&stepConfig.OsDeployUser, "osDeployUser", `node`, "By default we use a standard node docker image and prepare some fiori related packages before performing the deployment. For that we need to launch the image with root privileges. After that, before actually performing the deployment we swith to a non root user. This user can be specified here.")
cmd.Flags().StringVar(&stepConfig.DeployConfigFile, "deployConfigFile", `ui5-deploy.yaml`, "The ABAP package name of your application")
cmd.Flags().StringVar(&stepConfig.TransportRequestID, "transportRequestId", os.Getenv("PIPER_transportRequestId"), "The id of the transport request to upload the file. This parameter is only taken into account when provided via signature to the step.")
cmd.Flags().StringSliceVar(&stepConfig.DeployToolDependencies, "deployToolDependencies", []string{}, "By default we use a standard node docker iamge and prepare some fiori related packages performing the deployment. The additional dependencies can be provided here. In case you use an already prepared docker image which contains the required dependencies, the empty list can be provide here. Caused hereby installing additional dependencies will be skipped.")
cmd.Flags().StringSliceVar(&stepConfig.NpmInstallOpts, "npmInstallOpts", []string{}, "A list containing additional options for the npm install call. `-g`, `--global` is always assumed. Can be used for e.g. providing custom registries (`--registry https://your.registry.com`) or for providing the verbose flag (`--verbose`) for troubleshooting.")
cmd.Flags().StringVar(&stepConfig.Username, "username", os.Getenv("PIPER_username"), "Service user for uploading to the ABAP system via CTS")
cmd.Flags().StringVar(&stepConfig.Password, "password", os.Getenv("PIPER_password"), "Service user password for uploading to the ABAP system via CTS")
cmd.Flags().StringVar(&stepConfig.ApplicationName, "applicationName", os.Getenv("PIPER_applicationName"), "Name of the UI5 application")
cmd.Flags().StringVar(&stepConfig.AbapPackage, "abapPackage", os.Getenv("PIPER_abapPackage"), "ABAP package name of the UI5 application")
cmd.Flags().StringVar(&stepConfig.OsDeployUser, "osDeployUser", `node`, "Docker image user performing the deployment")
cmd.Flags().StringVar(&stepConfig.DeployConfigFile, "deployConfigFile", `ui5-deploy.yaml`, "Configuration file for the fiori deployment")
cmd.Flags().StringVar(&stepConfig.TransportRequestID, "transportRequestId", os.Getenv("PIPER_transportRequestId"), "ID of the transport request to which the UI5 application is uploaded")
cmd.Flags().StringSliceVar(&stepConfig.DeployToolDependencies, "deployToolDependencies", []string{`@ui5/cli`, `@sap/ux-ui5-tooling`, `@ui5/logger`, `@ui5/fs`}, "List of additional dependencies to fiori related packages. By default a standard node docker image is used on which the dependencies are installed. Provide an empty list, in case your docker image already contains the required dependencies")
cmd.Flags().StringSliceVar(&stepConfig.NpmInstallOpts, "npmInstallOpts", []string{}, "List of additional installation options for the npm install call. `-g`, `--global` is always assumed. Can be used for e.g. providing custom registries (`--registry https://your.registry.com`) or for providing the verbose flag (`--verbose`) for troubleshooting")
cmd.MarkFlagRequired("username")
cmd.MarkFlagRequired("password")
@@ -130,12 +162,12 @@ func transportRequestUploadCTSMetadata() config.StepData {
Metadata: config.StepMetadata{
Name: "transportRequestUploadCTS",
Aliases: []config.Alias{{Name: "transportRequestUploadFile", Deprecated: false}},
Description: "Uploads content to a transport request",
Description: "Uploads a UI5 application from your project folder to the ABAP system via CTS connections.",
},
Spec: config.StepSpec{
Inputs: config.StepInputs{
Secrets: []config.StepSecrets{
{Name: "uploadCredentialsId", Description: "Jenkins 'Username with password' credentials ID containing user and password to authenticate against the ABAP backend.", Type: "jenkins", Aliases: []config.Alias{{Name: "changeManagement/credentialsId", Deprecated: false}}},
{Name: "uploadCredentialsId", Description: "Jenkins 'Username with password' credentials ID containing user and password to authenticate against the ABAP system.", Type: "jenkins", Aliases: []config.Alias{{Name: "changeManagement/credentialsId", Deprecated: false}}},
},
Parameters: []config.StepParameters{
{
@@ -153,7 +185,7 @@ func transportRequestUploadCTSMetadata() config.StepData {
Scope: []string{"PARAMETERS", "STAGES", "STEPS", "GENERAL"},
Type: "string",
Mandatory: false,
Aliases: []config.Alias{{Name: "changeManagement/endpoint"}},
Aliases: []config.Alias{{Name: "changeManagement/endpoint"}, {Name: "changeManagement/cts/endpoint"}},
Default: os.Getenv("PIPER_endpoint"),
},
{
@@ -162,7 +194,7 @@ func transportRequestUploadCTSMetadata() config.StepData {
Scope: []string{"PARAMETERS", "STAGES", "STEPS", "GENERAL"},
Type: "string",
Mandatory: false,
Aliases: []config.Alias{{Name: "changeManagement/client"}},
Aliases: []config.Alias{{Name: "changeManagement/client"}, {Name: "changeManagement/cts/client"}},
Default: os.Getenv("PIPER_client"),
},
{
@@ -207,7 +239,7 @@ func transportRequestUploadCTSMetadata() config.StepData {
Scope: []string{"PARAMETERS", "STAGES", "STEPS", "GENERAL"},
Type: "string",
Mandatory: false,
Aliases: []config.Alias{{Name: "changeManagement/cts/osDeployUser"}},
Aliases: []config.Alias{{Name: "changeManagement/osDeployUser"}, {Name: "changeManagement/cts/osDeployUser"}},
Default: `node`,
},
{
@@ -216,17 +248,22 @@ func transportRequestUploadCTSMetadata() config.StepData {
Scope: []string{"PARAMETERS", "STAGES", "STEPS", "GENERAL"},
Type: "string",
Mandatory: false,
Aliases: []config.Alias{{Name: "changeManagement/cts/deployConfigFile"}, {Name: "cts/deployConfigFile"}},
Aliases: []config.Alias{{Name: "changeManagement/deployConfigFile"}, {Name: "changeManagement/cts/deployConfigFile"}},
Default: `ui5-deploy.yaml`,
},
{
Name: "transportRequestId",
ResourceRef: []config.ResourceReference{},
Scope: []string{"PARAMETERS"},
Type: "string",
Mandatory: true,
Aliases: []config.Alias{},
Default: os.Getenv("PIPER_transportRequestId"),
Name: "transportRequestId",
ResourceRef: []config.ResourceReference{
{
Name: "commonPipelineEnvironment",
Param: "custom/transportRequestId",
},
},
Scope: []string{"PARAMETERS"},
Type: "string",
Mandatory: true,
Aliases: []config.Alias{},
Default: os.Getenv("PIPER_transportRequestId"),
},
{
Name: "deployToolDependencies",
@@ -234,8 +271,8 @@ func transportRequestUploadCTSMetadata() config.StepData {
Scope: []string{"PARAMETERS", "STAGES", "STEPS", "GENERAL"},
Type: "[]string",
Mandatory: false,
Aliases: []config.Alias{{Name: "changeManagement/cts/deployToolDependencies"}},
Default: []string{},
Aliases: []config.Alias{{Name: "changeManagement/deployToolDependencies"}, {Name: "changeManagement/cts/deployToolDependencies"}},
Default: []string{`@ui5/cli`, `@sap/ux-ui5-tooling`, `@ui5/logger`, `@ui5/fs`},
},
{
Name: "npmInstallOpts",
@@ -243,11 +280,25 @@ func transportRequestUploadCTSMetadata() config.StepData {
Scope: []string{"PARAMETERS", "STAGES", "STEPS", "GENERAL"},
Type: "[]string",
Mandatory: false,
Aliases: []config.Alias{{Name: "changeManagement/cts/deployToolDependencies"}},
Aliases: []config.Alias{{Name: "changeManagement/npmInstallOpts"}, {Name: "changeManagement/cts/npmInstallOpts"}},
Default: []string{},
},
},
},
Containers: []config.Container{
{Name: "fiori-client", Image: "node"},
},
Outputs: config.StepOutputs{
Resources: []config.StepResources{
{
Name: "commonPipelineEnvironment",
Type: "piperEnvironment",
Parameters: []map[string]interface{}{
{"Name": "custom/transportRequestId"},
},
},
},
},
},
}
return theMetaData

View File

@@ -85,8 +85,9 @@ func TestRunTransportRequestUploadCTS(t *testing.T) {
}
actionMock := &UploadActionMock{thrown: nil}
cpe := &transportRequestUploadCTSCommonPipelineEnvironment{}
// test
err := runTransportRequestUploadCTS(&config, actionMock, nil, newTransportRequestUploadCTSTestsUtils())
err := runTransportRequestUploadCTS(&config, actionMock, nil, newTransportRequestUploadCTSTestsUtils(), cpe)
// assert
if assert.NoError(t, err) {
@@ -136,12 +137,14 @@ func TestRunTransportRequestUploadCTS(t *testing.T) {
DeployToolDependencies: []string{"@ui5/cli", "@sap/ux-ui5-tooling"},
NpmInstallOpts: []string{"--verbose", "--registry", "https://registry.example.org/"},
}
cpe := &transportRequestUploadCTSCommonPipelineEnvironment{}
err := runTransportRequestUploadCTS(
&config,
&UploadActionMock{thrown: fmt.Errorf("something went wrong")},
nil,
newTransportRequestUploadCTSTestsUtils())
newTransportRequestUploadCTSTestsUtils(),
cpe)
assert.EqualError(t, err, "something went wrong")
})
}

View File

@@ -2,21 +2,21 @@ metadata:
name: transportRequestUploadCTS
aliases:
- name: transportRequestUploadFile
description: "Uploads content to a transport request"
description: Uploads a UI5 application from your project folder to the ABAP system via CTS connections.
longDescription: |
Uploads content to a transport request.
This step uploads a UI5 application from your project folder to the ABAP system via CTS connections.
spec:
inputs:
secrets:
- name: uploadCredentialsId
description: Jenkins 'Username with password' credentials ID containing user and password to authenticate against the ABAP backend.
description: Jenkins 'Username with password' credentials ID containing user and password to authenticate against the ABAP system.
type: jenkins
aliases:
- name: changeManagement/credentialsId
params:
- name: description
type: string
description: "The description of the application. the desription is only taken into account for a new upload. In case of an update the description will not be updated."
description: "The description of the application. The desription is only taken into account for a new upload. In case of an update the description will not be updated."
default: "Deployed with Piper based on SAP Fiori tools"
scope:
- PARAMETERS
@@ -25,9 +25,10 @@ spec:
- GENERAL
- name: endpoint
type: string
description: "The service endpoint"
description: "The ODATA service endpoint"
aliases:
- name: changeManagement/endpoint
- name: changeManagement/cts/endpoint
scope:
- PARAMETERS
- STAGES
@@ -37,6 +38,7 @@ spec:
type: string
aliases:
- name: changeManagement/client
- name: changeManagement/cts/client
description: "The ABAP client"
scope:
- PARAMETERS
@@ -46,7 +48,7 @@ spec:
- name: username
type: string
mandatory: true
description: "The deploy user"
description: "Service user for uploading to the ABAP system via CTS"
secret: true
scope:
- PARAMETERS
@@ -56,14 +58,14 @@ spec:
- name: password
type: string
mandatory: true
description: "The password for the deploy user"
description: "Service user password for uploading to the ABAP system via CTS"
secret: true
scope:
- PARAMETERS
- name: applicationName
type: string
mandatory: true
description: "The name of the application."
description: "Name of the UI5 application"
scope:
- PARAMETERS
- STAGES
@@ -72,7 +74,7 @@ spec:
- name: abapPackage
type: string
mandatory: true
description: "The ABAP package name of your application"
description: "ABAP package name of the UI5 application"
scope:
- PARAMETERS
- STAGES
@@ -80,9 +82,10 @@ spec:
- GENERAL
- name: osDeployUser
type: string
default: node
description: "By default we use a standard node docker image and prepare some fiori related packages before performing the deployment. For that we need to launch the image with root privileges. After that, before actually performing the deployment we swith to a non root user. This user can be specified here."
default: 'node'
description: "Docker image user performing the deployment"
aliases:
- name: changeManagement/osDeployUser
- name: changeManagement/cts/osDeployUser
scope:
- PARAMETERS
@@ -90,27 +93,34 @@ spec:
- STEPS
- GENERAL
- name: deployConfigFile
default: ui5-deploy.yaml
default: 'ui5-deploy.yaml'
type: string
aliases:
- name: changeManagement/deployConfigFile
- name: changeManagement/cts/deployConfigFile
- name: cts/deployConfigFile
description: "The ABAP package name of your application"
description: "Configuration file for the fiori deployment"
scope:
- PARAMETERS
- STAGES
- STEPS
- GENERAL
- name: transportRequestId
resourceRef:
- name: commonPipelineEnvironment
param: custom/transportRequestId
type: string
mandatory: true
description: "The id of the transport request to upload the file. This parameter is only taken into account when provided via signature to the step."
description: "ID of the transport request to which the UI5 application is uploaded"
scope:
- PARAMETERS
- name: deployToolDependencies
type: "[]string"
description: "By default we use a standard node docker iamge and prepare some fiori related packages performing the deployment. The additional dependencies can be provided here. In case you use an already prepared docker image which contains the required dependencies, the empty list can be provide here. Caused hereby installing additional dependencies will be skipped."
default: ['@ui5/cli', '@sap/ux-ui5-tooling', '@ui5/logger', '@ui5/fs']
description: "List of additional dependencies to fiori related packages.
By default a standard node docker image is used on which the dependencies are installed.
Provide an empty list, in case your docker image already contains the required dependencies"
aliases:
- name: changeManagement/deployToolDependencies
- name: changeManagement/cts/deployToolDependencies
scope:
- PARAMETERS
@@ -119,11 +129,21 @@ spec:
- GENERAL
- name: npmInstallOpts
type: "[]string"
description: "A list containing additional options for the npm install call. `-g`, `--global` is always assumed. Can be used for e.g. providing custom registries (`--registry https://your.registry.com`) or for providing the verbose flag (`--verbose`) for troubleshooting."
description: "List of additional installation options for the npm install call. `-g`, `--global` is always assumed. Can be used for e.g. providing custom registries (`--registry https://your.registry.com`) or for providing the verbose flag (`--verbose`) for troubleshooting"
aliases:
- name: changeManagement/cts/deployToolDependencies
- name: changeManagement/npmInstallOpts
- name: changeManagement/cts/npmInstallOpts
scope:
- PARAMETERS
- STAGES
- STEPS
- GENERAL
outputs:
resources:
- name: commonPipelineEnvironment
type: piperEnvironment
params:
- name: custom/transportRequestId
containers:
- name: fiori-client
image: node