Skip to content

Commit

Permalink
feat: configurable image via spec
Browse files Browse the repository at this point in the history
  • Loading branch information
KevFan committed Aug 16, 2023
1 parent e110bb7 commit 0c1b7a3
Show file tree
Hide file tree
Showing 12 changed files with 252 additions and 176 deletions.
73 changes: 67 additions & 6 deletions api/v1alpha1/limitador_types.go
Original file line number Diff line number Diff line change
Expand Up @@ -22,18 +22,20 @@ import (

"github.com/go-logr/logr"
"github.com/google/go-cmp/cmp"
"github.com/kuadrant/limitador-operator/pkg/helpers"
corev1 "k8s.io/api/core/v1"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"

"github.com/kuadrant/limitador-operator/pkg/helpers"
)

const (
DefaultServiceHTTPPort int32 = 8080
DefaultServiceGRPCPort int32 = 8081
DefaultServiceHTTPPort int32 = 8080
DefaultServiceGRPCPort int32 = 8081
DefaultLimitadorRepository string = "quay.io/kuadrant/limitador"

// Status conditions
StatusConditionReady string = "Ready"

ImageEnvVarKey = "RELATED_IMAGE_LIMITADOR"
)

// EDIT THIS FILE! THIS IS SCAFFOLDING FOR YOU TO OWN!
Expand All @@ -47,6 +49,7 @@ type LimitadorSpec struct {
// +optional
Replicas *int `json:"replicas,omitempty"`

// Deprecated: Use Image for specifying image version
// +optional
Version *string `json:"version,omitempty"`

Expand All @@ -61,6 +64,9 @@ type LimitadorSpec struct {

// +optional
Limits []RateLimit `json:"limits,omitempty"`

// +optional
Image *Image `json:"image"`
}

//+kubebuilder:object:root=true
Expand Down Expand Up @@ -103,6 +109,47 @@ func (l *Limitador) Limits() []RateLimit {
return l.Spec.Limits
}

func (l *Limitador) GetImage() string {
image := fmt.Sprintf("%s:%s", l.GetImageRepository(), l.GetImageTag())
return helpers.FetchEnv(ImageEnvVarKey, image)
}

func (l *Limitador) GetImageRepository() string {
if l.Spec.Image == nil || l.Spec.Image.Repository == nil {
return DefaultLimitadorRepository
}

return *l.Spec.Image.Repository
}

func (l *Limitador) GetImageTag() string {
versionSet := l.Spec.Version != nil
imageTagSet := l.Spec.Image != nil && l.Spec.Image.Tag != nil

// Preference for tag in image struct over deprecated field
if imageTagSet {
return *l.Spec.Image.Tag
}

// Maintain backwards compatability for deprecated field if set
if versionSet {
return *l.Spec.Version
}

return "latest"
}

func (l *Limitador) GetImagePullSecrets() []corev1.LocalObjectReference {
var imagePullSecrets []corev1.LocalObjectReference
if l.Spec.Image == nil || l.Spec.Image.PullSecret == nil {
return nil
}

imagePullSecrets = append(imagePullSecrets, *l.Spec.Image.PullSecret)

return imagePullSecrets
}

//+kubebuilder:object:root=true

// LimitadorList contains a list of Limitador
Expand Down Expand Up @@ -177,7 +224,7 @@ func (s *Storage) Config(url string) []string {
}

type Redis struct {
// +ConfigSecretRef refers to the secret holding the URL for Redis.
// ConfigSecretRef refers to the secret holding the URL for Redis.
// +optional
ConfigSecretRef *corev1.ObjectReference `json:"configSecretRef,omitempty"`
}
Expand All @@ -201,7 +248,7 @@ type RedisCachedOptions struct {
}

type RedisCached struct {
// +ConfigSecretRef refers to the secret holding the URL for Redis.
// ConfigSecretRef refers to the secret holding the URL for Redis.
// +optional
ConfigSecretRef *corev1.ObjectReference `json:"configSecretRef,omitempty"`

Expand Down Expand Up @@ -285,6 +332,20 @@ func (s *LimitadorStatus) Equals(other *LimitadorStatus, logger logr.Logger) boo
return true
}

type Image struct {
// Repository containing the image to be used
// +optional
Repository *string `json:"repository"`

// Tag of the image
// +optional
Tag *string `json:"tag"`

// PullSecret for pulling private images
// +optional
PullSecret *corev1.LocalObjectReference `json:"pullSecret"`
}

func init() {
SchemeBuilder.Register(&Limitador{}, &LimitadorList{})
}
48 changes: 48 additions & 0 deletions api/v1alpha1/limitador_types_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
package v1alpha1

import (
"fmt"
"os"
"testing"

"gotest.tools/assert"
)

func TestLimitadorGetImage(t *testing.T) {
var (
testRepo = "quay.io/test/limitador"
testTag = "nightly"
)

t.Run("test default image if not specified in spec", func(subT *testing.T) {
l := &Limitador{}
assert.Equal(subT, l.GetImage(), "quay.io/kuadrant/limitador:latest")
})

t.Run("test image repo override", func(subT *testing.T) {
l := &Limitador{Spec: LimitadorSpec{Image: &Image{Repository: &testRepo}}}
assert.Equal(subT, l.GetImage(), fmt.Sprintf("%s:latest", testRepo))
})

t.Run("test image tag override", func(subT *testing.T) {
l := &Limitador{Spec: LimitadorSpec{Image: &Image{Tag: &testTag}}}
assert.Equal(subT, l.GetImage(), fmt.Sprintf("quay.io/kuadrant/limitador:%s", testTag))
})

t.Run("test image repo & tag override", func(subT *testing.T) {
l := &Limitador{Spec: LimitadorSpec{Image: &Image{Repository: &testRepo, Tag: &testTag}}}
assert.Equal(subT, l.GetImage(), fmt.Sprintf("%s:%s", testRepo, testTag))
})

t.Run("test preference for env var", func(subT *testing.T) {
envVarImage := "quay.io/env/limitador:custom"
if err := os.Setenv(ImageEnvVarKey, envVarImage); err != nil {
t.Fatal(err)
}
l := &Limitador{Spec: LimitadorSpec{Image: &Image{Repository: &testRepo, Tag: &testTag}}}
assert.Equal(subT, l.GetImage(), envVarImage)
if err := os.Unsetenv(ImageEnvVarKey); err != nil {
t.Fatal(err)
}
})
}
35 changes: 35 additions & 0 deletions api/v1alpha1/zz_generated.deepcopy.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

75 changes: 23 additions & 52 deletions bundle/manifests/limitador.kuadrant.io_limitadors.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,24 @@ spec:
spec:
description: LimitadorSpec defines the desired state of Limitador
properties:
image:
properties:
name:
description: Name of the image
type: string
pullSecret:
description: PullSecret for pulling private images
properties:
name:
description: 'Name of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names
TODO: Add other useful fields. apiVersion, kind, uid?'
type: string
type: object
x-kubernetes-map-type: atomic
tag:
description: Tag of the image
type: string
type: object
limits:
items:
description: RateLimit defines the desired Limitador limit
Expand Down Expand Up @@ -91,32 +109,8 @@ spec:
redis:
properties:
configSecretRef:
description: 'ObjectReference contains enough information
to let you inspect or modify the referred object. --- New
uses of this type are discouraged because of difficulty
describing its usage when embedded in APIs. 1. Ignored fields. It
includes many fields which are not generally honored. For
instance, ResourceVersion and FieldPath are both very rarely
valid in actual usage. 2. Invalid usage help. It is impossible
to add specific help for individual usage. In most embedded
usages, there are particular restrictions like, "must refer
only to types A and B" or "UID not honored" or "name must
be restricted". Those cannot be well described when embedded.
3. Inconsistent validation. Because the usages are different,
the validation rules are different by usage, which makes
it hard for users to predict what will happen. 4. The fields
are both imprecise and overly precise. Kind is not a precise
mapping to a URL. This can produce ambiguity during interpretation
and require a REST mapping. In most cases, the dependency
is on the group,resource tuple and the version of the actual
struct is irrelevant. 5. We cannot easily change it. Because
this type is embedded in many locations, updates to this
type will affect numerous schemas. Don''t make new APIs
embed an underspecified API type they do not control. Instead
of using this type, create a locally provided and used type
that is well-focused on your reference. For example, ServiceReferences
for admission registration: https://github.com/kubernetes/api/blob/release-1.17/admissionregistration/v1/types.go#L533
.'
description: ConfigSecretRef refers to the secret holding
the URL for Redis.
properties:
apiVersion:
description: API version of the referent.
Expand Down Expand Up @@ -157,32 +151,8 @@ spec:
redis-cached:
properties:
configSecretRef:
description: 'ObjectReference contains enough information
to let you inspect or modify the referred object. --- New
uses of this type are discouraged because of difficulty
describing its usage when embedded in APIs. 1. Ignored fields. It
includes many fields which are not generally honored. For
instance, ResourceVersion and FieldPath are both very rarely
valid in actual usage. 2. Invalid usage help. It is impossible
to add specific help for individual usage. In most embedded
usages, there are particular restrictions like, "must refer
only to types A and B" or "UID not honored" or "name must
be restricted". Those cannot be well described when embedded.
3. Inconsistent validation. Because the usages are different,
the validation rules are different by usage, which makes
it hard for users to predict what will happen. 4. The fields
are both imprecise and overly precise. Kind is not a precise
mapping to a URL. This can produce ambiguity during interpretation
and require a REST mapping. In most cases, the dependency
is on the group,resource tuple and the version of the actual
struct is irrelevant. 5. We cannot easily change it. Because
this type is embedded in many locations, updates to this
type will affect numerous schemas. Don''t make new APIs
embed an underspecified API type they do not control. Instead
of using this type, create a locally provided and used type
that is well-focused on your reference. For example, ServiceReferences
for admission registration: https://github.com/kubernetes/api/blob/release-1.17/admissionregistration/v1/types.go#L533
.'
description: ConfigSecretRef refers to the secret holding
the URL for Redis.
properties:
apiVersion:
description: API version of the referent.
Expand Down Expand Up @@ -241,6 +211,7 @@ spec:
type: object
type: object
version:
description: 'Deprecated: Use Image for specifying image version'
type: string
type: object
status:
Expand Down
Loading

0 comments on commit 0c1b7a3

Please sign in to comment.