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

Abap refactoring (#3340)

* Update abapAddonAssemblyKitReleasePackages.go

* add error handling for initAAKaaS

* runtime to config, url.QueryEscape, check return body

* Update abapAddonAssemblyKitCheckCVs_test.go

* add log entrys for testing

* correct yaml

* change unmarshal logic

* Update abapAddonAssemblyKitCheckPV_test.go

* adding utils functionality

* Update bfw_test.go

* reset CheckPV

* reset CheckCVs

* reset ReserveNextPackages

* set back CheckPV and CheckCVs

* moving mock

* renaming

* renaming

* moving mocking to checkCVs test

* fixing unittests

* trying mock with comment

* referencing unittest to mockfile

* Update abapAddonAssemblyKitCheckCVs.go

* Update cmd/abapAddonAssemblyKitCheckPV.go

Co-authored-by: tiloKo <70266685+tiloKo@users.noreply.github.com>

* Update cmd/abapAddonAssemblyKitReleasePackages.go

Co-authored-by: tiloKo <70266685+tiloKo@users.noreply.github.com>

* Update cmd/abapAddonAssemblyKitPublishTargetVector.go

Co-authored-by: tiloKo <70266685+tiloKo@users.noreply.github.com>

* Update cmd/abapAddonAssemblyKitReserveNextPackages.go

Co-authored-by: tiloKo <70266685+tiloKo@users.noreply.github.com>

* fixing unittests

* fixing mock comment

Co-authored-by: tiloKo <70266685+tiloKo@users.noreply.github.com>
This commit is contained in:
rosemarieB
2021-12-09 12:54:18 +01:00
committed by GitHub
parent c1dc725fcc
commit e6c5c8a72f
19 changed files with 511 additions and 268 deletions

View File

@@ -3,39 +3,31 @@ package cmd
import (
"encoding/json"
"fmt"
"net/url"
"github.com/SAP/jenkins-library/pkg/abap/aakaas"
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"
"github.com/pkg/errors"
)
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 {
utils := aakaas.NewAakBundle()
if err := runAbapAddonAssemblyKitCheckCVs(&config, telemetryData, &utils, cpe); 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 {
func runAbapAddonAssemblyKitCheckCVs(config *abapAddonAssemblyKitCheckCVsOptions, telemetryData *telemetry.CustomData, utils *aakaas.AakUtils, cpe *abapAddonAssemblyKitCheckCVsCommonPipelineEnvironment) error {
conn := new(abapbuild.Connector)
conn.InitAAKaaS(config.AbapAddonAssemblyKitEndpoint, config.Username, config.Password, client)
if err := conn.InitAAKaaS(config.AbapAddonAssemblyKitEndpoint, config.Username, config.Password, *utils); err != nil {
return err
}
log.Entry().Infof("Reading Product Version Information from addonDescriptor (aka addon.yml) file: %s", config.AddonDescriptorFileName)
addonDescriptor, err := readAdoDescriptor(config.AddonDescriptorFileName)
addonDescriptor, err := (*utils).ReadAddonDescriptor(config.AddonDescriptorFileName)
if err != nil {
return err
}
@@ -87,13 +79,15 @@ func (c *componentVersion) copyFieldsToRepo(initialRepo *abaputils.Repository) {
func (c *componentVersion) 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 + "'"
appendum := "/odata/aas_ocs_package/ValidateComponentVersion?Name='" + url.QueryEscape(c.Name) + "'&Version='" + url.QueryEscape(c.VersionYAML) + "'"
body, err := c.Connector.Get(appendum)
if err != nil {
return err
}
var jCV jsonComponentVersion
json.Unmarshal(body, &jCV)
if err := json.Unmarshal(body, &jCV); err != nil {
return errors.Wrap(err, "Unexpected AAKaaS response for Validate Component Version: "+string(body))
}
c.Name = jCV.ComponentVersion.Name
c.Version = jCV.ComponentVersion.Version
c.SpLevel = jCV.ComponentVersion.SpLevel

View File

@@ -4,60 +4,24 @@ import (
"encoding/json"
"testing"
"github.com/SAP/jenkins-library/pkg/abap/aakaas"
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",
CommitID: "HUGO1234",
},
},
}
}
case "noCommitID":
{
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,
}
bundle := aakaas.NewAakBundleMock()
bundle.SetBody(responseCheckCVs)
utils := bundle.GetUtils()
config.Username = "dummyUser"
config.Password = "dummyPassword"
t.Run("step success", func(t *testing.T) {
config.AddonDescriptorFileName = "success"
err := runAbapAddonAssemblyKitCheckCVs(&config, nil, client, &cpe, mockReadAddonDescriptor)
err := runAbapAddonAssemblyKitCheckCVs(&config, nil, &utils, &cpe)
assert.NoError(t, err, "Did not expect error")
var addonDescriptorFinal abaputils.AddonDescriptor
json.Unmarshal([]byte(cpe.abap.addonDescriptor), &addonDescriptorFinal)
@@ -68,23 +32,21 @@ func TestCheckCVsStep(t *testing.T) {
})
t.Run("step error - in validate(no CommitID)", func(t *testing.T) {
config.AddonDescriptorFileName = "noCommitID"
err := runAbapAddonAssemblyKitCheckCVs(&config, nil, client, &cpe, mockReadAddonDescriptor)
err := runAbapAddonAssemblyKitCheckCVs(&config, nil, &utils, &cpe)
assert.Error(t, err, "Must end with error")
assert.Contains(t, err.Error(), "CommitID missing in repo")
})
t.Run("step error - in ReadAddonDescriptor", func(t *testing.T) {
config.AddonDescriptorFileName = "failing"
err := runAbapAddonAssemblyKitCheckCVs(&config, nil, client, &cpe, mockReadAddonDescriptor)
err := runAbapAddonAssemblyKitCheckCVs(&config, nil, &utils, &cpe)
assert.Error(t, err, "Must end with error")
assert.Contains(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)
bundle.SetBody("ErrorBody")
bundle.SetError("error during validation")
err := runAbapAddonAssemblyKitCheckCVs(&config, nil, &utils, &cpe)
assert.Error(t, err, "Must end with error")
})
}

View File

@@ -4,39 +4,31 @@ import (
"encoding/json"
"net/url"
"github.com/SAP/jenkins-library/pkg/abap/aakaas"
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/piperutils"
"github.com/SAP/jenkins-library/pkg/telemetry"
"github.com/pkg/errors"
)
func abapAddonAssemblyKitCheckPV(config abapAddonAssemblyKitCheckPVOptions, telemetryData *telemetry.CustomData, cpe *abapAddonAssemblyKitCheckPVCommonPipelineEnvironment) {
// 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{}
utils := aakaas.NewAakBundle()
// error situations should stop execution through log.Entry().Fatal() call which leads to an os.Exit(1) in the end
err := runAbapAddonAssemblyKitCheckPV(&config, telemetryData, &client, cpe, abaputils.ReadAddonDescriptor)
if err != nil {
if err := runAbapAddonAssemblyKitCheckPV(&config, telemetryData, &utils, cpe); err != nil {
log.Entry().WithError(err).Fatal("step execution failed")
}
}
func runAbapAddonAssemblyKitCheckPV(config *abapAddonAssemblyKitCheckPVOptions, telemetryData *telemetry.CustomData, client piperhttp.Sender,
cpe *abapAddonAssemblyKitCheckPVCommonPipelineEnvironment, readAdoDescriptor abaputils.ReadAddonDescriptorType) error {
func runAbapAddonAssemblyKitCheckPV(config *abapAddonAssemblyKitCheckPVOptions, telemetryData *telemetry.CustomData, utils *aakaas.AakUtils, cpe *abapAddonAssemblyKitCheckPVCommonPipelineEnvironment) error {
conn := new(abapbuild.Connector)
conn.InitAAKaaS(config.AbapAddonAssemblyKitEndpoint, config.Username, config.Password, client)
if err := conn.InitAAKaaS(config.AbapAddonAssemblyKitEndpoint, config.Username, config.Password, *utils); err != nil {
return err
}
log.Entry().Infof("Reading Product Version Information from addonDescriptor (aka addon.yml) file: %s", config.AddonDescriptorFileName)
addonDescriptor, err := readAdoDescriptor(config.AddonDescriptorFileName)
addonDescriptor, err := (*utils).ReadAddonDescriptor(config.AddonDescriptorFileName)
if err != nil {
return err
}
@@ -93,7 +85,9 @@ func (p *productVersion) validateAndResolveVersionFields() error {
return err
}
var jPV jsonProductVersion
json.Unmarshal(body, &jPV)
if err := json.Unmarshal(body, &jPV); err != nil {
return errors.Wrap(err, "Unexpected AAKaaS response for Validate Product Version: "+string(body))
}
p.Name = jPV.ProductVersion.Name
p.Version = jPV.ProductVersion.Version
p.SpsLevel = jPV.ProductVersion.SpsLevel

View File

@@ -4,6 +4,7 @@ import (
"encoding/json"
"testing"
"github.com/SAP/jenkins-library/pkg/abap/aakaas"
abapbuild "github.com/SAP/jenkins-library/pkg/abap/build"
"github.com/SAP/jenkins-library/pkg/abaputils"
"github.com/pkg/errors"
@@ -13,12 +14,14 @@ import (
func TestCheckPVStep(t *testing.T) {
var config abapAddonAssemblyKitCheckPVOptions
var cpe abapAddonAssemblyKitCheckPVCommonPipelineEnvironment
client := &abaputils.ClientMock{
Body: responseCheckPV,
}
bundle := aakaas.NewAakBundleMock()
bundle.SetBody(responseCheckPV)
utils := bundle.GetUtils()
config.Username = "dummyUser"
config.Password = "dummyPassword"
t.Run("step success", func(t *testing.T) {
config.AddonDescriptorFileName = "success"
err := runAbapAddonAssemblyKitCheckPV(&config, nil, client, &cpe, mockReadAddonDescriptor)
err := runAbapAddonAssemblyKitCheckPV(&config, nil, &utils, &cpe)
assert.NoError(t, err, "Did not expect error")
var addonDescriptorFinal abaputils.AddonDescriptor
json.Unmarshal([]byte(cpe.abap.addonDescriptor), &addonDescriptorFinal)
@@ -28,17 +31,15 @@ func TestCheckPVStep(t *testing.T) {
})
t.Run("step error - in ReadAddonDescriptor", func(t *testing.T) {
config.AddonDescriptorFileName = "failing"
err := runAbapAddonAssemblyKitCheckPV(&config, nil, client, &cpe, mockReadAddonDescriptor)
err := runAbapAddonAssemblyKitCheckPV(&config, nil, &utils, &cpe)
assert.Error(t, err, "Did expect error")
assert.Equal(t, err.Error(), "error in ReadAddonDescriptor")
})
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 := runAbapAddonAssemblyKitCheckPV(&config, nil, client, &cpe, mockReadAddonDescriptor)
bundle.SetBody("ErrorBody")
bundle.SetError("error during validation")
err := runAbapAddonAssemblyKitCheckPV(&config, nil, &utils, &cpe)
assert.Error(t, err, "Did expect error")
})
}

View File

@@ -6,38 +6,28 @@ import (
"github.com/SAP/jenkins-library/pkg/abap/aakaas"
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"
"github.com/pkg/errors"
)
func abapAddonAssemblyKitPublishTargetVector(config abapAddonAssemblyKitPublishTargetVectorOptions, telemetryData *telemetry.CustomData) {
// 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{}
utils := aakaas.NewAakBundleWithTime(time.Duration(config.MaxRuntimeInMinutes), time.Duration(config.PollingIntervalInSeconds))
// error situations should stop execution through log.Entry().Fatal() call which leads to an os.Exit(1) in the end
err := runAbapAddonAssemblyKitPublishTargetVector(&config, telemetryData, &client, time.Duration(config.MaxRuntimeInMinutes)*time.Minute, time.Duration(config.PollingIntervalInSeconds)*time.Second)
if err != nil {
if err := runAbapAddonAssemblyKitPublishTargetVector(&config, telemetryData, &utils); err != nil {
log.Entry().WithError(err).Fatal("step execution failed")
}
}
func runAbapAddonAssemblyKitPublishTargetVector(config *abapAddonAssemblyKitPublishTargetVectorOptions, telemetryData *telemetry.CustomData, client piperhttp.Sender,
maxRuntime time.Duration, pollingInterval time.Duration) error {
func runAbapAddonAssemblyKitPublishTargetVector(config *abapAddonAssemblyKitPublishTargetVectorOptions, telemetryData *telemetry.CustomData, utils *aakaas.AakUtils) error {
conn := new(abapbuild.Connector)
if err := conn.InitAAKaaS(config.AbapAddonAssemblyKitEndpoint, config.Username, config.Password, client); err != nil {
if err := conn.InitAAKaaS(config.AbapAddonAssemblyKitEndpoint, config.Username, config.Password, *utils); err != nil {
return err
}
conn.MaxRuntime = maxRuntime
conn.PollingInterval = pollingInterval
conn.MaxRuntime = (*utils).GetMaxRuntime()
conn.PollingInterval = (*utils).GetPollingInterval()
addonDescriptor := new(abaputils.AddonDescriptor)
if err := addonDescriptor.InitFromJSONstring(config.AddonDescriptor); err != nil {

View File

@@ -3,12 +3,10 @@ package cmd
import (
"encoding/json"
"testing"
"time"
"github.com/SAP/jenkins-library/pkg/abap/aakaas"
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"
)
@@ -32,9 +30,11 @@ func TestPublishTargetVectorStep(t *testing.T) {
mc.AddData(aakaas.AAKaaSTVPublishProdPost)
mc.AddData(aakaas.AAKaaSGetTVPublishRunning)
mc.AddData(aakaas.AAKaaSGetTVPublishProdSuccess)
bundle := aakaas.NewAakBundleMockNewMC(&mc)
utils := bundle.GetUtils()
//act
err := runAbapAddonAssemblyKitPublishTargetVector(&config, nil, &mc, time.Duration(1*time.Second), time.Duration(1*time.Microsecond))
err := runAbapAddonAssemblyKitPublishTargetVector(&config, nil, &utils)
//assert
assert.NoError(t, err, "Did not expect error")
})
@@ -47,20 +47,24 @@ func TestPublishTargetVectorStep(t *testing.T) {
mc.AddData(aakaas.AAKaaSTVPublishTestPost)
mc.AddData(aakaas.AAKaaSGetTVPublishRunning)
mc.AddData(aakaas.AAKaaSGetTVPublishTestSuccess)
bundle := aakaas.NewAakBundleMockNewMC(&mc)
utils := bundle.GetUtils()
//act
err := runAbapAddonAssemblyKitPublishTargetVector(&config, nil, &mc, time.Duration(1*time.Second), time.Duration(1*time.Microsecond))
err := runAbapAddonAssemblyKitPublishTargetVector(&config, nil, &utils)
//assert
assert.NoError(t, err, "Did not expect error")
})
t.Run("step fail http", func(t *testing.T) {
//arrange
client := &abaputils.ClientMock{
Body: "dummy",
Error: errors.New("dummy"),
}
bundle := aakaas.NewAakBundleMock()
bundle.SetBody("dummy")
bundle.SetError("dummy")
utils := bundle.GetUtils()
//act
err := runAbapAddonAssemblyKitPublishTargetVector(&config, nil, client, time.Duration(1*time.Second), time.Duration(1*time.Microsecond))
err := runAbapAddonAssemblyKitPublishTargetVector(&config, nil, &utils)
//assert
assert.Error(t, err, "Must end with error")
})
@@ -69,8 +73,11 @@ func TestPublishTargetVectorStep(t *testing.T) {
//arrange
config := abapAddonAssemblyKitPublishTargetVectorOptions{}
mc := abapbuild.NewMockClient()
bundle := aakaas.NewAakBundleMockNewMC(&mc)
utils := bundle.GetUtils()
//act
err := runAbapAddonAssemblyKitPublishTargetVector(&config, nil, &mc, time.Duration(1*time.Second), time.Duration(1*time.Microsecond))
err := runAbapAddonAssemblyKitPublishTargetVector(&config, nil, &utils)
//assert
assert.Error(t, err, "Must end with error")
})

View File

@@ -7,35 +7,26 @@ import (
"github.com/SAP/jenkins-library/pkg/abap/aakaas"
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"
"github.com/pkg/errors"
)
func abapAddonAssemblyKitReleasePackages(config abapAddonAssemblyKitReleasePackagesOptions, telemetryData *telemetry.CustomData, cpe *abapAddonAssemblyKitReleasePackagesCommonPipelineEnvironment) {
// for command execution use Command
c := command.Command{}
// reroute command output to logging framework
c.Stdout(log.Writer())
c.Stderr(log.Writer())
utils := aakaas.NewAakBundleWithTime(time.Duration(config.MaxRuntimeInMinutes), time.Duration(config.PollingIntervalInSeconds))
client := piperhttp.Client{}
maxRuntimeInMinutes := time.Duration(5 * time.Minute)
pollIntervalsInSeconds := time.Duration(30 * time.Second)
// error situations should stop execution through log.Entry().Fatal() call which leads to an os.Exit(1) in the end
err := runAbapAddonAssemblyKitReleasePackages(&config, telemetryData, &client, cpe, maxRuntimeInMinutes, pollIntervalsInSeconds)
if err != nil {
if err := runAbapAddonAssemblyKitReleasePackages(&config, telemetryData, &utils, cpe); err != nil {
log.Entry().WithError(err).Fatal("step execution failed")
}
}
func runAbapAddonAssemblyKitReleasePackages(config *abapAddonAssemblyKitReleasePackagesOptions, telemetryData *telemetry.CustomData, client piperhttp.Sender,
cpe *abapAddonAssemblyKitReleasePackagesCommonPipelineEnvironment, maxRuntimeInMinutes time.Duration, pollIntervalsInSeconds time.Duration) error {
func runAbapAddonAssemblyKitReleasePackages(config *abapAddonAssemblyKitReleasePackagesOptions, telemetryData *telemetry.CustomData, utils *aakaas.AakUtils,
cpe *abapAddonAssemblyKitReleasePackagesCommonPipelineEnvironment) error {
conn := new(abapbuild.Connector)
conn.InitAAKaaS(config.AbapAddonAssemblyKitEndpoint, config.Username, config.Password, client)
if err := conn.InitAAKaaS(config.AbapAddonAssemblyKitEndpoint, config.Username, config.Password, *utils); err != nil {
return err
}
var addonDescriptor abaputils.AddonDescriptor
json.Unmarshal([]byte(config.AddonDescriptor), &addonDescriptor)
@@ -44,14 +35,13 @@ func runAbapAddonAssemblyKitReleasePackages(config *abapAddonAssemblyKitReleaseP
return err
}
packagesWithReposLocked, packagesWithReposNotLocked := sortByStatus(addonDescriptor.Repositories, *conn)
packagesWithReposLocked, err = releaseAndPoll(packagesWithReposLocked, maxRuntimeInMinutes, pollIntervalsInSeconds)
packagesWithReposLocked, err = releaseAndPoll(packagesWithReposLocked, utils)
if err != nil {
return err
}
addonDescriptor.Repositories = sortingBack(packagesWithReposLocked, packagesWithReposNotLocked)
log.Entry().Info("Writing package status to CommonPipelineEnvironment")
backToCPE, _ := json.Marshal(addonDescriptor)
cpe.abap.addonDescriptor = string(backToCPE)
cpe.abap.addonDescriptor = string(addonDescriptor.AsJSON())
return nil
}
@@ -96,9 +86,9 @@ func sortByStatus(repos []abaputils.Repository, conn abapbuild.Connector) ([]aak
return packagesWithReposLocked, packagesWithReposNotLocked
}
func releaseAndPoll(pckgWR []aakaas.PackageWithRepository, maxRuntimeInMinutes time.Duration, pollIntervalsInSeconds time.Duration) ([]aakaas.PackageWithRepository, error) {
timeout := time.After(maxRuntimeInMinutes)
ticker := time.Tick(pollIntervalsInSeconds)
func releaseAndPoll(pckgWR []aakaas.PackageWithRepository, utils *aakaas.AakUtils) ([]aakaas.PackageWithRepository, error) {
timeout := time.After((*utils).GetMaxRuntime())
ticker := time.Tick((*utils).GetPollingInterval())
for {
select {
@@ -111,7 +101,7 @@ func releaseAndPoll(pckgWR []aakaas.PackageWithRepository, maxRuntimeInMinutes t
err := pckgWR[i].Package.Release()
// if there is an error, release is not yet finished
if err != nil {
log.Entry().Infof("Release of %s is not yet finished, check again in %s", pckgWR[i].Package.PackageName, pollIntervalsInSeconds)
log.Entry().Infof("Release of %s is not yet finished, check again in %s", pckgWR[i].Package.PackageName, (*utils).GetPollingInterval())
allFinished = false
}
}

View File

@@ -22,6 +22,8 @@ type abapAddonAssemblyKitReleasePackagesOptions struct {
Username string `json:"username,omitempty"`
Password string `json:"password,omitempty"`
AddonDescriptor string `json:"addonDescriptor,omitempty"`
MaxRuntimeInMinutes int `json:"maxRuntimeInMinutes,omitempty"`
PollingIntervalInSeconds int `json:"pollingIntervalInSeconds,omitempty"`
}
type abapAddonAssemblyKitReleasePackagesCommonPipelineEnvironment struct {
@@ -150,6 +152,8 @@ func addAbapAddonAssemblyKitReleasePackagesFlags(cmd *cobra.Command, stepConfig
cmd.Flags().StringVar(&stepConfig.Username, "username", os.Getenv("PIPER_username"), "User for the Addon Assembly Kit as a Service (AAKaaS) system")
cmd.Flags().StringVar(&stepConfig.Password, "password", os.Getenv("PIPER_password"), "Password for the Addon Assembly Kit as a Service (AAKaaS) system")
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.Flags().IntVar(&stepConfig.MaxRuntimeInMinutes, "maxRuntimeInMinutes", 5, "Maximum runtime for status polling in minutes")
cmd.Flags().IntVar(&stepConfig.PollingIntervalInSeconds, "pollingIntervalInSeconds", 30, "Wait time in seconds between polling calls")
cmd.MarkFlagRequired("abapAddonAssemblyKitEndpoint")
cmd.MarkFlagRequired("username")
@@ -212,6 +216,24 @@ func abapAddonAssemblyKitReleasePackagesMetadata() config.StepData {
Aliases: []config.Alias{},
Default: os.Getenv("PIPER_addonDescriptor"),
},
{
Name: "maxRuntimeInMinutes",
ResourceRef: []config.ResourceReference{},
Scope: []string{"PARAMETERS", "STAGES", "STEPS", "GENERAL"},
Type: "int",
Mandatory: false,
Aliases: []config.Alias{},
Default: 5,
},
{
Name: "pollingIntervalInSeconds",
ResourceRef: []config.ResourceReference{},
Scope: []string{"PARAMETERS", "STAGES", "STEPS", "GENERAL"},
Type: "int",
Mandatory: false,
Aliases: []config.Alias{},
Default: 30,
},
},
},
Outputs: config.StepOutputs{

View File

@@ -5,22 +5,22 @@ import (
"testing"
"time"
"github.com/SAP/jenkins-library/pkg/abap/aakaas"
"github.com/SAP/jenkins-library/pkg/abaputils"
"github.com/pkg/errors"
"github.com/stretchr/testify/assert"
)
func TestReleasePackagesStep(t *testing.T) {
var config abapAddonAssemblyKitReleasePackagesOptions
var cpe abapAddonAssemblyKitReleasePackagesCommonPipelineEnvironment
client := &abaputils.ClientMock{
Body: responseRelease,
Token: "myToken",
StatusCode: 200,
}
timeout := time.Duration(5 * time.Second)
pollInterval := time.Duration(1 * time.Second)
bundle := aakaas.NewAakBundleMock()
bundle.SetBody(responseRelease)
utils := bundle.GetUtils()
config.Username = "dummyUser"
config.Password = "dummyPassword"
t.Run("step success", func(t *testing.T) {
//arrange
addonDescriptor := abaputils.AddonDescriptor{
Repositories: []abaputils.Repository{
{
@@ -35,9 +35,9 @@ func TestReleasePackagesStep(t *testing.T) {
}
adoDesc, _ := json.Marshal(addonDescriptor)
config.AddonDescriptor = string(adoDesc)
err := runAbapAddonAssemblyKitReleasePackages(&config, nil, client, &cpe, timeout, pollInterval)
//act
err := runAbapAddonAssemblyKitReleasePackages(&config, nil, &utils, &cpe)
//assert
assert.NoError(t, err, "Did not expect error")
var addonDescriptorFinal abaputils.AddonDescriptor
json.Unmarshal([]byte(cpe.abap.addonDescriptor), &addonDescriptorFinal)
@@ -45,6 +45,7 @@ func TestReleasePackagesStep(t *testing.T) {
})
t.Run("step error - invalid input", func(t *testing.T) {
//arrange
addonDescriptor := abaputils.AddonDescriptor{
Repositories: []abaputils.Repository{
{
@@ -54,14 +55,17 @@ func TestReleasePackagesStep(t *testing.T) {
}
adoDesc, _ := json.Marshal(addonDescriptor)
config.AddonDescriptor = string(adoDesc)
err := runAbapAddonAssemblyKitReleasePackages(&config, nil, client, &cpe, timeout, pollInterval)
//act
err := runAbapAddonAssemblyKitReleasePackages(&config, nil, &utils, &cpe)
//assert
assert.Error(t, err, "Did expect error")
assert.Equal(t, err.Error(), "Parameter missing. Please provide the name of the package which should be released")
})
t.Run("step error - timeout", func(t *testing.T) {
client.Error = errors.New("Release not finished")
//arrange
bundle.SetError("Release not finished")
bundle.SetMaxRuntime(1 * time.Microsecond)
addonDescriptor := abaputils.AddonDescriptor{
Repositories: []abaputils.Repository{
{
@@ -72,9 +76,9 @@ func TestReleasePackagesStep(t *testing.T) {
}
adoDesc, _ := json.Marshal(addonDescriptor)
config.AddonDescriptor = string(adoDesc)
timeout := time.Duration(2 * time.Second)
err := runAbapAddonAssemblyKitReleasePackages(&config, nil, client, &cpe, timeout, pollInterval)
//act
err := runAbapAddonAssemblyKitReleasePackages(&config, nil, &utils, &cpe)
//assert
assert.Error(t, err, "Did expect error")
assert.Equal(t, err.Error(), "Timed out")
})

View File

@@ -7,35 +7,25 @@ import (
"github.com/SAP/jenkins-library/pkg/abap/aakaas"
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"
"github.com/pkg/errors"
)
func abapAddonAssemblyKitReserveNextPackages(config abapAddonAssemblyKitReserveNextPackagesOptions, telemetryData *telemetry.CustomData, cpe *abapAddonAssemblyKitReserveNextPackagesCommonPipelineEnvironment) {
// 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{}
maxRuntimeInMinutes := time.Duration(5 * time.Minute)
pollIntervalsInSeconds := time.Duration(30 * time.Second)
utils := aakaas.NewAakBundleWithTime(time.Duration(config.MaxRuntimeInMinutes), time.Duration(config.PollingIntervalInSeconds))
// error situations should stop execution through log.Entry().Fatal() call which leads to an os.Exit(1) in the end
err := runAbapAddonAssemblyKitReserveNextPackages(&config, telemetryData, &client, cpe, maxRuntimeInMinutes, pollIntervalsInSeconds)
if err != nil {
if err := runAbapAddonAssemblyKitReserveNextPackages(&config, telemetryData, &utils, cpe); err != nil {
log.Entry().WithError(err).Fatal("step execution failed")
}
}
func runAbapAddonAssemblyKitReserveNextPackages(config *abapAddonAssemblyKitReserveNextPackagesOptions, telemetryData *telemetry.CustomData, client piperhttp.Sender,
cpe *abapAddonAssemblyKitReserveNextPackagesCommonPipelineEnvironment, maxRuntimeInMinutes time.Duration, pollIntervalsInSeconds time.Duration) error {
func runAbapAddonAssemblyKitReserveNextPackages(config *abapAddonAssemblyKitReserveNextPackagesOptions, telemetryData *telemetry.CustomData, utils *aakaas.AakUtils,
cpe *abapAddonAssemblyKitReserveNextPackagesCommonPipelineEnvironment) error {
conn := new(abapbuild.Connector)
if err := conn.InitAAKaaS(config.AbapAddonAssemblyKitEndpoint, config.Username, config.Password, client); err != nil {
if err := conn.InitAAKaaS(config.AbapAddonAssemblyKitEndpoint, config.Username, config.Password, *utils); err != nil {
return err
}
@@ -49,8 +39,7 @@ func runAbapAddonAssemblyKitReserveNextPackages(config *abapAddonAssemblyKitRese
return err
}
err = pollReserveNextPackages(packagesWithRepos, maxRuntimeInMinutes, pollIntervalsInSeconds)
if err != nil {
if err = pollReserveNextPackages(packagesWithRepos, utils); err != nil {
return err
}
@@ -104,9 +93,10 @@ func checkAndCopyFieldsToRepositories(pckgWR []aakaas.PackageWithRepository) ([]
return repos, nil
}
func pollReserveNextPackages(pckgWR []aakaas.PackageWithRepository, maxRuntimeInMinutes time.Duration, pollIntervalsInSeconds time.Duration) error {
timeout := time.After(maxRuntimeInMinutes)
ticker := time.Tick(pollIntervalsInSeconds)
func pollReserveNextPackages(pckgWR []aakaas.PackageWithRepository, utils *aakaas.AakUtils) error {
pollingInterval := (*utils).GetPollingInterval()
timeout := time.After((*utils).GetMaxRuntime())
ticker := time.Tick(pollingInterval)
for {
select {
case <-timeout:
@@ -117,14 +107,14 @@ func pollReserveNextPackages(pckgWR []aakaas.PackageWithRepository, maxRuntimeIn
err := pckgWR[i].Package.GetPackageAndNamespace()
// if there is an error, reservation is not yet finished
if err != nil {
log.Entry().Infof("Reservation of %s is not yet finished, check again in %s", pckgWR[i].Package.PackageName, pollIntervalsInSeconds)
log.Entry().Infof("Reservation of %s is not yet finished, check again in %s", pckgWR[i].Package.PackageName, pollingInterval)
allFinished = false
} else {
switch pckgWR[i].Package.Status {
case aakaas.PackageStatusLocked:
return fmt.Errorf("Package %s has invalid status 'locked'", pckgWR[i].Package.PackageName)
case aakaas.PackageStatusCreationTriggered:
log.Entry().Infof("Reservation of %s is still running with status 'creation triggered', check again in %s", pckgWR[i].Package.PackageName, pollIntervalsInSeconds)
log.Entry().Infof("Reservation of %s is still running with status 'creation triggered', check again in %s", pckgWR[i].Package.PackageName, pollingInterval)
allFinished = false
case aakaas.PackageStatusPlanned:
log.Entry().Infof("Reservation of %s was successful with status 'planned'", pckgWR[i].Package.PackageName)

View File

@@ -22,6 +22,8 @@ type abapAddonAssemblyKitReserveNextPackagesOptions struct {
Username string `json:"username,omitempty"`
Password string `json:"password,omitempty"`
AddonDescriptor string `json:"addonDescriptor,omitempty"`
MaxRuntimeInMinutes int `json:"maxRuntimeInMinutes,omitempty"`
PollingIntervalInSeconds int `json:"pollingIntervalInSeconds,omitempty"`
}
type abapAddonAssemblyKitReserveNextPackagesCommonPipelineEnvironment struct {
@@ -156,6 +158,8 @@ func addAbapAddonAssemblyKitReserveNextPackagesFlags(cmd *cobra.Command, stepCon
cmd.Flags().StringVar(&stepConfig.Username, "username", os.Getenv("PIPER_username"), "User for the Addon Assembly Kit as a Service (AAKaaS) system")
cmd.Flags().StringVar(&stepConfig.Password, "password", os.Getenv("PIPER_password"), "Password for the Addon Assembly Kit as a Service (AAKaaS) system")
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.Flags().IntVar(&stepConfig.MaxRuntimeInMinutes, "maxRuntimeInMinutes", 5, "Maximum runtime for status polling in minutes")
cmd.Flags().IntVar(&stepConfig.PollingIntervalInSeconds, "pollingIntervalInSeconds", 30, "Wait time in seconds between polling calls")
cmd.MarkFlagRequired("abapAddonAssemblyKitEndpoint")
cmd.MarkFlagRequired("username")
@@ -218,6 +222,24 @@ func abapAddonAssemblyKitReserveNextPackagesMetadata() config.StepData {
Aliases: []config.Alias{},
Default: os.Getenv("PIPER_addonDescriptor"),
},
{
Name: "maxRuntimeInMinutes",
ResourceRef: []config.ResourceReference{},
Scope: []string{"PARAMETERS", "STAGES", "STEPS", "GENERAL"},
Type: "int",
Mandatory: false,
Aliases: []config.Alias{},
Default: 5,
},
{
Name: "pollingIntervalInSeconds",
ResourceRef: []config.ResourceReference{},
Scope: []string{"PARAMETERS", "STAGES", "STEPS", "GENERAL"},
Type: "int",
Mandatory: false,
Aliases: []config.Alias{},
Default: 30,
},
},
},
Outputs: config.StepOutputs{

View File

@@ -17,8 +17,8 @@ func TestReserveNextPackagesStep(t *testing.T) {
config.Username = "dummy"
config.Password = "dummy"
var cpe abapAddonAssemblyKitReserveNextPackagesCommonPipelineEnvironment
timeout := time.Duration(5 * time.Second)
pollInterval := time.Duration(1 * time.Second)
bundle := aakaas.NewAakBundleMock()
utils := bundle.GetUtils()
t.Run("step success", func(t *testing.T) {
addonDescriptor := abaputils.AddonDescriptor{
Repositories: []abaputils.Repository{
@@ -36,12 +36,9 @@ func TestReserveNextPackagesStep(t *testing.T) {
}
adoDesc, _ := json.Marshal(addonDescriptor)
config.AddonDescriptor = string(adoDesc)
client := &abaputils.ClientMock{
BodyList: []string{responseReserveNextPackageReleased, responseReserveNextPackagePlanned, responseReserveNextPackagePostReleased, "myToken", responseReserveNextPackagePostPlanned, "myToken"},
}
err := runAbapAddonAssemblyKitReserveNextPackages(&config, nil, client, &cpe, timeout, pollInterval)
bodyList := []string{responseReserveNextPackageReleased, responseReserveNextPackagePlanned, responseReserveNextPackagePostReleased, "myToken", responseReserveNextPackagePostPlanned, "myToken"}
bundle.SetBodyList(bodyList)
err := runAbapAddonAssemblyKitReserveNextPackages(&config, nil, &utils, &cpe)
assert.NoError(t, err, "Did not expect error")
var addonDescriptorFinal abaputils.AddonDescriptor
json.Unmarshal([]byte(cpe.abap.addonDescriptor), &addonDescriptorFinal)
@@ -58,9 +55,7 @@ func TestReserveNextPackagesStep(t *testing.T) {
}
adoDesc, _ := json.Marshal(addonDescriptor)
config.AddonDescriptor = string(adoDesc)
client := &abaputils.ClientMock{}
err := runAbapAddonAssemblyKitReserveNextPackages(&config, nil, client, &cpe, timeout, pollInterval)
err := runAbapAddonAssemblyKitReserveNextPackages(&config, nil, &utils, &cpe)
assert.Error(t, err, "Did expect error")
})
t.Run("step error - timeout", func(t *testing.T) {
@@ -74,12 +69,10 @@ func TestReserveNextPackagesStep(t *testing.T) {
}
adoDesc, _ := json.Marshal(addonDescriptor)
config.AddonDescriptor = string(adoDesc)
client := &abaputils.ClientMock{
BodyList: []string{responseReserveNextPackageCreationTriggered, responseReserveNextPackagePostPlanned, "myToken"},
}
timeout := time.Duration(1 * time.Second)
err := runAbapAddonAssemblyKitReserveNextPackages(&config, nil, client, &cpe, timeout, pollInterval)
bodyList := []string{responseReserveNextPackageCreationTriggered, responseReserveNextPackagePostPlanned, "myToken"}
bundle.SetBodyList(bodyList)
bundle.SetMaxRuntime(time.Duration(1 * time.Microsecond))
err := runAbapAddonAssemblyKitReserveNextPackages(&config, nil, &utils, &cpe)
assert.Error(t, err, "Did expect error")
})
}
@@ -251,62 +244,53 @@ func TestReservePackages(t *testing.T) {
// ********************* Test pollReserveNextPackages *******************
func TestPollReserveNextPackages(t *testing.T) {
timeout := time.Duration(5 * time.Second)
pollInterval := time.Duration(1 * time.Second)
bundle := aakaas.NewAakBundleMock()
utils := bundle.GetUtils()
t.Run("test pollReserveNextPackages - testing loop", func(t *testing.T) {
client := abaputils.ClientMock{
BodyList: []string{responseReserveNextPackagePlanned, responseReserveNextPackageCreationTriggered},
}
pckgWR := testPollPackagesSetup(client)
err := pollReserveNextPackages(pckgWR, timeout, pollInterval)
bodyList := []string{responseReserveNextPackagePlanned, responseReserveNextPackageCreationTriggered}
bundle.SetBodyList(bodyList)
pckgWR := testPollPackagesSetup(&utils)
err := pollReserveNextPackages(pckgWR, &utils)
assert.NoError(t, err)
assert.Equal(t, aakaas.PackageStatusPlanned, pckgWR[0].Package.Status)
assert.Equal(t, "/DRNMSPC/", pckgWR[0].Package.Namespace)
})
t.Run("test pollReserveNextPackages - status locked", func(t *testing.T) {
client := abaputils.ClientMock{
Body: responseReserveNextPackageLocked,
}
pckgWR := testPollPackagesSetup(client)
err := pollReserveNextPackages(pckgWR, timeout, pollInterval)
bundle.SetBody(responseReserveNextPackageLocked)
pckgWR := testPollPackagesSetup(&utils)
err := pollReserveNextPackages(pckgWR, &utils)
assert.Error(t, err)
assert.Equal(t, aakaas.PackageStatusLocked, pckgWR[0].Package.Status)
})
t.Run("test pollReserveNextPackages - status released", func(t *testing.T) {
client := abaputils.ClientMock{
Body: responseReserveNextPackageReleased,
}
pckgWR := testPollPackagesSetup(client)
err := pollReserveNextPackages(pckgWR, timeout, pollInterval)
bundle.SetBody(responseReserveNextPackageReleased)
pckgWR := testPollPackagesSetup(&utils)
err := pollReserveNextPackages(pckgWR, &utils)
assert.NoError(t, err)
assert.Equal(t, aakaas.PackageStatusReleased, pckgWR[0].Package.Status)
})
t.Run("test pollReserveNextPackages - unknow status", func(t *testing.T) {
client := abaputils.ClientMock{
Body: responseReserveNextPackageUnknownState,
}
pckgWR := testPollPackagesSetup(client)
err := pollReserveNextPackages(pckgWR, timeout, pollInterval)
bundle.SetBody(responseReserveNextPackageUnknownState)
pckgWR := testPollPackagesSetup(&utils)
err := pollReserveNextPackages(pckgWR, &utils)
assert.Error(t, err)
assert.Equal(t, aakaas.PackageStatus("X"), pckgWR[0].Package.Status)
})
t.Run("test pollReserveNextPackages - timeout", func(t *testing.T) {
client := abaputils.ClientMock{
Body: "ErrorBody",
Error: errors.New("Failure during reserve next"),
}
pckgWR := testPollPackagesSetup(client)
timeout := time.Duration(2 * time.Second)
err := pollReserveNextPackages(pckgWR, timeout, pollInterval)
bundle.SetBody(responseReserveNextPackageUnknownState)
bundle.SetError("Failure during reserve next")
bundle.SetMaxRuntime(time.Duration(1 * time.Microsecond))
pckgWR := testPollPackagesSetup(&utils)
err := pollReserveNextPackages(pckgWR, &utils)
assert.Error(t, err)
})
}
// ********************* Setup functions *******************
func testPollPackagesSetup(client abaputils.ClientMock) []aakaas.PackageWithRepository {
func testPollPackagesSetup(utils *aakaas.AakUtils) []aakaas.PackageWithRepository {
conn := new(abapbuild.Connector)
conn.Client = &client
conn.Client = *utils
conn.Header = make(map[string][]string)
pckgWR := []aakaas.PackageWithRepository{
{

View File

@@ -0,0 +1,61 @@
package aakaas
import (
"time"
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"
)
type AakUtils interface {
command.ExecRunner
abapbuild.HTTPSendLoader
ReadAddonDescriptor(FileName string) (abaputils.AddonDescriptor, error)
GetMaxRuntime() time.Duration
GetPollingInterval() time.Duration
}
type AakBundle struct {
*command.Command
*piperhttp.Client
maxRuntime time.Duration
pollingInterval time.Duration
}
func (bundle *AakBundle) GetMaxRuntime() time.Duration {
return bundle.maxRuntime
}
func (bundle *AakBundle) GetPollingInterval() time.Duration {
return bundle.pollingInterval
}
func (bundle *AakBundle) ReadAddonDescriptor(FileName string) (abaputils.AddonDescriptor, error) {
return abaputils.ReadAddonDescriptor(FileName)
}
func NewAakBundleWithTime(maxRuntime time.Duration, pollingInterval time.Duration) AakUtils {
utils := AakBundle{
Command: &command.Command{},
Client: &piperhttp.Client{},
maxRuntime: maxRuntime * time.Minute,
pollingInterval: pollingInterval * time.Second,
}
// Reroute command output to logging framework
utils.Stdout(log.Writer())
utils.Stderr(log.Writer())
return &utils
}
func NewAakBundle() AakUtils {
utils := AakBundle{
Command: &command.Command{},
Client: &piperhttp.Client{},
}
// Reroute command output to logging framework
utils.Stdout(log.Writer())
utils.Stderr(log.Writer())
return &utils
}

View File

@@ -0,0 +1,131 @@
//go:build !release
// +build !release
package aakaas
import (
"time"
abapbuild "github.com/SAP/jenkins-library/pkg/abap/build"
"github.com/SAP/jenkins-library/pkg/abaputils"
"github.com/SAP/jenkins-library/pkg/mock"
"github.com/pkg/errors"
)
type AakBundleMock struct {
*mock.ExecMockRunner
*abaputils.ClientMock
maxRuntime time.Duration
}
func NewAakBundleMock() *AakBundleMock {
utils := AakBundleMock{
ExecMockRunner: &mock.ExecMockRunner{},
ClientMock: &abaputils.ClientMock{},
maxRuntime: 1 * time.Second,
}
return &utils
}
func (bundle *AakBundleMock) GetUtils() AakUtils {
return bundle
}
func (bundle *AakBundleMock) GetMaxRuntime() time.Duration {
return bundle.maxRuntime
}
func (bundle *AakBundleMock) SetMaxRuntime(maxRuntime time.Duration) {
bundle.maxRuntime = maxRuntime
}
func (bundle *AakBundleMock) GetPollingInterval() time.Duration {
return 1 * time.Microsecond
}
func (bundle *AakBundleMock) SetBodyList(bodyList []string) {
bundle.ClientMock.Body = ""
bundle.ClientMock.BodyList = bodyList
}
func (bundle *AakBundleMock) SetBody(body string) {
bundle.ClientMock.Body = body
bundle.ClientMock.BodyList = []string{}
}
func (bundle *AakBundleMock) SetError(errorText string) {
bundle.ClientMock.Error = errors.New(errorText)
}
func (bundle *AakBundleMock) ReadAddonDescriptor(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",
CommitID: "HUGO1234",
},
},
}
}
case "noCommitID":
{
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
}
//*****************************other client mock *******************************
type AakBundleMockNewMC struct {
*mock.ExecMockRunner
*abapbuild.MockClient
maxRuntime time.Duration
}
func NewAakBundleMockNewMC(mC *abapbuild.MockClient) *AakBundleMockNewMC {
utils := AakBundleMockNewMC{
ExecMockRunner: &mock.ExecMockRunner{},
MockClient: mC,
maxRuntime: 1 * time.Second,
}
return &utils
}
func (bundle *AakBundleMockNewMC) GetUtils() AakUtils {
return bundle
}
func (bundle *AakBundleMockNewMC) GetMaxRuntime() time.Duration {
return bundle.maxRuntime
}
func (bundle *AakBundleMockNewMC) GetPollingInterval() time.Duration {
return 1 * time.Microsecond
}
func (bundle *AakBundleMockNewMC) ReadAddonDescriptor(FileName string) (abaputils.AddonDescriptor, error) {
var addonDescriptor abaputils.AddonDescriptor
err := errors.New("don't use this")
return addonDescriptor, err
}

View File

@@ -2,12 +2,12 @@ package aakaas
import (
"encoding/json"
"errors"
"fmt"
"net/url"
abapbuild "github.com/SAP/jenkins-library/pkg/abap/build"
"github.com/SAP/jenkins-library/pkg/abaputils"
"github.com/SAP/jenkins-library/pkg/log"
"github.com/pkg/errors"
)
// PackageStatus : Status of an ABAP delivery package
@@ -79,13 +79,15 @@ func (p *Package) ReserveNext() error {
}
log.Entry().Infof("Reserve package for %s version %s", p.ComponentName, p.VersionYAML)
p.Connector.GetToken("/odata/aas_ocs_package")
appendum := "/odata/aas_ocs_package/DeterminePackageForScv?Name='" + p.ComponentName + "'&Version='" + p.VersionYAML + "'"
appendum := "/odata/aas_ocs_package/DeterminePackageForScv?Name='" + url.QueryEscape(p.ComponentName) + "'&Version='" + url.QueryEscape(p.VersionYAML) + "'"
body, err := p.Connector.Post(appendum, "")
if err != nil {
return err
}
var jPck jsonPackageDeterminePackageForScv
json.Unmarshal(body, &jPck)
if err := json.Unmarshal(body, &jPck); err != nil {
return errors.Wrap(err, "Unexpected AAKaaS response for reserve package: "+string(body))
}
p.PackageName = jPck.DeterminePackage.Package.PackageName
p.Type = jPck.DeterminePackage.Package.Type
p.PredecessorCommitID = jPck.DeterminePackage.Package.PredecessorCommitID
@@ -98,13 +100,15 @@ func (p *Package) ReserveNext() error {
// GetPackageAndNamespace : retrieve attributes of the package from AAKaaS
func (p *Package) GetPackageAndNamespace() error {
appendum := "/odata/aas_ocs_package/OcsPackageSet('" + p.PackageName + "')"
appendum := "/odata/aas_ocs_package/OcsPackageSet('" + url.QueryEscape(p.PackageName) + "')"
body, err := p.Connector.Get(appendum)
if err != nil {
return err
}
var jPck jsonPackage
json.Unmarshal(body, &jPck)
if err := json.Unmarshal(body, &jPck); err != nil {
return errors.Wrap(err, "Unexpected AAKaaS response for check of package status: "+string(body))
}
p.Status = jPck.Package.Status
p.Namespace = jPck.Package.Namespace
return nil
@@ -122,16 +126,15 @@ func (p *Package) Register() error {
}
log.Entry().Infof("Register package %s", p.PackageName)
p.Connector.GetToken("/odata/aas_ocs_package")
appendum := "/odata/aas_ocs_package/RegisterPackage?Name='" + p.PackageName + "'"
appendum := "/odata/aas_ocs_package/RegisterPackage?Name='" + url.QueryEscape(p.PackageName) + "'"
body, err := p.Connector.Post(appendum, "")
if err != nil {
return err
}
var jPck jsonPackage
err = json.Unmarshal(body, &jPck)
if err != nil {
return fmt.Errorf("failed to parse package status from response: %w", err)
if err := json.Unmarshal(body, &jPck); err != nil {
return errors.Wrap(err, "Unexpected AAKaaS response for register package: "+string(body))
}
p.Status = jPck.Package.Status
log.Entry().Infof("Package status %s", p.Status)
@@ -144,13 +147,15 @@ func (p *Package) Release() error {
var err error
log.Entry().Infof("Release package %s", p.PackageName)
p.Connector.GetToken("/odata/aas_ocs_package")
appendum := "/odata/aas_ocs_package/ReleasePackage?Name='" + p.PackageName + "'"
appendum := "/odata/aas_ocs_package/ReleasePackage?Name='" + url.QueryEscape(p.PackageName) + "'"
body, err = p.Connector.Post(appendum, "")
if err != nil {
return err
}
var jPck jsonPackage
json.Unmarshal(body, &jPck)
if err := json.Unmarshal(body, &jPck); err != nil {
return errors.Wrap(err, "Unexpected AAKaaS response for release package: "+string(body))
}
p.Status = jPck.Package.Status
return nil
}

View File

@@ -3,6 +3,7 @@ package build
import (
"encoding/json"
"fmt"
"net/url"
"path"
"path/filepath"
"sort"
@@ -43,17 +44,35 @@ const (
)
//******** structs needed for json convertion ********
type jsonBuild struct {
Build *Build `json:"d"`
Build struct {
BuildID string `json:"build_id"`
RunState RunState `json:"run_state"`
ResultState resultState `json:"result_state"`
Phase string `json:"phase"`
Entitytype string `json:"entitytype"`
Startedby string `json:"startedby"`
StartedAt string `json:"started_at"`
FinishedAt string `json:"finished_at"`
} `json:"d"`
}
type jsonTasks struct {
ResultTasks struct {
Tasks []task `json:"results"`
Tasks []jsonTask `json:"results"`
} `json:"d"`
}
type jsonTask struct {
BuildID string `json:"build_id"`
TaskID int `json:"task_id"`
LogID string `json:"log_id"`
PluginClass string `json:"plugin_class"`
StartedAt string `json:"started_at"`
FinishedAt string `json:"finished_at"`
ResultState resultState `json:"result_state"`
}
type jsonLogs struct {
ResultLogs struct {
Logs []logStruct `json:"results"`
@@ -162,7 +181,9 @@ func (b *Build) Start(phase string, inputValues Values) error {
}
var jBuild jsonBuild
json.Unmarshal(body, &jBuild)
if err := json.Unmarshal(body, &jBuild); err != nil {
return errors.Wrap(err, "Unexpected buildFrameWork response: "+string(body))
}
b.BuildID = jBuild.Build.BuildID
b.RunState = jBuild.Build.RunState
b.ResultState = jBuild.Build.ResultState
@@ -209,13 +230,15 @@ func (b *Build) EvaluteIfBuildSuccessful(treatWarningsAsError bool) error {
// Get : Get all Build tasks
func (b *Build) Get() error {
appendum := "/builds('" + b.BuildID + "')"
appendum := "/builds('" + url.QueryEscape(b.BuildID) + "')"
body, err := b.Connector.Get(appendum)
if err != nil {
return err
}
var jBuild jsonBuild
json.Unmarshal(body, &jBuild)
if err := json.Unmarshal(body, &jBuild); err != nil {
return errors.Wrap(err, "Unexpected buildFrameWork response: "+string(body))
}
b.RunState = jBuild.Build.RunState
b.ResultState = jBuild.Build.ResultState
b.Phase = jBuild.Build.Phase
@@ -228,20 +251,18 @@ func (b *Build) Get() error {
func (b *Build) getTasks() error {
if len(b.Tasks) == 0 {
appendum := "/builds('" + b.BuildID + "')/tasks"
appendum := "/builds('" + url.QueryEscape(b.BuildID) + "')/tasks"
body, err := b.Connector.Get(appendum)
if err != nil {
return err
}
var jTasks jsonTasks
json.Unmarshal(body, &jTasks)
b.Tasks = jTasks.ResultTasks.Tasks
b.Tasks, err = unmarshalTasks(body, b.Connector)
if err != nil {
return err
}
sort.Slice(b.Tasks, func(i, j int) bool {
return b.Tasks[i].TaskID < b.Tasks[j].TaskID
})
for i := range b.Tasks {
b.Tasks[i].connector = b.Connector
}
}
return nil
}
@@ -249,13 +270,15 @@ func (b *Build) getTasks() error {
// GetValues : Gets all Build values
func (b *Build) GetValues() error {
if len(b.Values) == 0 {
appendum := "/builds('" + b.BuildID + "')/values"
appendum := "/builds('" + url.QueryEscape(b.BuildID) + "')/values"
body, err := b.Connector.Get(appendum)
if err != nil {
return err
}
var jValues jsonValues
json.Unmarshal(body, &jValues)
if err := json.Unmarshal(body, &jValues); err != nil {
return errors.Wrap(err, "Unexpected buildFrameWork response: "+string(body))
}
b.Values = jValues.ResultValues.Values
for i := range b.Values {
b.Values[i].connector = b.Connector
@@ -346,13 +369,15 @@ func (b *Build) IsFinished() bool {
func (t *task) getLogs() error {
if len(t.Logs) == 0 {
appendum := fmt.Sprint("/tasks(build_id='", t.BuildID, "',task_id=", t.TaskID, ")/logs")
appendum := fmt.Sprint("/tasks(build_id='", url.QueryEscape(t.BuildID), "',task_id=", t.TaskID, ")/logs")
body, err := t.connector.Get(appendum)
if err != nil {
return err
}
var jLogs jsonLogs
json.Unmarshal(body, &jLogs)
if err := json.Unmarshal(body, &jLogs); err != nil {
return errors.Wrap(err, "Unexpected buildFrameWork response: "+string(body))
}
t.Logs = jLogs.ResultLogs.Logs
}
return nil
@@ -360,13 +385,15 @@ func (t *task) getLogs() error {
func (t *task) getResults() error {
if len(t.Results) == 0 {
appendum := fmt.Sprint("/tasks(build_id='", t.BuildID, "',task_id=", t.TaskID, ")/results")
appendum := fmt.Sprint("/tasks(build_id='", url.QueryEscape(t.BuildID), "',task_id=", t.TaskID, ")/results")
body, err := t.connector.Get(appendum)
if err != nil {
return err
}
var jResults jsonResults
json.Unmarshal(body, &jResults)
if err := json.Unmarshal(body, &jResults); err != nil {
return errors.Wrap(err, "Unexpected buildFrameWork response: "+string(body))
}
t.Results = jResults.ResultResults.Results
for i := range t.Results {
t.Results[i].connector = t.connector
@@ -452,7 +479,7 @@ func (b *Build) PublishDownloadedResults(stepname string, filenames []string, pu
// Download : Provides the atrefact of build step
func (result *Result) Download(downloadPath string) error {
appendum := fmt.Sprint("/results(build_id='", result.BuildID, "',task_id=", result.TaskID, ",name='", result.Name, "')/$value")
appendum := fmt.Sprint("/results(build_id='", url.QueryEscape(result.BuildID), "',task_id=", result.TaskID, ",name='", url.QueryEscape(result.Name), "')/$value")
err := result.connector.Download(appendum, downloadPath)
return err
}
@@ -543,6 +570,29 @@ func (in inputForPost) String() string {
return fmt.Sprintf(`{ "phase": "%s", "values": [%s]}`, in.phase, in.values.String())
}
//******** unmarshal function ************
func unmarshalTasks(body []byte, connector Connector) ([]task, error) {
var tasks []task
var append_task task
var jTasks jsonTasks
if err := json.Unmarshal(body, &jTasks); err != nil {
return tasks, errors.Wrap(err, "Unexpected buildFrameWork response: "+string(body))
}
for _, jTask := range jTasks.ResultTasks.Tasks {
append_task.connector = connector
append_task.BuildID = jTask.BuildID
append_task.TaskID = jTask.TaskID
append_task.LogID = jTask.LogID
append_task.PluginClass = jTask.PluginClass
append_task.StartedAt = jTask.StartedAt
append_task.FinishedAt = jTask.FinishedAt
append_task.ResultState = jTask.ResultState
tasks = append(tasks, append_task)
}
return tasks, nil
}
// *****************publish *******************************
type Publish interface {
PersistReportsAndLinks(stepName, workspace string, reports, links []piperutils.Path)

View File

@@ -162,7 +162,7 @@ func TestPoll(t *testing.T) {
t.Run("Poll timeout", func(t *testing.T) {
//arrange
build.BuildID = "AKO22FYOFYPOXHOBVKXUTX3A3Q"
conn.MaxRuntime = time.Duration(2 * time.Microsecond)
conn.MaxRuntime = time.Duration(1 * time.Microsecond)
conn.PollingInterval = time.Duration(1 * time.Microsecond)
mc := NewMockClient()
mc.AddData(buildGet1)

View File

@@ -48,6 +48,24 @@ spec:
resourceRef:
- name: commonPipelineEnvironment
param: abap/addonDescriptor
- name: maxRuntimeInMinutes
type: int
description: Maximum runtime for status polling in minutes
scope:
- PARAMETERS
- STAGES
- STEPS
- GENERAL
default: 5
- name: pollingIntervalInSeconds
type: int
description: Wait time in seconds between polling calls
scope:
- PARAMETERS
- STAGES
- STEPS
- GENERAL
default: 30
outputs:
resources:
- name: commonPipelineEnvironment

View File

@@ -54,6 +54,24 @@ spec:
resourceRef:
- name: commonPipelineEnvironment
param: abap/addonDescriptor
- name: maxRuntimeInMinutes
type: int
description: Maximum runtime for status polling in minutes
scope:
- PARAMETERS
- STAGES
- STEPS
- GENERAL
default: 5
- name: pollingIntervalInSeconds
type: int
description: Wait time in seconds between polling calls
scope:
- PARAMETERS
- STAGES
- STEPS
- GENERAL
default: 30
outputs:
resources:
- name: commonPipelineEnvironment