Skip to content

Commit

Permalink
Fix marshaling of StringVariable to match unmarshaling (#19)
Browse files Browse the repository at this point in the history
When I added "pebble plan" to fetch the plan, I didn't add a custom
MarshalYAML function on plan.StringVariable, so it marshaled like so:

environment:
    - name: FOO
      value: bar

This changes it to matching the unmarshaling, like so:

environment:
    - FOO: bar

Corresponding Python Operator Framework issue:
canonical/operator#486
  • Loading branch information
benhoyt authored Mar 23, 2021
1 parent 616b5a5 commit e7f5987
Show file tree
Hide file tree
Showing 2 changed files with 50 additions and 5 deletions.
14 changes: 12 additions & 2 deletions internal/plan/plan.go
Original file line number Diff line number Diff line change
Expand Up @@ -70,10 +70,16 @@ const (
)

type StringVariable struct {
Name string `yaml:"name"`
Value string `yaml:"value"`
Name string
Value string
}

// Ensure we're implementing both the custom unmarshaler and marshaller. Note
// that the unmarshaller is on *StringVariable, but the marshaller needs to be
// on the non-pointer type.
var _ yaml.Unmarshaler = &StringVariable{}
var _ yaml.Marshaler = StringVariable{}

func (sv *StringVariable) UnmarshalYAML(node *yaml.Node) error {
if node.ShortTag() != "!!map" || len(node.Content) != 2 {
return fmt.Errorf("environment must be a list of single-item maps (- name: value)")
Expand All @@ -91,6 +97,10 @@ func (sv *StringVariable) UnmarshalYAML(node *yaml.Node) error {
return nil
}

func (sv StringVariable) MarshalYAML() (interface{}, error) {
return map[string]string{sv.Name: sv.Value}, nil
}

// CombineLayers combines the given layers into a Plan, with the later layers
// layers overriding earlier ones.
func CombineLayers(layers ...*Layer) (*Layer, error) {
Expand Down
41 changes: 38 additions & 3 deletions internal/plan/plan_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -23,17 +23,18 @@ import (
"path/filepath"
"strings"

"github.com/canonical/pebble/internal/plan"

. "gopkg.in/check.v1"
"gopkg.in/yaml.v3"

"github.com/canonical/pebble/internal/plan"
)

// TODOs:
// - command-chain
// - error on invalid keys
// - constraints on service names

// The YAML on tests below passes throught this function to deindent and
// The YAML on tests below passes through this function to deindent and
// replace tabs by spaces, so we can keep the code here sane.
func reindent(in string) []byte {
var buf bytes.Buffer
Expand Down Expand Up @@ -478,3 +479,37 @@ func (s *S) TestReadDirDupNames(c *C) {
}
}
}

func (s *S) TestMarshalLayer(c *C) {
layerBytes := reindent(`
summary: Simple layer
description: A simple layer.
services:
srv1:
summary: Service summary
default: start
override: replace
command: cmd arg1 "arg2 arg3"
after:
- srv2
before:
- srv3
requires:
- srv2
- srv3
environment:
- var1: val1
- var0: val0
- var2: val2
srv2:
override: replace
command: srv2cmd
srv3:
override: replace
command: srv3cmd`)
layer, err := plan.ParseLayer(1, "layer1", layerBytes)
c.Assert(err, IsNil)
out, err := yaml.Marshal(layer)
c.Assert(err, IsNil)
c.Assert(string(out), Equals, string(layerBytes))
}

0 comments on commit e7f5987

Please sign in to comment.