Skip to content

Commit 6b12d18

Browse files
authored
Merge pull request #102 from fluxcd/helm-repository-timeout
Implement Helm repository timeout
2 parents 34dd00d + 2044de4 commit 6b12d18

File tree

10 files changed

+315
-35
lines changed

10 files changed

+315
-35
lines changed

api/v1alpha1/gitrepository_types.go

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,10 @@ import (
2323
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
2424
)
2525

26-
const GitRepositoryKind = "GitRepository"
26+
const (
27+
GitRepositoryKind = "GitRepository"
28+
GitRepositoryTimeout = time.Second * 20
29+
)
2730

2831
// GitRepositorySpec defines the desired state of a Git repository.
2932
type GitRepositorySpec struct {
@@ -194,7 +197,7 @@ func (in *GitRepository) GetTimeout() time.Duration {
194197
if in.Spec.Timeout != nil {
195198
return in.Spec.Timeout.Duration
196199
}
197-
return time.Second * 20
200+
return GitRepositoryTimeout
198201
}
199202

200203
// GetArtifact returns the latest artifact from the source

api/v1alpha1/helmrepository_types.go

Lines changed: 18 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,11 +17,16 @@ limitations under the License.
1717
package v1alpha1
1818

1919
import (
20+
"time"
21+
2022
corev1 "k8s.io/api/core/v1"
2123
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
2224
)
2325

24-
const HelmRepositoryKind = "HelmRepository"
26+
const (
27+
HelmRepositoryKind = "HelmRepository"
28+
HelmRepositoryTimeout = time.Second * 60
29+
)
2530

2631
// HelmRepositorySpec defines the reference to a Helm repository.
2732
type HelmRepositorySpec struct {
@@ -41,6 +46,10 @@ type HelmRepositorySpec struct {
4146
// The interval at which to check the upstream for updates.
4247
// +required
4348
Interval metav1.Duration `json:"interval"`
49+
50+
// The timeout of index downloading, defaults to 60s.
51+
// +optional
52+
Timeout *metav1.Duration `json:"timeout,omitempty"`
4453
}
4554

4655
// HelmRepositoryStatus defines the observed state of the HelmRepository.
@@ -148,6 +157,14 @@ func (in *HelmRepository) GetInterval() metav1.Duration {
148157
return in.Spec.Interval
149158
}
150159

160+
// GetTimeout returns the configured timeout or the default.
161+
func (in *HelmRepository) GetTimeout() time.Duration {
162+
if in.Spec.Timeout != nil {
163+
return in.Spec.Timeout.Duration
164+
}
165+
return HelmRepositoryTimeout
166+
}
167+
151168
// +genclient
152169
// +genclient:Namespaced
153170
// +kubebuilder:object:root=true

api/v1alpha1/zz_generated.deepcopy.go

Lines changed: 5 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

config/crd/bases/source.toolkit.fluxcd.io_helmrepositories.yaml

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -63,6 +63,9 @@ spec:
6363
TODO: Add other useful fields. apiVersion, kind, uid?'
6464
type: string
6565
type: object
66+
timeout:
67+
description: The timeout of index downloading, defaults to 60s.
68+
type: string
6669
url:
6770
description: The Helm repository URL, a valid URL contains at least
6871
a protocol and host.

controllers/helmrepository_controller.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -204,8 +204,8 @@ func (r *HelmRepositoryReconciler) reconcile(ctx context.Context, repository sou
204204
clientOpts = opts
205205
}
206206

207-
// TODO(hidde): implement timeout from the HelmRepository
208-
// https://github.com/helm/helm/pull/7950
207+
clientOpts = append(clientOpts, getter.WithTimeout(repository.GetTimeout()))
208+
209209
res, err := c.Get(u.String(), clientOpts...)
210210
if err != nil {
211211
return sourcev1.HelmRepositoryNotReady(repository, sourcev1.IndexationFailedReason, err.Error()), err

controllers/helmrepository_controller_test.go

Lines changed: 56 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -37,9 +37,10 @@ import (
3737
var _ = Describe("HelmRepositoryReconciler", func() {
3838

3939
const (
40-
timeout = time.Second * 30
41-
interval = time.Second * 1
42-
indexInterval = time.Second * 2
40+
timeout = time.Second * 30
41+
interval = time.Second * 1
42+
indexInterval = time.Second * 2
43+
repositoryTimeout = time.Second * 5
4344
)
4445

4546
Context("HelmRepository", func() {
@@ -87,6 +88,7 @@ var _ = Describe("HelmRepositoryReconciler", func() {
8788
Spec: sourcev1.HelmRepositorySpec{
8889
URL: helmServer.URL(),
8990
Interval: metav1.Duration{Duration: indexInterval},
91+
Timeout: &metav1.Duration{Duration: repositoryTimeout},
9092
},
9193
}
9294
Expect(k8sClient.Create(context.Background(), created)).Should(Succeed())
@@ -150,6 +152,57 @@ var _ = Describe("HelmRepositoryReconciler", func() {
150152
Eventually(exists(got.Status.Artifact.Path), timeout, interval).ShouldNot(BeTrue())
151153
})
152154

155+
It("Handles timeout", func() {
156+
helmServer.Start()
157+
158+
Expect(helmServer.PackageChart(path.Join("testdata/helmchart"))).Should(Succeed())
159+
Expect(helmServer.GenerateIndex()).Should(Succeed())
160+
161+
key := types.NamespacedName{
162+
Name: "helmrepository-sample-" + randStringRunes(5),
163+
Namespace: namespace.Name,
164+
}
165+
created := &sourcev1.HelmRepository{
166+
ObjectMeta: metav1.ObjectMeta{
167+
Name: key.Name,
168+
Namespace: key.Namespace,
169+
},
170+
Spec: sourcev1.HelmRepositorySpec{
171+
URL: helmServer.URL(),
172+
Interval: metav1.Duration{Duration: indexInterval},
173+
},
174+
}
175+
Expect(k8sClient.Create(context.Background(), created)).Should(Succeed())
176+
177+
By("Expecting index download to succeed")
178+
Eventually(func() bool {
179+
got := &sourcev1.HelmRepository{}
180+
_ = k8sClient.Get(context.Background(), key, got)
181+
for _, condition := range got.Status.Conditions {
182+
if condition.Reason == sourcev1.IndexationSucceededReason {
183+
return true
184+
}
185+
}
186+
return false
187+
}, timeout, interval).Should(BeTrue())
188+
189+
By("Expecting index download to timeout")
190+
updated := &sourcev1.HelmRepository{}
191+
Expect(k8sClient.Get(context.Background(), key, updated)).Should(Succeed())
192+
updated.Spec.Timeout = &metav1.Duration{Duration: time.Microsecond}
193+
Expect(k8sClient.Update(context.Background(), updated)).Should(Succeed())
194+
Eventually(func() string {
195+
got := &sourcev1.HelmRepository{}
196+
_ = k8sClient.Get(context.Background(), key, got)
197+
for _, condition := range got.Status.Conditions {
198+
if condition.Reason == sourcev1.IndexationFailedReason {
199+
return condition.Message
200+
}
201+
}
202+
return ""
203+
}, timeout, interval).Should(MatchRegexp("(?i)timeout"))
204+
})
205+
153206
It("Authenticates when basic auth credentials are provided", func() {
154207
helmServer, err = testserver.NewTempHelmServer()
155208
Expect(err).NotTo(HaveOccurred())

docs/api/source.md

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -418,6 +418,20 @@ Kubernetes meta/v1.Duration
418418
<p>The interval at which to check the upstream for updates.</p>
419419
</td>
420420
</tr>
421+
<tr>
422+
<td>
423+
<code>timeout</code><br>
424+
<em>
425+
<a href="https://godoc.org/k8s.io/apimachinery/pkg/apis/meta/v1#Duration">
426+
Kubernetes meta/v1.Duration
427+
</a>
428+
</em>
429+
</td>
430+
<td>
431+
<em>(Optional)</em>
432+
<p>The timeout of index downloading, defaults to 60s.</p>
433+
</td>
434+
</tr>
421435
</table>
422436
</td>
423437
</tr>
@@ -998,6 +1012,20 @@ Kubernetes meta/v1.Duration
9981012
<p>The interval at which to check the upstream for updates.</p>
9991013
</td>
10001014
</tr>
1015+
<tr>
1016+
<td>
1017+
<code>timeout</code><br>
1018+
<em>
1019+
<a href="https://godoc.org/k8s.io/apimachinery/pkg/apis/meta/v1#Duration">
1020+
Kubernetes meta/v1.Duration
1021+
</a>
1022+
</em>
1023+
</td>
1024+
<td>
1025+
<em>(Optional)</em>
1026+
<p>The timeout of index downloading, defaults to 60s.</p>
1027+
</td>
1028+
</tr>
10011029
</tbody>
10021030
</table>
10031031
</div>

docs/spec/v1alpha1/helmrepositories.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,10 @@ type HelmRepositorySpec struct {
2727
// The interval at which to check the upstream for updates.
2828
// +required
2929
Interval metav1.Duration `json:"interval"`
30+
31+
// The timeout of index downloading, defaults to 60s.
32+
// +optional
33+
Timeout *metav1.Duration `json:"timeout,omitempty"`
3034
}
3135
```
3236

go.mod

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -11,8 +11,8 @@ require (
1111
github.com/onsi/ginkgo v1.12.1
1212
github.com/onsi/gomega v1.10.1
1313
github.com/sosedoff/gitkit v0.2.1-0.20191202022816-7182d43c6254
14-
go.uber.org/zap v1.10.0
15-
helm.sh/helm/v3 v3.2.4
14+
go.uber.org/zap v1.13.0
15+
helm.sh/helm/v3 v3.3.0
1616
k8s.io/api v0.18.4
1717
k8s.io/apimachinery v0.18.4
1818
k8s.io/client-go v0.18.4

0 commit comments

Comments
 (0)