Skip to content

Commit b8eb951

Browse files
authored
feat: improve schema command ux (#150)
* feat: improve schema command * refactor: cleanup schema commands * refactor: cleanup schema commands * feat: prompt in schema create * refactor: cleanup schema commands * fix: fix typods * fix: fix space * chore: remove promots from schema
1 parent 61c4d82 commit b8eb951

File tree

18 files changed

+946
-793
lines changed

18 files changed

+946
-793
lines changed

README.md

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -14,8 +14,8 @@ Stencil is a schema registry that provides schema mangement and validation to en
1414
Discover why users choose Stencil as their main schema registry
1515

1616
- **Version history** Stencil stores versioned history of proto descriptor file on specified namespace and name
17-
- **Backward compatibility** enforce backward compatability check on upload by default
18-
- **Flexbility** ability to skip some of the backward compatability checks while upload
17+
- **Backward compatibility** enforce backward compatibility check on upload by default
18+
- **Flexbility** ability to skip some of the backward compatibility checks while upload
1919
- **Descriptor fetch** ability to download proto descriptor files
2020
- **Metadata** provides metadata API to retrieve latest version number given a name and namespace
2121
- **Clients in multiple languages** Stencil provides clients in GO, Java, JS languages to interact with Stencil server and deserialize messages using dynamic schema
@@ -90,7 +90,7 @@ Stencil has three major components. Server, CLI and clients. Stencil server and
9090

9191
**Server**
9292

93-
Stencil server provides a way to store and fetch schemas and enforce compatability rules. Run `stencil server --help` to see instructions to manage Stencil server.
93+
Stencil server provides a way to store and fetch schemas and enforce compatibility rules. Run `stencil server --help` to see instructions to manage Stencil server.
9494

9595
Stencil server also provides a fully-featured GRPC and HTTP API to interact with Stencil server. Both APIs adheres to a set of standards that are rigidly followed. Please refer to [proton](https://github.com/odpf/proton/tree/main/odpf/stencil/v1beta1) for GRPC API definitions.
9696

cmd/cdk.go

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
package cmd
2+
3+
var dict = map[string]string{
4+
"COMPATIBILITY_BACKWARD": "backward",
5+
"COMPATIBILITY_FORWARD": "forward",
6+
"COMPATIBILITY_FULL": "full",
7+
"FORMAT_PROTOBUF": "protobuf",
8+
"FORMAT_JSON": "json",
9+
"FORMAT_AVRO": "avro",
10+
}
11+
12+
var (
13+
formats = []string{
14+
"FORMAT_JSON",
15+
"FORMAT_PROTOBUF",
16+
"FORMAT_AVRO",
17+
}
18+
19+
comps = []string{
20+
"COMPATIBILITY_BACKWARD",
21+
"COMPATIBILITY_FORWARD",
22+
"COMPATIBILITY_FULL",
23+
}
24+
)

cmd/check.go

Lines changed: 78 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,78 @@
1+
package cmd
2+
3+
import (
4+
"context"
5+
"errors"
6+
"fmt"
7+
"os"
8+
9+
"github.com/MakeNowJust/heredoc"
10+
"github.com/odpf/salt/printer"
11+
"github.com/odpf/salt/term"
12+
stencilv1beta1 "github.com/odpf/stencil/proto/odpf/stencil/v1beta1"
13+
"github.com/spf13/cobra"
14+
"google.golang.org/grpc/status"
15+
)
16+
17+
func checkSchemaCmd() *cobra.Command {
18+
var host, comp, file, namespaceID string
19+
var req stencilv1beta1.CheckCompatibilityRequest
20+
21+
cmd := &cobra.Command{
22+
Use: "check <id>",
23+
Args: cobra.ExactArgs(1),
24+
Short: "Check schema compatibility",
25+
Long: heredoc.Doc(`
26+
Check schema compatibility of a local schema
27+
against a remote schema(against) on stencil server.`),
28+
Example: heredoc.Doc(`
29+
$ stencil schema check <id> -n odpf -c COMPATIBILITY_BACKWARD -F ./booking.desc
30+
`),
31+
RunE: func(cmd *cobra.Command, args []string) error {
32+
spinner := printer.Spin("")
33+
defer spinner.Stop()
34+
35+
fileData, err := os.ReadFile(file)
36+
if err != nil {
37+
return err
38+
}
39+
40+
client, cancel, err := createClient(cmd)
41+
if err != nil {
42+
return err
43+
}
44+
defer cancel()
45+
46+
schemaID := args[0]
47+
48+
req.Data = fileData
49+
req.NamespaceId = namespaceID
50+
req.SchemaId = schemaID
51+
req.Compatibility = stencilv1beta1.Schema_Compatibility(stencilv1beta1.Schema_Compatibility_value[comp])
52+
53+
_, err = client.CheckCompatibility(context.Background(), &req)
54+
if err != nil {
55+
errStatus := status.Convert(err)
56+
return errors.New(errStatus.Message())
57+
}
58+
59+
spinner.Stop()
60+
fmt.Printf("\n%s Schema is compatible.\n", term.Green(term.SuccessIcon()))
61+
return nil
62+
},
63+
}
64+
65+
cmd.Flags().StringVar(&host, "host", "", "Server host address eg: localhost:8000")
66+
cmd.MarkFlagRequired("host")
67+
68+
cmd.Flags().StringVarP(&namespaceID, "namespace", "n", "", "Parent namespace ID")
69+
cmd.MarkFlagRequired("namespace")
70+
71+
cmd.Flags().StringVarP(&comp, "comp", "c", "", "Schema compatibility")
72+
cmd.MarkFlagRequired("comp")
73+
74+
cmd.Flags().StringVarP(&file, "file", "F", "", "Path to the schema file")
75+
cmd.MarkFlagRequired("file")
76+
77+
return cmd
78+
}

cmd/create.go

Lines changed: 83 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,83 @@
1+
package cmd
2+
3+
import (
4+
"context"
5+
"errors"
6+
"fmt"
7+
"os"
8+
9+
"github.com/MakeNowJust/heredoc"
10+
"github.com/odpf/salt/printer"
11+
"github.com/odpf/salt/term"
12+
stencilv1beta1 "github.com/odpf/stencil/proto/odpf/stencil/v1beta1"
13+
"github.com/spf13/cobra"
14+
"google.golang.org/grpc/codes"
15+
"google.golang.org/grpc/status"
16+
)
17+
18+
func createSchemaCmd() *cobra.Command {
19+
var host, format, comp, file, namespaceID string
20+
var req stencilv1beta1.CreateSchemaRequest
21+
22+
cmd := &cobra.Command{
23+
Use: "create",
24+
Short: "Create a schema",
25+
Args: cobra.ExactArgs(1),
26+
Example: heredoc.Doc(`
27+
$ stencil schema create booking -n odpf –F booking.json
28+
$ stencil schema create booking -n odpf -f FORMAT_JSON –c COMPATIBILITY_BACKWARD –F ./booking.json
29+
`),
30+
RunE: func(cmd *cobra.Command, args []string) error {
31+
fileData, err := os.ReadFile(file)
32+
if err != nil {
33+
return err
34+
}
35+
req.Data = fileData
36+
37+
spinner := printer.Spin("")
38+
defer spinner.Stop()
39+
client, cancel, err := createClient(cmd)
40+
if err != nil {
41+
return err
42+
}
43+
defer cancel()
44+
45+
schemaID := args[0]
46+
req.NamespaceId = namespaceID
47+
req.SchemaId = schemaID
48+
req.Format = stencilv1beta1.Schema_Format(stencilv1beta1.Schema_Format_value[format])
49+
req.Compatibility = stencilv1beta1.Schema_Compatibility(stencilv1beta1.Schema_Compatibility_value[comp])
50+
51+
res, err := client.CreateSchema(context.Background(), &req)
52+
if err != nil {
53+
errStatus := status.Convert(err)
54+
if codes.AlreadyExists == errStatus.Code() {
55+
fmt.Printf("\n%s Schema with id '%s' already exist.\n", term.FailureIcon(), args[0])
56+
return nil
57+
}
58+
return errors.New(errStatus.Message())
59+
}
60+
61+
id := res.GetId()
62+
63+
spinner.Stop()
64+
fmt.Printf("\n%s Created schema with id %s.\n", term.Green(term.SuccessIcon()), term.Cyan(id))
65+
return nil
66+
},
67+
}
68+
69+
cmd.Flags().StringVar(&host, "host", "", "Stencil host address eg: localhost:8000")
70+
cmd.MarkFlagRequired("host")
71+
72+
cmd.Flags().StringVarP(&namespaceID, "namespace", "n", "", "Namespace ID")
73+
cmd.MarkFlagRequired("namespace")
74+
75+
cmd.Flags().StringVarP(&format, "format", "f", "", "Schema format")
76+
77+
cmd.Flags().StringVarP(&comp, "comp", "c", "", "Schema compatibility")
78+
79+
cmd.Flags().StringVarP(&file, "file", "F", "", "Path to the schema file")
80+
cmd.MarkFlagRequired("file")
81+
82+
return cmd
83+
}

cmd/delete.go

Lines changed: 72 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,72 @@
1+
package cmd
2+
3+
import (
4+
"context"
5+
"fmt"
6+
7+
"github.com/MakeNowJust/heredoc"
8+
"github.com/odpf/salt/printer"
9+
stencilv1beta1 "github.com/odpf/stencil/proto/odpf/stencil/v1beta1"
10+
"github.com/spf13/cobra"
11+
)
12+
13+
func deleteSchemaCmd() *cobra.Command {
14+
var host, namespaceID string
15+
var req stencilv1beta1.DeleteSchemaRequest
16+
var reqVer stencilv1beta1.DeleteVersionRequest
17+
var version int32
18+
19+
cmd := &cobra.Command{
20+
Use: "delete <id>",
21+
Short: "Delete a schema",
22+
Args: cobra.ExactArgs(1),
23+
Example: heredoc.Doc(`
24+
$ stencil schema delete booking -n odpf
25+
`),
26+
RunE: func(cmd *cobra.Command, args []string) error {
27+
spinner := printer.Spin("")
28+
defer spinner.Stop()
29+
30+
client, cancel, err := createClient(cmd)
31+
if err != nil {
32+
return err
33+
}
34+
defer cancel()
35+
36+
schemaID := args[0]
37+
38+
if version == 0 {
39+
req.NamespaceId = namespaceID
40+
req.SchemaId = schemaID
41+
42+
_, err = client.DeleteSchema(context.Background(), &req)
43+
if err != nil {
44+
return err
45+
}
46+
} else {
47+
reqVer.NamespaceId = namespaceID
48+
reqVer.SchemaId = schemaID
49+
reqVer.VersionId = version
50+
51+
_, err = client.DeleteVersion(context.Background(), &reqVer)
52+
if err != nil {
53+
return err
54+
}
55+
}
56+
57+
spinner.Stop()
58+
fmt.Printf("Schema successfully deleted")
59+
return nil
60+
},
61+
}
62+
63+
cmd.Flags().StringVar(&host, "host", "", "Stencil host address eg: localhost:8000")
64+
cmd.MarkFlagRequired("host")
65+
66+
cmd.Flags().StringVarP(&namespaceID, "namespace", "n", "", "Parent namespace ID")
67+
cmd.MarkFlagRequired("namespace")
68+
69+
cmd.Flags().Int32VarP(&version, "version", "v", 0, "Particular version to be deleted")
70+
71+
return cmd
72+
}

0 commit comments

Comments
 (0)