Skip to content

Commit

Permalink
feat: expose a cache cleanup function for unit tests
Browse files Browse the repository at this point in the history
* move resource selectors to a separate file
  • Loading branch information
adityathebe committed Feb 1, 2024
1 parent b33a417 commit 0a6a46e
Show file tree
Hide file tree
Showing 4 changed files with 105 additions and 87 deletions.
7 changes: 7 additions & 0 deletions getters.go
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,13 @@ var (
immutableCache = cache.New(cache.NoExpiration, time.Hour*12)
)

// CleanCache flushes the getter caches.
// Mainly used by unit tests.
func CleanCache() {
getterCache.Flush()
immutableCache.Flush()
}

func cacheKey[T any](field, key string) string {
var v T
return fmt.Sprintf("%T:%s=%s", v, field, key)
Expand Down
87 changes: 0 additions & 87 deletions types/component.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,7 @@ import (
"database/sql/driver"
"encoding/json"
"fmt"
"strings"

"github.com/flanksource/commons/collections"
"github.com/flanksource/commons/hash"
"github.com/google/uuid"
"gorm.io/gorm"
Expand Down Expand Up @@ -155,91 +153,6 @@ func (s Summary) GormValue(ctx context.Context, db *gorm.DB) clause.Expr {
return GormValue(s)
}

// +kubebuilder:object:generate=true
type ResourceSelector struct {
// Agent can be the agent id or the name of the agent.
// Additionally, the special "self" value can be used to select resources without an agent.
Agent string `yaml:"agent,omitempty" json:"agent,omitempty"`

ID string `yaml:"id,omitempty" json:"id,omitempty"`
Name string `yaml:"name,omitempty" json:"name,omitempty"`
Namespace string `yaml:"namespace,omitempty" json:"namespace,omitempty"`
Types Items `yaml:"types,omitempty" json:"types,omitempty"`
Statuses Items `yaml:"statuses,omitempty" json:"statuses,omitempty"`
LabelSelector string `json:"labelSelector,omitempty" yaml:"labelSelector,omitempty"`
FieldSelector string `json:"fieldSelector,omitempty" yaml:"fieldSelector,omitempty"`
}

// Immutable returns true if the selector can be cached indefinitely
func (c ResourceSelector) Immutable() bool {
if c.ID != "" {
return true
}

if c.Name == "" {
// without a name, a selector is never specific enough to be cached indefinitely
return false
}

if c.Namespace == "" {
return false // still not specific enough
}

if len(c.LabelSelector) != 0 || len(c.FieldSelector) != 0 || len(c.Statuses) != 0 {
// These selectors work on mutable part of the resource, so they can't be cached indefinitely
return false
}

return true
}

func (c ResourceSelector) Hash() string {
items := []string{
c.ID,
c.Name,
c.Namespace,
c.Agent,
strings.Join(c.Types.Sort(), ","),
strings.Join(c.Statuses.Sort(), ","),
collections.SortedMap(collections.SelectorToMap(c.LabelSelector)),
collections.SortedMap(collections.SelectorToMap(c.FieldSelector)),
}

return hash.Sha256Hex(strings.Join(items, "|"))
}

type ResourceSelectors []ResourceSelector

func (rs *ResourceSelectors) Scan(val any) error {
return GenericStructScan(&rs, val)
}

func (rs ResourceSelectors) Value() (driver.Value, error) {
return GenericStructValue(rs, true)
}

func (rs ResourceSelectors) Hash() string {
hash, err := hash.JSONMD5Hash(rs)
if err != nil {
return ""
}
return hash
}

// GormDataType gorm common data type
func (rs ResourceSelectors) GormDataType() string {
return "resourceSelectors"
}

// GormDBDataType gorm db data type
func (ResourceSelectors) GormDBDataType(db *gorm.DB, field *schema.Field) string {
return JSONGormDBDataType(db.Dialector.Name())
}

func (rs ResourceSelectors) GormValue(ctx context.Context, db *gorm.DB) clause.Expr {
return GormValue(rs)
}

// +kubebuilder:object:generate=true
type ComponentCheck struct {
Selector ResourceSelector `json:"selector,omitempty"`
Expand Down
98 changes: 98 additions & 0 deletions types/resource_selector.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,98 @@
package types

import (
"context"
"database/sql/driver"
"strings"

"github.com/flanksource/commons/collections"
"github.com/flanksource/commons/hash"
"gorm.io/gorm"
"gorm.io/gorm/clause"
"gorm.io/gorm/schema"
)

// +kubebuilder:object:generate=true
type ResourceSelector struct {
// Agent can be the agent id or the name of the agent.
// Additionally, the special "self" value can be used to select resources without an agent.
Agent string `yaml:"agent,omitempty" json:"agent,omitempty"`

ID string `yaml:"id,omitempty" json:"id,omitempty"`
Name string `yaml:"name,omitempty" json:"name,omitempty"`
Namespace string `yaml:"namespace,omitempty" json:"namespace,omitempty"`
Types Items `yaml:"types,omitempty" json:"types,omitempty"`
Statuses Items `yaml:"statuses,omitempty" json:"statuses,omitempty"`
LabelSelector string `json:"labelSelector,omitempty" yaml:"labelSelector,omitempty"`
FieldSelector string `json:"fieldSelector,omitempty" yaml:"fieldSelector,omitempty"`
}

// Immutable returns true if the selector can be cached indefinitely
func (c ResourceSelector) Immutable() bool {
if c.ID != "" {
return true
}

if c.Name == "" {
// without a name, a selector is never specific enough to be cached indefinitely
return false
}

if c.Namespace == "" {
return false // still not specific enough
}

if len(c.LabelSelector) != 0 || len(c.FieldSelector) != 0 || len(c.Statuses) != 0 {
// These selectors work on mutable part of the resource, so they can't be cached indefinitely
return false
}

return true
}

func (c ResourceSelector) Hash() string {
items := []string{
c.ID,
c.Name,
c.Namespace,
c.Agent,
strings.Join(c.Types.Sort(), ","),
strings.Join(c.Statuses.Sort(), ","),
collections.SortedMap(collections.SelectorToMap(c.LabelSelector)),
collections.SortedMap(collections.SelectorToMap(c.FieldSelector)),
}

return hash.Sha256Hex(strings.Join(items, "|"))
}

type ResourceSelectors []ResourceSelector

func (rs *ResourceSelectors) Scan(val any) error {
return GenericStructScan(&rs, val)
}

func (rs ResourceSelectors) Value() (driver.Value, error) {
return GenericStructValue(rs, true)
}

func (rs ResourceSelectors) Hash() string {
hash, err := hash.JSONMD5Hash(rs)
if err != nil {
return ""
}
return hash
}

// GormDataType gorm common data type
func (rs ResourceSelectors) GormDataType() string {
return "resourceSelectors"
}

// GormDBDataType gorm db data type
func (ResourceSelectors) GormDBDataType(db *gorm.DB, field *schema.Field) string {
return JSONGormDBDataType(db.Dialector.Name())
}

func (rs ResourceSelectors) GormValue(ctx context.Context, db *gorm.DB) clause.Expr {
return GormValue(rs)
}
File renamed without changes.

0 comments on commit 0a6a46e

Please sign in to comment.