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 += "
"
+ data += "All other relationships not described here are implicitly denied (not allowed)\n"
+ ardkindmap := make(map[string]string)
+ for _, ard := range allowedFromRD {
+ for _, ar := range ard.Selectors.Allow.To {
+ if ar.Kind != "" {
+ ardkindmap[ard.Kind] += fmt.Sprintf(`- %s from %s to %s of subtype %s
+
`, ard.Kind, c.Kind, ar.Kind, ard.SubType)
+ } else {
+ ardkindmap[ard.Kind] += fmt.Sprintf(`- %s from %s to all components in model %s of subtype %s
+
`, ard.Kind, c.Kind, ar.Model, ard.SubType)
+ }
+ }
+ }
+ data += "
"
+
+ allowedToRD := GetMeshModelRelationship(db, RelationshipFilter{
+ AllowedTo: []RelationshipKindModelFilter{
+ {
+ Kind: c.Kind,
+ Model: c.Model.Name,
+ },
+ },
+ })
+ data += ""
+ for _, ard := range allowedToRD {
+ for _, ar := range ard.Selectors.Allow.From {
+ if ar.Kind != "" {
+ ardkindmap[ard.Kind] += fmt.Sprintf(`- %s from %s to %s of subtype %s
+
`, ard.Kind, ar.Kind, c.Kind, ard.SubType)
+ } else {
+ ardkindmap[ard.Kind] += fmt.Sprintf(`- %s from all components in model %s to %s of subtype %s
+
`, ard.Kind, ar.Model, c.Kind, ard.SubType)
+ }
+ }
+ }
+ for kind, content := range ardkindmap {
+ data += fmt.Sprintf("%s: %s", kind, content)
+ }
+ 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)