Skip to content

Commit 2bbcd91

Browse files
committed
Add artifact to Git and Helm repos status
- create index.yaml symlink for Helm repos - set symlink URL in status
1 parent 461c015 commit 2bbcd91

File tree

4 files changed

+149
-104
lines changed

4 files changed

+149
-104
lines changed

controllers/conditions.go

+58
Original file line numberDiff line numberDiff line change
@@ -42,3 +42,61 @@ func NotReadyCondition(reason, message string) sourcev1.SourceCondition {
4242
Message: message,
4343
}
4444
}
45+
46+
func ReadyGitRepository(repository sourcev1.GitRepository, artifact sourcev1.Artifact, url, reason, message string) sourcev1.GitRepository {
47+
repository.Status.Conditions = []sourcev1.SourceCondition{ReadyCondition(reason, message)}
48+
repository.Status.URL = url
49+
50+
if repository.Status.Artifact != nil {
51+
if repository.Status.Artifact.Path != artifact.Path {
52+
repository.Status.Artifact = &artifact
53+
}
54+
} else {
55+
repository.Status.Artifact = &artifact
56+
}
57+
58+
return repository
59+
}
60+
61+
func NotReadyGitRepository(repository sourcev1.GitRepository, reason, message string) sourcev1.GitRepository {
62+
repository.Status.Conditions = []sourcev1.SourceCondition{NotReadyCondition(reason, message)}
63+
return repository
64+
}
65+
66+
func GitRepositoryReadyMessage(repository sourcev1.GitRepository) string {
67+
for _, condition := range repository.Status.Conditions {
68+
if condition.Type == sourcev1.ReadyCondition {
69+
return condition.Message
70+
}
71+
}
72+
return ""
73+
}
74+
75+
func ReadyHelmRepository(repository sourcev1.HelmRepository, artifact sourcev1.Artifact, url, reason, message string) sourcev1.HelmRepository {
76+
repository.Status.Conditions = []sourcev1.SourceCondition{ReadyCondition(reason, message)}
77+
repository.Status.URL = url
78+
79+
if repository.Status.Artifact != nil {
80+
if repository.Status.Artifact.Path != artifact.Path {
81+
repository.Status.Artifact = &artifact
82+
}
83+
} else {
84+
repository.Status.Artifact = &artifact
85+
}
86+
87+
return repository
88+
}
89+
90+
func NotReadyHelmRepository(repository sourcev1.HelmRepository, reason, message string) sourcev1.HelmRepository {
91+
repository.Status.Conditions = []sourcev1.SourceCondition{NotReadyCondition(reason, message)}
92+
return repository
93+
}
94+
95+
func HelmRepositoryReadyMessage(repository sourcev1.HelmRepository) string {
96+
for _, condition := range repository.Status.Conditions {
97+
if condition.Type == sourcev1.ReadyCondition {
98+
return condition.Message
99+
}
100+
}
101+
return ""
102+
}

controllers/gitrepository_controller.go

+39-42
Original file line numberDiff line numberDiff line change
@@ -83,28 +83,19 @@ func (r *GitRepositoryReconciler) Reconcile(req ctrl.Request) (ctrl.Result, erro
8383
r.gc(repo)
8484

8585
// try git clone
86-
readyCondition, artifacts, err := r.sync(repo)
86+
syncedRepo, err := r.sync(*repo.DeepCopy())
8787
if err != nil {
8888
log.Info("Repository sync failed", "error", err.Error())
89-
} else {
90-
// update artifacts if commit hash changed
91-
if repo.Status.Artifact != artifacts {
92-
timeNew := metav1.Now()
93-
repo.Status.LastUpdateTime = &timeNew
94-
repo.Status.Artifact = artifacts
95-
}
96-
log.Info("Repository sync succeeded", "msg", readyCondition.Message)
9789
}
9890

9991
// update status
100-
readyCondition.LastTransitionTime = metav1.Now()
101-
repo.Status.Conditions = []sourcev1.SourceCondition{readyCondition}
102-
103-
if err := r.Status().Update(ctx, &repo); err != nil {
92+
if err := r.Status().Update(ctx, &syncedRepo); err != nil {
10493
log.Error(err, "unable to update GitRepository status")
10594
return result, err
10695
}
10796

97+
log.Info("Repository sync succeeded", "msg", GitRepositoryReadyMessage(syncedRepo))
98+
10899
// requeue repository
109100
return result, nil
110101
}
@@ -116,7 +107,7 @@ func (r *GitRepositoryReconciler) SetupWithManager(mgr ctrl.Manager) error {
116107
WithEventFilter(predicate.Funcs{
117108
DeleteFunc: func(e event.DeleteEvent) bool {
118109
// delete artifacts
119-
artifact := r.Storage.ArtifactFor(r.Kind, e.Meta, "dummy")
110+
artifact := r.Storage.ArtifactFor(r.Kind, e.Meta, "dummy", "")
120111
if err := r.Storage.RemoveAll(artifact); err != nil {
121112
r.Log.Error(err, "unable to delete artifacts",
122113
r.Kind, fmt.Sprintf("%s/%s", e.Meta.GetNamespace(), e.Meta.GetName()))
@@ -130,9 +121,10 @@ func (r *GitRepositoryReconciler) SetupWithManager(mgr ctrl.Manager) error {
130121
Complete(r)
131122
}
132123

133-
func (r *GitRepositoryReconciler) sync(repository sourcev1.GitRepository) (sourcev1.SourceCondition, string, error) {
124+
func (r *GitRepositoryReconciler) sync(repository sourcev1.GitRepository) (sourcev1.GitRepository, error) {
134125
// set defaults: master branch, no tags fetching, max two commits
135126
branch := "master"
127+
revision := ""
136128
tagMode := git.NoTags
137129
depth := 2
138130

@@ -159,21 +151,21 @@ func (r *GitRepositoryReconciler) sync(repository sourcev1.GitRepository) (sourc
159151
tmpSSH, err := ioutil.TempDir("", repository.Name)
160152
if err != nil {
161153
err = fmt.Errorf("tmp dir error: %w", err)
162-
return NotReadyCondition(sourcev1.StorageOperationFailedReason, err.Error()), "", err
154+
return NotReadyGitRepository(repository, sourcev1.StorageOperationFailedReason, err.Error()), err
163155
}
164156
defer os.RemoveAll(tmpSSH)
165157

166158
auth, err := r.auth(repository, tmpSSH)
167159
if err != nil {
168160
err = fmt.Errorf("auth error: %w", err)
169-
return NotReadyCondition(sourcev1.AuthenticationFailedReason, err.Error()), "", err
161+
return NotReadyGitRepository(repository, sourcev1.StorageOperationFailedReason, err.Error()), err
170162
}
171163

172164
// create tmp dir for the Git clone
173165
tmpGit, err := ioutil.TempDir("", repository.Name)
174166
if err != nil {
175167
err = fmt.Errorf("tmp dir error: %w", err)
176-
return NotReadyCondition(sourcev1.StorageOperationFailedReason, err.Error()), "", err
168+
return NotReadyGitRepository(repository, sourcev1.StorageOperationFailedReason, err.Error()), err
177169
}
178170
defer os.RemoveAll(tmpGit)
179171

@@ -192,7 +184,7 @@ func (r *GitRepositoryReconciler) sync(repository sourcev1.GitRepository) (sourc
192184
})
193185
if err != nil {
194186
err = fmt.Errorf("git clone error: %w", err)
195-
return NotReadyCondition(sourcev1.GitOperationFailedReason, err.Error()), "", err
187+
return NotReadyGitRepository(repository, sourcev1.GitOperationFailedReason, err.Error()), err
196188
}
197189

198190
// checkout commit or tag
@@ -201,7 +193,7 @@ func (r *GitRepositoryReconciler) sync(repository sourcev1.GitRepository) (sourc
201193
w, err := repo.Worktree()
202194
if err != nil {
203195
err = fmt.Errorf("git worktree error: %w", err)
204-
return NotReadyCondition(sourcev1.GitOperationFailedReason, err.Error()), "", err
196+
return NotReadyGitRepository(repository, sourcev1.GitOperationFailedReason, err.Error()), err
205197
}
206198

207199
err = w.Checkout(&git.CheckoutOptions{
@@ -210,19 +202,19 @@ func (r *GitRepositoryReconciler) sync(repository sourcev1.GitRepository) (sourc
210202
})
211203
if err != nil {
212204
err = fmt.Errorf("git checkout %s for %s error: %w", commit, branch, err)
213-
return NotReadyCondition(sourcev1.GitOperationFailedReason, err.Error()), "", err
205+
return NotReadyGitRepository(repository, sourcev1.GitOperationFailedReason, err.Error()), err
214206
}
215207
} else if exp := repository.Spec.Reference.SemVer; exp != "" {
216208
rng, err := semver.ParseRange(exp)
217209
if err != nil {
218210
err = fmt.Errorf("semver parse range error: %w", err)
219-
return NotReadyCondition(sourcev1.GitOperationFailedReason, err.Error()), "", err
211+
return NotReadyGitRepository(repository, sourcev1.GitOperationFailedReason, err.Error()), err
220212
}
221213

222214
repoTags, err := repo.Tags()
223215
if err != nil {
224216
err = fmt.Errorf("git list tags error: %w", err)
225-
return NotReadyCondition(sourcev1.GitOperationFailedReason, err.Error()), "", err
217+
return NotReadyGitRepository(repository, sourcev1.GitOperationFailedReason, err.Error()), err
226218
}
227219

228220
tags := make(map[string]string)
@@ -246,23 +238,24 @@ func (r *GitRepositoryReconciler) sync(repository sourcev1.GitRepository) (sourc
246238
v := svers[len(svers)-1]
247239
t := svTags[v.String()]
248240
commit := tags[t]
241+
revision = fmt.Sprintf("%s/%s", t, commit)
249242

250243
w, err := repo.Worktree()
251244
if err != nil {
252245
err = fmt.Errorf("git worktree error: %w", err)
253-
return NotReadyCondition(sourcev1.GitOperationFailedReason, err.Error()), "", err
246+
return NotReadyGitRepository(repository, sourcev1.GitOperationFailedReason, err.Error()), err
254247
}
255248

256249
err = w.Checkout(&git.CheckoutOptions{
257250
Hash: plumbing.NewHash(commit),
258251
})
259252
if err != nil {
260253
err = fmt.Errorf("git checkout error: %w", err)
261-
return NotReadyCondition(sourcev1.GitOperationFailedReason, err.Error()), "", err
254+
return NotReadyGitRepository(repository, sourcev1.GitOperationFailedReason, err.Error()), err
262255
}
263256
} else {
264257
err = fmt.Errorf("no match found for semver: %s", repository.Spec.Reference.SemVer)
265-
return NotReadyCondition(sourcev1.GitOperationFailedReason, err.Error()), "", err
258+
return NotReadyGitRepository(repository, sourcev1.GitOperationFailedReason, err.Error()), err
266259
}
267260
}
268261
}
@@ -271,51 +264,53 @@ func (r *GitRepositoryReconciler) sync(repository sourcev1.GitRepository) (sourc
271264
ref, err := repo.Head()
272265
if err != nil {
273266
err = fmt.Errorf("git resolve HEAD error: %w", err)
274-
return NotReadyCondition(sourcev1.GitOperationFailedReason, err.Error()), "", err
267+
return NotReadyGitRepository(repository, sourcev1.GitOperationFailedReason, err.Error()), err
268+
}
269+
270+
if revision == "" {
271+
revision = fmt.Sprintf("%s/%s", branch, ref.Hash().String())
275272
}
276273

277274
artifact := r.Storage.ArtifactFor(r.Kind, repository.ObjectMeta.GetObjectMeta(),
278-
fmt.Sprintf("%s.tar.gz", ref.Hash().String()))
275+
fmt.Sprintf("%s.tar.gz", ref.Hash().String()), revision)
279276

280277
// create artifact dir
281278
err = r.Storage.MkdirAll(artifact)
282279
if err != nil {
283280
err = fmt.Errorf("mkdir dir error: %w", err)
284-
return NotReadyCondition(sourcev1.StorageOperationFailedReason, err.Error()), "", err
281+
return NotReadyGitRepository(repository, sourcev1.StorageOperationFailedReason, err.Error()), err
285282
}
286283

287284
// acquire lock
288285
unlock, err := r.Storage.Lock(artifact)
289286
if err != nil {
290287
err = fmt.Errorf("unable to acquire lock: %w", err)
291-
return NotReadyCondition(sourcev1.StorageOperationFailedReason, err.Error()), "", err
288+
return NotReadyGitRepository(repository, sourcev1.StorageOperationFailedReason, err.Error()), err
292289
}
293290
defer unlock()
294291

295292
// archive artifact
296293
err = r.Storage.Archive(artifact, tmpGit, "")
297294
if err != nil {
298295
err = fmt.Errorf("storage archive error: %w", err)
299-
return NotReadyCondition(sourcev1.StorageOperationFailedReason, err.Error()), "", err
296+
return NotReadyGitRepository(repository, sourcev1.StorageOperationFailedReason, err.Error()), err
300297
}
301298

302299
// update latest symlink
303-
err = r.Storage.Symlink(artifact, "latest.tar.gz")
300+
url, err := r.Storage.Symlink(artifact, "latest.tar.gz")
304301
if err != nil {
305302
err = fmt.Errorf("storage lock error: %w", err)
306-
return NotReadyCondition(sourcev1.StorageOperationFailedReason, err.Error()), "", err
303+
return NotReadyGitRepository(repository, sourcev1.StorageOperationFailedReason, err.Error()), err
307304
}
308305

309306
message := fmt.Sprintf("Artifact is available at: %s", artifact.Path)
310-
return ReadyCondition(sourcev1.GitOperationSucceedReason, message), artifact.URL, nil
307+
return ReadyGitRepository(repository, artifact, url, sourcev1.GitOperationSucceedReason, message), nil
311308
}
312309

313310
func (r *GitRepositoryReconciler) shouldResetStatus(repository sourcev1.GitRepository) (bool, sourcev1.GitRepositoryStatus) {
314311
resetStatus := false
315-
if repository.Status.Artifact != "" {
316-
parts := strings.Split(repository.Status.Artifact, "/")
317-
artifact := r.Storage.ArtifactFor(r.Kind, repository.ObjectMeta.GetObjectMeta(), parts[len(parts)-1])
318-
if !r.Storage.ArtifactExist(artifact) {
312+
if repository.Status.Artifact != nil {
313+
if !r.Storage.ArtifactExist(*repository.Status.Artifact) {
319314
resetStatus = true
320315
}
321316
}
@@ -338,10 +333,8 @@ func (r *GitRepositoryReconciler) shouldResetStatus(repository sourcev1.GitRepos
338333
}
339334

340335
func (r *GitRepositoryReconciler) gc(repository sourcev1.GitRepository) {
341-
if repository.Status.Artifact != "" {
342-
parts := strings.Split(repository.Status.Artifact, "/")
343-
artifact := r.Storage.ArtifactFor(r.Kind, repository.ObjectMeta.GetObjectMeta(), parts[len(parts)-1])
344-
if err := r.Storage.RemoveAllButCurrent(artifact); err != nil {
336+
if repository.Status.Artifact != nil {
337+
if err := r.Storage.RemoveAllButCurrent(*repository.Status.Artifact); err != nil {
345338
r.Log.Info("Artifacts GC failed", "error", err)
346339
}
347340
}
@@ -370,9 +363,13 @@ func (r *GitRepositoryReconciler) auth(repository sourcev1.GitRepository, tmp st
370363
auth := &http.BasicAuth{}
371364
if username, ok := credentials["username"]; ok {
372365
auth.Username = string(username)
366+
} else {
367+
return nil, fmt.Errorf("%s secret does not contain username", repository.Spec.SecretRef.Name)
373368
}
374369
if password, ok := credentials["password"]; ok {
375370
auth.Password = string(password)
371+
} else {
372+
return nil, fmt.Errorf("%s secret does not contain password", repository.Spec.SecretRef.Name)
376373
}
377374

378375
if auth.Username == "" || auth.Password == "" {

0 commit comments

Comments
 (0)