// Copyright (c) HashiCorp, Inc.
// SPDX-License-Identifier: MPL-2.0
package api
import (
"testing"
"time"
"github.com/stretchr/testify/require"
)
func TestAPI_ConfigEntries_IngressGateway ( t * testing . T ) {
t . Parallel ( )
c , s := makeClient ( t )
defer s . Stop ( )
config_entries := c . ConfigEntries ( )
ingress1 := & IngressGatewayConfigEntry {
Kind : IngressGateway ,
Name : "foo" ,
Meta : map [ string ] string {
"foo" : "bar" ,
"gir" : "zim" ,
} ,
}
ingress2 := & IngressGatewayConfigEntry {
Kind : IngressGateway ,
Name : "bar" ,
TLS : GatewayTLSConfig {
Enabled : true ,
TLSMinVersion : "TLSv1_2" ,
} ,
Defaults : & IngressServiceConfig {
MaxConnections : uint32Pointer ( 2048 ) ,
MaxPendingRequests : uint32Pointer ( 4096 ) ,
PassiveHealthCheck : & PassiveHealthCheck {
MaxFailures : 20 ,
Interval : 500000000 ,
} ,
} ,
}
global := & ProxyConfigEntry {
Kind : ProxyDefaults ,
Name : ProxyConfigGlobal ,
Config : map [ string ] interface { } {
"protocol" : "http" ,
} ,
}
// set default protocol to http so that ingress gateways pass validation
_ , wm , err := config_entries . Set ( global , nil )
require . NoError ( t , err )
require . NotNil ( t , wm )
require . NotEqual ( t , 0 , wm . RequestTime )
// set it
_ , wm , err = config_entries . Set ( ingress1 , nil )
require . NoError ( t , err )
require . NotNil ( t , wm )
require . NotEqual ( t , 0 , wm . RequestTime )
// also set the second one
_ , wm , err = config_entries . Set ( ingress2 , nil )
require . NoError ( t , err )
require . NotNil ( t , wm )
require . NotEqual ( t , 0 , wm . RequestTime )
// get it
entry , qm , err := config_entries . Get ( IngressGateway , "foo" , nil )
require . NoError ( t , err )
require . NotNil ( t , qm )
require . NotEqual ( t , 0 , qm . RequestTime )
// verify it
readIngress , ok := entry . ( * IngressGatewayConfigEntry )
require . True ( t , ok )
require . Equal ( t , ingress1 . Kind , readIngress . Kind )
require . Equal ( t , ingress1 . Name , readIngress . Name )
require . Equal ( t , ingress1 . Meta , readIngress . Meta )
require . Equal ( t , ingress1 . Meta , readIngress . GetMeta ( ) )
// update it
ingress1 . Listeners = [ ] IngressListener {
{
Port : 2222 ,
Protocol : "http" ,
Services : [ ] IngressService {
{
Name : "asdf" ,
Hosts : [ ] string { "test.example.com" } ,
RequestHeaders : & HTTPHeaderModifiers {
Set : map [ string ] string {
"x-foo" : "bar" ,
} ,
} ,
ResponseHeaders : & HTTPHeaderModifiers {
Remove : [ ] string { "x-foo" } ,
} ,
TLS : & GatewayServiceTLSConfig {
SDS : & GatewayTLSSDSConfig {
ClusterName : "foo" ,
CertResource : "bar" ,
} ,
} ,
MaxConnections : uint32Pointer ( 5120 ) ,
MaxPendingRequests : uint32Pointer ( 512 ) ,
MaxConcurrentRequests : uint32Pointer ( 2048 ) ,
PassiveHealthCheck : & PassiveHealthCheck {
MaxFailures : 10 ,
} ,
} ,
} ,
TLS : & GatewayTLSConfig {
SDS : & GatewayTLSSDSConfig {
ClusterName : "baz" ,
CertResource : "qux" ,
} ,
} ,
} ,
}
ingress1 . TLS = GatewayTLSConfig {
SDS : & GatewayTLSSDSConfig {
ClusterName : "qux" ,
CertResource : "bug" ,
} ,
}
// CAS fail
written , _ , err := config_entries . CAS ( ingress1 , 0 , nil )
require . NoError ( t , err )
require . False ( t , written )
// CAS success
written , wm , err = config_entries . CAS ( ingress1 , readIngress . ModifyIndex , nil )
require . NoError ( t , err )
require . NotNil ( t , wm )
require . NotEqual ( t , 0 , wm . RequestTime )
require . True ( t , written )
// update no cas
ingress2 . Listeners = [ ] IngressListener {
{
Port : 3333 ,
Protocol : "http" ,
Services : [ ] IngressService {
{
Name : "qwer" ,
} ,
} ,
} ,
}
_ , wm , err = config_entries . Set ( ingress2 , nil )
require . NoError ( t , err )
require . NotNil ( t , wm )
require . NotEqual ( t , 0 , wm . RequestTime )
// list them
entries , qm , err := config_entries . List ( IngressGateway , nil )
require . NoError ( t , err )
require . NotNil ( t , qm )
require . NotEqual ( t , 0 , qm . RequestTime )
require . Len ( t , entries , 2 )
for _ , entry = range entries {
switch entry . GetName ( ) {
case "foo" :
// this also verifies that the update value was persisted and
// the updated values are seen
readIngress , ok = entry . ( * IngressGatewayConfigEntry )
require . True ( t , ok )
require . Equal ( t , ingress1 . Kind , readIngress . Kind )
require . Equal ( t , ingress1 . Name , readIngress . Name )
require . Len ( t , readIngress . Listeners , 1 )
require . Len ( t , readIngress . Listeners [ 0 ] . Services , 1 )
// Set namespace and partition to blank so that CE and ent can utilize the same tests
readIngress . Listeners [ 0 ] . Services [ 0 ] . Namespace = ""
readIngress . Listeners [ 0 ] . Services [ 0 ] . Partition = ""
require . Equal ( t , ingress1 . Listeners , readIngress . Listeners )
case "bar" :
readIngress , ok = entry . ( * IngressGatewayConfigEntry )
require . True ( t , ok )
require . Equal ( t , ingress2 . Kind , readIngress . Kind )
require . Equal ( t , ingress2 . Name , readIngress . Name )
require . Equal ( t , * ingress2 . Defaults . MaxConnections , * readIngress . Defaults . MaxConnections )
require . Equal ( t , uint32 ( 4096 ) , * readIngress . Defaults . MaxPendingRequests )
require . Equal ( t , uint32 ( 0 ) , * readIngress . Defaults . MaxConcurrentRequests )
require . Equal ( t , uint32 ( 20 ) , readIngress . Defaults . PassiveHealthCheck . MaxFailures )
require . Equal ( t , time . Duration ( 500000000 ) , readIngress . Defaults . PassiveHealthCheck . Interval )
require . Nil ( t , readIngress . Defaults . PassiveHealthCheck . EnforcingConsecutive5xx )
require . Len ( t , readIngress . Listeners , 1 )
require . Len ( t , readIngress . Listeners [ 0 ] . Services , 1 )
// Set namespace and partition to blank so that CE and ent can utilize the same tests
readIngress . Listeners [ 0 ] . Services [ 0 ] . Namespace = ""
readIngress . Listeners [ 0 ] . Services [ 0 ] . Partition = ""
require . Equal ( t , ingress2 . Listeners , readIngress . Listeners )
}
}
// delete it
wm , err = config_entries . Delete ( IngressGateway , "foo" , nil )
require . NoError ( t , err )
require . NotNil ( t , wm )
require . NotEqual ( t , 0 , wm . RequestTime )
// verify deletion
_ , _ , err = config_entries . Get ( IngressGateway , "foo" , nil )
require . Error ( t , err )
}
func TestAPI_ConfigEntries_TerminatingGateway ( t * testing . T ) {
t . Parallel ( )
c , s := makeClient ( t )
defer s . Stop ( )
configEntries := c . ConfigEntries ( )
terminating1 := & TerminatingGatewayConfigEntry {
Kind : TerminatingGateway ,
Name : "foo" ,
Meta : map [ string ] string {
"foo" : "bar" ,
"gir" : "zim" ,
} ,
}
terminating2 := & TerminatingGatewayConfigEntry {
Kind : TerminatingGateway ,
Name : "bar" ,
}
// set it
_ , wm , err := configEntries . Set ( terminating1 , nil )
require . NoError ( t , err )
require . NotNil ( t , wm )
require . NotEqual ( t , 0 , wm . RequestTime )
// also set the second one
_ , wm , err = configEntries . Set ( terminating2 , nil )
require . NoError ( t , err )
require . NotNil ( t , wm )
require . NotEqual ( t , 0 , wm . RequestTime )
// get it
entry , qm , err := configEntries . Get ( TerminatingGateway , "foo" , nil )
require . NoError ( t , err )
require . NotNil ( t , qm )
require . NotEqual ( t , 0 , qm . RequestTime )
// verify it
readTerminating , ok := entry . ( * TerminatingGatewayConfigEntry )
require . True ( t , ok )
require . Equal ( t , terminating1 . Kind , readTerminating . Kind )
require . Equal ( t , terminating1 . Name , readTerminating . Name )
require . Equal ( t , terminating1 . Meta , readTerminating . Meta )
require . Equal ( t , terminating1 . Meta , readTerminating . GetMeta ( ) )
// update it
terminating1 . Services = [ ] LinkedService {
{
Name : "web" ,
CAFile : "/etc/web/ca.crt" ,
CertFile : "/etc/web/client.crt" ,
KeyFile : "/etc/web/tls.key" ,
SNI : "mydomain" ,
} ,
}
// CAS fail
written , _ , err := configEntries . CAS ( terminating1 , 0 , nil )
require . NoError ( t , err )
require . False ( t , written )
// CAS success
written , wm , err = configEntries . CAS ( terminating1 , readTerminating . ModifyIndex , nil )
require . NoError ( t , err )
require . NotNil ( t , wm )
require . NotEqual ( t , 0 , wm . RequestTime )
require . True ( t , written )
// re-setting should not yield an error
_ , wm , err = configEntries . Set ( terminating1 , nil )
require . NoError ( t , err )
require . NotNil ( t , wm )
require . NotEqual ( t , 0 , wm . RequestTime )
terminating2 . Services = [ ] LinkedService {
{
Name : "*" ,
CAFile : "/etc/certs/ca.crt" ,
CertFile : "/etc/certs/client.crt" ,
KeyFile : "/etc/certs/tls.key" ,
SNI : "mydomain" ,
} ,
}
_ , wm , err = configEntries . Set ( terminating2 , nil )
require . NoError ( t , err )
require . NotNil ( t , wm )
require . NotEqual ( t , 0 , wm . RequestTime )
// list them
entries , qm , err := configEntries . List ( TerminatingGateway , nil )
require . NoError ( t , err )
require . NotNil ( t , qm )
require . NotEqual ( t , 0 , qm . RequestTime )
require . Len ( t , entries , 2 )
for _ , entry = range entries {
switch entry . GetName ( ) {
case "foo" :
// this also verifies that the update value was persisted and
// the updated values are seen
readTerminating , ok = entry . ( * TerminatingGatewayConfigEntry )
require . True ( t , ok )
require . Equal ( t , terminating1 . Kind , readTerminating . Kind )
require . Equal ( t , terminating1 . Name , readTerminating . Name )
require . Len ( t , readTerminating . Services , 1 )
// Set namespace to blank so that CE and ent can utilize the same tests
readTerminating . Services [ 0 ] . Namespace = ""
require . Equal ( t , terminating1 . Services , readTerminating . Services )
case "bar" :
readTerminating , ok = entry . ( * TerminatingGatewayConfigEntry )
require . True ( t , ok )
require . Equal ( t , terminating2 . Kind , readTerminating . Kind )
require . Equal ( t , terminating2 . Name , readTerminating . Name )
require . Len ( t , readTerminating . Services , 1 )
// Set namespace to blank so that CE and ent can utilize the same tests
readTerminating . Services [ 0 ] . Namespace = ""
require . Equal ( t , terminating2 . Services , readTerminating . Services )
}
}
// delete it
wm , err = configEntries . Delete ( TerminatingGateway , "foo" , nil )
require . NoError ( t , err )
require . NotNil ( t , wm )
require . NotEqual ( t , 0 , wm . RequestTime )
// verify deletion
_ , _ , err = configEntries . Get ( TerminatingGateway , "foo" , nil )
require . Error ( t , err )
}
func TestAPI_ConfigEntries_APIGateway ( t * testing . T ) {
t . Parallel ( )
c , s := makeClient ( t )
defer s . Stop ( )
configEntries := c . ConfigEntries ( )
listener1 := APIGatewayListener {
Name : "listener1" ,
Hostname : "host.com" ,
Port : 3360 ,
Protocol : "http" ,
}
listener2 := APIGatewayListener {
Name : "listener2" ,
Hostname : "host2.com" ,
Port : 3362 ,
Protocol : "http" ,
}
apigw1 := & APIGatewayConfigEntry {
Kind : APIGateway ,
Name : "foo" ,
Meta : map [ string ] string {
"foo" : "bar" ,
"gir" : "zim" ,
} ,
Listeners : [ ] APIGatewayListener { listener1 } ,
}
apigw2 := & APIGatewayConfigEntry {
Kind : APIGateway ,
Name : "bar" ,
Listeners : [ ] APIGatewayListener { listener2 } ,
}
// set it
_ , wm , err := configEntries . Set ( apigw1 , nil )
require . NoError ( t , err )
require . NotNil ( t , wm )
require . NotEqual ( t , 0 , wm . RequestTime )
// also set the second one
_ , wm , err = configEntries . Set ( apigw2 , nil )
require . NoError ( t , err )
require . NotNil ( t , wm )
require . NotEqual ( t , 0 , wm . RequestTime )
// get it
entry , qm , err := configEntries . Get ( APIGateway , "foo" , nil )
require . NoError ( t , err )
require . NotNil ( t , qm )
require . NotEqual ( t , 0 , qm . RequestTime )
// verify it
readGW , ok := entry . ( * APIGatewayConfigEntry )
require . True ( t , ok )
require . Equal ( t , apigw1 . Kind , readGW . Kind )
require . Equal ( t , apigw1 . Name , readGW . Name )
require . Equal ( t , apigw1 . Meta , readGW . Meta )
require . Equal ( t , apigw1 . Meta , readGW . GetMeta ( ) )
// update it
apigw1 . Listeners = [ ] APIGatewayListener {
listener1 ,
{
Name : "listener3" ,
Hostname : "host3.com" ,
Port : 3363 ,
Protocol : "http" ,
} ,
}
// CAS fail
written , _ , err := configEntries . CAS ( apigw1 , 0 , nil )
require . NoError ( t , err )
require . False ( t , written )
// CAS success
written , wm , err = configEntries . CAS ( apigw1 , readGW . ModifyIndex , nil )
require . NoError ( t , err )
require . NotNil ( t , wm )
require . NotEqual ( t , 0 , wm . RequestTime )
require . True ( t , written )
// re-setting should not yield an error
_ , wm , err = configEntries . Set ( apigw1 , nil )
require . NoError ( t , err )
require . NotNil ( t , wm )
require . NotEqual ( t , 0 , wm . RequestTime )
apigw2 . Listeners = [ ] APIGatewayListener {
listener2 ,
{
Name : "listener4" ,
Hostname : "host4.com" ,
Port : 3364 ,
Protocol : "http" ,
} ,
}
_ , wm , err = configEntries . Set ( apigw2 , nil )
require . NoError ( t , err )
require . NotNil ( t , wm )
require . NotEqual ( t , 0 , wm . RequestTime )
// list them
entries , qm , err := configEntries . List ( APIGateway , nil )
require . NoError ( t , err )
require . NotNil ( t , qm )
require . NotEqual ( t , 0 , qm . RequestTime )
require . Len ( t , entries , 2 )
for _ , entry = range entries {
switch entry . GetName ( ) {
case "foo" :
// this also verifies that the update value was persisted and
// the updated values are seen
readGW , ok = entry . ( * APIGatewayConfigEntry )
require . True ( t , ok )
require . Equal ( t , apigw1 . Kind , readGW . Kind )
require . Equal ( t , apigw1 . Name , readGW . Name )
require . Len ( t , readGW . Listeners , 2 )
require . Equal ( t , apigw1 . Listeners , readGW . Listeners )
case "bar" :
readGW , ok = entry . ( * APIGatewayConfigEntry )
require . True ( t , ok )
require . Equal ( t , apigw2 . Kind , readGW . Kind )
require . Equal ( t , apigw2 . Name , readGW . Name )
require . Len ( t , readGW . Listeners , 2 )
require . Equal ( t , apigw2 . Listeners , readGW . Listeners )
}
}
// delete it
wm , err = configEntries . Delete ( APIGateway , "foo" , nil )
require . NoError ( t , err )
require . NotNil ( t , wm )
require . NotEqual ( t , 0 , wm . RequestTime )
// verify deletion
_ , _ , err = configEntries . Get ( APIGateway , "foo" , nil )
require . Error ( t , err )
}