1
0
mirror of https://github.com/SAP/jenkins-library.git synced 2024-12-14 11:03:09 +02:00
sap-jenkins-library/pkg/transportrequest/solman/upload.go

138 lines
3.8 KiB
Go
Raw Normal View History

package solman
import (
"fmt"
"github.com/SAP/jenkins-library/pkg/config/validation"
"github.com/SAP/jenkins-library/pkg/log"
"github.com/pkg/errors"
"strings"
)
// FileSystem interface collecting everything which is file system
// related and needed in the context of a SOLMAN upload.
type FileSystem interface {
FileExists(path string) (bool, error)
}
// UploadAction Collects all the properties we need for the deployment
type UploadAction struct {
Connection Connection
ChangeDocumentID string
TransportRequestID string
ApplicationID string
File string
CMOpts []string
}
// Action collects everything which is needed to perform a SOLMAN upload
type Action interface {
WithConnection(Connection)
WithChangeDocumentID(string)
WithTransportRequestID(string)
WithApplicationID(string)
WithFile(string)
WithCMOpts([]string)
Perform(fs FileSystem, command Exec) error
}
// WithConnection specifies all the connection details which
// are required in order to connect to SOLMAN
func (a *UploadAction) WithConnection(c Connection) {
a.Connection = c
}
// WithChangeDocumentID specifies the change document which
// receives the executable.
func (a *UploadAction) WithChangeDocumentID(id string) {
a.ChangeDocumentID = id
}
// WithTransportRequestID specifies the transport request which
// receives the executable.
func (a *UploadAction) WithTransportRequestID(id string) {
a.TransportRequestID = id
}
// WithApplicationID specifies the application ID.
func (a *UploadAction) WithApplicationID(id string) {
a.ApplicationID = id
}
// WithFile specifies the executable which should be uploaded into
// a transport on SOLMAN
func (a *UploadAction) WithFile(f string) {
a.File = f
}
// WithCMOpts sets additional options for calling the
// cm client tool. E.g. -D options. Useful for troubleshooting
func (a *UploadAction) WithCMOpts(opts []string) {
a.CMOpts = opts
}
// Perform performs the SOLMAN upload
func (a *UploadAction) Perform(fs FileSystem, command Exec) error {
log.Entry().Infof("Deploying artifact '%s' to '%s'.",
a.File, a.Connection.Endpoint)
missingParameters, err := validation.FindEmptyStringsInConfigStruct(*a)
if err == nil {
notInitialized := len(missingParameters) != 0
if notInitialized {
err = fmt.Errorf("the following parameters are not available '%s'", missingParameters)
}
}
if err == nil {
var exists bool
exists, err = fs.FileExists(a.File)
if err == nil && !exists {
err = fmt.Errorf("file '%s' does not exist", a.File)
}
}
if err == nil {
if len(a.CMOpts) > 0 {
command.SetEnv([]string{fmt.Sprintf("CMCLIENT_OPTS=%s", strings.Join(a.CMOpts, " "))})
}
err = command.RunExecutable("cmclient",
"--endpoint", a.Connection.Endpoint,
"--user", a.Connection.User,
"--password", a.Connection.Password,
"--backend-type", "SOLMAN",
"upload-file-to-transport",
"-cID", a.ChangeDocumentID,
"-tID", a.TransportRequestID,
a.ApplicationID, a.File)
exitCode := command.GetExitCode()
if exitCode != 0 {
message := fmt.Sprintf("upload command returned with exit code '%d'", exitCode)
if err != nil {
// Using the wrapping here is to some extend an abuse, since it is not really
// error chaining (the other error is not necessaryly a "predecessor" of this one).
// But it is a pragmatic approach for not loosing information for trouble shooting. There
// is no possibility to have something like suppressed errors.
err = errors.Wrap(err, message)
} else {
err = errors.New(message)
}
}
}
if err == nil {
log.Entry().Infof("Deployment succeeded, artifact: '%s', endpoint: '%s'",
a.File, a.Connection.Endpoint)
} else {
log.Entry().WithError(err).Warnf("Deployment failed, artifact: '%s', endpoint: '%s'",
a.File, a.Connection.Endpoint)
}
return errors.Wrapf(err, "cannot upload artifact '%s'", a.File)
}