Skip to content

Commit baa09f3

Browse files
zmotsoMykolaMarusenko
authored andcommitted
feat: Add support onboarding git projects with access token (#231)
With this change, the GitServer secret may not include the SSH key. We can onboard a project only with a token. If an SSH key and a token are provided, the operator will use the SSH key by default.
1 parent eb7116c commit baa09f3

32 files changed

+3235
-761
lines changed

.gitignore

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -77,8 +77,6 @@ Session.vim
7777
.netrwhist
7878
# auto-generated tag files
7979
tags
80-
### VisualStudioCode IDEA ###
81-
.vscode/*
8280
.history
8381
.idea/*
8482
# End of https://www.gitignore.io/api/go,vim,emacs,visualstudiocode

.mockery.yaml

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,9 @@ packages:
2424
interfaces:
2525
Git:
2626
Command:
27+
github.com/epam/edp-codebase-operator/v2/pkg/git/v2:
28+
interfaces:
29+
Git:
2730
github.com/epam/edp-codebase-operator/v2/pkg/gitprovider:
2831
interfaces:
2932
GitProjectProvider:

.vscode/launch.json

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
{
2+
// Use IntelliSense to learn about possible attributes.
3+
// Hover to view descriptions of existing attributes.
4+
// For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387
5+
"version": "0.2.0",
6+
"configurations": [
7+
{
8+
"name": "local",
9+
"type": "go",
10+
"request": "launch",
11+
"mode": "auto",
12+
"program": "${workspaceFolder}/cmd",
13+
"env": {
14+
"WORKING_DIR": "/tmp",
15+
"WATCH_NAMESPACE": "default",
16+
"ENABLE_WEBHOOKS": "false",
17+
"PLATFORM_TYPE": "kubernetes",
18+
"ASSETS_DIR": "${workspaceFolder}/build"
19+
}
20+
}
21+
]
22+
}

api/v1/git_server_types.go

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -69,6 +69,10 @@ func (in *GitServerStatus) SetSuccess() {
6969
in.Status = "ok"
7070
}
7171

72+
func (in *GitServerStatus) IsSuccess() bool {
73+
return in.Status == "ok"
74+
}
75+
7276
// +kubebuilder:object:root=true
7377
// +kubebuilder:subresource:status
7478
// +kubebuilder:resource:shortName=gs

controllers/codebase/service/chain/checkout_branch.go

Lines changed: 26 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ import (
99
"sigs.k8s.io/controller-runtime/pkg/client"
1010

1111
codebaseApi "github.com/epam/edp-codebase-operator/v2/api/v1"
12-
"github.com/epam/edp-codebase-operator/v2/pkg/git"
12+
gitproviderv2 "github.com/epam/edp-codebase-operator/v2/pkg/git/v2"
1313
"github.com/epam/edp-codebase-operator/v2/pkg/util"
1414
)
1515

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

34-
func CheckoutBranch(repository, projectPath, branchName string, g git.Git, cb *codebaseApi.Codebase, c client.Client) error {
35-
user, password, err := GetRepositoryCredentialsIfExists(cb, c)
36-
if err != nil && !k8sErrors.IsNotFound(err) {
37-
return err
38-
}
39-
40-
if !g.CheckPermissions(ctrl.LoggerInto(context.TODO(), ctrl.Log.WithName("git-provider")), repository, user, password) {
41-
msg := fmt.Errorf("user %s cannot get access to the repository %s", *user, repository)
42-
return msg
43-
}
44-
45-
currentBranchName, err := g.GetCurrentBranchName(projectPath)
34+
func CheckoutBranch(
35+
ctx context.Context,
36+
repository, projectPath, branchName string,
37+
g gitproviderv2.Git,
38+
cb *codebaseApi.Codebase,
39+
c client.Client,
40+
createGitProviderWithConfig func(config gitproviderv2.Config) gitproviderv2.Git,
41+
) error {
42+
currentBranchName, err := g.GetCurrentBranchName(ctx, projectPath)
4643
if err != nil {
4744
return fmt.Errorf("failed to get current branch name: %w", err)
4845
}
@@ -54,32 +51,32 @@ func CheckoutBranch(repository, projectPath, branchName string, g git.Git, cb *c
5451

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

6158
case "clone":
62-
if err := g.Checkout(user, password, projectPath, branchName, true); err != nil {
63-
return fmt.Errorf("failed to checkout to default branch %s (clone strategy): %w", branchName, err)
64-
}
65-
case "import":
66-
gs, err := util.GetGitServer(c, cb.Spec.GitServer, cb.Namespace)
67-
if err != nil {
68-
return fmt.Errorf("failed to get GitServer: %w", err)
59+
user, password, err := GetRepositoryCredentialsIfExists(cb, c)
60+
if err != nil && !k8sErrors.IsNotFound(err) {
61+
return err
6962
}
7063

71-
secret, err := util.GetSecret(c, gs.NameSshKeySecret, cb.Namespace)
72-
if err != nil {
73-
return fmt.Errorf("failed to get %v secret: %w", gs.NameSshKeySecret, err)
64+
cloneRepoGitProvider := g
65+
66+
if user != nil && password != nil {
67+
cloneRepoGitProvider = createGitProviderWithConfig(gitproviderv2.Config{
68+
Username: *user,
69+
Token: *password,
70+
})
7471
}
7572

76-
k := string(secret.Data[util.PrivateSShKeyName])
77-
u := gs.GitUser
78-
// CheckoutRemoteBranchBySSH(key, user, gitPath, remoteBranchName string)
79-
if err := g.CheckoutRemoteBranchBySSH(k, u, projectPath, branchName); err != nil {
73+
if err := cloneRepoGitProvider.Checkout(ctx, projectPath, branchName, true); err != nil {
74+
return fmt.Errorf("failed to checkout to default branch %s (clone strategy): %w", branchName, err)
75+
}
76+
case "import":
77+
if err := g.CheckoutRemoteBranch(ctx, projectPath, branchName); err != nil {
8078
return fmt.Errorf("failed to checkout to default branch %s (import strategy): %w", branchName, err)
8179
}
82-
8380
default:
8481
return fmt.Errorf("failed to checkout, unsupported strategy: '%s'", cb.Spec.Strategy)
8582
}

controllers/codebase/service/chain/checkout_branch_test.go

Lines changed: 23 additions & 57 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
package chain
22

33
import (
4+
"context"
45
"errors"
56
"strings"
67
"testing"
@@ -13,7 +14,8 @@ import (
1314
"sigs.k8s.io/controller-runtime/pkg/client/fake"
1415

1516
codebaseApi "github.com/epam/edp-codebase-operator/v2/api/v1"
16-
gitServerMocks "github.com/epam/edp-codebase-operator/v2/pkg/git/mocks"
17+
gitproviderv2 "github.com/epam/edp-codebase-operator/v2/pkg/git/v2"
18+
gitServerMocks "github.com/epam/edp-codebase-operator/v2/pkg/git/v2/mocks"
1719
"github.com/epam/edp-codebase-operator/v2/pkg/util"
1820
)
1921

@@ -89,6 +91,7 @@ func TestCheckoutBranch_ShouldFailOnGetSecret(t *testing.T) {
8991
Repository: &codebaseApi.Repository{
9092
Url: "repo",
9193
},
94+
Strategy: codebaseApi.Clone,
9295
},
9396
}
9497

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

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

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

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

109-
func TestCheckoutBranch_ShouldFailOnCheckPermission(t *testing.T) {
110-
c := &codebaseApi.Codebase{
111-
ObjectMeta: metaV1.ObjectMeta{
112-
Name: "fake-name",
113-
Namespace: fakeNamespace,
114-
},
115-
Spec: codebaseApi.CodebaseSpec{
116-
Repository: &codebaseApi.Repository{
117-
Url: "repo",
118-
},
119-
},
120-
}
121-
s := &coreV1.Secret{
122-
ObjectMeta: metaV1.ObjectMeta{
123-
Name: "repository-codebase-fake-name-temp",
124-
Namespace: fakeNamespace,
125-
},
126-
Data: map[string][]byte{
127-
"username": []byte("user"),
128-
"password": []byte("pass"),
129-
},
130-
}
131-
scheme := runtime.NewScheme()
132-
133-
scheme.AddKnownTypes(coreV1.SchemeGroupVersion, s)
134-
scheme.AddKnownTypes(codebaseApi.GroupVersion, c)
135-
136-
fakeCl := fake.NewClientBuilder().WithScheme(scheme).WithRuntimeObjects(s, c).Build()
137-
138-
mGit := gitServerMocks.NewMockGit(t)
139-
mGit.On("CheckPermissions", testify.Anything, "repo", util.GetStringP("user"), util.GetStringP("pass")).Return(false)
140-
141-
err := CheckoutBranch("repo", "project-path", "branch", mGit, c, fakeCl)
142-
assert.Error(t, err)
143-
144-
if !strings.Contains(err.Error(), "user user cannot get access to the repository repo") {
145-
t.Fatalf("wrong error returned: %s", err.Error())
146-
}
147-
}
148-
149115
func TestCheckoutBranch_ShouldFailOnGetCurrentBranchName(t *testing.T) {
150116
c := &codebaseApi.Codebase{
151117
ObjectMeta: metaV1.ObjectMeta{
@@ -156,6 +122,7 @@ func TestCheckoutBranch_ShouldFailOnGetCurrentBranchName(t *testing.T) {
156122
Repository: &codebaseApi.Repository{
157123
Url: "repo",
158124
},
125+
Strategy: codebaseApi.Clone,
159126
},
160127
}
161128
s := &coreV1.Secret{
@@ -174,10 +141,11 @@ func TestCheckoutBranch_ShouldFailOnGetCurrentBranchName(t *testing.T) {
174141
fakeCl := fake.NewClientBuilder().WithScheme(scheme).WithRuntimeObjects(s, c).Build()
175142

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

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

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

188156
func TestCheckoutBranch_ShouldFailOnCheckout(t *testing.T) {
189157
repo := "repo"
190-
u := "user1"
191-
p := "pass1"
192158
c := &codebaseApi.Codebase{
193159
ObjectMeta: metaV1.ObjectMeta{
194160
Name: "fake-name",
@@ -217,11 +183,12 @@ func TestCheckoutBranch_ShouldFailOnCheckout(t *testing.T) {
217183
fakeCl := fake.NewClientBuilder().WithScheme(scheme).WithRuntimeObjects(s, c).Build()
218184

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

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

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

232199
func TestCheckoutBranch_ShouldPassForCloneStrategy(t *testing.T) {
233200
repo := "repo"
234-
u := "user"
235-
p := "pass"
236201
c := &codebaseApi.Codebase{
237202
ObjectMeta: metaV1.ObjectMeta{
238203
Name: "fake-name",
@@ -283,10 +248,11 @@ func TestCheckoutBranch_ShouldPassForCloneStrategy(t *testing.T) {
283248
fakeCl := fake.NewClientBuilder().WithScheme(scheme).WithRuntimeObjects(s, c, gs, ssh).Build()
284249

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

290-
err := CheckoutBranch(repo, "project-path", "branch", mGit, c, fakeCl)
254+
err := CheckoutBranch(context.Background(), repo, "project-path", "branch", mGit, c, fakeCl, func(config gitproviderv2.Config) gitproviderv2.Git {
255+
return mGit
256+
})
291257
assert.NoError(t, err)
292258
}

0 commit comments

Comments
 (0)