From 141475af86182d1e3a120e1d9c8b5e31e661d4b5 Mon Sep 17 00:00:00 2001 From: Shashank Ram Date: Mon, 7 Jun 2021 15:26:24 -0700 Subject: [PATCH] utils/proto: add unit test and remove duplicated code Adds a unit test for ProtoToYAML and directly leverages the yaml pkg to perform JSON -> YAML conversions. Signed-off-by: Shashank Ram --- go.mod | 1 + pkg/utils/proto.go | 23 +--------- pkg/utils/proto_test.go | 98 +++++++++++++++++++++++++++++++++++++++++ 3 files changed, 101 insertions(+), 21 deletions(-) create mode 100644 pkg/utils/proto_test.go diff --git a/go.mod b/go.mod index 58395dcefb..0a6c0038c3 100644 --- a/go.mod +++ b/go.mod @@ -12,6 +12,7 @@ require ( github.com/dustin/go-humanize v1.0.0 github.com/envoyproxy/go-control-plane v0.9.9 github.com/fatih/color v1.10.0 + github.com/ghodss/yaml v1.0.0 github.com/go-logr/logr v0.2.1 // indirect github.com/golang/mock v1.4.1 github.com/golang/protobuf v1.4.3 diff --git a/pkg/utils/proto.go b/pkg/utils/proto.go index 2465318ae4..a79f685b83 100644 --- a/pkg/utils/proto.go +++ b/pkg/utils/proto.go @@ -1,9 +1,9 @@ package utils import ( + "github.com/ghodss/yaml" "google.golang.org/protobuf/encoding/protojson" "google.golang.org/protobuf/reflect/protoreflect" - yaml "gopkg.in/yaml.v2" ) // ProtoToYAML converts a Proto message to it's YAML representation in bytes @@ -16,29 +16,10 @@ func ProtoToYAML(m protoreflect.ProtoMessage) ([]byte, error) { return nil, err } - configYAML, err := jsonToYAML(configJSON) + configYAML, err := yaml.JSONToYAML(configJSON) if err != nil { log.Error().Err(err).Msgf("Error marshaling xDS struct into YAML") return nil, err } return configYAML, err } - -// jsonToYAML converts a JSON representation in bytes to the corresponding YAML representation in bytes -// Reference impl taken from https://github.com/ghodss/yaml/blob/master/yaml.go#L87 -func jsonToYAML(jb []byte) ([]byte, error) { - // Convert the JSON to an object. - var jsonObj interface{} - // 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 unmarshalling 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([]byte(jb), &jsonObj) - if err != nil { - return nil, err - } - - // Marshal this object into YAML. - return yaml.Marshal(jsonObj) -} diff --git a/pkg/utils/proto_test.go b/pkg/utils/proto_test.go new file mode 100644 index 0000000000..e471de23ab --- /dev/null +++ b/pkg/utils/proto_test.go @@ -0,0 +1,98 @@ +package utils + +import ( + "testing" + "time" + + xds_cluster "github.com/envoyproxy/go-control-plane/envoy/config/cluster/v3" + xds_core "github.com/envoyproxy/go-control-plane/envoy/config/core/v3" + xds_endpoint "github.com/envoyproxy/go-control-plane/envoy/config/endpoint/v3" + xds_transport_sockets "github.com/envoyproxy/go-control-plane/envoy/extensions/transport_sockets/tls/v3" + "github.com/golang/protobuf/ptypes" + "github.com/golang/protobuf/ptypes/wrappers" + tassert "github.com/stretchr/testify/assert" + "google.golang.org/protobuf/reflect/protoreflect" +) + +func TestProtoToYAML(t *testing.T) { + assert := tassert.New(t) + + testCases := []struct { + name string + proto protoreflect.ProtoMessage + expectedYAML string + }{ + { + name: "XDS cluster proto", + proto: &xds_cluster.Cluster{ + TransportSocketMatches: nil, + Name: "foo", + AltStatName: "foo", + ClusterDiscoveryType: &xds_cluster.Cluster_Type{Type: xds_cluster.Cluster_STATIC}, + EdsClusterConfig: nil, + ConnectTimeout: ptypes.DurationProto(1 * time.Second), + LoadAssignment: &xds_endpoint.ClusterLoadAssignment{ + ClusterName: "foo", + Endpoints: []*xds_endpoint.LocalityLbEndpoints{ + { + Locality: nil, + LbEndpoints: []*xds_endpoint.LbEndpoint{{ + HostIdentifier: &xds_endpoint.LbEndpoint_Endpoint{ + Endpoint: &xds_endpoint.Endpoint{ + Address: &xds_core.Address{ + Address: &xds_core.Address_SocketAddress{ + SocketAddress: &xds_core.SocketAddress{ + Protocol: xds_core.SocketAddress_TCP, + Address: "127.0.0.1", + PortSpecifier: &xds_core.SocketAddress_PortValue{ + PortValue: 80, + }, + }, + }, + }, + }, + }, + LoadBalancingWeight: &wrappers.UInt32Value{ + Value: 100, + }, + }}, + }, + }, + }, + }, + expectedYAML: `alt_stat_name: foo +connect_timeout: 1s +load_assignment: + cluster_name: foo + endpoints: + - lb_endpoints: + - endpoint: + address: + socket_address: + address: 127.0.0.1 + port_value: 80 + load_balancing_weight: 100 +name: foo +type: STATIC +`, + }, + { + name: "TLS params proto", + proto: &xds_transport_sockets.TlsParameters{ + TlsMinimumProtocolVersion: xds_transport_sockets.TlsParameters_TLSv1_2, + TlsMaximumProtocolVersion: xds_transport_sockets.TlsParameters_TLSv1_3, + }, + expectedYAML: `tls_maximum_protocol_version: TLSv1_3 +tls_minimum_protocol_version: TLSv1_2 +`, + }, + } + + for _, tc := range testCases { + t.Run(tc.name, func(t *testing.T) { + actual, err := ProtoToYAML(tc.proto) + assert.Nil(err) + assert.Equal(tc.expectedYAML, string(actual)) + }) + } +}