1
0
mirror of https://github.com/SAP/jenkins-library.git synced 2024-11-24 08:32:32 +02:00

Adapt clone step to work with customer-managed Repos (BYOG) (#4966)

* adding byog credentials for clone command

* adding unit tests for clone body

* adding parameters

* adding optional byog parameters

* fixing typo in username

* remove aliases in config yaml

* change yaml config

* logs

* change info log

* change logs

* remove logs

* adding log statements

* remove log statements

* fixing typo in test class

* change repoTest structure

* remove comment

* remove comment

* generate

* adding unit test comments

* adding error handling

* adding isByog check

* fixing unit test

* generate

* Update manageGitRepositoryUtils_test.go

* restructure isByog parameter

* adding empty line for md linter

* adding config.yaml example to docs

* Update documentation/docs/steps/abapEnvironmentCloneGitRepo.md

Co-authored-by: Daniel Mieg <56156797+DanielMieg@users.noreply.github.com>

* Update documentation/docs/steps/abapEnvironmentCloneGitRepo.md

Co-authored-by: Daniel Mieg <56156797+DanielMieg@users.noreply.github.com>

* Update documentation/docs/steps/abapEnvironmentCloneGitRepo.md

Co-authored-by: Daniel Mieg <56156797+DanielMieg@users.noreply.github.com>

* Update documentation/docs/steps/abapEnvironmentCloneGitRepo.md

Co-authored-by: Daniel Mieg <56156797+DanielMieg@users.noreply.github.com>

* Update documentation/docs/steps/abapEnvironmentCloneGitRepo.md

Co-authored-by: Daniel Mieg <56156797+DanielMieg@users.noreply.github.com>

* adding release

---------

Co-authored-by: Daniel Mieg <56156797+DanielMieg@users.noreply.github.com>
This commit is contained in:
Simon Dold 2024-06-25 10:09:31 +02:00 committed by GitHub
parent b9022dc10d
commit 65dbd4526c
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
14 changed files with 281 additions and 44 deletions

View File

@ -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
}

View File

@ -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{},

View File

@ -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.
<strong> Store the credentials: </strong> <br>
A new credential with the type username and password must be stored.<br>
`Jenkins Dashboard > Manage Jenkins > Credentials` <br>
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.

View File

@ -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"`

View File

@ -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"`

View File

@ -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) {

View File

@ -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) {

View File

@ -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")
}

View File

@ -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)

View File

@ -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,30 +249,42 @@ 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 {
@ -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))
}

View File

@ -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")
})
}

View File

@ -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
}

View File

@ -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

View File

@ -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)
}