Skip to content
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

Migrating to duty models #966

Open
wants to merge 14 commits into
base: master
Choose a base branch
from
48 changes: 48 additions & 0 deletions api/v1/canary_types.go
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,8 @@ import (

"github.com/flanksource/canary-checker/api/external"
"github.com/flanksource/commons/logger"
"github.com/flanksource/duty/models"
"github.com/flanksource/duty/types"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
)

Expand Down Expand Up @@ -312,6 +314,52 @@ type Canary struct {
Status CanaryStatus `json:"status,omitempty"`
}

func (c Canary) ToModel() (models.Canary, error) {
spec, err := json.Marshal(c.Spec)
if err != nil {
return models.Canary{}, err
}
var checks = make(map[string]string)
if c.Status.Checks != nil {
checks = c.Status.Checks
}

return models.Canary{
Spec: spec,
Labels: types.JSONStringMap(c.Labels),
Name: c.Name,
Namespace: c.Namespace,
Source: c.Annotations["source"],
Checks: types.JSONStringMap(checks),
}, nil
}

func CanaryFromModel(c *models.Canary) (*Canary, error) {
canary := Canary{
ObjectMeta: metav1.ObjectMeta{
Name: c.Name,
Namespace: c.Namespace,
Annotations: map[string]string{
"source": c.Source,
},
Labels: c.Labels,
},
}
var deletionTimestamp metav1.Time
if c.DeletedAt != nil && !c.DeletedAt.IsZero() {
deletionTimestamp = metav1.NewTime(*c.DeletedAt)
canary.ObjectMeta.DeletionTimestamp = &deletionTimestamp
}
if err := json.Unmarshal(c.Spec, &canary.Spec); err != nil {
return nil, fmt.Errorf("failed to unmarshal spec: %w", err)
}

id := c.ID.String()
canary.Status.PersistedID = &id
canary.Status.Checks = c.Checks
return &canary, nil
}

func NewCanaryFromSpec(name string, spec CanarySpec) Canary {
return Canary{
ObjectMeta: metav1.ObjectMeta{
Expand Down
10 changes: 2 additions & 8 deletions api/v1/checks.go
Original file line number Diff line number Diff line change
Expand Up @@ -891,17 +891,11 @@ func (c ConfigDBCheck) GetEndpoint() string {
return c.Query
}

type ResourceSelector struct {
Name string `yaml:"name,omitempty" json:"name,omitempty"`
LabelSelector string `json:"labelSelector,omitempty" yaml:"labelSelector,omitempty"`
FieldSelector string `json:"fieldSelector,omitempty" yaml:"fieldSelector,omitempty"`
}

type KubernetesCheck struct {
Description `yaml:",inline" json:",inline"`
Templatable `yaml:",inline" json:",inline"`
Namespace ResourceSelector `yaml:"namespace,omitempty" json:"namespace,omitempty"`
Resource ResourceSelector `yaml:"resource,omitempty" json:"resource,omitempty"`
Namespace types.ResourceSelector `yaml:"namespace,omitempty" json:"namespace,omitempty"`
Resource types.ResourceSelector `yaml:"resource,omitempty" json:"resource,omitempty"`
// Ignore the specified resources from the fetched resources. Can be a glob pattern.
Ignore []string `yaml:"ignore,omitempty" json:"ignore,omitempty"`
Kind string `yaml:"kind" json:"kind"`
Expand Down
113 changes: 38 additions & 75 deletions api/v1/component_types.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,8 @@ package v1

import (
"fmt"
"strings"

"github.com/flanksource/duty/models"
"github.com/flanksource/duty/types"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
)
Expand Down Expand Up @@ -39,12 +39,12 @@ type ComponentSpec struct {
// Create new child components
Components []ComponentSpecObject `json:"components,omitempty"`
// Lookup and associcate other components with this component
Selectors ResourceSelectors `json:"selectors,omitempty"`
ComponentChecks ComponentChecks `json:"checks,omitempty"`
Selectors types.ResourceSelectors `json:"selectors,omitempty"`
ComponentChecks ComponentChecks `json:"checks,omitempty"`
// Lookup and associate config items with this component
Configs []Config `json:"configs,omitempty"`
Configs Configs `json:"configs,omitempty"`
//
Summary *Summary `json:"summary,omitempty"`
Summary *types.Summary `json:"summary,omitempty"`
// Only applies when using lookup, when specified the components and properties
// specified under ForEach will be templated using the components returned by the lookup
// ${.properties} can be used to reference the properties of the component
Expand All @@ -70,11 +70,11 @@ type ForEach struct {
// Properties are created once the full component tree is created, property lookup functions
// can return a map of coomponent name => properties to allow for bulk property lookups
// being applied to multiple components in the tree
Properties Properties `json:"properties,omitempty"`
Configs []Config `json:"configs,omitempty"`
Selectors ResourceSelectors `json:"selectors,omitempty"`
Relationships []RelationshipSpec `json:"relationships,omitempty"`
ComponentChecks ComponentChecks `json:"checks,omitempty"`
Properties Properties `json:"properties,omitempty"`
Configs []Config `json:"configs,omitempty"`
Selectors types.ResourceSelectors `json:"selectors,omitempty"`
Relationships []RelationshipSpec `json:"relationships,omitempty"`
ComponentChecks ComponentChecks `json:"checks,omitempty"`
}

func (f *ForEach) IsEmpty() bool {
Expand All @@ -85,57 +85,6 @@ func (f *ForEach) String() string {
return fmt.Sprintf("ForEach(components=%d, properties=%d)", len(f.Components), len(f.Properties))
}

type Summary struct {
Healthy int `json:"healthy,omitempty"`
Unhealthy int `json:"unhealthy,omitempty"`
Warning int `json:"warning,omitempty"`
Info int `json:"info,omitempty"`
Incidents map[string]map[string]int `json:"incidents,omitempty"`
Insights map[string]map[string]int `json:"insights,omitempty"`
}

func (s Summary) String() string {
str := ""
if s.Unhealthy > 0 {
str += fmt.Sprintf("unhealthy=%d ", s.Unhealthy)
}
if s.Warning > 0 {
str += fmt.Sprintf("warning=%d ", s.Warning)
}
if s.Healthy > 0 {
str += fmt.Sprintf("healthy=%d ", s.Healthy)
}
return strings.TrimSpace(str)
}

func (s Summary) GetStatus() ComponentPropertyStatus {
if s.Unhealthy > 0 {
return ComponentPropertyStatusUnhealthy
} else if s.Warning > 0 {
return ComponentPropertyStatusWarning
} else if s.Healthy > 0 {
return ComponentPropertyStatusHealthy
}
return "unknown"
}

func (s Summary) Add(b Summary) Summary {
if b.Healthy > 0 && b.Unhealthy > 0 {
s.Warning += 1
} else if b.Unhealthy > 0 {
s.Unhealthy += 1
} else if b.Healthy > 0 {
s.Healthy += 1
}
if b.Warning > 0 {
s.Warning += b.Warning
}
if b.Info > 0 {
s.Info += b.Info
}
return s
}

type ComponentStatus struct {
Status ComponentPropertyStatus `json:"status,omitempty"`
}
Expand Down Expand Up @@ -165,13 +114,6 @@ type Text struct {
Label string `json:"label,omitempty"`
}

type Link struct {
// e.g. documentation, support, playbook
Type string `json:"type,omitempty"`
URL string `json:"url,omitempty"`
Text `json:",inline"`
}

type Properties []Property

type Property struct {
Expand All @@ -185,19 +127,40 @@ type Property struct {
Type string `json:"type,omitempty"`
Color string `json:"color,omitempty"`
// e.g. milliseconds, bytes, millicores, epoch etc.
Unit string `json:"unit,omitempty"`
Value int64 `json:"value,omitempty"`
Max *int64 `json:"max,omitempty"`
Min int64 `json:"min,omitempty"`
Status string `json:"status,omitempty"`
LastTransition string `json:"lastTransition,omitempty"`
Links []Link `json:"links,omitempty"`
Unit string `json:"unit,omitempty"`
Value int64 `json:"value,omitempty"`
Max *int64 `json:"max,omitempty"`
Min int64 `json:"min,omitempty"`
Status string `json:"status,omitempty"`
LastTransition string `json:"lastTransition,omitempty"`
Links []models.Link `json:"links,omitempty"`
// +kubebuilder:validation:XPreserveUnknownFields
Lookup *CanarySpec `json:"lookup,omitempty"`
ConfigLookup *ConfigLookup `json:"configLookup,omitempty"`
Summary *Template `json:"summary,omitempty"`
}

func (p Property) ToModel() *models.Property {
return &models.Property{
Label: p.Label,
Name: p.Name,
Tooltip: p.Tooltip,
Icon: p.Icon,
Order: p.Order,
Text: p.Text,
Value: p.Value,
Unit: p.Unit,
Max: p.Max,
Min: p.Min,
Status: p.Status,
LastTransition: p.LastTransition,
Links: p.Links,
Headline: p.Headline,
Type: p.Type,
Color: p.Color,
}
}

func (p *Property) String() string {
if p.Label != "" {
return p.Label
Expand Down
92 changes: 0 additions & 92 deletions api/v1/db_types.go
Original file line number Diff line number Diff line change
Expand Up @@ -16,61 +16,13 @@ const (
SQLServerType = "sqlserver"
PostgresType = "postgres"
SqliteType = "sqlite"
text = "TEXT"
jsonType = "json"
jsonbType = "JSONB"
nvarcharType = "NVARCHAR(MAX)"
)

type ResourceSelectors []ResourceSelector

type ComponentChecks []ComponentCheck

func (rs ResourceSelectors) Value() (driver.Value, error) {
if len(rs) == 0 {
return []byte("[]"), nil
}
return json.Marshal(rs)
}

func (rs *ResourceSelectors) Scan(val interface{}) error {
if val == nil {
*rs = ResourceSelectors{}
return nil
}
var ba []byte
switch v := val.(type) {
case []byte:
ba = v
default:
return errors.New(fmt.Sprint("Failed to unmarshal ResourceSelectors value:", val))
}
return json.Unmarshal(ba, rs)
}

// 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 {
switch db.Dialector.Name() {
case SqliteType:
return jsonType
case PostgresType:
return jsonbType
case SQLServerType:
return nvarcharType
}
return ""
}

func (rs ResourceSelectors) GormValue(ctx context.Context, db *gorm.DB) clause.Expr {
data, _ := json.Marshal(rs)
return gorm.Expr("?", string(data))
}

func (cs ComponentChecks) Value() (driver.Value, error) {
if len(cs) == 0 {
return []byte("[]"), nil
Expand Down Expand Up @@ -115,47 +67,3 @@ func (cs ComponentChecks) GormValue(ctx context.Context, db *gorm.DB) clause.Exp
data, _ := json.Marshal(cs)
return gorm.Expr("?", string(data))
}

// Scan scan value into Jsonb, implements sql.Scanner interface
func (s Summary) Value() (driver.Value, error) {
return json.Marshal(s)
}

// Scan scan value into Jsonb, implements sql.Scanner interface
func (s *Summary) Scan(val interface{}) error {
if val == nil {
*s = Summary{}
return nil
}
var ba []byte
switch v := val.(type) {
case []byte:
ba = v
default:
return errors.New(fmt.Sprint("Failed to unmarshal properties value:", val))
}
err := json.Unmarshal(ba, s)
return err
}

// GormDataType gorm common data type
func (Summary) GormDataType() string {
return "summary"
}

func (Summary) GormDBDataType(db *gorm.DB, field *schema.Field) string {
switch db.Dialector.Name() {
case SqliteType:
return text
case PostgresType:
return jsonbType
case SQLServerType:
return nvarcharType
}
return ""
}

func (s Summary) GormValue(ctx context.Context, db *gorm.DB) clause.Expr {
data, _ := json.Marshal(s)
return gorm.Expr("?", data)
}
Loading