Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 3 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -14,8 +14,8 @@ Stencil is a schema registry that provides schema mangement and validation to en
Discover why users choose Stencil as their main schema registry

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

**Server**

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.
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.

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.

Expand Down
24 changes: 24 additions & 0 deletions cmd/cdk.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
package cmd

var dict = map[string]string{
"COMPATIBILITY_BACKWARD": "backward",
"COMPATIBILITY_FORWARD": "forward",
"COMPATIBILITY_FULL": "full",
"FORMAT_PROTOBUF": "protobuf",
"FORMAT_JSON": "json",
"FORMAT_AVRO": "avro",
}

var (
formats = []string{
"FORMAT_JSON",
"FORMAT_PROTOBUF",
"FORMAT_AVRO",
}

comps = []string{
"COMPATIBILITY_BACKWARD",
"COMPATIBILITY_FORWARD",
"COMPATIBILITY_FULL",
}
)
78 changes: 78 additions & 0 deletions cmd/check.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,78 @@
package cmd

import (
"context"
"errors"
"fmt"
"os"

"github.com/MakeNowJust/heredoc"
"github.com/odpf/salt/printer"
"github.com/odpf/salt/term"
stencilv1beta1 "github.com/odpf/stencil/proto/odpf/stencil/v1beta1"
"github.com/spf13/cobra"
"google.golang.org/grpc/status"
)

func checkSchemaCmd() *cobra.Command {
var host, comp, file, namespaceID string
var req stencilv1beta1.CheckCompatibilityRequest

cmd := &cobra.Command{
Use: "check <id>",
Args: cobra.ExactArgs(1),
Short: "Check schema compatibility",
Long: heredoc.Doc(`
Check schema compatibility of a local schema
against a remote schema(against) on stencil server.`),
Example: heredoc.Doc(`
$ stencil schema check <id> -n odpf -c COMPATIBILITY_BACKWARD -F ./booking.desc
`),
RunE: func(cmd *cobra.Command, args []string) error {
spinner := printer.Spin("")
defer spinner.Stop()

fileData, err := os.ReadFile(file)
if err != nil {
return err
}

client, cancel, err := createClient(cmd)
if err != nil {
return err
}
defer cancel()

schemaID := args[0]

req.Data = fileData
req.NamespaceId = namespaceID
req.SchemaId = schemaID
req.Compatibility = stencilv1beta1.Schema_Compatibility(stencilv1beta1.Schema_Compatibility_value[comp])

_, err = client.CheckCompatibility(context.Background(), &req)
if err != nil {
errStatus := status.Convert(err)
return errors.New(errStatus.Message())
}

spinner.Stop()
fmt.Printf("\n%s Schema is compatible.\n", term.Green(term.SuccessIcon()))
return nil
},
}

cmd.Flags().StringVar(&host, "host", "", "Server host address eg: localhost:8000")
cmd.MarkFlagRequired("host")

cmd.Flags().StringVarP(&namespaceID, "namespace", "n", "", "Parent namespace ID")
cmd.MarkFlagRequired("namespace")

cmd.Flags().StringVarP(&comp, "comp", "c", "", "Schema compatibility")
cmd.MarkFlagRequired("comp")

cmd.Flags().StringVarP(&file, "file", "F", "", "Path to the schema file")
cmd.MarkFlagRequired("file")

return cmd
}
83 changes: 83 additions & 0 deletions cmd/create.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,83 @@
package cmd

import (
"context"
"errors"
"fmt"
"os"

"github.com/MakeNowJust/heredoc"
"github.com/odpf/salt/printer"
"github.com/odpf/salt/term"
stencilv1beta1 "github.com/odpf/stencil/proto/odpf/stencil/v1beta1"
"github.com/spf13/cobra"
"google.golang.org/grpc/codes"
"google.golang.org/grpc/status"
)

func createSchemaCmd() *cobra.Command {
var host, format, comp, file, namespaceID string
var req stencilv1beta1.CreateSchemaRequest

cmd := &cobra.Command{
Use: "create",
Short: "Create a schema",
Args: cobra.ExactArgs(1),
Example: heredoc.Doc(`
$ stencil schema create booking -n odpf –F booking.json
$ stencil schema create booking -n odpf -f FORMAT_JSON –c COMPATIBILITY_BACKWARD –F ./booking.json
`),
RunE: func(cmd *cobra.Command, args []string) error {
fileData, err := os.ReadFile(file)
if err != nil {
return err
}
req.Data = fileData

spinner := printer.Spin("")
defer spinner.Stop()
client, cancel, err := createClient(cmd)
if err != nil {
return err
}
defer cancel()

schemaID := args[0]
req.NamespaceId = namespaceID
req.SchemaId = schemaID
req.Format = stencilv1beta1.Schema_Format(stencilv1beta1.Schema_Format_value[format])
req.Compatibility = stencilv1beta1.Schema_Compatibility(stencilv1beta1.Schema_Compatibility_value[comp])

res, err := client.CreateSchema(context.Background(), &req)
if err != nil {
errStatus := status.Convert(err)
if codes.AlreadyExists == errStatus.Code() {
fmt.Printf("\n%s Schema with id '%s' already exist.\n", term.FailureIcon(), args[0])
return nil
}
return errors.New(errStatus.Message())
}

id := res.GetId()

spinner.Stop()
fmt.Printf("\n%s Created schema with id %s.\n", term.Green(term.SuccessIcon()), term.Cyan(id))
return nil
},
}

cmd.Flags().StringVar(&host, "host", "", "Stencil host address eg: localhost:8000")
cmd.MarkFlagRequired("host")

cmd.Flags().StringVarP(&namespaceID, "namespace", "n", "", "Namespace ID")
cmd.MarkFlagRequired("namespace")

cmd.Flags().StringVarP(&format, "format", "f", "", "Schema format")

cmd.Flags().StringVarP(&comp, "comp", "c", "", "Schema compatibility")

cmd.Flags().StringVarP(&file, "file", "F", "", "Path to the schema file")
cmd.MarkFlagRequired("file")

return cmd
}
72 changes: 72 additions & 0 deletions cmd/delete.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
package cmd

import (
"context"
"fmt"

"github.com/MakeNowJust/heredoc"
"github.com/odpf/salt/printer"
stencilv1beta1 "github.com/odpf/stencil/proto/odpf/stencil/v1beta1"
"github.com/spf13/cobra"
)

func deleteSchemaCmd() *cobra.Command {
var host, namespaceID string
var req stencilv1beta1.DeleteSchemaRequest
var reqVer stencilv1beta1.DeleteVersionRequest
var version int32

cmd := &cobra.Command{
Use: "delete <id>",
Short: "Delete a schema",
Args: cobra.ExactArgs(1),
Example: heredoc.Doc(`
$ stencil schema delete booking -n odpf
`),
RunE: func(cmd *cobra.Command, args []string) error {
spinner := printer.Spin("")
defer spinner.Stop()

client, cancel, err := createClient(cmd)
if err != nil {
return err
}
defer cancel()

schemaID := args[0]

if version == 0 {
req.NamespaceId = namespaceID
req.SchemaId = schemaID

_, err = client.DeleteSchema(context.Background(), &req)
if err != nil {
return err
}
} else {
reqVer.NamespaceId = namespaceID
reqVer.SchemaId = schemaID
reqVer.VersionId = version

_, err = client.DeleteVersion(context.Background(), &reqVer)
if err != nil {
return err
}
}

spinner.Stop()
fmt.Printf("Schema successfully deleted")
return nil
},
}

cmd.Flags().StringVar(&host, "host", "", "Stencil host address eg: localhost:8000")
cmd.MarkFlagRequired("host")

cmd.Flags().StringVarP(&namespaceID, "namespace", "n", "", "Parent namespace ID")
cmd.MarkFlagRequired("namespace")

cmd.Flags().Int32VarP(&version, "version", "v", 0, "Particular version to be deleted")

return cmd
}
Loading