diff --git a/cmd/abapEnvironmentCheckoutBranch_test.go b/cmd/abapEnvironmentCheckoutBranch_test.go index 5ba5334a8a..87bf02fe43 100644 --- a/cmd/abapEnvironmentCheckoutBranch_test.go +++ b/cmd/abapEnvironmentCheckoutBranch_test.go @@ -67,7 +67,7 @@ func TestCheckoutBranchStep(t *testing.T) { StatusCode: 200, } - apiManager = &abaputils.SoftwareComponentApiManager{Client: client, PollIntervall: 1 * time.Microsecond} + apiManager = &abaputils.SoftwareComponentApiManager{Client: client, PollIntervall: 1 * time.Nanosecond, Force0510: true} err := runAbapEnvironmentCheckoutBranch(&config, &autils, apiManager) assert.NoError(t, err, "Did not expect error") }) @@ -96,7 +96,7 @@ func TestCheckoutBranchStep(t *testing.T) { StatusCode: 200, } - apiManager = &abaputils.SoftwareComponentApiManager{Client: client, PollIntervall: 1 * time.Microsecond} + apiManager = &abaputils.SoftwareComponentApiManager{Client: client, PollIntervall: 1 * time.Nanosecond, Force0510: true} err := runAbapEnvironmentCheckoutBranch(&config, &autils, apiManager) assert.EqualError(t, err, expectedErrorMessage) }) @@ -135,7 +135,7 @@ func TestCheckoutBranchStep(t *testing.T) { StatusCode: 200, } - apiManager = &abaputils.SoftwareComponentApiManager{Client: client, PollIntervall: 1 * time.Microsecond} + apiManager = &abaputils.SoftwareComponentApiManager{Client: client, PollIntervall: 1 * time.Nanosecond, Force0510: true} err := runAbapEnvironmentCheckoutBranch(&config, &autils, apiManager) assert.EqualError(t, err, expectedErrorMessage) }) @@ -184,7 +184,7 @@ repositories: Password: "testPassword", Repositories: "repositoriesTest.yml", } - apiManager = &abaputils.SoftwareComponentApiManager{Client: client, PollIntervall: 1 * time.Microsecond} + apiManager = &abaputils.SoftwareComponentApiManager{Client: client, PollIntervall: 1 * time.Nanosecond, Force0510: true} err = runAbapEnvironmentCheckoutBranch(&config, &autils, apiManager) assert.NoError(t, err) }) @@ -228,7 +228,7 @@ repositories: Password: "testPassword", Repositories: "repositoriesTest.yml", } - apiManager = &abaputils.SoftwareComponentApiManager{Client: client, PollIntervall: 1 * time.Microsecond} + apiManager = &abaputils.SoftwareComponentApiManager{Client: client, PollIntervall: 1 * time.Nanosecond, Force0510: true} err = runAbapEnvironmentCheckoutBranch(&config, &autils, apiManager) assert.EqualError(t, err, expectedErrorMessage) }) @@ -277,7 +277,7 @@ repositories: Password: "testPassword", Repositories: "repositoriesTest.yml", } - apiManager = &abaputils.SoftwareComponentApiManager{Client: client, PollIntervall: 1 * time.Microsecond} + apiManager = &abaputils.SoftwareComponentApiManager{Client: client, PollIntervall: 1 * time.Nanosecond, Force0510: true} err = runAbapEnvironmentCheckoutBranch(&config, &autils, apiManager) assert.EqualError(t, err, expectedErrorMessage) }) diff --git a/cmd/abapEnvironmentCloneGitRepo_test.go b/cmd/abapEnvironmentCloneGitRepo_test.go index f009b831f4..ae6f47f75f 100644 --- a/cmd/abapEnvironmentCloneGitRepo_test.go +++ b/cmd/abapEnvironmentCloneGitRepo_test.go @@ -100,7 +100,7 @@ repositories: Token: "myToken", } - apiManager = &abaputils.SoftwareComponentApiManager{Client: client, PollIntervall: 1 * time.Nanosecond} + apiManager = &abaputils.SoftwareComponentApiManager{Client: client, PollIntervall: 1 * time.Nanosecond, Force0510: true} err = runAbapEnvironmentCloneGitRepo(&config, &autils, apiManager) assert.NoError(t, err, "Did not expect error") assert.Equal(t, 0, len(client.BodyList), "Not all requests were done") @@ -140,7 +140,7 @@ repositories: StatusCode: 200, } - apiManager = &abaputils.SoftwareComponentApiManager{Client: client, PollIntervall: 1 * time.Nanosecond} + apiManager = &abaputils.SoftwareComponentApiManager{Client: client, PollIntervall: 1 * time.Nanosecond, Force0510: true} err := runAbapEnvironmentCloneGitRepo(&config, &autils, apiManager) assert.NoError(t, err, "Did not expect error") assert.Equal(t, 0, len(client.BodyList), "Not all requests were done") @@ -177,7 +177,7 @@ repositories: StatusCode: 200, } - apiManager = &abaputils.SoftwareComponentApiManager{Client: client, PollIntervall: 1 * time.Nanosecond} + apiManager = &abaputils.SoftwareComponentApiManager{Client: client, PollIntervall: 1 * time.Nanosecond, Force0510: true} err := runAbapEnvironmentCloneGitRepo(&config, &autils, apiManager) if assert.Error(t, err, "Expected error") { assert.Equal(t, "Clone of repository / software component 'testRepo1', branch 'testBranch1' failed on the ABAP system: Request to ABAP System not successful", err.Error(), "Expected different error message") @@ -239,7 +239,7 @@ repositories: Token: "myToken", StatusCode: 200, } - apiManager = &abaputils.SoftwareComponentApiManager{Client: client, PollIntervall: 1 * time.Nanosecond} + apiManager = &abaputils.SoftwareComponentApiManager{Client: client, PollIntervall: 1 * time.Nanosecond, Force0510: true} err = runAbapEnvironmentCloneGitRepo(&config, &autils, apiManager) if assert.Error(t, err, "Expected error") { assert.Equal(t, "Clone of repository / software component '/DMO/REPO_A', branch 'branchA', commit 'ABCD1234' failed on the ABAP system: Request to ABAP System not successful", err.Error(), "Expected different error message") @@ -275,7 +275,7 @@ repositories: Token: "myToken", StatusCode: 200, } - apiManager = &abaputils.SoftwareComponentApiManager{Client: client, PollIntervall: 1 * time.Nanosecond} + apiManager = &abaputils.SoftwareComponentApiManager{Client: client, PollIntervall: 1 * time.Nanosecond, Force0510: true} err := runAbapEnvironmentCloneGitRepo(&config, &autils, apiManager) if assert.Error(t, err, "Expected error") { assert.Equal(t, "Clone of repository / software component 'testRepo1', branch 'testBranch1' failed on the ABAP system: Request to ABAP System not successful", err.Error(), "Expected different error message") @@ -310,7 +310,7 @@ repositories: Token: "myToken", StatusCode: 200, } - apiManager = &abaputils.SoftwareComponentApiManager{Client: client, PollIntervall: 1 * time.Nanosecond} + apiManager = &abaputils.SoftwareComponentApiManager{Client: client, PollIntervall: 1 * time.Nanosecond, Force0510: true} err := runAbapEnvironmentCloneGitRepo(&config, &autils, apiManager) if assert.Error(t, err, "Expected error") { assert.Equal(t, "Clone of repository / software component 'testRepo1', branch 'testBranch1' failed on the ABAP system: Request to ABAP System not successful", err.Error(), "Expected different error message") @@ -344,7 +344,7 @@ repositories: Token: "myToken", StatusCode: 200, } - apiManager = &abaputils.SoftwareComponentApiManager{Client: client, PollIntervall: 1 * time.Nanosecond} + apiManager = &abaputils.SoftwareComponentApiManager{Client: client, PollIntervall: 1 * time.Nanosecond, Force0510: true} err := runAbapEnvironmentCloneGitRepo(&config, &autils, apiManager) if assert.Error(t, err, "Expected error") { assert.Equal(t, "Could not read repositories: Could not find filename.yaml", err.Error(), "Expected different error message") @@ -385,7 +385,7 @@ repositories: Token: "myToken", StatusCode: 200, } - apiManager = &abaputils.SoftwareComponentApiManager{Client: client, PollIntervall: 1 * time.Nanosecond} + apiManager = &abaputils.SoftwareComponentApiManager{Client: client, PollIntervall: 1 * time.Nanosecond, Force0510: true} err := runAbapEnvironmentCloneGitRepo(&config, &autils, apiManager) if assert.Error(t, err, "Expected error") { assert.Equal(t, "The provided configuration is not allowed: It is not allowed to configure the parameters `repositories`and `repositoryName` at the same time", err.Error(), "Expected different error message") @@ -441,7 +441,7 @@ func TestALreadyCloned(t *testing.T) { CommitID: "abcd1234", } - apiManager = &abaputils.SoftwareComponentApiManager{Client: client, PollIntervall: 1 * time.Nanosecond} + apiManager = &abaputils.SoftwareComponentApiManager{Client: client, PollIntervall: 1 * time.Nanosecond, Force0510: true} err := cloneSingleRepo(apiManager, autils.ReturnedConnectionDetailsHTTP, repo, &config, &autils) assert.NoError(t, err, "Did not expect error") }) @@ -487,7 +487,7 @@ func TestALreadyCloned(t *testing.T) { CommitID: "abcd1234", } - apiManager = &abaputils.SoftwareComponentApiManager{Client: client, PollIntervall: 1 * time.Nanosecond} + apiManager = &abaputils.SoftwareComponentApiManager{Client: client, PollIntervall: 1 * time.Nanosecond, Force0510: true} err := cloneSingleRepo(apiManager, autils.ReturnedConnectionDetailsHTTP, repo, &config, &autils) assert.NoError(t, err, "Did not expect error") }) diff --git a/cmd/abapEnvironmentCreateTag_test.go b/cmd/abapEnvironmentCreateTag_test.go index 996cafd2bf..cdd1310062 100644 --- a/cmd/abapEnvironmentCreateTag_test.go +++ b/cmd/abapEnvironmentCreateTag_test.go @@ -80,15 +80,15 @@ repositories: } client := &abaputils.ClientMock{ BodyList: []string{ - `{"d" : ` + executionLogStringClone + `}`, + `{"d" : ` + executionLogStringCreateTag + `}`, logResultSuccess, `{"d" : { "Status" : "S" } }`, `{"d" : { "uuid" : "abc" } }`, - `{"d" : ` + executionLogStringClone + `}`, + `{"d" : ` + executionLogStringCreateTag + `}`, logResultSuccess, `{"d" : { "Status" : "S" } }`, `{"d" : { "uuid" : "abc" } }`, - `{"d" : ` + executionLogStringClone + `}`, + `{"d" : ` + executionLogStringCreateTag + `}`, logResultSuccess, `{"d" : { "Status" : "S" } }`, `{"d" : { "uuid" : "abc" } }`, @@ -101,14 +101,14 @@ repositories: _, hook := test.NewNullLogger() log.RegisterHook(hook) - apiManager = &abaputils.SoftwareComponentApiManager{Client: client, PollIntervall: 1 * time.Microsecond} + apiManager := &abaputils.SoftwareComponentApiManager{Client: client, PollIntervall: 1 * time.Nanosecond, Force0510: true} err = runAbapEnvironmentCreateTag(config, autils, apiManager) assert.NoError(t, err, "Did not expect error") - assert.Equal(t, 22, len(hook.Entries), "Expected a different number of entries") - assert.Equal(t, `Created tag v4.5.6 for repository /DMO/SWC with commitID 1234abcd`, hook.AllEntries()[11].Message, "Expected a different message") - assert.Equal(t, `Created tag -DMO-PRODUCT-1.2.3 for repository /DMO/SWC with commitID 1234abcd`, hook.AllEntries()[16].Message, "Expected a different message") - assert.Equal(t, `Created tag tag for repository /DMO/SWC with commitID 1234abcd`, hook.AllEntries()[21].Message, "Expected a different message") + assert.Equal(t, 25, len(hook.Entries), "Expected a different number of entries") + assert.Equal(t, `Created tag v4.5.6 for repository /DMO/SWC with commitID 1234abcd`, hook.AllEntries()[12].Message, "Expected a different message") + assert.Equal(t, `Created tag -DMO-PRODUCT-1.2.3 for repository /DMO/SWC with commitID 1234abcd`, hook.AllEntries()[18].Message, "Expected a different message") + assert.Equal(t, `Created tag tag for repository /DMO/SWC with commitID 1234abcd`, hook.AllEntries()[24].Message, "Expected a different message") hook.Reset() }) @@ -153,17 +153,17 @@ repositories: } client := &abaputils.ClientMock{ BodyList: []string{ - `{"d" : ` + executionLogStringClone + `}`, + `{"d" : ` + executionLogStringCreateTag + `}`, logResultSuccess, `{"d" : { "Status" : "E" } }`, `{"d" : { "uuid" : "abc" } }`, `{"d" : { "empty" : "body" } }`, - `{"d" : ` + executionLogStringClone + `}`, + `{"d" : ` + executionLogStringCreateTag + `}`, logResultSuccess, `{"d" : { "Status" : "E" } }`, `{"d" : { "uuid" : "abc" } }`, `{"d" : { "empty" : "body" } }`, - `{"d" : ` + executionLogStringClone + `}`, + `{"d" : ` + executionLogStringCreateTag + `}`, logResultSuccess, `{"d" : { "Status" : "E" } }`, `{"d" : { "uuid" : "abc" } }`, @@ -176,15 +176,15 @@ repositories: _, hook := test.NewNullLogger() log.RegisterHook(hook) - apiManager = &abaputils.SoftwareComponentApiManager{Client: client, PollIntervall: 1 * time.Microsecond} + apiManager := &abaputils.SoftwareComponentApiManager{Client: client, PollIntervall: 1 * time.Nanosecond, Force0510: true} err = runAbapEnvironmentCreateTag(config, autils, apiManager) assert.Error(t, err, "Did expect error") - assert.Equal(t, 37, len(hook.Entries), "Expected a different number of entries") - assert.Equal(t, `NOT created: Tag v4.5.6 for repository /DMO/SWC with commitID 1234abcd`, hook.AllEntries()[11].Message, "Expected a different message") - assert.Equal(t, `NOT created: Tag -DMO-PRODUCT-1.2.3 for repository /DMO/SWC with commitID 1234abcd`, hook.AllEntries()[23].Message, "Expected a different message") - assert.Equal(t, `NOT created: Tag tag for repository /DMO/SWC with commitID 1234abcd`, hook.AllEntries()[35].Message, "Expected a different message") - assert.Equal(t, `At least one tag has not been created`, hook.AllEntries()[36].Message, "Expected a different message") + assert.Equal(t, 40, len(hook.Entries), "Expected a different number of entries") + assert.Equal(t, `NOT created: Tag v4.5.6 for repository /DMO/SWC with commitID 1234abcd`, hook.AllEntries()[12].Message, "Expected a different message") + assert.Equal(t, `NOT created: Tag -DMO-PRODUCT-1.2.3 for repository /DMO/SWC with commitID 1234abcd`, hook.AllEntries()[25].Message, "Expected a different message") + assert.Equal(t, `NOT created: Tag tag for repository /DMO/SWC with commitID 1234abcd`, hook.AllEntries()[38].Message, "Expected a different message") + assert.Equal(t, `At least one tag has not been created`, hook.AllEntries()[39].Message, "Expected a different message") hook.Reset() }) @@ -215,7 +215,7 @@ func TestRunAbapEnvironmentCreateTagConfigurations(t *testing.T) { } client := &abaputils.ClientMock{ BodyList: []string{ - `{"d" : ` + executionLogStringClone + `}`, + `{"d" : ` + executionLogStringCreateTag + `}`, logResultSuccess, `{"d" : { "Status" : "S" } }`, `{"d" : { "uuid" : "abc" } }`, @@ -228,12 +228,12 @@ func TestRunAbapEnvironmentCreateTagConfigurations(t *testing.T) { _, hook := test.NewNullLogger() log.RegisterHook(hook) - apiManager = &abaputils.SoftwareComponentApiManager{Client: client, PollIntervall: 1 * time.Microsecond} + apiManager := &abaputils.SoftwareComponentApiManager{Client: client, PollIntervall: 1 * time.Nanosecond, Force0510: true} err := runAbapEnvironmentCreateTag(config, autils, apiManager) assert.NoError(t, err, "Did not expect error") - assert.Equal(t, 12, len(hook.Entries), "Expected a different number of entries") - assert.Equal(t, `Created tag tag for repository /DMO/SWC with commitID 1234abcd`, hook.AllEntries()[11].Message, "Expected a different message") + assert.Equal(t, 13, len(hook.Entries), "Expected a different number of entries") + assert.Equal(t, `Created tag tag for repository /DMO/SWC with commitID 1234abcd`, hook.AllEntries()[12].Message, "Expected a different message") hook.Reset() }) @@ -296,7 +296,7 @@ repositories: StatusCode: 200, } - apiManager = &abaputils.SoftwareComponentApiManager{Client: client, PollIntervall: 1 * time.Microsecond} + apiManager := &abaputils.SoftwareComponentApiManager{Client: client, PollIntervall: 1 * time.Nanosecond, Force0510: true} err = runAbapEnvironmentCreateTag(config, autils, apiManager) assert.Error(t, err, "Did expect error") @@ -359,12 +359,12 @@ repositories: _, hook := test.NewNullLogger() log.RegisterHook(hook) - apiManager = &abaputils.SoftwareComponentApiManager{Client: client, PollIntervall: 1 * time.Microsecond} + apiManager := &abaputils.SoftwareComponentApiManager{Client: client, PollIntervall: 1 * time.Nanosecond, Force0510: true} err = runAbapEnvironmentCreateTag(config, autils, apiManager) assert.NoError(t, err, "Did not expect error") - assert.Equal(t, 5, len(hook.Entries), "Expected a different number of entries") - assert.Equal(t, `Created tag tag for repository /DMO/SWC with commitID 1234abcd`, hook.AllEntries()[4].Message, "Expected a different message") + assert.Equal(t, 6, len(hook.Entries), "Expected a different number of entries") + assert.Equal(t, `Created tag tag for repository /DMO/SWC with commitID 1234abcd`, hook.AllEntries()[5].Message, "Expected a different message") hook.Reset() }) diff --git a/cmd/abapEnvironmentPullGitRepo_test.go b/cmd/abapEnvironmentPullGitRepo_test.go index 50e0c5e223..cd805f37d5 100644 --- a/cmd/abapEnvironmentPullGitRepo_test.go +++ b/cmd/abapEnvironmentPullGitRepo_test.go @@ -69,7 +69,7 @@ func TestPullStep(t *testing.T) { StatusCode: 200, } - apiManager = &abaputils.SoftwareComponentApiManager{Client: client, PollIntervall: 1 * time.Microsecond} + apiManager = &abaputils.SoftwareComponentApiManager{Client: client, PollIntervall: 1 * time.Nanosecond, Force0510: true} err := runAbapEnvironmentPullGitRepo(&config, &autils, apiManager) assert.NoError(t, err, "Did not expect error") assert.Equal(t, 0, len(client.BodyList), "Not all requests were done") @@ -96,7 +96,7 @@ func TestPullStep(t *testing.T) { config := abapEnvironmentPullGitRepoOptions{} - apiManager = &abaputils.SoftwareComponentApiManager{Client: client, PollIntervall: 1 * time.Microsecond} + apiManager = &abaputils.SoftwareComponentApiManager{Client: client, PollIntervall: 1 * time.Nanosecond, Force0510: true} err := runAbapEnvironmentPullGitRepo(&config, &autils, apiManager) assert.Equal(t, expectedErrorMessage, err.Error(), "Different error message expected") }) @@ -147,7 +147,7 @@ repositories: Password: "testPassword", Repositories: "repositoriesTest.yml", } - apiManager = &abaputils.SoftwareComponentApiManager{Client: client, PollIntervall: 1 * time.Microsecond} + apiManager = &abaputils.SoftwareComponentApiManager{Client: client, PollIntervall: 1 * time.Nanosecond, Force0510: true} err = runAbapEnvironmentPullGitRepo(&config, &autils, apiManager) assert.NoError(t, err) }) @@ -203,7 +203,7 @@ repositories: StatusCode: 200, } - apiManager = &abaputils.SoftwareComponentApiManager{Client: client, PollIntervall: 1 * time.Microsecond} + apiManager = &abaputils.SoftwareComponentApiManager{Client: client, PollIntervall: 1 * time.Nanosecond, Force0510: true} err = runAbapEnvironmentPullGitRepo(&config, &autils, apiManager) if assert.Error(t, err, "Expected error") { assert.Equal(t, "Pull of the repository / software component '/DMO/REPO_A', commit 'ABCD1234' failed on the ABAP system", err.Error(), "Expected different error message") @@ -262,7 +262,7 @@ repositories: StatusCode: 200, } - apiManager = &abaputils.SoftwareComponentApiManager{Client: client, PollIntervall: 1 * time.Microsecond} + apiManager = &abaputils.SoftwareComponentApiManager{Client: client, PollIntervall: 1 * time.Nanosecond, Force0510: true} err = runAbapEnvironmentPullGitRepo(&config, &autils, apiManager) if assert.Error(t, err, "Expected error") { assert.Equal(t, "Pull of the repository / software component '/DMO/REPO_A', tag 'v-1.0.1-build-0001' failed on the ABAP system", err.Error(), "Expected different error message") @@ -302,7 +302,7 @@ repositories: StatusCode: 200, } - apiManager = &abaputils.SoftwareComponentApiManager{Client: client, PollIntervall: 1 * time.Microsecond} + apiManager = &abaputils.SoftwareComponentApiManager{Client: client, PollIntervall: 1 * time.Nanosecond, Force0510: true} err := runAbapEnvironmentPullGitRepo(&config, &autils, apiManager) if assert.Error(t, err, "Expected error") { assert.Equal(t, "Pull of the repository / software component '/DMO/SWC', commit '123456' failed on the ABAP system", err.Error(), "Expected different error message") @@ -341,7 +341,7 @@ repositories: StatusCode: 200, } - apiManager = &abaputils.SoftwareComponentApiManager{Client: client, PollIntervall: 1 * time.Microsecond} + apiManager = &abaputils.SoftwareComponentApiManager{Client: client, PollIntervall: 1 * time.Nanosecond, Force0510: true} err := runAbapEnvironmentPullGitRepo(&config, &autils, apiManager) if assert.Error(t, err, "Expected error") { assert.Equal(t, "Pull of the repository / software component '/DMO/SWC' failed on the ABAP system", err.Error(), "Expected different error message") @@ -388,7 +388,7 @@ repositories: Password: "testPassword", Repositories: "repositoriesTest.yml", } - apiManager = &abaputils.SoftwareComponentApiManager{Client: client, PollIntervall: 1 * time.Microsecond} + apiManager = &abaputils.SoftwareComponentApiManager{Client: client, PollIntervall: 1 * time.Nanosecond, Force0510: true} err = runAbapEnvironmentPullGitRepo(&config, &autils, apiManager) assert.EqualError(t, err, expectedErrorMessage) }) @@ -438,7 +438,7 @@ repositories: Password: "testPassword", Repositories: "repositoriesTest.yml", } - apiManager = &abaputils.SoftwareComponentApiManager{Client: client, PollIntervall: 1 * time.Microsecond} + apiManager = &abaputils.SoftwareComponentApiManager{Client: client, PollIntervall: 1 * time.Nanosecond, Force0510: true} err = runAbapEnvironmentPullGitRepo(&config, &autils, apiManager) assert.EqualError(t, err, expectedErrorMessage) }) diff --git a/pkg/abaputils/manageGitRepositoryUtils.go b/pkg/abaputils/manageGitRepositoryUtils.go index 19a56659f9..84fe060dd6 100644 --- a/pkg/abaputils/manageGitRepositoryUtils.go +++ b/pkg/abaputils/manageGitRepositoryUtils.go @@ -4,7 +4,6 @@ import ( "fmt" "reflect" "sort" - "strconv" "strings" "time" @@ -42,21 +41,21 @@ func PollEntity(api SoftwareComponentApiInterface, pollIntervall time.Duration) func PrintLogs(api SoftwareComponentApiInterface) { // connectionDetails.URL = connectionDetails.URL + "?$expand=to_Log_Overview" - entity, err := api.GetLogOverview() - if err != nil || len(entity.ToLogOverview.Results) == 0 { + results, err := api.GetLogOverview() + if err != nil || len(results) == 0 { // return if no logs are available return } // Sort logs - sort.SliceStable(entity.ToLogOverview.Results, func(i, j int) bool { - return entity.ToLogOverview.Results[i].Index < entity.ToLogOverview.Results[j].Index + sort.SliceStable(results, func(i, j int) bool { + return results[i].Index < results[j].Index }) - printOverview(entity) + printOverview(results) // Print Details - for _, logEntryForDetails := range entity.ToLogOverview.Results { + for _, logEntryForDetails := range results { printLog(logEntryForDetails, api) } AddDefaultDashedLine(1) @@ -64,9 +63,9 @@ func PrintLogs(api SoftwareComponentApiInterface) { return } -func printOverview(entity ActionEntity) { +func printOverview(results []LogResultsV2) { - logOutputPhaseLength, logOutputLineLength := calculateLenghts(entity) + logOutputPhaseLength, logOutputLineLength := calculateLenghts(results) log.Entry().Infof("\n") @@ -76,15 +75,15 @@ func printOverview(entity ActionEntity) { printDashedLine(logOutputLineLength) - for _, logEntry := range entity.ToLogOverview.Results { + for _, logEntry := range results { log.Entry().Infof("| %-"+fmt.Sprint(logOutputPhaseLength)+"s | %"+fmt.Sprint(logOutputStatusLength)+"s | %-"+fmt.Sprint(logOutputTimestampLength)+"s |", logEntry.Name, logEntry.Status, ConvertTime(logEntry.Timestamp)) } printDashedLine(logOutputLineLength) } -func calculateLenghts(entity ActionEntity) (int, int) { +func calculateLenghts(results []LogResultsV2) (int, int) { phaseLength := 22 - for _, logEntry := range entity.ToLogOverview.Results { + for _, logEntry := range results { if l := len(logEntry.Name); l > phaseLength { phaseLength = l } @@ -103,40 +102,34 @@ func printLog(logOverviewEntry LogResultsV2, api SoftwareComponentApiInterface) page := 0 printHeader(logOverviewEntry) for { - logProtocolEntry, err := api.GetLogProtocol(logOverviewEntry, page) - printLogProtocolEntries(logOverviewEntry, logProtocolEntry) + logProtocols, count, err := api.GetLogProtocol(logOverviewEntry, page) + printLogProtocolEntries(logOverviewEntry, logProtocols) page += 1 - if allLogsHaveBeenPrinted(logProtocolEntry, page, err) { + if allLogsHaveBeenPrinted(logProtocols, page, count, err) { break } } } -func printLogProtocolEntries(logEntry LogResultsV2, entity LogProtocolResults) { +func printLogProtocolEntries(logEntry LogResultsV2, logProtocols []LogProtocol) { - sort.SliceStable(entity.Results, func(i, j int) bool { - return entity.Results[i].ProtocolLine < entity.Results[j].ProtocolLine + sort.SliceStable(logProtocols, func(i, j int) bool { + return logProtocols[i].ProtocolLine < logProtocols[j].ProtocolLine }) if logEntry.Status != `Success` { - for _, entry := range entity.Results { + for _, entry := range logProtocols { log.Entry().Info(entry.Description) } } else { - for _, entry := range entity.Results { + for _, entry := range logProtocols { log.Entry().Debug(entry.Description) } } } -func allLogsHaveBeenPrinted(entity LogProtocolResults, page int, err error) bool { - allPagesHaveBeenRead := false - numberOfProtocols, errConversion := strconv.Atoi(entity.Count) - if errConversion == nil { - allPagesHaveBeenRead = numberOfProtocols <= page*numberOfEntriesPerPage - } else { - return true - } - return (err != nil || allPagesHaveBeenRead || reflect.DeepEqual(entity.Results, LogProtocolResults{})) +func allLogsHaveBeenPrinted(protocols []LogProtocol, page int, count int, err error) bool { + allPagesHaveBeenRead := count <= page*numberOfEntriesPerPage + return (err != nil || allPagesHaveBeenRead || reflect.DeepEqual(protocols, []LogProtocol{})) } func printHeader(logEntry LogResultsV2) { @@ -153,13 +146,6 @@ func printHeader(logEntry LogResultsV2) { } } -func getLogProtocolQuery(page int) string { - skip := page * numberOfEntriesPerPage - top := numberOfEntriesPerPage - - return fmt.Sprintf("?$skip=%s&$top=%s&$inlinecount=allpages", fmt.Sprint(skip), fmt.Sprint(top)) -} - // GetRepositories for parsing one or multiple branches and repositories from repositories file or branchName and repositoryName configuration func GetRepositories(config *RepositoriesConfig, branchRequired bool) ([]Repository, error) { var repositories = make([]Repository, 0) @@ -240,6 +226,10 @@ func (repo *Repository) GetPullRequestBody() (body string) { return body } +func (repo *Repository) GetPullActionRequestBody() (body string) { + return `{` + `"commit_id":"` + repo.CommitID + `", ` + `"tag_name":"` + repo.Tag + `"` + `}` +} + func (repo *Repository) GetPullLogString() (logString string) { commitOrTag := repo.GetLogStringForCommitOrTag() logString = "repository / software component '" + repo.Name + "'" + commitOrTag diff --git a/pkg/abaputils/manageGitRepositoryUtils_test.go b/pkg/abaputils/manageGitRepositoryUtils_test.go index 58a37cb92d..9b6cf3ca3f 100644 --- a/pkg/abaputils/manageGitRepositoryUtils_test.go +++ b/pkg/abaputils/manageGitRepositoryUtils_test.go @@ -59,7 +59,7 @@ func TestPollEntity(t *testing.T) { XCsrfToken: "MY_TOKEN", } - swcManager := SoftwareComponentApiManager{Client: client} + swcManager := SoftwareComponentApiManager{Client: client, Force0510: true} repo := Repository{Name: "testRepo1"} api, _ := swcManager.GetAPI(con, repo) @@ -91,7 +91,7 @@ func TestPollEntity(t *testing.T) { XCsrfToken: "MY_TOKEN", } - swcManager := SoftwareComponentApiManager{Client: client} + swcManager := SoftwareComponentApiManager{Client: client, Force0510: true} repo := Repository{Name: "testRepo1"} api, _ := swcManager.GetAPI(con, repo) diff --git a/pkg/abaputils/sap_com_0510.go b/pkg/abaputils/sap_com_0510.go index c7940832d5..fcf0b6938e 100644 --- a/pkg/abaputils/sap_com_0510.go +++ b/pkg/abaputils/sap_com_0510.go @@ -7,6 +7,7 @@ import ( "net/http" "net/http/cookiejar" "reflect" + "strconv" "strings" "time" @@ -48,6 +49,7 @@ func (api *SAP_COM_0510) init(con ConnectionDetailsHTTP, client piperhttp.Sender api.maxRetries = 3 api.setSleepTimeConfig(1*time.Second, 120*time.Second) api.retryAllowedErrorCodes = append(api.retryAllowedErrorCodes, "A4C_A2G/228") + api.retryAllowedErrorCodes = append(api.retryAllowedErrorCodes, "A4C_A2G/501") } func (api *SAP_COM_0510) getUUID() string { @@ -121,35 +123,41 @@ func (api *SAP_COM_0510) Pull() error { return api.triggerRequest(pullConnectionDetails, jsonBody) } -func (api *SAP_COM_0510) GetLogProtocol(logOverviewEntry LogResultsV2, page int) (body LogProtocolResults, err error) { +func (api *SAP_COM_0510) GetLogProtocol(logOverviewEntry LogResultsV2, page int) (result []LogProtocol, count int, err error) { connectionDetails := api.con - connectionDetails.URL = logOverviewEntry.ToLogProtocol.Deferred.URI + getLogProtocolQuery(page) + connectionDetails.URL = logOverviewEntry.ToLogProtocol.Deferred.URI + api.getLogProtocolQuery(page) resp, err := GetHTTPResponse("GET", connectionDetails, nil, api.client) if err != nil { log.SetErrorCategory(log.ErrorInfrastructure) _, err = HandleHTTPError(resp, err, api.failureMessage, connectionDetails) - return body, err + return nil, 0, err } defer resp.Body.Close() // Parse response + var body LogProtocolResults var abapResp map[string]*json.RawMessage bodyText, _ := io.ReadAll(resp.Body) marshallError := json.Unmarshal(bodyText, &abapResp) if marshallError != nil { - return body, errors.Wrap(marshallError, "Could not parse response from the ABAP Environment system") + return nil, 0, errors.Wrap(marshallError, "Could not parse response from the ABAP Environment system") } marshallError = json.Unmarshal(*abapResp["d"], &body) if marshallError != nil { - return body, errors.Wrap(marshallError, "Could not parse response from the ABAP Environment system") + return nil, 0, errors.Wrap(marshallError, "Could not parse response from the ABAP Environment system") } - return body, nil + count, errConv := strconv.Atoi(body.Count) + if errConv != nil { + return nil, 0, errors.Wrap(errConv, "Could not parse response from the ABAP Environment system") + } + + return body.Results, count, nil } -func (api *SAP_COM_0510) GetLogOverview() (body ActionEntity, err error) { +func (api *SAP_COM_0510) GetLogOverview() (result []LogResultsV2, err error) { connectionDetails := api.con connectionDetails.URL = api.con.URL + api.path + api.actionEntity + "(uuid=guid'" + api.getUUID() + "')" + "?$expand=to_Log_Overview" @@ -157,33 +165,34 @@ func (api *SAP_COM_0510) GetLogOverview() (body ActionEntity, err error) { if err != nil { log.SetErrorCategory(log.ErrorInfrastructure) _, err = HandleHTTPError(resp, err, api.failureMessage, connectionDetails) - return body, err + return nil, err } defer resp.Body.Close() // Parse response + var body ActionEntity var abapResp map[string]*json.RawMessage bodyText, _ := io.ReadAll(resp.Body) marshallError := json.Unmarshal(bodyText, &abapResp) if marshallError != nil { - return body, errors.Wrap(marshallError, "Could not parse response from the ABAP Environment system") + return nil, errors.Wrap(marshallError, "Could not parse response from the ABAP Environment system") } marshallError = json.Unmarshal(*abapResp["d"], &body) if marshallError != nil { - return body, errors.Wrap(marshallError, "Could not parse response from the ABAP Environment system") + return nil, errors.Wrap(marshallError, "Could not parse response from the ABAP Environment system") } if reflect.DeepEqual(ActionEntity{}, body) { log.Entry().WithField("StatusCode", resp.Status).Error(api.failureMessage) log.SetErrorCategory(log.ErrorInfrastructure) var err = errors.New("Request to ABAP System not successful") - return body, err + return nil, err } abapStatusCode := body.Status log.Entry().Info("Status: " + abapStatusCode + " - " + body.StatusDescription) - return body, nil + return body.ToLogOverview.Results, nil } @@ -367,3 +376,10 @@ func (api *SAP_COM_0510) setSleepTimeConfig(timeUnit time.Duration, maxSleepTime api.retryBaseSleepUnit = timeUnit api.retryMaxSleepTime = maxSleepTime } + +func (api *SAP_COM_0510) getLogProtocolQuery(page int) string { + skip := page * numberOfEntriesPerPage + top := numberOfEntriesPerPage + + return fmt.Sprintf("?$skip=%s&$top=%s&$inlinecount=allpages", fmt.Sprint(skip), fmt.Sprint(top)) +} diff --git a/pkg/abaputils/sap_com_0510_test.go b/pkg/abaputils/sap_com_0510_test.go index 772207d5eb..776aa28d7f 100644 --- a/pkg/abaputils/sap_com_0510_test.go +++ b/pkg/abaputils/sap_com_0510_test.go @@ -43,7 +43,7 @@ func TestRetry(t *testing.T) { }, } - apiManager := &SoftwareComponentApiManager{Client: client, PollIntervall: 1 * time.Microsecond} + apiManager := &SoftwareComponentApiManager{Client: client, PollIntervall: 1 * time.Microsecond, Force0510: true} api, err := apiManager.GetAPI(con, repo) api.setSleepTimeConfig(time.Nanosecond, 120*time.Nanosecond) @@ -73,7 +73,7 @@ func TestRetry(t *testing.T) { }, } - apiManager := &SoftwareComponentApiManager{Client: client, PollIntervall: 1 * time.Microsecond} + apiManager := &SoftwareComponentApiManager{Client: client, PollIntervall: 1 * time.Microsecond, Force0510: true} api, err := apiManager.GetAPI(con, repo) api.setSleepTimeConfig(time.Nanosecond, 120*time.Nanosecond) @@ -117,7 +117,7 @@ func TestRetry(t *testing.T) { }, } - apiManager := &SoftwareComponentApiManager{Client: client, PollIntervall: 1 * time.Microsecond} + apiManager := &SoftwareComponentApiManager{Client: client, PollIntervall: 1 * time.Microsecond, Force0510: true} api, err := apiManager.GetAPI(con, repo) api.setSleepTimeConfig(time.Nanosecond, 20*time.Nanosecond) @@ -164,7 +164,7 @@ func TestRetry(t *testing.T) { }, } - apiManager := &SoftwareComponentApiManager{Client: client, PollIntervall: 1 * time.Microsecond} + apiManager := &SoftwareComponentApiManager{Client: client, PollIntervall: 1 * time.Microsecond, Force0510: true} api, err := apiManager.GetAPI(con, repo) api.setSleepTimeConfig(time.Nanosecond, 999*time.Nanosecond) @@ -193,7 +193,7 @@ func TestClone(t *testing.T) { StatusCode: 200, } - apiManager := &SoftwareComponentApiManager{Client: client, PollIntervall: 1 * time.Microsecond} + apiManager := &SoftwareComponentApiManager{Client: client, PollIntervall: 1 * time.Microsecond, Force0510: true} api, err := apiManager.GetAPI(con, repo) assert.NoError(t, err) @@ -216,7 +216,7 @@ func TestClone(t *testing.T) { StatusCode: 200, } - apiManager := &SoftwareComponentApiManager{Client: client, PollIntervall: 1 * time.Microsecond} + apiManager := &SoftwareComponentApiManager{Client: client, PollIntervall: 1 * time.Microsecond, Force0510: true} api, err := apiManager.GetAPI(con, repo) api.setSleepTimeConfig(time.Nanosecond, 120*time.Nanosecond) @@ -245,7 +245,7 @@ func TestClone(t *testing.T) { }, } - apiManager := &SoftwareComponentApiManager{Client: client, PollIntervall: 1 * time.Microsecond} + apiManager := &SoftwareComponentApiManager{Client: client, PollIntervall: 1 * time.Microsecond, Force0510: true} api, err := apiManager.GetAPI(con, repo) api.setSleepTimeConfig(time.Nanosecond, 120*time.Nanosecond) @@ -270,7 +270,7 @@ func TestPull(t *testing.T) { StatusCode: 200, } - apiManager := &SoftwareComponentApiManager{Client: client, PollIntervall: 1 * time.Microsecond} + apiManager := &SoftwareComponentApiManager{Client: client, PollIntervall: 1 * time.Microsecond, Force0510: true} api, err := apiManager.GetAPI(con, repo) assert.NoError(t, err) @@ -292,7 +292,7 @@ func TestPull(t *testing.T) { StatusCode: 200, } - apiManager := &SoftwareComponentApiManager{Client: client, PollIntervall: 1 * time.Microsecond} + apiManager := &SoftwareComponentApiManager{Client: client, PollIntervall: 1 * time.Microsecond, Force0510: true} api, err := apiManager.GetAPI(con, repo) assert.NoError(t, err) @@ -316,7 +316,7 @@ func TestCheckout(t *testing.T) { StatusCode: 200, } - apiManager := &SoftwareComponentApiManager{Client: client, PollIntervall: 1 * time.Microsecond} + apiManager := &SoftwareComponentApiManager{Client: client, PollIntervall: 1 * time.Microsecond, Force0510: true} api, err := apiManager.GetAPI(con, repo) assert.NoError(t, err) @@ -338,7 +338,7 @@ func TestCheckout(t *testing.T) { StatusCode: 200, } - apiManager := &SoftwareComponentApiManager{Client: client, PollIntervall: 1 * time.Microsecond} + apiManager := &SoftwareComponentApiManager{Client: client, PollIntervall: 1 * time.Microsecond, Force0510: true} api, err := apiManager.GetAPI(con, repo) assert.NoError(t, err) @@ -362,7 +362,7 @@ func TestGetRepo(t *testing.T) { StatusCode: 200, } - apiManager := &SoftwareComponentApiManager{Client: client, PollIntervall: 1 * time.Microsecond} + apiManager := &SoftwareComponentApiManager{Client: client, PollIntervall: 1 * time.Microsecond, Force0510: true} api, err := apiManager.GetAPI(con, repo) assert.NoError(t, err) @@ -387,7 +387,7 @@ func TestCreateTag(t *testing.T) { StatusCode: 200, } - apiManager := &SoftwareComponentApiManager{Client: client, PollIntervall: 1 * time.Microsecond} + apiManager := &SoftwareComponentApiManager{Client: client, PollIntervall: 1 * time.Microsecond, Force0510: true} api, err := apiManager.GetAPI(con, repo) assert.NoError(t, err) @@ -409,7 +409,7 @@ func TestCreateTag(t *testing.T) { StatusCode: 200, } - apiManager := &SoftwareComponentApiManager{Client: client, PollIntervall: 1 * time.Microsecond} + apiManager := &SoftwareComponentApiManager{Client: client, PollIntervall: 1 * time.Microsecond, Force0510: true} api, err := apiManager.GetAPI(con, repo) assert.NoError(t, err) @@ -431,7 +431,7 @@ func TestCreateTag(t *testing.T) { StatusCode: 200, } - apiManager := &SoftwareComponentApiManager{Client: client, PollIntervall: 1 * time.Microsecond} + apiManager := &SoftwareComponentApiManager{Client: client, PollIntervall: 1 * time.Microsecond, Force0510: true} api, err := apiManager.GetAPI(con, repo) assert.NoError(t, err) diff --git a/pkg/abaputils/sap_com_0948.go b/pkg/abaputils/sap_com_0948.go new file mode 100644 index 0000000000..18aa31decd --- /dev/null +++ b/pkg/abaputils/sap_com_0948.go @@ -0,0 +1,376 @@ +package abaputils + +import ( + "encoding/json" + "fmt" + "io" + "net/http" + "net/http/cookiejar" + "reflect" + "strings" + "time" + + piperhttp "github.com/SAP/jenkins-library/pkg/http" + "github.com/SAP/jenkins-library/pkg/log" + "github.com/pkg/errors" + "k8s.io/utils/strings/slices" +) + +type SAP_COM_0948 struct { + con ConnectionDetailsHTTP + client piperhttp.Sender + repository Repository + path string + cloneAction string + pullAction string + softwareComponentEntity string + branchEntity string + tagsEntity string + checkoutAction string + actionsEntity string + uuid string + failureMessage string + maxRetries int + retryBaseSleepUnit time.Duration + retryMaxSleepTime time.Duration + retryAllowedErrorCodes []string +} + +func (api *SAP_COM_0948) init(con ConnectionDetailsHTTP, client piperhttp.Sender, repo Repository) { + api.con = con + api.client = client + api.repository = repo + api.path = "/sap/opu/odata4/sap/a4c_mswc_api/srvd_a2x/sap/manage_software_components/0001" + api.checkoutAction = "/SAP__self.checkout_branch" + api.softwareComponentEntity = "/SoftwareComponents" + api.actionsEntity = "/Actions" + api.branchEntity = "/Branches" + api.cloneAction = "/SAP__self.clone" + api.pullAction = "/SAP__self.pull" + api.tagsEntity = "/Tags" + api.failureMessage = "The action of the Repository / Software Component " + api.repository.Name + " failed" + api.maxRetries = 3 + api.setSleepTimeConfig(1*time.Second, 120*time.Second) + api.retryAllowedErrorCodes = append(api.retryAllowedErrorCodes, "A4C_A2G/228") + api.retryAllowedErrorCodes = append(api.retryAllowedErrorCodes, "A4C_A2G/501") +} + +func (api *SAP_COM_0948) getUUID() string { + return api.uuid +} + +func (api *SAP_COM_0948) CreateTag(tag Tag) error { + + if reflect.DeepEqual(Tag{}, tag) { + return errors.New("No Tag provided") + } + + con := api.con + con.URL = api.con.URL + api.path + api.tagsEntity + + requestBodyStruct := CreateTagBody{RepositoryName: api.repository.Name, CommitID: api.repository.CommitID, Tag: tag.TagName, Description: tag.TagDescription} + jsonBody, err := json.Marshal(&requestBodyStruct) + if err != nil { + return err + } + return api.triggerRequest(con, jsonBody) +} + +func (api *SAP_COM_0948) CheckoutBranch() error { + + if api.repository.Name == "" || api.repository.Branch == "" { + return fmt.Errorf("Failed to trigger checkout: %w", errors.New("Repository and/or Branch Configuration is empty. Please make sure that you have specified the correct values")) + } + + checkoutConnectionDetails := api.con + checkoutConnectionDetails.URL = api.con.URL + api.path + api.branchEntity + api.getRepoNameForPath() + api.getBranchNameForPath() + api.checkoutAction + jsonBody := []byte(`{ + "import_mode" : "", + "execution_mode": "" + }`) + + return api.triggerRequest(checkoutConnectionDetails, jsonBody) +} + +func (api *SAP_COM_0948) parseActionResponse(resp *http.Response, err error) (ActionEntity, error) { + + var body ActionEntity + bodyText, errRead := io.ReadAll(resp.Body) + if errRead != nil { + return ActionEntity{}, err + } + if err := json.Unmarshal(bodyText, &body); err != nil { + return ActionEntity{}, err + } + if reflect.DeepEqual(ActionEntity{}, body) { + log.Entry().WithField("StatusCode", resp.Status).WithField("branchName", api.repository.Branch).Error("Could not switch to specified branch") + err := errors.New("Request to ABAP System not successful") + return ActionEntity{}, err + } + return body, nil +} + +func (api *SAP_COM_0948) Pull() error { + + // Trigger the Pull of a Repository + if api.repository.Name == "" { + return errors.New("An empty string was passed for the parameter 'repositoryName'") + } + + pullConnectionDetails := api.con + pullConnectionDetails.URL = api.con.URL + api.path + api.softwareComponentEntity + api.getRepoNameForPath() + api.pullAction + + jsonBody := []byte(api.repository.GetPullActionRequestBody()) + return api.triggerRequest(pullConnectionDetails, jsonBody) +} + +func (api *SAP_COM_0948) GetLogProtocol(logOverviewEntry LogResultsV2, page int) (result []LogProtocol, count int, err error) { + + connectionDetails := api.con + connectionDetails.URL = api.con.URL + api.path + api.actionsEntity + "/" + api.getUUID() + "/_Log_Overview" + "/" + fmt.Sprint(logOverviewEntry.Index) + "/_Log_Protocol" + api.getLogProtocolQuery(page) + resp, err := GetHTTPResponse("GET", connectionDetails, nil, api.client) + if err != nil { + log.SetErrorCategory(log.ErrorInfrastructure) + _, err = HandleHTTPError(resp, err, api.failureMessage, connectionDetails) + return nil, 0, err + } + defer resp.Body.Close() + + // Parse response + var body LogProtocolResultsV4 + bodyText, _ := io.ReadAll(resp.Body) + + marshallError := json.Unmarshal(bodyText, &body) + if marshallError != nil { + return nil, 0, errors.Wrap(marshallError, "Could not parse response from the ABAP Environment system") + } + + return body.Results, body.Count, nil +} + +func (api *SAP_COM_0948) GetLogOverview() (result []LogResultsV2, err error) { + + connectionDetails := api.con + connectionDetails.URL = api.con.URL + api.path + api.actionsEntity + "/" + api.getUUID() + "/_Log_Overview" + resp, err := GetHTTPResponse("GET", connectionDetails, nil, api.client) + if err != nil { + log.SetErrorCategory(log.ErrorInfrastructure) + _, err = HandleHTTPError(resp, err, api.failureMessage, connectionDetails) + return nil, err + } + defer resp.Body.Close() + + // Parse response + var abapResp map[string]*json.RawMessage + bodyText, _ := io.ReadAll(resp.Body) + + marshallError := json.Unmarshal(bodyText, &abapResp) + if marshallError != nil { + return nil, errors.Wrap(marshallError, "Could not parse response from the ABAP Environment system") + } + marshallError = json.Unmarshal(*abapResp["value"], &result) + if marshallError != nil { + return nil, errors.Wrap(marshallError, "Could not parse response from the ABAP Environment system") + } + + if reflect.DeepEqual(LogResultsV2{}, result) { + log.Entry().WithField("StatusCode", resp.Status).Error(api.failureMessage) + log.SetErrorCategory(log.ErrorInfrastructure) + var err = errors.New("Request to ABAP System not successful") + return nil, err + } + return result, nil + +} + +func (api *SAP_COM_0948) GetAction() (string, error) { + + connectionDetails := api.con + connectionDetails.URL = api.con.URL + api.path + api.actionsEntity + "/" + api.getUUID() + resp, err := GetHTTPResponse("GET", connectionDetails, nil, api.client) + if err != nil { + log.SetErrorCategory(log.ErrorInfrastructure) + _, err = HandleHTTPError(resp, err, api.failureMessage, connectionDetails) + return "E", err + } + defer resp.Body.Close() + + // Parse Response + body, parseError := api.parseActionResponse(resp, err) + if parseError != nil { + return "E", parseError + } + + api.uuid = body.UUID + + abapStatusCode := body.Status + log.Entry().Info("Status: " + abapStatusCode + " - " + body.StatusDescription) + return abapStatusCode, nil +} + +func (api *SAP_COM_0948) GetRepository() (bool, string, error) { + + if api.repository.Name == "" { + return false, "", errors.New("An empty string was passed for the parameter 'repositoryName'") + } + + swcConnectionDetails := api.con + swcConnectionDetails.URL = api.con.URL + api.path + api.softwareComponentEntity + api.getRepoNameForPath() + resp, err := GetHTTPResponse("GET", swcConnectionDetails, nil, api.client) + if err != nil { + _, errRepo := HandleHTTPError(resp, err, "Reading the Repository / Software Component failed", api.con) + return false, "", errRepo + } + defer resp.Body.Close() + + var body RepositoryEntity + bodyText, errRead := io.ReadAll(resp.Body) + if errRead != nil { + return false, "", err + } + + if err := json.Unmarshal(bodyText, &body); err != nil { + return false, "", err + } + if reflect.DeepEqual(RepositoryEntity{}, body) { + log.Entry().WithField("StatusCode", resp.Status).WithField("repositoryName", api.repository.Name).WithField("branchName", api.repository.Branch).WithField("commitID", api.repository.CommitID).WithField("Tag", api.repository.Tag).Error("Could not Clone the Repository / Software Component") + err := errors.New("Request to ABAP System not successful") + return false, "", err + } + + if body.AvailOnInst { + return true, body.ActiveBranch, nil + } + return false, "", err + +} + +func (api *SAP_COM_0948) Clone() error { + + // Trigger the Clone of a Repository + if api.repository.Name == "" { + return errors.New("An empty string was passed for the parameter 'repositoryName'") + } + + cloneConnectionDetails := api.con + cloneConnectionDetails.URL = api.con.URL + api.path + api.softwareComponentEntity + api.getRepoNameForPath() + api.cloneAction + body := []byte(api.repository.GetCloneRequestBody()) + + return api.triggerRequest(cloneConnectionDetails, body) + +} + +func (api *SAP_COM_0948) triggerRequest(cloneConnectionDetails ConnectionDetailsHTTP, jsonBody []byte) error { + var err error + var body ActionEntity + var resp *http.Response + var errorCode string + + for i := 0; i <= api.maxRetries; i++ { + if i > 0 { + sleepTime, err := api.getSleepTime(i + 5) + if err != nil { + // reached max retry duration + break + } + log.Entry().Infof("Retrying in %s", sleepTime.String()) + time.Sleep(sleepTime) + } + resp, err = GetHTTPResponse("POST", cloneConnectionDetails, jsonBody, api.client) + if err != nil { + errorCode, err = HandleHTTPError(resp, err, "Triggering the action failed", api.con) + if slices.Contains(api.retryAllowedErrorCodes, errorCode) { + // Error Code allows for retry + continue + } else { + break + } + } + defer resp.Body.Close() + log.Entry().WithField("StatusCode", resp.Status).WithField("repositoryName", api.repository.Name).WithField("branchName", api.repository.Branch).WithField("commitID", api.repository.CommitID).WithField("Tag", api.repository.Tag).Info("Triggered action of Repository / Software Component") + + body, err = api.parseActionResponse(resp, err) + break + } + api.uuid = body.UUID + return err +} + +// initialRequest implements SoftwareComponentApiInterface. +func (api *SAP_COM_0948) initialRequest() error { + // Configuring the HTTP Client and CookieJar + cookieJar, errorCookieJar := cookiejar.New(nil) + if errorCookieJar != nil { + return errors.Wrap(errorCookieJar, "Could not create a Cookie Jar") + } + + api.client.SetOptions(piperhttp.ClientOptions{ + MaxRequestDuration: 180 * time.Second, + CookieJar: cookieJar, + Username: api.con.User, + Password: api.con.Password, + }) + + headConnection := api.con + headConnection.XCsrfToken = "fetch" + headConnection.URL = api.con.URL + api.path + + // Loging into the ABAP System - getting the x-csrf-token and cookies + resp, err := GetHTTPResponse("HEAD", headConnection, nil, api.client) + if err != nil { + _, err = HandleHTTPError(resp, err, "Authentication on the ABAP system failed", api.con) + return err + } + defer resp.Body.Close() + + log.Entry().WithField("StatusCode", resp.Status).WithField("ABAP Endpoint", api.con).Debug("Authentication on the ABAP system successful") + api.con.XCsrfToken = resp.Header.Get("X-Csrf-Token") + return nil +} + +// getSleepTime Should return the Fibonacci numbers in the define time unit up to the defined maximum duration +func (api *SAP_COM_0948) getSleepTime(n int) (time.Duration, error) { + + if n == 0 { + return 0, nil + } else if n == 1 { + return 1 * api.retryBaseSleepUnit, nil + } else if n < 0 { + return 0, errors.New("Negative numbers are not allowed") + } + var result, i int + prev := 0 + next := 1 + for i = 2; i <= n; i++ { + result = prev + next + prev = next + next = result + } + sleepTime := time.Duration(result) * api.retryBaseSleepUnit + + if sleepTime > api.retryMaxSleepTime { + return 0, errors.New("Exceeded max sleep time") + } + return sleepTime, nil +} + +// setSleepTimeConfig sets the time unit (seconds, nanoseconds) and the maximum sleep duration +func (api *SAP_COM_0948) setSleepTimeConfig(timeUnit time.Duration, maxSleepTime time.Duration) { + api.retryBaseSleepUnit = timeUnit + api.retryMaxSleepTime = maxSleepTime +} + +func (api *SAP_COM_0948) getRepoNameForPath() string { + return "/" + strings.ReplaceAll(api.repository.Name, "/", "%2F") +} + +func (api *SAP_COM_0948) getBranchNameForPath() string { + return "/" + api.repository.Branch +} + +func (api *SAP_COM_0948) getLogProtocolQuery(page int) string { + skip := page * numberOfEntriesPerPage + top := numberOfEntriesPerPage + + return fmt.Sprintf("?$skip=%s&$top=%s&$count=true", fmt.Sprint(skip), fmt.Sprint(top)) +} diff --git a/pkg/abaputils/sap_com_0948_test.go b/pkg/abaputils/sap_com_0948_test.go new file mode 100644 index 0000000000..72c8fdd158 --- /dev/null +++ b/pkg/abaputils/sap_com_0948_test.go @@ -0,0 +1,483 @@ +//go:build unit +// +build unit + +package abaputils + +import ( + "testing" + "time" + + "github.com/pkg/errors" + "github.com/stretchr/testify/assert" +) + +var connection ConnectionDetailsHTTP +var repository Repository + +func init() { + + connection.User = "CC_USER" + connection.Password = "123abc" + connection.URL = "https://example.com" + + repository.Name = "/DMO/REPO" + repository.Branch = "main" + +} + +func TestRetry0948(t *testing.T) { + t.Run("Test retry success", func(t *testing.T) { + + client := &ClientMock{ + BodyList: []string{ + `{ "status" : "R", "UUID" : "GUID" }`, + `{"error" : { "code" : "A4C_A2G/228", "message" : { "lang" : "de", "value" : "Software component lifecycle activities in progress. Try again later..."} } }`, + `{ }`, + }, + Token: "myToken", + StatusCode: 200, + ErrorList: []error{ + nil, + errors.New("HTTP 400"), + nil, + }, + } + + apiManager := &SoftwareComponentApiManager{Client: client, PollIntervall: 1 * time.Microsecond} + + api, err := apiManager.GetAPI(con, repo) + api.setSleepTimeConfig(time.Nanosecond, 120*time.Nanosecond) + assert.NoError(t, err) + assert.IsType(t, &SAP_COM_0948{}, api.(*SAP_COM_0948), "API has wrong type") + + errAction := api.(*SAP_COM_0948).triggerRequest(ConnectionDetailsHTTP{User: "CC_USER", Password: "abc123", URL: "https://example.com/path"}, []byte("{}")) + assert.NoError(t, errAction) + assert.Equal(t, "GUID", api.getUUID(), "API does not cotain correct UUID") + + }) + + t.Run("Test retry not allowed", func(t *testing.T) { + + client := &ClientMock{ + BodyList: []string{ + `{ "status" : "R", "UUID" : "GUID" }`, + `{"error" : { "code" : "A4C_A2G/224", "message" : { "lang" : "de", "value" : "Error Text"} } }`, + `{ }`, + }, + Token: "myToken", + StatusCode: 200, + ErrorList: []error{ + nil, + errors.New("HTTP 400"), + nil, + }, + } + + apiManager := &SoftwareComponentApiManager{Client: client, PollIntervall: 1 * time.Microsecond} + + api, err := apiManager.GetAPI(con, repo) + api.setSleepTimeConfig(time.Nanosecond, 120*time.Nanosecond) + assert.NoError(t, err) + assert.IsType(t, &SAP_COM_0948{}, api.(*SAP_COM_0948), "API has wrong type") + + errAction := api.(*SAP_COM_0948).triggerRequest(ConnectionDetailsHTTP{User: "CC_USER", Password: "abc123", URL: "https://example.com/path"}, []byte("{}")) + assert.ErrorContains(t, errAction, "HTTP 400: A4C_A2G/224 - Error Text") + assert.Empty(t, api.getUUID(), "API does not cotain correct UUID") + + }) + + t.Run("Test retry maxSleepTime", func(t *testing.T) { + + client := &ClientMock{ + BodyList: []string{ + `{"error" : { "code" : "A4C_A2G/228", "message" : { "lang" : "de", "value" : "Error Text"} } }`, + `{"error" : { "code" : "A4C_A2G/228", "message" : { "lang" : "de", "value" : "Error Text"} } }`, + `{"error" : { "code" : "A4C_A2G/228", "message" : { "lang" : "de", "value" : "Error Text"} } }`, + `{"error" : { "code" : "A4C_A2G/228", "message" : { "lang" : "de", "value" : "Error Text"} } }`, + `{"error" : { "code" : "A4C_A2G/228", "message" : { "lang" : "de", "value" : "Error Text"} } }`, + `{"error" : { "code" : "A4C_A2G/228", "message" : { "lang" : "de", "value" : "Error Text"} } }`, + `{"error" : { "code" : "A4C_A2G/228", "message" : { "lang" : "de", "value" : "Error Text"} } }`, + `{"error" : { "code" : "A4C_A2G/228", "message" : { "lang" : "de", "value" : "Error Text"} } }`, + `{"error" : { "code" : "A4C_A2G/228", "message" : { "lang" : "de", "value" : "Error Text"} } }`, + `{ }`, + }, + Token: "myToken", + StatusCode: 200, + ErrorList: []error{ + errors.New("HTTP 400"), + errors.New("HTTP 400"), + errors.New("HTTP 400"), + errors.New("HTTP 400"), + errors.New("HTTP 400"), + errors.New("HTTP 400"), + errors.New("HTTP 400"), + errors.New("HTTP 400"), + errors.New("HTTP 400"), + nil, + }, + } + + apiManager := &SoftwareComponentApiManager{Client: client, PollIntervall: 1 * time.Microsecond} + + api, err := apiManager.GetAPI(con, repo) + api.setSleepTimeConfig(time.Nanosecond, 20*time.Nanosecond) + assert.NoError(t, err) + assert.IsType(t, &SAP_COM_0948{}, api.(*SAP_COM_0948), "API has wrong type") + + api.(*SAP_COM_0948).maxRetries = 20 + + errAction := api.(*SAP_COM_0948).triggerRequest(ConnectionDetailsHTTP{User: "CC_USER", Password: "abc123", URL: "https://example.com/path"}, []byte("{}")) + assert.ErrorContains(t, errAction, "HTTP 400: A4C_A2G/228 - Error Text") + assert.Empty(t, api.getUUID(), "API does not cotain correct UUID") + + assert.Equal(t, 6, len(client.BodyList), "Expected maxSleepTime to limit requests") + }) + + t.Run("Test retry maxRetries", func(t *testing.T) { + + client := &ClientMock{ + BodyList: []string{ + `{"error" : { "code" : "A4C_A2G/228", "message" : { "lang" : "de", "value" : "Error Text"} } }`, + `{"error" : { "code" : "A4C_A2G/228", "message" : { "lang" : "de", "value" : "Error Text"} } }`, + `{"error" : { "code" : "A4C_A2G/228", "message" : { "lang" : "de", "value" : "Error Text"} } }`, + `{"error" : { "code" : "A4C_A2G/228", "message" : { "lang" : "de", "value" : "Error Text"} } }`, + `{"error" : { "code" : "A4C_A2G/228", "message" : { "lang" : "de", "value" : "Error Text"} } }`, + `{"error" : { "code" : "A4C_A2G/228", "message" : { "lang" : "de", "value" : "Error Text"} } }`, + `{"error" : { "code" : "A4C_A2G/228", "message" : { "lang" : "de", "value" : "Error Text"} } }`, + `{"error" : { "code" : "A4C_A2G/228", "message" : { "lang" : "de", "value" : "Error Text"} } }`, + `{"error" : { "code" : "A4C_A2G/228", "message" : { "lang" : "de", "value" : "Error Text"} } }`, + `{ }`, + }, + Token: "myToken", + StatusCode: 200, + ErrorList: []error{ + errors.New("HTTP 400"), + errors.New("HTTP 400"), + errors.New("HTTP 400"), + errors.New("HTTP 400"), + errors.New("HTTP 400"), + errors.New("HTTP 400"), + errors.New("HTTP 400"), + errors.New("HTTP 400"), + errors.New("HTTP 400"), + nil, + }, + } + + apiManager := &SoftwareComponentApiManager{Client: client, PollIntervall: 1 * time.Microsecond} + + api, err := apiManager.GetAPI(con, repo) + api.setSleepTimeConfig(time.Nanosecond, 999*time.Nanosecond) + assert.NoError(t, err) + assert.IsType(t, &SAP_COM_0948{}, api.(*SAP_COM_0948), "API has wrong type") + + api.(*SAP_COM_0948).maxRetries = 3 + + errAction := api.(*SAP_COM_0948).triggerRequest(ConnectionDetailsHTTP{User: "CC_USER", Password: "abc123", URL: "https://example.com/path"}, []byte("{}")) + assert.ErrorContains(t, errAction, "HTTP 400: A4C_A2G/228 - Error Text") + assert.Empty(t, api.getUUID(), "API does not cotain correct UUID") + + assert.Equal(t, 5, len(client.BodyList), "Expected maxRetries to limit requests") + }) + +} +func TestClone0948(t *testing.T) { + t.Run("Test Clone Success", func(t *testing.T) { + + client := &ClientMock{ + BodyList: []string{ + `{ "status" : "R", "UUID" : "GUID" }`, + `{ }`, + }, + Token: "myToken", + StatusCode: 200, + } + + apiManager := &SoftwareComponentApiManager{Client: client, PollIntervall: 1 * time.Microsecond} + + api, err := apiManager.GetAPI(con, repo) + assert.NoError(t, err) + assert.IsType(t, &SAP_COM_0948{}, api.(*SAP_COM_0948), "API has wrong type") + + errClone := api.Clone() + assert.NoError(t, errClone) + assert.Equal(t, "GUID", api.getUUID(), "API does not cotain correct UUID") + }) + + t.Run("Test Clone Failure", func(t *testing.T) { + + client := &ClientMock{ + BodyList: []string{ + `{ "d" : {} }`, + `{ "d" : {} }`, + `{ }`, + }, + Token: "myToken", + StatusCode: 200, + } + + apiManager := &SoftwareComponentApiManager{Client: client, PollIntervall: 1 * time.Microsecond} + + api, err := apiManager.GetAPI(con, repo) + api.setSleepTimeConfig(time.Nanosecond, 120*time.Nanosecond) + assert.NoError(t, err) + assert.IsType(t, &SAP_COM_0948{}, api.(*SAP_COM_0948), "API has wrong type") + + errClone := api.Clone() + assert.ErrorContains(t, errClone, "Request to ABAP System not successful") + assert.Empty(t, api.getUUID(), "API does not cotain correct UUID") + }) + + t.Run("Test Clone Retry", func(t *testing.T) { + + client := &ClientMock{ + BodyList: []string{ + `{ "status" : "R", "UUID" : "GUID" }`, + `{"error" : { "code" : "A4C_A2G/228", "message" : { "lang" : "de", "value" : "Software component lifecycle activities in progress. Try again later..."} } }`, + `{ }`, + }, + Token: "myToken", + StatusCode: 200, + ErrorList: []error{ + nil, + errors.New("HTTP 400"), + nil, + }, + } + + apiManager := &SoftwareComponentApiManager{Client: client, PollIntervall: 1 * time.Microsecond} + + api, err := apiManager.GetAPI(con, repo) + api.setSleepTimeConfig(time.Nanosecond, 120*time.Nanosecond) + assert.NoError(t, err) + assert.IsType(t, &SAP_COM_0948{}, api.(*SAP_COM_0948), "API has wrong type") + + errClone := api.Clone() + assert.NoError(t, errClone) + assert.Equal(t, "GUID", api.getUUID(), "API does not cotain correct UUID") + }) +} + +func TestPull0948(t *testing.T) { + t.Run("Test Pull Success", func(t *testing.T) { + + client := &ClientMock{ + BodyList: []string{ + `{ "status" : "R", "UUID" : "GUID" }`, + `{ }`, + }, + Token: "myToken", + StatusCode: 200, + } + + apiManager := &SoftwareComponentApiManager{Client: client, PollIntervall: 1 * time.Microsecond} + + api, err := apiManager.GetAPI(con, repo) + assert.NoError(t, err) + assert.IsType(t, &SAP_COM_0948{}, api.(*SAP_COM_0948), "API has wrong type") + + errPull := api.Pull() + assert.NoError(t, errPull) + assert.Equal(t, "GUID", api.getUUID(), "API does not cotain correct UUID") + }) + + t.Run("Test Pull Failure", func(t *testing.T) { + + client := &ClientMock{ + BodyList: []string{ + `{ "d" : {} }`, + `{ }`, + }, + Token: "myToken", + StatusCode: 200, + } + + apiManager := &SoftwareComponentApiManager{Client: client, PollIntervall: 1 * time.Microsecond} + + api, err := apiManager.GetAPI(con, repo) + assert.NoError(t, err) + assert.IsType(t, &SAP_COM_0948{}, api.(*SAP_COM_0948), "API has wrong type") + + errPull := api.Pull() + assert.ErrorContains(t, errPull, "Request to ABAP System not successful") + assert.Empty(t, api.getUUID(), "API does not cotain correct UUID") + }) +} + +func TestCheckout0948(t *testing.T) { + t.Run("Test Checkout Success", func(t *testing.T) { + + client := &ClientMock{ + BodyList: []string{ + `{ "status" : "R", "UUID" : "GUID" }`, + `{ }`, + }, + Token: "myToken", + StatusCode: 200, + } + + apiManager := &SoftwareComponentApiManager{Client: client, PollIntervall: 1 * time.Microsecond} + + api, err := apiManager.GetAPI(con, repo) + assert.NoError(t, err) + assert.IsType(t, &SAP_COM_0948{}, api.(*SAP_COM_0948), "API has wrong type") + + errCheckout := api.CheckoutBranch() + assert.NoError(t, errCheckout) + assert.Equal(t, "GUID", api.getUUID(), "API does not cotain correct UUID") + }) + + t.Run("Test Checkout Failure", func(t *testing.T) { + + client := &ClientMock{ + BodyList: []string{ + `{ "d" : {} }`, + `{ }`, + }, + Token: "myToken", + StatusCode: 200, + } + + apiManager := &SoftwareComponentApiManager{Client: client, PollIntervall: 1 * time.Microsecond} + + api, err := apiManager.GetAPI(con, repo) + assert.NoError(t, err) + assert.IsType(t, &SAP_COM_0948{}, api.(*SAP_COM_0948), "API has wrong type") + + errCheckoput := api.CheckoutBranch() + assert.ErrorContains(t, errCheckoput, "Request to ABAP System not successful") + assert.Empty(t, api.getUUID(), "API does not cotain correct UUID") + }) +} + +func TestGetRepo0948(t *testing.T) { + t.Run("Test GetRepo Success", func(t *testing.T) { + + client := &ClientMock{ + BodyList: []string{ + `{ "sc_name" : "testRepo1", "avail_on_inst" : true, "active_branch": "testBranch1" }`, + `{"d" : [] }`, + }, + Token: "myToken", + StatusCode: 200, + } + + apiManager := &SoftwareComponentApiManager{Client: client, PollIntervall: 1 * time.Microsecond} + + api, err := apiManager.GetAPI(con, repo) + assert.NoError(t, err) + assert.IsType(t, &SAP_COM_0948{}, api.(*SAP_COM_0948), "API has wrong type") + + cloned, activeBranch, errAction := api.GetRepository() + assert.True(t, cloned) + assert.Equal(t, "testBranch1", activeBranch) + assert.NoError(t, errAction) + }) +} + +func TestCreateTag0948(t *testing.T) { + t.Run("Test Tag Success", func(t *testing.T) { + + client := &ClientMock{ + BodyList: []string{ + `{ "status" : "R", "UUID" : "GUID" }`, + `{ }`, + }, + Token: "myToken", + StatusCode: 200, + } + + apiManager := &SoftwareComponentApiManager{Client: client, PollIntervall: 1 * time.Microsecond} + + api, err := apiManager.GetAPI(con, repo) + assert.NoError(t, err) + assert.IsType(t, &SAP_COM_0948{}, api.(*SAP_COM_0948), "API has wrong type") + + errCreateTag := api.CreateTag(Tag{TagName: "myTag", TagDescription: "descr"}) + assert.NoError(t, errCreateTag) + assert.Equal(t, "GUID", api.getUUID(), "API does not cotain correct UUID") + }) + + t.Run("Test Tag Failure", func(t *testing.T) { + + client := &ClientMock{ + BodyList: []string{ + `{ "d" : {} }`, + `{ }`, + }, + Token: "myToken", + StatusCode: 200, + } + + apiManager := &SoftwareComponentApiManager{Client: client, PollIntervall: 1 * time.Microsecond} + + api, err := apiManager.GetAPI(con, repo) + assert.NoError(t, err) + assert.IsType(t, &SAP_COM_0948{}, api.(*SAP_COM_0948), "API has wrong type") + + errCreateTag := api.CreateTag(Tag{TagName: "myTag", TagDescription: "descr"}) + assert.ErrorContains(t, errCreateTag, "Request to ABAP System not successful") + assert.Empty(t, api.getUUID(), "API does not cotain correct UUID") + }) + + t.Run("Test Tag Empty", func(t *testing.T) { + + client := &ClientMock{ + BodyList: []string{ + `{ "d" : {} }`, + `{ }`, + }, + Token: "myToken", + StatusCode: 200, + } + + apiManager := &SoftwareComponentApiManager{Client: client, PollIntervall: 1 * time.Microsecond} + + api, err := apiManager.GetAPI(con, repo) + assert.NoError(t, err) + assert.IsType(t, &SAP_COM_0948{}, api.(*SAP_COM_0948), "API has wrong type") + + errCreateTag := api.CreateTag(Tag{}) + assert.ErrorContains(t, errCreateTag, "No Tag provided") + assert.Empty(t, api.getUUID(), "API does not cotain correct UUID") + }) +} + +func TestSleepTime0948(t *testing.T) { + t.Run("Test Sleep Time", func(t *testing.T) { + + api := SAP_COM_0948{ + retryMaxSleepTime: 120 * time.Nanosecond, + retryBaseSleepUnit: 1 * time.Nanosecond, + } + + expectedResults := make([]time.Duration, 12) + expectedResults[0] = 0 + expectedResults[1] = 1 + expectedResults[2] = 1 + expectedResults[3] = 2 + expectedResults[4] = 3 + expectedResults[5] = 5 + expectedResults[6] = 8 + expectedResults[7] = 13 + expectedResults[8] = 21 + expectedResults[9] = 34 + expectedResults[10] = 55 + expectedResults[11] = 89 + results := make([]time.Duration, 12) + var err error + + for i := 0; i <= 11; i++ { + + results[i], err = api.getSleepTime(i) + assert.NoError(t, err) + } + assert.ElementsMatch(t, expectedResults, results) + + _, err = api.getSleepTime(-10) + assert.Error(t, err) + + _, err = api.getSleepTime(12) + assert.ErrorContains(t, err, "Exceeded max sleep time") + }) +} diff --git a/pkg/abaputils/softwareComponentApiManager.go b/pkg/abaputils/softwareComponentApiManager.go index 65565a0405..9b5e06332d 100644 --- a/pkg/abaputils/softwareComponentApiManager.go +++ b/pkg/abaputils/softwareComponentApiManager.go @@ -1,9 +1,11 @@ package abaputils import ( + "errors" "time" piperhttp "github.com/SAP/jenkins-library/pkg/http" + "github.com/SAP/jenkins-library/pkg/log" ) type SoftwareComponentApiManagerInterface interface { @@ -14,16 +16,34 @@ type SoftwareComponentApiManagerInterface interface { type SoftwareComponentApiManager struct { Client piperhttp.Sender PollIntervall time.Duration + Force0510 bool } func (manager *SoftwareComponentApiManager) GetAPI(con ConnectionDetailsHTTP, repo Repository) (SoftwareComponentApiInterface, error) { + + var err0948 error + if !manager.Force0510 { + // Initialize SAP_COM_0948, if it does not work, use SAP_COM_0510 + sap_com_0948 := SAP_COM_0948{} + sap_com_0948.init(con, manager.Client, repo) + err0948 = sap_com_0948.initialRequest() + if err0948 == nil { + return &sap_com_0948, nil + } + } + sap_com_0510 := SAP_COM_0510{} sap_com_0510.init(con, manager.Client, repo) + err0510 := sap_com_0510.initialRequest() + if err0510 == nil { + log.Entry().Infof("SAP_COM_0510 will be replaced by SAP_COM_0948 starting from the SAP BTP, ABAP environment release 2402.") + return &sap_com_0510, nil + } + + log.Entry().Errorf("Could not connect via SAP_COM_0948: %s", err0948) + log.Entry().Errorf("Could not connect via SAP_COM_0510: %s", err0510) - // Initialize all APIs, use the one that returns a response - // Currently SAP_COM_0510, later SAP_COM_0948 - err := sap_com_0510.initialRequest() - return &sap_com_0510, err + return nil, errors.New("Could not initialize API") } func (manager *SoftwareComponentApiManager) GetPollIntervall() time.Duration { @@ -44,8 +64,8 @@ type SoftwareComponentApiInterface interface { CheckoutBranch() error GetRepository() (bool, string, error) GetAction() (string, error) - GetLogOverview() (ActionEntity, error) - GetLogProtocol(LogResultsV2, int) (body LogProtocolResults, err error) + GetLogOverview() ([]LogResultsV2, error) + GetLogProtocol(LogResultsV2, int) (result []LogProtocol, count int, err error) CreateTag(tag Tag) error } @@ -57,7 +77,7 @@ type SoftwareComponentApiInterface interface { type ActionEntity struct { Metadata AbapMetadata `json:"__metadata"` UUID string `json:"uuid"` - Namespace string `json:"namepsace"` + Namespace string `json:"namespace"` ScName string `json:"sc_name"` ImportType string `json:"import_type"` BranchName string `json:"branch_name"` @@ -141,13 +161,18 @@ type LogProtocolResults struct { Count string `json:"__count"` } +type LogProtocolResultsV4 struct { + Results []LogProtocol `json:"value"` + Count int `json:"@odata.count"` +} + type LogProtocol struct { - Metadata AbapMetadata `json:"__metadata"` - OverviewIndex int `json:"log_index"` - ProtocolLine int `json:"index_no"` - Type string `json:"type"` - Description string `json:"descr"` - Timestamp string `json:"timestamp"` + // Metadata AbapMetadata `json:"__metadata"` + OverviewIndex int `json:"log_index"` + ProtocolLine int `json:"index_no"` + Type string `json:"type"` + Description string `json:"descr"` + Timestamp string `json:"timestamp"` } // LogResults struct for Execution and Transport Log entities A4C_A2G_GHA_SC_LOG_EXE and A4C_A2G_GHA_SC_LOG_TP