Change:
I spin up a new cluster using GKE at version 0.9.2. Then I run: $kubectl get minion <minion-id-o yaml This returns a yaml file: apiVersion: v1beta1 creationTimestamp: 2015-02-03T01:16:46Z hostIP: <ipid: <minion-idkind: Node labels: diskSize: "massive" resourceVersion: 12 resources: capacity: cpu: "1" memory: 4.+09 selfLink: /api/v1beta1/minions/<minion-idstatus: conditions: kind: Ready lastTransitionTime: null status: Full uid: -ab42-11e4-9817- I delete the hostIp and status so that the update request won't get rejected ( should fix that), then run: $ kubectl update -f ERROR: F0202 18:08:19. 767 ] error unmarshaling JSON: json: cannot unmarshal number 4.+09 into Go value of type int I'm not sure whether the marshaling or the unmarshaling is what needs to be fixed, but the API shouldn't be returning numbers that it can't parse.
It looks like Quantity is unmarshalling wrong? , Alex Robinson wrote:
That's very likely. And sorry, I didn't realize yaml didn't paste into comments well. Here's the actual yaml:
Yeah, on the client-side, apparently, since the error is in It's possible that was missed during the Quantity refactoring. It may be troublesome that the v1beta1 API accepts a util.IntOrString for resources rather than a Quantity:
/cc
The (external) yaml library that we use is the cause for this. I will send a patch to fix the yaml library.
Sent a to our yaml dependency.
If we are only fixing our yaml unmarshalling, we are still losing precision. E.g. The yaml that Alex posted above is supposed to be representing 3.75 GiB. 75 GiB * 2^30 = , which we are representing as 4.+09. The amount of memory we are "losing" here is trivial, but if this is actually using scientific notation, we could be rounding up half the time as well (creating a very very low chance of an unexpected OOM). Both of these are pretty small problems, but it seems silly to needlessly lose precision. Can we just not write these in scientific notation?
Resource quantities must be lossless. , CJ Cullen wrote:
+1. These are supposed to be strings, not integers nor floats.
What does return?
That does look like an API bug. It should be a string, IIUC.
Legacy CPU and memory are int and int64, respectively. Resource.Quantity should always produce strings.
This can't possibly work. IntOrString is a 32-bit signed int. This value doesn't fit in 32 bits.
Yes - this isn't a problem with the YAML library. This is a problem with trying to render a number larger than 32 bits () as a 32-bit integer (IntOrString), which instead ends up rendering as a floating point. (or something that keeps this value as a 64-bit integer the whole time) is the right fix.
The yaml library converts an into a as part of Marshal. Isn't that an issue with the yaml library? I agree that the kubernetes API has another issue which is that of not being able to represent resources greater than MaxInt. But to me these are two separate issues.
Even an int32 gets marshaled into a floating point number. I don't see how that is valid. The underlying golang package has separate APIs to address this behavior and the YAML library will also have to do that.
IntOrString stores things as "int", which is 32 or 64 bits depending on the platform. We should explicitly use int32 or int64 in our api objects. These values should be stored as a Quantity in v1beta3, and converted to a string in v1beta1 & 2.
Ack , Daniel Smith wrote:
If someone changed IntOrString to use int64 I would approve. , Vish Kannan wrote:
Assigned to myself.

Discussion:
}, { "ImportPath": "github.com/ghodss/yaml", <del> "Rev": "3bc1590d16074751993dd3b1a76e7a8d1a916a11" </del> <ins> "Rev": "588cb435e59ee8b6c2795482887755841ad67207" </ins> }, { "ImportPath": "github.com/golang/glog",

func JSONToYAML(j []byte) ([]byte, error) { // Convert the JSON to an object. var jsonObj interface{} <del> err := json.Unmarshal(j, &jsonObj) </del> <ins> // We are using yaml.Unmarshal here (instead of json.Unmarshal) because the // Go JSON library doesn't try to pick the right number type (int, float, // etc.) when unmarshling to interface{}, it just picks float64 // universally. go-yaml does go through the effort of picking the right // number type, so we can preserve number type throughout this process. err := yaml.Unmarshal(j, &jsonObj) </ins> if err != nil { return nil, err }

package yaml import ( <ins> "fmt" "math" </ins> "reflect" <ins> "strconv" </ins> "testing" ) type MarshalTest struct { A string <ins> B int64 // Would like to test float64, but it's not supported in go-yaml. // (See https://github.com/go-yaml/yaml/issues/83.) C float32 </ins> } func TestMarshal(t *testing.T) { <del> s := MarshalTest{"a"} e := []byte("A: an") </del> <ins> f32String := strconv.FormatFloat(math.MaxFloat32, 'g', -1, 32) s := MarshalTest{"a", math.MaxInt64, math.MaxFloat32} e := []byte(fmt.Sprintf("A: anB: %dnC: %sn", math.MaxInt64, f32String)) </ins> y, err := Marshal(s) if err != nil {