Skip to content

Commit

Permalink
Add bulk-delete command for relationships in zed
Browse files Browse the repository at this point in the history
  • Loading branch information
josephschorr committed Nov 9, 2021
1 parent c5949fe commit 221a4d5
Showing 1 changed file with 122 additions and 17 deletions.
139 changes: 122 additions & 17 deletions cmd/zed/relationship.go
Original file line number Diff line number Diff line change
@@ -1,9 +1,11 @@
package main

import (
"bufio"
"context"
"fmt"
"io"
"os"
"strings"

v1 "github.com/authzed/authzed-go/proto/authzed/api/v1"
Expand Down Expand Up @@ -31,6 +33,9 @@ func registerRelationshipCmd(rootCmd *cobra.Command) {
relationshipCmd.AddCommand(readCmd)
readCmd.Flags().Bool("json", false, "output as JSON")
readCmd.Flags().String("revision", "", "optional revision at which to check")

relationshipCmd.AddCommand(bulkDeleteCmd)
bulkDeleteCmd.Flags().Bool("force", false, "force deletion immediately without confirmation")
}

var relationshipCmd = &cobra.Command{
Expand Down Expand Up @@ -71,13 +76,104 @@ var readCmd = &cobra.Command{
RunE: readRelationships,
}

func readRelationships(cmd *cobra.Command, args []string) error {
var bulkDeleteCmd = &cobra.Command{
Use: "bulk-delete <resource_type:optional_resource_id> <optional_relation> <optional_subject_type:optional_subject_id#optional_subject_relation>",
Short: "bulk delete Relationships",
Args: cobra.RangeArgs(1, 3),
PersistentPreRunE: persistentPreRunE,
RunE: bulkDeleteRelationships,
}

func bulkDeleteRelationships(cmd *cobra.Command, args []string) error {
configStore, secretStore := defaultStorage()
token, err := storage.DefaultToken(
cobrautil.MustGetString(cmd, "endpoint"),
cobrautil.MustGetString(cmd, "token"),
configStore,
secretStore,
)
if err != nil {
return err
}
log.Trace().Interface("token", token).Send()

client, err := authzed.NewClient(token.Endpoint, dialOptsFromFlags(cmd, token.ApiToken)...)
if err != nil {
return err
}

request, err := buildReadRequest(cmd, args)
if err != nil {
return err
}

if !cobrautil.MustGetBool(cmd, "force") {
request.Consistency = &v1.Consistency{
Requirement: &v1.Consistency_FullyConsistent{FullyConsistent: true},
}

log.Trace().Interface("request", request).Send()

resp, err := client.ReadRelationships(context.Background(), request)
if err != nil {
return err
}

counter := 0
for {
_, err := resp.Recv()
if err == io.EOF {
break
}

if err != nil {
return err
}

counter++
if counter > 1000 {
break
}
}

if counter == 0 {
fmt.Println("No matching relationships found")
return nil
} else if counter > 1000 {
fmt.Print("Will delete 1000+ relationships. Continue? [y/N]: ")
} else {
fmt.Printf("Will delete %d relationships. Continue? [y/N]: ", counter)
}

reader := bufio.NewReader(os.Stdin)
response, err := reader.ReadString('\n')
if err != nil {
return err
}

if strings.ToLower(strings.TrimSpace(response)) != "y" {
return nil
}
}

resp, err := client.DeleteRelationships(context.Background(), &v1.DeleteRelationshipsRequest{
RelationshipFilter: request.RelationshipFilter,
})
if err != nil {
return err
}

fmt.Println(resp.DeletedAt.GetToken())
return nil
}

func buildReadRequest(cmd *cobra.Command, args []string) (*v1.ReadRelationshipsRequest, error) {
readFilter := &v1.RelationshipFilter{ResourceType: args[0]}

if strings.Contains(args[0], ":") {
err := stringz.SplitExact(args[0], ":", &readFilter.ResourceType, &readFilter.OptionalResourceId)
if err != nil {
return err
return nil, err
}
}

Expand All @@ -89,7 +185,7 @@ func readRelationships(cmd *cobra.Command, args []string) error {
if strings.Contains(args[2], ":") {
subjectNS, subjectID, subjectRel, err := parseSubject(args[2])
if err != nil {
return err
return nil, err
}

readFilter.OptionalSubjectFilter = &v1.SubjectFilter{
Expand All @@ -106,26 +202,18 @@ func readRelationships(cmd *cobra.Command, args []string) error {
}
}

configStore, secretStore := defaultStorage()
token, err := storage.DefaultToken(
cobrautil.MustGetString(cmd, "endpoint"),
cobrautil.MustGetString(cmd, "token"),
configStore,
secretStore,
)
if err != nil {
return err
request := &v1.ReadRelationshipsRequest{
RelationshipFilter: readFilter,
}
log.Trace().Interface("token", token).Send()
return request, nil
}

client, err := authzed.NewClient(token.Endpoint, dialOptsFromFlags(cmd, token.ApiToken)...)
func readRelationships(cmd *cobra.Command, args []string) error {
request, err := buildReadRequest(cmd, args)
if err != nil {
return err
}

request := &v1.ReadRelationshipsRequest{
RelationshipFilter: readFilter,
}
if zedtoken := cobrautil.MustGetString(cmd, "revision"); zedtoken != "" {
request.Consistency = &v1.Consistency{
Requirement: &v1.Consistency_AtLeastAsFresh{&v1.ZedToken{Token: zedtoken}},
Expand All @@ -138,6 +226,23 @@ func readRelationships(cmd *cobra.Command, args []string) error {

log.Trace().Interface("request", request).Send()

configStore, secretStore := defaultStorage()
token, err := storage.DefaultToken(
cobrautil.MustGetString(cmd, "endpoint"),
cobrautil.MustGetString(cmd, "token"),
configStore,
secretStore,
)
if err != nil {
return err
}
log.Trace().Interface("token", token).Send()

client, err := authzed.NewClient(token.Endpoint, dialOptsFromFlags(cmd, token.ApiToken)...)
if err != nil {
return err
}

resp, err := client.ReadRelationships(context.Background(), request)
if err != nil {
return err
Expand Down

0 comments on commit 221a4d5

Please sign in to comment.