Skip to content

Commit

Permalink
commands: add consistency flags
Browse files Browse the repository at this point in the history
  • Loading branch information
jzelinskie committed Jan 13, 2023
1 parent caf48fe commit 83ea942
Show file tree
Hide file tree
Showing 3 changed files with 85 additions and 41 deletions.
96 changes: 77 additions & 19 deletions internal/commands/permission.go
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ import (
"github.com/jzelinskie/stringz"
"github.com/rs/zerolog/log"
"github.com/spf13/cobra"
"github.com/spf13/pflag"
"google.golang.org/grpc"
"google.golang.org/grpc/metadata"
"google.golang.org/protobuf/encoding/protojson"
Expand All @@ -24,34 +25,81 @@ import (
"github.com/authzed/zed/internal/printers"
)

var ErrMultipleConsistencies = errors.New("provided multiple consistency flags")

func registerConsistencyFlags(flags *pflag.FlagSet) {
flags.String("consistency-at-exactly", "", "evaluate at the provided snapshot")
flags.String("consistency-at-least", "", "evaluate at least as consistent as the provided zedtoken")
flags.Bool("consistency-min-latency", false, "evaluate at the fastest snapshot")
flags.Bool("consistency-full", false, "evaluate at the most recent snapshot")
}

func consistencyFromCmd(cmd *cobra.Command) (c *v1.Consistency, err error) {
if cobrautil.MustGetBool(cmd, "consistency-full") {
c = &v1.Consistency{Requirement: &v1.Consistency_FullyConsistent{FullyConsistent: true}}
}
if atLeast := cobrautil.MustGetStringExpanded(cmd, "consistency-at-least"); atLeast != "" {
if c != nil {
return nil, ErrMultipleConsistencies
}
c = &v1.Consistency{Requirement: &v1.Consistency_AtLeastAsFresh{AtLeastAsFresh: &v1.ZedToken{Token: atLeast}}}
}

// Deprecated (hidden) flag.
if revision := cobrautil.MustGetStringExpanded(cmd, "revision"); revision != "" {
if c != nil {
return nil, ErrMultipleConsistencies
}
c = &v1.Consistency{Requirement: &v1.Consistency_AtLeastAsFresh{AtLeastAsFresh: &v1.ZedToken{Token: revision}}}
}

if exact := cobrautil.MustGetStringExpanded(cmd, "consistency-at-exactly"); exact != "" {
if c != nil {
return nil, ErrMultipleConsistencies
}
c = &v1.Consistency{Requirement: &v1.Consistency_AtExactSnapshot{AtExactSnapshot: &v1.ZedToken{Token: exact}}}
}

if c == nil {
c = &v1.Consistency{Requirement: &v1.Consistency_MinimizeLatency{MinimizeLatency: true}}
}
return
}

func RegisterPermissionCmd(rootCmd *cobra.Command) *cobra.Command {
rootCmd.AddCommand(permissionCmd)

permissionCmd.AddCommand(checkCmd)
checkCmd.Flags().Bool("json", false, "output as JSON")
checkCmd.Flags().String("revision", "", "optional revision at which to check")
_ = checkCmd.Flags().MarkHidden("revision")
checkCmd.Flags().Bool("explain", false, "requests debug information from SpiceDB and prints out a trace of the requests")
checkCmd.Flags().Bool("schema", false, "requests debug information from SpiceDB and prints out the schema used")
checkCmd.Flags().String("caveat-context", "", "the caveat context to send along with the check, in JSON form")
registerConsistencyFlags(checkCmd.Flags())

permissionCmd.AddCommand(expandCmd)
expandCmd.Flags().Bool("json", false, "output as JSON")
expandCmd.Flags().String("revision", "", "optional revision at which to check")
registerConsistencyFlags(expandCmd.Flags())

permissionCmd.AddCommand(lookupCmd)
lookupCmd.Flags().Bool("json", false, "output as JSON")
lookupCmd.Flags().String("revision", "", "optional revision at which to check")
lookupCmd.Flags().String("caveat-context", "", "the caveat context to send along with the lookup, in JSON form")
registerConsistencyFlags(lookupCmd.Flags())

permissionCmd.AddCommand(lookupResourcesCmd)
lookupResourcesCmd.Flags().Bool("json", false, "output as JSON")
lookupResourcesCmd.Flags().String("revision", "", "optional revision at which to check")
lookupResourcesCmd.Flags().String("caveat-context", "", "the caveat context to send along with the lookup, in JSON form")
registerConsistencyFlags(lookupResourcesCmd.Flags())

permissionCmd.AddCommand(lookupSubjectsCmd)
lookupSubjectsCmd.Flags().Bool("json", false, "output as JSON")
lookupSubjectsCmd.Flags().String("revision", "", "optional revision at which to check")
lookupSubjectsCmd.Flags().String("caveat-context", "", "the caveat context to send along with the lookup, in JSON form")
registerConsistencyFlags(lookupSubjectsCmd.Flags())

return permissionCmd
}
Expand Down Expand Up @@ -116,10 +164,16 @@ func checkCmdFunc(cmd *cobra.Command, args []string) error {
return err
}

consistency, err := consistencyFromCmd(cmd)
if err != nil {
return err
}

client, err := client.NewClient(cmd)
if err != nil {
return err
}

request := &v1.CheckPermissionRequest{
Resource: &v1.ObjectReference{
ObjectType: objectNS,
Expand All @@ -133,11 +187,8 @@ func checkCmdFunc(cmd *cobra.Command, args []string) error {
},
OptionalRelation: subjectRel,
},
Context: caveatContext,
}

if zedtoken := cobrautil.MustGetString(cmd, "revision"); zedtoken != "" {
request.Consistency = AtLeastAsFresh(zedtoken)
Context: caveatContext,
Consistency: consistency,
}
log.Trace().Interface("request", request).Send()

Expand Down Expand Up @@ -195,20 +246,23 @@ func expandCmdFunc(cmd *cobra.Command, args []string) error {
return err
}

consistency, err := consistencyFromCmd(cmd)
if err != nil {
return err
}

client, err := client.NewClient(cmd)
if err != nil {
return err
}

request := &v1.ExpandPermissionTreeRequest{
Resource: &v1.ObjectReference{
ObjectType: objectNS,
ObjectId: objectID,
},
Permission: relation,
}

if zedtoken := cobrautil.MustGetString(cmd, "revision"); zedtoken != "" {
request.Consistency = AtLeastAsFresh(zedtoken)
Permission: relation,
Consistency: consistency,
}
log.Trace().Interface("request", request).Send()

Expand Down Expand Up @@ -247,6 +301,11 @@ func lookupResourcesCmdFunc(cmd *cobra.Command, args []string) error {
return err
}

consistency, err := consistencyFromCmd(cmd)
if err != nil {
return err
}

client, err := client.NewClient(cmd)
if err != nil {
return err
Expand All @@ -261,11 +320,8 @@ func lookupResourcesCmdFunc(cmd *cobra.Command, args []string) error {
},
OptionalRelation: subjectRel,
},
Context: caveatContext,
}

if zedtoken := cobrautil.MustGetString(cmd, "revision"); zedtoken != "" {
request.Consistency = AtLeastAsFresh(zedtoken)
Context: caveatContext,
Consistency: consistency,
}
log.Trace().Interface("request", request).Send()

Expand Down Expand Up @@ -312,6 +368,11 @@ func lookupSubjectsCmdFunc(cmd *cobra.Command, args []string) error {
return err
}

consistency, err := consistencyFromCmd(cmd)
if err != nil {
return err
}

client, err := client.NewClient(cmd)
if err != nil {
return err
Expand All @@ -325,10 +386,7 @@ func lookupSubjectsCmdFunc(cmd *cobra.Command, args []string) error {
SubjectObjectType: subjectType,
OptionalSubjectRelation: subjectRelation,
Context: caveatContext,
}

if zedtoken := cobrautil.MustGetString(cmd, "revision"); zedtoken != "" {
request.Consistency = AtLeastAsFresh(zedtoken)
Consistency: consistency,
}
log.Trace().Interface("request", request).Send()

Expand Down
19 changes: 8 additions & 11 deletions internal/commands/relationship.go
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,9 @@ func RegisterRelationshipCmd(rootCmd *cobra.Command) *cobra.Command {
relationshipCmd.AddCommand(readCmd)
readCmd.Flags().Bool("json", false, "output as JSON")
readCmd.Flags().String("revision", "", "optional revision at which to check")
_ = readCmd.Flags().MarkHidden("revision")
readCmd.Flags().String("subject-filter", "", "optional subject filter")
registerConsistencyFlags(readCmd.Flags())

relationshipCmd.AddCommand(bulkDeleteCmd)
bulkDeleteCmd.Flags().Bool("force", false, "force deletion immediately without confirmation")
Expand Down Expand Up @@ -84,10 +86,6 @@ var bulkDeleteCmd = &cobra.Command{
RunE: bulkDeleteRelationships,
}

var fullyConsistent = &v1.Consistency{
Requirement: &v1.Consistency_FullyConsistent{FullyConsistent: true},
}

func bulkDeleteRelationships(cmd *cobra.Command, args []string) error {
client, err := client.NewClient(cmd)
if err != nil {
Expand All @@ -101,13 +99,12 @@ func bulkDeleteRelationships(cmd *cobra.Command, args []string) error {

counter := -1
if cobrautil.MustGetBool(cmd, "estimate-count") {
request.Consistency = fullyConsistent

log.Trace().Interface("request", request).Send()
request.Consistency = &v1.Consistency{Requirement: &v1.Consistency_FullyConsistent{FullyConsistent: true}}

ctx, cancel := context.WithCancel(context.Background())
defer cancel()

log.Trace().Interface("request", request).Send()
resp, err := client.ReadRelationships(ctx, request)
if err != nil {
return err
Expand Down Expand Up @@ -205,16 +202,16 @@ func readRelationships(cmd *cobra.Command, args []string) error {
return err
}

if zedtoken := cobrautil.MustGetString(cmd, "revision"); zedtoken != "" {
request.Consistency = AtLeastAsFresh(zedtoken)
} else {
request.Consistency = fullyConsistent
request.Consistency, err = consistencyFromCmd(cmd)
if err != nil {
return err
}

client, err := client.NewClient(cmd)
if err != nil {
return err
}

log.Trace().Interface("request", request).Msg("reading relationships")
resp, err := client.ReadRelationships(context.Background(), request)
if err != nil {
Expand Down
11 changes: 0 additions & 11 deletions internal/commands/util.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,6 @@ import (
"strings"

"github.com/TylerBrock/colorjson"
v1 "github.com/authzed/authzed-go/proto/authzed/api/v1"
"github.com/jzelinskie/cobrautil/v2"
"github.com/jzelinskie/stringz"
"github.com/spf13/cobra"
Expand Down Expand Up @@ -46,16 +45,6 @@ func GetCaveatContext(cmd *cobra.Command) (*structpb.Struct, error) {
return ParseCaveatContext(contextString)
}

// AtLeastAsFresh returns a consistency block set to AtLeastAsFresh as the
// specified zedtoken.
func AtLeastAsFresh(zedtoken string) *v1.Consistency {
return &v1.Consistency{
Requirement: &v1.Consistency_AtLeastAsFresh{
AtLeastAsFresh: &v1.ZedToken{Token: zedtoken},
},
}
}

// ParseCaveatContext parses the given context JSON string into caveat context,
// if valid.
func ParseCaveatContext(contextString string) (*structpb.Struct, error) {
Expand Down

0 comments on commit 83ea942

Please sign in to comment.