From 828aed4cc8cca192e69409784e7b6062943ae19a Mon Sep 17 00:00:00 2001 From: Daniel Smith Date: Tue, 29 Jul 2014 18:06:25 -0700 Subject: [PATCH] Copy docker client structs, adding yaml/json tags. Use these in our v1beta1 package so that we can pass fuzz test encode/decode. --- pkg/api/helper_test.go | 40 ++++--- pkg/api/v1beta1/types.go | 5 +- pkg/util/fuzz.go | 4 +- .../container.go | 104 ++++++++++++++++++ 4 files changed, 136 insertions(+), 17 deletions(-) create mode 100644 third_party/src/github.com/fsouza/go-dockerclient-copiedstructs/container.go diff --git a/pkg/api/helper_test.go b/pkg/api/helper_test.go index defa5b6bede55..d39e544ad3777 100644 --- a/pkg/api/helper_test.go +++ b/pkg/api/helper_test.go @@ -24,6 +24,7 @@ import ( "testing" "github.com/GoogleCloudPlatform/kubernetes/pkg/util" + "github.com/fsouza/go-dockerclient" ) var fuzzIters = flag.Int("fuzz_iters", 3, "How many fuzzing iterations to do.") @@ -55,23 +56,28 @@ var apiObjectFuzzer = util.NewFuzzer( intstr.StrVal = util.RandString() } }, - func(p *PodInfo) { - // The docker container type doesn't survive fuzzing. - // TODO: fix this. - *p = nil + func(u64 *uint64) { + // TODO: uint64's are NOT handled right. + *u64 = util.RandUint64() >> 8 + }, + func(pb map[docker.Port][]docker.PortBinding) { + // This is necessary because keys with nil values get omitted. + // TODO: Is this a bug? + pb[docker.Port(util.RandString())] = []docker.PortBinding{ + {util.RandString(), util.RandString()}, + {util.RandString(), util.RandString()}, + } + }, + func(pm map[string]docker.PortMapping) { + // This is necessary because keys with nil values get omitted. + // TODO: Is this a bug? + pm[util.RandString()] = docker.PortMapping{ + util.RandString(): util.RandString(), + } }, ) func objDiff(a, b interface{}) string { - - // An alternate diff attempt, in case json isn't showing you - // the difference. (reflect.DeepEqual makes a distinction between - // nil and empty slices, for example.) - return util.StringDiff( - fmt.Sprintf("%#v", a), - fmt.Sprintf("%#v", b), - ) - ab, err := json.Marshal(a) if err != nil { panic("a") @@ -81,6 +87,14 @@ func objDiff(a, b interface{}) string { panic("b") } return util.StringDiff(string(ab), string(bb)) + + // An alternate diff attempt, in case json isn't showing you + // the difference. (reflect.DeepEqual makes a distinction between + // nil and empty slices, for example.) + return util.StringDiff( + fmt.Sprintf("%#v", a), + fmt.Sprintf("%#v", b), + ) } func runTest(t *testing.T, source interface{}) { diff --git a/pkg/api/v1beta1/types.go b/pkg/api/v1beta1/types.go index aa2615f022592..c2d05f797bbe6 100644 --- a/pkg/api/v1beta1/types.go +++ b/pkg/api/v1beta1/types.go @@ -19,7 +19,7 @@ package v1beta1 import ( "github.com/GoogleCloudPlatform/kubernetes/pkg/util" "github.com/GoogleCloudPlatform/kubernetes/pkg/watch" - "github.com/fsouza/go-dockerclient" + "github.com/fsouza/go-dockerclient-copiedstructs" ) // Common string formats @@ -237,7 +237,8 @@ type PodState struct { // The key of this map is the *name* of the container within the manifest; it has one // entry per container in the manifest. The value of this map is currently the output // of `docker inspect`. This output format is *not* final and should not be relied - // upon. + // upon. To allow marshalling/unmarshalling, we copied the client's structs and added + // json/yaml tags. // TODO: Make real decisions about what our info should look like. Info PodInfo `json:"info,omitempty" yaml:"info,omitempty"` RestartPolicy RestartPolicy `json:"restartpolicy,omitempty" yaml:"restartpolicy,omitempty"` diff --git a/pkg/util/fuzz.go b/pkg/util/fuzz.go index 0a1ce71f94f37..f76bcd3b89e69 100644 --- a/pkg/util/fuzz.go +++ b/pkg/util/fuzz.go @@ -109,7 +109,7 @@ func (f *Fuzzer) doFuzz(v reflect.Value) { case reflect.Map: if rand.Intn(5) > 0 { v.Set(reflect.MakeMap(v.Type())) - n := 1 + rand.Intn(10) + n := 1 + rand.Intn(2) for i := 0; i < n; i++ { key := reflect.New(v.Type().Key()).Elem() f.doFuzz(key) @@ -129,7 +129,7 @@ func (f *Fuzzer) doFuzz(v reflect.Value) { v.Set(reflect.Zero(v.Type())) case reflect.Slice: if rand.Intn(5) > 0 { - n := 1 + rand.Intn(10) + n := 1 + rand.Intn(2) v.Set(reflect.MakeSlice(v.Type(), n, n)) for i := 0; i < n; i++ { f.doFuzz(v.Index(i)) diff --git a/third_party/src/github.com/fsouza/go-dockerclient-copiedstructs/container.go b/third_party/src/github.com/fsouza/go-dockerclient-copiedstructs/container.go new file mode 100644 index 0000000000000..3e45a7547de8a --- /dev/null +++ b/third_party/src/github.com/fsouza/go-dockerclient-copiedstructs/container.go @@ -0,0 +1,104 @@ +// Copyright 2014 go-dockerclient authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +package docker + +import ( + "time" +) + +type Container struct { + ID string `yaml:"ID,omitempty" json:"ID,omitempty"` + Created time.Time `yaml:"Created,omitempty" json:"Created,omitempty"` + Path string `yaml:"Path,omitempty" json:"Path,omitempty"` + Args []string `yaml:"Args,omitempty" json:"Args,omitempty"` + Config *Config `yaml:"Config,omitempty" json:"Config,omitempty"` + State State `yaml:"State,omitempty" json:"State,omitempty"` + Image string `yaml:"Image,omitempty" json:"Image,omitempty"` + + NetworkSettings *NetworkSettings `yaml:"NetworkSettings,omitempty" json:"NetworkSettings,omitempty"` + + SysInitPath string `yaml:"SysInitPath,omitempty" json:"SysInitPath,omitempty"` + ResolvConfPath string `yaml:"ResolvConfPath,omitempty" json:"ResolvConfPath,omitempty"` + HostnamePath string `yaml:"HostnamePath,omitempty" json:"HostnamePath,omitempty"` + HostsPath string `yaml:"HostsPath,omitempty" json:"HostsPath,omitempty"` + Name string `yaml:"Name,omitempty" json:"Name,omitempty"` + Driver string `yaml:"Driver,omitempty" json:"Driver,omitempty"` + + Volumes map[string]string `yaml:"Volumes,omitempty" json:"Volumes,omitempty"` + VolumesRW map[string]bool `yaml:"VolumesRW,omitempty" json:"VolumesRW,omitempty"` + HostConfig *HostConfig `yaml:"HostConfig,omitempty" json:"HostConfig,omitempty"` +} + +type Config struct { + Hostname string `yaml:"Hostname,omitempty" json:"Hostname,omitempty"` + Domainname string `yaml:"Domainname,omitempty" json:"Domainname,omitempty"` + User string `yaml:"User,omitempty" json:"User,omitempty"` + Memory int64 `yaml:"Memory,omitempty" json:"Memory,omitempty"` + MemorySwap int64 `yaml:"MemorySwap,omitempty" json:"MemorySwap,omitempty"` + CpuShares int64 `yaml:"CpuShares,omitempty" json:"CpuShares,omitempty"` + AttachStdin bool `yaml:"AttachStdin,omitempty" json:"AttachStdin,omitempty"` + AttachStdout bool `yaml:"AttachStdout,omitempty" json:"AttachStdout,omitempty"` + AttachStderr bool `yaml:"AttachStderr,omitempty" json:"AttachStderr,omitempty"` + PortSpecs []string `yaml:"PortSpecs,omitempty" json:"PortSpecs,omitempty"` + ExposedPorts map[Port]struct{} `yaml:"ExposedPorts,omitempty" json:"ExposedPorts,omitempty"` + Tty bool `yaml:"Tty,omitempty" json:"Tty,omitempty"` + OpenStdin bool `yaml:"OpenStdin,omitempty" json:"OpenStdin,omitempty"` + StdinOnce bool `yaml:"StdinOnce,omitempty" json:"StdinOnce,omitempty"` + Env []string `yaml:"Env,omitempty" json:"Env,omitempty"` + Cmd []string `yaml:"Cmd,omitempty" json:"Cmd,omitempty"` + Dns []string `yaml:"Dns,omitempty" json:"Dns,omitempty"` + Image string `yaml:"Image,omitempty" json:"Image,omitempty"` + Volumes map[string]struct{} `yaml:"Volumes,omitempty" json:"Volumes,omitempty"` + VolumesFrom string `yaml:"VolumesFrom,omitempty" json:"VolumesFrom,omitempty"` + WorkingDir string `yaml:"WorkingDir,omitempty" json:"WorkingDir,omitempty"` + Entrypoint []string `yaml:"Entrypoint,omitempty" json:"Entrypoint,omitempty"` + NetworkDisabled bool `yaml:"NetworkDisabled,omitempty" json:"NetworkDisabled,omitempty"` +} + +type State struct { + Running bool `yaml:"Running,omitempty" json:"Running,omitempty"` + Paused bool `yaml:"Paused,omitempty" json:"Paused,omitempty"` + Pid int `yaml:"Pid,omitempty" json:"Pid,omitempty"` + ExitCode int `yaml:"ExitCode,omitempty" json:"ExitCode,omitempty"` + StartedAt time.Time `yaml:"StartedAt,omitempty" json:"StartedAt,omitempty"` + FinishedAt time.Time `yaml:"FinishedAt,omitempty" json:"FinishedAt,omitempty"` +} + +type PortBinding struct { + HostIp string `yaml:"HostIp,omitempty" json:"HostIp,omitempty"` + HostPort string `yaml:"HostPort,omitempty" json:"HostPort,omitempty"` +} + +type PortMapping map[string]string + +type NetworkSettings struct { + IPAddress string `yaml:"IPAddress,omitempty" json:"IPAddress,omitempty"` + IPPrefixLen int `yaml:"IPPrefixLen,omitempty" json:"IPPrefixLen,omitempty"` + Gateway string `yaml:"Gateway,omitempty" json:"Gateway,omitempty"` + Bridge string `yaml:"Bridge,omitempty" json:"Bridge,omitempty"` + PortMapping map[string]PortMapping `yaml:"PortMapping,omitempty" json:"PortMapping,omitempty"` + Ports map[Port][]PortBinding `yaml:"Ports,omitempty" json:"Ports,omitempty"` +} + +type KeyValuePair struct { + Key string `yaml:"Key,omitempty" json:"Key,omitempty"` + Value string `yaml:"Value,omitempty" json:"Value,omitempty"` +} + +type Port string + +type HostConfig struct { + Binds []string `yaml:"Binds,omitempty" json:"Binds,omitempty"` + ContainerIDFile string `yaml:"ContainerIDFile,omitempty" json:"ContainerIDFile,omitempty"` + LxcConf []KeyValuePair `yaml:"LxcConf,omitempty" json:"LxcConf,omitempty"` + Privileged bool `yaml:"Privileged,omitempty" json:"Privileged,omitempty"` + PortBindings map[Port][]PortBinding `yaml:"PortBindings,omitempty" json:"PortBindings,omitempty"` + Links []string `yaml:"Links,omitempty" json:"Links,omitempty"` + PublishAllPorts bool `yaml:"PublishAllPorts,omitempty" json:"PublishAllPorts,omitempty"` + Dns []string `yaml:"Dns,omitempty" json:"Dns,omitempty"` + DnsSearch []string `yaml:"DnsSearch,omitempty" json:"DnsSearch,omitempty"` + VolumesFrom []string `yaml:"VolumesFrom,omitempty" json:"VolumesFrom,omitempty"` + NetworkMode string `yaml:"NetworkMode,omitempty" json:"NetworkMode,omitempty"` +}