1
0
mirror of https://github.com/SAP/jenkins-library.git synced 2025-03-03 15:02:35 +02:00

Mass enabling for pullGitRepo & checkoutBranch steps (#2005)

This commit is contained in:
Dominik Lendle 2020-10-05 14:38:35 +02:00 committed by GitHub
parent 19f45aa687
commit 703f8e921e
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
18 changed files with 940 additions and 88 deletions

View File

@ -2,6 +2,7 @@ package cmd
import (
"encoding/json"
"fmt"
"io/ioutil"
"net/http/cookiejar"
"reflect"
@ -40,7 +41,7 @@ func abapEnvironmentCheckoutBranch(options abapEnvironmentCheckoutBranchOptions,
}
}
func runAbapEnvironmentCheckoutBranch(options *abapEnvironmentCheckoutBranchOptions, telemetryData *telemetry.CustomData, com abaputils.Communication, client piperhttp.Sender) error {
func runAbapEnvironmentCheckoutBranch(options *abapEnvironmentCheckoutBranchOptions, telemetryData *telemetry.CustomData, com abaputils.Communication, client piperhttp.Sender) (err error) {
// Mapping for options
subOptions := abaputils.AbapEnvironmentOptions{}
@ -74,38 +75,44 @@ func runAbapEnvironmentCheckoutBranch(options *abapEnvironmentCheckoutBranchOpti
client.SetOptions(clientOptions)
pollIntervall := com.GetPollIntervall()
log.Entry().Infof("Starting to switch branch to branch '%v' on repository '%v'", options.BranchName, options.RepositoryName)
log.Entry().Info("--------------------------------")
log.Entry().Info("Start checkout branch: " + options.BranchName)
log.Entry().Info("--------------------------------")
repositories := []abaputils.Repository{}
err = checkCheckoutBranchRepositoryConfiguration(*options)
// Triggering the Checkout of the repository into the ABAP Environment system
uriConnectionDetails, errorTriggerCheckout := triggerCheckout(options.RepositoryName, options.BranchName, connectionDetails, client)
if errorTriggerCheckout != nil {
log.Entry().WithError(errorTriggerCheckout).Fatal("Checkout of " + options.BranchName + " for software component " + options.RepositoryName + " failed on the ABAP System")
if err == nil {
repositories, err = abaputils.GetRepositories(&abaputils.RepositoriesConfig{BranchName: options.BranchName, RepositoryName: options.RepositoryName, Repositories: options.Repositories})
}
// Polling the status of the repository import on the ABAP Environment system
status, errorPollEntity := abaputils.PollEntity(options.RepositoryName, uriConnectionDetails, client, pollIntervall)
if errorPollEntity != nil {
log.Entry().WithError(errorPollEntity).Fatal("Status of checkout action on repository" + options.RepositoryName + " failed on the ABAP System")
if err == nil {
err = checkoutBranches(repositories, connectionDetails, client, pollIntervall)
}
if status == "E" {
log.Entry().Fatal("Checkout of branch " + options.BranchName + " failed on the ABAP System")
if err != nil {
return fmt.Errorf("Something failed during the checkout: %w", err)
}
log.Entry().Info("--------------------------------")
log.Entry().Infof("Checkout of branch %v on repository %v was successful", options.BranchName, options.RepositoryName)
log.Entry().Info("--------------------------------")
log.Entry().Info("-------------------------")
log.Entry().Info("All branches were checked out successfully")
return nil
}
func triggerCheckout(repositoryName string, branchName string, checkoutConnectionDetails abaputils.ConnectionDetailsHTTP, client piperhttp.Sender) (abaputils.ConnectionDetailsHTTP, error) {
func checkoutBranches(repositories []abaputils.Repository, checkoutConnectionDetails abaputils.ConnectionDetailsHTTP, client piperhttp.Sender, pollIntervall time.Duration) (err error) {
log.Entry().Infof("Start switching of %v branches", len(repositories))
for _, repo := range repositories {
err = handleCheckout(repo, checkoutConnectionDetails, client, pollIntervall)
if err != nil {
break
}
finishCheckoutLogs(repo.Branch, repo.Name)
}
return err
}
func triggerCheckout(repositoryName string, branchName string, checkoutConnectionDetails abaputils.ConnectionDetailsHTTP, client piperhttp.Sender) (abaputils.ConnectionDetailsHTTP, error) {
uriConnectionDetails := checkoutConnectionDetails
uriConnectionDetails.URL = ""
checkoutConnectionDetails.XCsrfToken = "fetch"
if repositoryName == "" || branchName == "" {
return uriConnectionDetails, 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"))
}
// Loging into the ABAP System - getting the x-csrf-token and cookies
resp, err := abaputils.GetHTTPResponse("HEAD", checkoutConnectionDetails, nil, client)
if err != nil {
@ -128,7 +135,7 @@ func triggerCheckout(repositoryName string, branchName string, checkoutConnectio
return uriConnectionDetails, err
}
defer resp.Body.Close()
log.Entry().WithField("StatusCode", resp.Status).WithField("repositoryName", repositoryName).WithField("branchName", branchName).Info("Triggered checkout of branch")
log.Entry().WithField("StatusCode", resp.StatusCode).WithField("repositoryName", repositoryName).WithField("branchName", branchName).Info("Triggered checkout of branch")
// Parse Response
var body abaputils.PullEntity
@ -150,3 +157,59 @@ func triggerCheckout(repositoryName string, branchName string, checkoutConnectio
uriConnectionDetails.URL = body.Metadata.URI + expandLog
return uriConnectionDetails, nil
}
func checkCheckoutBranchRepositoryConfiguration(options abapEnvironmentCheckoutBranchOptions) error {
if options.Repositories == "" && options.RepositoryName == "" && options.BranchName == "" {
return fmt.Errorf("Checking configuration failed: %w", errors.New("You have not specified any repository or branch configuration to be checked out in the ABAP Environment System. Please make sure that you specified the repositories with their branches that should be checked out either in a dedicated file or via the parameters 'repositoryName' and 'branchName'. For more information please read the User documentation"))
}
if options.Repositories != "" && options.RepositoryName != "" && options.BranchName != "" {
log.Entry().Info("It seems like you have specified repositories directly via the configuration parameters 'repositoryName' and 'branchName' as well as in the dedicated repositories configuration file. Please note that in this case both configurations will be handled and checked out.")
}
if options.Repositories != "" && ((options.RepositoryName == "") != (options.BranchName == "")) {
log.Entry().Info("It seems like you have specified a dedicated repository configuration file but also a wrong configuration for the parameters 'repositoryName' and 'branchName' to be checked out.")
if options.RepositoryName != "" {
log.Entry().Info("Please also add the value for the branchName parameter or remove the repositoryName parameter.")
} else {
log.Entry().Info("Please also add the value for the repositoryName parameter or remove the branchName parameter.")
}
}
return nil
}
func handleCheckout(repo abaputils.Repository, checkoutConnectionDetails abaputils.ConnectionDetailsHTTP, client piperhttp.Sender, pollIntervall time.Duration) (err error) {
if reflect.DeepEqual(abaputils.Repository{}, repo) {
return fmt.Errorf("Failed to read repository configuration: %w", errors.New("Error in configuration, most likely you have entered empty or wrong configuration values. Please make sure that you have correctly specified the branches in the repositories to be checked out"))
}
startCheckoutLogs(repo.Branch, repo.Name)
uriConnectionDetails, err := triggerCheckout(repo.Name, repo.Branch, checkoutConnectionDetails, client)
if err != nil {
return fmt.Errorf("Failed to trigger Checkout: %w", errors.New("Checkout of "+repo.Branch+" for software component "+repo.Name+" failed on the ABAP System"))
}
// Polling the status of the repository import on the ABAP Environment system
status, err := abaputils.PollEntity(repo.Name, uriConnectionDetails, client, pollIntervall)
if err != nil {
return fmt.Errorf("Failed to poll Checkout: %w", errors.New("Status of checkout action on repository"+repo.Name+" failed on the ABAP System"))
}
const abapStatusCheckoutFail = "E"
if status == abapStatusCheckoutFail {
return fmt.Errorf("Checkout failed: %w", errors.New("Checkout of branch "+repo.Branch+" failed on the ABAP System"))
}
finishCheckoutLogs(repo.Branch, repo.Name)
return err
}
func startCheckoutLogs(branchName string, repositoryName string) {
log.Entry().Infof("Starting to switch branch to branch '%v' on repository '%v'", branchName, repositoryName)
log.Entry().Info("--------------------------------")
log.Entry().Info("Start checkout branch: " + branchName)
log.Entry().Info("--------------------------------")
}
func finishCheckoutLogs(branchName string, repositoryName string) {
log.Entry().Info("--------------------------------")
log.Entry().Infof("Checkout of branch %v on repository %v was successful", branchName, repositoryName)
log.Entry().Info("--------------------------------")
}

View File

@ -19,6 +19,7 @@ type abapEnvironmentCheckoutBranchOptions struct {
RepositoryName string `json:"repositoryName,omitempty"`
BranchName string `json:"branchName,omitempty"`
Host string `json:"host,omitempty"`
Repositories string `json:"repositories,omitempty"`
CfAPIEndpoint string `json:"cfApiEndpoint,omitempty"`
CfOrg string `json:"cfOrg,omitempty"`
CfSpace string `json:"cfSpace,omitempty"`
@ -94,6 +95,7 @@ func addAbapEnvironmentCheckoutBranchFlags(cmd *cobra.Command, stepConfig *abapE
cmd.Flags().StringVar(&stepConfig.RepositoryName, "repositoryName", os.Getenv("PIPER_repositoryName"), "Specifies a Repository (Software Component) on the SAP Cloud Platform ABAP Environment system")
cmd.Flags().StringVar(&stepConfig.BranchName, "branchName", os.Getenv("PIPER_branchName"), "Specifies a Branch of a Repository (Software Component) on the SAP Cloud Platform ABAP Environment system")
cmd.Flags().StringVar(&stepConfig.Host, "host", os.Getenv("PIPER_host"), "Specifies the host address of the SAP Cloud Platform ABAP Environment system")
cmd.Flags().StringVar(&stepConfig.Repositories, "repositories", os.Getenv("PIPER_repositories"), "Specifies a YAML file containing the repositories configuration")
cmd.Flags().StringVar(&stepConfig.CfAPIEndpoint, "cfApiEndpoint", os.Getenv("PIPER_cfApiEndpoint"), "Cloud Foundry API Enpoint")
cmd.Flags().StringVar(&stepConfig.CfOrg, "cfOrg", os.Getenv("PIPER_cfOrg"), "Cloud Foundry target organization")
cmd.Flags().StringVar(&stepConfig.CfSpace, "cfSpace", os.Getenv("PIPER_cfSpace"), "Cloud Foundry target space")
@ -102,7 +104,6 @@ func addAbapEnvironmentCheckoutBranchFlags(cmd *cobra.Command, stepConfig *abapE
cmd.MarkFlagRequired("username")
cmd.MarkFlagRequired("password")
cmd.MarkFlagRequired("repositoryName")
cmd.MarkFlagRequired("branchName")
}
@ -149,7 +150,7 @@ func abapEnvironmentCheckoutBranchMetadata() config.StepData {
ResourceRef: []config.ResourceReference{},
Scope: []string{"PARAMETERS", "STAGES", "STEPS"},
Type: "string",
Mandatory: true,
Mandatory: false,
Aliases: []config.Alias{},
},
{
@ -168,6 +169,14 @@ func abapEnvironmentCheckoutBranchMetadata() config.StepData {
Mandatory: false,
Aliases: []config.Alias{},
},
{
Name: "repositories",
ResourceRef: []config.ResourceReference{},
Scope: []string{"GENERAL", "PARAMETERS", "STAGES", "STEPS"},
Type: "string",
Mandatory: false,
Aliases: []config.Alias{},
},
{
Name: "cfApiEndpoint",
ResourceRef: []config.ResourceReference{},

View File

@ -1,6 +1,8 @@
package cmd
import (
"io/ioutil"
"os"
"testing"
"github.com/SAP/jenkins-library/pkg/abaputils"
@ -9,7 +11,7 @@ import (
)
func TestCheckoutBranchStep(t *testing.T) {
t.Run("Run Step Successful", func(t *testing.T) {
t.Run("Run Step Successful - repositoryName and branchName config", func(t *testing.T) {
var autils = abaputils.AUtilsMock{}
defer autils.Cleanup()
@ -43,10 +45,220 @@ func TestCheckoutBranchStep(t *testing.T) {
err := runAbapEnvironmentCheckoutBranch(&config, nil, &autils, client)
assert.NoError(t, err, "Did not expect error")
})
t.Run("Run Step Failure - empty config", func(t *testing.T) {
expectedErrorMessage := "Something failed during the checkout: Checking configuration failed: You have not specified any repository or branch configuration to be checked out in the ABAP Environment System. Please make sure that you specified the repositories with their branches that should be checked out either in a dedicated file or via the parameters 'repositoryName' and 'branchName'. For more information please read the User documentation"
var autils = abaputils.AUtilsMock{}
defer autils.Cleanup()
autils.ReturnedConnectionDetailsHTTP.Password = "password"
autils.ReturnedConnectionDetailsHTTP.User = "user"
autils.ReturnedConnectionDetailsHTTP.URL = "https://example.com"
autils.ReturnedConnectionDetailsHTTP.XCsrfToken = "xcsrftoken"
config := abapEnvironmentCheckoutBranchOptions{}
client := &abaputils.ClientMock{
BodyList: []string{
`{"d" : { "status" : "E" } }`,
`{"d" : { "status" : "E" } }`,
`{"d" : { "status" : "E" } }`,
},
Token: "myToken",
StatusCode: 200,
}
err := runAbapEnvironmentCheckoutBranch(&config, nil, &autils, client)
assert.EqualError(t, err, expectedErrorMessage)
})
t.Run("Run Step Failure - wrong status", func(t *testing.T) {
expectedErrorMessage := "Something failed during the checkout: Checkout failed: Checkout of branch testBranch failed on the ABAP System"
var autils = abaputils.AUtilsMock{}
defer autils.Cleanup()
autils.ReturnedConnectionDetailsHTTP.Password = "password"
autils.ReturnedConnectionDetailsHTTP.User = "user"
autils.ReturnedConnectionDetailsHTTP.URL = "https://example.com"
autils.ReturnedConnectionDetailsHTTP.XCsrfToken = "xcsrftoken"
config := abapEnvironmentCheckoutBranchOptions{
CfAPIEndpoint: "https://api.endpoint.com",
CfOrg: "testOrg",
CfSpace: "testSpace",
CfServiceInstance: "testInstance",
CfServiceKeyName: "testServiceKey",
Username: "testUser",
Password: "testPassword",
RepositoryName: "testRepo1",
BranchName: "testBranch",
}
client := &abaputils.ClientMock{
BodyList: []string{
`{"d" : { "status" : "E" } }`,
`{"d" : { "status" : "E" } }`,
`{"d" : { "status" : "E" } }`,
},
Token: "myToken",
StatusCode: 200,
}
err := runAbapEnvironmentCheckoutBranch(&config, nil, &autils, client)
assert.EqualError(t, err, expectedErrorMessage)
})
t.Run("Success case: checkout Branches from file config", func(t *testing.T) {
var autils = abaputils.AUtilsMock{}
defer autils.Cleanup()
autils.ReturnedConnectionDetailsHTTP.Password = "password"
autils.ReturnedConnectionDetailsHTTP.User = "user"
autils.ReturnedConnectionDetailsHTTP.URL = "https://example.com"
autils.ReturnedConnectionDetailsHTTP.XCsrfToken = "xcsrftoken"
receivedURI := "example.com/Branches"
client := &abaputils.ClientMock{
Body: `{"d" : { "__metadata" : { "uri" : "` + receivedURI + `" } } }`,
Token: "myToken",
StatusCode: 200,
}
dir, err := ioutil.TempDir("", "test checkout branches")
if err != nil {
t.Fatal("Failed to create temporary directory")
}
oldCWD, _ := os.Getwd()
_ = os.Chdir(dir)
// clean up tmp dir
defer func() {
_ = os.Chdir(oldCWD)
_ = os.RemoveAll(dir)
}()
manifestFileString := `
repositories:
- name: 'testRepo'
branch: 'testBranch'
- name: 'testRepo2'
branch: 'testBranch2'
- name: 'testRepo3'
branch: 'testBranch3'`
err = ioutil.WriteFile("repositoriesTest.yml", []byte(manifestFileString), 0644)
config := abapEnvironmentCheckoutBranchOptions{
CfAPIEndpoint: "https://api.endpoint.com",
CfOrg: "testOrg",
CfSpace: "testSpace",
CfServiceInstance: "testInstance",
CfServiceKeyName: "testServiceKey",
Username: "testUser",
Password: "testPassword",
Repositories: "repositoriesTest.yml",
}
err = runAbapEnvironmentCheckoutBranch(&config, nil, &autils, client)
assert.NoError(t, err)
})
t.Run("Failure case: checkout Branches from empty file config", func(t *testing.T) {
expectedErrorMessage := "Something failed during the checkout: Error in config file repositoriesTest.yml, AddonDescriptor doesn't contain any repositories"
var autils = abaputils.AUtilsMock{}
defer autils.Cleanup()
autils.ReturnedConnectionDetailsHTTP.Password = "password"
autils.ReturnedConnectionDetailsHTTP.User = "user"
autils.ReturnedConnectionDetailsHTTP.URL = "https://example.com"
autils.ReturnedConnectionDetailsHTTP.XCsrfToken = "xcsrftoken"
receivedURI := "example.com/Branches"
client := &abaputils.ClientMock{
Body: `{"d" : { "__metadata" : { "uri" : "` + receivedURI + `" } } }`,
Token: "myToken",
StatusCode: 200,
}
dir, err := ioutil.TempDir("", "test checkout branches")
if err != nil {
t.Fatal("Failed to create temporary directory")
}
oldCWD, _ := os.Getwd()
_ = os.Chdir(dir)
// clean up tmp dir
defer func() {
_ = os.Chdir(oldCWD)
_ = os.RemoveAll(dir)
}()
manifestFileString := ``
manifestFileStringBody := []byte(manifestFileString)
err = ioutil.WriteFile("repositoriesTest.yml", manifestFileStringBody, 0644)
config := abapEnvironmentCheckoutBranchOptions{
CfAPIEndpoint: "https://api.endpoint.com",
CfOrg: "testOrg",
CfSpace: "testSpace",
CfServiceInstance: "testInstance",
CfServiceKeyName: "testServiceKey",
Username: "testUser",
Password: "testPassword",
Repositories: "repositoriesTest.yml",
}
err = runAbapEnvironmentCheckoutBranch(&config, nil, &autils, client)
assert.EqualError(t, err, expectedErrorMessage)
})
t.Run("Failure case: checkout Branches from wrong file config", func(t *testing.T) {
expectedErrorMessage := "Something failed during the checkout: Could not unmarshal repositoriesTest.yml"
var autils = abaputils.AUtilsMock{}
defer autils.Cleanup()
autils.ReturnedConnectionDetailsHTTP.Password = "password"
autils.ReturnedConnectionDetailsHTTP.User = "user"
autils.ReturnedConnectionDetailsHTTP.URL = "https://example.com"
autils.ReturnedConnectionDetailsHTTP.XCsrfToken = "xcsrftoken"
pollIntervall := abaputils.AUtilsMock{}
defer pollIntervall.Cleanup()
receivedURI := "example.com/Branches"
client := &abaputils.ClientMock{
Body: `{"d" : { "__metadata" : { "uri" : "` + receivedURI + `" } } }`,
Token: "myToken",
StatusCode: 200,
}
dir, err := ioutil.TempDir("", "test checkout branches")
if err != nil {
t.Fatal("Failed to create temporary directory")
}
oldCWD, _ := os.Getwd()
_ = os.Chdir(dir)
// clean up tmp dir
defer func() {
_ = os.Chdir(oldCWD)
_ = os.RemoveAll(dir)
}()
manifestFileString := `
- repo: 'testRepo'
- repo: 'testRepo2'`
manifestFileStringBody := []byte(manifestFileString)
err = ioutil.WriteFile("repositoriesTest.yml", manifestFileStringBody, 0644)
config := abapEnvironmentCheckoutBranchOptions{
CfAPIEndpoint: "https://api.endpoint.com",
CfOrg: "testOrg",
CfSpace: "testSpace",
CfServiceInstance: "testInstance",
CfServiceKeyName: "testServiceKey",
Username: "testUser",
Password: "testPassword",
Repositories: "repositoriesTest.yml",
}
err = runAbapEnvironmentCheckoutBranch(&config, nil, &autils, client)
assert.EqualError(t, err, expectedErrorMessage)
})
}
func TestTriggerCheckout(t *testing.T) {
t.Run("Test trigger checkout: success case", func(t *testing.T) {
// given
@ -122,3 +334,29 @@ func TestTriggerCheckout(t *testing.T) {
assert.Equal(t, combinedErrorMessage, err.Error(), "Different error message expected")
})
}
func TestCheckoutConfigChecker(t *testing.T) {
t.Run("Success case: check config", func(t *testing.T) {
config := abapEnvironmentCheckoutBranchOptions{
RepositoryName: "testRepo1",
BranchName: "feature-unit-test",
}
err := checkCheckoutBranchRepositoryConfiguration(config)
assert.NoError(t, err)
})
t.Run("Success case: check file config", func(t *testing.T) {
config := abapEnvironmentCheckoutBranchOptions{
Repositories: "test.file",
BranchName: "feature-unit-test",
}
err := checkCheckoutBranchRepositoryConfiguration(config)
assert.NoError(t, err)
})
t.Run("Failure case: check empty config", func(t *testing.T) {
expectedErrorMessage := "Checking configuration failed: You have not specified any repository or branch configuration to be checked out in the ABAP Environment System. Please make sure that you specified the repositories with their branches that should be checked out either in a dedicated file or via the parameters 'repositoryName' and 'branchName'. For more information please read the User documentation"
config := abapEnvironmentCheckoutBranchOptions{}
err := checkCheckoutBranchRepositoryConfiguration(config)
assert.Equal(t, expectedErrorMessage, err.Error(), "Different error message expected")
})
}

View File

@ -2,6 +2,7 @@ package cmd
import (
"encoding/json"
"fmt"
"io/ioutil"
"net/http/cookiejar"
"reflect"
@ -63,9 +64,9 @@ func runAbapEnvironmentCloneGitRepo(config *abapEnvironmentCloneGitRepoOptions,
Password: connectionDetails.Password,
})
repositories, errGetRepos := getRepositories(config)
repositories, errGetRepos := abaputils.GetRepositories(&abaputils.RepositoriesConfig{BranchName: config.BranchName, RepositoryName: config.RepositoryName, Repositories: config.Repositories})
if errGetRepos != nil {
return errGetRepos
return fmt.Errorf("Something failed during the clone: %w", errGetRepos)
}
log.Entry().Infof("Start cloning %v repositories", len(repositories))
@ -152,21 +153,6 @@ func triggerClone(repositoryName string, branchName string, cloneConnectionDetai
return uriConnectionDetails, nil
}
func getRepositories(config *abapEnvironmentCloneGitRepoOptions) ([]abaputils.Repository, error) {
var repositories = make([]abaputils.Repository, 0)
if config.Repositories != "" {
descriptor, err := abaputils.ReadAddonDescriptor(config.Repositories)
if err != nil {
return nil, err
}
repositories = descriptor.Repositories
}
if config.RepositoryName != "" && config.BranchName != "" {
repositories = append(repositories, abaputils.Repository{Name: config.RepositoryName, Branch: config.BranchName})
}
return repositories, nil
}
func convertConfig(config *abapEnvironmentCloneGitRepoOptions) abaputils.AbapEnvironmentOptions {
subOptions := abaputils.AbapEnvironmentOptions{}

View File

@ -147,7 +147,7 @@ func abapEnvironmentCloneGitRepoMetadata() config.StepData {
{
Name: "repositories",
ResourceRef: []config.ResourceReference{},
Scope: []string{"PARAMETERS", "STAGES", "STEPS"},
Scope: []string{"GENERAL", "PARAMETERS", "STAGES", "STEPS"},
Type: "string",
Mandatory: false,
Aliases: []config.Alias{},

View File

@ -258,7 +258,7 @@ func TestCloneStepErrorMessages(t *testing.T) {
err := runAbapEnvironmentCloneGitRepo(&config, nil, &autils, client)
if assert.Error(t, err, "Expected error") {
assert.Equal(t, "Could not find filename.yaml", err.Error(), "Expected different error message")
assert.Equal(t, "Something failed during the clone: Could not find filename.yaml", err.Error(), "Expected different error message")
}
})

View File

@ -2,6 +2,7 @@ package cmd
import (
"encoding/json"
"fmt"
"io/ioutil"
"net/http/cookiejar"
"reflect"
@ -40,9 +41,7 @@ func abapEnvironmentPullGitRepo(options abapEnvironmentPullGitRepoOptions, telem
}
}
func runAbapEnvironmentPullGitRepo(options *abapEnvironmentPullGitRepoOptions, telemetryData *telemetry.CustomData, com abaputils.Communication, client piperhttp.Sender) error {
// Mapping for options
func runAbapEnvironmentPullGitRepo(options *abapEnvironmentPullGitRepoOptions, telemetryData *telemetry.CustomData, com abaputils.Communication, client piperhttp.Sender) (err error) {
subOptions := abaputils.AbapEnvironmentOptions{}
subOptions.CfAPIEndpoint = options.CfAPIEndpoint
@ -55,16 +54,14 @@ func runAbapEnvironmentPullGitRepo(options *abapEnvironmentPullGitRepoOptions, t
subOptions.Username = options.Username
// Determine the host, user and password, either via the input parameters or via a cloud foundry service key
connectionDetails, errorGetInfo := com.GetAbapCommunicationArrangementInfo(subOptions, "/sap/opu/odata/sap/MANAGE_GIT_REPOSITORY/Pull")
if errorGetInfo != nil {
return errors.Wrap(errorGetInfo, "Parameters for the ABAP Connection not available")
connectionDetails, err := com.GetAbapCommunicationArrangementInfo(subOptions, "/sap/opu/odata/sap/MANAGE_GIT_REPOSITORY/Pull")
if err != nil {
return errors.Wrap(err, "Parameters for the ABAP Connection not available")
}
// Configuring the HTTP Client and CookieJar
cookieJar, errorCookieJar := cookiejar.New(nil)
if errorCookieJar != nil {
return errors.Wrap(errorCookieJar, "Could not create a Cookie Jar")
cookieJar, err := cookiejar.New(nil)
if err != nil {
return errors.Wrap(err, "Could not create a Cookie Jar")
}
clientOptions := piperhttp.ClientOptions{
MaxRequestDuration: 180 * time.Second,
@ -75,34 +72,36 @@ func runAbapEnvironmentPullGitRepo(options *abapEnvironmentPullGitRepoOptions, t
client.SetOptions(clientOptions)
pollIntervall := com.GetPollIntervall()
log.Entry().Infof("Start pulling %v repositories", len(options.RepositoryNames))
for _, repositoryName := range options.RepositoryNames {
repositories := []abaputils.Repository{}
err = checkPullRepositoryConfiguration(*options)
log.Entry().Info("-------------------------")
log.Entry().Info("Start pulling " + repositoryName)
log.Entry().Info("-------------------------")
// Triggering the Pull of the repository into the ABAP Environment system
uriConnectionDetails, errorTriggerPull := triggerPull(repositoryName, connectionDetails, client)
if errorTriggerPull != nil {
return errors.Wrapf(errorTriggerPull, "Pull of '%s' failed on the ABAP System", repositoryName)
}
// Polling the status of the repository import on the ABAP Environment system
status, errorPollEntity := abaputils.PollEntity(repositoryName, uriConnectionDetails, client, pollIntervall)
if errorPollEntity != nil {
return errors.Wrapf(errorPollEntity, "Pull of '%s' failed on the ABAP System", repositoryName)
}
if status == "E" {
return errors.New("Pull of " + repositoryName + " failed on the ABAP System")
}
log.Entry().Info(repositoryName + " was pulled successfully")
if err == nil {
repositories, err = abaputils.GetRepositories(&abaputils.RepositoriesConfig{RepositoryNames: options.RepositoryNames, Repositories: options.Repositories})
}
if err == nil {
err = pullRepositories(repositories, connectionDetails, client, pollIntervall)
}
if err != nil {
return fmt.Errorf("Something failed during the pull of the repositories: %w", err)
}
log.Entry().Info("-------------------------")
log.Entry().Info("All repositories were pulled successfully")
return nil
return err
}
func pullRepositories(repositories []abaputils.Repository, pullConnectionDetails abaputils.ConnectionDetailsHTTP, client piperhttp.Sender, pollIntervall time.Duration) (err error) {
log.Entry().Infof("Start cloning %v repositories", len(repositories))
for _, repo := range repositories {
err = handlePull(repo, pullConnectionDetails, client, pollIntervall)
if err != nil {
break
}
finishPullLogs()
}
return err
}
func triggerPull(repositoryName string, pullConnectionDetails abaputils.ConnectionDetailsHTTP, client piperhttp.Sender) (abaputils.ConnectionDetailsHTTP, error) {
@ -154,3 +153,44 @@ func triggerPull(repositoryName string, pullConnectionDetails abaputils.Connecti
uriConnectionDetails.URL = body.Metadata.URI + expandLog
return uriConnectionDetails, nil
}
func checkPullRepositoryConfiguration(options abapEnvironmentPullGitRepoOptions) error {
if len(options.RepositoryNames) > 0 && options.Repositories != "" {
log.Entry().Info("It seems like you have specified repositories directly via the configuration parameter 'repositoryNames' as well as in the dedicated repositories configuration file. Please note that in this case both configurations will be handled and pulled.")
}
if len(options.RepositoryNames) == 0 && options.Repositories == "" {
return fmt.Errorf("Checking configuration failed: %w", errors.New("You have not specified any repository configuration to be pulled into the ABAP Environment System. Please make sure that you specified the repositories that should be pulled either in a dedicated file or via the parameter 'repositoryNames'. For more information please read the User documentation"))
}
return nil
}
func handlePull(repo abaputils.Repository, pullConnectionDetails abaputils.ConnectionDetailsHTTP, client piperhttp.Sender, pollIntervall time.Duration) (err error) {
startPullLogs(repo.Branch)
uriConnectionDetails, err := triggerPull(repo.Name, pullConnectionDetails, client)
if err != nil {
return errors.Wrapf(err, "Pull of '%s' failed on the ABAP System", repo.Name)
}
// Polling the status of the repository import on the ABAP Environment system
status, errorPollEntity := abaputils.PollEntity(repo.Name, uriConnectionDetails, client, pollIntervall)
if errorPollEntity != nil {
return errors.Wrapf(errorPollEntity, "Pull of '%s' failed on the ABAP System", repo.Name)
}
if status == "E" {
return errors.New("Pull of " + repo.Name + " failed on the ABAP System")
}
log.Entry().Info(repo.Name + " was pulled successfully")
return err
}
func startPullLogs(repositoryName string) {
log.Entry().Info("-------------------------")
log.Entry().Info("Start pulling " + repositoryName)
log.Entry().Info("-------------------------")
}
func finishPullLogs() {
log.Entry().Info("-------------------------")
log.Entry().Info("All repositories were pulled successfully")
}

View File

@ -17,6 +17,7 @@ type abapEnvironmentPullGitRepoOptions struct {
Username string `json:"username,omitempty"`
Password string `json:"password,omitempty"`
RepositoryNames []string `json:"repositoryNames,omitempty"`
Repositories string `json:"repositories,omitempty"`
Host string `json:"host,omitempty"`
CfAPIEndpoint string `json:"cfApiEndpoint,omitempty"`
CfOrg string `json:"cfOrg,omitempty"`
@ -91,6 +92,7 @@ func addAbapEnvironmentPullGitRepoFlags(cmd *cobra.Command, stepConfig *abapEnvi
cmd.Flags().StringVar(&stepConfig.Username, "username", os.Getenv("PIPER_username"), "User for either the Cloud Foundry API or the Communication Arrangement for SAP_COM_0510")
cmd.Flags().StringVar(&stepConfig.Password, "password", os.Getenv("PIPER_password"), "Password for either the Cloud Foundry API or the Communication Arrangement for SAP_COM_0510")
cmd.Flags().StringSliceVar(&stepConfig.RepositoryNames, "repositoryNames", []string{}, "Specifies a list of Repositories (Software Components) on the SAP Cloud Platform ABAP Environment system")
cmd.Flags().StringVar(&stepConfig.Repositories, "repositories", os.Getenv("PIPER_repositories"), "Specifies a YAML file containing the repositories configuration")
cmd.Flags().StringVar(&stepConfig.Host, "host", os.Getenv("PIPER_host"), "Specifies the host address of the SAP Cloud Platform ABAP Environment system")
cmd.Flags().StringVar(&stepConfig.CfAPIEndpoint, "cfApiEndpoint", os.Getenv("PIPER_cfApiEndpoint"), "Cloud Foundry API Enpoint")
cmd.Flags().StringVar(&stepConfig.CfOrg, "cfOrg", os.Getenv("PIPER_cfOrg"), "Cloud Foundry target organization")
@ -100,7 +102,6 @@ func addAbapEnvironmentPullGitRepoFlags(cmd *cobra.Command, stepConfig *abapEnvi
cmd.MarkFlagRequired("username")
cmd.MarkFlagRequired("password")
cmd.MarkFlagRequired("repositoryNames")
}
// retrieve step metadata
@ -146,7 +147,15 @@ func abapEnvironmentPullGitRepoMetadata() config.StepData {
ResourceRef: []config.ResourceReference{},
Scope: []string{"PARAMETERS", "STAGES", "STEPS"},
Type: "[]string",
Mandatory: true,
Mandatory: false,
Aliases: []config.Alias{},
},
{
Name: "repositories",
ResourceRef: []config.ResourceReference{},
Scope: []string{"GENERAL", "PARAMETERS", "STAGES", "STEPS"},
Type: "string",
Mandatory: false,
Aliases: []config.Alias{},
},
{

View File

@ -1,6 +1,8 @@
package cmd
import (
"io/ioutil"
"os"
"testing"
"github.com/SAP/jenkins-library/pkg/abaputils"
@ -44,6 +46,180 @@ func TestPullStep(t *testing.T) {
err := runAbapEnvironmentPullGitRepo(&config, nil, &autils, client)
assert.NoError(t, err, "Did not expect error")
})
t.Run("Run Step Failure", func(t *testing.T) {
expectedErrorMessage := "Something failed during the pull of the repositories: Checking configuration failed: You have not specified any repository configuration to be pulled into the ABAP Environment System. Please make sure that you specified the repositories that should be pulled either in a dedicated file or via the parameter 'repositoryNames'. For more information please read the User documentation"
var autils = abaputils.AUtilsMock{}
defer autils.Cleanup()
autils.ReturnedConnectionDetailsHTTP.Password = "password"
autils.ReturnedConnectionDetailsHTTP.User = "user"
autils.ReturnedConnectionDetailsHTTP.URL = "https://example.com"
autils.ReturnedConnectionDetailsHTTP.XCsrfToken = "xcsrftoken"
receivedURI := "example.com/Entity"
tokenExpected := "myToken"
client := &abaputils.ClientMock{
Body: `{"d" : { "__metadata" : { "uri" : "` + receivedURI + `" } } }`,
Token: tokenExpected,
StatusCode: 200,
}
config := abapEnvironmentPullGitRepoOptions{}
err := runAbapEnvironmentPullGitRepo(&config, nil, &autils, client)
assert.Equal(t, expectedErrorMessage, err.Error(), "Different error message expected")
})
t.Run("Success case: pull repos from file config", func(t *testing.T) {
var autils = abaputils.AUtilsMock{}
defer autils.Cleanup()
autils.ReturnedConnectionDetailsHTTP.Password = "password"
autils.ReturnedConnectionDetailsHTTP.User = "user"
autils.ReturnedConnectionDetailsHTTP.URL = "https://example.com"
autils.ReturnedConnectionDetailsHTTP.XCsrfToken = "xcsrftoken"
receivedURI := "example.com/Branches"
client := &abaputils.ClientMock{
Body: `{"d" : { "__metadata" : { "uri" : "` + receivedURI + `" } } }`,
Token: "myToken",
StatusCode: 200,
}
dir, err := ioutil.TempDir("", "test pull repos")
if err != nil {
t.Fatal("Failed to create temporary directory")
}
oldCWD, _ := os.Getwd()
_ = os.Chdir(dir)
// clean up tmp dir
defer func() {
_ = os.Chdir(oldCWD)
_ = os.RemoveAll(dir)
}()
manifestFileString := `
repositories:
- name: 'testRepo'
branch: 'testBranch'
- name: 'testRepo2'
branch: 'testBranch2'
- name: 'testRepo3'
branch: 'testBranch3'`
err = ioutil.WriteFile("repositoriesTest.yml", []byte(manifestFileString), 0644)
config := abapEnvironmentPullGitRepoOptions{
CfAPIEndpoint: "https://api.endpoint.com",
CfOrg: "testOrg",
CfSpace: "testSpace",
CfServiceInstance: "testInstance",
CfServiceKeyName: "testServiceKey",
Username: "testUser",
Password: "testPassword",
Repositories: "repositoriesTest.yml",
}
err = runAbapEnvironmentPullGitRepo(&config, nil, &autils, client)
assert.NoError(t, err)
})
t.Run("Failure case: pull repos from empty file config", func(t *testing.T) {
expectedErrorMessage := "Something failed during the pull of the repositories: Error in config file repositoriesTest.yml, AddonDescriptor doesn't contain any repositories"
var autils = abaputils.AUtilsMock{}
defer autils.Cleanup()
autils.ReturnedConnectionDetailsHTTP.Password = "password"
autils.ReturnedConnectionDetailsHTTP.User = "user"
autils.ReturnedConnectionDetailsHTTP.URL = "https://example.com"
autils.ReturnedConnectionDetailsHTTP.XCsrfToken = "xcsrftoken"
receivedURI := "example.com/Branches"
client := &abaputils.ClientMock{
Body: `{"d" : { "__metadata" : { "uri" : "` + receivedURI + `" } } }`,
Token: "myToken",
StatusCode: 200,
}
dir, err := ioutil.TempDir("", "test pull repos")
if err != nil {
t.Fatal("Failed to create temporary directory")
}
oldCWD, _ := os.Getwd()
_ = os.Chdir(dir)
// clean up tmp dir
defer func() {
_ = os.Chdir(oldCWD)
_ = os.RemoveAll(dir)
}()
manifestFileString := ``
manifestFileStringBody := []byte(manifestFileString)
err = ioutil.WriteFile("repositoriesTest.yml", manifestFileStringBody, 0644)
config := abapEnvironmentPullGitRepoOptions{
CfAPIEndpoint: "https://api.endpoint.com",
CfOrg: "testOrg",
CfSpace: "testSpace",
CfServiceInstance: "testInstance",
CfServiceKeyName: "testServiceKey",
Username: "testUser",
Password: "testPassword",
Repositories: "repositoriesTest.yml",
}
err = runAbapEnvironmentPullGitRepo(&config, nil, &autils, client)
assert.EqualError(t, err, expectedErrorMessage)
})
t.Run("Failure case: pull repos from wrong file config", func(t *testing.T) {
expectedErrorMessage := "Something failed during the pull of the repositories: Could not unmarshal repositoriesTest.yml"
var autils = abaputils.AUtilsMock{}
defer autils.Cleanup()
autils.ReturnedConnectionDetailsHTTP.Password = "password"
autils.ReturnedConnectionDetailsHTTP.User = "user"
autils.ReturnedConnectionDetailsHTTP.URL = "https://example.com"
autils.ReturnedConnectionDetailsHTTP.XCsrfToken = "xcsrftoken"
pollIntervall := abaputils.AUtilsMock{}
defer pollIntervall.Cleanup()
receivedURI := "example.com/Branches"
client := &abaputils.ClientMock{
Body: `{"d" : { "__metadata" : { "uri" : "` + receivedURI + `" } } }`,
Token: "myToken",
StatusCode: 200,
}
dir, err := ioutil.TempDir("", "test pull repos")
if err != nil {
t.Fatal("Failed to create temporary directory")
}
oldCWD, _ := os.Getwd()
_ = os.Chdir(dir)
// clean up tmp dir
defer func() {
_ = os.Chdir(oldCWD)
_ = os.RemoveAll(dir)
}()
manifestFileString := `
- repo: 'testRepo'
- repo: 'testRepo2'`
manifestFileStringBody := []byte(manifestFileString)
err = ioutil.WriteFile("repositoriesTest.yml", manifestFileStringBody, 0644)
config := abapEnvironmentPullGitRepoOptions{
CfAPIEndpoint: "https://api.endpoint.com",
CfOrg: "testOrg",
CfSpace: "testSpace",
CfServiceInstance: "testInstance",
CfServiceKeyName: "testServiceKey",
Username: "testUser",
Password: "testPassword",
Repositories: "repositoriesTest.yml",
}
err = runAbapEnvironmentPullGitRepo(&config, nil, &autils, client)
assert.EqualError(t, err, expectedErrorMessage)
})
}
func TestTriggerPull(t *testing.T) {
@ -113,5 +289,27 @@ func TestTriggerPull(t *testing.T) {
_, err := triggerPull(config.RepositoryNames[0], con, client)
assert.Equal(t, combinedErrorMessage, err.Error(), "Different error message expected")
})
}
func TestPullConfigChecker(t *testing.T) {
t.Run("Success case: check config file", func(t *testing.T) {
config := abapEnvironmentPullGitRepoOptions{
Repositories: "test.file",
}
err := checkPullRepositoryConfiguration(config)
assert.NoError(t, err)
})
t.Run("Success case: check config", func(t *testing.T) {
config := abapEnvironmentPullGitRepoOptions{
RepositoryNames: []string{"testRepo", "testRepo2"},
}
err := checkPullRepositoryConfiguration(config)
assert.NoError(t, err)
})
t.Run("Failure case: empty config", func(t *testing.T) {
errorMessage := "Checking configuration failed: You have not specified any repository configuration to be pulled into the ABAP Environment System. Please make sure that you specified the repositories that should be pulled either in a dedicated file or via the parameter 'repositoryNames'. For more information please read the User documentation"
config := abapEnvironmentPullGitRepoOptions{}
err := checkPullRepositoryConfiguration(config)
assert.Equal(t, errorMessage, err.Error(), "Different error message expected")
})
}

View File

@ -32,8 +32,32 @@ steps:
abapCredentialsId: 'abapCredentialsId'
host: '1234-abcd-5678-efgh-ijk.abap.eu10.hana.ondemand.com'
```
Please note that the branchName parameter specifies the target branch you want to switch on. Also keep in mind that the repositoryName parameter must define a single repository.
Also you can specify a dedicated file, e.g. `repositories.yml` containing a list of repositories and the respective branches you want to switch on:
```yaml
steps:
abapEnvironmentCheckoutBranch:
repositories: 'repositories.yml'
abapCredentialsId: 'abapCredentialsId'
host: '1234-abcd-5678-efgh-ijk.abap.eu10.hana.ondemand.com'
```
The associated config file, e.g. `repositories.yml` could look as follows:
```yaml
repositories:
- name: '/DMO/GIT_REPOSITORY'
branch: 'master'
- name: '/DMO/GIT_REPO'
branch: 'master'
```
Please note that you need to use the YAML data structure as in the example above when using the `repositories.yml` config file.
For this step it is mandatory to fill the branch values. You can also use this file for the abapEnvironmentPullGitRepo step.
If you want to read the host and credentials from the cloud foundry service key of the respective instance, the configuration could look as follows:
```yaml

View File

@ -24,7 +24,6 @@ abapEnvironmentPullGitRepo script: this
If you want to provide the host and credentials of the Communication Arrangement directly, the configuration could look as follows:
```yaml
steps:
abapEnvironmentPullGitRepo:
repositoryNames: ['/DMO/GIT_REPOSITORY']
@ -32,6 +31,29 @@ steps:
host: '1234-abcd-5678-efgh-ijk.abap.eu10.hana.ondemand.com'
```
Also you can specify a dedicated file, e.g. `repositories.yml` containing the repositories to be pulled:
```yaml
steps:
abapEnvironmentPullGitRepo:
repositories: 'repositories.yml'
abapCredentialsId: 'abapCredentialsId'
host: '1234-abcd-5678-efgh-ijk.abap.eu10.hana.ondemand.com'
```
The associated config file, e.g. `repositories.yml` could look as follows:
```yaml
repositories:
- name: '/DMO/GIT_REPOSITORY'
branch: 'master'
- name: '/DMO/GIT_REPO'
branch: 'master'
```
Please note that you need to adapt the file structure according to the structure in this example in order to work.
It is possible to leave the branch value out. However if you also want to use this file for the abapEnvironmentCheckoutBranch step it is recommended to follow above structure.
If you want to read the host and credentials from the cloud foundry service key of the respective instance, the configuration could look as follows:
```yaml

View File

@ -116,6 +116,7 @@ func TestCloudFoundryGetAbapCommunicationInfo(t *testing.T) {
assert.NoError(t, err)
})
}
func TestHostGetAbapCommunicationInfo(t *testing.T) {
t.Run("HOST GetAbapCommunicationArrangementInfo - Success", func(t *testing.T) {
@ -192,6 +193,7 @@ func TestHostGetAbapCommunicationInfo(t *testing.T) {
assert.NoError(t, err)
})
}
func TestReadServiceKeyAbapEnvironment(t *testing.T) {
t.Run("CF ReadServiceKeyAbapEnvironment - Failed to login to Cloud Foundry", func(t *testing.T) {
@ -300,11 +302,62 @@ repositories:
assert.Equal(t, `2.1.1`, addonDescriptor.Repositories[1].VersionYAML)
assert.Equal(t, ``, addonDescriptor.Repositories[0].SpLevel)
assert.Equal(t, ``, addonDescriptor.Repositories[1].SpLevel)
})
err = CheckAddonDescriptorForRepositories(addonDescriptor)
assert.NoError(t, err)
})
t.Run("Test: file does not exist", func(t *testing.T) {
_, err := ReadAddonDescriptor("filename.yaml")
expectedErrorMessage := "AddonDescriptor doesn't contain any repositories"
addonDescriptor, err := ReadAddonDescriptor("filename.yaml")
assert.EqualError(t, err, fmt.Sprintf("Could not find %v", "filename.yaml"))
assert.Equal(t, AddonDescriptor{}, addonDescriptor)
err = CheckAddonDescriptorForRepositories(addonDescriptor)
assert.EqualError(t, err, expectedErrorMessage)
})
t.Run("Test: empty config - failure case", func(t *testing.T) {
expectedErrorMessage := "AddonDescriptor doesn't contain any repositories"
addonDescriptor, err := ReadAddonDescriptor("")
assert.EqualError(t, err, fmt.Sprintf("Could not find %v", ""))
assert.Equal(t, AddonDescriptor{}, addonDescriptor)
err = CheckAddonDescriptorForRepositories(addonDescriptor)
assert.EqualError(t, err, expectedErrorMessage)
})
t.Run("Read empty addon descriptor from wrong config - failure case", func(t *testing.T) {
expectedErrorMessage := "AddonDescriptor doesn't contain any repositories"
expectedRepositoryList := AddonDescriptor{Repositories: []Repository{{}, {}}}
dir, err := ioutil.TempDir("", "test abap utils")
if err != nil {
t.Fatal("Failed to create temporary directory")
}
oldCWD, _ := os.Getwd()
_ = os.Chdir(dir)
// clean up tmp dir
defer func() {
_ = os.Chdir(oldCWD)
_ = os.RemoveAll(dir)
}()
manifestFileString := `
repositories:
- repo: 'testRepo'
- repo: 'testRepo2'`
err = ioutil.WriteFile("repositories.yml", []byte(manifestFileString), 0644)
addonDescriptor, err := ReadAddonDescriptor("repositories.yml")
assert.Equal(t, expectedRepositoryList, addonDescriptor)
assert.NoError(t, err)
err = CheckAddonDescriptorForRepositories(addonDescriptor)
assert.EqualError(t, err, expectedErrorMessage)
})
}

View File

@ -5,6 +5,7 @@ import (
"fmt"
"io/ioutil"
"path/filepath"
"reflect"
"github.com/ghodss/yaml"
"github.com/pkg/errors"
@ -89,6 +90,25 @@ func (me *AddonDescriptor) initFromYmlFile(FileName string) error {
return nil
}
// CheckAddonDescriptorForRepositories checks AddonDescriptor struct if it contains any repositories. If not it will return an error
func CheckAddonDescriptorForRepositories(addonDescriptor AddonDescriptor) error {
//checking if parsing went wrong
if len(addonDescriptor.Repositories) == 0 {
return errors.New(fmt.Sprintf("AddonDescriptor doesn't contain any repositories"))
}
//
emptyRepositoryCounter := 0
for counter, repo := range addonDescriptor.Repositories {
if reflect.DeepEqual(Repository{}, repo) {
emptyRepositoryCounter++
}
if counter+1 == len(addonDescriptor.Repositories) && emptyRepositoryCounter == len(addonDescriptor.Repositories) {
return errors.New(fmt.Sprintf("AddonDescriptor doesn't contain any repositories"))
}
}
return nil
}
// initFromJSON : Init from json
func (me *AddonDescriptor) initFromJSON(JSON []byte) error {
return json.Unmarshal(JSON, me)

View File

@ -2,6 +2,7 @@ package abaputils
import (
"encoding/json"
"fmt"
"io/ioutil"
"reflect"
"sort"
@ -80,6 +81,37 @@ func PrintLogs(entity PullEntity) {
log.Entry().Info("-------------------------")
}
//GetRepositories for parsing one or multiple branches and repositories from repositories file or branchName and repositoryName configuration
func GetRepositories(config *RepositoriesConfig) ([]Repository, error) {
var repositories = make([]Repository, 0)
if reflect.DeepEqual(RepositoriesConfig{}, config) {
return repositories, fmt.Errorf("Failed to read repository configuration: %w", errors.New("Eror in configuration, most likely you have entered empty or wrong configuration values. Please make sure that you have correctly specified them. For more information please read the User documentation"))
}
if config.RepositoryName == "" && config.BranchName == "" && config.Repositories == "" && len(config.RepositoryNames) == 0 {
return repositories, fmt.Errorf("Failed to read repository configuration: %w", errors.New("You have not specified any repository configuration. Please make sure that you have correctly specified it. For more information please read the User documentation"))
}
if config.Repositories != "" {
descriptor, err := ReadAddonDescriptor(config.Repositories)
if err != nil {
return repositories, err
}
err = CheckAddonDescriptorForRepositories(descriptor)
if err != nil {
return repositories, fmt.Errorf("Error in config file %v, %w", config.Repositories, err)
}
repositories = descriptor.Repositories
}
if config.RepositoryName != "" && config.BranchName != "" {
repositories = append(repositories, Repository{Name: config.RepositoryName, Branch: config.BranchName})
}
if len(config.RepositoryNames) > 0 {
for _, repository := range config.RepositoryNames {
repositories = append(repositories, Repository{Name: repository})
}
}
return repositories, nil
}
/****************************************
* Structs for the A4C_A2G_GHA service *
****************************************/
@ -144,3 +176,11 @@ type LogResults struct {
Description string `json:"descr"`
Timestamp string `json:"timestamp"`
}
//RepositoriesConfig struct for parsing one or multiple branches and repositories configurations
type RepositoriesConfig struct {
BranchName string
RepositoryName string
RepositoryNames []string
Repositories string
}

View File

@ -1,6 +1,8 @@
package abaputils
import (
"io/ioutil"
"os"
"testing"
"github.com/stretchr/testify/assert"
@ -80,3 +82,136 @@ func TestPollEntity(t *testing.T) {
assert.Equal(t, "E", status)
})
}
func TestGetRepositories(t *testing.T) {
t.Run("Get Repositories from config - success case", func(t *testing.T) {
expectedRepositoryList := []Repository{{
Name: "testRepo",
Branch: "testBranch",
}, {
Name: "testRepo2",
Branch: "testBranch2",
}, {
Name: "testRepo3",
Branch: "testBranch3",
}, {
Name: "testRepository",
Branch: "testBranch",
}, {
Name: "testRepository",
}}
dir, err := ioutil.TempDir("", "test abap utils")
if err != nil {
t.Fatal("Failed to create temporary directory")
}
oldCWD, _ := os.Getwd()
_ = os.Chdir(dir)
// clean up tmp dir
defer func() {
_ = os.Chdir(oldCWD)
_ = os.RemoveAll(dir)
}()
manifestFileString := `
repositories:
- name: 'testRepo'
branch: 'testBranch'
- name: 'testRepo2'
branch: 'testBranch2'
- name: 'testRepo3'
branch: 'testBranch3'`
err = ioutil.WriteFile("repositoriesTest.yml", []byte(manifestFileString), 0644)
config := RepositoriesConfig{
BranchName: "testBranch",
RepositoryName: "testRepository",
RepositoryNames: []string{"testRepository"},
Repositories: "repositoriesTest.yml",
}
repositories, err := GetRepositories(&config)
assert.Equal(t, expectedRepositoryList, repositories)
assert.NoError(t, err)
})
t.Run("Get Repositories from file config - failure case", func(t *testing.T) {
expectedRepositoryList := []Repository([]Repository{})
expectedErrorMessage := "Error in config file repositoriesTest.yml, AddonDescriptor doesn't contain any repositories"
dir, err := ioutil.TempDir("", "test abap utils")
if err != nil {
t.Fatal("Failed to create temporary directory")
}
oldCWD, _ := os.Getwd()
_ = os.Chdir(dir)
// clean up tmp dir
defer func() {
_ = os.Chdir(oldCWD)
_ = os.RemoveAll(dir)
}()
manifestFileString := `
repositories:
- repo: 'testRepo'
- repo: 'testRepo2'`
err = ioutil.WriteFile("repositoriesTest.yml", []byte(manifestFileString), 0644)
config := RepositoriesConfig{
Repositories: "repositoriesTest.yml",
}
repositories, err := GetRepositories(&config)
assert.Equal(t, expectedRepositoryList, repositories)
assert.EqualError(t, err, expectedErrorMessage)
})
t.Run("Get Repositories from config - failure case", func(t *testing.T) {
expectedRepositoryList := []Repository([]Repository{})
expectedErrorMessage := "Error in config file repositoriesTest.yml, AddonDescriptor doesn't contain any repositories"
dir, err := ioutil.TempDir("", "test abap utils")
if err != nil {
t.Fatal("Failed to create temporary directory")
}
oldCWD, _ := os.Getwd()
_ = os.Chdir(dir)
// clean up tmp dir
defer func() {
_ = os.Chdir(oldCWD)
_ = os.RemoveAll(dir)
}()
manifestFileString := `
repositories:
- repo: 'testRepo'
- repo: 'testRepo2'`
err = ioutil.WriteFile("repositoriesTest.yml", []byte(manifestFileString), 0644)
config := RepositoriesConfig{
Repositories: "repositoriesTest.yml",
}
repositories, err := GetRepositories(&config)
assert.Equal(t, expectedRepositoryList, repositories)
assert.EqualError(t, err, expectedErrorMessage)
})
t.Run("Get Repositories from empty config - failure case", func(t *testing.T) {
expectedRepositoryList := []Repository([]Repository{})
expectedErrorMessage := "Failed to read repository configuration: You have not specified any repository configuration. Please make sure that you have correctly specified it. For more information please read the User documentation"
config := RepositoriesConfig{}
repositories, err := GetRepositories(&config)
assert.Equal(t, expectedRepositoryList, repositories)
assert.EqualError(t, err, expectedErrorMessage)
})
}

View File

@ -52,7 +52,6 @@ spec:
- PARAMETERS
- STAGES
- STEPS
mandatory: true
- name: branchName
type: string
description: Specifies a Branch of a Repository (Software Component) on the SAP Cloud Platform ABAP Environment system
@ -69,6 +68,14 @@ spec:
- STAGES
- STEPS
- GENERAL
- name: repositories
type: string
description: Specifies a YAML file containing the repositories configuration
scope:
- GENERAL
- PARAMETERS
- STAGES
- STEPS
- name: cfApiEndpoint
type: string
description: Cloud Foundry API Enpoint

View File

@ -49,6 +49,7 @@ spec:
type: string
description: Specifies a YAML file containing the repositories configuration
scope:
- GENERAL
- PARAMETERS
- STAGES
- STEPS

View File

@ -52,7 +52,14 @@ spec:
- PARAMETERS
- STAGES
- STEPS
mandatory: true
- name: repositories
type: string
description: Specifies a YAML file containing the repositories configuration
scope:
- GENERAL
- PARAMETERS
- STAGES
- STEPS
- name: host
type: string
description: Specifies the host address of the SAP Cloud Platform ABAP Environment system