Skip to content

Commit 11851a0

Browse files
author
Paulo Gomes
authored
Merge pull request #410 from pjbgf/early-eof
Enrich `early EOF` error message
2 parents 46e4f99 + 5ccda9c commit 11851a0

File tree

7 files changed

+144
-40
lines changed

7 files changed

+144
-40
lines changed

DEVELOPMENT.md

Lines changed: 29 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -155,4 +155,32 @@ Deploy `image-automation-controller` into the cluster that is configured in the
155155

156156
```sh
157157
make deploy
158-
```
158+
```
159+
160+
### Debugging controller with VSCode
161+
162+
Create a `.vscode/launch.json` file:
163+
```json
164+
{
165+
"version": "0.2.0",
166+
"configurations": [
167+
{
168+
"name": "Launch Package",
169+
"type": "go",
170+
"request": "launch",
171+
"mode": "auto",
172+
"envFile": "${workspaceFolder}/build/.env",
173+
"program": "${workspaceFolder}/main.go"
174+
}
175+
]
176+
}
177+
```
178+
179+
Create the environment file containing details on how to load
180+
`libgit2` dependencies:
181+
```bash
182+
make env
183+
```
184+
185+
Start debugging by either clicking `Run` > `Start Debugging` or using
186+
the relevant shortcut.

Makefile

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -301,3 +301,15 @@ endif
301301
.PHONY: help
302302
help: ## Display this help menu
303303
@awk 'BEGIN {FS = ":.*##"; printf "\nUsage:\n make \033[36m<target>\033[0m\n"} /^[a-zA-Z_0-9-]+:.*?##/ { printf " \033[36m%-20s\033[0m %s\n", $$1, $$2 } /^##@/ { printf "\n\033[1m%s\033[0m\n", substr($$0, 5) } ' $(MAKEFILE_LIST)
304+
305+
# Creates an env file that can be used to load all image-automation-controller's
306+
# dependencies this is handy when you want to run adhoc debug sessions on tests or
307+
# start the controller in a new debug session.
308+
env: $(LIBGIT2)
309+
echo 'GO_ENABLED="1"' > $(BUILD_DIR)/.env
310+
echo 'PKG_CONFIG_PATH="$(PKG_CONFIG_PATH)"' >> $(BUILD_DIR)/.env
311+
echo 'LIBRARY_PATH="$(LIBRARY_PATH)"' >> $(BUILD_DIR)/.env
312+
echo 'CGO_CFLAGS="$(CGO_CFLAGS)"' >> $(BUILD_DIR)/.env
313+
echo 'CGO_LDFLAGS="$(CGO_LDFLAGS)"' >> $(BUILD_DIR)/.env
314+
echo 'KUBEBUILDER_ASSETS=$(KUBEBUILDER_ASSETS)' >> $(BUILD_DIR)/.env
315+
echo 'GIT_CONFIG_GLOBAL=/dev/null' >> $(BUILD_DIR)/.env

controllers/git_test.go

Lines changed: 53 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ import (
1414
"k8s.io/apimachinery/pkg/types"
1515

1616
"github.com/fluxcd/pkg/gittestserver"
17+
"github.com/fluxcd/source-controller/pkg/git"
1718
)
1819

1920
func populateRepoFromFixture(repo *libgit2.Repository, fixture string) error {
@@ -141,13 +142,13 @@ func TestPushRejected(t *testing.T) {
141142
repoURL := gitServer.HTTPAddressWithCredentials() + "/appconfig.git"
142143
cloneCtx, cancel := context.WithTimeout(ctx, time.Second*10)
143144
defer cancel()
144-
repo, err := clone(cloneCtx, repoURL, "test")
145+
repo, err := clone(cloneCtx, repoURL, "test", nil)
145146
if err != nil {
146147
t.Fatal(err)
147148
}
148149
defer repo.Free()
149150

150-
cleanup, err := configureTransportOptsForRepo(repo)
151+
cleanup, err := configureTransportOptsForRepo(repo, nil)
151152
if err != nil {
152153
t.Fatal(err)
153154
}
@@ -172,6 +173,54 @@ func TestPushRejected(t *testing.T) {
172173
}
173174
}
174175

176+
func TestEarlyEOF(t *testing.T) {
177+
g := NewWithT(t)
178+
179+
gitServer, err := gittestserver.NewTempGitServer()
180+
g.Expect(err).ToNot(HaveOccurred())
181+
defer os.RemoveAll(gitServer.Root())
182+
183+
username := "norris"
184+
password := "chuck"
185+
186+
gitServer.
187+
AutoCreate().
188+
KeyDir(filepath.Join(t.TempDir(), "keys")).
189+
Auth(username, password).
190+
ReadOnly(true)
191+
192+
err = gitServer.StartHTTP()
193+
g.Expect(err).ToNot(HaveOccurred())
194+
195+
err = initGitRepo(gitServer, "testdata/appconfig", "test", "/appconfig.git")
196+
g.Expect(err).ToNot(HaveOccurred())
197+
198+
repoURL := gitServer.HTTPAddressWithCredentials() + "/appconfig.git"
199+
cloneCtx, cancel := context.WithTimeout(ctx, time.Second*10)
200+
defer cancel()
201+
202+
access := repoAccess{
203+
auth: &git.AuthOptions{
204+
Username: username,
205+
Password: password,
206+
},
207+
}
208+
209+
repo, err := clone(cloneCtx, repoURL, "test", access.auth)
210+
g.Expect(err).ToNot(HaveOccurred())
211+
212+
defer repo.Free()
213+
214+
cleanup, err := configureTransportOptsForRepo(repo, access.auth)
215+
g.Expect(err).ToNot(HaveOccurred())
216+
217+
defer cleanup()
218+
219+
err = push(context.TODO(), repo.Workdir(), "test", access)
220+
g.Expect(err).To(HaveOccurred())
221+
g.Expect(err.Error()).To(ContainSubstring("early EOF (the SSH key may not have write access to the repository)"))
222+
}
223+
175224
func Test_switchToBranch(t *testing.T) {
176225
g := NewWithT(t)
177226
gitServer, err := gittestserver.NewTempGitServer()
@@ -190,7 +239,7 @@ func Test_switchToBranch(t *testing.T) {
190239
repoURL := gitServer.HTTPAddressWithCredentials() + "/appconfig.git"
191240
cloneCtx, cancel := context.WithTimeout(ctx, time.Second*10)
192241
defer cancel()
193-
repo, err := clone(cloneCtx, repoURL, branch)
242+
repo, err := clone(cloneCtx, repoURL, branch, nil)
194243
g.Expect(err).ToNot(HaveOccurred())
195244
defer repo.Free()
196245

@@ -200,7 +249,7 @@ func Test_switchToBranch(t *testing.T) {
200249
target := head.Target()
201250

202251
// register transport options and update remote to transport url
203-
cleanup, err := configureTransportOptsForRepo(repo)
252+
cleanup, err := configureTransportOptsForRepo(repo, nil)
204253
if err != nil {
205254
t.Fatal(err)
206255
}

controllers/imageupdateautomation_controller.go

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -887,6 +887,9 @@ func push(ctx context.Context, path, branch string, access repoAccess) error {
887887
ProxyOptions: libgit2.ProxyOptions{Type: libgit2.ProxyTypeAuto},
888888
})
889889
if err != nil {
890+
if strings.Contains(err.Error(), "early EOF") {
891+
return fmt.Errorf("%w (the SSH key may not have write access to the repository)", err)
892+
}
890893
return libgit2PushError(err)
891894
}
892895
return callbackErr

controllers/update_test.go

Lines changed: 20 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -54,6 +54,7 @@ import (
5454
"github.com/fluxcd/pkg/gittestserver"
5555
"github.com/fluxcd/pkg/ssh"
5656
sourcev1 "github.com/fluxcd/source-controller/api/v1beta2"
57+
"github.com/fluxcd/source-controller/pkg/git"
5758
"github.com/fluxcd/source-controller/pkg/git/libgit2/managed"
5859

5960
imagev1 "github.com/fluxcd/image-automation-controller/api/v1beta1"
@@ -484,7 +485,7 @@ func TestImageAutomationReconciler_e2e(t *testing.T) {
484485
// Clone the repo locally.
485486
cloneCtx, cancel := context.WithTimeout(ctx, timeout)
486487
defer cancel()
487-
localRepo, err := clone(cloneCtx, cloneLocalRepoURL, branch)
488+
localRepo, err := clone(cloneCtx, cloneLocalRepoURL, branch, nil)
488489
g.Expect(err).ToNot(HaveOccurred(), "failed to clone git repo")
489490
defer localRepo.Free()
490491

@@ -628,7 +629,7 @@ func TestImageAutomationReconciler_e2e(t *testing.T) {
628629
// separate localRepo.
629630
cloneCtx, cancel := context.WithTimeout(ctx, timeout)
630631
defer cancel()
631-
localRepo, err := clone(cloneCtx, cloneLocalRepoURL, branch)
632+
localRepo, err := clone(cloneCtx, cloneLocalRepoURL, branch, nil)
632633
g.Expect(err).ToNot(HaveOccurred(), "failed to clone git repo")
633634
defer localRepo.Free()
634635

@@ -880,7 +881,7 @@ func compareRepoWithExpected(g *WithT, repoURL, branch, fixture string, changeFi
880881
changeFixture(expected)
881882
cloneCtx, cancel := context.WithTimeout(ctx, timeout)
882883
defer cancel()
883-
repo, err := clone(cloneCtx, repoURL, branch)
884+
repo, err := clone(cloneCtx, repoURL, branch, nil)
884885
g.Expect(err).ToNot(HaveOccurred())
885886
defer repo.Free()
886887
// NOTE: The workdir contains a trailing /. Clean it to not confuse the
@@ -897,7 +898,7 @@ func compareRepoWithExpected(g *WithT, repoURL, branch, fixture string, changeFi
897898
// it tries to figure it out by looking at the remote url of origin. It returns a function
898899
// which removes the transport options for this repo and sets the remote url of the origin
899900
// back to the actual url. Callers are expected to call this function in a deferred manner.
900-
func configureTransportOptsForRepo(repo *libgit2.Repository) (func(), error) {
901+
func configureTransportOptsForRepo(repo *libgit2.Repository, authOpts *git.AuthOptions) (func(), error) {
901902
origin, err := repo.Remotes.Lookup(originRemote)
902903
if err != nil {
903904
return nil, err
@@ -911,6 +912,7 @@ func configureTransportOptsForRepo(repo *libgit2.Repository) (func(), error) {
911912
transportOptsURL := u.Scheme + "://" + randStringRunes(5)
912913
managed.AddTransportOptions(transportOptsURL, managed.TransportOptions{
913914
TargetURL: repoURL,
915+
AuthOpts: authOpts,
914916
})
915917

916918
err = repo.Remotes.SetUrl(originRemote, transportOptsURL)
@@ -926,7 +928,7 @@ func configureTransportOptsForRepo(repo *libgit2.Repository) (func(), error) {
926928
func commitInRepo(g *WithT, repoURL, branch, msg string, changeFiles func(path string)) *libgit2.Oid {
927929
cloneCtx, cancel := context.WithTimeout(ctx, timeout)
928930
defer cancel()
929-
repo, err := clone(cloneCtx, repoURL, branch)
931+
repo, err := clone(cloneCtx, repoURL, branch, nil)
930932
g.Expect(err).ToNot(HaveOccurred())
931933
defer repo.Free()
932934

@@ -940,7 +942,7 @@ func commitInRepo(g *WithT, repoURL, branch, msg string, changeFiles func(path s
940942
id, err := commitWorkDir(repo, branch, msg, sig)
941943
g.Expect(err).ToNot(HaveOccurred())
942944

943-
cleanup, err := configureTransportOptsForRepo(repo)
945+
cleanup, err := configureTransportOptsForRepo(repo, nil)
944946
g.Expect(err).ToNot(HaveOccurred())
945947
defer cleanup()
946948
origin, err := repo.Remotes.Lookup(originRemote)
@@ -1177,15 +1179,22 @@ func mockSignature(time time.Time) *git2go.Signature {
11771179
}
11781180
}
11791181

1180-
func clone(ctx context.Context, repoURL, branchName string) (*git2go.Repository, error) {
1182+
func clone(ctx context.Context, repoURL, branchName string, authOpts *git.AuthOptions) (*git2go.Repository, error) {
11811183
dir, err := os.MkdirTemp("", "iac-clone-*")
11821184
if err != nil {
11831185
return nil, err
11841186
}
1185-
transportOptsURL := "http://" + randStringRunes(5)
1187+
1188+
u, err := url.Parse(repoURL)
1189+
if err != nil {
1190+
return nil, err
1191+
}
1192+
1193+
transportOptsURL := u.Scheme + "://" + randStringRunes(5)
11861194
managed.AddTransportOptions(transportOptsURL, managed.TransportOptions{
11871195
TargetURL: repoURL,
11881196
Context: ctx,
1197+
AuthOpts: authOpts,
11891198
})
11901199
defer managed.RemoveTransportOptions(transportOptsURL)
11911200

@@ -1214,7 +1223,7 @@ func clone(ctx context.Context, repoURL, branchName string) (*git2go.Repository,
12141223
func waitForNewHead(g *WithT, repo *git2go.Repository, branch, preChangeHash string) {
12151224
var commitToResetTo *git2go.Commit
12161225

1217-
cleanup, err := configureTransportOptsForRepo(repo)
1226+
cleanup, err := configureTransportOptsForRepo(repo, nil)
12181227
g.Expect(err).ToNot(HaveOccurred())
12191228
defer cleanup()
12201229

@@ -1272,7 +1281,7 @@ func commitIdFromBranch(repo *git2go.Repository, branchName string) string {
12721281
}
12731282

12741283
func getRemoteHead(repo *git2go.Repository, branchName string) (*git2go.Oid, error) {
1275-
cleanup, err := configureTransportOptsForRepo(repo)
1284+
cleanup, err := configureTransportOptsForRepo(repo, nil)
12761285
if err != nil {
12771286
return nil, err
12781287
}
@@ -1460,7 +1469,7 @@ func testWithCustomRepoAndImagePolicy(
14601469
repoURL := gitServer.HTTPAddressWithCredentials() + repositoryPath
14611470
cloneCtx, cancel := context.WithTimeout(ctx, timeout)
14621471
defer cancel()
1463-
localRepo, err := clone(cloneCtx, repoURL, args.branch)
1472+
localRepo, err := clone(cloneCtx, repoURL, args.branch, nil)
14641473
g.Expect(err).ToNot(HaveOccurred(), "failed to clone git repo")
14651474
defer localRepo.Free()
14661475

go.mod

Lines changed: 9 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -12,17 +12,18 @@ require (
1212
github.com/fluxcd/image-reflector-controller/api v0.19.3
1313
github.com/fluxcd/pkg/apis/acl v0.0.3
1414
github.com/fluxcd/pkg/apis/meta v0.14.2
15-
github.com/fluxcd/pkg/gittestserver v0.5.4
15+
github.com/fluxcd/pkg/gittestserver v0.6.0
1616
github.com/fluxcd/pkg/runtime v0.16.2
1717
github.com/fluxcd/pkg/ssh v0.5.0
1818
github.com/fluxcd/source-controller v0.25.10
1919
github.com/fluxcd/source-controller/api v0.25.10
2020
github.com/go-logr/logr v1.2.3
21-
github.com/google/go-containerregistry v0.10.0
21+
github.com/google/go-containerregistry v0.11.0
2222
github.com/libgit2/git2go/v33 v33.0.9
23-
github.com/onsi/gomega v1.19.0
23+
github.com/onsi/gomega v1.20.0
2424
github.com/otiai10/copy v1.7.0
2525
github.com/spf13/pflag v1.0.5
26+
golang.org/x/crypto v0.0.0-20220722155217-630584e8d5aa
2627
k8s.io/api v0.24.2
2728
k8s.io/apimachinery v0.24.2
2829
k8s.io/client-go v0.24.2
@@ -55,7 +56,7 @@ require (
5556
github.com/emicklei/go-restful/v3 v3.8.0 // indirect
5657
github.com/emirpasic/gods v1.18.1 // indirect
5758
github.com/evanphx/json-patch v5.6.0+incompatible // indirect
58-
github.com/fluxcd/gitkit v0.5.1 // indirect
59+
github.com/fluxcd/gitkit v0.6.0 // indirect
5960
github.com/fluxcd/pkg/gitutil v0.1.0 // indirect
6061
github.com/fluxcd/pkg/version v0.1.0 // indirect
6162
github.com/fsnotify/fsnotify v1.5.1 // indirect
@@ -96,6 +97,7 @@ require (
9697
github.com/modern-go/reflect2 v1.0.2 // indirect
9798
github.com/monochromegane/go-gitignore v0.0.0-20200626010858-205db1a8cc00 // indirect
9899
github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 // indirect
100+
github.com/opencontainers/go-digest v1.0.0 // indirect
99101
github.com/pkg/errors v0.9.1 // indirect
100102
github.com/prometheus/client_golang v1.12.2 // indirect
101103
github.com/prometheus/client_model v0.2.0 // indirect
@@ -110,10 +112,9 @@ require (
110112
go.uber.org/atomic v1.7.0 // indirect
111113
go.uber.org/multierr v1.6.0 // indirect
112114
go.uber.org/zap v1.21.0 // indirect
113-
golang.org/x/crypto v0.0.0-20220622213112-05595931fe9d
114-
golang.org/x/net v0.0.0-20220706163947-c90051bbdb60 // indirect
115-
golang.org/x/oauth2 v0.0.0-20220622183110-fd043fe589d2 // indirect
116-
golang.org/x/sys v0.0.0-20220624220833-87e55d714810 // indirect
115+
golang.org/x/net v0.0.0-20220708220712-1185a9018129 // indirect
116+
golang.org/x/oauth2 v0.0.0-20220718184931-c8730f7fcb92 // indirect
117+
golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8 // indirect
117118
golang.org/x/term v0.0.0-20210927222741-03fcf44c2211 // indirect
118119
golang.org/x/text v0.3.7 // indirect
119120
golang.org/x/time v0.0.0-20220210224613-90d013bbcef8 // indirect

0 commit comments

Comments
 (0)