diff --git a/cmd/abapEnvironmentCloneGitRepo.go b/cmd/abapEnvironmentCloneGitRepo.go
index 687044dd77..71cfe60abd 100644
--- a/cmd/abapEnvironmentCloneGitRepo.go
+++ b/cmd/abapEnvironmentCloneGitRepo.go
@@ -42,7 +42,7 @@ func runAbapEnvironmentCloneGitRepo(config *abapEnvironmentCloneGitRepoOptions,
return errors.Wrap(errConfig, "The provided configuration is not allowed")
}
- repositories, errGetRepos := abaputils.GetRepositories(&abaputils.RepositoriesConfig{BranchName: config.BranchName, RepositoryName: config.RepositoryName, Repositories: config.Repositories}, false)
+ repositories, errGetRepos := abaputils.GetRepositories(&abaputils.RepositoriesConfig{BranchName: config.BranchName, RepositoryName: config.RepositoryName, Repositories: config.Repositories, ByogUsername: config.ByogUsername, ByogPassword: config.ByogPassword, ByogAuthMethod: config.ByogAuthMethod}, false)
if errGetRepos != nil {
return errors.Wrap(errGetRepos, "Could not read repositories")
}
@@ -85,12 +85,15 @@ func cloneSingleRepo(apiManager abaputils.SoftwareComponentApiManagerInterface,
log.Entry().Info("Start cloning " + logString)
abaputils.AddDefaultDashedLine(1)
- alreadyCloned, activeBranch, errCheckCloned := api.GetRepository()
+ alreadyCloned, activeBranch, errCheckCloned, isByog := api.GetRepository()
if errCheckCloned != nil {
return errors.Wrapf(errCheckCloned, errorString)
}
if !alreadyCloned {
+ if isByog {
+ api.UpdateRepoWithBYOGCredentials(config.ByogAuthMethod, config.ByogUsername, config.ByogPassword)
+ }
errClone := api.Clone()
if errClone != nil {
return errors.Wrapf(errClone, errorString)
@@ -186,5 +189,8 @@ func convertCloneConfig(config *abapEnvironmentCloneGitRepoOptions) abaputils.Ab
subOptions.Host = config.Host
subOptions.Password = config.Password
subOptions.Username = config.Username
+ subOptions.ByogUsername = config.ByogUsername
+ subOptions.ByogPassword = config.ByogPassword
+ subOptions.ByogAuthMethod = config.ByogAuthMethod
return subOptions
}
diff --git a/cmd/abapEnvironmentCloneGitRepo_generated.go b/cmd/abapEnvironmentCloneGitRepo_generated.go
index 9cba6305e5..8e160194f1 100644
--- a/cmd/abapEnvironmentCloneGitRepo_generated.go
+++ b/cmd/abapEnvironmentCloneGitRepo_generated.go
@@ -18,6 +18,9 @@ import (
type abapEnvironmentCloneGitRepoOptions struct {
Username string `json:"username,omitempty"`
Password string `json:"password,omitempty"`
+ ByogUsername string `json:"byogUsername,omitempty"`
+ ByogPassword string `json:"byogPassword,omitempty"`
+ ByogAuthMethod string `json:"byogAuthMethod,omitempty"`
Repositories string `json:"repositories,omitempty"`
RepositoryName string `json:"repositoryName,omitempty"`
BranchName string `json:"branchName,omitempty"`
@@ -68,6 +71,8 @@ Please provide either of the following options:
}
log.RegisterSecret(stepConfig.Username)
log.RegisterSecret(stepConfig.Password)
+ log.RegisterSecret(stepConfig.ByogUsername)
+ log.RegisterSecret(stepConfig.ByogPassword)
if len(GeneralConfig.HookConfig.SentryConfig.Dsn) > 0 {
sentryHook := log.NewSentryHook(GeneralConfig.HookConfig.SentryConfig.Dsn, GeneralConfig.CorrelationID)
@@ -138,6 +143,9 @@ Please provide either of the following options:
func addAbapEnvironmentCloneGitRepoFlags(cmd *cobra.Command, stepConfig *abapEnvironmentCloneGitRepoOptions) {
cmd.Flags().StringVar(&stepConfig.Username, "username", os.Getenv("PIPER_username"), "User for either the Cloud Foundry API or the Communication Arrangement for SAP_COM_0948")
cmd.Flags().StringVar(&stepConfig.Password, "password", os.Getenv("PIPER_password"), "Password for either the Cloud Foundry API or the Communication Arrangement for SAP_COM_0948")
+ cmd.Flags().StringVar(&stepConfig.ByogUsername, "byogUsername", os.Getenv("PIPER_byogUsername"), "Username for bring your own git (BYOG) authentication")
+ cmd.Flags().StringVar(&stepConfig.ByogPassword, "byogPassword", os.Getenv("PIPER_byogPassword"), "Password for bring your own git (BYOG) authentication")
+ cmd.Flags().StringVar(&stepConfig.ByogAuthMethod, "byogAuthMethod", os.Getenv("PIPER_byogAuthMethod"), "Specifies which authentication method is used for bring your own git (BYOG) repositories")
cmd.Flags().StringVar(&stepConfig.Repositories, "repositories", os.Getenv("PIPER_repositories"), "Specifies a YAML file containing the repositories configuration")
cmd.Flags().StringVar(&stepConfig.RepositoryName, "repositoryName", os.Getenv("PIPER_repositoryName"), "Specifies a repository (Software Components) on the SAP BTP ABAP Environment system")
cmd.Flags().StringVar(&stepConfig.BranchName, "branchName", os.Getenv("PIPER_branchName"), "Specifies a branch of a repository (Software Components) on the SAP BTP ABAP Environment system")
@@ -151,6 +159,8 @@ func addAbapEnvironmentCloneGitRepoFlags(cmd *cobra.Command, stepConfig *abapEnv
cmd.MarkFlagRequired("username")
cmd.MarkFlagRequired("password")
+ cmd.MarkFlagRequired("byogUsername")
+ cmd.MarkFlagRequired("byogPassword")
}
// retrieve step metadata
@@ -165,6 +175,7 @@ func abapEnvironmentCloneGitRepoMetadata() config.StepData {
Inputs: config.StepInputs{
Secrets: []config.StepSecrets{
{Name: "abapCredentialsId", Description: "Jenkins credentials ID containing user and password to authenticate to the BTP ABAP Environment system or the Cloud Foundry API", Type: "jenkins", Aliases: []config.Alias{{Name: "cfCredentialsId", Deprecated: false}, {Name: "credentialsId", Deprecated: false}}},
+ {Name: "byogCredentialsId", Description: "Jenkins credentials ID containing ByogUsername and ByogPassword to authenticate to a software component which is used in a BYOG scenario. (https://help.sap.com/docs/btp/sap-business-technology-platform/cloning-software-components-to-abap-environment-system-383ce2f9e2eb40f1b8ad538ddf79e656)", Type: "jenkins"},
},
Parameters: []config.StepParameters{
{
@@ -197,6 +208,45 @@ func abapEnvironmentCloneGitRepoMetadata() config.StepData {
Aliases: []config.Alias{},
Default: os.Getenv("PIPER_password"),
},
+ {
+ Name: "byogUsername",
+ ResourceRef: []config.ResourceReference{
+ {
+ Name: "byogCredentialsId",
+ Param: "username",
+ Type: "secret",
+ },
+ },
+ Scope: []string{"PARAMETERS", "STAGES", "STEPS", "GENERAL"},
+ Type: "string",
+ Mandatory: true,
+ Aliases: []config.Alias{},
+ Default: os.Getenv("PIPER_byogUsername"),
+ },
+ {
+ Name: "byogPassword",
+ ResourceRef: []config.ResourceReference{
+ {
+ Name: "byogCredentialsId",
+ Param: "password",
+ Type: "secret",
+ },
+ },
+ Scope: []string{"PARAMETERS", "STAGES", "STEPS", "GENERAL"},
+ Type: "string",
+ Mandatory: true,
+ Aliases: []config.Alias{},
+ Default: os.Getenv("PIPER_byogPassword"),
+ },
+ {
+ Name: "byogAuthMethod",
+ ResourceRef: []config.ResourceReference{},
+ Scope: []string{"PARAMETERS", "STAGES", "STEPS", "GENERAL"},
+ Type: "string",
+ Mandatory: false,
+ Aliases: []config.Alias{},
+ Default: os.Getenv("PIPER_byogAuthMethod"),
+ },
{
Name: "repositories",
ResourceRef: []config.ResourceReference{},
diff --git a/documentation/docs/steps/abapEnvironmentCloneGitRepo.md b/documentation/docs/steps/abapEnvironmentCloneGitRepo.md
index 8bdf906a74..53c88aec7c 100644
--- a/documentation/docs/steps/abapEnvironmentCloneGitRepo.md
+++ b/documentation/docs/steps/abapEnvironmentCloneGitRepo.md
@@ -97,3 +97,39 @@ abapEnvironmentCloneGitRepo (
cfServiceKeyName: 'cfServiceKeyName'
)
```
+
+## Example: Cloning a Bring Your Own Git (BYOG) repository
+
+> Feature will be available in November 2024.
+
+Since a ByoG repository is an external repository, you must be authenticated to clone it.
+For this, the corresponding credentials must be stored in Jenkins as a username and password/token.
+
+ Store the credentials:
+A new credential with the type username and password must be stored.
+`Jenkins Dashboard > Manage Jenkins > Credentials`
+These credentials are used to clone the ByoG repository.
+More information on configuring the credentials can be found [here](https://www.jenkins.io/doc/book/using/using-credentials/).
+
+The config.yaml should look like this:
+
+```yaml
+steps:
+ abapEnvironmentCloneGitRepo:
+ repositories: 'repos.yaml'
+ byogCredentialsId: 'byogCredentialsId'
+ abapCredentialsId: 'abapCredentialsId'
+ host: '1234-abcd-5678-efgh-ijk.abap.eu10.hana.ondemand.com'
+```
+
+`byogCredentialsId: 'byogCredentialsId'` is the reference to the defined credential in Jenkins. So take care that this matches with your setup.
+
+After that, the ByoG repository that is to be cloned must be specified in the repos.yaml:
+
+```yaml
+repositories:
+ - name: '/DMO/REPO_BYOG'
+ branch: 'main'
+```
+
+After the pipeline has run through, the repository has been cloned.
diff --git a/pkg/abaputils/abaputils.go b/pkg/abaputils/abaputils.go
index caf6cb9938..2f43a003c6 100644
--- a/pkg/abaputils/abaputils.go
+++ b/pkg/abaputils/abaputils.go
@@ -285,6 +285,9 @@ type AbapEnvironmentRunATCCheckOptions struct {
type AbapEnvironmentOptions struct {
Username string `json:"username,omitempty"`
Password string `json:"password,omitempty"`
+ ByogUsername string `json:"byogUsername,omitempty"`
+ ByogPassword string `json:"byogPassword,omitempty"`
+ ByogAuthMethod string `json:"byogAuthMethod,omitempty"`
Host string `json:"host,omitempty"`
CfAPIEndpoint string `json:"cfApiEndpoint,omitempty"`
CfOrg string `json:"cfOrg,omitempty"`
diff --git a/pkg/abaputils/descriptor.go b/pkg/abaputils/descriptor.go
index e63e9c2196..1a044d23e4 100644
--- a/pkg/abaputils/descriptor.go
+++ b/pkg/abaputils/descriptor.go
@@ -42,6 +42,10 @@ type Repository struct {
Tag string `json:"tag,omitempty"`
Branch string `json:"branch,omitempty"`
CommitID string `json:"commitID,omitempty"`
+ ByogUsername string `json:"byogUsername"`
+ ByogPassword string `json:"byogPassword"`
+ ByogAuthMethod string `json:"byogAuthMethod"`
+ IsByog bool `json:",omitempty"`
VersionYAML string `json:"version,omitempty"`
Version string `json:"versionAAK"`
AdditionalPiecelist string `json:"additionalPiecelist,omitempty"`
diff --git a/pkg/abaputils/manageGitRepositoryUtils.go b/pkg/abaputils/manageGitRepositoryUtils.go
index d53755a50e..73da35c043 100644
--- a/pkg/abaputils/manageGitRepositoryUtils.go
+++ b/pkg/abaputils/manageGitRepositoryUtils.go
@@ -163,7 +163,7 @@ func printHeader(logEntry LogResultsV2, api SoftwareComponentApiInterface) {
}
}
-// GetRepositories for parsing one or multiple branches and repositories from repositories file or branchName and repositoryName configuration
+// 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)
if reflect.DeepEqual(RepositoriesConfig{}, config) {
@@ -193,6 +193,7 @@ func GetRepositories(config *RepositoriesConfig, branchRequired bool) ([]Reposit
if config.RepositoryName != "" && !branchRequired {
repositories = append(repositories, Repository{Name: config.RepositoryName, CommitID: config.CommitID})
}
+
if len(config.RepositoryNames) > 0 {
for _, repository := range config.RepositoryNames {
repositories = append(repositories, Repository{Name: repository})
@@ -210,6 +211,25 @@ func (repo *Repository) GetRequestBodyForCommitOrTag() (requestBodyString string
return requestBodyString
}
+func (repo *Repository) GetRequestBodyForBYOGCredentials() (string, error) {
+ var byogBodyString string
+
+ if repo.ByogAuthMethod != "" {
+ byogBodyString += `, "auth_method":"` + repo.ByogAuthMethod + `"`
+ }
+ if repo.ByogUsername != "" {
+ byogBodyString += `, "username":"` + repo.ByogUsername + `"`
+ } else {
+ return "", fmt.Errorf("Failed to get BYOG credentials: %w", errors.New("Username for BYOG is missing, please provide git username to authenticate"))
+ }
+ if repo.ByogPassword != "" {
+ byogBodyString += `, "password":"` + repo.ByogPassword + `"`
+ } else {
+ return "", fmt.Errorf("Failed to get BYOG credentials: %w", errors.New("Password/Token for BYOG is missing, please provide git password or token to authenticate"))
+ }
+ return byogBodyString, nil
+}
+
func (repo *Repository) GetLogStringForCommitOrTag() (logString string) {
if repo.CommitID != "" {
logString = ", commit '" + repo.CommitID + "'"
@@ -228,13 +248,21 @@ func (repo *Repository) GetCloneRequestBodyWithSWC() (body string) {
return body
}
-func (repo *Repository) GetCloneRequestBody() (body string) {
+func (repo *Repository) GetCloneRequestBody() (body string, err error) {
if repo.CommitID != "" && repo.Tag != "" {
log.Entry().WithField("Tag", repo.Tag).WithField("Commit ID", repo.CommitID).Info("The commit ID takes precedence over the tag")
}
requestBodyString := repo.GetRequestBodyForCommitOrTag()
- body = `{"branch_name":"` + repo.Branch + `"` + requestBodyString + `}`
- return body
+ var byogBodyString = ""
+ if repo.IsByog {
+ byogBodyString, err = repo.GetRequestBodyForBYOGCredentials()
+ if err != nil {
+ return "", err
+ }
+ }
+
+ body = `{"branch_name":"` + repo.Branch + `"` + requestBodyString + byogBodyString + `}`
+ return body, nil
}
func (repo *Repository) GetCloneLogString() (logString string) {
diff --git a/pkg/abaputils/manageGitRepositoryUtils_test.go b/pkg/abaputils/manageGitRepositoryUtils_test.go
index ffd96a614b..557c742cea 100644
--- a/pkg/abaputils/manageGitRepositoryUtils_test.go
+++ b/pkg/abaputils/manageGitRepositoryUtils_test.go
@@ -268,7 +268,7 @@ func TestCreateRequestBodies(t *testing.T) {
CommitID: "1234567",
Tag: "myTag",
}
- body := repo.GetCloneRequestBody()
+ body, _ := repo.GetCloneRequestBody()
assert.Equal(t, `{"branch_name":"main", "commit_id":"1234567"}`, body, "Expected different body")
})
t.Run("Clone Body Tag", func(t *testing.T) {
diff --git a/pkg/abaputils/sap_com_0510.go b/pkg/abaputils/sap_com_0510.go
index f543c9ff6f..24d3d99251 100644
--- a/pkg/abaputils/sap_com_0510.go
+++ b/pkg/abaputils/sap_com_0510.go
@@ -225,10 +225,10 @@ func (api *SAP_COM_0510) GetAction() (string, error) {
return abapStatusCode, nil
}
-func (api *SAP_COM_0510) GetRepository() (bool, string, error) {
+func (api *SAP_COM_0510) GetRepository() (bool, string, error, bool) {
if api.repository.Name == "" {
- return false, "", errors.New("An empty string was passed for the parameter 'repositoryName'")
+ return false, "", errors.New("An empty string was passed for the parameter 'repositoryName'"), false
}
swcConnectionDetails := api.con
@@ -236,7 +236,7 @@ func (api *SAP_COM_0510) GetRepository() (bool, string, error) {
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
+ return false, "", errRepo, false
}
defer resp.Body.Close()
@@ -244,25 +244,25 @@ func (api *SAP_COM_0510) GetRepository() (bool, string, error) {
var abapResp map[string]*json.RawMessage
bodyText, errRead := io.ReadAll(resp.Body)
if errRead != nil {
- return false, "", err
+ return false, "", err, false
}
if err := json.Unmarshal(bodyText, &abapResp); err != nil {
- return false, "", err
+ return false, "", err, false
}
if err := json.Unmarshal(*abapResp["d"], &body); err != nil {
- return false, "", err
+ return false, "", err, false
}
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
+ return false, "", err, false
}
if body.AvailOnInst {
- return true, body.ActiveBranch, nil
+ return true, body.ActiveBranch, nil, false
}
- return false, "", err
+ return false, "", err, false
}
@@ -399,3 +399,8 @@ func (api *SAP_COM_0510) ConvertTime(logTimeStamp string) time.Time {
t := time.Unix(n, 0).UTC()
return t
}
+
+// Dummy implementation of the "optional" method UpdateRepoWithBYOGCredentials (only used in SAP_COM_0948)
+func (api *SAP_COM_0510) UpdateRepoWithBYOGCredentials(byogAuthMethod string, byogUsername string, byogPassword string) {
+ panic("UpdateRepoWithBYOGCredentials cannot be used in SAP_COM_0510")
+}
diff --git a/pkg/abaputils/sap_com_0510_test.go b/pkg/abaputils/sap_com_0510_test.go
index 28c3af01e6..1e953560c0 100644
--- a/pkg/abaputils/sap_com_0510_test.go
+++ b/pkg/abaputils/sap_com_0510_test.go
@@ -368,7 +368,7 @@ func TestGetRepo(t *testing.T) {
assert.NoError(t, err)
assert.IsType(t, &SAP_COM_0510{}, api.(*SAP_COM_0510), "API has wrong type")
- cloned, activeBranch, errAction := api.GetRepository()
+ cloned, activeBranch, errAction, _ := api.GetRepository()
assert.True(t, cloned)
assert.Equal(t, "testBranch1", activeBranch)
assert.NoError(t, errAction)
diff --git a/pkg/abaputils/sap_com_0948.go b/pkg/abaputils/sap_com_0948.go
index de1ac13eba..ef25db3bb6 100644
--- a/pkg/abaputils/sap_com_0948.go
+++ b/pkg/abaputils/sap_com_0948.go
@@ -238,10 +238,10 @@ func (api *SAP_COM_0948) GetAction() (string, error) {
return abapStatusCode, nil
}
-func (api *SAP_COM_0948) GetRepository() (bool, string, error) {
+func (api *SAP_COM_0948) GetRepository() (bool, string, error, bool) {
if api.repository.Name == "" {
- return false, "", errors.New("An empty string was passed for the parameter 'repositoryName'")
+ return false, "", errors.New("An empty string was passed for the parameter 'repositoryName'"), false
}
swcConnectionDetails := api.con
@@ -249,32 +249,44 @@ func (api *SAP_COM_0948) GetRepository() (bool, string, error) {
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
+ return false, "", errRepo, false
}
defer resp.Body.Close()
var body RepositoryEntity
bodyText, errRead := io.ReadAll(resp.Body)
if errRead != nil {
- return false, "", err
+ return false, "", err, false
}
if err := json.Unmarshal(bodyText, &body); err != nil {
- return false, "", err
+ return false, "", err, false
}
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
+ return false, "", err, false
}
if body.AvailOnInst {
- return true, body.ActiveBranch, nil
+ return true, body.ActiveBranch, nil, false
}
- return false, "", err
+
+ if body.ByogUrl != "" {
+ return false, "", err, true
+ }
+
+ return false, "", err, false
}
+func (api *SAP_COM_0948) UpdateRepoWithBYOGCredentials(byogAuthMethod string, byogUsername string, byogPassword string) {
+ api.repository.ByogAuthMethod = byogAuthMethod
+ api.repository.ByogUsername = byogUsername
+ api.repository.ByogPassword = byogPassword
+ api.repository.IsByog = true
+}
+
func (api *SAP_COM_0948) Clone() error {
// Trigger the Clone of a Repository
@@ -284,9 +296,12 @@ func (api *SAP_COM_0948) Clone() error {
cloneConnectionDetails := api.con
cloneConnectionDetails.URL = api.con.URL + api.path + api.softwareComponentEntity + api.getRepoNameForPath() + api.cloneAction
- body := []byte(api.repository.GetCloneRequestBody())
+ body, err := api.repository.GetCloneRequestBody()
+ if err != nil {
+ return errors.Wrap(err, "Failed to clone repository")
+ }
- return api.triggerRequest(cloneConnectionDetails, body)
+ return api.triggerRequest(cloneConnectionDetails, []byte(body))
}
diff --git a/pkg/abaputils/sap_com_0948_test.go b/pkg/abaputils/sap_com_0948_test.go
index 8855e994ef..629f23c040 100644
--- a/pkg/abaputils/sap_com_0948_test.go
+++ b/pkg/abaputils/sap_com_0948_test.go
@@ -23,6 +23,11 @@ func init() {
repoTest0948.Name = "/DMO/REPO"
repoTest0948.Branch = "main"
+ repoTest0948.IsByog = false
+ repoTest0948.ByogAuthMethod = "token"
+ repoTest0948.ByogUsername = "byogUser"
+ repoTest0948.ByogPassword = "byogToken"
+
}
func TestRetry0948(t *testing.T) {
@@ -52,7 +57,7 @@ func TestRetry0948(t *testing.T) {
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")
+ assert.Equal(t, "GUID", api.getUUID(), "API does not contain correct UUID")
})
@@ -82,7 +87,7 @@ func TestRetry0948(t *testing.T) {
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")
+ assert.Empty(t, api.getUUID(), "API does not contain correct UUID")
})
@@ -128,7 +133,7 @@ func TestRetry0948(t *testing.T) {
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.Empty(t, api.getUUID(), "API does not contain correct UUID")
assert.Equal(t, 6, len(client.BodyList), "Expected maxSleepTime to limit requests")
})
@@ -175,7 +180,7 @@ func TestRetry0948(t *testing.T) {
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.Empty(t, api.getUUID(), "API does not contain correct UUID")
assert.Equal(t, 5, len(client.BodyList), "Expected maxRetries to limit requests")
})
@@ -201,7 +206,7 @@ func TestClone0948(t *testing.T) {
errClone := api.Clone()
assert.NoError(t, errClone)
- assert.Equal(t, "GUID", api.getUUID(), "API does not cotain correct UUID")
+ assert.Equal(t, "GUID", api.getUUID(), "API does not contain correct UUID")
})
t.Run("Test Clone Failure", func(t *testing.T) {
@@ -225,7 +230,7 @@ func TestClone0948(t *testing.T) {
errClone := api.Clone()
assert.ErrorContains(t, errClone, "Request to ABAP System not successful")
- assert.Empty(t, api.getUUID(), "API does not cotain correct UUID")
+ assert.Empty(t, api.getUUID(), "API does not contain correct UUID")
})
t.Run("Test Clone Retry", func(t *testing.T) {
@@ -254,8 +259,48 @@ func TestClone0948(t *testing.T) {
errClone := api.Clone()
assert.NoError(t, errClone)
- assert.Equal(t, "GUID", api.getUUID(), "API does not cotain correct UUID")
+ assert.Equal(t, "GUID", api.getUUID(), "API does not contain correct UUID")
+ })
+
+ t.Run("Test Clone Body Success", func(t *testing.T) {
+
+ cloneBody, _ := repoTest0948.GetCloneRequestBody()
+ assert.Equal(t, "{\"branch_name\":\"main\"}", string([]byte(cloneBody)), "Clone body is not correct")
})
+
+ t.Run("Test Clone Body Failure", func(t *testing.T) {
+
+ repoTest0948.Branch = "wrongBranch"
+
+ cloneBody, _ := repoTest0948.GetCloneRequestBody()
+ assert.NotEqual(t, "{\"branch_name\":\"main\"}", string([]byte(cloneBody)), "Clone body should not match")
+
+ repoTest0948.Branch = "main"
+
+ })
+
+ t.Run("Test Clone Body BYOG Success", func(t *testing.T) {
+
+ repoTest0948.IsByog = true
+
+ cloneBody, _ := repoTest0948.GetCloneRequestBody()
+ assert.Equal(t, "{\"branch_name\":\"main\", \"auth_method\":\"token\", \"username\":\"byogUser\", \"password\":\"byogToken\"}", string([]byte(cloneBody)), "Clone body for byog parameter is not correct")
+
+ repoTest0948.IsByog = false
+ })
+
+ t.Run("Test Clone Body BYOG Failure", func(t *testing.T) {
+
+ repoTest0948.ByogPassword = "wrongToken"
+ repoTest0948.IsByog = true
+
+ cloneBody, _ := repoTest0948.GetCloneRequestBody()
+ assert.NotEqual(t, "{\"branch_name\":\"main\", \"auth_method\":\"token\", \"username\":\"byogUser\", \"password\":\"byogToken\"}", string([]byte(cloneBody)), "Clone body for byog parameter should not match")
+
+ repoTest0948.ByogPassword = "byogToken"
+ repoTest0948.IsByog = false
+ })
+
}
func TestPull0948(t *testing.T) {
@@ -278,7 +323,7 @@ func TestPull0948(t *testing.T) {
errPull := api.Pull()
assert.NoError(t, errPull)
- assert.Equal(t, "GUID", api.getUUID(), "API does not cotain correct UUID")
+ assert.Equal(t, "GUID", api.getUUID(), "API does not contain correct UUID")
})
t.Run("Test Pull Failure", func(t *testing.T) {
@@ -300,7 +345,7 @@ func TestPull0948(t *testing.T) {
errPull := api.Pull()
assert.ErrorContains(t, errPull, "Request to ABAP System not successful")
- assert.Empty(t, api.getUUID(), "API does not cotain correct UUID")
+ assert.Empty(t, api.getUUID(), "API does not contain correct UUID")
})
}
@@ -324,7 +369,7 @@ func TestCheckout0948(t *testing.T) {
errCheckout := api.CheckoutBranch()
assert.NoError(t, errCheckout)
- assert.Equal(t, "GUID", api.getUUID(), "API does not cotain correct UUID")
+ assert.Equal(t, "GUID", api.getUUID(), "API does not contain correct UUID")
})
t.Run("Test Checkout Failure", func(t *testing.T) {
@@ -346,7 +391,7 @@ func TestCheckout0948(t *testing.T) {
errCheckoput := api.CheckoutBranch()
assert.ErrorContains(t, errCheckoput, "Request to ABAP System not successful")
- assert.Empty(t, api.getUUID(), "API does not cotain correct UUID")
+ assert.Empty(t, api.getUUID(), "API does not contain correct UUID")
})
}
@@ -368,7 +413,7 @@ func TestGetRepo0948(t *testing.T) {
assert.NoError(t, err)
assert.IsType(t, &SAP_COM_0948{}, api.(*SAP_COM_0948), "API has wrong type")
- cloned, activeBranch, errAction := api.GetRepository()
+ cloned, activeBranch, errAction, _ := api.GetRepository()
assert.True(t, cloned)
assert.Equal(t, "testBranch1", activeBranch)
assert.NoError(t, errAction)
@@ -395,7 +440,7 @@ func TestCreateTag0948(t *testing.T) {
errCreateTag := api.CreateTag(Tag{TagName: "myTag", TagDescription: "descr"})
assert.NoError(t, errCreateTag)
- assert.Equal(t, "GUID", api.getUUID(), "API does not cotain correct UUID")
+ assert.Equal(t, "GUID", api.getUUID(), "API does not contain correct UUID")
})
t.Run("Test Tag Failure", func(t *testing.T) {
@@ -417,7 +462,7 @@ func TestCreateTag0948(t *testing.T) {
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")
+ assert.Empty(t, api.getUUID(), "API does not contain correct UUID")
})
t.Run("Test Tag Empty", func(t *testing.T) {
@@ -439,7 +484,7 @@ func TestCreateTag0948(t *testing.T) {
errCreateTag := api.CreateTag(Tag{})
assert.ErrorContains(t, errCreateTag, "No Tag provided")
- assert.Empty(t, api.getUUID(), "API does not cotain correct UUID")
+ assert.Empty(t, api.getUUID(), "API does not contain correct UUID")
})
}
diff --git a/pkg/abaputils/softwareComponentApiManager.go b/pkg/abaputils/softwareComponentApiManager.go
index c4d02e7115..0bd7b712f9 100644
--- a/pkg/abaputils/softwareComponentApiManager.go
+++ b/pkg/abaputils/softwareComponentApiManager.go
@@ -59,7 +59,7 @@ type SoftwareComponentApiInterface interface {
setSleepTimeConfig(timeUnit time.Duration, maxSleepTime time.Duration)
getSleepTime(n int) (time.Duration, error)
getUUID() string
- GetRepository() (bool, string, error)
+ GetRepository() (bool, string, error, bool)
Clone() error
Pull() error
CheckoutBranch() error
@@ -69,6 +69,7 @@ type SoftwareComponentApiInterface interface {
GetLogProtocol(LogResultsV2, int) (result []LogProtocol, count int, err error)
ConvertTime(logTimeStamp string) time.Time
GetExecutionLog() (ExecutionLog, error)
+ UpdateRepoWithBYOGCredentials(string, string, string)
}
/****************************************
@@ -128,6 +129,7 @@ type CloneEntity struct {
type RepositoryEntity struct {
Metadata AbapMetadata `json:"__metadata"`
ScName string `json:"sc_name"`
+ ByogUrl string `json:"url"`
ActiveBranch string `json:"active_branch"`
AvailOnInst bool `json:"avail_on_inst"`
}
@@ -201,6 +203,9 @@ type RepositoriesConfig struct {
BranchName string
CommitID string
RepositoryName string
+ ByogUsername string
+ ByogPassword string
+ ByogAuthMethod string
RepositoryNames []string
Repositories string
}
diff --git a/resources/metadata/abapEnvironmentCloneGitRepo.yaml b/resources/metadata/abapEnvironmentCloneGitRepo.yaml
index e3d3828388..746c2c3a82 100644
--- a/resources/metadata/abapEnvironmentCloneGitRepo.yaml
+++ b/resources/metadata/abapEnvironmentCloneGitRepo.yaml
@@ -18,6 +18,9 @@ spec:
aliases:
- name: cfCredentialsId
- name: credentialsId
+ - name: byogCredentialsId
+ description: Jenkins credentials ID containing ByogUsername and ByogPassword to authenticate to a software component which is used in a BYOG scenario. (https://help.sap.com/docs/btp/sap-business-technology-platform/cloning-software-components-to-abap-environment-system-383ce2f9e2eb40f1b8ad538ddf79e656)
+ type: jenkins
params:
- name: username
type: string
@@ -45,6 +48,42 @@ spec:
- name: abapCredentialsId
type: secret
param: password
+ - name: byogUsername
+ type: string
+ description: Username for bring your own git (BYOG) authentication
+ scope:
+ - PARAMETERS
+ - STAGES
+ - STEPS
+ - GENERAL
+ mandatory: true
+ secret: true
+ resourceRef:
+ - name: byogCredentialsId
+ type: secret
+ param: username
+ - name: byogPassword
+ type: string
+ description: Password for bring your own git (BYOG) authentication
+ scope:
+ - PARAMETERS
+ - STAGES
+ - STEPS
+ - GENERAL
+ mandatory: true
+ secret: true
+ resourceRef:
+ - name: byogCredentialsId
+ type: secret
+ param: password
+ - name: byogAuthMethod
+ type: string
+ description: Specifies which authentication method is used for bring your own git (BYOG) repositories
+ scope:
+ - PARAMETERS
+ - STAGES
+ - STEPS
+ - GENERAL
- name: repositories
type: string
description: Specifies a YAML file containing the repositories configuration
diff --git a/vars/abapEnvironmentCloneGitRepo.groovy b/vars/abapEnvironmentCloneGitRepo.groovy
index 96d948cbda..46aaf03120 100644
--- a/vars/abapEnvironmentCloneGitRepo.groovy
+++ b/vars/abapEnvironmentCloneGitRepo.groovy
@@ -5,7 +5,8 @@ import groovy.transform.Field
void call(Map parameters = [:]) {
List credentials = [
- [type: 'usernamePassword', id: 'abapCredentialsId', env: ['PIPER_username', 'PIPER_password']]
+ [type: 'usernamePassword', id: 'abapCredentialsId', env: ['PIPER_username', 'PIPER_password']],
+ [type: 'usernamePassword', id: 'byogCredentialsId', env: ['PIPER_byogUsername', 'PIPER_byogPassword']]
]
piperExecuteBin(parameters, STEP_NAME, METADATA_FILE, credentials, false, false, true)
}