From 45e1dad540d38dbecba68fd4e524e2dde486dec6 Mon Sep 17 00:00:00 2001
From: Sanskar Jaiswal
Date: Wed, 22 Nov 2023 20:33:47 +0530
Subject: [PATCH] imagerepo: add `.spec.insecure` to `ImageRepository`
Add a new boolean field `.spec.insecure` to the `ImageRepository` API.
This enables connecting to insecure registries hosted at an HTTP
endpoint.
Signed-off-by: Sanskar Jaiswal
---
api/v1beta2/imagerepository_types.go | 5 ++++
...e.toolkit.fluxcd.io_imagerepositories.yaml | 4 +++
docs/api/v1beta2/image-reflector.md | 26 ++++++++++++++++
docs/spec/v1beta2/imagerepositories.md | 6 ++++
.../controller/imagerepository_controller.go | 16 ++++++----
.../imagerepository_controller_test.go | 30 +++++++++++++------
6 files changed, 73 insertions(+), 14 deletions(-)
diff --git a/api/v1beta2/imagerepository_types.go b/api/v1beta2/imagerepository_types.go
index eaee2c14..5b770a1b 100644
--- a/api/v1beta2/imagerepository_types.go
+++ b/api/v1beta2/imagerepository_types.go
@@ -104,6 +104,11 @@ type ImageRepositorySpec struct {
// +kubebuilder:default:=generic
// +optional
Provider string `json:"provider,omitempty"`
+
+ // Insecure, if set to true indicates that the image registry is hosted at an
+ // HTTP endpoint.
+ // +optional
+ Insecure bool `json:"insecure,omitempty"`
}
type ScanResult struct {
diff --git a/config/crd/bases/image.toolkit.fluxcd.io_imagerepositories.yaml b/config/crd/bases/image.toolkit.fluxcd.io_imagerepositories.yaml
index 40075d79..44dec07f 100644
--- a/config/crd/bases/image.toolkit.fluxcd.io_imagerepositories.yaml
+++ b/config/crd/bases/image.toolkit.fluxcd.io_imagerepositories.yaml
@@ -315,6 +315,10 @@ spec:
image:
description: Image is the name of the image repository
type: string
+ insecure:
+ description: Insecure, if set to true indicates that the image registry
+ is hosted at an HTTP endpoint.
+ type: boolean
interval:
description: Interval is the length of time to wait between scans
of the image repository.
diff --git a/docs/api/v1beta2/image-reflector.md b/docs/api/v1beta2/image-reflector.md
index 576479fa..b215c913 100644
--- a/docs/api/v1beta2/image-reflector.md
+++ b/docs/api/v1beta2/image-reflector.md
@@ -543,6 +543,19 @@ string
When not specified, defaults to ‘generic’.
+
+
+insecure
+
+bool
+
+ |
+
+(Optional)
+ Insecure, if set to true indicates that the image registry is hosted at an
+HTTP endpoint.
+ |
+
@@ -731,6 +744,19 @@ string
When not specified, defaults to ‘generic’.
+
+
+insecure
+
+bool
+
+ |
+
+(Optional)
+ Insecure, if set to true indicates that the image registry is hosted at an
+HTTP endpoint.
+ |
+
diff --git a/docs/spec/v1beta2/imagerepositories.md b/docs/spec/v1beta2/imagerepositories.md
index 12986aaa..768e878a 100644
--- a/docs/spec/v1beta2/imagerepositories.md
+++ b/docs/spec/v1beta2/imagerepositories.md
@@ -318,6 +318,12 @@ spec:
- "1.1.1|1.0.0"
```
+### Insecure
+
+`.spec.insecure` is an optional field to specify that the image registry is
+hosted at a non-TLS endpoint and thus the controller should use plain HTTP
+requests to communicate with the registry.
+
### Provider
`.spec.provider` is an optional field that allows specifying an OIDC provider
diff --git a/internal/controller/imagerepository_controller.go b/internal/controller/imagerepository_controller.go
index 0ae58872..1e60b1cb 100644
--- a/internal/controller/imagerepository_controller.go
+++ b/internal/controller/imagerepository_controller.go
@@ -249,7 +249,7 @@ func (r *ImageRepositoryReconciler) reconcile(ctx context.Context, sp *patch.Ser
}
// Parse image reference.
- ref, err := parseImageReference(obj.Spec.Image)
+ ref, err := parseImageReference(obj.Spec.Image, obj.Spec.Insecure)
if err != nil {
conditions.MarkStalled(obj, imagev1.ImageURLInvalidReason, err.Error())
result, retErr = ctrl.Result{}, nil
@@ -468,7 +468,7 @@ func (r *ImageRepositoryReconciler) shouldScan(obj imagev1.ImageRepository, now
// If the canonical image name of the image is different from the last
// observed name, scan now.
- ref, err := parseImageReference(obj.Spec.Image)
+ ref, err := parseImageReference(obj.Spec.Image, obj.Spec.Insecure)
if err != nil {
return false, scanInterval, "", err
}
@@ -570,13 +570,19 @@ func eventLogf(ctx context.Context, r kuberecorder.EventRecorder, obj runtime.Ob
}
// parseImageReference parses the given URL into a container registry repository
-// reference.
-func parseImageReference(url string) (name.Reference, error) {
+// reference. If insecure is set to true, then the registry is deemed to be
+// located at an HTTP endpoint.
+func parseImageReference(url string, insecure bool) (name.Reference, error) {
if s := strings.Split(url, "://"); len(s) > 1 {
return nil, fmt.Errorf(".spec.image value should not start with URL scheme; remove '%s://'", s[0])
}
- ref, err := name.ParseReference(url)
+ var opts []name.Option
+ if insecure {
+ opts = append(opts, name.Insecure)
+ }
+
+ ref, err := name.ParseReference(url, opts...)
if err != nil {
return nil, err
}
diff --git a/internal/controller/imagerepository_controller_test.go b/internal/controller/imagerepository_controller_test.go
index df25ac43..141adfbd 100644
--- a/internal/controller/imagerepository_controller_test.go
+++ b/internal/controller/imagerepository_controller_test.go
@@ -580,7 +580,7 @@ func TestImageRepositoryReconciler_scan(t *testing.T) {
repo.SetAnnotations(map[string]string{meta.ReconcileRequestAnnotation: tt.annotation})
}
- ref, err := parseImageReference(imgRepo)
+ ref, err := parseImageReference(imgRepo, false)
g.Expect(err).ToNot(HaveOccurred())
opts := []remote.Option{}
@@ -656,12 +656,13 @@ func TestGetLatestTags(t *testing.T) {
}
}
-func TestParseImageReference(t *testing.T) {
+func Test_parseImageReference(t *testing.T) {
tests := []struct {
- name string
- url string
- wantErr bool
- wantRef string
+ name string
+ url string
+ insecure bool
+ wantErr bool
+ wantRef string
}{
{
name: "simple valid url",
@@ -684,16 +685,27 @@ func TestParseImageReference(t *testing.T) {
wantErr: false,
wantRef: "example.com:9999/foo/bar",
},
+ {
+ name: "with insecure registry",
+ url: "example.com/foo/bar",
+ insecure: true,
+ wantRef: "example.com/foo/bar",
+ },
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
g := NewWithT(t)
- ref, err := parseImageReference(tt.url)
- g.Expect(err != nil).To(Equal(tt.wantErr))
- if err == nil {
+ ref, err := parseImageReference(tt.url, tt.insecure)
+ if tt.wantErr {
+ g.Expect(err).To(HaveOccurred())
+ } else {
+ g.Expect(err).ToNot(HaveOccurred())
g.Expect(ref.String()).To(Equal(tt.wantRef))
+ if tt.insecure {
+ g.Expect(ref.Context().Registry.Scheme()).To(Equal("http"))
+ }
}
})
}