Omit empty tproxy config in JSON responses (#10402)

This commit is contained in:
Freddy 2021-06-15 13:53:35 -06:00 committed by GitHub
parent b8b44419a0
commit 3ee66b2e9a
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 139 additions and 7 deletions

View File

@ -399,7 +399,7 @@ func TestAgent_Service(t *testing.T) {
Service: "web-sidecar-proxy", Service: "web-sidecar-proxy",
Port: 8000, Port: 8000,
Proxy: expectProxy.ToAPI(), Proxy: expectProxy.ToAPI(),
ContentHash: "518ece989813bc13", ContentHash: "854327a458fe02a6",
Weights: api.AgentWeights{ Weights: api.AgentWeights{
Passing: 1, Passing: 1,
Warning: 1, Warning: 1,
@ -413,7 +413,7 @@ func TestAgent_Service(t *testing.T) {
// Copy and modify // Copy and modify
updatedResponse := *expectedResponse updatedResponse := *expectedResponse
updatedResponse.Port = 9999 updatedResponse.Port = 9999
updatedResponse.ContentHash = "6cc7a4afb000afb1" updatedResponse.ContentHash = "b80a4d9370ed1104"
// Simple response for non-proxy service registered in TestAgent config // Simple response for non-proxy service registered in TestAgent config
expectWebResponse := &api.AgentService{ expectWebResponse := &api.AgentService{

View File

@ -133,12 +133,20 @@ type TransparentProxyConfig struct {
} }
func (c TransparentProxyConfig) ToAPI() *api.TransparentProxyConfig { func (c TransparentProxyConfig) ToAPI() *api.TransparentProxyConfig {
if c.IsZero() {
return nil
}
return &api.TransparentProxyConfig{ return &api.TransparentProxyConfig{
OutboundListenerPort: c.OutboundListenerPort, OutboundListenerPort: c.OutboundListenerPort,
DialedDirectly: c.DialedDirectly, DialedDirectly: c.DialedDirectly,
} }
} }
func (c *TransparentProxyConfig) IsZero() bool {
zeroVal := TransparentProxyConfig{}
return *c == zeroVal
}
// ConnectProxyConfig describes the configuration needed for any proxy managed // ConnectProxyConfig describes the configuration needed for any proxy managed
// or unmanaged. It describes a single logical service's listener and optionally // or unmanaged. It describes a single logical service's listener and optionally
// upstreams and sidecar-related config for a single instance. To describe a // upstreams and sidecar-related config for a single instance. To describe a
@ -242,16 +250,25 @@ func (t *ConnectProxyConfig) UnmarshalJSON(data []byte) (err error) {
} }
func (c *ConnectProxyConfig) MarshalJSON() ([]byte, error) { func (c *ConnectProxyConfig) MarshalJSON() ([]byte, error) {
type typeCopy ConnectProxyConfig type Alias ConnectProxyConfig
copy := typeCopy(*c) out := struct {
TransparentProxy *TransparentProxyConfig `json:",omitempty"`
Alias
}{
Alias: (Alias)(*c),
}
proxyConfig, err := lib.MapWalk(copy.Config) proxyConfig, err := lib.MapWalk(c.Config)
if err != nil { if err != nil {
return nil, err return nil, err
} }
copy.Config = proxyConfig out.Alias.Config = proxyConfig
return json.Marshal(&copy) if !c.TransparentProxy.IsZero() {
out.TransparentProxy = &out.Alias.TransparentProxy
}
return json.Marshal(&out)
} }
// ToAPI returns the api struct with the same fields. We have duplicates to // ToAPI returns the api struct with the same fields. We have duplicates to

View File

@ -94,6 +94,121 @@ func TestConnectProxyConfig_ToAPI(t *testing.T) {
} }
} }
func TestConnectProxyConfig_MarshalJSON(t *testing.T) {
tests := []struct {
name string
in ConnectProxyConfig
want string
wantErr bool
}{
{
name: "direct proxy",
in: ConnectProxyConfig{
DestinationServiceName: "api",
DestinationServiceID: "api-1",
LocalServiceAddress: "127.0.0.1",
LocalServicePort: 8080,
Mode: ProxyModeDirect,
Config: map[string]interface{}{
"connect_timeout_ms": 5000,
},
Upstreams: Upstreams{
Upstream{
DestinationType: UpstreamDestTypeService,
DestinationName: "db",
Datacenter: "dc1",
LocalBindPort: 1234,
},
},
MeshGateway: MeshGatewayConfig{Mode: MeshGatewayModeLocal},
Expose: ExposeConfig{Checks: true},
// No transparent proxy config, since proxy is set to "direct" mode.
// Field should be omitted from json output.
// TransparentProxy: TransparentProxyConfig{},
},
want: `{
"DestinationServiceName": "api",
"DestinationServiceID": "api-1",
"LocalServiceAddress": "127.0.0.1",
"LocalServicePort": 8080,
"Mode": "direct",
"Config": {
"connect_timeout_ms": 5000
},
"Upstreams": [
{
"DestinationType": "service",
"DestinationName": "db",
"Datacenter": "dc1",
"LocalBindPort": 1234,
"MeshGateway": {}
}
],
"MeshGateway": {
"Mode": "local"
},
"Expose": {
"Checks": true
}
}`,
wantErr: false,
},
{
name: "transparent proxy",
in: ConnectProxyConfig{
DestinationServiceName: "billing",
DestinationServiceID: "billing-1",
LocalServiceAddress: "127.0.0.1",
LocalServicePort: 8080,
Mode: ProxyModeTransparent,
Config: map[string]interface{}{
"connect_timeout_ms": 5000,
},
MeshGateway: MeshGatewayConfig{Mode: MeshGatewayModeLocal},
Expose: ExposeConfig{Checks: true},
TransparentProxy: TransparentProxyConfig{
DialedDirectly: true,
OutboundListenerPort: 16001,
},
},
want: `{
"DestinationServiceName": "billing",
"DestinationServiceID": "billing-1",
"LocalServiceAddress": "127.0.0.1",
"LocalServicePort": 8080,
"Mode": "transparent",
"Config": {
"connect_timeout_ms": 5000
},
"TransparentProxy": {
"DialedDirectly": true,
"OutboundListenerPort": 16001
},
"MeshGateway": {
"Mode": "local"
},
"Expose": {
"Checks": true
}
}`,
wantErr: false,
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
require := require.New(t)
got, err := tt.in.MarshalJSON()
if tt.wantErr {
require.Error(err)
return
}
require.NoError(err)
require.JSONEq(tt.want, string(got))
})
}
}
func TestUpstream_MarshalJSON(t *testing.T) { func TestUpstream_MarshalJSON(t *testing.T) {
tests := []struct { tests := []struct {
name string name string