chartutil.ReadValues is forced to unmarshal numbers into json.Number refs #1707 [dev-v3]

Backport of https://github.com/helm/helm/pull/6010 to dev-v3 (the
description below is a copy-paste from the original v2 branch PR).
As https://github.com/helm/helm/pull/6016 is now merged to dev-v3, the
change is reasonably trivial.

This change is an attempt to address the common problem of json number
unmarshalling where any number is converted into a float64 and
represented in a scientific notation on a marshall call. This behavior
breaks things like: chart versions and image tags if not converted to
yaml strings explicitly.

An example of this behavior: k8s failure to fetch an image tagged with a
big number like: $IMAGE:20190612073634 after a few steps of yaml
re-rendering turns into: $IMAGE:2.0190612073634e+13.

Example issue: #1707

This commit forces yaml parser to use JSON modifiers and explicitly
enables interface{} unmarshalling instead of float64. The change
introduced might be breaking so should be processed with an extra care.

Due to the fact helm mostly dals with human-produced data (charts), we
have a decent level of confidence this change looses no functionality
helm users rely upon (the scientific notation).

Relevant doc: https://golang.org/pkg/encoding/json/#Decoder.UseNumber

Signed-off-by: Oleg Sidorov <oleg.sidorov@booking.com>
Signed-off-by: Oleg Sidorov <me@whitebox.io>
pull/6032/head
Oleg Sidorov 5 years ago
parent 84d0f231e8
commit f94bac0643

@ -10,3 +10,4 @@ water:
water:
where: "everywhere"
nor: "any drop to drink"
temperature: 1234567890

@ -17,6 +17,7 @@ limitations under the License.
package chartutil
import (
"encoding/json"
"fmt"
"io"
"io/ioutil"
@ -105,7 +106,10 @@ func tableLookup(v Values, simple string) (Values, error) {
// ReadValues will parse YAML byte data into a Values.
func ReadValues(data []byte) (vals Values, err error) {
err = yaml.Unmarshal(data, &vals)
err = yaml.Unmarshal(data, &vals, func(d *json.Decoder) *json.Decoder {
d.UseNumber()
return d
})
if len(vals) == 0 {
vals = Values{}
}

@ -45,6 +45,7 @@ water:
water:
where: "everywhere"
nor: "any drop to drink"
temperature: 1234567890
`
data, err := ReadValues([]byte(doc))
@ -237,6 +238,12 @@ func matchValues(t *testing.T, data map[string]interface{}) {
} else if o != "everywhere" {
t.Errorf("Expected water water everywhere")
}
if o, err := ttpl("{{.water.water.temperature}}", data); err != nil {
t.Errorf(".water.water.temperature: %s", err)
} else if o != "1234567890" {
t.Errorf("Expected water water temperature: 1234567890, got: %s", o)
}
}
func ttpl(tpl string, v map[string]interface{}) (string, error) {

Loading…
Cancel
Save