diff --git a/models/meshmodel/core/v1alpha1/component.go b/models/meshmodel/core/v1alpha1/component.go index 85d1c54f..a67dcbb8 100644 --- a/models/meshmodel/core/v1alpha1/component.go +++ b/models/meshmodel/core/v1alpha1/component.go @@ -52,6 +52,69 @@ type ComponentDefinitionDB struct { func (c ComponentDefinition) Type() types.CapabilityType { return types.ComponentDefinition } +func (c ComponentDefinition) Doc(f DocFormat, db *database.Handler) (doc string) { + switch f { + case HTMLFormat: + data := fmt.Sprintf("%s supports following relationships:", c.Kind) + allowedFromRD := GetMeshModelRelationship(db, RelationshipFilter{ + AllowedFrom: []RelationshipKindModelFilter{ + { + Kind: c.Kind, + Model: c.Model.Name, + }, + }, + }) + data += "" + + allowedToRD := GetMeshModelRelationship(db, RelationshipFilter{ + AllowedTo: []RelationshipKindModelFilter{ + { + Kind: c.Kind, + Model: c.Model.Name, + }, + }, + }) + data += "" + data += fmt.Sprintf("\n%s supports following policies: ", c.Kind) + //Todo: Scan registry to get policies for the given c.Kind and c.Model + doc = fmt.Sprintf(` + + %s + + `, data) + } + return doc +} + func (c ComponentDefinition) GetID() uuid.UUID { return c.ID } diff --git a/models/meshmodel/core/v1alpha1/models.go b/models/meshmodel/core/v1alpha1/models.go index 1f823302..b430f750 100644 --- a/models/meshmodel/core/v1alpha1/models.go +++ b/models/meshmodel/core/v1alpha1/models.go @@ -17,6 +17,11 @@ type ModelFilter struct { Limit int //If 0 or unspecified then all records are returned and limit is not used Offset int } +type DocFormat string + +const ( + HTMLFormat DocFormat = "HTMLFormat" +) // swagger:response Model type Model struct { diff --git a/models/meshmodel/core/v1alpha1/policy.go b/models/meshmodel/core/v1alpha1/policy.go index 3e9bb5b1..0b6cc5a2 100644 --- a/models/meshmodel/core/v1alpha1/policy.go +++ b/models/meshmodel/core/v1alpha1/policy.go @@ -49,7 +49,10 @@ func (p PolicyDefinition) GetID() uuid.UUID { func (p PolicyDefinition) Type() types.CapabilityType { return types.PolicyDefinition } - +func (p PolicyDefinition) Doc(f DocFormat, db *database.Handler) string { + //TODO: Add doc + return "" +} func GetMeshModelPolicy(db *database.Handler, f PolicyFilter) (pl []PolicyDefinition) { type componentDefinitionWithModel struct { PolicyDefinitionDB diff --git a/models/meshmodel/core/v1alpha1/relationship.go b/models/meshmodel/core/v1alpha1/relationship.go index de3af366..fb2e0d70 100644 --- a/models/meshmodel/core/v1alpha1/relationship.go +++ b/models/meshmodel/core/v1alpha1/relationship.go @@ -22,11 +22,26 @@ type RelationshipDefinition struct { Model Model `json:"model"` Metadata map[string]interface{} `json:"metadata" yaml:"metadata"` SubType string `json:"subType" yaml:"subType" gorm:"subType"` - Selectors map[string]interface{} `json:"selectors" yaml:"selectors"` + Selectors RelationshipSelector `json:"selectors" yaml:"selectors"` CreatedAt time.Time `json:"-"` UpdatedAt time.Time `json:"-"` } +type RelationshipSelector struct { + Allow struct { + From []RelationshipKindModelFilter `json:"from"` + To []RelationshipKindModelFilter `json:"to"` + } `json:"allow"` + Deny struct { + From []RelationshipKindModelFilter `json:"from"` + To []RelationshipKindModelFilter `json:"to"` + } `json:"deny"` +} + +type RelationshipKindModelFilter struct { + Kind string `json:"kind"` + Model string `json:"model"` +} type RelationshipDefinitionDB struct { ID uuid.UUID `json:"-"` ModelID uuid.UUID `json:"-" gorm:"modelID"` @@ -42,15 +57,19 @@ type RelationshipDefinitionDB struct { // In the future, we will add support to query using `selectors` (using CUE) // TODO: Add support for Model type RelationshipFilter struct { - Kind string - Greedy bool //when set to true - instead of an exact match, kind will be prefix matched - SubType string - Version string - ModelName string - OrderOn string - Sort string //asc or desc. Default behavior is asc - Limit int //If 0 or unspecified then all records are returned and limit is not used - Offset int + Kind string + Greedy bool //when set to true - instead of an exact match, kind will be prefix matched + SubType string + Version string + AllowedFrom []RelationshipKindModelFilter + AllowedTo []RelationshipKindModelFilter + DeniedFrom []RelationshipKindModelFilter + DeniedTo []RelationshipKindModelFilter + ModelName string + OrderOn string + Sort string //asc or desc. Default behavior is asc + Limit int //If 0 or unspecified then all records are returned and limit is not used + Offset int } // Create the filter from map[string]interface{} @@ -101,11 +120,36 @@ func GetMeshModelRelationship(db *database.Handler, f RelationshipFilter) (r []R fmt.Println(err.Error()) //for debugging } for _, cm := range componentDefinitionsWithModel { - r = append(r, cm.RelationshipDefinitionDB.GetRelationshipDefinition(cm.Model)) + rd := cm.RelationshipDefinitionDB.GetRelationshipDefinition(cm.Model) + if f.AllowedFrom != nil && !matchRelationship(f.AllowedFrom, rd.Selectors.Allow.From) { + continue + } + if f.AllowedTo != nil && !matchRelationship(f.AllowedTo, rd.Selectors.Allow.To) { + continue + } + r = append(r, rd) } return r } +// Checks if all the kind-model pair passed in "src" are present inside "tocheck" or not +func matchRelationship(src []RelationshipKindModelFilter, tocheck []RelationshipKindModelFilter) bool { + counter := len(src) + for _, t := range tocheck { + for _, s := range src { + if t.Kind == s.Kind && t.Model == s.Model { + counter-- + } + if counter == 0 { + return true + } + } + } + if counter == 0 { + return true + } + return false +} func (rdb *RelationshipDefinitionDB) GetRelationshipDefinition(m Model) (r RelationshipDefinition) { r.ID = rdb.ID r.TypeMeta = rdb.TypeMeta @@ -113,9 +157,6 @@ func (rdb *RelationshipDefinitionDB) GetRelationshipDefinition(m Model) (r Relat r.Metadata = make(map[string]interface{}) } _ = json.Unmarshal(rdb.Metadata, &r.Metadata) - if r.Selectors == nil { - r.Selectors = make(map[string]interface{}) - } _ = json.Unmarshal(rdb.Selectors, &r.Selectors) r.SubType = rdb.SubType r.Kind = rdb.Kind @@ -126,6 +167,10 @@ func (rdb *RelationshipDefinitionDB) GetRelationshipDefinition(m Model) (r Relat func (r RelationshipDefinition) Type() types.CapabilityType { return types.RelationshipDefinition } +func (r RelationshipDefinition) Doc(f DocFormat, db *database.Handler) string { + //TODO: add doc + return "" +} func (r RelationshipDefinition) GetID() uuid.UUID { return r.ID } diff --git a/models/meshmodel/registry.go b/models/meshmodel/registry.go index fa0b5238..d4738a2a 100644 --- a/models/meshmodel/registry.go +++ b/models/meshmodel/registry.go @@ -50,6 +50,7 @@ func createHost(db *database.Handler, h Host) (uuid.UUID, error) { // ComponentDefinitions and PolicyDefinitions are examples of entities type Entity interface { Type() types.CapabilityType + Doc(v1alpha1.DocFormat, *database.Handler) string GetID() uuid.UUID } @@ -182,6 +183,19 @@ func (rm *RegistryManager) GetEntities(f types.Filter) []Entity { return nil } } + +func (rm *RegistryManager) GetEntityDoc(f types.Filter) string { + switch filter := f.(type) { + case *v1alpha1.ComponentFilter: + comps := v1alpha1.GetMeshModelComponents(rm.db, *filter) + if len(comps) == 0 { + return "" + } + return comps[0].Doc(v1alpha1.HTMLFormat, rm.db) + default: + return "" + } +} func (rm *RegistryManager) GetModels(f types.Filter) []v1alpha1.Model { var mod []v1alpha1.Model finder := rm.db.Model(&mod)