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

Make selectors available in mindev #3943

Merged
merged 1 commit into from
Jul 19, 2024
Merged
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
75 changes: 66 additions & 9 deletions cmd/dev/app/rule_type/rttst.go
Original file line number Diff line number Diff line change
Expand Up @@ -37,12 +37,14 @@ import (
"github.com/stacklok/minder/internal/engine/eval/rego"
engif "github.com/stacklok/minder/internal/engine/interfaces"
"github.com/stacklok/minder/internal/engine/rtengine"
"github.com/stacklok/minder/internal/engine/selectors"
"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"
"github.com/stacklok/minder/internal/providers/ratecache"
provsel "github.com/stacklok/minder/internal/providers/selectors"
"github.com/stacklok/minder/internal/providers/telemetry"
"github.com/stacklok/minder/internal/util/jsonyaml"
minderv1 "github.com/stacklok/minder/pkg/api/protobuf/go/minder/v1"
Expand Down Expand Up @@ -118,7 +120,7 @@ func testCmdRun(cmd *cobra.Command, _ []string) error {
Project: &rootProject,
}

ent, err := readEntityFromFile(epath.Value.String(), minderv1.EntityFromString(ruletype.Def.InEntity))
eiw, err := getEiwFromFile(ruletype, epath.Value.String())
if err != nil {
return fmt.Errorf("error reading entity from file: %w", err)
}
Expand Down Expand Up @@ -163,6 +165,9 @@ func testCmdRun(cmd *cobra.Command, _ []string) error {
if err != nil {
return fmt.Errorf("error getting relevant fragment: %w", err)
}
if len(rules) == 0 {
return fmt.Errorf("no rules found with type %s", ruletype.Name)
}

// TODO: Whenever we add more Provider classes, we will need to rethink this
prov, err := getProvider(providerclass.Value.String(), token, providerconfig.Value.String())
Expand All @@ -181,25 +186,48 @@ func testCmdRun(cmd *cobra.Command, _ []string) error {
return fmt.Errorf("cannot create rule actions engine: %w", err)
}

inf := &entities.EntityInfoWrapper{
Entity: ent,
ExecutionID: &uuid.Nil,
profSel, err := getProfileSelectors(eiw.Type, profile)
if err != nil {
return fmt.Errorf("error creating selectors: %w", err)
}

return runEvaluationForRules(cmd, eng, eiw, prov, profSel, remediateStatus, remMetadata, rules, actionEngine)
}

func getProfileSelectors(entType minderv1.Entity, profile *minderv1.Profile) (selectors.Selection, error) {
selectorEnv, err := selectors.NewEnv()
if err != nil {
return fmt.Errorf("error creating rule type engine: %w", err)
return nil, fmt.Errorf("error creating selector environment: %w", err)
}

if len(rules) == 0 {
return fmt.Errorf("no rules found with type %s", ruletype.Name)
profSel, err := selectorEnv.NewSelectionFromProfile(entType, profile.Selection)
if err != nil {
return nil, fmt.Errorf("error creating selectors: %w", err)
}

return runEvaluationForRules(cmd, eng, inf, remediateStatus, remMetadata, rules, actionEngine)
return profSel, nil
}

func getEiwFromFile(ruletype *minderv1.RuleType, epath string) (*entities.EntityInfoWrapper, error) {
entType := minderv1.EntityFromString(ruletype.Def.InEntity)
ent, err := readEntityFromFile(epath, entType)
if err != nil {
return nil, fmt.Errorf("error reading entity from file: %w", err)
}

return &entities.EntityInfoWrapper{
Entity: ent,
Type: entType,
ExecutionID: &uuid.Nil,
}, nil
}

func runEvaluationForRules(
cmd *cobra.Command,
eng *rtengine.RuleTypeEngine,
inf *entities.EntityInfoWrapper,
provider provifv1.Provider,
entitySelectors selectors.Selection,
remediateStatus db.NullRemediationStatusTypes,
remMetadata pqtype.NullRawMessage,
frags []*minderv1.Profile_Rule,
Expand Down Expand Up @@ -232,7 +260,8 @@ func runEvaluationForRules(
ctx = logger.FromFlags(logConfig).WithContext(ctx)

// Perform rule evaluation
evalStatus.SetEvalErr(eng.Eval(ctx, inf, evalStatus))
evalErr := selectAndEval(ctx, eng, provider, inf, evalStatus, entitySelectors)
evalStatus.SetEvalErr(evalErr)

// Perform the actions, if any
evalStatus.SetActionsErr(ctx, actionEngine.DoActions(ctx, inf.Entity, evalStatus))
Expand All @@ -251,6 +280,34 @@ func runEvaluationForRules(
return nil
}

func selectAndEval(
ctx context.Context,
eng *rtengine.RuleTypeEngine,
provider provifv1.Provider,
inf *entities.EntityInfoWrapper,
evalStatus *engif.EvalStatusParams,
profileSelectors selectors.Selection,
) error {
selEnt := provsel.EntityToSelectorEntity(ctx, provider, inf.Type, inf.Entity)
if selEnt == nil {
return fmt.Errorf("error converting entity to selector entity")
}

selected, err := profileSelectors.Select(selEnt)
if err != nil {
return fmt.Errorf("error selecting entity: %w", err)
}

var evalErr error
if selected {
evalErr = eng.Eval(ctx, inf, evalStatus)
} else {
evalErr = errors.NewErrEvaluationSkipped("entity not selected by selectors")
}

return evalErr
}

func readRuleTypeFromFile(fpath string) (*minderv1.RuleType, error) {
f, err := os.Open(filepath.Clean(fpath))
if err != nil {
Expand Down