From 7d413fb53b3ad70bcdb8f7fd2b17d78ff631226c Mon Sep 17 00:00:00 2001 From: Clayton Coleman Date: Fri, 17 Mar 2017 00:08:44 -0400 Subject: [PATCH 1/2] protobuf generation modifies types.go, which needs to be copied out This was broken when we moved to the build container, but no one noticed. We also likely have another bug, which is that protobuf should hard fail when we have fields that aren't assigned a tag. --- build/common.sh | 1 + 1 file changed, 1 insertion(+) diff --git a/build/common.sh b/build/common.sh index 055a8bcac1e..772f353000e 100755 --- a/build/common.sh +++ b/build/common.sh @@ -704,6 +704,7 @@ function kube::build::copy_output() { --filter='+ zz_generated.*' \ --filter='+ generated.proto' \ --filter='+ *.pb.go' \ + --filter='+ types.go' \ --filter='+ */' \ --filter='- /**' \ "rsync://k8s@${KUBE_RSYNC_ADDR}/k8s/" "${KUBE_ROOT}" From 6d2a3bdd60316b8713e3c8449cecd1777a07e3a6 Mon Sep 17 00:00:00 2001 From: Clayton Coleman Date: Fri, 17 Mar 2017 00:28:05 -0400 Subject: [PATCH 2/2] Add a test that verifies all structs have protobuf tags --- pkg/api/serialization_proto_test.go | 37 +++++++++++++++++++++++++++++ 1 file changed, 37 insertions(+) diff --git a/pkg/api/serialization_proto_test.go b/pkg/api/serialization_proto_test.go index 523653d16ab..ac3bbeae74f 100644 --- a/pkg/api/serialization_proto_test.go +++ b/pkg/api/serialization_proto_test.go @@ -19,7 +19,9 @@ package api_test import ( "bytes" "encoding/hex" + "fmt" "math/rand" + "reflect" "testing" "github.com/gogo/protobuf/proto" @@ -59,6 +61,41 @@ func TestUniversalDeserializer(t *testing.T) { } } +func TestAllFieldsHaveTags(t *testing.T) { + for gvk, obj := range api.Scheme.AllKnownTypes() { + if gvk.Version == runtime.APIVersionInternal { + // internal versions are not serialized to protobuf + continue + } + if gvk.Group == "componentconfig" { + // component config is not serialized to protobuf + continue + } + if err := fieldsHaveProtobufTags(obj); err != nil { + t.Errorf("type %s as gvk %v is missing tags: %v", obj, gvk, err) + } + } +} + +func fieldsHaveProtobufTags(obj reflect.Type) error { + switch obj.Kind() { + case reflect.Slice, reflect.Map, reflect.Ptr, reflect.Array: + return fieldsHaveProtobufTags(obj.Elem()) + case reflect.Struct: + for i := 0; i < obj.NumField(); i++ { + f := obj.Field(i) + if f.Name == "TypeMeta" && f.Type.Name() == "TypeMeta" { + // TypeMeta is not included in external protobuf because we use an envelope type with TypeMeta + continue + } + if len(f.Tag.Get("json")) > 0 && len(f.Tag.Get("protobuf")) == 0 { + return fmt.Errorf("field %s in %s has a 'json' tag but no protobuf tag", f.Name, obj) + } + } + } + return nil +} + func TestProtobufRoundTrip(t *testing.T) { obj := &v1.Pod{} apitesting.FuzzerFor(kapitesting.FuzzerFuncs(t, api.Codecs), rand.NewSource(benchmarkSeed)).Fuzz(obj)