WIP: First cut at input validation for Kubelet

* Add some util functions for basic validation
* Spec api fields more tightly
* Break a dep from util -> api, so I can do the reverse
* Add functions to validate structures
* Call those functions when running manifests

This does not validate as it unmarshals YAML or JSON because I want to be able
to validate structures that come from other inputs without forcing them to be
YAML.

This does not handle all api structures - I am not familiar wnough with the
rest to spec them this tightly - I hope someone else can do that.

There are a number of open questions, marked "FIXME".  Please offer feedback
or opinions.
I'm looking at this failure but I don't know where to start on it, really...


On Sun, Jun 29, 2014 at 2:04 PM, Tim Hockin <thockin@google.com> wrote:

> e2e fails in a way I did not expect or quite understand:
>
> F0629 13:29:03.757801 24067 kubecfg.go:185] Failed to print:
> &json.UnsupportedTypeError{Type:(*reflect.rtype)(0x696460)}
> Raw received object:
> &api.PodList{JSONBase:api.JSONBase{Kind:"", ID:"", CreationTimestamp:"",
> SelfLink:""}, Items:[]api.Pod{api.Pod{JSONBase:api.JSONBase{Kind:"",
> ID:"9acb0442", CreationTimestamp:"", SelfLink:""},
> Labels:map[string]string{"replicationController":"myNginx",
> "name":"myNginx"},
> DesiredState:api.PodState{Manifest:api.ContainerManifest{Version:"",
> Volumes:[]api.Volume(nil),
> Containers:[]api.Container{api.Container{Name:"", Image:"dockerfile/nginx",
> Command:[]string(nil), WorkingDir:"", Ports:[]api.Port{api.Port{Name:"",
> HostPort:8080, ContainerPort:80, Protocol:""}}, Env:[]api.EnvVar(nil),
> Memory:0, CPU:0, VolumeMounts:[]api.VolumeMount(nil)}}, Id:""}, Status:"",
> Host:"", HostIP:"", Info:interface {}(nil)},
> CurrentState:api.PodState{Manifest:api.ContainerManifest{Version:"",
> Volumes:[]api.Volume(nil), Containers:[]api.Container(nil), Id:""},
> Status:"", Host:"e2e-test-thockin-minion-1.c.thockin-dev.internal",
> HostIP:"", Info:map[interface {}]interface {}{}}},
> api.Pod{JSONBase:api.JSONBase{Kind:"", ID:"700e0976", CreationTimestamp:"",
> SelfLink:""}, Labels:map[string]string{"name":"redisslave",
> "replicationController":"redisSlaveController"},
> DesiredState:api.PodState{Manifest:api.ContainerManifest{Version:"",
> Volumes:[]api.Volume(nil),
> Containers:[]api.Container{api.Container{Name:"",
> Image:"brendanburns/redis-slave", Command:[]string(nil), WorkingDir:"",
> Ports:[]api.Port{api.Port{Name:"", HostPort:6380, ContainerPort:6379,
> Protocol:""}}, Env:[]api.EnvVar(nil), Memory:0, CPU:0,
> VolumeMounts:[]api.VolumeMount(nil)}}, Id:""}, Status:"", Host:"",
> HostIP:"", Info:interface {}(nil)},
> CurrentState:api.PodState{Manifest:api.ContainerManifest{Version:"",
> Volumes:[]api.Volume(nil), Containers:[]api.Container(nil), Id:""},
> Status:"", Host:"e2e-test-thockin-minion-1.c.thockin-dev.internal",
> HostIP:"", Info:interface {}(nil)}}, api.Pod{JSONBase:api.JSONBase{Kind:"",
> ID:"f0c5341e", CreationTimestamp:"", SelfLink:""},
> Labels:map[string]string{"name":"myNginx",
> "replicationController":"myNginx"},
> DesiredState:api.PodState{Manifest:api.ContainerManifest{Version:"",
> Volumes:[]api.Volume(nil),
> Containers:[]api.Container{api.Container{Name:"", Image:"dockerfile/nginx",
> Command:[]string(nil), WorkingDir:"", Ports:[]api.Port{api.Port{Name:"",
> HostPort:8080, ContainerPort:80, Protocol:""}}, Env:[]api.EnvVar(nil),
> Memory:0, CPU:0, VolumeMounts:[]api.VolumeMount(nil)}}, Id:""}, Status:"",
> Host:"", HostIP:"", Info:interface {}(nil)},
> CurrentState:api.PodState{Manifest:api.ContainerManifest{Version:"",
> Volumes:[]api.Volume(nil), Containers:[]api.Container(nil), Id:""},
> Status:"", Host:"e2e-test-thockin-minion-2.c.thockin-dev.internal",
> HostIP:"", Info:map[interface {}]interface {}{}}},
> api.Pod{JSONBase:api.JSONBase{Kind:"", ID:"redis-master-2",
> CreationTimestamp:"", SelfLink:""},
> Labels:map[string]string{"name":"redis-master"},
> DesiredState:api.PodState{Manifest:api.ContainerManifest{Version:"",
> Volumes:[]api.Volume(nil),
> Containers:[]api.Container{api.Container{Name:"master",
> Image:"dockerfile/redis", Command:[]string(nil), WorkingDir:"",
> Ports:[]api.Port{api.Port{Name:"", HostPort:6379, ContainerPort:6379,
> Protocol:""}}, Env:[]api.EnvVar(nil), Memory:0, CPU:0,
> VolumeMounts:[]api.VolumeMount(nil)}}, Id:""}, Status:"", Host:"",
> HostIP:"", Info:interface {}(nil)},
> CurrentState:api.PodState{Manifest:api.ContainerManifest{Version:"",
> Volumes:[]api.Volume(nil), Containers:[]api.Container(nil), Id:""},
> Status:"", Host:"e2e-test-thockin-minion-2.c.thockin-dev.internal",
> HostIP:"", Info:map[interface {}]interface {}{}}},
> api.Pod{JSONBase:api.JSONBase{Kind:"", ID:"aa209b8e", CreationTimestamp:"",
> SelfLink:""}, Labels:map[string]string{"name":"redisslave",
> "replicationController":"redisSlaveController"},
> DesiredState:api.PodState{Manifest:api.ContainerManifest{Version:"",
> Volumes:[]api.Volume(nil),
> Containers:[]api.Container{api.Container{Name:"",
> Image:"brendanburns/redis-slave", Command:[]string(nil), WorkingDir:"",
> Ports:[]api.Port{api.Port{Name:"", HostPort:6380, ContainerPort:6379,
> Protocol:""}}, Env:[]api.EnvVar(nil), Memory:0, CPU:0,
> VolumeMounts:[]api.VolumeMount(nil)}}, Id:""}, Status:"", Host:"",
> HostIP:"", Info:interface {}(nil)},
> CurrentState:api.PodState{Manifest:api.ContainerManifest{Version:"",
> Volumes:[]api.Volume(nil), Containers:[]api.Container(nil), Id:""},
> Status:"", Host:"e2e-test-thockin-minion-2.c.thockin-dev.internal",
> HostIP:"", Info:interface {}(nil)}}}}
>
>
> On Sun, Jun 29, 2014 at 1:47 PM, Daniel Smith <notifications@github.com>
> wrote:
>
>> In api/examples/pod-list.json:
>>
>> > @@ -8,6 +8,8 @@
>> >              },
>> >              "desiredState": {
>> >                "manifest": {
>> > +                "version": "v1beta1",
>> > +                "id": "my-pod-1",
>>
>> Ah-- specifically, I'm thinking it'll fail due to the ID requirement.
>>
>> --
>> Reply to this email directly or view it on GitHub
>> <https://github.com/GoogleCloudPlatform/kubernetes/pull/280/files#r14331472>
>> .
>>
>
>