Skip to content

Commit

Permalink
Fixes error display and improves user experience in gipoller
Browse files Browse the repository at this point in the history
When the gitpoller job returns an error it is added to the `gitrepo` conditions so it
can be properly displayed by the UI.

It also reschedules the gitpoller job when the `gitrepo` spec is changed so job is inmediatelly
executed.

Signed-off-by: Xavi Garcia <[email protected]>
  • Loading branch information
0xavi0 committed Jun 21, 2024
1 parent 8b11049 commit 61b79ef
Show file tree
Hide file tree
Showing 5 changed files with 65 additions and 11 deletions.
17 changes: 16 additions & 1 deletion pkg/durations/durations.go
Original file line number Diff line number Diff line change
@@ -1,6 +1,10 @@
package durations

import "time"
import (
"time"

metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
)

const (
AgentRegistrationRetry = time.Minute * 1
Expand All @@ -27,3 +31,14 @@ const (
TriggerSleep = time.Second * 5
DefaultCpuPprofPeriod = time.Minute
)

// Equal reports whether the duration t is equal to u.
func Equal(t *metav1.Duration, u *metav1.Duration) bool {
if t == nil && u == nil {
return true
}
if t != nil && u != nil {
return t.Duration == u.Duration
}
return false
}
3 changes: 3 additions & 0 deletions pkg/git/poll/gitrepopolljob.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import (
"context"
"fmt"

"github.com/rancher/fleet/internal/cmd/controller/grutil"
v1alpha1 "github.com/rancher/fleet/pkg/apis/fleet.cattle.io/v1alpha1"
"github.com/reugn/go-quartz/quartz"
"golang.org/x/sync/semaphore"
Expand Down Expand Up @@ -66,6 +67,8 @@ func (j *GitRepoPollJob) fetchLatestCommitAndUpdateStatus(ctx context.Context) {
commit, err := j.fetcher.LatestCommit(ctx, &j.GitRepo, j.client)
if err != nil {
logger.Error(err, "error fetching commit", "gitrepo", j.GitRepo)
nsName := types.NamespacedName{Name: j.GitRepo.Name, Namespace: j.GitRepo.Namespace}
_ = grutil.UpdateErrorStatus(ctx, j.client, nsName, j.GitRepo.Status, err)
return
}
if j.GitRepo.Status.Commit != commit {
Expand Down
7 changes: 7 additions & 0 deletions pkg/git/poll/gitrepopolljob_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -86,6 +86,13 @@ var _ = Describe("GitRepoPollJob tests", func() {
err := client.Get(ctx, types.NamespacedName{Name: gitRepo.Name, Namespace: gitRepo.Namespace}, &updatedGitRepo)
Expect(err).ToNot(HaveOccurred())
Expect(updatedGitRepo.Status.Commit).To(Equal(gitRepo.Status.Commit))
errorFound := false
for _, c := range updatedGitRepo.Status.Conditions {
if c.Message == "Some error" {
errorFound = true
}
}
Expect(errorFound).To(BeTrue())
})
})
})
9 changes: 7 additions & 2 deletions pkg/git/poll/handler.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import (
"time"

v1alpha1 "github.com/rancher/fleet/pkg/apis/fleet.cattle.io/v1alpha1"
"github.com/rancher/fleet/pkg/durations"
"github.com/rancher/fleet/pkg/git"
"github.com/reugn/go-quartz/quartz"

Expand Down Expand Up @@ -77,9 +78,13 @@ func (h *Handler) AddOrModifyGitRepoPollJob(ctx context.Context, gitRepo v1alpha
return
}
previousInterval := gitRepoPollJob.GitRepo.Spec.PollingInterval
previousGeneration := gitRepoPollJob.GitRepo.Generation
gitRepoPollJob.GitRepo = gitRepo
if gitRepo.Spec.PollingInterval != previousInterval {
// ignoring the error because we're going to schedule immediately
if (previousGeneration != gitRepo.Generation) ||
!durations.Equal(gitRepo.Spec.PollingInterval, previousInterval) {
// Spec or polling interval changed
// Reschedule so the job is immediately executed
// (otherwise it'll wait until next timeout)
_ = h.scheduler.DeleteJob(gitRepoPollKey)
h.scheduleJob(ctx, gitRepoPollKey, gitRepo, true)
}
Expand Down
40 changes: 32 additions & 8 deletions pkg/git/poll/handler_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ var _ = Describe("Gitrepo pooling tests", func() {
client = fake.NewClientBuilder().WithScheme(scheme).WithRuntimeObjects(&gitRepo).WithStatusSubresource(&gitRepo).Build()
})
DescribeTable("Gitrepo pooling tests",
func(pollingInterval time.Duration, disablePolling bool,
func(pollingInterval time.Duration, disablePolling bool, changeSpec bool,
schedulerCalls func(gitRepo v1alpha1.GitRepo, pollingInterval time.Duration),
fetcherCalls func()) {
if pollingInterval != 0 {
Expand All @@ -49,6 +49,9 @@ var _ = Describe("Gitrepo pooling tests", func() {
gitRepo.Spec.PollingInterval = nil
}
gitRepo.Spec.DisablePolling = disablePolling
if changeSpec {
gitRepo.Generation = 2
}

handler := Handler{
scheduler: scheduler,
Expand All @@ -63,13 +66,13 @@ var _ = Describe("Gitrepo pooling tests", func() {
},

Entry("GitRepo is not present and disablePolling = true",
1*time.Second, true, func(gitRepo v1alpha1.GitRepo, pollingInterval time.Duration) {
1*time.Second, true, false, func(gitRepo v1alpha1.GitRepo, pollingInterval time.Duration) {
key := GitRepoPollKey(gitRepo)
scheduler.EXPECT().GetScheduledJob(key).Return(nil, quartz.ErrJobNotFound).Times(1)
}, func() {}),

Entry("Gitrepo is not present, not setting pollingInterval and disablePolling=false",
0*time.Second, false, func(gitRepo v1alpha1.GitRepo, pollingInterval time.Duration) {
0*time.Second, false, false, func(gitRepo v1alpha1.GitRepo, pollingInterval time.Duration) {
key := GitRepoPollKey(gitRepo)
scheduler.EXPECT().GetScheduledJob(key).Return(nil, quartz.ErrJobNotFound).Times(1)

Expand All @@ -84,7 +87,7 @@ var _ = Describe("Gitrepo pooling tests", func() {
),

Entry("Gitrepo is not present, setting pollingInterval to a specific value and disablePolling=false",
1999*time.Second, false, func(gitRepo v1alpha1.GitRepo, pollingInterval time.Duration) {
1999*time.Second, false, false, func(gitRepo v1alpha1.GitRepo, pollingInterval time.Duration) {
key := GitRepoPollKey(gitRepo)
scheduler.EXPECT().GetScheduledJob(key).Return(nil, quartz.ErrJobNotFound).Times(1)

Expand All @@ -99,7 +102,7 @@ var _ = Describe("Gitrepo pooling tests", func() {
),

Entry("gitrepo present, same polling interval, disablePolling=true",
10*time.Second, true, func(gitRepo v1alpha1.GitRepo, pollingInterval time.Duration) {
10*time.Second, true, false, func(gitRepo v1alpha1.GitRepo, pollingInterval time.Duration) {
key := GitRepoPollKey(gitRepo)
job := NewGitRepoPollJob(client, fetcher, gitRepo)
jobDetail := quartz.NewJobDetail(job, key)
Expand All @@ -115,7 +118,7 @@ var _ = Describe("Gitrepo pooling tests", func() {
),

Entry("gitrepo present, different polling interval, disablePolling=true",
10*time.Second, true, func(gitRepo v1alpha1.GitRepo, pollingInterval time.Duration) {
10*time.Second, true, false, func(gitRepo v1alpha1.GitRepo, pollingInterval time.Duration) {
key := GitRepoPollKey(gitRepo)
job := NewGitRepoPollJob(client, fetcher, gitRepo)
jobDetail := quartz.NewJobDetail(job, key)
Expand All @@ -131,7 +134,7 @@ var _ = Describe("Gitrepo pooling tests", func() {
),

Entry("gitrepo present, same polling interval, disablePolling=false",
10*time.Second, false, func(gitRepo v1alpha1.GitRepo, pollingInterval time.Duration) {
10*time.Second, false, false, func(gitRepo v1alpha1.GitRepo, pollingInterval time.Duration) {
key := GitRepoPollKey(gitRepo)
job := NewGitRepoPollJob(client, fetcher, gitRepo)
jobDetail := quartz.NewJobDetail(job, key)
Expand All @@ -145,7 +148,7 @@ var _ = Describe("Gitrepo pooling tests", func() {
),

Entry("gitrepo present, different polling interval, disablePolling=false",
1999*time.Second, false, func(gitRepo v1alpha1.GitRepo, pollingInterval time.Duration) {
1999*time.Second, false, false, func(gitRepo v1alpha1.GitRepo, pollingInterval time.Duration) {
gitRepoCopy := gitRepo
gitRepoCopy.Spec.PollingInterval = &metav1.Duration{Duration: 10 * time.Second}
key := GitRepoPollKey(gitRepoCopy)
Expand All @@ -164,6 +167,27 @@ var _ = Describe("Gitrepo pooling tests", func() {
fetcher.EXPECT().LatestCommit(gomock.Any(), gomock.Any(), gomock.Any()).Return("commit", nil).Times(1)
},
),

Entry("gitrepo present, same polling interval, disablePolling=false, generation changed",
10*time.Second, false, true, func(gitRepo v1alpha1.GitRepo, pollingInterval time.Duration) {
gitRepoCopy := gitRepo
gitRepoCopy.Generation = 1
key := GitRepoPollKey(gitRepoCopy)
job := NewGitRepoPollJob(client, fetcher, gitRepoCopy)
jobDetail := quartz.NewJobDetail(job, key)
schedJob := &mocks.MockScheduledJob{
Detail: jobDetail,
TriggerDuration: 10 * time.Second,
}
// gets the job and rechedules
scheduler.EXPECT().GetScheduledJob(key).Return(schedJob, nil).Times(1)
scheduler.EXPECT().DeleteJob(key).Return(nil).Times(1)
trigger := quartz.NewSimpleTrigger(10 * time.Second)
scheduler.EXPECT().ScheduleJob(jobDetail, trigger).Return(nil).Times(1)
}, func() {
fetcher.EXPECT().LatestCommit(gomock.Any(), gomock.Any(), gomock.Any()).Return("commit", nil).Times(1)
},
),
)
})

Expand Down

0 comments on commit 61b79ef

Please sign in to comment.