diff --git a/cmd/abapAddonAssemblyKitCheckCVs.go b/cmd/abapAddonAssemblyKitCheckCVs.go new file mode 100644 index 0000000000..23cfc110cc --- /dev/null +++ b/cmd/abapAddonAssemblyKitCheckCVs.go @@ -0,0 +1,103 @@ +package cmd + +import ( + "encoding/json" + + abapbuild "github.com/SAP/jenkins-library/pkg/abap/build" + "github.com/SAP/jenkins-library/pkg/abaputils" + "github.com/SAP/jenkins-library/pkg/command" + piperhttp "github.com/SAP/jenkins-library/pkg/http" + "github.com/SAP/jenkins-library/pkg/log" + "github.com/SAP/jenkins-library/pkg/telemetry" +) + +func abapAddonAssemblyKitCheckCVs(config abapAddonAssemblyKitCheckCVsOptions, telemetryData *telemetry.CustomData, cpe *abapAddonAssemblyKitCheckCVsCommonPipelineEnvironment) { + // for command execution use Command + c := command.Command{} + // reroute command output to logging framework + c.Stdout(log.Writer()) + c.Stderr(log.Writer()) + + client := piperhttp.Client{} + + // error situations should stop execution through log.Entry().Fatal() call which leads to an os.Exit(1) in the end + err := runAbapAddonAssemblyKitCheckCVs(&config, telemetryData, &client, cpe, abaputils.ReadAddonDescriptor) + if err != nil { + log.Entry().WithError(err).Fatal("step execution failed") + } +} + +func runAbapAddonAssemblyKitCheckCVs(config *abapAddonAssemblyKitCheckCVsOptions, telemetryData *telemetry.CustomData, client piperhttp.Sender, + cpe *abapAddonAssemblyKitCheckCVsCommonPipelineEnvironment, readAdoDescriptor abaputils.ReadAddonDescriptorType) error { + var addonDescriptorFromCPE abaputils.AddonDescriptor + json.Unmarshal([]byte(config.AddonDescriptor), &addonDescriptorFromCPE) + addonDescriptor, err := readAdoDescriptor(config.AddonDescriptorFileName) + if err != nil { + return err + } + addonDescriptor = combineYAMLRepositoriesWithCPEProduct(addonDescriptor, addonDescriptorFromCPE) + conn := new(abapbuild.Connector) + conn.InitAAKaaS(config.AbapAddonAssemblyKitEndpoint, config.Username, config.Password, client) + + for i := range addonDescriptor.Repositories { + var c cv + c.initCV(addonDescriptor.Repositories[i], *conn) + err := c.validate() + if err != nil { + return err + } + c.copyFieldsToRepo(&addonDescriptor.Repositories[i]) + } + log.Entry().Info("Write the resolved versions to the CommonPipelineEnvironment") + toCPE, _ := json.Marshal(addonDescriptor) + cpe.abap.addonDescriptor = string(toCPE) + return nil +} + +//take the product part from CPE and the repositories part from the YAML file +func combineYAMLRepositoriesWithCPEProduct(addonDescriptor abaputils.AddonDescriptor, addonDescriptorFromCPE abaputils.AddonDescriptor) abaputils.AddonDescriptor { + addonDescriptorFromCPE.Repositories = addonDescriptor.Repositories + return addonDescriptorFromCPE +} + +func (c *cv) initCV(repo abaputils.Repository, conn abapbuild.Connector) { + c.Connector = conn + c.Name = repo.Name + c.VersionYAML = repo.VersionYAML +} + +func (c *cv) copyFieldsToRepo(initialRepo *abaputils.Repository) { + initialRepo.Version = c.Version + initialRepo.SpLevel = c.SpLevel + initialRepo.PatchLevel = c.PatchLevel +} + +func (c *cv) validate() error { + log.Entry().Infof("Validate component %s version %s and resolve version", c.Name, c.VersionYAML) + appendum := "/odata/aas_ocs_package/ValidateComponentVersion?Name='" + c.Name + "'&Version='" + c.VersionYAML + "'" + body, err := c.Connector.Get(appendum) + if err != nil { + return err + } + var jCV jsonCV + json.Unmarshal(body, &jCV) + c.Name = jCV.CV.Name + c.Version = jCV.CV.Version + c.SpLevel = jCV.CV.SpLevel + c.PatchLevel = jCV.CV.PatchLevel + log.Entry().Infof("Resolved version %s, splevel %s, patchlevel %s", c.Version, c.SpLevel, c.PatchLevel) + return nil +} + +type jsonCV struct { + CV *cv `json:"d"` +} + +type cv struct { + abapbuild.Connector + Name string `json:"Name"` + VersionYAML string + Version string `json:"Version"` + SpLevel string `json:"SpLevel"` + PatchLevel string `json:"PatchLevel"` +} diff --git a/cmd/abapAddonAssemblyKitCheckCVs_generated.go b/cmd/abapAddonAssemblyKitCheckCVs_generated.go new file mode 100644 index 0000000000..0f5038dbd8 --- /dev/null +++ b/cmd/abapAddonAssemblyKitCheckCVs_generated.go @@ -0,0 +1,186 @@ +// Code generated by piper's step-generator. DO NOT EDIT. + +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/telemetry" + "github.com/spf13/cobra" +) + +type abapAddonAssemblyKitCheckCVsOptions struct { + AbapAddonAssemblyKitEndpoint string `json:"abapAddonAssemblyKitEndpoint,omitempty"` + Username string `json:"username,omitempty"` + Password string `json:"password,omitempty"` + AddonDescriptorFileName string `json:"addonDescriptorFileName,omitempty"` + AddonDescriptor string `json:"addonDescriptor,omitempty"` +} + +type abapAddonAssemblyKitCheckCVsCommonPipelineEnvironment struct { + abap struct { + addonDescriptor string + } +} + +func (p *abapAddonAssemblyKitCheckCVsCommonPipelineEnvironment) persist(path, resourceName string) { + content := []struct { + category string + name string + value string + }{ + {category: "abap", name: "addonDescriptor", value: p.abap.addonDescriptor}, + } + + 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") + } +} + +// AbapAddonAssemblyKitCheckCVsCommand This step checks the validity of Software Component Versions. +func AbapAddonAssemblyKitCheckCVsCommand() *cobra.Command { + const STEP_NAME = "abapAddonAssemblyKitCheckCVs" + + metadata := abapAddonAssemblyKitCheckCVsMetadata() + var stepConfig abapAddonAssemblyKitCheckCVsOptions + var startTime time.Time + var commonPipelineEnvironment abapAddonAssemblyKitCheckCVsCommonPipelineEnvironment + + var createAbapAddonAssemblyKitCheckCVsCmd = &cobra.Command{ + Use: STEP_NAME, + Short: "This step checks the validity of Software Component Versions.", + Long: `This steps takes a list of Software Component Versions from the addonDescriptorFileName and checks whether they exist or are a valid successor of an existing Software Component Version. +It resolves the dotted version string into version, support package level and patch level and writes it to the commonPipelineEnvironment.`, + PreRunE: func(cmd *cobra.Command, _ []string) error { + startTime = time.Now() + log.SetStepName(STEP_NAME) + log.SetVerbose(GeneralConfig.Verbose) + + 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.Username) + log.RegisterSecret(stepConfig.Password) + + if len(GeneralConfig.HookConfig.SentryConfig.Dsn) > 0 { + sentryHook := log.NewSentryHook(GeneralConfig.HookConfig.SentryConfig.Dsn, GeneralConfig.CorrelationID) + log.RegisterHook(&sentryHook) + } + + return nil + }, + Run: func(_ *cobra.Command, _ []string) { + telemetryData := telemetry.CustomData{} + telemetryData.ErrorCode = "1" + handler := func() { + commonPipelineEnvironment.persist(GeneralConfig.EnvRootPath, "commonPipelineEnvironment") + telemetryData.Duration = fmt.Sprintf("%v", time.Since(startTime).Milliseconds()) + telemetry.Send(&telemetryData) + } + log.DeferExitHandler(handler) + defer handler() + telemetry.Initialize(GeneralConfig.NoTelemetry, STEP_NAME) + abapAddonAssemblyKitCheckCVs(stepConfig, &telemetryData, &commonPipelineEnvironment) + telemetryData.ErrorCode = "0" + log.Entry().Info("SUCCESS") + }, + } + + addAbapAddonAssemblyKitCheckCVsFlags(createAbapAddonAssemblyKitCheckCVsCmd, &stepConfig) + return createAbapAddonAssemblyKitCheckCVsCmd +} + +func addAbapAddonAssemblyKitCheckCVsFlags(cmd *cobra.Command, stepConfig *abapAddonAssemblyKitCheckCVsOptions) { + cmd.Flags().StringVar(&stepConfig.AbapAddonAssemblyKitEndpoint, "abapAddonAssemblyKitEndpoint", os.Getenv("PIPER_abapAddonAssemblyKitEndpoint"), "Base URL to the Addon Assembly Kit as a Service (AAKaaS) system") + cmd.Flags().StringVar(&stepConfig.Username, "username", os.Getenv("PIPER_username"), "User for the Addon Assembly Kit as a Service System (AAKaaS)") + cmd.Flags().StringVar(&stepConfig.Password, "password", os.Getenv("PIPER_password"), "Password the Addon Assembly Kit as a Service System (AAKaaS)") + cmd.Flags().StringVar(&stepConfig.AddonDescriptorFileName, "addonDescriptorFileName", `addon.yml`, "File name of the YAML file which describes the Product Version and corresponding Software Component Versions") + cmd.Flags().StringVar(&stepConfig.AddonDescriptor, "addonDescriptor", os.Getenv("PIPER_addonDescriptor"), "Structure in the commonPipelineEnvironment containing information about the Product Version and corresponding Software Component Versions") + + cmd.MarkFlagRequired("abapAddonAssemblyKitEndpoint") + cmd.MarkFlagRequired("username") + cmd.MarkFlagRequired("password") + cmd.MarkFlagRequired("addonDescriptorFileName") +} + +// retrieve step metadata +func abapAddonAssemblyKitCheckCVsMetadata() config.StepData { + var theMetaData = config.StepData{ + Metadata: config.StepMetadata{ + Name: "abapAddonAssemblyKitCheckCVs", + Aliases: []config.Alias{}, + }, + Spec: config.StepSpec{ + Inputs: config.StepInputs{ + Parameters: []config.StepParameters{ + { + Name: "abapAddonAssemblyKitEndpoint", + ResourceRef: []config.ResourceReference{}, + Scope: []string{"PARAMETERS", "STAGES", "STEPS", "GENERAL"}, + Type: "string", + Mandatory: true, + Aliases: []config.Alias{}, + }, + { + Name: "username", + ResourceRef: []config.ResourceReference{}, + Scope: []string{"PARAMETERS", "STAGES", "STEPS"}, + Type: "string", + Mandatory: true, + Aliases: []config.Alias{}, + }, + { + Name: "password", + ResourceRef: []config.ResourceReference{}, + Scope: []string{"PARAMETERS"}, + Type: "string", + Mandatory: true, + Aliases: []config.Alias{}, + }, + { + Name: "addonDescriptorFileName", + ResourceRef: []config.ResourceReference{}, + Scope: []string{"PARAMETERS", "STAGES", "STEPS", "GENERAL"}, + Type: "string", + Mandatory: true, + Aliases: []config.Alias{}, + }, + { + Name: "addonDescriptor", + ResourceRef: []config.ResourceReference{ + { + Name: "commonPipelineEnvironment", + Param: "abap/addonDescriptor", + }, + }, + Scope: []string{"PARAMETERS", "STAGES", "STEPS"}, + Type: "string", + Mandatory: false, + Aliases: []config.Alias{}, + }, + }, + }, + }, + } + return theMetaData +} diff --git a/cmd/abapAddonAssemblyKitCheckCVs_generated_test.go b/cmd/abapAddonAssemblyKitCheckCVs_generated_test.go new file mode 100644 index 0000000000..83d9798243 --- /dev/null +++ b/cmd/abapAddonAssemblyKitCheckCVs_generated_test.go @@ -0,0 +1,16 @@ +package cmd + +import ( + "testing" + + "github.com/stretchr/testify/assert" +) + +func TestAbapAddonAssemblyKitCheckCVsCommand(t *testing.T) { + + testCmd := AbapAddonAssemblyKitCheckCVsCommand() + + // only high level testing performed - details are tested in step generation procedure + assert.Equal(t, "abapAddonAssemblyKitCheckCVs", testCmd.Use, "command name incorrect") + +} diff --git a/cmd/abapAddonAssemblyKitCheckCVs_test.go b/cmd/abapAddonAssemblyKitCheckCVs_test.go new file mode 100644 index 0000000000..bdc8304d0f --- /dev/null +++ b/cmd/abapAddonAssemblyKitCheckCVs_test.go @@ -0,0 +1,183 @@ +package cmd + +import ( + "encoding/json" + "testing" + + abapbuild "github.com/SAP/jenkins-library/pkg/abap/build" + "github.com/SAP/jenkins-library/pkg/abaputils" + "github.com/pkg/errors" + "github.com/stretchr/testify/assert" +) + +func mockReadAddonDescriptor(FileName string) (abaputils.AddonDescriptor, error) { + var addonDescriptor abaputils.AddonDescriptor + var err error + switch FileName { + case "success": + { + addonDescriptor = abaputils.AddonDescriptor{ + AddonProduct: "/DRNMSPC/PRD01", + AddonVersionYAML: "3.2.1", + Repositories: []abaputils.Repository{ + { + Name: "/DRNMSPC/COMP01", + VersionYAML: "1.2.3", + }, + }, + } + } + case "failing": + { + err = errors.New("error in ReadAddonDescriptor") + } + } + return addonDescriptor, err +} + +func TestCheckCVsStep(t *testing.T) { + var config abapAddonAssemblyKitCheckCVsOptions + var cpe abapAddonAssemblyKitCheckCVsCommonPipelineEnvironment + client := &abaputils.ClientMock{ + Body: responseCheckCVs, + } + t.Run("step success", func(t *testing.T) { + config.AddonDescriptorFileName = "success" + err := runAbapAddonAssemblyKitCheckCVs(&config, nil, client, &cpe, mockReadAddonDescriptor) + assert.NoError(t, err, "Did not expect error") + var addonDescriptorFinal abaputils.AddonDescriptor + json.Unmarshal([]byte(cpe.abap.addonDescriptor), &addonDescriptorFinal) + assert.Equal(t, "0001", addonDescriptorFinal.Repositories[0].Version) + assert.Equal(t, "0002", addonDescriptorFinal.Repositories[0].SpLevel) + assert.Equal(t, "0003", addonDescriptorFinal.Repositories[0].PatchLevel) + }) + t.Run("step error - in ReadAddonDescriptor", func(t *testing.T) { + config.AddonDescriptorFileName = "failing" + err := runAbapAddonAssemblyKitCheckCVs(&config, nil, client, &cpe, mockReadAddonDescriptor) + assert.Error(t, err, "Must end with error") + assert.Equal(t, "error in ReadAddonDescriptor", err.Error()) + }) + t.Run("step error - in validate", func(t *testing.T) { + config.AddonDescriptorFileName = "success" + client := &abaputils.ClientMock{ + Body: "ErrorBody", + Error: errors.New("error during validation"), + } + err := runAbapAddonAssemblyKitCheckCVs(&config, nil, client, &cpe, mockReadAddonDescriptor) + assert.Error(t, err, "Must end with error") + }) +} + +func TestInitCV(t *testing.T) { + t.Run("test init", func(t *testing.T) { + conn := new(abapbuild.Connector) + conn.Client = &abaputils.ClientMock{} + repo := abaputils.Repository{ + Name: "/DRNMSPC/COMP01", + VersionYAML: "1.2.3", + } + var c cv + c.initCV(repo, *conn) + assert.Equal(t, "/DRNMSPC/COMP01", c.Name) + assert.Equal(t, "1.2.3", c.VersionYAML) + }) +} + +func TestValidateCV(t *testing.T) { + conn := new(abapbuild.Connector) + t.Run("test validate - success", func(t *testing.T) { + conn.Client = &abaputils.ClientMock{ + Body: responseCheckCVs, + } + c := cv{ + Connector: *conn, + Name: "/DRNMSPC/COMP01", + VersionYAML: "1.2.3", + } + conn.Client = &abaputils.ClientMock{ + Body: responseCheckCVs, + } + err := c.validate() + assert.NoError(t, err) + assert.Equal(t, "0001", c.Version) + assert.Equal(t, "0002", c.SpLevel) + assert.Equal(t, "0003", c.PatchLevel) + }) + t.Run("test validate - with error", func(t *testing.T) { + conn.Client = &abaputils.ClientMock{ + Body: "ErrorBody", + Error: errors.New("Validation failed"), + } + c := cv{ + Connector: *conn, + Name: "/DRNMSPC/COMP01", + VersionYAML: "1.2.3", + } + err := c.validate() + assert.Error(t, err) + assert.Equal(t, "", c.Version) + assert.Equal(t, "", c.SpLevel) + assert.Equal(t, "", c.PatchLevel) + }) +} + +func TestCopyFieldsCV(t *testing.T) { + t.Run("test copyFieldsToRepo", func(t *testing.T) { + repo := abaputils.Repository{ + Name: "/DRNMSPC/COMP01", + VersionYAML: "1.2.3", + } + var c cv + c.Version = "0001" + c.SpLevel = "0002" + c.PatchLevel = "0003" + c.copyFieldsToRepo(&repo) + assert.Equal(t, "0001", repo.Version) + assert.Equal(t, "0002", repo.SpLevel) + assert.Equal(t, "0003", repo.PatchLevel) + }) +} + +func TestCombineYAMLRepositoriesWithCPEProduct(t *testing.T) { + t.Run("test combineYAMLRepositoriesWithCPEProduct", func(t *testing.T) { + addonDescriptor := abaputils.AddonDescriptor{ + Repositories: []abaputils.Repository{ + { + Name: "/DRNMSPC/COMP01", + VersionYAML: "1.2.3", + }, + { + Name: "/DRNMSPC/COMP02", + VersionYAML: "3.2.1", + }, + }, + } + addonDescriptorFromCPE := abaputils.AddonDescriptor{ + AddonProduct: "/DRNMSP/PROD", + AddonVersionYAML: "1.2.3", + } + finalAddonDescriptor := combineYAMLRepositoriesWithCPEProduct(addonDescriptor, addonDescriptorFromCPE) + assert.Equal(t, "/DRNMSP/PROD", finalAddonDescriptor.AddonProduct) + assert.Equal(t, "1.2.3", finalAddonDescriptor.AddonVersionYAML) + assert.Equal(t, "/DRNMSPC/COMP01", finalAddonDescriptor.Repositories[0].Name) + assert.Equal(t, "/DRNMSPC/COMP02", finalAddonDescriptor.Repositories[1].Name) + assert.Equal(t, "1.2.3", finalAddonDescriptor.Repositories[0].VersionYAML) + assert.Equal(t, "3.2.1", finalAddonDescriptor.Repositories[1].VersionYAML) + }) +} + +var responseCheckCVs = `{ + "d": { + "__metadata": { + "id": "https://W7Q.DMZWDF.SAP.CORP:443/odata/aas_ocs_package/SoftwareComponentVersionSet(Name='%2FDRNMSPC%2FCOMP01',Version='0001')", + "uri": "https://W7Q.DMZWDF.SAP.CORP:443/odata/aas_ocs_package/SoftwareComponentVersionSet(Name='%2FDRNMSPC%2FCOMP01',Version='0001')", + "type": "SSDA.AAS_ODATA_PACKAGE_SRV.SoftwareComponentVersion" + }, + "Name": "/DRNMSPC/COMP01", + "Version": "0001", + "SpLevel": "0002", + "PatchLevel": "0003", + "Vendor": "", + "VendorType": "" + } +}` diff --git a/cmd/piper.go b/cmd/piper.go index 384cb64d8a..b33f6444ea 100644 --- a/cmd/piper.go +++ b/cmd/piper.go @@ -105,6 +105,7 @@ func Execute() { rootCmd.AddCommand(JsonApplyPatchCommand()) rootCmd.AddCommand(KanikoExecuteCommand()) rootCmd.AddCommand(AbapEnvironmentAssemblePackagesCommand()) + rootCmd.AddCommand(AbapAddonAssemblyKitCheckCVsCommand()) addRootFlags(rootCmd) if err := rootCmd.Execute(); err != nil { diff --git a/documentation/docs/steps/abapAddonAssemblyKitCheckCVs.md b/documentation/docs/steps/abapAddonAssemblyKitCheckCVs.md new file mode 100644 index 0000000000..f2b3fb9384 --- /dev/null +++ b/documentation/docs/steps/abapAddonAssemblyKitCheckCVs.md @@ -0,0 +1,48 @@ +# ${docGenStepName} + +## ${docGenDescription} + +## Prerequisites + +* The credentials to access the AAKaaS (e.g. S-User) must be stored in the Jenkins Credential Store +* The step needs an addon.yml containing information about the Product Version and corresponding Software Component Versions/Repositories. The addon.yml should look like this: + +```yaml +addonProduct: /DMO/myAddonProduct +addonVersion: 3.1.4 +addonUniqueID: myAddonId +customerID: $ID +repositories: + - name: /DMO/REPO_A + tag: v-1.0.1-build-0001 + version: 1.0.1 + - name: /DMO/REPO_B + tag: rel-2.1.1-build-0001 + version: 2.1.1 +``` + +## ${docGenParameters} + +## ${docGenConfiguration} + +## ${docJenkinsPluginDependencies} + +## Examples + +### Configuration in the config.yml + +The recommended way to configure your pipeline is via the config.yml file. In this case, calling the step in the Jenkinsfile is reduced to one line: + +```groovy +abapAddonAssemblyKitCheckPV script: this +``` + +The config.yml should look like this: + +```yaml +steps: + abapAddonAssemblyKitCheckCVs: + abapAddonAssemblyKitCredentialsId: 'abapAddonAssemblyKitCredentialsId', + abapAddonAssemblyKitEndpoint: 'https://myabapAddonAssemblyKitEndpoint.com', + addonDescriptorFileName: 'addon.yml' +``` diff --git a/documentation/mkdocs.yml b/documentation/mkdocs.yml index 720b31bbac..ce1205901a 100644 --- a/documentation/mkdocs.yml +++ b/documentation/mkdocs.yml @@ -49,6 +49,7 @@ nav: - 'Build an SAP Fiori Application and Attach It to a Transport Request on an ABAP System with Jenkins': scenarios/upload-to-transportrequest/Readme.md - Extensibility: extensibility.md - 'Library steps': + - abapAddonAssemblyKitCheckCVs: steps/abapAddonAssemblyKitCheckCVs.md - abapEnvironmentAssemblePackages: steps/abapEnvironmentAssemblePackages.md - abapEnvironmentCheckoutBranch: steps/abapEnvironmentCheckoutBranch.md - abapEnvironmentCloneGitRepo: steps/abapEnvironmentCloneGitRepo.md diff --git a/pkg/abap/build/connector.go b/pkg/abap/build/connector.go new file mode 100644 index 0000000000..c9e35846a3 --- /dev/null +++ b/pkg/abap/build/connector.go @@ -0,0 +1,106 @@ +package build + +import ( + "bytes" + "io/ioutil" + "net/http" + "net/http/cookiejar" + + piperhttp "github.com/SAP/jenkins-library/pkg/http" + "github.com/pkg/errors" +) + +// Connector : Connector Utility Wrapping http client +type Connector struct { + Client piperhttp.Sender + DownloadClient piperhttp.Downloader + Header map[string][]string + Baseurl string +} + +// ******** technical communication calls ******** + +// GetToken : Get the X-CRSF Token from ABAP Backend for later post +func (conn *Connector) GetToken(appendum string) error { + url := conn.Baseurl + appendum + conn.Header["X-CSRF-Token"] = []string{"Fetch"} + response, err := conn.Client.SendRequest("HEAD", url, nil, conn.Header, nil) + if err != nil { + if response == nil { + return errors.Wrap(err, "Fetching X-CSRF-Token failed") + } + defer response.Body.Close() + errorbody, _ := ioutil.ReadAll(response.Body) + return errors.Wrapf(err, "Fetching X-CSRF-Token failed: %v", string(errorbody)) + + } + defer response.Body.Close() + token := response.Header.Get("X-CSRF-Token") + conn.Header["X-CSRF-Token"] = []string{token} + return nil +} + +// Get : http get request +func (conn Connector) Get(appendum string) ([]byte, error) { + url := conn.Baseurl + appendum + response, err := conn.Client.SendRequest("GET", url, nil, conn.Header, nil) + if err != nil { + if response == nil { + return nil, errors.Wrap(err, "Get failed") + } + defer response.Body.Close() + errorbody, _ := ioutil.ReadAll(response.Body) + return errorbody, errors.Wrapf(err, "Get failed: %v", string(errorbody)) + + } + defer response.Body.Close() + body, err := ioutil.ReadAll(response.Body) + return body, err +} + +// Post : http post request +func (conn Connector) Post(appendum string, importBody string) ([]byte, error) { + url := conn.Baseurl + appendum + var response *http.Response + var err error + if importBody == "" { + response, err = conn.Client.SendRequest("POST", url, nil, conn.Header, nil) + } else { + response, err = conn.Client.SendRequest("POST", url, bytes.NewBuffer([]byte(importBody)), conn.Header, nil) + } + if err != nil { + if response == nil { + return nil, errors.Wrap(err, "Post failed") + } + defer response.Body.Close() + errorbody, _ := ioutil.ReadAll(response.Body) + return errorbody, errors.Wrapf(err, "Post failed: %v", string(errorbody)) + + } + defer response.Body.Close() + body, err := ioutil.ReadAll(response.Body) + return body, err +} + +// Download : download a file via http +func (conn Connector) Download(appendum string, downloadPath string) error { + url := conn.Baseurl + appendum + err := conn.DownloadClient.DownloadFile(url, downloadPath, nil, nil) + return err +} + +// InitAAKaaS : initializie Connector for communication with AAKaaS backend +func (conn *Connector) InitAAKaaS(aAKaaSEndpoint string, username string, password string, inputclient piperhttp.Sender) { + conn.Client = inputclient + conn.Header = make(map[string][]string) + conn.Header["Accept"] = []string{"application/json"} + conn.Header["Content-Type"] = []string{"application/json"} + + cookieJar, _ := cookiejar.New(nil) + conn.Client.SetOptions(piperhttp.ClientOptions{ + Username: username, + Password: password, + CookieJar: cookieJar, + }) + conn.Baseurl = aAKaaSEndpoint +} diff --git a/pkg/abaputils/abaputils.go b/pkg/abaputils/abaputils.go index 4299eff1d7..a35c6646b6 100644 --- a/pkg/abaputils/abaputils.go +++ b/pkg/abaputils/abaputils.go @@ -194,6 +194,9 @@ func ConvertTime(logTimeStamp string) time.Time { return t } +// ReadAddonDescriptorType is the type for ReadAddonDescriptor for mocking +type ReadAddonDescriptorType func(FileName string) (AddonDescriptor, error) + // ReadAddonDescriptor parses AddonDescriptor YAML file func ReadAddonDescriptor(FileName string) (AddonDescriptor, error) { diff --git a/resources/metadata/abapAddonAssemblyKitCheckCVs.yaml b/resources/metadata/abapAddonAssemblyKitCheckCVs.yaml new file mode 100644 index 0000000000..28b98fffa8 --- /dev/null +++ b/resources/metadata/abapAddonAssemblyKitCheckCVs.yaml @@ -0,0 +1,66 @@ +metadata: + name: abapAddonAssemblyKitCheckCVs + description: This step checks the validity of Software Component Versions. + longDescription: | + This steps takes a list of Software Component Versions from the addonDescriptorFileName and checks whether they exist or are a valid successor of an existing Software Component Version. + It resolves the dotted version string into version, support package level and patch level and writes it to the commonPipelineEnvironment. + +spec: + inputs: + secrets: + - name: abapAddonAssemblyKitCredentialsId + description: Credential stored in Jenkins for Addon Assembly Kit as a Service System (AAKaaS) + type: jenkins + params: + - name: abapAddonAssemblyKitEndpoint + type: string + description: Base URL to the Addon Assembly Kit as a Service (AAKaaS) system + scope: + - PARAMETERS + - STAGES + - STEPS + - GENERAL + mandatory: true + - name: username + type: string + description: User for the Addon Assembly Kit as a Service System (AAKaaS) + scope: + - PARAMETERS + - STAGES + - STEPS + mandatory: true + secret: true + - name: password + type: string + description: Password the Addon Assembly Kit as a Service System (AAKaaS) + scope: + - PARAMETERS + mandatory: true + secret: true + - name: addonDescriptorFileName + type: string + description: File name of the YAML file which describes the Product Version and corresponding Software Component Versions + mandatory: true + default: addon.yml + scope: + - PARAMETERS + - STAGES + - STEPS + - GENERAL + - name: addonDescriptor + type: string + description: Structure in the commonPipelineEnvironment containing information about the Product Version and corresponding Software Component Versions + mandatory: false + scope: + - PARAMETERS + - STAGES + - STEPS + resourceRef: + - name: commonPipelineEnvironment + param: abap/addonDescriptor + outputs: + resources: + - name: commonPipelineEnvironment + type: piperEnvironment + params: + - name: abap/addonDescriptor diff --git a/test/groovy/CommonStepsTest.groovy b/test/groovy/CommonStepsTest.groovy index 6ea6b7c162..3ed3de5a7f 100644 --- a/test/groovy/CommonStepsTest.groovy +++ b/test/groovy/CommonStepsTest.groovy @@ -106,6 +106,7 @@ public class CommonStepsTest extends BasePiperTest{ } private static fieldRelatedWhitelist = [ + 'abapAddonAssemblyKitCheckCVs', //implementing new golang pattern without fields 'abapEnvironmentAssemblePackages', //implementing new golang pattern without fields 'abapEnvironmentCheckoutBranch', //implementing new golang pattern without fields 'abapEnvironmentCloneGitRepo', //implementing new golang pattern without fields diff --git a/vars/abapAddonAssemblyKitCheckCVs.groovy b/vars/abapAddonAssemblyKitCheckCVs.groovy new file mode 100644 index 0000000000..806e113ba6 --- /dev/null +++ b/vars/abapAddonAssemblyKitCheckCVs.groovy @@ -0,0 +1,11 @@ +import groovy.transform.Field + +@Field String STEP_NAME = getClass().getName() +@Field String METADATA_FILE = 'metadata/abapAddonAssemblyKitCheckCVs.yaml' + +void call(Map parameters = [:]) { + List credentials = [ + [type: 'usernamePassword', id: 'abapAddonAssemblyKitCredentialsId', env: ['PIPER_username', 'PIPER_password']] + ] + piperExecuteBin(parameters, STEP_NAME, METADATA_FILE, credentials, false, false, true) +}