Giter Club home page Giter Club logo

Comments (3)

goccy avatar goccy commented on May 14, 2024

Hi @kav
I saw a referenced issue.

I understood that you want to refer to it from alias ​​after replacing the value defined in anchor with an arbitrary one.

For example, can you solve it with like the following API?

yml := `---
image: &image
  version: 1.0.0
  foo: bar
`
anchorOpt := yaml.UnmarshalAnchor(func(anchorName string, anchorValue interface{}) interface{}{
  // anchorName:  image
  // anchorValue: map[string]interface{}{ "version": "1.0.0", "foo" : "bar" }
  if anchorName == "image" {
    anchorValue["version"] = "2.0.0"
  }
  return anchorValue // returns replaced value
})

dec := yaml.NewDecoder(strings.NewReader(yml), anchorOpt)
var v interface{}
dec.Decode(&v) // use replaced anchor value with UnmarshalAnchor option in decoding

or

yaml.UnmarshalAnchor(func(anchorName string, anchorDoc []byte) interface{}{
  // anchorName: image
  // anchorDoc: []byte("version: 1.0.0\nfoo: bar")
  var v map[string]interface{}{}
  yaml.Unmarshal(anchorDoc, &v)
  if anchorName == "image" {
    v["version"] = "2.0.0"
  }
  return v // returns anchor value
})

from go-yaml.

kav avatar kav commented on May 14, 2024

There are essentially two tasks happening at once that I think make this more complex. We are combining an arbitrary number of yaml files and command line options, which I'm thinking of as sparse yaml, and then resolving anchors. Using the above might work but I'll need to pseudocode out a bit how the resolution logic should determine the final value.

So let's walkthrough an unreasonably hairy example. Though the "asubchart" use case is exactly the common scenario we run into here:
I run
helm --set image.version=3.0.0 -f my-values.yaml
which gives me my first yaml

image:
  version: 3.0.0

Given I have
my-values.yaml

image:
  version: 2.0.0
  foo: baz

and the chart has
values.yaml

image: &image
  version: 1.0.0
  foo: bar
asubchart:
  image: *image

I'm perhaps incorrectly imagining the easiest solution would be to combine the three yamls without resolving the anchor.

my-values.yaml + values.yaml =

image: &image
  version: 2.0.0
  foo: baz
asubchart:
  image: *image

set + (my-values.yaml + values.yaml ) =

image: &image
  version: 3.0.0
  foo: baz
asubchart:
  image: *image

resolve( set + (my-values.yaml + values.yaml )) =

image:
  version: 3.0.0
  foo: baz
asubchart:
  image:
    version: 3.0.0
    foo: baz

I'm not sure there is a simple solution using the unmarshal anchor above, though perhaps something like this I could use to "keep" the anchor around in the unmarshaled object.

yaml.UnmarshalAnchor(func(anchorName string, anchorDoc []byte) interface{}{
  // anchorName: image
  // anchorDoc: []byte("version: 1.0.0\nfoo: bar")
  var v map[string]interface{}{}
  yaml.Unmarshal(anchorDoc, &v)
  v["__anchor"] = anchorName
  return v // returns anchor value
})

Though something like this might not work if the original anchor point and the resolved alias point both now had the resulting object. I'd have no way to determine the direction of reference so there is likely something around unmarshaling aliases needed here as well.

yaml. UnmarshalAlias(func(aliasName string, anchorDoc []byte) interface {}{
  var v map[string]interface{}{}
  v["__alias"] = aliasName
  return v
}

Then my resultant object could be combined easily and I could crawl through it to resolve and remove the __anchor and '__alias properties after unmarshaling.

There is another twist in overriding a partial sub of an alias but I think I could handle that with the above working. Also not 100% sure what happens if we are anchoring and aliasing a scalar value? Do I need to be throwing the resolved v into a value property or something?

from go-yaml.

goccy avatar goccy commented on May 14, 2024

Perhaps this problem can be solved by filtering the nodes created by parser.ParseBytes by yaml.Path .

file, _ := parser.ParseBytes(yml, 0)
path, _ := yaml.PathString("$path.to.anchor")
anchorNode, _ := path.FilterFile(file)
// manipulate anchorNode
var v struct{}
yaml.Unmashal([]byte(file.String()), &v)

from go-yaml.

Related Issues (20)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    πŸ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. πŸ“ŠπŸ“ˆπŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❀️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.