From 54479f7255e10d4765c67d1672e81b077079cac2 Mon Sep 17 00:00:00 2001 From: tiloKo <70266685+tiloKo@users.noreply.github.com> Date: Fri, 12 Nov 2021 14:33:18 +0100 Subject: [PATCH] abapAddonAssemblyKitPublishTargetVector polling + refactoring (#3271) * new checks for commitIDs * new checks for commitIDs * relocate step from build stage to initial checks + refac * log list * fix log + check * log format * fix unit tests * targetVector refac + polling * refac * refac 2 * polling * remove debug output * remove debug output Co-authored-by: Christian Luttenberger <42861202+bluesbrother84@users.noreply.github.com> --- cmd/abapAddonAssemblyKitCreateTargetVector.go | 100 +--- ...AddonAssemblyKitCreateTargetVector_test.go | 5 +- ...abapAddonAssemblyKitPublishTargetVector.go | 61 ++- ...ssemblyKitPublishTargetVector_generated.go | 22 + ...ddonAssemblyKitPublishTargetVector_test.go | 34 +- pkg/abap/aakaas/targetVector.go | 323 ++++++++++++ pkg/abap/aakaas/targetVector_test.go | 180 +++++++ pkg/abap/build/connector.go | 10 +- pkg/abap/build/mockClient.go | 474 +++++++++--------- ...apAddonAssemblyKitPublishTargetVector.yaml | 18 + 10 files changed, 870 insertions(+), 357 deletions(-) create mode 100644 pkg/abap/aakaas/targetVector.go create mode 100644 pkg/abap/aakaas/targetVector_test.go diff --git a/cmd/abapAddonAssemblyKitCreateTargetVector.go b/cmd/abapAddonAssemblyKitCreateTargetVector.go index b0450bf09..c92e1eed4 100644 --- a/cmd/abapAddonAssemblyKitCreateTargetVector.go +++ b/cmd/abapAddonAssemblyKitCreateTargetVector.go @@ -1,8 +1,7 @@ package cmd import ( - "encoding/json" - + "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" @@ -30,96 +29,29 @@ func abapAddonAssemblyKitCreateTargetVector(config abapAddonAssemblyKitCreateTar func runAbapAddonAssemblyKitCreateTargetVector(config *abapAddonAssemblyKitCreateTargetVectorOptions, telemetryData *telemetry.CustomData, client piperhttp.Sender, cpe *abapAddonAssemblyKitCreateTargetVectorCommonPipelineEnvironment) error { conn := new(abapbuild.Connector) - conn.InitAAKaaS(config.AbapAddonAssemblyKitEndpoint, config.Username, config.Password, client) - var addonDescriptor abaputils.AddonDescriptor - json.Unmarshal([]byte(config.AddonDescriptor), &addonDescriptor) - - var tv targetVector - err := tv.init(addonDescriptor) - if err != nil { + if err := conn.InitAAKaaS(config.AbapAddonAssemblyKitEndpoint, config.Username, config.Password, client); err != nil { return err } + + addonDescriptor := new(abaputils.AddonDescriptor) + if err := addonDescriptor.InitFromJSONstring(config.AddonDescriptor); err != nil { + return errors.Wrap(err, "Reading AddonDescriptor failed [Make sure abapAddonAssemblyKit...CheckCVs|CheckPV steps have been run before]") + } + + var tv aakaas.TargetVector + if err := tv.InitNew(addonDescriptor); err != nil { + return err + } + log.Entry().Infof("Create target vector for product %s version %s", addonDescriptor.AddonProduct, addonDescriptor.AddonVersionYAML) - err = tv.createTargetVector(*conn) - if err != nil { + if err := tv.CreateTargetVector(conn); err != nil { return err } log.Entry().Infof("Created target vector %s", tv.ID) addonDescriptor.TargetVectorID = tv.ID + log.Entry().Info("Write target vector to CommonPipelineEnvironment") - toCPE, _ := json.Marshal(addonDescriptor) - cpe.abap.addonDescriptor = string(toCPE) + cpe.abap.addonDescriptor = addonDescriptor.AsJSONstring() return nil } - -func (tv *targetVector) init(addonDescriptor abaputils.AddonDescriptor) error { - if addonDescriptor.AddonProduct == "" || addonDescriptor.AddonVersion == "" || addonDescriptor.AddonSpsLevel == "" || addonDescriptor.AddonPatchLevel == "" { - return errors.New("Parameters missing. Please provide product name, version, spslevel and patchlevel") - } - - tv.ProductName = addonDescriptor.AddonProduct - tv.ProductVersion = addonDescriptor.AddonVersion - tv.SpsLevel = addonDescriptor.AddonSpsLevel - tv.PatchLevel = addonDescriptor.AddonPatchLevel - - var tvCVs []targetVectorCV - var tvCV targetVectorCV - for i := range addonDescriptor.Repositories { - if addonDescriptor.Repositories[i].Name == "" || addonDescriptor.Repositories[i].Version == "" || addonDescriptor.Repositories[i].SpLevel == "" || - addonDescriptor.Repositories[i].PatchLevel == "" || addonDescriptor.Repositories[i].PackageName == "" { - return errors.New("Parameters missing. Please provide software component name, version, splevel, patchlevel and packagename") - } - tvCV.ScName = addonDescriptor.Repositories[i].Name - tvCV.ScVersion = addonDescriptor.Repositories[i].Version - tvCV.DeliveryPackage = addonDescriptor.Repositories[i].PackageName - tvCV.SpLevel = addonDescriptor.Repositories[i].SpLevel - tvCV.PatchLevel = addonDescriptor.Repositories[i].PatchLevel - tvCVs = append(tvCVs, tvCV) - } - tv.Content.TargetVectorCVs = tvCVs - return nil -} - -func (tv *targetVector) createTargetVector(conn abapbuild.Connector) error { - conn.GetToken("/odata/aas_ocs_package") - tvJSON, err := json.Marshal(tv) - if err != nil { - return err - } - appendum := "/odata/aas_ocs_package/TargetVectorSet" - body, err := conn.Post(appendum, string(tvJSON)) - if err != nil { - return err - } - var jTV jsonTargetVector - json.Unmarshal(body, &jTV) - tv.ID = jTV.Tv.ID - return nil -} - -type jsonTargetVector struct { - Tv *targetVector `json:"d"` -} - -type targetVector struct { - ID string `json:"Id"` - ProductName string `json:"ProductName"` - ProductVersion string `json:"ProductVersion"` - SpsLevel string `json:"SpsLevel"` - PatchLevel string `json:"PatchLevel"` - Content targetVectorCVs `json:"Content"` -} - -type targetVectorCV struct { - ID string `json:"Id"` - ScName string `json:"ScName"` - ScVersion string `json:"ScVersion"` - DeliveryPackage string `json:"DeliveryPackage"` - SpLevel string `json:"SpLevel"` - PatchLevel string `json:"PatchLevel"` -} - -type targetVectorCVs struct { - TargetVectorCVs []targetVectorCV `json:"results"` -} diff --git a/cmd/abapAddonAssemblyKitCreateTargetVector_test.go b/cmd/abapAddonAssemblyKitCreateTargetVector_test.go index 7fb96135f..0c1912fda 100644 --- a/cmd/abapAddonAssemblyKitCreateTargetVector_test.go +++ b/cmd/abapAddonAssemblyKitCreateTargetVector_test.go @@ -11,7 +11,10 @@ import ( func TestCreateTargetVectorStep(t *testing.T) { //setup - config := abapAddonAssemblyKitCreateTargetVectorOptions{} + config := abapAddonAssemblyKitCreateTargetVectorOptions{ + Username: "dummy", + Password: "dummy", + } addonDescriptor := abaputils.AddonDescriptor{ AddonProduct: "dummy", AddonVersion: "dummy", diff --git a/cmd/abapAddonAssemblyKitPublishTargetVector.go b/cmd/abapAddonAssemblyKitPublishTargetVector.go index 55495abb8..0296c0922 100644 --- a/cmd/abapAddonAssemblyKitPublishTargetVector.go +++ b/cmd/abapAddonAssemblyKitPublishTargetVector.go @@ -1,8 +1,9 @@ package cmd import ( - "encoding/json" + "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/SAP/jenkins-library/pkg/command" @@ -22,33 +23,51 @@ func abapAddonAssemblyKitPublishTargetVector(config abapAddonAssemblyKitPublishT client := piperhttp.Client{} // 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) + err := runAbapAddonAssemblyKitPublishTargetVector(&config, telemetryData, &client, time.Duration(config.MaxRuntimeInMinutes)*time.Minute, time.Duration(config.PollingIntervalInSeconds)*time.Second) if err != nil { log.Entry().WithError(err).Fatal("step execution failed") } } -func runAbapAddonAssemblyKitPublishTargetVector(config *abapAddonAssemblyKitPublishTargetVectorOptions, telemetryData *telemetry.CustomData, client piperhttp.Sender) error { +func runAbapAddonAssemblyKitPublishTargetVector(config *abapAddonAssemblyKitPublishTargetVectorOptions, telemetryData *telemetry.CustomData, client piperhttp.Sender, + maxRuntime time.Duration, pollingInterval time.Duration) error { + conn := new(abapbuild.Connector) - conn.InitAAKaaS(config.AbapAddonAssemblyKitEndpoint, config.Username, config.Password, client) - var addonDescriptor abaputils.AddonDescriptor - json.Unmarshal([]byte(config.AddonDescriptor), &addonDescriptor) - - if addonDescriptor.TargetVectorID == "" { - return errors.New("Parameter missing. Please provide the target vector id") - } - - if config.TargetVectorScope == "T" { - log.Entry().Infof("Publish target vector %s to test SPC", addonDescriptor.TargetVectorID) - } - if config.TargetVectorScope == "P" { - log.Entry().Infof("Publish target vector %s to SPC", addonDescriptor.TargetVectorID) - } - conn.GetToken("/odata/aas_ocs_package") - appendum := "/odata/aas_ocs_package/PublishTargetVector?Id='" + addonDescriptor.TargetVectorID + "'&Scope='" + config.TargetVectorScope + "'" - _, err := conn.Post(appendum, "") - if err != nil { + if err := conn.InitAAKaaS(config.AbapAddonAssemblyKitEndpoint, config.Username, config.Password, client); err != nil { return err } + conn.MaxRuntime = maxRuntime + conn.PollingInterval = pollingInterval + + addonDescriptor := new(abaputils.AddonDescriptor) + if err := addonDescriptor.InitFromJSONstring(config.AddonDescriptor); err != nil { + return errors.Wrap(err, "Reading AddonDescriptor failed [Make sure abapAddonAssemblyKit...CheckCVs|CheckPV steps have been run before]") + } + + if addonDescriptor.TargetVectorID == "" { + return errors.New("Parameter missing. Please provide the target vector id (e.g. by running step abapAddonAssemblyKitCreateTargetVector beforehand") + } + targetVector := new(aakaas.TargetVector) + targetVector.InitExisting(addonDescriptor.TargetVectorID) + + switch config.TargetVectorScope { + case string(aakaas.TargetVectorStatusTest): + log.Entry().Infof("Publish target vector %s for test use", addonDescriptor.TargetVectorID) + case string(aakaas.TargetVectorStatusProductive): + log.Entry().Infof("Publish target vector %s for productive use", addonDescriptor.TargetVectorID) + default: + return errors.New("Invalid Value of configuration Parameter TargetVectorScope: " + config.TargetVectorScope) + } + + if err := targetVector.PublishTargetVector(conn, aakaas.TargetVectorStatus(config.TargetVectorScope)); err != nil { + return err + } + + log.Entry().Info("Waiting for target vector publishing to finish") + if err := targetVector.PollForStatus(conn, aakaas.TargetVectorStatus(config.TargetVectorScope)); err != nil { + return err + } + + log.Entry().Info("Success: Publishing finised") return nil } diff --git a/cmd/abapAddonAssemblyKitPublishTargetVector_generated.go b/cmd/abapAddonAssemblyKitPublishTargetVector_generated.go index 2df4300ad..0dd32e5c9 100644 --- a/cmd/abapAddonAssemblyKitPublishTargetVector_generated.go +++ b/cmd/abapAddonAssemblyKitPublishTargetVector_generated.go @@ -20,6 +20,8 @@ type abapAddonAssemblyKitPublishTargetVectorOptions struct { Username string `json:"username,omitempty"` Password string `json:"password,omitempty"` TargetVectorScope string `json:"targetVectorScope,omitempty" validate:"oneof=T P"` + MaxRuntimeInMinutes int `json:"maxRuntimeInMinutes,omitempty"` + PollingIntervalInSeconds int `json:"pollingIntervalInSeconds,omitempty"` AddonDescriptor string `json:"addonDescriptor,omitempty"` } @@ -116,6 +118,8 @@ func addAbapAddonAssemblyKitPublishTargetVectorFlags(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.TargetVectorScope, "targetVectorScope", `T`, "Determines whether the Target Vector is published to the productive ('P') or test ('T') environment") + 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.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") @@ -174,6 +178,24 @@ func abapAddonAssemblyKitPublishTargetVectorMetadata() config.StepData { Aliases: []config.Alias{}, Default: `T`, }, + { + 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, + }, { Name: "addonDescriptor", ResourceRef: []config.ResourceReference{ diff --git a/cmd/abapAddonAssemblyKitPublishTargetVector_test.go b/cmd/abapAddonAssemblyKitPublishTargetVector_test.go index 068b3bdca..35eeb3ba2 100644 --- a/cmd/abapAddonAssemblyKitPublishTargetVector_test.go +++ b/cmd/abapAddonAssemblyKitPublishTargetVector_test.go @@ -3,7 +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" @@ -13,22 +16,25 @@ func TestPublishTargetVectorStep(t *testing.T) { //setup config := abapAddonAssemblyKitPublishTargetVectorOptions{ TargetVectorScope: "P", + Username: "dummy", + Password: "dummy", } addonDescriptor := abaputils.AddonDescriptor{ - TargetVectorID: "dummy", + TargetVectorID: "W7Q00207512600000353", } adoDesc, _ := json.Marshal(addonDescriptor) config.AddonDescriptor = string(adoDesc) - client := &abaputils.ClientMock{ - Body: "dummy", - Token: "myToken", - StatusCode: 200, - } - t.Run("step success prod", func(t *testing.T) { + //arrange + mc := abapbuild.NewMockClient() + mc.AddData(aakaas.AAKaaSHead) + mc.AddData(aakaas.AAKaaSTVPublishProdPost) + mc.AddData(aakaas.AAKaaSGetTVPublishRunning) + mc.AddData(aakaas.AAKaaSGetTVPublishProdSuccess) + //act - err := runAbapAddonAssemblyKitPublishTargetVector(&config, nil, client) + err := runAbapAddonAssemblyKitPublishTargetVector(&config, nil, &mc, time.Duration(1*time.Second), time.Duration(1*time.Microsecond)) //assert assert.NoError(t, err, "Did not expect error") }) @@ -36,8 +42,13 @@ func TestPublishTargetVectorStep(t *testing.T) { t.Run("step success test", func(t *testing.T) { //arrange config.TargetVectorScope = "T" + mc := abapbuild.NewMockClient() + mc.AddData(aakaas.AAKaaSHead) + mc.AddData(aakaas.AAKaaSTVPublishTestPost) + mc.AddData(aakaas.AAKaaSGetTVPublishRunning) + mc.AddData(aakaas.AAKaaSGetTVPublishTestSuccess) //act - err := runAbapAddonAssemblyKitPublishTargetVector(&config, nil, client) + err := runAbapAddonAssemblyKitPublishTargetVector(&config, nil, &mc, time.Duration(1*time.Second), time.Duration(1*time.Microsecond)) //assert assert.NoError(t, err, "Did not expect error") }) @@ -49,7 +60,7 @@ func TestPublishTargetVectorStep(t *testing.T) { Error: errors.New("dummy"), } //act - err := runAbapAddonAssemblyKitPublishTargetVector(&config, nil, client) + err := runAbapAddonAssemblyKitPublishTargetVector(&config, nil, client, time.Duration(1*time.Second), time.Duration(1*time.Microsecond)) //assert assert.Error(t, err, "Must end with error") }) @@ -57,8 +68,9 @@ func TestPublishTargetVectorStep(t *testing.T) { t.Run("step fail no id", func(t *testing.T) { //arrange config := abapAddonAssemblyKitPublishTargetVectorOptions{} + mc := abapbuild.NewMockClient() //act - err := runAbapAddonAssemblyKitPublishTargetVector(&config, nil, client) + err := runAbapAddonAssemblyKitPublishTargetVector(&config, nil, &mc, time.Duration(1*time.Second), time.Duration(1*time.Microsecond)) //assert assert.Error(t, err, "Must end with error") }) diff --git a/pkg/abap/aakaas/targetVector.go b/pkg/abap/aakaas/targetVector.go new file mode 100644 index 000000000..46c7a7127 --- /dev/null +++ b/pkg/abap/aakaas/targetVector.go @@ -0,0 +1,323 @@ +package aakaas + +import ( + "encoding/json" + "net/http" + "net/url" + "time" + + abapbuild "github.com/SAP/jenkins-library/pkg/abap/build" + "github.com/SAP/jenkins-library/pkg/abaputils" + "github.com/pkg/errors" +) + +// TargetVectorStatus : Status of TargetVector in AAKaaS +type TargetVectorStatus string + +const ( + // TargetVectorStatusGenerated : TargetVector is Generated (not published yet) + TargetVectorStatusGenerated TargetVectorStatus = "G" + // TargetVectorStatusTest : TargetVector is published for testing + TargetVectorStatusTest TargetVectorStatus = "T" + // TargetVectorStatusProductive : TargetVector is published for productive use + TargetVectorStatusProductive TargetVectorStatus = "P" + + TargetVectorPublishStatusRunning TargetVectorStatus = "R" + TargetVectorPublishStatusSuccess TargetVectorStatus = "S" + TargetVectorPublishStatusError TargetVectorStatus = "E" +) + +// internal usage : Json Structure for AAKaaS Odata Service +type jsonTargetVector struct { + Tv *TargetVector `json:"d"` +} + +// TargetVector : TargetVector desribes a deployble state of an ABAP product version +type TargetVector struct { + ID string `json:"Id"` + ProductName string `json:"ProductName"` + ProductVersion string `json:"ProductVersion"` + SpsLevel string `json:"SpsLevel"` + PatchLevel string `json:"PatchLevel"` + Status string `json:"Status"` + PublishStatus string `json:"PublishStatus"` + Content TargetVectorCVs `json:"Content"` +} + +// TargetVectorCV : deployable state of an software Component Version as part of an TargetVector +type TargetVectorCV struct { + ID string `json:"Id"` + ScName string `json:"ScName"` + ScVersion string `json:"ScVersion"` + DeliveryPackage string `json:"DeliveryPackage"` + SpLevel string `json:"SpLevel"` + PatchLevel string `json:"PatchLevel"` +} + +// TargetVectorCVs : deployable states of the software Component Versions of the product version +type TargetVectorCVs struct { + TargetVectorCVs []TargetVectorCV `json:"results"` +} + +// Init : Initialize TargetVector for Creation in AAKaaS +func (tv *TargetVector) InitNew(addonDescriptor *abaputils.AddonDescriptor) error { + if addonDescriptor.AddonProduct == "" || addonDescriptor.AddonVersion == "" || addonDescriptor.AddonSpsLevel == "" || addonDescriptor.AddonPatchLevel == "" { + return errors.New("Parameters missing. Please provide product name, version, spslevel and patchlevel") + } + tv.ProductName = addonDescriptor.AddonProduct + tv.ProductVersion = addonDescriptor.AddonVersion + tv.SpsLevel = addonDescriptor.AddonSpsLevel + tv.PatchLevel = addonDescriptor.AddonPatchLevel + + var tvCVs []TargetVectorCV + var tvCV TargetVectorCV + for i := range addonDescriptor.Repositories { + if addonDescriptor.Repositories[i].Name == "" || addonDescriptor.Repositories[i].Version == "" || addonDescriptor.Repositories[i].SpLevel == "" || + addonDescriptor.Repositories[i].PatchLevel == "" || addonDescriptor.Repositories[i].PackageName == "" { + return errors.New("Parameters missing. Please provide software component name, version, splevel, patchlevel and packagename") + } + tvCV.ScName = addonDescriptor.Repositories[i].Name + tvCV.ScVersion = addonDescriptor.Repositories[i].Version + tvCV.DeliveryPackage = addonDescriptor.Repositories[i].PackageName + tvCV.SpLevel = addonDescriptor.Repositories[i].SpLevel + tvCV.PatchLevel = addonDescriptor.Repositories[i].PatchLevel + tvCVs = append(tvCVs, tvCV) + } + tv.Content.TargetVectorCVs = tvCVs + return nil +} + +// InitExisting : Initialize an already in AAKaaS existing TargetVector +func (tv *TargetVector) InitExisting(ID string) { + tv.ID = ID +} + +// CreateTargetVector : Initial Creation of an TargetVector +func (tv *TargetVector) CreateTargetVector(conn *abapbuild.Connector) error { + conn.GetToken("/odata/aas_ocs_package") + tvJSON, err := json.Marshal(tv) + if err != nil { + return errors.Wrap(err, "Generating Request Data for Create Target Vector failed") + } + appendum := "/odata/aas_ocs_package/TargetVectorSet" + body, err := conn.Post(appendum, string(tvJSON)) + if err != nil { + return errors.Wrap(err, "Creating Target Vector in AAKaaS failed") + } + var jTV jsonTargetVector + if err := json.Unmarshal(body, &jTV); err != nil { + return errors.Wrap(err, "Unexpected AAKaaS response for create target vector: "+string(body)) + } + tv.ID = jTV.Tv.ID + tv.Status = jTV.Tv.Status + return nil +} + +func (tv *TargetVector) PublishTargetVector(conn *abapbuild.Connector, targetVectorScope TargetVectorStatus) error { + conn.GetToken("/odata/aas_ocs_package") + appendum := "/odata/aas_ocs_package/PublishTargetVector?Id='" + url.QueryEscape(tv.ID) + "'&Scope='" + url.QueryEscape(string(targetVectorScope)) + "'" + body, err := conn.Post(appendum, "") + if err != nil { + return errors.Wrap(err, "Publish Target Vector in AAKaaS failed") + } + + var jTV jsonTargetVector + if err := json.Unmarshal(body, &jTV); err != nil { + return errors.Wrap(err, "Unexpected AAKaaS response for publish target vector: "+string(body)) + } + + tv.Status = jTV.Tv.Status + tv.PublishStatus = jTV.Tv.PublishStatus + return nil +} + +// GetTargetVector : Read details of the TargetVector +func (tv *TargetVector) GetTargetVector(conn *abapbuild.Connector) error { + if tv.ID == "" { + return errors.New("Without ID no details of a targetVector can be obtained from AAKaaS") + } + appendum := "/odata/aas_ocs_package/TargetVectorSet('" + url.QueryEscape(tv.ID) + "')" + body, err := conn.Get(appendum) + if err != nil { + return errors.Wrap(err, "Getting Target Vector details from AAKaaS failed") + } + + var jTV jsonTargetVector + if err := json.Unmarshal(body, &jTV); err != nil { + return errors.Wrap(err, "Unexpected AAKaaS response for getting target vector details: "+string(body)) + } + + tv.Status = jTV.Tv.Status + tv.PublishStatus = jTV.Tv.PublishStatus + //other fields not needed atm + return nil +} + +// PollForStatus : Poll AAKaaS until final PublishStatus reached and check if desired Status was reached +func (tv *TargetVector) PollForStatus(conn *abapbuild.Connector, targetStatus TargetVectorStatus) error { + timeout := time.After(conn.MaxRuntime) + ticker := time.Tick(conn.PollingInterval) + for { + select { + case <-timeout: + return errors.New("Timed out (AAKaaS target Vector Status change)") + case <-ticker: + if err := tv.GetTargetVector(conn); err != nil { + return errors.Wrap(err, "Getting TargetVector status during polling resulted in an error") + } + switch TargetVectorStatus(tv.PublishStatus) { + case TargetVectorPublishStatusRunning: + continue + case TargetVectorPublishStatusSuccess: + if TargetVectorStatus(tv.Status) == targetStatus { + return nil + } else { + return errors.New("Publishing of Targetvector " + tv.ID + " resulted in state " + string(tv.Status) + "instead of expected state " + string(targetStatus)) + } + case TargetVectorPublishStatusError: + return errors.New("Publishing of Targetvector " + tv.ID + " failed in AAKaaS") + default: + return errors.New("Polling returned invalid TargetVectorPublishStatus: " + string(tv.PublishStatus)) + } + } + } +} + +/**************** + Mock Client Data +****************/ + +var AAKaaSHead = abapbuild.MockData{ + Method: `HEAD`, + Url: `/odata/aas_ocs_package`, + Body: ` + `, + StatusCode: 200, + Header: http.Header{"x-csrf-token": {"HRfJP0OhB9C9mHs2RRqUzw=="}}, +} + +var AAKaaSTVPublishTestPost = abapbuild.MockData{ + Method: `POST`, + Url: `/odata/aas_ocs_package/PublishTargetVector?Id='W7Q00207512600000353'&Scope='T'`, + Body: `{ + "d": { + "Id": "W7Q00207512600000353", + "Vendor": "0000029218", + "ProductName": "/DRNMSPC/PRD01", + "ProductVersion": "0001", + "SpsLevel": "0000", + "PatchLevel": "0000", + "Status": "G", + "PublishStatus": "R" + } + }`, + StatusCode: 200, +} + +var AAKaaSTVPublishProdPost = abapbuild.MockData{ + Method: `POST`, + Url: `/odata/aas_ocs_package/PublishTargetVector?Id='W7Q00207512600000353'&Scope='P'`, + Body: `{ + "d": { + "Id": "W7Q00207512600000353", + "Vendor": "0000029218", + "ProductName": "/DRNMSPC/PRD01", + "ProductVersion": "0001", + "SpsLevel": "0000", + "PatchLevel": "0000", + "Status": "G", + "PublishStatus": "R" + } + }`, + StatusCode: 200, +} + +var AAKaaSGetTVPublishRunning = abapbuild.MockData{ + Method: `GET`, + Url: `/odata/aas_ocs_package/TargetVectorSet('W7Q00207512600000353')`, + Body: `{ + "d": { + "Id": "W7Q00207512600000353", + "Vendor": "0000029218", + "ProductName": "/DRNMSPC/PRD01", + "ProductVersion": "0001", + "SpsLevel": "0000", + "PatchLevel": "0000", + "Status": "G", + "PublishStatus": "R" + } + }`, + StatusCode: 200, +} + +var AAKaaSGetTVPublishTestSuccess = abapbuild.MockData{ + Method: `GET`, + Url: `/odata/aas_ocs_package/TargetVectorSet('W7Q00207512600000353')`, + Body: `{ + "d": { + "Id": "W7Q00207512600000353", + "Vendor": "0000029218", + "ProductName": "/DRNMSPC/PRD01", + "ProductVersion": "0001", + "SpsLevel": "0000", + "PatchLevel": "0000", + "Status": "T", + "PublishStatus": "S" + } + }`, + StatusCode: 200, +} + +var AAKaaSGetTVPublishProdSuccess = abapbuild.MockData{ + Method: `GET`, + Url: `/odata/aas_ocs_package/TargetVectorSet('W7Q00207512600000353')`, + Body: `{ + "d": { + "Id": "W7Q00207512600000353", + "Vendor": "0000029218", + "ProductName": "/DRNMSPC/PRD01", + "ProductVersion": "0001", + "SpsLevel": "0000", + "PatchLevel": "0000", + "Status": "P", + "PublishStatus": "S" + } + }`, + StatusCode: 200, +} + +var AAKaaSTVCreatePost = abapbuild.MockData{ + Method: `POST`, + Url: `/odata/aas_ocs_package/TargetVectorSet`, + Body: `{ + "d": { + "Id": "W7Q00207512600000262", + "Vendor": "0000203069", + "ProductName": "/DRNMSPC/PRD01", + "ProductVersion": "0001", + "SpsLevel": "0000", + "PatchLevel": "0000", + "Status": "G", + "Content": { + "results": [ + { + "Id": "W7Q00207512600000262", + "ScName": "/DRNMSPC/COMP01", + "ScVersion": "0001", + "DeliveryPackage": "SAPK-001AAINDRNMSPC", + "SpLevel": "0000", + "PatchLevel": "0000" + } + ] + } + } + }`, + StatusCode: 200, +} + +var templateMockData = abapbuild.MockData{ + Method: `GET`, + Url: ``, + Body: ``, + StatusCode: 200, +} diff --git a/pkg/abap/aakaas/targetVector_test.go b/pkg/abap/aakaas/targetVector_test.go new file mode 100644 index 000000000..07f81806e --- /dev/null +++ b/pkg/abap/aakaas/targetVector_test.go @@ -0,0 +1,180 @@ +package aakaas + +import ( + "testing" + "time" + + abapbuild "github.com/SAP/jenkins-library/pkg/abap/build" + "github.com/SAP/jenkins-library/pkg/abaputils" + "github.com/stretchr/testify/assert" +) + +func TestTargetVectorInitExisting(t *testing.T) { + t.Run("ID is set", func(t *testing.T) { + //arrange + id := "dummyID" + targetVector := new(TargetVector) + //act + targetVector.InitExisting(id) + //assert + assert.Equal(t, id, targetVector.ID) + }) +} + +func TestTargetVectorInitNew(t *testing.T) { + t.Run("Ensure values not initial", func(t *testing.T) { + //arrange + addonDescriptor := abaputils.AddonDescriptor{ + AddonProduct: "dummy", + AddonVersion: "dummy", + AddonSpsLevel: "dummy", + AddonPatchLevel: "dummy", + TargetVectorID: "dummy", + Repositories: []abaputils.Repository{ + { + Name: "dummy", + Version: "dummy", + SpLevel: "dummy", + PatchLevel: "dummy", + PackageName: "dummy", + }, + }, + } + targetVector := new(TargetVector) + //act + err := targetVector.InitNew(&addonDescriptor) + //assert + assert.NoError(t, err) + assert.Equal(t, "dummy", targetVector.ProductVersion) + }) + t.Run("Fail if values initial", func(t *testing.T) { + //arrange + addonDescriptor := abaputils.AddonDescriptor{} + targetVector := new(TargetVector) + //act + err := targetVector.InitNew(&addonDescriptor) + //assert + assert.Error(t, err) + }) +} + +func TestTargetVectorGet(t *testing.T) { + //arrange global + targetVector := new(TargetVector) + conn := new(abapbuild.Connector) + + t.Run("Ensure error if ID is initial", func(t *testing.T) { + //arrange + targetVector.ID = "" + //act + err := targetVector.GetTargetVector(conn) + //assert + assert.Error(t, err) + }) + t.Run("Normal Get Test Success", func(t *testing.T) { + //arrange + targetVector.ID = "W7Q00207512600000353" + mc := abapbuild.NewMockClient() + mc.AddData(AAKaaSGetTVPublishTestSuccess) + conn.Client = &mc + //act + err := targetVector.GetTargetVector(conn) + //assert + assert.NoError(t, err) + assert.Equal(t, TargetVectorPublishStatusSuccess, TargetVectorStatus(targetVector.PublishStatus)) + assert.Equal(t, TargetVectorStatusTest, TargetVectorStatus(targetVector.Status)) + }) + t.Run("Error Get", func(t *testing.T) { + //arrange + targetVector.ID = "W7Q00207512600000353" + mc := abapbuild.NewMockClient() + conn.Client = &mc + //act + err := targetVector.GetTargetVector(conn) + //assert + assert.Error(t, err) + }) +} + +func TestTargetVectorPollForStatus(t *testing.T) { + //arrange global + targetVector := new(TargetVector) + conn := new(abapbuild.Connector) + conn.MaxRuntime = time.Duration(1 * time.Second) + conn.PollingInterval = time.Duration(1 * time.Microsecond) + + t.Run("Normal Poll", func(t *testing.T) { + //arrange + targetVector.ID = "W7Q00207512600000353" + mc := abapbuild.NewMockClient() + mc.AddData(AAKaaSGetTVPublishRunning) + mc.AddData(AAKaaSGetTVPublishTestSuccess) + conn.Client = &mc + //act + err := targetVector.PollForStatus(conn, TargetVectorStatusTest) + //assert + assert.NoError(t, err) + }) +} + +func TestTargetVectorCreate(t *testing.T) { + //arrange global + targetVector := new(TargetVector) + conn := new(abapbuild.Connector) + + addonDescriptor := abaputils.AddonDescriptor{ + AddonProduct: "dummy", + AddonVersion: "dummy", + AddonSpsLevel: "dummy", + AddonPatchLevel: "dummy", + TargetVectorID: "dummy", + Repositories: []abaputils.Repository{ + { + Name: "dummy", + Version: "dummy", + SpLevel: "dummy", + PatchLevel: "dummy", + PackageName: "dummy", + }, + }, + } + + t.Run("Create Success", func(t *testing.T) { + //arrange + mc := abapbuild.NewMockClient() + mc.AddData(AAKaaSHead) + mc.AddData(AAKaaSTVCreatePost) + errInitConn := conn.InitAAKaaS("", "dummyUser", "dummyPassword", &mc) + assert.NoError(t, errInitConn) + + errInitTV := targetVector.InitNew(&addonDescriptor) + assert.NoError(t, errInitTV) + //act + err := targetVector.CreateTargetVector(conn) + //assert + assert.NoError(t, err) + assert.Equal(t, "W7Q00207512600000262", targetVector.ID) + }) +} + +func TestTargetVectorPublish(t *testing.T) { + //arrange global + targetVector := new(TargetVector) + conn := new(abapbuild.Connector) + + t.Run("Publish Test", func(t *testing.T) { + //arrange + targetVector.ID = "W7Q00207512600000353" + mc := abapbuild.NewMockClient() + mc.AddData(AAKaaSHead) + mc.AddData(AAKaaSTVPublishTestPost) + errInitConn := conn.InitAAKaaS("", "dummyUser", "dummyPassword", &mc) + assert.NoError(t, errInitConn) + + //act + err := targetVector.PublishTargetVector(conn, TargetVectorStatusTest) + //assert + assert.NoError(t, err) + assert.Equal(t, string(TargetVectorPublishStatusRunning), targetVector.PublishStatus) + }) +} diff --git a/pkg/abap/build/connector.go b/pkg/abap/build/connector.go index 506089f70..ecb1f7ec7 100644 --- a/pkg/abap/build/connector.go +++ b/pkg/abap/build/connector.go @@ -16,10 +16,12 @@ import ( // Connector : Connector Utility Wrapping http client type Connector struct { - Client piperhttp.Sender - DownloadClient piperhttp.Downloader - Header map[string][]string - Baseurl string + Client piperhttp.Sender + DownloadClient piperhttp.Downloader + Header map[string][]string + Baseurl string + MaxRuntime time.Duration // just as handover parameter for polling functions + PollingInterval time.Duration // just as handover parameter for polling functions } // ConnectorConfiguration : Handover Structure for Connector Creation diff --git a/pkg/abap/build/mockClient.go b/pkg/abap/build/mockClient.go index 55601d203..b2110995b 100644 --- a/pkg/abap/build/mockClient.go +++ b/pkg/abap/build/mockClient.go @@ -12,16 +12,17 @@ import ( // MockClient : use NewMockClient for construction type MockClient struct { - //Key = HTTP-Method + url + //Key = HTTP-Method + Url Data map[string][]http.Response } -type mockData struct { - method string - url string - body string - statusCode int - header http.Header +// MockData: data for the mockClient +type MockData struct { + Method string + Url string + Body string + StatusCode int + Header http.Header } // NewMockClient : Constructs a new Mock Client implementing piperhttp.Sender @@ -32,52 +33,53 @@ func NewMockClient() MockClient { } // AddResponse : adds a response object to the mock lib -func (mc *MockClient) AddResponse(method, url string, response http.Response) { - responseList, ok := mc.Data[method+url] +func (mc *MockClient) AddResponse(Method, Url string, response http.Response) { + responseList, ok := mc.Data[Method+Url] if !ok { responseList = make([]http.Response, 0) } responseList = append(responseList, response) - mc.Data[method+url] = responseList + mc.Data[Method+Url] = responseList } -// Add : adds a response with the given body and statusOK to the mock lib -func (mc *MockClient) Add(method, url, body string) { - mc.AddResponse(method, url, http.Response{ +// Add : adds a response with the given Body and statusOK to the mock lib +func (mc *MockClient) Add(Method, Url, Body string) { + mc.AddResponse(Method, Url, http.Response{ StatusCode: http.StatusOK, Header: http.Header{}, - Body: ioutil.NopCloser(bytes.NewReader([]byte(body))), + Body: ioutil.NopCloser(bytes.NewReader([]byte(Body))), }) } // AddBody : adds a response with the given data to the mock lib -func (mc *MockClient) AddBody(method, url, body string, statusCode int, header http.Header) { - mc.AddResponse(method, url, http.Response{ - StatusCode: statusCode, +func (mc *MockClient) AddBody(Method, Url, Body string, StatusCode int, header http.Header) { + mc.AddResponse(Method, Url, http.Response{ + StatusCode: StatusCode, Header: header, - Body: ioutil.NopCloser(bytes.NewReader([]byte(body))), + Body: ioutil.NopCloser(bytes.NewReader([]byte(Body))), }) } -func (mc *MockClient) addData(data mockData) { - mc.AddResponse(data.method, data.url, http.Response{ - StatusCode: data.statusCode, - Header: data.header, - Body: ioutil.NopCloser(bytes.NewReader([]byte(data.body))), +// AddData : add the mock Data as response to the mock lib +func (mc *MockClient) AddData(data MockData) { + mc.AddResponse(data.Method, data.Url, http.Response{ + StatusCode: data.StatusCode, + Header: data.Header, + Body: ioutil.NopCloser(bytes.NewReader([]byte(data.Body))), }) } -func (mc *MockClient) getResponse(method, url string) (http.Response, bool) { - responseList, ok := mc.Data[method+url] +func (mc *MockClient) getResponse(Method, Url string) (http.Response, bool) { + responseList, ok := mc.Data[Method+Url] if !ok { return http.Response{}, false } response := responseList[0] if len(responseList) > 1 { - mc.Data[method+url] = responseList[1:] + mc.Data[Method+Url] = responseList[1:] } else { - delete(mc.Data, method+url) + delete(mc.Data, Method+Url) } return response, true @@ -87,17 +89,17 @@ func (mc *MockClient) getResponse(method, url string) (http.Response, bool) { func (mc *MockClient) SetOptions(opts piperhttp.ClientOptions) {} // SendRequest sets a HTTP response for a client mock -func (mc *MockClient) SendRequest(method, url string, bdy io.Reader, hdr http.Header, cookies []*http.Cookie) (*http.Response, error) { - response, ok := mc.getResponse(method, url) +func (mc *MockClient) SendRequest(Method, Url string, bdy io.Reader, hdr http.Header, cookies []*http.Cookie) (*http.Response, error) { + response, ok := mc.getResponse(Method, Url) if !ok { - //return nil, errors.New("No Mock data for given Method+URL") - return nil, fmt.Errorf("No Mock data for %s", method+url) + //return nil, errors.New("No Mock data for given Method+Url") + return nil, fmt.Errorf("No Mock data for %s", Method+Url) } return &response, nil } // DownloadFile : Empty file download -func (mc *MockClient) DownloadFile(url, filename string, header http.Header, cookies []*http.Cookie) error { +func (mc *MockClient) DownloadFile(Url, filename string, header http.Header, cookies []*http.Cookie) error { return nil } @@ -109,55 +111,55 @@ func (mc *MockClient) DownloadFile(url, filename string, header http.Header, coo func GetBuildMockClient() MockClient { mc := NewMockClient() - mc.addData(buildHead) - mc.addData(buildPost) - mc.addData(buildGet1) - mc.addData(buildGet2) - mc.addData(buildGetTasks) - mc.addData(buildGetTask0Logs) - mc.addData(buildGetTask1Logs) - mc.addData(buildGetTask2Logs) - mc.addData(buildGetTask3Logs) - mc.addData(buildGetTask4Logs) - mc.addData(buildGetTask5Logs) - mc.addData(buildGetTask6Logs) - mc.addData(buildGetTask7Logs) - mc.addData(buildGetTask8Logs) - mc.addData(buildGetTask9Logs) - mc.addData(buildGetTask10Logs) - mc.addData(buildGetTask11Logs) - mc.addData(buildGetTask12Logs) - mc.addData(buildGetTask0Result) - mc.addData(buildGetTask1Result) - mc.addData(buildGetTask2Result) - mc.addData(buildGetTask3Result) - mc.addData(buildGetTask4Result) - mc.addData(buildGetTask5Result) - mc.addData(buildGetTask6Result) - mc.addData(buildGetTask7Result) - mc.addData(buildGetTask8Result) - mc.addData(buildGetTask9Result) - mc.addData(buildGetTask10Result) - mc.addData(buildGetTask11Result) - mc.addData(buildGetTask12Result) - mc.addData(buildGetTask11ResultMedia) + mc.AddData(buildHead) + mc.AddData(buildPost) + mc.AddData(buildGet1) + mc.AddData(buildGet2) + mc.AddData(buildGetTasks) + mc.AddData(buildGetTask0Logs) + mc.AddData(buildGetTask1Logs) + mc.AddData(buildGetTask2Logs) + mc.AddData(buildGetTask3Logs) + mc.AddData(buildGetTask4Logs) + mc.AddData(buildGetTask5Logs) + mc.AddData(buildGetTask6Logs) + mc.AddData(buildGetTask7Logs) + mc.AddData(buildGetTask8Logs) + mc.AddData(buildGetTask9Logs) + mc.AddData(buildGetTask10Logs) + mc.AddData(buildGetTask11Logs) + mc.AddData(buildGetTask12Logs) + mc.AddData(buildGetTask0Result) + mc.AddData(buildGetTask1Result) + mc.AddData(buildGetTask2Result) + mc.AddData(buildGetTask3Result) + mc.AddData(buildGetTask4Result) + mc.AddData(buildGetTask5Result) + mc.AddData(buildGetTask6Result) + mc.AddData(buildGetTask7Result) + mc.AddData(buildGetTask8Result) + mc.AddData(buildGetTask9Result) + mc.AddData(buildGetTask10Result) + mc.AddData(buildGetTask11Result) + mc.AddData(buildGetTask12Result) + mc.AddData(buildGetTask11ResultMedia) return mc } -var buildHead = mockData{ - method: `HEAD`, - url: `/sap/opu/odata/BUILD/CORE_SRV`, - body: ` - `, - statusCode: 200, - header: http.Header{"x-csrf-token": {"HRfJP0OhB9C9mHs2RRqUzw=="}}, +var buildHead = MockData{ + Method: `HEAD`, + Url: `/sap/opu/odata/BUILD/CORE_SRV`, + Body: ` + `, + StatusCode: 200, + Header: http.Header{"x-csrf-token": {"HRfJP0OhB9C9mHs2RRqUzw=="}}, } -var buildPost = mockData{ - method: `POST`, - url: `/sap/opu/odata/BUILD/CORE_SRV/builds`, - body: `{ +var buildPost = MockData{ + Method: `POST`, + Url: `/sap/opu/odata/BUILD/CORE_SRV/builds`, + Body: `{ "d" : { "__metadata" : { "id" : "https://7aa9d1a3-a876-464e-b59a-f26104452461.abap.stagingaws.hanavlab.ondemand.com/sap/opu/odata/BUILD/CORE_SRV/builds('AKO22FYOFYPOXHOBVKXUTX3A3Q')", @@ -183,13 +185,13 @@ var buildPost = mockData{ } } }`, - statusCode: 201, + StatusCode: 201, } -var buildGet1 = mockData{ - method: `GET`, - url: `/sap/opu/odata/BUILD/CORE_SRV/builds('AKO22FYOFYPOXHOBVKXUTX3A3Q')`, - body: `{ +var buildGet1 = MockData{ + Method: `GET`, + Url: `/sap/opu/odata/BUILD/CORE_SRV/builds('AKO22FYOFYPOXHOBVKXUTX3A3Q')`, + Body: `{ "d" : { "__metadata" : { "id" : "https://7aa9d1a3-a876-464e-b59a-f26104452461.abap.stagingaws.hanavlab.ondemand.com/sap/opu/odata/BUILD/CORE_SRV/builds('AKO22FYOFYPOXHOBVKXUTX3A3Q')", @@ -216,13 +218,13 @@ var buildGet1 = mockData{ } } }`, - statusCode: 200, + StatusCode: 200, } -var buildGet2 = mockData{ - method: `GET`, - url: `/sap/opu/odata/BUILD/CORE_SRV/builds('AKO22FYOFYPOXHOBVKXUTX3A3Q')`, - body: `{ +var buildGet2 = MockData{ + Method: `GET`, + Url: `/sap/opu/odata/BUILD/CORE_SRV/builds('AKO22FYOFYPOXHOBVKXUTX3A3Q')`, + Body: `{ "d" : { "__metadata" : { "id" : "https://7aa9d1a3-a876-464e-b59a-f26104452461.abap.stagingaws.hanavlab.ondemand.com/sap/opu/odata/BUILD/CORE_SRV/builds('AKO22FYOFYPOXHOBVKXUTX3A3Q')", @@ -249,13 +251,13 @@ var buildGet2 = mockData{ } } }`, - statusCode: 200, + StatusCode: 200, } -var buildGetTasks = mockData{ - method: `GET`, - url: `/sap/opu/odata/BUILD/CORE_SRV/builds('AKO22FYOFYPOXHOBVKXUTX3A3Q')/tasks`, - body: `{ +var buildGetTasks = MockData{ + Method: `GET`, + Url: `/sap/opu/odata/BUILD/CORE_SRV/builds('AKO22FYOFYPOXHOBVKXUTX3A3Q')/tasks`, + Body: `{ "d" : { "results" : [ { @@ -573,13 +575,13 @@ var buildGetTasks = mockData{ ] } }`, - statusCode: 200, + StatusCode: 200, } -var buildGetTask0Logs = mockData{ - method: `GET`, - url: `/sap/opu/odata/BUILD/CORE_SRV/tasks(build_id='AKO22FYOFYPOXHOBVKXUTX3A3Q',task_id=0)/logs`, - body: `{ +var buildGetTask0Logs = MockData{ + Method: `GET`, + Url: `/sap/opu/odata/BUILD/CORE_SRV/tasks(build_id='AKO22FYOFYPOXHOBVKXUTX3A3Q',task_id=0)/logs`, + Body: `{ "d" : { "results" : [ { @@ -907,13 +909,13 @@ var buildGetTask0Logs = mockData{ ] } }`, - statusCode: 200, + StatusCode: 200, } -var buildGetTask1Logs = mockData{ - method: `GET`, - url: `/sap/opu/odata/BUILD/CORE_SRV/tasks(build_id='AKO22FYOFYPOXHOBVKXUTX3A3Q',task_id=1)/logs`, - body: `{ +var buildGetTask1Logs = MockData{ + Method: `GET`, + Url: `/sap/opu/odata/BUILD/CORE_SRV/tasks(build_id='AKO22FYOFYPOXHOBVKXUTX3A3Q',task_id=1)/logs`, + Body: `{ "d" : { "results" : [ { @@ -933,25 +935,25 @@ var buildGetTask1Logs = mockData{ ] } }`, - statusCode: 200, + StatusCode: 200, } -var buildGetTask2Logs = mockData{ - method: `GET`, - url: `/sap/opu/odata/BUILD/CORE_SRV/tasks(build_id='AKO22FYOFYPOXHOBVKXUTX3A3Q',task_id=2)/logs`, - body: `{ +var buildGetTask2Logs = MockData{ + Method: `GET`, + Url: `/sap/opu/odata/BUILD/CORE_SRV/tasks(build_id='AKO22FYOFYPOXHOBVKXUTX3A3Q',task_id=2)/logs`, + Body: `{ "d" : { "results" : [ ] } }`, - statusCode: 200, + StatusCode: 200, } -var buildGetTask3Logs = mockData{ - method: `GET`, - url: `/sap/opu/odata/BUILD/CORE_SRV/tasks(build_id='AKO22FYOFYPOXHOBVKXUTX3A3Q',task_id=3)/logs`, - body: `{ +var buildGetTask3Logs = MockData{ + Method: `GET`, + Url: `/sap/opu/odata/BUILD/CORE_SRV/tasks(build_id='AKO22FYOFYPOXHOBVKXUTX3A3Q',task_id=3)/logs`, + Body: `{ "d" : { "results" : [ { @@ -971,13 +973,13 @@ var buildGetTask3Logs = mockData{ ] } }`, - statusCode: 200, + StatusCode: 200, } -var buildGetTask4Logs = mockData{ - method: `GET`, - url: `/sap/opu/odata/BUILD/CORE_SRV/tasks(build_id='AKO22FYOFYPOXHOBVKXUTX3A3Q',task_id=4)/logs`, - body: `{ +var buildGetTask4Logs = MockData{ + Method: `GET`, + Url: `/sap/opu/odata/BUILD/CORE_SRV/tasks(build_id='AKO22FYOFYPOXHOBVKXUTX3A3Q',task_id=4)/logs`, + Body: `{ "d" : { "results" : [ { @@ -1053,13 +1055,13 @@ var buildGetTask4Logs = mockData{ ] } }`, - statusCode: 200, + StatusCode: 200, } -var buildGetTask5Logs = mockData{ - method: `GET`, - url: `/sap/opu/odata/BUILD/CORE_SRV/tasks(build_id='AKO22FYOFYPOXHOBVKXUTX3A3Q',task_id=5)/logs`, - body: `{ +var buildGetTask5Logs = MockData{ + Method: `GET`, + Url: `/sap/opu/odata/BUILD/CORE_SRV/tasks(build_id='AKO22FYOFYPOXHOBVKXUTX3A3Q',task_id=5)/logs`, + Body: `{ "d" : { "results" : [ { @@ -1093,13 +1095,13 @@ var buildGetTask5Logs = mockData{ ] } }`, - statusCode: 200, + StatusCode: 200, } -var buildGetTask6Logs = mockData{ - method: `GET`, - url: `/sap/opu/odata/BUILD/CORE_SRV/tasks(build_id='AKO22FYOFYPOXHOBVKXUTX3A3Q',task_id=6)/logs`, - body: `{ +var buildGetTask6Logs = MockData{ + Method: `GET`, + Url: `/sap/opu/odata/BUILD/CORE_SRV/tasks(build_id='AKO22FYOFYPOXHOBVKXUTX3A3Q',task_id=6)/logs`, + Body: `{ "d" : { "results" : [ { @@ -1133,13 +1135,13 @@ var buildGetTask6Logs = mockData{ ] } }`, - statusCode: 200, + StatusCode: 200, } -var buildGetTask7Logs = mockData{ - method: `GET`, - url: `/sap/opu/odata/BUILD/CORE_SRV/tasks(build_id='AKO22FYOFYPOXHOBVKXUTX3A3Q',task_id=7)/logs`, - body: `{ +var buildGetTask7Logs = MockData{ + Method: `GET`, + Url: `/sap/opu/odata/BUILD/CORE_SRV/tasks(build_id='AKO22FYOFYPOXHOBVKXUTX3A3Q',task_id=7)/logs`, + Body: `{ "d" : { "results" : [ { @@ -1159,13 +1161,13 @@ var buildGetTask7Logs = mockData{ ] } }`, - statusCode: 200, + StatusCode: 200, } -var buildGetTask8Logs = mockData{ - method: `GET`, - url: `/sap/opu/odata/BUILD/CORE_SRV/tasks(build_id='AKO22FYOFYPOXHOBVKXUTX3A3Q',task_id=8)/logs`, - body: `{ +var buildGetTask8Logs = MockData{ + Method: `GET`, + Url: `/sap/opu/odata/BUILD/CORE_SRV/tasks(build_id='AKO22FYOFYPOXHOBVKXUTX3A3Q',task_id=8)/logs`, + Body: `{ "d" : { "results" : [ { @@ -1185,13 +1187,13 @@ var buildGetTask8Logs = mockData{ ] } }`, - statusCode: 200, + StatusCode: 200, } -var buildGetTask9Logs = mockData{ - method: `GET`, - url: `/sap/opu/odata/BUILD/CORE_SRV/tasks(build_id='AKO22FYOFYPOXHOBVKXUTX3A3Q',task_id=9)/logs`, - body: `{ +var buildGetTask9Logs = MockData{ + Method: `GET`, + Url: `/sap/opu/odata/BUILD/CORE_SRV/tasks(build_id='AKO22FYOFYPOXHOBVKXUTX3A3Q',task_id=9)/logs`, + Body: `{ "d" : { "results" : [ { @@ -1211,13 +1213,13 @@ var buildGetTask9Logs = mockData{ ] } }`, - statusCode: 200, + StatusCode: 200, } -var buildGetTask10Logs = mockData{ - method: `GET`, - url: `/sap/opu/odata/BUILD/CORE_SRV/tasks(build_id='AKO22FYOFYPOXHOBVKXUTX3A3Q',task_id=10)/logs`, - body: `{ +var buildGetTask10Logs = MockData{ + Method: `GET`, + Url: `/sap/opu/odata/BUILD/CORE_SRV/tasks(build_id='AKO22FYOFYPOXHOBVKXUTX3A3Q',task_id=10)/logs`, + Body: `{ "d" : { "results" : [ { @@ -1251,13 +1253,13 @@ var buildGetTask10Logs = mockData{ ] } }`, - statusCode: 200, + StatusCode: 200, } -var buildGetTask11Logs = mockData{ - method: `GET`, - url: `/sap/opu/odata/BUILD/CORE_SRV/tasks(build_id='AKO22FYOFYPOXHOBVKXUTX3A3Q',task_id=11)/logs`, - body: `{ +var buildGetTask11Logs = MockData{ + Method: `GET`, + Url: `/sap/opu/odata/BUILD/CORE_SRV/tasks(build_id='AKO22FYOFYPOXHOBVKXUTX3A3Q',task_id=11)/logs`, + Body: `{ "d" : { "results" : [ { @@ -1277,13 +1279,13 @@ var buildGetTask11Logs = mockData{ ] } }`, - statusCode: 200, + StatusCode: 200, } -var buildGetTask12Logs = mockData{ - method: `GET`, - url: `/sap/opu/odata/BUILD/CORE_SRV/tasks(build_id='AKO22FYOFYPOXHOBVKXUTX3A3Q',task_id=12)/logs`, - body: `{ +var buildGetTask12Logs = MockData{ + Method: `GET`, + Url: `/sap/opu/odata/BUILD/CORE_SRV/tasks(build_id='AKO22FYOFYPOXHOBVKXUTX3A3Q',task_id=12)/logs`, + Body: `{ "d" : { "results" : [ { @@ -1303,134 +1305,134 @@ var buildGetTask12Logs = mockData{ ] } }`, - statusCode: 200, + StatusCode: 200, } -var buildGetTask0Result = mockData{ - method: `GET`, - url: `/sap/opu/odata/BUILD/CORE_SRV/tasks(build_id='AKO22FYOFYPOXHOBVKXUTX3A3Q',task_id=0)/results`, - body: `{ +var buildGetTask0Result = MockData{ + Method: `GET`, + Url: `/sap/opu/odata/BUILD/CORE_SRV/tasks(build_id='AKO22FYOFYPOXHOBVKXUTX3A3Q',task_id=0)/results`, + Body: `{ "d" : { "results" : [ ] } }`, - statusCode: 200, + StatusCode: 200, } -var buildGetTask1Result = mockData{ - method: `GET`, - url: `/sap/opu/odata/BUILD/CORE_SRV/tasks(build_id='AKO22FYOFYPOXHOBVKXUTX3A3Q',task_id=1)/results`, - body: `{ +var buildGetTask1Result = MockData{ + Method: `GET`, + Url: `/sap/opu/odata/BUILD/CORE_SRV/tasks(build_id='AKO22FYOFYPOXHOBVKXUTX3A3Q',task_id=1)/results`, + Body: `{ "d" : { "results" : [ ] } }`, - statusCode: 200, + StatusCode: 200, } -var buildGetTask2Result = mockData{ - method: `GET`, - url: `/sap/opu/odata/BUILD/CORE_SRV/tasks(build_id='AKO22FYOFYPOXHOBVKXUTX3A3Q',task_id=2)/results`, - body: `{ +var buildGetTask2Result = MockData{ + Method: `GET`, + Url: `/sap/opu/odata/BUILD/CORE_SRV/tasks(build_id='AKO22FYOFYPOXHOBVKXUTX3A3Q',task_id=2)/results`, + Body: `{ "d" : { "results" : [ ] } }`, - statusCode: 200, + StatusCode: 200, } -var buildGetTask3Result = mockData{ - method: `GET`, - url: `/sap/opu/odata/BUILD/CORE_SRV/tasks(build_id='AKO22FYOFYPOXHOBVKXUTX3A3Q',task_id=3)/results`, - body: `{ +var buildGetTask3Result = MockData{ + Method: `GET`, + Url: `/sap/opu/odata/BUILD/CORE_SRV/tasks(build_id='AKO22FYOFYPOXHOBVKXUTX3A3Q',task_id=3)/results`, + Body: `{ "d" : { "results" : [ ] } }`, - statusCode: 200, + StatusCode: 200, } -var buildGetTask4Result = mockData{ - method: `GET`, - url: `/sap/opu/odata/BUILD/CORE_SRV/tasks(build_id='AKO22FYOFYPOXHOBVKXUTX3A3Q',task_id=4)/results`, - body: `{ +var buildGetTask4Result = MockData{ + Method: `GET`, + Url: `/sap/opu/odata/BUILD/CORE_SRV/tasks(build_id='AKO22FYOFYPOXHOBVKXUTX3A3Q',task_id=4)/results`, + Body: `{ "d" : { "results" : [ ] } }`, - statusCode: 200, + StatusCode: 200, } -var buildGetTask5Result = mockData{ - method: `GET`, - url: `/sap/opu/odata/BUILD/CORE_SRV/tasks(build_id='AKO22FYOFYPOXHOBVKXUTX3A3Q',task_id=5)/results`, - body: `{ +var buildGetTask5Result = MockData{ + Method: `GET`, + Url: `/sap/opu/odata/BUILD/CORE_SRV/tasks(build_id='AKO22FYOFYPOXHOBVKXUTX3A3Q',task_id=5)/results`, + Body: `{ "d" : { "results" : [ ] } }`, - statusCode: 200, + StatusCode: 200, } -var buildGetTask6Result = mockData{ - method: `GET`, - url: `/sap/opu/odata/BUILD/CORE_SRV/tasks(build_id='AKO22FYOFYPOXHOBVKXUTX3A3Q',task_id=6)/results`, - body: `{ +var buildGetTask6Result = MockData{ + Method: `GET`, + Url: `/sap/opu/odata/BUILD/CORE_SRV/tasks(build_id='AKO22FYOFYPOXHOBVKXUTX3A3Q',task_id=6)/results`, + Body: `{ "d" : { "results" : [ ] } }`, - statusCode: 200, + StatusCode: 200, } -var buildGetTask7Result = mockData{ - method: `GET`, - url: `/sap/opu/odata/BUILD/CORE_SRV/tasks(build_id='AKO22FYOFYPOXHOBVKXUTX3A3Q',task_id=7)/results`, - body: `{ +var buildGetTask7Result = MockData{ + Method: `GET`, + Url: `/sap/opu/odata/BUILD/CORE_SRV/tasks(build_id='AKO22FYOFYPOXHOBVKXUTX3A3Q',task_id=7)/results`, + Body: `{ "d" : { "results" : [ ] } }`, - statusCode: 200, + StatusCode: 200, } -var buildGetTask8Result = mockData{ - method: `GET`, - url: `/sap/opu/odata/BUILD/CORE_SRV/tasks(build_id='AKO22FYOFYPOXHOBVKXUTX3A3Q',task_id=8)/results`, - body: `{ +var buildGetTask8Result = MockData{ + Method: `GET`, + Url: `/sap/opu/odata/BUILD/CORE_SRV/tasks(build_id='AKO22FYOFYPOXHOBVKXUTX3A3Q',task_id=8)/results`, + Body: `{ "d" : { "results" : [ ] } }`, - statusCode: 200, + StatusCode: 200, } -var buildGetTask9Result = mockData{ - method: `GET`, - url: `/sap/opu/odata/BUILD/CORE_SRV/tasks(build_id='AKO22FYOFYPOXHOBVKXUTX3A3Q',task_id=9)/results`, - body: `{ +var buildGetTask9Result = MockData{ + Method: `GET`, + Url: `/sap/opu/odata/BUILD/CORE_SRV/tasks(build_id='AKO22FYOFYPOXHOBVKXUTX3A3Q',task_id=9)/results`, + Body: `{ "d" : { "results" : [ ] } }`, - statusCode: 200, + StatusCode: 200, } -var buildGetTask10Result = mockData{ - method: `GET`, - url: `/sap/opu/odata/BUILD/CORE_SRV/tasks(build_id='AKO22FYOFYPOXHOBVKXUTX3A3Q',task_id=10)/results`, - body: `{ +var buildGetTask10Result = MockData{ + Method: `GET`, + Url: `/sap/opu/odata/BUILD/CORE_SRV/tasks(build_id='AKO22FYOFYPOXHOBVKXUTX3A3Q',task_id=10)/results`, + Body: `{ "d" : { "results" : [ ] } }`, - statusCode: 200, + StatusCode: 200, } -var buildGetTask11Result = mockData{ - method: `GET`, - url: `/sap/opu/odata/BUILD/CORE_SRV/tasks(build_id='AKO22FYOFYPOXHOBVKXUTX3A3Q',task_id=11)/results`, - body: `{ +var buildGetTask11Result = MockData{ + Method: `GET`, + Url: `/sap/opu/odata/BUILD/CORE_SRV/tasks(build_id='AKO22FYOFYPOXHOBVKXUTX3A3Q',task_id=11)/results`, + Body: `{ "d" : { "results" : [ { @@ -1450,12 +1452,12 @@ var buildGetTask11Result = mockData{ ] } }`, - statusCode: 200, + StatusCode: 200, } -var buildGetTask12Result = mockData{ - method: `GET`, - url: `/sap/opu/odata/BUILD/CORE_SRV/tasks(build_id='AKO22FYOFYPOXHOBVKXUTX3A3Q',task_id=12)/results`, - body: `{ +var buildGetTask12Result = MockData{ + Method: `GET`, + Url: `/sap/opu/odata/BUILD/CORE_SRV/tasks(build_id='AKO22FYOFYPOXHOBVKXUTX3A3Q',task_id=12)/results`, + Body: `{ "d" : { "results" : [ { @@ -1475,13 +1477,13 @@ var buildGetTask12Result = mockData{ ] } }`, - statusCode: 200, + StatusCode: 200, } -var buildGetTask12ResultOrig = mockData{ - method: `GET`, - url: `/sap/opu/odata/BUILD/CORE_SRV/tasks(build_id='AKO22FYOFYPOXHOBVKXUTX3A3Q',task_id=12)/results`, - body: `{ +var buildGetTask12ResultOrig = MockData{ + Method: `GET`, + Url: `/sap/opu/odata/BUILD/CORE_SRV/tasks(build_id='AKO22FYOFYPOXHOBVKXUTX3A3Q',task_id=12)/results`, + Body: `{ "d" : { "results" : [ { @@ -1501,19 +1503,19 @@ var buildGetTask12ResultOrig = mockData{ ] } }`, - statusCode: 200, + StatusCode: 200, } -var buildGetTask11ResultMedia = mockData{ - method: `GET`, - url: `/sap/opu/odata/BUILD/CORE_SRV/results(build_id='AKO22FYOFYPOXHOBVKXUTX3A3Q',task_id=11,name='SAR_XML')/$value`, - body: ``, - statusCode: 200, +var buildGetTask11ResultMedia = MockData{ + Method: `GET`, + Url: `/sap/opu/odata/BUILD/CORE_SRV/results(build_id='AKO22FYOFYPOXHOBVKXUTX3A3Q',task_id=11,name='SAR_XML')/$value`, + Body: ``, + StatusCode: 200, } -var template = mockData{ - method: `GET`, - url: ``, - body: ``, - statusCode: 200, +var template = MockData{ + Method: `GET`, + Url: ``, + Body: ``, + StatusCode: 200, } diff --git a/resources/metadata/abapAddonAssemblyKitPublishTargetVector.yaml b/resources/metadata/abapAddonAssemblyKitPublishTargetVector.yaml index e5a710cf9..a6b9878f3 100644 --- a/resources/metadata/abapAddonAssemblyKitPublishTargetVector.yaml +++ b/resources/metadata/abapAddonAssemblyKitPublishTargetVector.yaml @@ -50,6 +50,24 @@ spec: - STAGES - STEPS default: T + - 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 - name: addonDescriptor type: string description: Structure in the commonPipelineEnvironment containing information about the Product Version and corresponding Software Component Versions