Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
95 changes: 95 additions & 0 deletions models/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -168,6 +168,101 @@ type ConfigItemLastScrapedTime struct {
LastScrapedTime *time.Time `json:"last_scraped_time,omitempty"`
}

// ConfigProperty represents typed properties for a config item.
type ConfigProperty struct {
ID uuid.UUID `json:"id" gorm:"default:generate_ulid()"`
ConfigID uuid.UUID `json:"config_id"`
ScraperID *uuid.UUID `json:"scraper_id,omitempty"`
CreatedBy *uuid.UUID `json:"created_by,omitempty"`
Name string `json:"name"`
Label string `json:"label,omitempty"`
Tooltip string `json:"tooltip,omitempty"`
Icon string `json:"icon,omitempty"`
PropertyType string `json:"type,omitempty" gorm:"column:property_type"`
Color string `json:"color,omitempty"`
DisplayOrder int `json:"order,omitempty" gorm:"column:display_order"`
Headline bool `json:"headline,omitempty"`
Hidden bool `json:"hidden,omitempty"`
Text string `json:"text,omitempty"`
Value *int64 `json:"value,omitempty"`
Unit string `json:"unit,omitempty"`
Max *int64 `json:"max,omitempty"`
Min *int64 `json:"min,omitempty"`
Status string `json:"status,omitempty"`
LinkURL string `json:"link_url,omitempty"`
LinkLabel string `json:"link_label,omitempty"`
LinkIcon string `json:"link_icon,omitempty"`
CreatedAt time.Time `json:"created_at" gorm:"<-:create"`
UpdatedAt *time.Time `json:"updated_at,omitempty" gorm:"autoUpdateTime:false"`
}

func (ConfigProperty) TableName() string {
return "config_properties"
}

func NewConfigProperty(configID uuid.UUID, scraperID, createdBy *uuid.UUID, property types.Property) ConfigProperty {
var link types.Link
if len(property.Links) > 0 {
link = property.Links[0]
}

return ConfigProperty{
ConfigID: configID,
ScraperID: scraperID,
CreatedBy: createdBy,
Name: property.Name,
Label: property.Label,
Tooltip: property.Tooltip,
Icon: property.Icon,
PropertyType: property.Type,
Color: property.Color,
DisplayOrder: property.Order,
Headline: property.Headline,
Hidden: property.Hidden,
Text: property.Text,
Value: property.Value,
Unit: property.Unit,
Max: property.Max,
Min: property.Min,
Status: property.Status,
LinkURL: link.URL,
LinkLabel: link.Text.Label,
LinkIcon: link.Text.Icon,
}
}
Comment thread
coderabbitai[bot] marked this conversation as resolved.

func (p ConfigProperty) AsProperty() types.Property {
var links []types.Link
if p.LinkURL != "" {
links = []types.Link{{
URL: p.LinkURL,
Text: types.Text{
Label: p.LinkLabel,
Icon: p.LinkIcon,
},
}}
}

return types.Property{
Name: p.Name,
Label: p.Label,
Tooltip: p.Tooltip,
Icon: p.Icon,
Type: p.PropertyType,
Color: p.Color,
Order: p.DisplayOrder,
Headline: p.Headline,
Hidden: p.Hidden,
Text: p.Text,
Value: p.Value,
Unit: p.Unit,
Max: p.Max,
Min: p.Min,
Status: p.Status,
Links: links,
}
}

func (ConfigItemLastScrapedTime) TableName() string {
return "config_items_last_scraped_time"
}
Expand Down
3 changes: 3 additions & 0 deletions rbac/objects.go
Original file line number Diff line number Diff line change
Expand Up @@ -75,6 +75,9 @@ var dbResourceObjMap = map[string]string{
"config_items_aws": policy.ObjectCatalog,
"config_items": policy.ObjectCatalog,
"config_items_last_scraped_time": policy.ObjectCatalog,
"config_properties": policy.ObjectCatalog,
"config_properties_json": policy.ObjectCatalog,
"config_items_with_properties": policy.ObjectCatalog,
"config_labels": policy.ObjectDatabasePublic,
"config_names": policy.ObjectDatabasePublic,
"config_relationships": policy.ObjectCatalog,
Expand Down
161 changes: 161 additions & 0 deletions schema/config.hcl
Original file line number Diff line number Diff line change
Expand Up @@ -449,6 +449,167 @@ table "config_items" {
}
}

# Config properties that are owned independently from the scraper-written
# config_items.properties JSONB column. This table is the typed write path for
# user-created and future scraper-created properties; compatibility views merge
# these rows back into the legacy JSON array shape for existing readers.
table "config_properties" {
schema = schema.public
column "id" {
null = false
type = uuid
default = sql("generate_ulid()")
}
column "config_id" {
null = false
type = uuid
}
column "scraper_id" {
null = true
type = uuid
}
column "created_by" {
null = true
type = uuid
}
column "name" {
null = false
type = text
}
column "label" {
null = true
type = text
}
column "tooltip" {
null = true
type = text
}
column "icon" {
null = true
type = text
}
column "property_type" {
null = true
type = text
}
column "color" {
null = true
type = text
}
column "display_order" {
null = true
type = integer
}
column "headline" {
null = false
type = bool
default = false
}
column "hidden" {
null = false
type = bool
default = false
}
column "text" {
null = true
type = text
}
column "value" {
null = true
type = bigint
}
column "unit" {
null = true
type = text
}
column "max" {
null = true
type = bigint
}
column "min" {
null = true
type = bigint
}
column "status" {
null = true
type = text
}
column "link_url" {
null = true
type = text
}
column "link_label" {
null = true
type = text
}
column "link_icon" {
null = true
type = text
}
column "created_at" {
null = false
type = timestamptz
default = sql("now()")
}
column "updated_at" {
null = true
type = timestamptz
default = sql("now()")
}
primary_key {
columns = [column.id]
}
foreign_key "config_properties_config_id_fkey" {
columns = [column.config_id]
ref_columns = [table.config_items.column.id]
on_update = NO_ACTION
on_delete = CASCADE
}
foreign_key "config_properties_scraper_id_fkey" {
columns = [column.scraper_id]
ref_columns = [table.config_scrapers.column.id]
on_update = NO_ACTION
on_delete = NO_ACTION
}
foreign_key "config_properties_created_by_fkey" {
columns = [column.created_by]
ref_columns = [table.people.column.id]
on_update = NO_ACTION
on_delete = NO_ACTION
}
index "config_properties_config_id_idx" {
columns = [column.config_id]
}
index "config_properties_scraper_id_idx" {
columns = [column.scraper_id]
}
index "config_properties_created_by_idx" {
columns = [column.created_by]
}
index "config_properties_name_idx" {
columns = [column.name]
}
index "config_properties_config_name_text_idx" {
columns = [column.config_id, column.name, column.text]
}
index "config_properties_config_name_value_idx" {
columns = [column.config_id, column.name, column.value]
}
index "config_properties_scraper_unique_idx" {
unique = true
columns = [column.config_id, column.scraper_id, column.name]
where = "scraper_id IS NOT NULL"
}
index "config_properties_created_by_unique_idx" {
unique = true
columns = [column.config_id, column.created_by, column.name]
where = "created_by IS NOT NULL"
}
check "config_properties_creator_check" {
expr = "((scraper_id IS NOT NULL) <> (created_by IS NOT NULL))"
}
}

table "config_items_last_scraped_time" {
schema = schema.public
unlogged = true
Expand Down
Loading
Loading