From faa0e1ab524092d3d7a1088a1502c41240eaf676 Mon Sep 17 00:00:00 2001 From: Akihiro Suda Date: Tue, 7 Mar 2017 04:07:20 +0000 Subject: [PATCH] build: support --format (pb and json) Signed-off-by: Akihiro Suda --- commands/apply.go | 10 ++----- commands/build.go | 22 +++++++++++++--- commands/commandsutil.go | 22 ++++++++++++++++ commands/mount.go | 10 ++----- commands/verify.go | 10 ++----- manifest.go | 57 ++++++++++++++++++++++++++++++---------- 6 files changed, 90 insertions(+), 41 deletions(-) create mode 100644 commands/commandsutil.go diff --git a/commands/apply.go b/commands/apply.go index 6dd32721..be511abd 100644 --- a/commands/apply.go +++ b/commands/apply.go @@ -1,7 +1,6 @@ package commands import ( - "io/ioutil" "log" "github.com/spf13/cobra" @@ -14,14 +13,9 @@ var ApplyCmd = &cobra.Command{ Run: func(cmd *cobra.Command, args []string) { root, path := args[0], args[1] - p, err := ioutil.ReadFile(path) + m, err := readManifest(path) if err != nil { - log.Fatalf("error reading manifest: %v", err) - } - - m, err := continuity.Unmarshal(p) - if err != nil { - log.Fatalf("error unmarshaling manifest: %v", err) + log.Fatal(err) } ctx, err := continuity.NewContext(root) diff --git a/commands/build.go b/commands/build.go index b42ab4d9..2fdb76f0 100644 --- a/commands/build.go +++ b/commands/build.go @@ -1,6 +1,7 @@ package commands import ( + "fmt" "log" "os" @@ -13,6 +14,13 @@ var ( format string } + marshalers = map[string]func(*continuity.Manifest) ([]byte, error){ + "pb": continuity.Marshal, + continuity.MediaTypeManifestV0Protobuf: continuity.Marshal, + "json": continuity.MarshalJSON, + continuity.MediaTypeManifestV0JSON: continuity.MarshalJSON, + } + BuildCmd = &cobra.Command{ Use: "build ", Short: "Build a manifest for the provided root", @@ -31,9 +39,15 @@ var ( log.Fatalf("error generating manifest: %v", err) } - p, err := continuity.Marshal(m) + marshaler, ok := marshalers[buildCmdConfig.format] + if !ok { + log.Fatalf("unknown format %s", buildCmdConfig.format) + } + + p, err := marshaler(m) if err != nil { - log.Fatalf("error marshaling manifest: %v", err) + log.Fatalf("error marshalling manifest as %s: %v", + buildCmdConfig.format, err) } if _, err := os.Stdout.Write(p); err != nil { @@ -44,5 +58,7 @@ var ( ) func init() { - BuildCmd.Flags().StringVar(&buildCmdConfig.format, "format", "pb", "specify the output format of the manifest") + BuildCmd.Flags().StringVar(&buildCmdConfig.format, "format", "pb", + fmt.Sprintf("specify the output format of the manifest (\"pb\"|%q|\"json\"|%q)", + continuity.MediaTypeManifestV0Protobuf, continuity.MediaTypeManifestV0JSON)) } diff --git a/commands/commandsutil.go b/commands/commandsutil.go new file mode 100644 index 00000000..d501ec84 --- /dev/null +++ b/commands/commandsutil.go @@ -0,0 +1,22 @@ +package commands + +import ( + "fmt" + "io/ioutil" + "path/filepath" + "strings" + + "github.com/stevvooe/continuity" +) + +func readManifest(path string) (*continuity.Manifest, error) { + p, err := ioutil.ReadFile(path) + if err != nil { + return nil, fmt.Errorf("error reading manifest: %v", err) + } + ext := strings.ToLower(filepath.Ext(path)) + if ext == ".json" { + return continuity.UnmarshalJSON(p) + } + return continuity.Unmarshal(p) +} diff --git a/commands/mount.go b/commands/mount.go index eda50ef8..9a90270e 100644 --- a/commands/mount.go +++ b/commands/mount.go @@ -1,7 +1,6 @@ package commands import ( - "io/ioutil" "log" "os" "os/signal" @@ -30,14 +29,9 @@ var MountCmd = &cobra.Command{ manifestName := filepath.Base(manifest) - p, err := ioutil.ReadFile(manifest) + m, err := readManifest(manifest) if err != nil { - log.Fatalf("error reading manifest: %v", err) - } - - m, err := continuity.Unmarshal(p) - if err != nil { - log.Fatalf("error unmarshaling manifest: %v", err) + log.Fatal(err) } driver, err := continuity.NewSystemDriver() diff --git a/commands/verify.go b/commands/verify.go index 2011d933..3d74fdd6 100644 --- a/commands/verify.go +++ b/commands/verify.go @@ -1,7 +1,6 @@ package commands import ( - "io/ioutil" "log" "github.com/spf13/cobra" @@ -18,14 +17,9 @@ var VerifyCmd = &cobra.Command{ root, path := args[0], args[1] - p, err := ioutil.ReadFile(path) + m, err := readManifest(path) if err != nil { - log.Fatalf("error reading manifest: %v", err) - } - - m, err := continuity.Unmarshal(p) - if err != nil { - log.Fatalf("error unmarshaling manifest: %v", err) + log.Fatal(err) } ctx, err := continuity.NewContext(root) diff --git a/manifest.go b/manifest.go index 4315bcbb..d3563e28 100644 --- a/manifest.go +++ b/manifest.go @@ -1,16 +1,29 @@ package continuity import ( + "bytes" "fmt" "io" "log" "os" "sort" + "github.com/golang/protobuf/jsonpb" "github.com/golang/protobuf/proto" pb "github.com/stevvooe/continuity/proto" ) +const ( + // MediaTypeManifestV0Protobuf is the media type for manifest formatted as protobuf. + // The format is unstable during v0. + MediaTypeManifestV0Protobuf = "application/vnd.continuity.manifest.v0+pb" + // MediaTypeManifestV0JSON is the media type for manifest formatted as JSON. + // JSON is marshalled from protobuf using jsonpb.Marshaler + // ({EnumAsInts = false, EmitDefaults = false, OrigName = false}) + // The format is unstable during v0. + MediaTypeManifestV0JSON = "application/vnd.continuity.manifest.v0+json" +) + // Manifest provides the contents of a manifest. Users of this struct should // not typically modify any fields directly. type Manifest struct { @@ -18,13 +31,7 @@ type Manifest struct { Resources []Resource } -func Unmarshal(p []byte) (*Manifest, error) { - var bm pb.Manifest - - if err := proto.Unmarshal(p, &bm); err != nil { - return nil, err - } - +func manifestFromProto(bm *pb.Manifest) (*Manifest, error) { var m Manifest for _, b := range bm.Resource { r, err := fromProto(b) @@ -34,26 +41,48 @@ func Unmarshal(p []byte) (*Manifest, error) { m.Resources = append(m.Resources, r) } - return &m, nil } -func Marshal(m *Manifest) ([]byte, error) { +func Unmarshal(p []byte) (*Manifest, error) { var bm pb.Manifest - for _, resource := range m.Resources { - bm.Resource = append(bm.Resource, toProto(resource)) + if err := proto.Unmarshal(p, &bm); err != nil { + return nil, err } + return manifestFromProto(&bm) +} - return proto.Marshal(&bm) +func UnmarshalJSON(p []byte) (*Manifest, error) { + var bm pb.Manifest + if err := jsonpb.Unmarshal(bytes.NewReader(p), &bm); err != nil { + return nil, err + } + return manifestFromProto(&bm) } -func MarshalText(w io.Writer, m *Manifest) error { +func manifestToProto(m *Manifest) *pb.Manifest { var bm pb.Manifest for _, resource := range m.Resources { bm.Resource = append(bm.Resource, toProto(resource)) } + return &bm +} - return proto.MarshalText(w, &bm) +func Marshal(m *Manifest) ([]byte, error) { + return proto.Marshal(manifestToProto(m)) +} + +func MarshalText(w io.Writer, m *Manifest) error { + return proto.MarshalText(w, manifestToProto(m)) +} + +func MarshalJSON(m *Manifest) ([]byte, error) { + var b bytes.Buffer + marshaler := &jsonpb.Marshaler{} + if err := marshaler.Marshal(&b, manifestToProto(m)); err != nil { + return nil, err + } + return b.Bytes(), nil } // BuildManifest creates the manifest for the given context