Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 0 additions & 2 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -77,8 +77,6 @@ Session.vim
.netrwhist
# auto-generated tag files
tags
### VisualStudioCode IDEA ###
.vscode/*
.history
.idea/*
# End of https://www.gitignore.io/api/go,vim,emacs,visualstudiocode
Expand Down
3 changes: 3 additions & 0 deletions .mockery.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,9 @@ packages:
interfaces:
Git:
Command:
github.com/epam/edp-codebase-operator/v2/pkg/git/v2:
interfaces:
Git:
github.com/epam/edp-codebase-operator/v2/pkg/gitprovider:
interfaces:
GitProjectProvider:
Expand Down
22 changes: 22 additions & 0 deletions .vscode/launch.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
{
// Use IntelliSense to learn about possible attributes.
// Hover to view descriptions of existing attributes.
// For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387
"version": "0.2.0",
"configurations": [
{
"name": "local",
"type": "go",
"request": "launch",
"mode": "auto",
"program": "${workspaceFolder}/cmd",
"env": {
"WORKING_DIR": "/tmp",
"WATCH_NAMESPACE": "default",
"ENABLE_WEBHOOKS": "false",
"PLATFORM_TYPE": "kubernetes",
"ASSETS_DIR": "${workspaceFolder}/build"
}
}
]
}
4 changes: 4 additions & 0 deletions api/v1/git_server_types.go
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,10 @@ func (in *GitServerStatus) SetSuccess() {
in.Status = "ok"
}

func (in *GitServerStatus) IsSuccess() bool {
return in.Status == "ok"
}

// +kubebuilder:object:root=true
// +kubebuilder:subresource:status
// +kubebuilder:resource:shortName=gs
Expand Down
55 changes: 26 additions & 29 deletions controllers/codebase/service/chain/checkout_branch.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ import (
"sigs.k8s.io/controller-runtime/pkg/client"

codebaseApi "github.com/epam/edp-codebase-operator/v2/api/v1"
"github.com/epam/edp-codebase-operator/v2/pkg/git"
gitproviderv2 "github.com/epam/edp-codebase-operator/v2/pkg/git/v2"
"github.com/epam/edp-codebase-operator/v2/pkg/util"
)

Expand All @@ -31,18 +31,15 @@ func GetRepositoryCredentialsIfExists(cb *codebaseApi.Codebase, c client.Client)
return
}

func CheckoutBranch(repository, projectPath, branchName string, g git.Git, cb *codebaseApi.Codebase, c client.Client) error {
user, password, err := GetRepositoryCredentialsIfExists(cb, c)
if err != nil && !k8sErrors.IsNotFound(err) {
return err
}

if !g.CheckPermissions(ctrl.LoggerInto(context.TODO(), ctrl.Log.WithName("git-provider")), repository, user, password) {
msg := fmt.Errorf("user %s cannot get access to the repository %s", *user, repository)
return msg
}

currentBranchName, err := g.GetCurrentBranchName(projectPath)
func CheckoutBranch(
ctx context.Context,
repository, projectPath, branchName string,
g gitproviderv2.Git,
cb *codebaseApi.Codebase,
c client.Client,
createGitProviderWithConfig func(config gitproviderv2.Config) gitproviderv2.Git,
) error {
currentBranchName, err := g.GetCurrentBranchName(ctx, projectPath)
if err != nil {
return fmt.Errorf("failed to get current branch name: %w", err)
}
Expand All @@ -54,32 +51,32 @@ func CheckoutBranch(repository, projectPath, branchName string, g git.Git, cb *c

switch cb.Spec.Strategy {
case "create":
if err := g.Checkout(user, password, projectPath, branchName, false); err != nil {
if err := g.Checkout(ctx, projectPath, branchName, false); err != nil {
return fmt.Errorf("failed to checkout to default branch %s (create strategy): %w", branchName, err)
}

case "clone":
if err := g.Checkout(user, password, projectPath, branchName, true); err != nil {
return fmt.Errorf("failed to checkout to default branch %s (clone strategy): %w", branchName, err)
}
case "import":
gs, err := util.GetGitServer(c, cb.Spec.GitServer, cb.Namespace)
if err != nil {
return fmt.Errorf("failed to get GitServer: %w", err)
user, password, err := GetRepositoryCredentialsIfExists(cb, c)
if err != nil && !k8sErrors.IsNotFound(err) {
return err
}

secret, err := util.GetSecret(c, gs.NameSshKeySecret, cb.Namespace)
if err != nil {
return fmt.Errorf("failed to get %v secret: %w", gs.NameSshKeySecret, err)
cloneRepoGitProvider := g

if user != nil && password != nil {
cloneRepoGitProvider = createGitProviderWithConfig(gitproviderv2.Config{
Username: *user,
Token: *password,
})
}

k := string(secret.Data[util.PrivateSShKeyName])
u := gs.GitUser
// CheckoutRemoteBranchBySSH(key, user, gitPath, remoteBranchName string)
if err := g.CheckoutRemoteBranchBySSH(k, u, projectPath, branchName); err != nil {
if err := cloneRepoGitProvider.Checkout(ctx, projectPath, branchName, true); err != nil {
return fmt.Errorf("failed to checkout to default branch %s (clone strategy): %w", branchName, err)
}
case "import":
if err := g.CheckoutRemoteBranch(ctx, projectPath, branchName); err != nil {
return fmt.Errorf("failed to checkout to default branch %s (import strategy): %w", branchName, err)
}

default:
return fmt.Errorf("failed to checkout, unsupported strategy: '%s'", cb.Spec.Strategy)
}
Expand Down
80 changes: 23 additions & 57 deletions controllers/codebase/service/chain/checkout_branch_test.go
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package chain

import (
"context"
"errors"
"strings"
"testing"
Expand All @@ -13,7 +14,8 @@ import (
"sigs.k8s.io/controller-runtime/pkg/client/fake"

codebaseApi "github.com/epam/edp-codebase-operator/v2/api/v1"
gitServerMocks "github.com/epam/edp-codebase-operator/v2/pkg/git/mocks"
gitproviderv2 "github.com/epam/edp-codebase-operator/v2/pkg/git/v2"
gitServerMocks "github.com/epam/edp-codebase-operator/v2/pkg/git/v2/mocks"
"github.com/epam/edp-codebase-operator/v2/pkg/util"
)

Expand Down Expand Up @@ -89,6 +91,7 @@ func TestCheckoutBranch_ShouldFailOnGetSecret(t *testing.T) {
Repository: &codebaseApi.Repository{
Url: "repo",
},
Strategy: codebaseApi.Clone,
},
}

Expand All @@ -97,55 +100,18 @@ func TestCheckoutBranch_ShouldFailOnGetSecret(t *testing.T) {
fakeCl := fake.NewClientBuilder().WithScheme(scheme).WithRuntimeObjects(c).Build()

mGit := gitServerMocks.NewMockGit(t)
mGit.On("GetCurrentBranchName", testify.Anything, "project-path").Return("some-other-branch", nil)

err := CheckoutBranch("repo", "project-path", "branch", mGit, c, fakeCl)
err := CheckoutBranch(context.Background(), "repo", "project-path", "branch", mGit, c, fakeCl, func(config gitproviderv2.Config) gitproviderv2.Git {
return mGit
})
assert.Error(t, err)

if !strings.Contains(err.Error(), "failed to get secret repository-codebase-fake-name-temp") {
t.Fatalf("wrong error returned: %s", err.Error())
}
}

func TestCheckoutBranch_ShouldFailOnCheckPermission(t *testing.T) {
c := &codebaseApi.Codebase{
ObjectMeta: metaV1.ObjectMeta{
Name: "fake-name",
Namespace: fakeNamespace,
},
Spec: codebaseApi.CodebaseSpec{
Repository: &codebaseApi.Repository{
Url: "repo",
},
},
}
s := &coreV1.Secret{
ObjectMeta: metaV1.ObjectMeta{
Name: "repository-codebase-fake-name-temp",
Namespace: fakeNamespace,
},
Data: map[string][]byte{
"username": []byte("user"),
"password": []byte("pass"),
},
}
scheme := runtime.NewScheme()

scheme.AddKnownTypes(coreV1.SchemeGroupVersion, s)
scheme.AddKnownTypes(codebaseApi.GroupVersion, c)

fakeCl := fake.NewClientBuilder().WithScheme(scheme).WithRuntimeObjects(s, c).Build()

mGit := gitServerMocks.NewMockGit(t)
mGit.On("CheckPermissions", testify.Anything, "repo", util.GetStringP("user"), util.GetStringP("pass")).Return(false)

err := CheckoutBranch("repo", "project-path", "branch", mGit, c, fakeCl)
assert.Error(t, err)

if !strings.Contains(err.Error(), "user user cannot get access to the repository repo") {
t.Fatalf("wrong error returned: %s", err.Error())
}
}

func TestCheckoutBranch_ShouldFailOnGetCurrentBranchName(t *testing.T) {
c := &codebaseApi.Codebase{
ObjectMeta: metaV1.ObjectMeta{
Expand All @@ -156,6 +122,7 @@ func TestCheckoutBranch_ShouldFailOnGetCurrentBranchName(t *testing.T) {
Repository: &codebaseApi.Repository{
Url: "repo",
},
Strategy: codebaseApi.Clone,
},
}
s := &coreV1.Secret{
Expand All @@ -174,10 +141,11 @@ func TestCheckoutBranch_ShouldFailOnGetCurrentBranchName(t *testing.T) {
fakeCl := fake.NewClientBuilder().WithScheme(scheme).WithRuntimeObjects(s, c).Build()

mGit := gitServerMocks.NewMockGit(t)
mGit.On("CheckPermissions", testify.Anything, "repo", util.GetStringP("user"), util.GetStringP("pass")).Return(true)
mGit.On("GetCurrentBranchName", "project-path").Return("", errors.New("FATAL:FAILED"))
mGit.On("GetCurrentBranchName", testify.Anything, "project-path").Return("", errors.New("FATAL:FAILED"))

err := CheckoutBranch("repo", "project-path", "branch", mGit, c, fakeCl)
err := CheckoutBranch(context.Background(), "repo", "project-path", "branch", mGit, c, fakeCl, func(config gitproviderv2.Config) gitproviderv2.Git {
return mGit
})
assert.Error(t, err)

if !strings.Contains(err.Error(), "FATAL:FAILED") {
Expand All @@ -187,8 +155,6 @@ func TestCheckoutBranch_ShouldFailOnGetCurrentBranchName(t *testing.T) {

func TestCheckoutBranch_ShouldFailOnCheckout(t *testing.T) {
repo := "repo"
u := "user1"
p := "pass1"
c := &codebaseApi.Codebase{
ObjectMeta: metaV1.ObjectMeta{
Name: "fake-name",
Expand Down Expand Up @@ -217,11 +183,12 @@ func TestCheckoutBranch_ShouldFailOnCheckout(t *testing.T) {
fakeCl := fake.NewClientBuilder().WithScheme(scheme).WithRuntimeObjects(s, c).Build()

mGit := gitServerMocks.NewMockGit(t)
mGit.On("CheckPermissions", testify.Anything, "repo", &u, &p).Return(true)
mGit.On("GetCurrentBranchName", "project-path").Return("some-other-branch", nil)
mGit.On("Checkout", &u, &p, "project-path", "branch", true).Return(errors.New("FATAL:FAILED"))
mGit.On("GetCurrentBranchName", testify.Anything, "project-path").Return("some-other-branch", nil)
mGit.On("Checkout", testify.Anything, "project-path", "branch", true).Return(errors.New("FATAL:FAILED"))

err := CheckoutBranch(repo, "project-path", "branch", mGit, c, fakeCl)
err := CheckoutBranch(context.Background(), repo, "project-path", "branch", mGit, c, fakeCl, func(config gitproviderv2.Config) gitproviderv2.Git {
return mGit
})
assert.Error(t, err)

if !strings.Contains(err.Error(), "FATAL:FAILED") {
Expand All @@ -231,8 +198,6 @@ func TestCheckoutBranch_ShouldFailOnCheckout(t *testing.T) {

func TestCheckoutBranch_ShouldPassForCloneStrategy(t *testing.T) {
repo := "repo"
u := "user"
p := "pass"
c := &codebaseApi.Codebase{
ObjectMeta: metaV1.ObjectMeta{
Name: "fake-name",
Expand Down Expand Up @@ -283,10 +248,11 @@ func TestCheckoutBranch_ShouldPassForCloneStrategy(t *testing.T) {
fakeCl := fake.NewClientBuilder().WithScheme(scheme).WithRuntimeObjects(s, c, gs, ssh).Build()

mGit := gitServerMocks.NewMockGit(t)
mGit.On("CheckPermissions", testify.Anything, "repo", &u, &p).Return(true)
mGit.On("GetCurrentBranchName", "project-path").Return("some-other-branch", nil)
mGit.On("CheckoutRemoteBranchBySSH", "fake", fakeName, "project-path", "branch").Return(nil)
mGit.On("GetCurrentBranchName", testify.Anything, "project-path").Return("some-other-branch", nil)
mGit.On("CheckoutRemoteBranch", testify.Anything, "project-path", "branch").Return(nil)

err := CheckoutBranch(repo, "project-path", "branch", mGit, c, fakeCl)
err := CheckoutBranch(context.Background(), repo, "project-path", "branch", mGit, c, fakeCl, func(config gitproviderv2.Config) gitproviderv2.Git {
return mGit
})
assert.NoError(t, err)
}
Loading