-
Notifications
You must be signed in to change notification settings - Fork 14
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Storage config #48
Storage config #48
Changes from all commits
b04d0cd
add7c52
2ab80b0
60a7ac5
dac7f55
d966584
b62862d
56b39bb
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -17,7 +17,11 @@ limitations under the License. | |
package v1alpha1 | ||
|
||
import ( | ||
"fmt" | ||
"github.com/kuadrant/limitador-operator/pkg/helpers" | ||
corev1 "k8s.io/api/core/v1" | ||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" | ||
"reflect" | ||
) | ||
|
||
const ( | ||
|
@@ -49,6 +53,9 @@ type LimitadorSpec struct { | |
// +optional | ||
Listener *Listener `json:"listener,omitempty"` | ||
|
||
// +optional | ||
Storage *Storage `json:"storage,omitempty"` | ||
|
||
// +optional | ||
Limits []RateLimit `json:"limits,omitempty"` | ||
} | ||
|
@@ -102,6 +109,99 @@ type LimitadorList struct { | |
Items []Limitador `json:"items"` | ||
} | ||
|
||
// StorageType defines the valid options for storage | ||
// +kubebuilder:validation:Enum=memory;redis;redis_cached | ||
type StorageType string | ||
|
||
const ( | ||
StorageTypeInMemory StorageType = "memory" | ||
StorageTypeRedis = "redis" | ||
StorageTypeRedisCached = "redis_cached" | ||
) | ||
|
||
// Storage contains the options for Limitador counters database or in-memory data storage | ||
type Storage struct { | ||
// +optional | ||
Redis *Redis `json:"redis,omitempty"` | ||
|
||
// +optional | ||
RedisCached *RedisCached `json:"redis-cached,omitempty"` | ||
} | ||
|
||
func (s *Storage) Validate() bool { | ||
return s.Redis != nil && s.Redis.ConfigSecretRef != nil || | ||
s.RedisCached != nil && s.RedisCached.ConfigSecretRef != nil | ||
} | ||
|
||
func (s *Storage) SecretRef() *corev1.ObjectReference { | ||
if s.Redis != nil { | ||
return s.Redis.ConfigSecretRef | ||
} | ||
return s.RedisCached.ConfigSecretRef | ||
} | ||
|
||
func (s *Storage) Config(url string) []string { | ||
if s.Redis != nil { | ||
return []string{ | ||
StorageTypeRedis, | ||
url, | ||
} | ||
} else if s.RedisCached != nil { | ||
params := []string{ | ||
StorageTypeRedisCached, | ||
url, | ||
} | ||
options := reflect.ValueOf(*s.RedisCached.Options) | ||
typesOf := options.Type() | ||
for i := 0; i < options.NumField(); i++ { | ||
if !options.Field(i).IsNil() { | ||
var value interface{} = options.Field(i).Elem() | ||
params = append( | ||
params, | ||
fmt.Sprintf( | ||
"--%s %d", | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. you are assuming that they will always be integers. What if we add a string? I let you decide. I am ok with this implementation, but I let you decide what to do. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Yup, only because they're all defined as type |
||
helpers.ToKebabCase(typesOf.Field(i).Name), | ||
value)) | ||
} | ||
} | ||
return params | ||
} | ||
return []string{string(StorageTypeInMemory)} | ||
} | ||
|
||
type Redis struct { | ||
// +ConfigSecretRef refers to the secret holding the URL for Redis. | ||
// +optional | ||
ConfigSecretRef *corev1.ObjectReference `json:"configSecretRef,omitempty"` | ||
} | ||
|
||
type RedisCachedOptions struct { | ||
// +optional | ||
// Ttl for cached counters in milliseconds [default: 5000] | ||
Ttl *int `json:"ttl,omitempty"` | ||
|
||
// +optional | ||
// Ratio to apply to the TTL from Redis on cached counters [default: 10] | ||
Ratio *int `json:"ratio,omitempty"` | ||
|
||
// +optional | ||
// FlushPeriod for counters in milliseconds [default: 1000] | ||
FlushPeriod *int `json:"flush-period,omitempty"` | ||
|
||
// +optional | ||
// MaxCached refers to the maximum amount of counters cached [default: 10000] | ||
MaxCached *int `json:"max-cached,omitempty"` | ||
} | ||
|
||
type RedisCached struct { | ||
// +ConfigSecretRef refers to the secret holding the URL for Redis. | ||
// +optional | ||
ConfigSecretRef *corev1.ObjectReference `json:"configSecretRef,omitempty"` | ||
|
||
// +optional | ||
Options *RedisCachedOptions `json:"options,omitempty"` | ||
didierofrivia marked this conversation as resolved.
Show resolved
Hide resolved
|
||
} | ||
|
||
type Listener struct { | ||
// +optional | ||
HTTP *TransportProtocol `json:"http,omitempty"` | ||
|
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -63,6 +63,7 @@ spec: | |
- "" | ||
resources: | ||
- configmaps | ||
- secrets | ||
verbs: | ||
- create | ||
- delete | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
minor thing: what about having one method returning
[]string
per each type?There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I thought of this too, but in terms of how the consumers of the "Storage API" goes, this way it's simplified, only interacting with "Storage" and not the underlying implementation (Redis, RedisCached, Memory, etc). The controller needs only to request the storage config to the Storage API. Does it make sense?