diff --git a/models/meshmodel/core/policies/rego_policy_relationship.go b/models/meshmodel/core/policies/rego_policy_relationship.go index d884fd18..df31f54c 100644 --- a/models/meshmodel/core/policies/rego_policy_relationship.go +++ b/models/meshmodel/core/policies/rego_policy_relationship.go @@ -10,12 +10,11 @@ import ( ) // RegoPolicyHandler takes the required inputs and run the query against all the policy files provided -func RegoPolicyHandler(ctx context.Context, policyDir []string, regoQueryString string, designFile []byte) (map[string]interface{}, error) { - regoPolicyLoader := rego.Load(policyDir, nil) +func RegoPolicyHandler(ctx context.Context, expression string, regoQueryString string, designFile []byte) (map[string]interface{}, error) { regoEngine, err := rego.New( rego.Query(regoQueryString), - regoPolicyLoader, + rego.Module("expression.rego", expression), ).PrepareForEval(ctx) if err != nil { logrus.Error("error preparing for evaluation", err) diff --git a/models/meshmodel/core/v1alpha1/policy.go b/models/meshmodel/core/v1alpha1/policy.go index f616cb4e..70b1b1ec 100644 --- a/models/meshmodel/core/v1alpha1/policy.go +++ b/models/meshmodel/core/v1alpha1/policy.go @@ -8,6 +8,7 @@ import ( "github.com/google/uuid" "github.com/layer5io/meshkit/database" "github.com/layer5io/meshkit/models/meshmodel/core/types" + "gorm.io/gorm/clause" ) type PolicyDefinition struct { @@ -15,7 +16,8 @@ type PolicyDefinition struct { TypeMeta Model Model `json:"model"` SubType string `json:"subType" yaml:"subType"` - Expression map[string]interface{} `json:"expression" yaml:"expression"` + Expression string `json:"expression" yaml:"expression"` + Metadata map[string]interface{} `json:"metadata" yaml:"metadata"` CreatedAt time.Time `json:"-"` UpdatedAt time.Time `json:"-"` } @@ -25,15 +27,23 @@ type PolicyDefinitionDB struct { ModelID uuid.UUID `json:"-" gorm:"modelID"` TypeMeta SubType string `json:"subType" yaml:"subType"` - Expression []byte `json:"expression" yaml:"expression"` + Expression string `json:"expression" yaml:"expression"` + Metadata []byte `json:"metadata" yaml:"metadata"` CreatedAt time.Time `json:"-"` UpdatedAt time.Time `json:"-"` } type PolicyFilter struct { - Kind string - SubType string - ModelName string + Kind string + SubType string + Name string + APIVersion string + ModelName string + Version string // future use for versioning + Sort string //asc or desc. Default behavior is asc + OrderOn string //Name of the field on which sorting is to be done + Limit int //If 0 or unspecified then all records are returned and limit is not used + Offset int } func (pf *PolicyFilter) Create(m map[string]interface{}) { @@ -50,15 +60,18 @@ func (p PolicyDefinition) Type() types.CapabilityType { return types.PolicyDefinition } -func GetMeshModelPolicy(db *database.Handler, f PolicyFilter) (pl []PolicyDefinition) { +func GetMeshModelPolicy(db *database.Handler, f PolicyFilter) (pl []PolicyDefinition, count int64) { type componentDefinitionWithModel struct { PolicyDefinitionDB - Model + ModelDB + CategoryDB } + var componentDefinitionsWithModel []componentDefinitionWithModel finder := db.Model(&PolicyDefinitionDB{}). - Select("policy_definition_dbs.*, models.*"). - Joins("JOIN model_dbs ON model_dbs.id = policy_definition_dbs.model_id") + Select("policy_definition_dbs.*, model_dbs.*"). + Joins("JOIN model_dbs ON model_dbs.id = policy_definition_dbs.model_id"). + Joins("JOIN category_dbs ON model_dbs.category_id = category_dbs.id") if f.Kind != "" { finder = finder.Where("policy_definition_dbs.kind = ?", f.Kind) } @@ -68,14 +81,35 @@ func GetMeshModelPolicy(db *database.Handler, f PolicyFilter) (pl []PolicyDefini if f.ModelName != "" { finder = finder.Where("model_dbs.name = ?", f.ModelName) } + if f.APIVersion != "" { + finder = finder.Where("policy_definition_dbs.api_version = ?", f.APIVersion) + } + if f.Name != "" { + finder = finder.Where("policy_definition_dbs.metadata ->> 'name'", f.Name) + } + if f.OrderOn != "" { + if f.Sort == "desc" { + finder = finder.Order(clause.OrderByColumn{Column: clause.Column{Name: f.OrderOn}, Desc: true}) + } else { + finder = finder.Order(f.OrderOn + " asc") + } + } + + finder.Count(&count) + + finder = finder.Offset(f.Offset) + if f.Limit != 0 { + finder = finder.Limit(f.Limit) + } + err := finder.Scan(&componentDefinitionsWithModel).Error if err != nil { fmt.Println(err.Error()) } for _, cm := range componentDefinitionsWithModel { - pl = append(pl, cm.PolicyDefinitionDB.GetPolicyDefinition(cm.Model)) + pl = append(pl, cm.PolicyDefinitionDB.GetPolicyDefinition(cm.ModelDB.GetModel(cm.CategoryDB.GetCategory(db)))) } - return pl + return pl, count } func (pdb *PolicyDefinitionDB) GetPolicyDefinition(m Model) (p PolicyDefinition) { @@ -83,10 +117,11 @@ func (pdb *PolicyDefinitionDB) GetPolicyDefinition(m Model) (p PolicyDefinition) p.TypeMeta = pdb.TypeMeta p.Model = m p.SubType = pdb.SubType - if p.Expression == nil { - p.Expression = make(map[string]interface{}) + p.Expression = pdb.Expression + if p.Metadata == nil { + p.Metadata = make(map[string]interface{}) } - _ = json.Unmarshal(pdb.Expression, &p.Expression) + _ = json.Unmarshal(pdb.Metadata, &p.Metadata) return } @@ -111,6 +146,7 @@ func (p *PolicyDefinition) GetPolicyDefinitionDB() (pdb PolicyDefinitionDB) { pdb.TypeMeta = p.TypeMeta pdb.SubType = p.SubType pdb.ModelID = p.Model.ID - pdb.Expression, _ = json.Marshal(p.Expression) + pdb.Expression = p.Expression + pdb.Metadata, _ = json.Marshal(p.Metadata) return } diff --git a/models/meshmodel/registry.go b/models/meshmodel/registry.go index 6266a181..4b88d03e 100644 --- a/models/meshmodel/registry.go +++ b/models/meshmodel/registry.go @@ -89,6 +89,7 @@ func (rm *RegistryManager) Cleanup() { &v1alpha1.ModelDB{}, &v1alpha1.CategoryDB{}, &v1alpha1.RelationshipDefinitionDB{}, + &v1alpha1.PolicyDefinitionDB{}, ) } func (rm *RegistryManager) RegisterEntity(h Host, en Entity) error { @@ -132,7 +133,6 @@ func (rm *RegistryManager) RegisterEntity(h Host, en Entity) error { UpdatedAt: time.Now(), } return rm.db.Create(&entry).Error - //Add logic for Policies and other entities below case v1alpha1.PolicyDefinition: policyID, err := v1alpha1.CreatePolicy(rm.db, entity) if err != nil { @@ -175,11 +175,11 @@ func (rm *RegistryManager) GetEntities(f types.Filter) ([]Entity, *int64, *int) return en, &count, nil case *v1alpha1.PolicyFilter: en := make([]Entity, 0) - policies := v1alpha1.GetMeshModelPolicy(rm.db, *filter) + policies, count := v1alpha1.GetMeshModelPolicy(rm.db, *filter) for _, pol := range policies { en = append(en, pol) } - return en, nil, nil + return en, &count default: return nil, nil, nil }