From 3989a857e22b0e1b34ff95100607c27347f1ffc1 Mon Sep 17 00:00:00 2001 From: Ashish Tiwari Date: Thu, 2 Mar 2023 22:54:03 +0530 Subject: [PATCH 1/4] [Draft]Add support for dynamic doc generation for Meshmodels Signed-off-by: Ashish Tiwari --- models/meshmodel/core/v1alpha1/component.go | 16 ++++++++++ models/meshmodel/core/v1alpha1/models.go | 5 +++ models/meshmodel/core/v1alpha1/policy.go | 5 ++- .../meshmodel/core/v1alpha1/relationship.go | 32 ++++++++++++++++--- models/meshmodel/registry.go | 1 + 5 files changed, 54 insertions(+), 5 deletions(-) diff --git a/models/meshmodel/core/v1alpha1/component.go b/models/meshmodel/core/v1alpha1/component.go index 85d1c54f..0b240f9e 100644 --- a/models/meshmodel/core/v1alpha1/component.go +++ b/models/meshmodel/core/v1alpha1/component.go @@ -52,6 +52,22 @@ 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) + //Todo: Scan registry to get relationships for the given c.Kind and c.Model + 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..ee9b2f44 100644 --- a/models/meshmodel/core/v1alpha1/relationship.go +++ b/models/meshmodel/core/v1alpha1/relationship.go @@ -22,10 +22,33 @@ 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 []struct { + Kind string `json:"kind"` + Model string `json:"model"` + } `json:"from"` + To []struct { + Kind string `json:"kind"` + Model string `json:"model"` + } `json:"to"` + } `json:"allow"` + + Deny struct { + From []struct { + Kind string `json:"kind"` + Model string `json:"model"` + } `json:"from"` + To []struct { + Kind string `json:"kind"` + Model string `json:"model"` + } `json:"to"` + } `json:"deny"` +} type RelationshipDefinitionDB struct { ID uuid.UUID `json:"-"` @@ -113,9 +136,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 +146,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..b96680ae 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 } From 685c1966fd218b57450d13fda5028a2b1aebf6cc Mon Sep 17 00:00:00 2001 From: Ashish Tiwari Date: Fri, 3 Mar 2023 02:20:06 +0530 Subject: [PATCH 2/4] complete doc for component Signed-off-by: Ashish Tiwari --- models/meshmodel/core/v1alpha1/component.go | 37 ++++++++++++++- .../meshmodel/core/v1alpha1/relationship.go | 46 +++++++++---------- models/meshmodel/registry.go | 13 ++++++ 3 files changed, 69 insertions(+), 27 deletions(-) diff --git a/models/meshmodel/core/v1alpha1/component.go b/models/meshmodel/core/v1alpha1/component.go index 0b240f9e..68376e6d 100644 --- a/models/meshmodel/core/v1alpha1/component.go +++ b/models/meshmodel/core/v1alpha1/component.go @@ -55,8 +55,41 @@ func (c ComponentDefinition) Type() types.CapabilityType { func (c ComponentDefinition) Doc(f DocFormat, db *database.Handler) (doc string) { switch f { case HTMLFormat: - data := fmt.Sprintf("%s supports following relationships: ", c.Kind) - //Todo: Scan registry to get relationships for the given c.Kind and c.Model + data := fmt.Sprintf("%s supports following relationships: \n\t", c.Kind) + allowedFromRD := GetMeshModelRelationship(db, RelationshipFilter{ + AllowedFrom: []RelationshipKindModelFilter{ + { + Kind: c.Kind, + Model: c.Model.Name, + }, + }, + }) + for _, ard := range allowedFromRD { + for _, ar := range ard.Selectors.Allow.To { + if ar.Kind != "" { + data += fmt.Sprintf("%s from %s to %s\n", ard.Kind, c.Kind, ar.Kind) + } else { + data += fmt.Sprintf("%s from %s to all components in model %s\n", ard.Kind, c.Kind, ar.Model) + } + } + } + allowedToRD := GetMeshModelRelationship(db, RelationshipFilter{ + AllowedFrom: []RelationshipKindModelFilter{ + { + Kind: c.Kind, + Model: c.Model.Name, + }, + }, + }) + for _, ard := range allowedToRD { + for _, ar := range ard.Selectors.Allow.From { + if ar.Kind != "" { + data += fmt.Sprintf("%s from %s to %s\n", ard.Kind, ar.Kind, c.Kind) + } else { + data += fmt.Sprintf("%s from all components in model %s to %s\n", ar.Model, ar.Kind, c.Kind) + } + } + } 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(` diff --git a/models/meshmodel/core/v1alpha1/relationship.go b/models/meshmodel/core/v1alpha1/relationship.go index ee9b2f44..49606209 100644 --- a/models/meshmodel/core/v1alpha1/relationship.go +++ b/models/meshmodel/core/v1alpha1/relationship.go @@ -28,28 +28,20 @@ type RelationshipDefinition struct { } type RelationshipSelector struct { Allow struct { - From []struct { - Kind string `json:"kind"` - Model string `json:"model"` - } `json:"from"` - To []struct { - Kind string `json:"kind"` - Model string `json:"model"` - } `json:"to"` + From []RelationshipKindModelFilter `json:"from"` + To []RelationshipKindModelFilter `json:"to"` } `json:"allow"` Deny struct { - From []struct { - Kind string `json:"kind"` - Model string `json:"model"` - } `json:"from"` - To []struct { - Kind string `json:"kind"` - Model string `json:"model"` - } `json:"to"` + 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"` @@ -65,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{} diff --git a/models/meshmodel/registry.go b/models/meshmodel/registry.go index b96680ae..d4738a2a 100644 --- a/models/meshmodel/registry.go +++ b/models/meshmodel/registry.go @@ -183,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) From 7c10e762c545e267b87301ffbbf71f83849655d7 Mon Sep 17 00:00:00 2001 From: Ashish Tiwari Date: Sat, 4 Mar 2023 00:36:34 +0530 Subject: [PATCH 3/4] Fix filtering bug Signed-off-by: Ashish Tiwari --- models/meshmodel/core/v1alpha1/component.go | 26 +++++++++++++----- .../meshmodel/core/v1alpha1/relationship.go | 27 ++++++++++++++++++- 2 files changed, 46 insertions(+), 7 deletions(-) diff --git a/models/meshmodel/core/v1alpha1/component.go b/models/meshmodel/core/v1alpha1/component.go index 68376e6d..a36d9928 100644 --- a/models/meshmodel/core/v1alpha1/component.go +++ b/models/meshmodel/core/v1alpha1/component.go @@ -55,7 +55,7 @@ func (c ComponentDefinition) Type() types.CapabilityType { func (c ComponentDefinition) Doc(f DocFormat, db *database.Handler) (doc string) { switch f { case HTMLFormat: - data := fmt.Sprintf("%s supports following relationships: \n\t", c.Kind) + data := fmt.Sprintf("%s supports following relationships:", c.Kind) allowedFromRD := GetMeshModelRelationship(db, RelationshipFilter{ AllowedFrom: []RelationshipKindModelFilter{ { @@ -64,32 +64,46 @@ func (c ComponentDefinition) Doc(f DocFormat, db *database.Handler) (doc string) }, }, }) + 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 != "" { - data += fmt.Sprintf("%s from %s to %s\n", ard.Kind, c.Kind, ar.Kind) + ardkindmap[ard.Kind] += fmt.Sprintf(`
  • %s from %s to %s +
  • `, ard.Kind, c.Kind, ar.Kind) } else { - data += fmt.Sprintf("%s from %s to all components in model %s\n", ard.Kind, c.Kind, ar.Model) + ardkindmap[ard.Kind] += fmt.Sprintf(`
  • %s from %s to all components in model %s +
  • `, ard.Kind, c.Kind, ar.Model) } } } + data += "
" + allowedToRD := GetMeshModelRelationship(db, RelationshipFilter{ - AllowedFrom: []RelationshipKindModelFilter{ + AllowedTo: []RelationshipKindModelFilter{ { Kind: c.Kind, Model: c.Model.Name, }, }, }) + data += "
    " for _, ard := range allowedToRD { for _, ar := range ard.Selectors.Allow.From { if ar.Kind != "" { - data += fmt.Sprintf("%s from %s to %s\n", ard.Kind, ar.Kind, c.Kind) + ardkindmap[ard.Kind] += fmt.Sprintf(`
  • %s from %s to %s +
  • `, ard.Kind, ar.Kind, c.Kind) } else { - data += fmt.Sprintf("%s from all components in model %s to %s\n", ar.Model, ar.Kind, c.Kind) + ardkindmap[ard.Kind] += fmt.Sprintf(`
  • %s from all components in model %s to %s +
  • `, ard.Kind, ar.Model, c.Kind) } } } + 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(` diff --git a/models/meshmodel/core/v1alpha1/relationship.go b/models/meshmodel/core/v1alpha1/relationship.go index 49606209..fb2e0d70 100644 --- a/models/meshmodel/core/v1alpha1/relationship.go +++ b/models/meshmodel/core/v1alpha1/relationship.go @@ -120,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 From b1edf3d2cb06a36bfe80d31f9aef9d03bd2a210e Mon Sep 17 00:00:00 2001 From: Ashish Tiwari Date: Sat, 4 Mar 2023 01:11:51 +0530 Subject: [PATCH 4/4] Add subtype Signed-off-by: Ashish Tiwari --- models/meshmodel/core/v1alpha1/component.go | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/models/meshmodel/core/v1alpha1/component.go b/models/meshmodel/core/v1alpha1/component.go index a36d9928..a67dcbb8 100644 --- a/models/meshmodel/core/v1alpha1/component.go +++ b/models/meshmodel/core/v1alpha1/component.go @@ -70,11 +70,11 @@ func (c ComponentDefinition) Doc(f DocFormat, db *database.Handler) (doc 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 -
  • `, ard.Kind, c.Kind, 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 -
  • `, ard.Kind, c.Kind, ar.Model) + 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) } } } @@ -92,11 +92,11 @@ func (c ComponentDefinition) Doc(f DocFormat, db *database.Handler) (doc string) for _, ard := range allowedToRD { for _, ar := range ard.Selectors.Allow.From { if ar.Kind != "" { - ardkindmap[ard.Kind] += fmt.Sprintf(`
  • %s from %s to %s -
  • `, ard.Kind, ar.Kind, c.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 -
  • `, ard.Kind, ar.Model, c.Kind) + 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) } } }