Unmarshal a number as a Number in RawInspectFallback

Running `docker inspect --format "{{.ID}} {{.Size}}" alpine` prints
sha256:651aa95985aa4a17a38ffcf71f598ec461924ca96865facc2c5782ef2d2be07f 3983636
While `docker inspect --format "{{.Id}} {{.Size}}" alpine` prints
sha256:651aa95985aa4a17a38ffcf71f598ec461924ca96865facc2c5782ef2d2be07f 3.983636e+06

This happens because "Id" is not a field of types.ImageInspect and thus
tryRawInspectFallback is called and converts the raw response into `interface{}`
using a JSON decoder. However, by default that decoder converts numbers into
`float64` unless `UseNumber` is set.

Signed-off-by: Boaz Shuster <ripcurld.github@gmail.com>
This commit is contained in:
Boaz Shuster 2017-06-18 18:48:10 +03:00
parent eb7452cf3a
commit 9a2f2d769d
2 changed files with 39 additions and 0 deletions

View File

@ -110,6 +110,7 @@ func (i *TemplateInspector) tryRawInspectFallback(rawElement []byte) error {
buffer := new(bytes.Buffer) buffer := new(bytes.Buffer)
rdr := bytes.NewReader(rawElement) rdr := bytes.NewReader(rawElement)
dec := json.NewDecoder(rdr) dec := json.NewDecoder(rdr)
dec.UseNumber()
if rawErr := dec.Decode(&raw); rawErr != nil { if rawErr := dec.Decode(&raw); rawErr != nil {
return errors.Errorf("unable to read inspect data: %v", rawErr) return errors.Errorf("unable to read inspect data: %v", rawErr)

View File

@ -6,6 +6,8 @@ import (
"testing" "testing"
"github.com/docker/docker/pkg/templates" "github.com/docker/docker/pkg/templates"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
) )
type testElement struct { type testElement struct {
@ -219,3 +221,39 @@ func TestIndentedInspectorRawElements(t *testing.T) {
t.Fatalf("Expected `%s`, got `%s`", expected, b.String()) t.Fatalf("Expected `%s`, got `%s`", expected, b.String())
} }
} }
// moby/moby#32235
// This test verifies that even if `tryRawInspectFallback` is called the fields containing
// numerical values are displayed correctly.
// For example, `docker inspect --format "{{.Id}} {{.Size}} alpine` and
// `docker inspect --format "{{.ID}} {{.Size}} alpine" will have the same output which is
// sha256:651aa95985aa4a17a38ffcf71f598ec461924ca96865facc2c5782ef2d2be07f 3983636
func TestTemplateInspectorRawFallbackNumber(t *testing.T) {
// Using typedElem to automatically fall to tryRawInspectFallback.
typedElem := struct {
ID string `json:"Id"`
}{"ad3"}
testcases := []struct {
raw []byte
exp string
}{
{raw: []byte(`{"Id": "ad3", "Size": 53317}`), exp: "53317 ad3\n"},
{raw: []byte(`{"Id": "ad3", "Size": 53317.102}`), exp: "53317.102 ad3\n"},
{raw: []byte(`{"Id": "ad3", "Size": 53317.0}`), exp: "53317.0 ad3\n"},
}
b := new(bytes.Buffer)
tmpl, err := templates.Parse("{{.Size}} {{.Id}}")
require.NoError(t, err)
i := NewTemplateInspector(b, tmpl)
for _, tc := range testcases {
err = i.Inspect(typedElem, tc.raw)
require.NoError(t, err)
err = i.Flush()
require.NoError(t, err)
assert.Equal(t, tc.exp, b.String())
b.Reset()
}
}