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

[Draft]Add support for dynamic doc generation for Meshmodels #273

Open
wants to merge 4 commits into
base: master
Choose a base branch
from
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
63 changes: 63 additions & 0 deletions models/meshmodel/core/v1alpha1/component.go
Original file line number Diff line number Diff line change
Expand Up @@ -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 += "<ul>"
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(`<li>%s from %s to %s of subtype %s
</li>`, ard.Kind, c.Kind, ar.Kind, ard.SubType)
} else {
ardkindmap[ard.Kind] += fmt.Sprintf(`<li>%s from %s to all components in model %s of subtype %s
</li>`, ard.Kind, c.Kind, ar.Model, ard.SubType)
}
}
}
data += "</ul>"

allowedToRD := GetMeshModelRelationship(db, RelationshipFilter{
AllowedTo: []RelationshipKindModelFilter{
{
Kind: c.Kind,
Model: c.Model.Name,
},
},
})
data += "<ul>"
for _, ard := range allowedToRD {
for _, ar := range ard.Selectors.Allow.From {
if ar.Kind != "" {
ardkindmap[ard.Kind] += fmt.Sprintf(`<li>%s from %s to %s of subtype %s
</li>`, ard.Kind, ar.Kind, c.Kind, ard.SubType)
} else {
ardkindmap[ard.Kind] += fmt.Sprintf(`<li>%s from all components in model %s to %s of subtype %s
</li>`, ard.Kind, ar.Model, c.Kind, ard.SubType)
}
}
}
for kind, content := range ardkindmap {
data += fmt.Sprintf("%s: %s", kind, content)
}
data += "</ul>"
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(`
<html>
%s
</html>
`, data)
}
return doc
}

func (c ComponentDefinition) GetID() uuid.UUID {
return c.ID
}
Expand Down
5 changes: 5 additions & 0 deletions models/meshmodel/core/v1alpha1/models.go
Original file line number Diff line number Diff line change
Expand Up @@ -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 {
Expand Down
5 changes: 4 additions & 1 deletion models/meshmodel/core/v1alpha1/policy.go
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
73 changes: 59 additions & 14 deletions models/meshmodel/core/v1alpha1/relationship.go
Original file line number Diff line number Diff line change
Expand Up @@ -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"`
Expand All @@ -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{}
Expand Down Expand Up @@ -101,21 +120,43 @@ 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
if r.Metadata == nil {
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
Expand All @@ -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
}
Expand Down
14 changes: 14 additions & 0 deletions models/meshmodel/registry.go
Original file line number Diff line number Diff line change
Expand Up @@ -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
}

Expand Down Expand Up @@ -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)
Expand Down