github.com/ouraigua/jenkins-library@v0.0.0-20231028010029-fbeaf2f3aa9b/pkg/transportrequest/rfc/upload.go (about)

     1  package rfc
     2  
     3  import (
     4  	"fmt"
     5  	"github.com/SAP/jenkins-library/pkg/command"
     6  	"github.com/SAP/jenkins-library/pkg/config/validation"
     7  	"github.com/SAP/jenkins-library/pkg/log"
     8  	"github.com/pkg/errors"
     9  	"strconv"
    10  )
    11  
    12  const (
    13  	eq = "="
    14  )
    15  
    16  // Exec Everything we need for calling an executable
    17  type Exec interface {
    18  	command.ExecRunner
    19  	GetExitCode() int
    20  }
    21  
    22  // Upload ...
    23  type Upload interface {
    24  	Perform(Exec) error
    25  	WithConnection(Connection)
    26  	WithConfiguration(UploadConfig)
    27  	WithApplication(Application)
    28  	WithTransportRequestID(string)
    29  	WithApplicationURL(string)
    30  }
    31  
    32  // Connection Everything we need for connecting to the ABAP system
    33  type Connection struct {
    34  	// The endpoint in for form <protocol>://<host>:<port>, no path
    35  	Endpoint string
    36  	// The ABAP client, like e.g. "001"
    37  	Client string
    38  	// The ABAP instance, like e.g. "DEV",  "QA"
    39  	Instance string
    40  	User     string
    41  	Password string
    42  }
    43  
    44  // Application Application specific properties
    45  type Application struct {
    46  	Name        string
    47  	Description string
    48  	AbapPackage string
    49  }
    50  
    51  // UploadConfig additional configuration properties
    52  type UploadConfig struct {
    53  	AcceptUnixStyleEndOfLine bool
    54  	CodePage                 string
    55  	FailUploadOnWarning      bool
    56  	Verbose                  bool
    57  }
    58  
    59  // UploadAction Collects all the properties we need for the deployment
    60  type UploadAction struct {
    61  	Connection         Connection
    62  	Application        Application
    63  	Configuration      UploadConfig
    64  	TransportRequestID string
    65  	ApplicationURL     string
    66  }
    67  
    68  // WithApplicationURL The location of the deployable
    69  func (action *UploadAction) WithApplicationURL(z string) {
    70  	action.ApplicationURL = z
    71  }
    72  
    73  // WithTransportRequestID The transport request ID for the upload
    74  func (action *UploadAction) WithTransportRequestID(t string) {
    75  	action.TransportRequestID = t
    76  }
    77  
    78  // WithApplication Everything we need to know about the application
    79  func (action *UploadAction) WithApplication(a Application) {
    80  	action.Application = a
    81  }
    82  
    83  // WithConfiguration Everything we need to know in order to perform the upload
    84  func (action *UploadAction) WithConfiguration(c UploadConfig) {
    85  	action.Configuration = c
    86  }
    87  
    88  // WithConnection Everything we need to know about the connection
    89  func (action *UploadAction) WithConnection(c Connection) {
    90  	action.Connection = c
    91  }
    92  
    93  // Perform Performs the upload
    94  func (action *UploadAction) Perform(command Exec) error {
    95  
    96  	log.Entry().Infof("Deploying artifact '%s' to '%s', client: '%s', instance: '%s'.",
    97  		action.ApplicationURL, action.Connection.Endpoint, action.Connection.Client, action.Connection.Instance,
    98  	)
    99  
   100  	parametersWithMissingValues, err := validation.FindEmptyStringsInConfigStruct(*action)
   101  	if err != nil {
   102  		return fmt.Errorf("invalid configuration parameters detected. SOLMAN upload parameter may be missing : %w", err)
   103  	}
   104  	if len(parametersWithMissingValues) != 0 {
   105  		return fmt.Errorf("cannot perform artifact upload. The following parameters are not available %s", parametersWithMissingValues)
   106  	}
   107  
   108  	command.SetEnv([]string{
   109  		"ABAP_DEVELOPMENT_SERVER" + eq + action.Connection.Endpoint,
   110  		"ABAP_DEVELOPMENT_USER" + eq + action.Connection.User,
   111  		"ABAP_DEVELOPMENT_PASSWORD" + eq + action.Connection.Password,
   112  		"ABAP_DEVELOPMENT_INSTANCE" + eq + action.Connection.Instance,
   113  		"ABAP_DEVELOPMENT_CLIENT" + eq + action.Connection.Client,
   114  		"ABAP_APPLICATION_NAME" + eq + action.Application.Name,
   115  		"ABAP_APPLICATION_DESC" + eq + action.Application.Description,
   116  		"ABAP_PACKAGE" + eq + action.Application.AbapPackage,
   117  		"ZIP_FILE_URL" + eq + action.ApplicationURL,
   118  		"CODE_PAGE" + eq + action.Configuration.CodePage,
   119  		"ABAP_ACCEPT_UNIX_STYLE_EOL" + eq + toAbapBool(action.Configuration.AcceptUnixStyleEndOfLine),
   120  		"FAIL_UPLOAD_ON_WARNING" + eq + strconv.FormatBool(action.Configuration.FailUploadOnWarning),
   121  		"VERBOSE" + eq + strconv.FormatBool(action.Configuration.Verbose),
   122  	})
   123  
   124  	err = command.RunExecutable("cts", fmt.Sprintf("uploadToABAP:%s", action.TransportRequestID))
   125  
   126  	exitCode := command.GetExitCode()
   127  	if exitCode != 0 {
   128  		message := fmt.Sprintf("upload command returned with exit code '%d'", exitCode)
   129  		if err != nil {
   130  			// Using the wrapping here is to some extend an abuse, since it is not really
   131  			// error chaining (the other error is not necessaryly a "predecessor" of this one).
   132  			// But it is a pragmatic approach for not loosing information for trouble shooting. There
   133  			// is no possibility to have something like suppressed errors.
   134  			err = errors.Wrap(err, message)
   135  		} else {
   136  			err = errors.New(message)
   137  		}
   138  	}
   139  
   140  	if err == nil {
   141  		log.Entry().Infof("Deploying artifact '%s' to '%s', client: '%s', instance: '%s' succeeded.",
   142  			action.ApplicationURL, action.Connection.Endpoint, action.Connection.Client, action.Connection.Instance,
   143  		)
   144  	} else {
   145  		log.Entry().Warnf("Deploying artifact '%s' to '%s', client: '%s', instance: '%s' failed.",
   146  			action.ApplicationURL, action.Connection.Endpoint, action.Connection.Client, action.Connection.Instance,
   147  		)
   148  	}
   149  	return errors.Wrap(err, "cannot upload artifact")
   150  }
   151  
   152  func toAbapBool(b bool) string {
   153  	abapBool := "-"
   154  	if b {
   155  		abapBool = "X"
   156  	}
   157  	return abapBool
   158  }