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

Move profile and ruletype logic out of engine package #3520

Merged
merged 1 commit into from
Jun 4, 2024
Merged
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
4 changes: 2 additions & 2 deletions cmd/cli/app/profile/common.go
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ import (

"github.com/spf13/viper"

"github.com/stacklok/minder/internal/engine"
"github.com/stacklok/minder/internal/profiles"
"github.com/stacklok/minder/internal/util"
"github.com/stacklok/minder/internal/util/cli"
"github.com/stacklok/minder/internal/util/cli/table"
Expand Down Expand Up @@ -57,7 +57,7 @@ func ExecOnOneProfile(ctx context.Context, t table.Table, f string, dashOpen io.
}

func parseProfile(r io.Reader, proj string) (*minderv1.Profile, error) {
p, err := engine.ParseYAML(r)
p, err := profiles.ParseYAML(r)
if err != nil {
return nil, fmt.Errorf("error reading profile from file: %w", err)
}
Expand Down
4 changes: 2 additions & 2 deletions cmd/cli/app/quickstart/quickstart.go
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ import (
"github.com/stacklok/minder/cmd/cli/app/profile"
minderprov "github.com/stacklok/minder/cmd/cli/app/provider"
"github.com/stacklok/minder/cmd/cli/app/repo"
"github.com/stacklok/minder/internal/engine"
"github.com/stacklok/minder/internal/profiles"
ghclient "github.com/stacklok/minder/internal/providers/github/clients"
"github.com/stacklok/minder/internal/util/cli"
minderv1 "github.com/stacklok/minder/pkg/api/protobuf/go/minder/v1"
Expand Down Expand Up @@ -325,7 +325,7 @@ func quickstartCommand(_ context.Context, cmd *cobra.Command, _ []string, conn *
}

// Load the profile from the embedded file system
p, err := engine.ParseYAML(reader)
p, err := profiles.ParseYAML(reader)
if err != nil {
return cli.MessageAndError("error parsing profile", err)
}
Expand Down
3 changes: 2 additions & 1 deletion cmd/dev/app/rule_type/rttst.go
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@ import (
"github.com/stacklok/minder/internal/engine/eval/rego"
engif "github.com/stacklok/minder/internal/engine/interfaces"
"github.com/stacklok/minder/internal/logger"
"github.com/stacklok/minder/internal/profiles"
"github.com/stacklok/minder/internal/providers/credentials"
"github.com/stacklok/minder/internal/providers/dockerhub"
"github.com/stacklok/minder/internal/providers/github/clients"
Expand Down Expand Up @@ -121,7 +122,7 @@ func testCmdRun(cmd *cobra.Command, _ []string) error {
return fmt.Errorf("error reading entity from file: %w", err)
}

profile, err := engine.ReadProfileFromFile(ppath.Value.String())
profile, err := profiles.ReadProfileFromFile(ppath.Value.String())
if err != nil {
return fmt.Errorf("error reading fragment from file: %w", err)
}
Expand Down
4 changes: 2 additions & 2 deletions internal/controlplane/handlers_profile.go
Original file line number Diff line number Diff line change
Expand Up @@ -143,7 +143,7 @@ func (s *Server) ListProfiles(ctx context.Context,

var resp minderv1.ListProfilesResponse
resp.Profiles = make([]*minderv1.Profile, 0, len(profiles))
profileMap := engine.MergeDatabaseListIntoProfiles(profiles)
profileMap := prof.MergeDatabaseListIntoProfiles(profiles)

// Sort the profiles by name to get a consistent order. This is important for UI.
profileNames := make([]string, 0, len(profileMap))
Expand Down Expand Up @@ -211,7 +211,7 @@ func getProfilePBFromDB(
return nil, err
}

pols := engine.MergeDatabaseGetIntoProfiles(profiles)
pols := prof.MergeDatabaseGetIntoProfiles(profiles)
if len(pols) == 0 {
return nil, fmt.Errorf("profile not found")
} else if len(pols) > 1 {
Expand Down
6 changes: 3 additions & 3 deletions internal/controlplane/handlers_ruletype.go
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,7 @@ func (s *Server) ListRuleTypes(

for idx := range lrt {
rt := lrt[idx]
rtpb, err := engine.RuleTypePBFromDB(&rt)
rtpb, err := ruletypes.RuleTypePBFromDB(&rt)
if err != nil {
return nil, fmt.Errorf("cannot convert rule type %s to pb: %v", rt.Name, err)
}
Expand Down Expand Up @@ -92,7 +92,7 @@ func (s *Server) GetRuleTypeByName(
return nil, status.Errorf(codes.Unknown, "failed to get rule type: %s", err)
}

rt, err := engine.RuleTypePBFromDB(&rtdb)
rt, err := ruletypes.RuleTypePBFromDB(&rtdb)
if err != nil {
return nil, fmt.Errorf("cannot convert rule type %s to pb: %v", rtdb.Name, err)
}
Expand Down Expand Up @@ -132,7 +132,7 @@ func (s *Server) GetRuleTypeById(
return nil, status.Errorf(codes.Unknown, "failed to get rule type: %s", err)
}

rt, err := engine.RuleTypePBFromDB(&rtdb)
rt, err := ruletypes.RuleTypePBFromDB(&rtdb)
if err != nil {
return nil, fmt.Errorf("cannot convert rule type %s to pb: %v", rtdb.Name, err)
}
Expand Down
10 changes: 6 additions & 4 deletions internal/engine/executor.go
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,9 @@ import (
engif "github.com/stacklok/minder/internal/engine/interfaces"
"github.com/stacklok/minder/internal/events"
minderlogger "github.com/stacklok/minder/internal/logger"
"github.com/stacklok/minder/internal/profiles"
"github.com/stacklok/minder/internal/providers/manager"
"github.com/stacklok/minder/internal/ruletypes"
pb "github.com/stacklok/minder/pkg/api/protobuf/go/minder/v1"
provinfv1 "github.com/stacklok/minder/pkg/providers/v1"
)
Expand Down Expand Up @@ -180,13 +182,13 @@ func (e *Executor) evalEntityEvent(ctx context.Context, inf *entities.EntityInfo
err = e.forProjectsInHierarchy(
ctx, inf, func(ctx context.Context, profile *pb.Profile, hierarchy []uuid.UUID) error {
// Get only these rules that are relevant for this entity type
relevant, err := GetRulesForEntity(profile, inf.Type)
relevant, err := profiles.GetRulesForEntity(profile, inf.Type)
if err != nil {
return fmt.Errorf("error getting rules for entity: %w", err)
}

// Let's evaluate all the rules for this profile
err = TraverseRules(relevant, func(rule *pb.Profile_Rule) error {
err = profiles.TraverseRules(relevant, func(rule *pb.Profile_Rule) error {
// Get the engine evaluator for this rule type
evalParams, rte, err := e.getEvaluator(
ctx, inf, provider, profile, rule, hierarchy, ingestCache)
Expand Down Expand Up @@ -246,7 +248,7 @@ func (e *Executor) forProjectsInHierarchy(
return fmt.Errorf("error getting profiles: %w", err)
}

for _, profile := range MergeDatabaseListIntoProfiles(dbpols) {
for _, profile := range profiles.MergeDatabaseListIntoProfiles(dbpols) {
if err := f(ctx, profile, projectHierarchy); err != nil {
return err
}
Expand Down Expand Up @@ -288,7 +290,7 @@ func (e *Executor) getEvaluator(
}

// Parse the rule type
rt, err := RuleTypePBFromDB(&dbrt)
rt, err := ruletypes.RuleTypePBFromDB(&dbrt)
if err != nil {
return nil, nil, fmt.Errorf("error parsing rule type when traversing profile %s: %w", params.ProfileID, err)
}
Expand Down
65 changes: 6 additions & 59 deletions internal/engine/rule_type_engine.go
Original file line number Diff line number Diff line change
Expand Up @@ -21,16 +21,15 @@ import (
"strings"

"github.com/rs/zerolog"
"google.golang.org/protobuf/encoding/protojson"

"github.com/stacklok/minder/internal/db"
"github.com/stacklok/minder/internal/engine/actions"
"github.com/stacklok/minder/internal/engine/entities"
enginerr "github.com/stacklok/minder/internal/engine/errors"
"github.com/stacklok/minder/internal/engine/eval"
"github.com/stacklok/minder/internal/engine/ingestcache"
"github.com/stacklok/minder/internal/engine/ingester"
engif "github.com/stacklok/minder/internal/engine/interfaces"
"github.com/stacklok/minder/internal/profiles"
minderv1 "github.com/stacklok/minder/pkg/api/protobuf/go/minder/v1"
provinfv1 "github.com/stacklok/minder/pkg/providers/v1"
)
Expand Down Expand Up @@ -69,7 +68,7 @@ type RuleTypeEngine struct {
// actionsEngine is the rule actions engine
actionsEngine *actions.RuleActionsEngine

ruleValidator *RuleValidator
ruleValidator *profiles.RuleValidator

ruletype *minderv1.RuleType

Expand All @@ -85,7 +84,7 @@ func NewRuleTypeEngine(
ruletype *minderv1.RuleType,
provider provinfv1.Provider,
) (*RuleTypeEngine, error) {
rval, err := NewRuleValidator(ruletype)
rval, err := profiles.NewRuleValidator(ruletype)
if err != nil {
return nil, fmt.Errorf("cannot create rule validator: %w", err)
}
Expand Down Expand Up @@ -142,7 +141,7 @@ func (r *RuleTypeEngine) GetID() string {

// GetRuleInstanceValidator returns the rule instance validator for this rule type.
// By instance we mean a rule that has been instantiated in a profile from a given rule type.
func (r *RuleTypeEngine) GetRuleInstanceValidator() *RuleValidator {
func (r *RuleTypeEngine) GetRuleInstanceValidator() *profiles.RuleValidator {
return r.ruleValidator
}

Expand Down Expand Up @@ -193,67 +192,15 @@ func (r *RuleTypeEngine) GetActionsOnOff() map[engif.ActionType]engif.ActionOpt
return r.actionsEngine.GetOnOffState()
}

// RuleDefFromDB converts a rule type definition from the database to a protobuf
// rule type definition
func RuleDefFromDB(r *db.RuleType) (*minderv1.RuleType_Definition, error) {
def := &minderv1.RuleType_Definition{}

if err := protojson.Unmarshal(r.Definition, def); err != nil {
return nil, fmt.Errorf("cannot unmarshal rule type definition: %w", err)
}
return def, nil
}

// RuleTypePBFromDB converts a rule type from the database to a protobuf
// rule type
func RuleTypePBFromDB(rt *db.RuleType) (*minderv1.RuleType, error) {
def, err := RuleDefFromDB(rt)
if err != nil {
return nil, fmt.Errorf("cannot get rule type definition: %w", err)
}

id := rt.ID.String()
project := rt.ProjectID.String()

var seval minderv1.Severity_Value

if err := seval.FromString(string(rt.SeverityValue)); err != nil {
seval = minderv1.Severity_VALUE_UNKNOWN
}

displayName := rt.DisplayName
if displayName == "" {
displayName = rt.Name
}

// TODO: (2024/03/28) this is for compatibility with old CLI versions that expect provider, remove this eventually
noProvider := ""
return &minderv1.RuleType{
Id: &id,
Name: rt.Name,
DisplayName: displayName,
Context: &minderv1.Context{
Provider: &noProvider,
Project: &project,
},
Description: rt.Description,
Guidance: rt.Guidance,
Def: def,
Severity: &minderv1.Severity{
Value: seval,
},
}, nil
}

// GetRulesFromProfileOfType returns the rules from the profile of the given type
func GetRulesFromProfileOfType(p *minderv1.Profile, rt *minderv1.RuleType) ([]*minderv1.Profile_Rule, error) {
contextualRules, err := GetRulesForEntity(p, minderv1.EntityFromString(rt.Def.InEntity))
contextualRules, err := profiles.GetRulesForEntity(p, minderv1.EntityFromString(rt.Def.InEntity))
if err != nil {
return nil, fmt.Errorf("error getting rules for entity: %w", err)
}

rules := []*minderv1.Profile_Rule{}
err = TraverseRules(contextualRules, func(r *minderv1.Profile_Rule) error {
err = profiles.TraverseRules(contextualRules, func(r *minderv1.Profile_Rule) error {
if r.Type == rt.Name {
rules = append(rules, r)
}
Expand Down
3 changes: 1 addition & 2 deletions internal/profiles/rule_names.go
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,6 @@
package profiles

import (
"github.com/stacklok/minder/internal/engine"
minderv1 "github.com/stacklok/minder/pkg/api/protobuf/go/minder/v1"
)

Expand All @@ -32,7 +31,7 @@ func ComputeRuleName(rule *minderv1.Profile_Rule) string {

// PopulateRuleNames fills in the rule name for all rule instances in a profile
func PopulateRuleNames(profile *minderv1.Profile) {
_ = engine.TraverseAllRulesForPipeline(profile, func(r *minderv1.Profile_Rule) error {
_ = TraverseAllRulesForPipeline(profile, func(r *minderv1.Profile_Rule) error {
r.Name = ComputeRuleName(r)
return nil
},
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@
// limitations under the License.
// Package rule provides the CLI subcommand for managing rules

package engine
package profiles

import (
"fmt"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@
// limitations under the License.
// Package rule provides the CLI subcommand for managing rules

package engine_test
package profiles_test

import (
"os"
Expand All @@ -23,14 +23,15 @@ import (
"github.com/stretchr/testify/require"

"github.com/stacklok/minder/internal/engine"
"github.com/stacklok/minder/internal/profiles"
minderv1 "github.com/stacklok/minder/pkg/api/protobuf/go/minder/v1"
)

func TestExampleRulesAreValidatedCorrectly(t *testing.T) {
t.Parallel()

t.Log("parsing example profile")
pol, err := engine.ReadProfileFromFile("../../examples/rules-and-profiles/profiles/github/profile.yaml")
pol, err := profiles.ReadProfileFromFile("../../examples/rules-and-profiles/profiles/github/profile.yaml")
require.NoError(t, err, "failed to parse example profile, make sure to do - make init-examples")

// open rules in example directory
Expand Down Expand Up @@ -63,7 +64,7 @@ func TestExampleRulesAreValidatedCorrectly(t *testing.T) {
require.NoError(t, rt.Validate(), "failed to validate rule type %s", path)

t.Log("creating rule validator")
rval, err := engine.NewRuleValidator(rt)
rval, err := profiles.NewRuleValidator(rt)
require.NoError(t, err, "failed to create rule validator for rule type %s", path)

rules, err := engine.GetRulesFromProfileOfType(pol, rt)
Expand Down
8 changes: 4 additions & 4 deletions internal/profiles/service.go
Original file line number Diff line number Diff line change
Expand Up @@ -33,12 +33,12 @@ import (
"google.golang.org/protobuf/types/known/fieldmaskpb"

"github.com/stacklok/minder/internal/db"
"github.com/stacklok/minder/internal/engine"
"github.com/stacklok/minder/internal/engine/entities"
"github.com/stacklok/minder/internal/events"
"github.com/stacklok/minder/internal/logger"
"github.com/stacklok/minder/internal/marketplaces/namespaces"
"github.com/stacklok/minder/internal/reconcilers"
"github.com/stacklok/minder/internal/ruletypes"
"github.com/stacklok/minder/internal/util"
"github.com/stacklok/minder/internal/util/ptr"
minderv1 "github.com/stacklok/minder/pkg/api/protobuf/go/minder/v1"
Expand Down Expand Up @@ -501,7 +501,7 @@ func getProfilePBFromDB(
return nil, err
}

pols := engine.MergeDatabaseGetIntoProfiles(profiles)
pols := MergeDatabaseGetIntoProfiles(profiles)
if len(pols) == 0 {
return nil, fmt.Errorf("profile not found")
} else if len(pols) > 1 {
Expand All @@ -526,7 +526,7 @@ func (_ *profileService) getRulesFromProfile(
// track them in the db later.
rulesInProf := make(RuleMapping)

err := engine.TraverseAllRulesForPipeline(profile, func(r *minderv1.Profile_Rule) error {
err := TraverseAllRulesForPipeline(profile, func(r *minderv1.Profile_Rule) error {
// TODO: This will need to be updated to support
// the hierarchy tree once that's settled in.
rtdb, err := qtx.GetRuleTypeByName(ctx, db.GetRuleTypeByNameParams{
Expand All @@ -537,7 +537,7 @@ func (_ *profileService) getRulesFromProfile(
return fmt.Errorf("error getting rule type %s: %w", r.GetType(), err)
}

rtyppb, err := engine.RuleTypePBFromDB(&rtdb)
rtyppb, err := ruletypes.RuleTypePBFromDB(&rtdb)
if err != nil {
return fmt.Errorf("cannot convert rule type %s to pb: %w", rtdb.Name, err)
}
Expand Down
3 changes: 1 addition & 2 deletions internal/engine/profile.go → internal/profiles/util.go
Original file line number Diff line number Diff line change
Expand Up @@ -11,9 +11,8 @@
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
// Package rule provides the CLI subcommand for managing rules

package engine
package profiles

import (
"bytes"
Expand Down
Loading
Loading