From 7f0267078f7ca2389769eb6ef3361260a1cef1e9 Mon Sep 17 00:00:00 2001 From: Nithish Date: Thu, 15 Dec 2022 19:15:11 +0530 Subject: [PATCH 1/6] feat: Add RELATIONSHIPDEFINITION type Signed-off-by: Nithish --- models/meshmodel/core/types/types.go | 5 +++-- .../meshmodel/core/v1alpha1/relationship.go | 20 +++++++++++++++++++ 2 files changed, 23 insertions(+), 2 deletions(-) create mode 100644 models/meshmodel/core/v1alpha1/relationship.go diff --git a/models/meshmodel/core/types/types.go b/models/meshmodel/core/types/types.go index 5c7c24fd..0c928bbc 100644 --- a/models/meshmodel/core/types/types.go +++ b/models/meshmodel/core/types/types.go @@ -3,8 +3,9 @@ package types type CapabilityType string const ( - ComponentDefinition CapabilityType = "component" - PolicyDefinition CapabilityType = "policy" + ComponentDefinition CapabilityType = "component" + PolicyDefinition CapabilityType = "policy" + RelationshipDefinition CapabilityType = "relationship" ) // Each entity will have it's own Filter implementation via which it exposes the nobs and dials to fetch entities diff --git a/models/meshmodel/core/v1alpha1/relationship.go b/models/meshmodel/core/v1alpha1/relationship.go new file mode 100644 index 00000000..08a962eb --- /dev/null +++ b/models/meshmodel/core/v1alpha1/relationship.go @@ -0,0 +1,20 @@ +package v1alpha1 + +import ( + "time" + + "github.com/google/uuid" +) + +// https://docs.google.com/drawings/d/1_qzQ_YxvCWPYrOBcdqGMlMwfbsZx96SBuIkbn8TfKhU/edit?pli=1 +// see RELATIONSHIPDEFINITIONS table in the diagram +type RelationshipDefinition struct { + ID uuid.UUID `json:"-"` + TypeMeta + Metadata map[string]interface{} `json:"metadata" yaml:"metadata"` + Type string `json:"type" yaml:"type"` + SubType string `json:"subType" yaml:"subType"` + Selectors string `json:"selectors" yaml:"selectors"` + CreatedAt time.Time `json:"-"` + UpdatedAt time.Time `json:"-"` +} From 915fadf0e87f227a9349ce3b627413f8ea9280d7 Mon Sep 17 00:00:00 2001 From: Nithish Date: Thu, 15 Dec 2022 23:35:06 +0530 Subject: [PATCH 2/6] feat: Support add and query functionality for relationships Signed-off-by: Nithish --- .../meshmodel/core/v1alpha1/relationship.go | 124 +++++++++++++++++- models/meshmodel/registry.go | 7 + 2 files changed, 127 insertions(+), 4 deletions(-) diff --git a/models/meshmodel/core/v1alpha1/relationship.go b/models/meshmodel/core/v1alpha1/relationship.go index 08a962eb..b286a39e 100644 --- a/models/meshmodel/core/v1alpha1/relationship.go +++ b/models/meshmodel/core/v1alpha1/relationship.go @@ -1,9 +1,12 @@ package v1alpha1 import ( + "encoding/json" "time" "github.com/google/uuid" + "github.com/layer5io/meshkit/database" + "github.com/layer5io/meshkit/models/meshmodel/core/types" ) // https://docs.google.com/drawings/d/1_qzQ_YxvCWPYrOBcdqGMlMwfbsZx96SBuIkbn8TfKhU/edit?pli=1 @@ -11,10 +14,123 @@ import ( type RelationshipDefinition struct { ID uuid.UUID `json:"-"` TypeMeta - Metadata map[string]interface{} `json:"metadata" yaml:"metadata"` - Type string `json:"type" yaml:"type"` - SubType string `json:"subType" yaml:"subType"` - Selectors string `json:"selectors" yaml:"selectors"` + Metadata map[string]interface{} `json:"metadata" yaml:"metadata"` + // using RelType since there is a method called `Type` + RelType string `json:"type" yaml:"type"` + SubType string `json:"subType" yaml:"subType" gorm:"subType"` + Selectors map[string]interface{} `json:"selectors" yaml:"selectors"` CreatedAt time.Time `json:"-"` UpdatedAt time.Time `json:"-"` } + +type RelationshipDefinitionDB struct { + ID uuid.UUID `json:"-"` + TypeMeta + Metadata []byte `json:"metadata" yaml:"metadata"` + RelType string `json:"type" yaml:"type" gorm:"type"` + SubType string `json:"subType" yaml:"subType"` + Selectors []byte `json:"selectors" yaml:"selectors"` + CreatedAt time.Time `json:"-"` + UpdatedAt time.Time `json:"-"` +} + +// For now, only filtering by Kind, Type or SubType can be done. +// In the future, we will add support to query using `selectors` (using CUE) +type RelationshipFilter struct { + Kind string + Type string + SubType string +} + +// Create the filter from map[string]interface{} +func (rf *RelationshipFilter) Create(m map[string]interface{}) { + if m == nil { + return + } +} + +func GetRelationships(db *database.Handler, f RelationshipFilter) (rs []RelationshipDefinition) { + var rdb []RelationshipDefinitionDB + if f.Type != "" { + _ = db.Where("type = ?", f.Type).Find(&rdb).Error + for _, reldb := range rdb { + rel := reldb.GetRelationshipDefinition() + rs = append(rs, rel) + } + } + if f.Kind != "" { + if len(rs) == 0 { + _ = db.Where("kind = ?", f.Kind).Find(&rdb).Error + for _, reldb := range rdb { + rel := reldb.GetRelationshipDefinition() + rs = append(rs, rel) + } + } else { + filteredRs := []RelationshipDefinition{} + for _, rd := range rs { + if rd.Kind == f.Kind { + filteredRs = append(filteredRs, rd) + } + } + rs = filteredRs + } + } + if f.SubType != "" { + if len(rs) == 0 { + _ = db.Where("subtype = ?", f.SubType).Find(&rdb).Error + for _, reldb := range rdb { + rel := reldb.GetRelationshipDefinition() + rs = append(rs, rel) + } + } else { + filteredRs := []RelationshipDefinition{} + for _, rd := range rs { + if rd.SubType == f.SubType { + filteredRs = append(filteredRs, rd) + } + } + rs = filteredRs + } + } + return +} + +func (rdb *RelationshipDefinitionDB) GetRelationshipDefinition() (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.RelType = rdb.RelType + return +} + +func (r RelationshipDefinition) Type() types.CapabilityType { + return types.RelationshipDefinition +} + +func CreateRelationship(db *database.Handler, r RelationshipDefinition) (uuid.UUID, error) { + r.ID = uuid.New() + rdb := r.GetRelationshipDefinitionDB() + err := db.Create(&rdb).Error + if err != nil { + return uuid.UUID{}, err + } + return r.ID, err +} + +func (r *RelationshipDefinition) GetRelationshipDefinitionDB() (rdb RelationshipDefinitionDB) { + rdb.ID = r.ID + rdb.TypeMeta = r.TypeMeta + rdb.Metadata, _ = json.Marshal(r.Metadata) + rdb.Selectors, _ = json.Marshal(r.Selectors) + rdb.RelType = r.RelType + rdb.SubType = r.SubType + return +} diff --git a/models/meshmodel/registry.go b/models/meshmodel/registry.go index 4109e4d0..d219d74e 100644 --- a/models/meshmodel/registry.go +++ b/models/meshmodel/registry.go @@ -119,6 +119,13 @@ func (rm *RegistryManager) GetEntities(f types.Filter) []Entity { en = append(en, comp) } return en + case *v1alpha1.RelationshipFilter: + en := make([]Entity, 1) + relationships := v1alpha1.GetRelationships(rm.db, *filter) + for _, rel := range relationships { + en = append(en, rel) + } + return en default: return nil } From cb8224e87db5686ba35d8f362968a82b65c93748 Mon Sep 17 00:00:00 2001 From: Nithish Date: Fri, 16 Dec 2022 00:31:05 +0530 Subject: [PATCH 3/6] refactor: Change Relationship struct Signed-off-by: Nithish --- .../meshmodel/core/v1alpha1/relationship.go | 30 ++++--------------- 1 file changed, 6 insertions(+), 24 deletions(-) diff --git a/models/meshmodel/core/v1alpha1/relationship.go b/models/meshmodel/core/v1alpha1/relationship.go index b286a39e..6de6e92f 100644 --- a/models/meshmodel/core/v1alpha1/relationship.go +++ b/models/meshmodel/core/v1alpha1/relationship.go @@ -11,12 +11,12 @@ import ( // https://docs.google.com/drawings/d/1_qzQ_YxvCWPYrOBcdqGMlMwfbsZx96SBuIkbn8TfKhU/edit?pli=1 // see RELATIONSHIPDEFINITIONS table in the diagram +// TODO: Add support for Model type RelationshipDefinition struct { ID uuid.UUID `json:"-"` TypeMeta Metadata map[string]interface{} `json:"metadata" yaml:"metadata"` // using RelType since there is a method called `Type` - RelType string `json:"type" yaml:"type"` SubType string `json:"subType" yaml:"subType" gorm:"subType"` Selectors map[string]interface{} `json:"selectors" yaml:"selectors"` CreatedAt time.Time `json:"-"` @@ -27,7 +27,6 @@ type RelationshipDefinitionDB struct { ID uuid.UUID `json:"-"` TypeMeta Metadata []byte `json:"metadata" yaml:"metadata"` - RelType string `json:"type" yaml:"type" gorm:"type"` SubType string `json:"subType" yaml:"subType"` Selectors []byte `json:"selectors" yaml:"selectors"` CreatedAt time.Time `json:"-"` @@ -36,9 +35,9 @@ type RelationshipDefinitionDB struct { // For now, only filtering by Kind, Type or SubType can be done. // In the future, we will add support to query using `selectors` (using CUE) +// TODO: Add support for Model type RelationshipFilter struct { Kind string - Type string SubType string } @@ -51,30 +50,13 @@ func (rf *RelationshipFilter) Create(m map[string]interface{}) { func GetRelationships(db *database.Handler, f RelationshipFilter) (rs []RelationshipDefinition) { var rdb []RelationshipDefinitionDB - if f.Type != "" { - _ = db.Where("type = ?", f.Type).Find(&rdb).Error + if f.Kind != "" { + _ = db.Where("kind = ?", f.Kind).Find(&rdb).Error for _, reldb := range rdb { rel := reldb.GetRelationshipDefinition() rs = append(rs, rel) } } - if f.Kind != "" { - if len(rs) == 0 { - _ = db.Where("kind = ?", f.Kind).Find(&rdb).Error - for _, reldb := range rdb { - rel := reldb.GetRelationshipDefinition() - rs = append(rs, rel) - } - } else { - filteredRs := []RelationshipDefinition{} - for _, rd := range rs { - if rd.Kind == f.Kind { - filteredRs = append(filteredRs, rd) - } - } - rs = filteredRs - } - } if f.SubType != "" { if len(rs) == 0 { _ = db.Where("subtype = ?", f.SubType).Find(&rdb).Error @@ -107,7 +89,7 @@ func (rdb *RelationshipDefinitionDB) GetRelationshipDefinition() (r Relationship } _ = json.Unmarshal(rdb.Selectors, &r.Selectors) r.SubType = rdb.SubType - r.RelType = rdb.RelType + r.Kind = rdb.Kind return } @@ -130,7 +112,7 @@ func (r *RelationshipDefinition) GetRelationshipDefinitionDB() (rdb Relationship rdb.TypeMeta = r.TypeMeta rdb.Metadata, _ = json.Marshal(r.Metadata) rdb.Selectors, _ = json.Marshal(r.Selectors) - rdb.RelType = r.RelType + rdb.Kind = r.Kind rdb.SubType = r.SubType return } From 5d13c092b5cdca6d8bc868cf192530fca3fcf036 Mon Sep 17 00:00:00 2001 From: Nithish Date: Fri, 16 Dec 2022 01:45:09 +0530 Subject: [PATCH 4/6] refactor: Change query logic and support adding relationships in the table Signed-off-by: Nithish --- .../meshmodel/core/v1alpha1/relationship.go | 7 +++++++ models/meshmodel/registry.go | 19 +++++++++++++++++++ 2 files changed, 26 insertions(+) diff --git a/models/meshmodel/core/v1alpha1/relationship.go b/models/meshmodel/core/v1alpha1/relationship.go index 6de6e92f..31da3392 100644 --- a/models/meshmodel/core/v1alpha1/relationship.go +++ b/models/meshmodel/core/v1alpha1/relationship.go @@ -74,6 +74,13 @@ func GetRelationships(db *database.Handler, f RelationshipFilter) (rs []Relation rs = filteredRs } } + if len(rs) == 0 { + db.Find(&rdb) + for _, reldb := range rdb { + rel := reldb.GetRelationshipDefinition() + rs = append(rs, rel) + } + } return } diff --git a/models/meshmodel/registry.go b/models/meshmodel/registry.go index d219d74e..3142a467 100644 --- a/models/meshmodel/registry.go +++ b/models/meshmodel/registry.go @@ -69,6 +69,7 @@ func NewRegistryManager(db *database.Handler) (*RegistryManager, error) { &Registry{}, &Host{}, &v1alpha1.ComponentDefinitionDB{}, + &v1alpha1.RelationshipDefinitionDB{}, &v1alpha1.Models{}, ) if err != nil { @@ -104,6 +105,24 @@ func (rm *RegistryManager) RegisterEntity(h Host, en Entity) error { UpdatedAt: time.Now(), } return rm.db.Create(&entry).Error + case v1alpha1.RelationshipDefinition: + relationshipID, err := v1alpha1.CreateRelationship(rm.db, entity) + if err != nil { + return err + } + registrantID, err := createHost(rm.db, h) + if err != nil { + return err + } + entry := Registry{ + ID: uuid.New(), + RegistrantID: registrantID, + Entity: relationshipID, + Type: en.Type(), + CreatedAt: time.Now(), + UpdatedAt: time.Now(), + } + return rm.db.Create(&entry).Error //Add logic for Policies and other entities below default: return nil From c2a79c37af07c75c5671358c98e9f23b40bf125d Mon Sep 17 00:00:00 2001 From: Nithish Date: Fri, 16 Dec 2022 02:17:43 +0530 Subject: [PATCH 5/6] refactor: Use gorm effectively Signed-off-by: Nithish --- .../meshmodel/core/v1alpha1/relationship.go | 41 ++++--------------- 1 file changed, 8 insertions(+), 33 deletions(-) diff --git a/models/meshmodel/core/v1alpha1/relationship.go b/models/meshmodel/core/v1alpha1/relationship.go index 31da3392..cd41c89d 100644 --- a/models/meshmodel/core/v1alpha1/relationship.go +++ b/models/meshmodel/core/v1alpha1/relationship.go @@ -15,8 +15,7 @@ import ( type RelationshipDefinition struct { ID uuid.UUID `json:"-"` TypeMeta - Metadata map[string]interface{} `json:"metadata" yaml:"metadata"` - // using RelType since there is a method called `Type` + Metadata map[string]interface{} `json:"metadata" yaml:"metadata"` SubType string `json:"subType" yaml:"subType" gorm:"subType"` Selectors map[string]interface{} `json:"selectors" yaml:"selectors"` CreatedAt time.Time `json:"-"` @@ -33,7 +32,7 @@ type RelationshipDefinitionDB struct { UpdatedAt time.Time `json:"-"` } -// For now, only filtering by Kind, Type or SubType can be done. +// For now, only filtering by Kind and SubType are allowed. // In the future, we will add support to query using `selectors` (using CUE) // TODO: Add support for Model type RelationshipFilter struct { @@ -50,36 +49,12 @@ func (rf *RelationshipFilter) Create(m map[string]interface{}) { func GetRelationships(db *database.Handler, f RelationshipFilter) (rs []RelationshipDefinition) { var rdb []RelationshipDefinitionDB - if f.Kind != "" { - _ = db.Where("kind = ?", f.Kind).Find(&rdb).Error - for _, reldb := range rdb { - rel := reldb.GetRelationshipDefinition() - rs = append(rs, rel) - } - } - if f.SubType != "" { - if len(rs) == 0 { - _ = db.Where("subtype = ?", f.SubType).Find(&rdb).Error - for _, reldb := range rdb { - rel := reldb.GetRelationshipDefinition() - rs = append(rs, rel) - } - } else { - filteredRs := []RelationshipDefinition{} - for _, rd := range rs { - if rd.SubType == f.SubType { - filteredRs = append(filteredRs, rd) - } - } - rs = filteredRs - } - } - if len(rs) == 0 { - db.Find(&rdb) - for _, reldb := range rdb { - rel := reldb.GetRelationshipDefinition() - rs = append(rs, rel) - } + // GORM takes care of drafting the correct SQL + // https://gorm.io/docs/query.html#Struct-amp-Map-Conditions + _ = db.Where(&RelationshipDefinitionDB{SubType: f.SubType, TypeMeta: TypeMeta{Kind: f.Kind}}).Find(&rdb) + for _, reldb := range rdb { + rel := reldb.GetRelationshipDefinition() + rs = append(rs, rel) } return } From 616ccf26e1bfcd0a594f157ef74c6276b953ae37 Mon Sep 17 00:00:00 2001 From: Nithish Date: Sun, 18 Dec 2022 03:16:52 +0530 Subject: [PATCH 6/6] fix: Update tests and migrate Relationships table Signed-off-by: Nithish --- utils/artifacthub/package_test.go | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/utils/artifacthub/package_test.go b/utils/artifacthub/package_test.go index f4d45be8..50cbc58c 100644 --- a/utils/artifacthub/package_test.go +++ b/utils/artifacthub/package_test.go @@ -1,6 +1,9 @@ package artifacthub -import "testing" +import ( + "strings" + "testing" +) func TestGetChartUrl(t *testing.T) { var tests = []struct { @@ -9,7 +12,7 @@ func TestGetChartUrl(t *testing.T) { }{ // these might change in the future, so the tests have to be changed as well when the urls change // because the urls will change with every new version update to the package - {AhPackage{Name: "consul", Repository: "bitnami", Organization: "", RepoUrl: "https://charts.bitnami.com/bitnami"}, "https://charts.bitnami.com/bitnami/consul-10.9.5.tgz"}, + {AhPackage{Name: "consul", Repository: "bitnami", Organization: "", RepoUrl: "https://charts.bitnami.com/bitnami"}, "https://charts.bitnami.com/bitnami/consul"}, {AhPackage{Name: "crossplane-types", Repository: "crossplane", Organization: "", RepoUrl: "https://charts.crossplane.io/master"}, "https://charts.crossplane.io/master/crossplane-types-0.13.0-rc.191.g3a18fb7.tgz"}, } for _, tt := range tests { @@ -19,7 +22,7 @@ func TestGetChartUrl(t *testing.T) { t.Errorf("error while updating package data = %v", err) return } - if tt.ahpkg.ChartUrl != tt.want { + if !strings.HasPrefix(tt.ahpkg.ChartUrl, tt.want) { t.Errorf("got %v, want %v", tt.ahpkg.ChartUrl, tt.want) } })