Skip to content

Commit e4f6f47

Browse files
Add names to returned entities-with-types (#5944)
1 parent 5eed5e2 commit e4f6f47

File tree

14 files changed

+244
-167
lines changed

14 files changed

+244
-167
lines changed

cmd/cli/app/profile/status/status_get.go

Lines changed: 19 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ import (
88
"fmt"
99
"os"
1010

11+
"github.com/google/uuid"
1112
"github.com/spf13/cobra"
1213
"github.com/spf13/viper"
1314
"google.golang.org/grpc"
@@ -44,14 +45,24 @@ func getCommand(ctx context.Context, cmd *cobra.Command, _ []string, conn *grpc.
4445
return cli.MessageAndError(fmt.Sprintf("Output format %s not supported", format), fmt.Errorf("invalid argument"))
4546
}
4647

48+
entity := &minderv1.EntityTypedId{
49+
Type: minderv1.EntityFromString(entityType),
50+
}
51+
// If entityId is a UUID, fill the `id` field, otherwise fill the name field.
52+
if _, err := uuid.Parse(entityId); err == nil {
53+
entity.Id = entityId
54+
} else {
55+
entity.Name = entityId
56+
}
57+
4758
if profileId != "" {
48-
resp, err := getProfileStatusById(ctx, client, project, profileId, entityId, entityType)
59+
resp, err := getProfileStatusById(ctx, client, project, profileId, entity)
4960
if err != nil {
5061
return cli.MessageAndError("Error getting profile status", err)
5162
}
5263
return formatAndDisplayOutput(cmd, format, resp, viper.GetBool("emoji"))
5364
} else if profileName != "" {
54-
resp, err := getProfileStatusByName(ctx, client, project, profileName, entityId, entityType)
65+
resp, err := getProfileStatusByName(ctx, client, project, profileName, entity)
5566
if err != nil {
5667
return cli.MessageAndError("Error getting profile status", err)
5768
}
@@ -64,7 +75,8 @@ func getCommand(ctx context.Context, cmd *cobra.Command, _ []string, conn *grpc.
6475
func getProfileStatusById(
6576
ctx context.Context,
6677
client minderv1.ProfileServiceClient,
67-
project, profileId, entityId, entityType string,
78+
project, profileId string,
79+
entity *minderv1.EntityTypedId,
6880
) (*minderv1.GetProfileStatusByIdResponse, error) {
6981
if profileId == "" {
7082
return nil, cli.MessageAndError("Error getting profile status", fmt.Errorf("profile id required"))
@@ -73,10 +85,7 @@ func getProfileStatusById(
7385
resp, err := client.GetProfileStatusById(ctx, &minderv1.GetProfileStatusByIdRequest{
7486
Context: &minderv1.Context{Project: &project},
7587
Id: profileId,
76-
Entity: &minderv1.EntityTypedId{
77-
Id: entityId,
78-
Type: minderv1.EntityFromString(entityType),
79-
},
88+
Entity: entity,
8089
})
8190
if err != nil {
8291
return nil, err
@@ -91,7 +100,8 @@ func getProfileStatusById(
91100
func getProfileStatusByName(
92101
ctx context.Context,
93102
client minderv1.ProfileServiceClient,
94-
project, profileName, entityId, entityType string,
103+
project, profileName string,
104+
entity *minderv1.EntityTypedId,
95105
) (*minderv1.GetProfileStatusByNameResponse, error) {
96106
if profileName == "" {
97107
return nil, cli.MessageAndError("Error getting profile status", fmt.Errorf("profile name required"))
@@ -100,10 +110,7 @@ func getProfileStatusByName(
100110
resp, err := client.GetProfileStatusByName(ctx, &minderv1.GetProfileStatusByNameRequest{
101111
Context: &minderv1.Context{Project: &project},
102112
Name: profileName,
103-
Entity: &minderv1.EntityTypedId{
104-
Id: entityId,
105-
Type: minderv1.EntityFromString(entityType),
106-
},
113+
Entity: entity,
107114
})
108115
if err != nil {
109116
return nil, err

cmd/cli/app/repo/repo_reconcile.go

Lines changed: 9 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -33,29 +33,19 @@ func reconcileCommand(ctx context.Context, cmd *cobra.Command, _ []string, conn
3333
// See https://github.com/spf13/cobra/issues/340#issuecomment-374617413
3434
cmd.SilenceUsage = true
3535

36-
if id == "" {
37-
repoClient := minderv1.NewRepositoryServiceClient(conn)
38-
39-
repo, err := repoClient.GetRepositoryByName(ctx, &minderv1.GetRepositoryByNameRequest{
40-
Name: name,
41-
Context: &minderv1.Context{
42-
Provider: &provider,
43-
Project: &project,
44-
},
45-
})
46-
if err != nil {
47-
return cli.MessageAndError("Failed to get repository", err)
48-
}
49-
50-
id = repo.GetRepository().GetId()
36+
entity := &minderv1.EntityTypedId{
37+
Type: minderv1.Entity_ENTITY_REPOSITORIES,
38+
}
39+
if id != "" {
40+
entity.Id = id
41+
}
42+
if name != "" {
43+
entity.Name = name
5144
}
5245

5346
projectsClient := minderv1.NewProjectsServiceClient(conn)
5447
_, err := projectsClient.CreateEntityReconciliationTask(ctx, &minderv1.CreateEntityReconciliationTaskRequest{
55-
Entity: &minderv1.EntityTypedId{
56-
Id: id,
57-
Type: minderv1.Entity_ENTITY_REPOSITORIES,
58-
},
48+
Entity: entity,
5949
Context: &minderv1.Context{
6050
Provider: &provider,
6151
Project: &project,

database/query/profile_status.sql

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -88,6 +88,7 @@ SELECT
8888
rt.guidance as rule_type_guidance,
8989
rt.display_name as rule_type_display_name,
9090
ere.entity_instance_id as entity_id,
91+
ei.name as entity_name,
9192
ei.project_id as project_id,
9293
rt.release_phase as rule_type_release_phase
9394
FROM latest_evaluation_statuses les
@@ -99,8 +100,9 @@ FROM latest_evaluation_statuses les
99100
INNER JOIN rule_type rt ON rt.id = ri.rule_type_id
100101
INNER JOIN entity_instances ei ON ei.id = ere.entity_instance_id
101102
INNER JOIN providers prov ON prov.id = ei.provider_id
102-
WHERE les.profile_id = $1 AND
103-
(ere.entity_instance_id = sqlc.narg(entity_id)::UUID OR sqlc.narg(entity_id)::UUID IS NULL)
103+
WHERE les.profile_id = $1
104+
AND (ere.entity_instance_id = sqlc.narg(entity_id)::UUID OR sqlc.narg(entity_id)::UUID IS NULL)
105+
AND (ei.name = sqlc.narg(entity_name) OR sqlc.narg(entity_name) IS NULL)
104106
AND (rt.name = sqlc.narg(rule_type_name) OR sqlc.narg(rule_type_name) IS NULL)
105107
AND (lower(ri.name) = lower(sqlc.narg(rule_name)) OR sqlc.narg(rule_name) IS NULL)
106108
;

docs/docs/ref/proto.mdx

Lines changed: 5 additions & 2 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

internal/controlplane/handlers_evalstatus.go

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -666,11 +666,10 @@ func (s *Server) buildRuleEvaluationStatusFromDBEvaluation(
666666
func buildEntityFromEvaluation(efp *entmodels.EntityWithProperties) *minderv1.EntityTypedId {
667667
ent := &minderv1.EntityTypedId{
668668
Type: efp.Entity.Type,
669+
Id: efp.Entity.ID.String(),
670+
Name: efp.Entity.Name,
669671
}
670672

671-
if ent.Type == minderv1.Entity_ENTITY_REPOSITORIES {
672-
ent.Id = efp.Entity.ID.String()
673-
}
674673
return ent
675674
}
676675

internal/controlplane/handlers_profile.go

Lines changed: 55 additions & 89 deletions
Original file line numberDiff line numberDiff line change
@@ -617,17 +617,6 @@ func (s *Server) GetProfileStatusById(
617617
}, nil
618618
}
619619

620-
func extractEntitySelector(entity *minderv1.EntityTypedId) *uuid.NullUUID {
621-
if entity == nil {
622-
return nil
623-
}
624-
var selector uuid.NullUUID
625-
if err := selector.Scan(entity.GetId()); err != nil {
626-
return nil
627-
}
628-
return &selector
629-
}
630-
631620
func (s *Server) processProfileStatusByName(
632621
ctx context.Context,
633622
profileName string,
@@ -638,21 +627,29 @@ func (s *Server) processProfileStatusByName(
638627
) (*minderv1.GetProfileStatusByNameResponse, error) {
639628
var ruleEvaluationStatuses []*minderv1.RuleEvaluationStatus
640629

641-
selector, ruleType, ruleName, err := extractFiltersFromNameRequest(req)
642-
if err != nil {
630+
// Telemetry logging
631+
entityCtx := engcontext.EntityFromContext(ctx)
632+
logger.BusinessRecord(ctx).Project = entityCtx.Project.ID
633+
logger.BusinessRecord(ctx).Profile = logger.Profile{Name: profileName, ID: profileID}
634+
635+
if err := validateEntityType(req.GetEntity()); err != nil {
643636
return nil, err
644637
}
638+
maybeEntityID, err := maybeNullUUID(req.GetEntity().GetId())
639+
if err != nil {
640+
return nil, util.UserVisibleError(codes.InvalidArgument, "Unable to parse entity id: %q", req.GetEntity().GetId())
641+
}
642+
maybeEntityName := maybeNullString(req.GetEntity().GetName())
643+
ruleType := maybeNullString(req.GetRuleType())
644+
ruleName := maybeNullString(req.GetRuleName())
645645

646-
if selector != nil || req.GetAll() {
647-
var entityID uuid.NullUUID
648-
if selector != nil {
649-
entityID = *selector
650-
}
646+
if req.GetAll() || maybeEntityID.Valid || maybeEntityName.Valid {
651647
dbRuleEvaluationStatuses, err := s.store.ListRuleEvaluationsByProfileId(ctx, db.ListRuleEvaluationsByProfileIdParams{
652648
ProfileID: profileID,
653-
EntityID: entityID,
654-
RuleTypeName: *ruleType,
655-
RuleName: *ruleName,
649+
EntityID: maybeEntityID,
650+
EntityName: maybeEntityName,
651+
RuleTypeName: ruleType,
652+
RuleName: ruleName,
656653
})
657654
if err != nil && !errors.Is(err, sql.ErrNoRows) {
658655
return nil, status.Errorf(codes.Unknown, "failed to list rule evaluation status: %s", err)
@@ -663,11 +660,6 @@ func (s *Server) processProfileStatusByName(
663660
)
664661
}
665662

666-
// Telemetry logging
667-
entityCtx := engcontext.EntityFromContext(ctx)
668-
logger.BusinessRecord(ctx).Project = entityCtx.Project.ID
669-
logger.BusinessRecord(ctx).Profile = logger.Profile{Name: profileName, ID: profileID}
670-
671663
return &minderv1.GetProfileStatusByNameResponse{
672664
ProfileStatus: &minderv1.ProfileStatus{
673665
ProfileId: profileID.String(),
@@ -689,22 +681,30 @@ func (s *Server) processProfileStatusById(
689681
) (*minderv1.GetProfileStatusByIdResponse, error) {
690682
var ruleEvaluationStatuses []*minderv1.RuleEvaluationStatus
691683

692-
selector, ruleType, ruleName, err := extractFiltersFromIdRequest(req)
693-
if err != nil {
684+
// Telemetry logging
685+
entityCtx := engcontext.EntityFromContext(ctx)
686+
logger.BusinessRecord(ctx).Project = entityCtx.Project.ID
687+
logger.BusinessRecord(ctx).Profile = logger.Profile{Name: profileName, ID: profileID}
688+
689+
// selector, ruleType, ruleName, err := extractFiltersFromIdRequest(req)
690+
if err := validateEntityType(req.GetEntity()); err != nil {
694691
return nil, err
695692
}
693+
maybeEntityID, err := maybeNullUUID(req.GetEntity().GetId())
694+
if err != nil {
695+
return nil, util.UserVisibleError(codes.InvalidArgument, "Unable to parse entity id: %q", req.GetEntity().GetId())
696+
}
697+
maybeEntityName := maybeNullString(req.GetEntity().GetName())
698+
ruleType := maybeNullString(req.GetRuleType())
699+
ruleName := maybeNullString(req.GetRuleName())
696700

697-
// Only fetch rule evaluations if selector is present or all is requested
698-
if selector != nil || req.GetAll() {
699-
var entityID uuid.NullUUID
700-
if selector != nil {
701-
entityID = *selector
702-
}
701+
if req.GetAll() || maybeEntityID.Valid || maybeEntityName.Valid {
703702
dbRuleEvaluationStatuses, err := s.store.ListRuleEvaluationsByProfileId(ctx, db.ListRuleEvaluationsByProfileIdParams{
704703
ProfileID: profileID,
705-
EntityID: entityID,
706-
RuleTypeName: *ruleType,
707-
RuleName: *ruleName,
704+
EntityID: maybeEntityID,
705+
EntityName: maybeEntityName,
706+
RuleTypeName: ruleType,
707+
RuleName: ruleName,
708708
})
709709
if err != nil && !errors.Is(err, sql.ErrNoRows) {
710710
return nil, status.Errorf(codes.Unknown, "failed to list rule evaluation status: %s", err)
@@ -715,11 +715,6 @@ func (s *Server) processProfileStatusById(
715715
)
716716
}
717717

718-
// Telemetry logging
719-
entityCtx := engcontext.EntityFromContext(ctx)
720-
logger.BusinessRecord(ctx).Project = entityCtx.Project.ID
721-
logger.BusinessRecord(ctx).Profile = logger.Profile{Name: profileName, ID: profileID}
722-
723718
return &minderv1.GetProfileStatusByIdResponse{
724719
ProfileStatus: &minderv1.ProfileStatus{
725720
ProfileId: profileID.String(),
@@ -731,61 +726,32 @@ func (s *Server) processProfileStatusById(
731726
}, nil
732727
}
733728

734-
func extractFiltersFromNameRequest(
735-
req *minderv1.GetProfileStatusByNameRequest) (
736-
*uuid.NullUUID, *sql.NullString, *sql.NullString, error) {
737-
if e := req.GetEntity(); e != nil {
729+
func validateEntityType(e *minderv1.EntityTypedId) error {
730+
if e != nil {
738731
if !e.GetType().IsValid() {
739-
return nil, nil, nil, util.UserVisibleError(codes.InvalidArgument,
732+
return util.UserVisibleError(codes.InvalidArgument,
740733
"invalid entity type %s, please use one of %s",
741734
e.GetType(), entities.KnownTypesCSV())
742735
}
743736
}
744-
745-
selector := extractEntitySelector(req.GetEntity())
746-
747-
ruleType := &sql.NullString{
748-
String: req.GetRuleType(),
749-
Valid: req.GetRuleType() != "",
750-
}
751-
if !ruleType.Valid {
752-
//nolint:staticcheck // ignore SA1019: Deprecated field supported for backward compatibility
753-
ruleType = &sql.NullString{
754-
String: req.GetRule(),
755-
Valid: req.GetRule() != "",
756-
}
757-
}
758-
759-
ruleName := &sql.NullString{
760-
String: req.GetRuleName(),
761-
Valid: req.GetRuleName() != "",
762-
}
763-
764-
return selector, ruleType, ruleName, nil
737+
return nil
765738
}
766739

767-
func extractFiltersFromIdRequest(
768-
req *minderv1.GetProfileStatusByIdRequest) (
769-
*uuid.NullUUID, *sql.NullString, *sql.NullString, error) {
770-
if e := req.GetEntity(); e != nil {
771-
if !e.GetType().IsValid() {
772-
return nil, nil, nil, util.UserVisibleError(codes.InvalidArgument,
773-
"invalid entity type %s, please use one of %s",
774-
e.GetType(), entities.KnownTypesCSV())
775-
}
776-
}
777-
778-
selector := extractEntitySelector(req.GetEntity())
779-
780-
ruleType := &sql.NullString{
781-
String: req.GetRuleType(),
782-
Valid: req.GetRuleType() != "",
740+
func maybeNullString(s string) sql.NullString {
741+
return sql.NullString{
742+
String: s,
743+
Valid: s != "",
783744
}
745+
}
784746

785-
ruleName := &sql.NullString{
786-
String: req.GetRuleName(),
787-
Valid: req.GetRuleName() != "",
747+
func maybeNullUUID(s string) (uuid.NullUUID, error) {
748+
var id uuid.UUID
749+
var err error
750+
if s != "" {
751+
id, err = uuid.Parse(s)
788752
}
789-
790-
return selector, ruleType, ruleName, nil
753+
return uuid.NullUUID{
754+
UUID: id,
755+
Valid: s != "",
756+
}, err
791757
}

internal/controlplane/handlers_profile_test.go

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1200,6 +1200,8 @@ func TestGetProfileStatusByName(t *testing.T) {
12001200
require.Equal(t, dbProfile.ID.String(), resp.ProfileStatus.ProfileId, "Profile ID should match")
12011201
require.Equal(t, expectedProfileName, resp.ProfileStatus.ProfileName, "Profile name should match")
12021202
})
1203+
1204+
// TODO: add test case for requesting evaluation details
12031205
}
12041206

12051207
func TestGetProfileStatusById(t *testing.T) {
@@ -1255,6 +1257,8 @@ func TestGetProfileStatusById(t *testing.T) {
12551257
require.Equal(t, dbProfile.ID.String(), resp.ProfileStatus.ProfileId, "Profile ID should match")
12561258
require.Equal(t, expectedProfileName, resp.ProfileStatus.ProfileName, "Profile name should match")
12571259
})
1260+
1261+
// TODO: add test case for requesting evaluation details
12581262
}
12591263

12601264
type deleteProfileTestCase struct {

0 commit comments

Comments
 (0)