Skip to content

Commit

Permalink
✨ Add TOML extender
Browse files Browse the repository at this point in the history
  • Loading branch information
antoinemartin committed Jan 24, 2023
1 parent 10cb26b commit 5cf9109
Show file tree
Hide file tree
Showing 5 changed files with 133 additions and 2 deletions.
1 change: 1 addition & 0 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,7 @@ require (
github.com/mailru/easyjson v0.7.7 // indirect
github.com/mitchellh/mapstructure v1.4.3 // indirect
github.com/monochromegane/go-gitignore v0.0.0-20200626010858-205db1a8cc00 // indirect
github.com/pelletier/go-toml/v2 v2.0.6
github.com/pjbgf/sha1cd v0.2.3 // indirect
github.com/pkg/errors v0.9.1 // indirect
github.com/pmezard/go-difflib v1.0.0 // indirect
Expand Down
2 changes: 2 additions & 0 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -129,6 +129,8 @@ github.com/munnerz/goautoneg v0.0.0-20120707110453-a547fc61f48d/go.mod h1:+n7T8m
github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e/go.mod h1:zD1mROLANZcx1PVRCS0qkT7pwLkGfwJo4zjcN/Tysno=
github.com/onsi/ginkgo v0.0.0-20170829012221-11459a886d9c/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE=
github.com/onsi/gomega v0.0.0-20170829124025-dcabb60a477c/go.mod h1:C1qb7wdrVGGVU+Z6iS04AVkA3Q65CEZX59MT0QO5uiA=
github.com/pelletier/go-toml/v2 v2.0.6 h1:nrzqCb7j9cDFj2coyLNLaZuJTLjWjlaz6nvTvIwycIU=
github.com/pelletier/go-toml/v2 v2.0.6/go.mod h1:eumQOmlWiOPt5WriQQqoM5y18pDHwha2N+QD+EUNTek=
github.com/pjbgf/sha1cd v0.2.3 h1:uKQP/7QOzNtKYH7UTohZLcjF5/55EnTw0jO/Ru4jZwI=
github.com/pjbgf/sha1cd v0.2.3/go.mod h1:HOK9QrgzdHpbc2Kzip0Q1yi3M2MFGPADtR6HjG65m5M=
github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4=
Expand Down
82 changes: 82 additions & 0 deletions pkg/extras/extender.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import (
"strconv"
"strings"

"github.com/pelletier/go-toml/v2"
"golang.org/x/text/cases"
"golang.org/x/text/language"
"sigs.k8s.io/kustomize/kyaml/errors"
Expand Down Expand Up @@ -48,6 +49,7 @@ const (
Base64Extender
RegexExtender
JsonExtender
TomlExtender
)

var stringToExtenderTypeMap map[string]ExtenderType
Expand Down Expand Up @@ -361,6 +363,85 @@ func NewJsonExtender() Extender {
return &jsonExtender{}
}

///////
// TOML
///////

type tomlExtender struct {
node *yaml.RNode
}

func (e *tomlExtender) SetPayload(payload []byte) error {

m := map[string]interface{}{}
err := toml.Unmarshal(payload, &m)
if err != nil {
return errors.WrapPrefixf(err, "while un-marshalling toml")
}

e.node, err = yaml.FromMap(m)
if err != nil {
return errors.WrapPrefixf(err, "while converting into yaml")
}

return nil
}

func getTOMLPayload(node *yaml.RNode) ([]byte, error) {
m, err := node.Map()
if err != nil {
return nil, errors.WrapPrefixf(err, "while encoding to map")
}
return toml.Marshal(m)
}

func (e *tomlExtender) GetPayload() ([]byte, error) {
return getTOMLPayload(e.node)
}

func (e *tomlExtender) Get(path []string) ([]byte, error) {
targetFields, err := Lookup(e.node, path)
if err != nil {
return nil, errors.WrapPrefixf(err, "error fetching elements in replacement target")
}

if len(targetFields) > 1 {
return nil, fmt.Errorf("path %s returned %d items. Expected one", strings.Join(path, "."), len(targetFields))
}

target := targetFields[0]
if target.YNode().Kind == yaml.ScalarNode {
return []byte(target.YNode().Value), nil
}

return getTOMLPayload(target)
}

func (e *tomlExtender) Set(path []string, value any) error {

targetFields, err := Lookup(e.node, path)
if err != nil {
return fmt.Errorf("error fetching elements in replacement target: %w", err)
}

for _, t := range targetFields {
if t.YNode().Kind == yaml.ScalarNode {
t.YNode().Value = string(GetByteValue(value))
} else {
if v, ok := value.(*yaml.Node); ok {
t.SetYNode(v)
} else {
return fmt.Errorf("setting non toml object in place of object of type %s at path %s", t.YNode().Tag, strings.Join(path, "."))
}
}
}
return nil
}

func NewTomlExtender() Extender {
return &tomlExtender{}
}

////////////
// Factories
////////////
Expand All @@ -370,6 +451,7 @@ var ExtenderFactories = map[ExtenderType]func() Extender{
Base64Extender: NewBase64Extender,
RegexExtender: NewRegexExtender,
JsonExtender: NewJsonExtender,
TomlExtender: NewTomlExtender,
}

func (path *ExtendedSegment) Extender(payload []byte) (Extender, error) {
Expand Down
45 changes: 45 additions & 0 deletions pkg/extras/extender_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -373,6 +373,51 @@ func (s *ExtenderTestSuite) TestJsonArrayExtender() {
require.Equal("deploy/citest", string(value), "error fetching changed value")
}

func (s *ExtenderTestSuite) TestTomlExtender() {
require := s.Require()
source := `
uninode = true
[common]
targetRevision = 'main'
[apps]
enabled = true
`
expected := `uninode = true
[apps]
enabled = true
[common]
targetRevision = 'deploy/citest'
`

p := `!!toml.common.targetRevision`
path := kyaml_utils.SmarterPathSplitter(p, ".")

extensions := []*ExtendedSegment{}
prefix, err := splitExtendedPath(path, &extensions)
require.NoError(err)
require.Len(prefix, 0, "There should be no prefix")
require.Len(extensions, 1, "There should be 2 extensions")
require.Equal("toml", extensions[0].Encoding, "The first extension should be toml")

tomlXP := extensions[0]
tomlExt, err := tomlXP.Extender([]byte(source))
require.NoError(err)
value, err := tomlExt.Get(tomlXP.Path)
require.NoError(err)
require.Equal("main", string(value), "error fetching value")
require.NoError(tomlExt.Set(tomlXP.Path, []byte("deploy/citest")))

modified, err := tomlExt.GetPayload()
require.NoError(err)
require.Equal(expected, string(modified), "final toml")

value, err = tomlExt.Get(tomlXP.Path)
require.NoError(err)
require.Equal("deploy/citest", string(value), "error fetching changed value")
}

func TestExtender(t *testing.T) {
suite.Run(t, new(ExtenderTestSuite))
}
5 changes: 3 additions & 2 deletions pkg/extras/extendertype_string.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

0 comments on commit 5cf9109

Please sign in to comment.