Skip to content

Commit

Permalink
WIP
Browse files Browse the repository at this point in the history
  • Loading branch information
orpheuslummis committed Mar 30, 2023
1 parent ef8ffed commit 73dbdbf
Show file tree
Hide file tree
Showing 17 changed files with 436 additions and 172 deletions.
7 changes: 7 additions & 0 deletions cli/cli.go
Original file line number Diff line number Diff line change
Expand Up @@ -75,6 +75,7 @@ func NewDefraCommand(cfg *config.Config) DefraCommand {
)
schemaCmd.AddCommand(
MakeSchemaAddCommand(cfg),
MakeSchemaPatchCommand(cfg),
)
clientCmd.AddCommand(
MakeDumpCommand(cfg),
Expand Down Expand Up @@ -103,6 +104,11 @@ func (defraCmd *DefraCommand) Execute(ctx context.Context) error {
defraCmd.RootCmd.SetOut(os.Stdout)
err := defraCmd.RootCmd.ExecuteContext(ctx)
if err != nil {
// Intentional cancellation.
if errors.Is(err, context.Canceled) || errors.Is(err, context.DeadlineExceeded) {
return nil
}
// User error.
for _, cobraError := range usageErrors {
if strings.HasPrefix(err.Error(), cobraError) {
log.FeedbackErrorE(ctx, "Usage error", err)
Expand All @@ -112,6 +118,7 @@ func (defraCmd *DefraCommand) Execute(ctx context.Context) error {
return err
}
}
// Internal error.
log.FeedbackErrorE(ctx, "Execution error", err)
return err
}
Expand Down
196 changes: 98 additions & 98 deletions cli/schema_patch.go
Original file line number Diff line number Diff line change
Expand Up @@ -20,14 +20,16 @@ import (
"github.com/spf13/cobra"

httpapi "github.com/sourcenetwork/defradb/api/http"
"github.com/sourcenetwork/defradb/config"
)

var patchFile string
func MakeSchemaPatchCommand(cfg *config.Config) *cobra.Command {
var patchFile string

var patchCmd = &cobra.Command{
Use: "patch [schema]",
Short: "Patch an existing schema type",
Long: `Patch an existing schema.
var cmd = &cobra.Command{
Use: "patch [schema]",
Short: "Patch an existing schema type",
Long: `Patch an existing schema.
Uses JSON PATCH formatting as a DDL.
Expand All @@ -41,111 +43,109 @@ Example: patch from stdin:
cat patch.json | defradb client schema patch -
To learn more about the DefraDB GraphQL Schema Language, refer to https://docs.source.network.`,
RunE: func(cmd *cobra.Command, args []string) (err error) {
var patch string
fi, err := os.Stdin.Stat()
if err != nil {
return err
}

if len(args) > 1 {
if err = cmd.Usage(); err != nil {
RunE: func(cmd *cobra.Command, args []string) (err error) {
var patch string
fi, err := os.Stdin.Stat()
if err != nil {
return err
}
return ErrTooManyArgs
}

if patchFile != "" {
buf, err := os.ReadFile(patchFile)
if len(args) > 1 {
if err = cmd.Usage(); err != nil {
return err
}
return ErrTooManyArgs
}

if patchFile != "" {
buf, err := os.ReadFile(patchFile)
if err != nil {
return NewFailedToReadFile(err)
}
patch = string(buf)
} else if isFileInfoPipe(fi) && (len(args) == 0 || args[0] != "-") {
log.FeedbackInfo(
cmd.Context(),
"Run 'defradb client schema patch -' to read from stdin."+
" Example: 'cat patch.json | defradb client schema patch -').",
)
return nil
} else if len(args) == 0 {
// ignore error, nothing we can do about it
// as printing an error about failing to print help
// is useless
//nolint:errcheck
cmd.Help()
return nil
} else if args[0] == "-" {
stdin, err := readStdin()
if err != nil {
return NewFailedToReadStdin(err)
}
if len(stdin) == 0 {
return ErrEmptyStdin
} else {
patch = stdin
}
} else {
patch = args[0]
}

if patch == "" {
return ErrEmptyFile
}

endpoint, err := httpapi.JoinPaths(cfg.API.AddressToURL(), httpapi.SchemaPatchPath)
if err != nil {
return NewFailedToReadFile(err)
return err
}
patch = string(buf)
} else if isFileInfoPipe(fi) && (len(args) == 0 || args[0] != "-") {
log.FeedbackInfo(
cmd.Context(),
"Run 'defradb client schema patch -' to read from stdin."+
" Example: 'cat patch.json | defradb client schema patch -').",
)
return nil
} else if len(args) == 0 {
// ignore error, nothing we can do about it
// as printing an error about failing to print help
// is useless
//nolint:errcheck
cmd.Help()
return nil
} else if args[0] == "-" {
stdin, err := readStdin()

res, err := http.Post(endpoint.String(), "text", strings.NewReader(patch))
if err != nil {
return NewFailedToReadStdin(err)
return NewErrFailedToSendRequest(err)
}
if len(stdin) == 0 {
return ErrEmptyStdin
} else {
patch = stdin

//nolint:errcheck
defer res.Body.Close()
response, err := io.ReadAll(res.Body)
if err != nil {
return NewErrFailedToReadResponseBody(err)
}
} else {
patch = args[0]
}

if patch == "" {
return ErrEmptyFile
}

endpoint, err := httpapi.JoinPaths(cfg.API.AddressToURL(), httpapi.SchemaPatchPath)
if err != nil {
return err
}

res, err := http.Post(endpoint.String(), "text", strings.NewReader(patch))
if err != nil {
return NewErrFailedToSendRequest(err)
}

//nolint:errcheck
defer res.Body.Close()
response, err := io.ReadAll(res.Body)
if err != nil {
return NewErrFailedToReadResponseBody(err)
}

stdout, err := os.Stdout.Stat()
if err != nil {
return NewErrFailedToStatStdOut(err)
}
if isFileInfoPipe(stdout) {
cmd.Println(string(response))
} else {
graphlErr, err := hasGraphQLErrors(response)

stdout, err := os.Stdout.Stat()
if err != nil {
return NewErrFailedToHandleGQLErrors(err)
return NewErrFailedToStatStdOut(err)
}
if graphlErr {
indentedResult, err := indentJSON(response)
if err != nil {
return NewErrFailedToPrettyPrintResponse(err)
}
log.FeedbackError(cmd.Context(), indentedResult)
if isFileInfoPipe(stdout) {
cmd.Println(string(response))
} else {
type schemaResponse struct {
Data struct {
Result string `json:"result"`
} `json:"data"`
}
r := schemaResponse{}
err = json.Unmarshal(response, &r)
graphlErr, err := hasGraphQLErrors(response)
if err != nil {
return NewErrFailedToUnmarshalResponse(err)
return NewErrFailedToHandleGQLErrors(err)
}
if graphlErr {
indentedResult, err := indentJSON(response)
if err != nil {
return NewErrFailedToPrettyPrintResponse(err)
}
log.FeedbackError(cmd.Context(), indentedResult)
} else {
type schemaResponse struct {
Data struct {
Result string `json:"result"`
} `json:"data"`
}
r := schemaResponse{}
err = json.Unmarshal(response, &r)
if err != nil {
return NewErrFailedToUnmarshalResponse(err)
}
log.FeedbackInfo(cmd.Context(), r.Data.Result)
}
log.FeedbackInfo(cmd.Context(), r.Data.Result)
}
}
return nil
},
}

func init() {
schemaCmd.AddCommand(patchCmd)
patchCmd.Flags().StringVarP(&patchFile, "file", "f", "", "File to load a patch from")
return nil
},
}
cmd.Flags().StringVarP(&patchFile, "file", "f", "", "File to load a patch from")
return cmd
}
11 changes: 5 additions & 6 deletions cli/start.go
Original file line number Diff line number Diff line change
Expand Up @@ -76,9 +76,7 @@ func MakeStartCommand(cfg *config.Config) *cobra.Command {
return err
}

wait(cmd.Context(), di)

return nil
return wait(cmd.Context(), di)
},
}

Expand Down Expand Up @@ -366,18 +364,19 @@ func start(ctx context.Context, cfg *config.Config) (*defraInstance, error) {
}

// wait waits for an interrupt signal to close the program.
func wait(ctx context.Context, di *defraInstance) {
func wait(ctx context.Context, di *defraInstance) error {
// setup signal handlers
signalCh := make(chan os.Signal, 1)
signal.Notify(signalCh, os.Interrupt)

select {
case <-ctx.Done():
log.FeedbackInfo(ctx, "Received context cancellation; closing database...")
di.close(ctx)
return ctx.Err()
case <-signalCh:
log.FeedbackInfo(ctx, "Received interrupt; closing database...")
di.close(ctx)
os.Exit(0)
return
return ctx.Err()
}
}
30 changes: 29 additions & 1 deletion tests/integration/cli/client_blocks_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,4 +10,32 @@

package clitest

// create a new block
import "testing"

func TestClientBlocksEmpty(t *testing.T) {
conf := NewDefraNodeDefaultConfig(t)
stdout, _ := runDefraCommand(t, conf, []string{"client", "blocks"})
assertContainsSubstring(t, stdout, "Usage:")
}

func TestClientBlocksGetEmpty(t *testing.T) {
conf := NewDefraNodeDefaultConfig(t)
stdout, _ := runDefraCommand(t, conf, []string{"client", "blocks", "get"})
assertContainsSubstring(t, stdout, "Usage:")
}

func TestClientBlocksGetInvalidCID(t *testing.T) {
conf := NewDefraNodeDefaultConfig(t)
stopDefra := runDefraNode(t, conf)
stdout, _ := runDefraCommand(t, conf, []string{"client", "blocks", "get", "invalid-cid"})
_ = stopDefra()
assertContainsSubstring(t, stdout, "\"errors\"")
}

func TestClientBlocksGetNonExistentCID(t *testing.T) {
conf := NewDefraNodeDefaultConfig(t)
stopDefra := runDefraNode(t, conf)
stdout, _ := runDefraCommand(t, conf, []string{"client", "blocks", "get", "bafybeieelb43ol5e5jiick2p7k4p577ph72ecwcuowlhbops4hpz24zhz4"})
_ = stopDefra()
assertContainsSubstring(t, stdout, "could not find")
}
14 changes: 14 additions & 0 deletions tests/integration/cli/client_dump_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,3 +9,17 @@
// licenses/APL.txt.

package clitest

import "testing"

func TestClientDumpSimple(t *testing.T) {
conf := NewDefraNodeDefaultConfig(t)
stopDefra := runDefraNode(t, conf)

stdout, _ := runDefraCommand(t, conf, []string{"client", "dump"})

nodeLog := stopDefra()

assertContainsSubstring(t, stdout, `{"data":{"response":"ok"}}`)
assertContainsSubstring(t, nodeLog, "/db/system/seq/collection/names")
}
6 changes: 1 addition & 5 deletions tests/integration/cli/client_peerid_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -12,8 +12,6 @@ package clitest

import (
"testing"

"github.com/stretchr/testify/assert"
)

func TestPeerID(t *testing.T) {
Expand All @@ -24,9 +22,7 @@ func TestPeerID(t *testing.T) {

defraLogLines := stopDefra()

for _, line := range defraLogLines {
assert.NotContains(t, line, "ERROR")
}
assertNotContainsSubstring(t, defraLogLines, "ERROR")

assertContainsSubstring(t, stdout, "peerID")
}
Expand Down
Loading

0 comments on commit 73dbdbf

Please sign in to comment.