Skip to content

Commit

Permalink
add graph to dataplane conversion
Browse files Browse the repository at this point in the history
Problem: Graph did not support TLS Route to dataplane configuration

Solution: Added the code to convert it
  • Loading branch information
sarthyparty committed Aug 7, 2024
1 parent bb8b57e commit d58e9f0
Show file tree
Hide file tree
Showing 49 changed files with 3,301 additions and 403 deletions.
1 change: 1 addition & 0 deletions .github/workflows/conformance.yml
Original file line number Diff line number Diff line change
Expand Up @@ -75,6 +75,7 @@ jobs:
run: |
ngf_prefix=ghcr.io/nginxinc/nginx-gateway-fabric
ngf_tag=${{ steps.ngf-meta.outputs.version }}
if [ ${{ inputs.enable-experimental }} == "true" ]; then export ENABLE_EXPERIMENTAL=true; fi
make generate-static-deployment PLUS_ENABLED=${{ inputs.image == 'plus' && 'true' || 'false' }} PREFIX=${ngf_prefix} TAG=${ngf_tag}
working-directory: ./tests

Expand Down
2 changes: 2 additions & 0 deletions charts/nginx-gateway-fabric/templates/clusterrole.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -72,6 +72,7 @@ rules:
- grpcroutes
{{- if .Values.nginxGateway.gwAPIExperimentalFeatures.enable }}
- backendtlspolicies
- tlsroutes
{{- end }}
verbs:
- list
Expand All @@ -85,6 +86,7 @@ rules:
- grpcroutes/status
{{- if .Values.nginxGateway.gwAPIExperimentalFeatures.enable }}
- backendtlspolicies/status
- tlsroutes/status
{{- end }}
verbs:
- update
Expand Down
2 changes: 2 additions & 0 deletions deploy/experimental-nginx-plus/deploy.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -82,6 +82,7 @@ rules:
- referencegrants
- grpcroutes
- backendtlspolicies
- tlsroutes
verbs:
- list
- watch
Expand All @@ -93,6 +94,7 @@ rules:
- gatewayclasses/status
- grpcroutes/status
- backendtlspolicies/status
- tlsroutes/status
verbs:
- update
- apiGroups:
Expand Down
2 changes: 2 additions & 0 deletions deploy/experimental/deploy.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -74,6 +74,7 @@ rules:
- referencegrants
- grpcroutes
- backendtlspolicies
- tlsroutes
verbs:
- list
- watch
Expand All @@ -85,6 +86,7 @@ rules:
- gatewayclasses/status
- grpcroutes/status
- backendtlspolicies/status
- tlsroutes/status
verbs:
- update
- apiGroups:
Expand Down
1 change: 1 addition & 0 deletions internal/framework/gatewayclass/validate.go
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ var gatewayCRDs = map[string]apiVersion{
"referencegrants.gateway.networking.k8s.io": {},
"backendtlspolicies.gateway.networking.k8s.io": {},
"grpcroutes.gateway.networking.k8s.io": {},
"tlsroutes.gateway.networking.k8s.io": {},
}

type apiVersion struct {
Expand Down
2 changes: 2 additions & 0 deletions internal/framework/kinds/kinds.go
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,8 @@ const (
HTTPRoute = "HTTPRoute"
// GRPCRoute is the GRPCRoute kind.
GRPCRoute = "GRPCRoute"
// TLSRoute is the TLSRoute kind.
TLSRoute = "TLSRoute"
)

// NGINX Gateway Fabric kinds.
Expand Down
1 change: 1 addition & 0 deletions internal/mode/static/handler.go
Original file line number Diff line number Diff line change
Expand Up @@ -249,6 +249,7 @@ func (h *eventHandlerImpl) updateStatuses(ctx context.Context, logger logr.Logge
gcReqs = status.PrepareGatewayClassRequests(graph.GatewayClass, graph.IgnoredGatewayClasses, transitionTime)
}
routeReqs := status.PrepareRouteRequests(
graph.L4Routes,
graph.Routes,
transitionTime,
h.latestReloadResult,
Expand Down
9 changes: 9 additions & 0 deletions internal/mode/static/manager.go
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ import (
metricsserver "sigs.k8s.io/controller-runtime/pkg/metrics/server"
k8spredicate "sigs.k8s.io/controller-runtime/pkg/predicate"
gatewayv1 "sigs.k8s.io/gateway-api/apis/v1"
gatewayv1alpha2 "sigs.k8s.io/gateway-api/apis/v1alpha2"
gatewayv1alpha3 "sigs.k8s.io/gateway-api/apis/v1alpha3"
gatewayv1beta1 "sigs.k8s.io/gateway-api/apis/v1beta1"

Expand Down Expand Up @@ -73,6 +74,7 @@ func init() {
utilruntime.Must(gatewayv1beta1.Install(scheme))
utilruntime.Must(gatewayv1.Install(scheme))
utilruntime.Must(gatewayv1alpha3.Install(scheme))
utilruntime.Must(gatewayv1alpha2.Install(scheme))
utilruntime.Must(apiv1.AddToScheme(scheme))
utilruntime.Must(discoveryV1.AddToScheme(scheme))
utilruntime.Must(ngfAPI.AddToScheme(scheme))
Expand Down Expand Up @@ -492,6 +494,12 @@ func registerControllers(
// https://github.com/nginxinc/nginx-gateway-fabric/issues/1545
objectType: &apiv1.ConfigMap{},
},
{
objectType: &gatewayv1alpha2.TLSRoute{},
options: []controller.Option{
controller.WithK8sPredicate(k8spredicate.GenerationChangedPredicate{}),
},
},
}
controllerRegCfgs = append(controllerRegCfgs, gwExpFeatures...)
}
Expand Down Expand Up @@ -666,6 +674,7 @@ func prepareFirstEventBatchPreparerArgs(
objectLists,
&gatewayv1alpha3.BackendTLSPolicyList{},
&apiv1.ConfigMapList{},
&gatewayv1alpha2.TLSRouteList{},
)
}

Expand Down
2 changes: 2 additions & 0 deletions internal/mode/static/manager_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ import (
"sigs.k8s.io/controller-runtime/pkg/client"
metricsserver "sigs.k8s.io/controller-runtime/pkg/metrics/server"
gatewayv1 "sigs.k8s.io/gateway-api/apis/v1"
gatewayv1alpha2 "sigs.k8s.io/gateway-api/apis/v1alpha2"
gatewayv1alpha3 "sigs.k8s.io/gateway-api/apis/v1alpha3"
gatewayv1beta1 "sigs.k8s.io/gateway-api/apis/v1beta1"

Expand Down Expand Up @@ -105,6 +106,7 @@ func TestPrepareFirstEventBatchPreparerArgs(t *testing.T) {
&ngfAPI.NginxProxyList{},
partialObjectMetadataList,
&gatewayv1alpha3.BackendTLSPolicyList{},
&gatewayv1alpha2.TLSRouteList{},
&gatewayv1.GRPCRouteList{},
&ngfAPI.ClientSettingsPolicyList{},
&ngfAPI.ObservabilityPolicyList{},
Expand Down
10 changes: 8 additions & 2 deletions internal/mode/static/nginx/config/generator_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ import (
"github.com/nginxinc/nginx-gateway-fabric/internal/mode/static/nginx/config"
"github.com/nginxinc/nginx-gateway-fabric/internal/mode/static/nginx/file"
"github.com/nginxinc/nginx-gateway-fabric/internal/mode/static/state/dataplane"
"github.com/nginxinc/nginx-gateway-fabric/internal/mode/static/state/resolver"
)

func TestGenerate(t *testing.T) {
Expand Down Expand Up @@ -62,8 +63,13 @@ func TestGenerate(t *testing.T) {
},
StreamUpstreams: []dataplane.Upstream{
{
Name: "stream_up",
Endpoints: nil,
Name: "stream_up",
Endpoints: []resolver.Endpoint{
{
Address: "1.1.1.1",
Port: 80,
},
},
},
},
BackendGroups: []dataplane.BackendGroup{bg},
Expand Down
11 changes: 4 additions & 7 deletions internal/mode/static/nginx/config/http/config.go
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
package http

import "github.com/nginxinc/nginx-gateway-fabric/internal/mode/static/nginx/config/shared"

// Server holds all configuration for an HTTP server.
type Server struct {
SSL *SSL
Expand All @@ -10,12 +12,7 @@ type Server struct {
IsDefaultHTTP bool
IsDefaultSSL bool
GRPC bool
}

// IPFamily holds the IP family configuration to be used by NGINX.
type IPFamily struct {
IPv4 bool
IPv6 bool
IsSocket bool
}

// Location holds all configuration for an HTTP location.
Expand Down Expand Up @@ -103,5 +100,5 @@ type ProxySSLVerify struct {
// ServerConfig holds configuration for an HTTP server and IP family to be used by NGINX.
type ServerConfig struct {
Servers []Server
IPFamily IPFamily
IPFamily shared.IPFamily
}
57 changes: 41 additions & 16 deletions internal/mode/static/nginx/config/maps.go
Original file line number Diff line number Diff line change
Expand Up @@ -11,12 +11,18 @@ import (

var mapsTemplate = gotemplate.Must(gotemplate.New("maps").Parse(mapsTemplateText))

// emptyStringSocket is used when the stream server has an invalid upstream. In this case, we pass the connection
// to the empty socket so that NGINX will close the connection with an error in the error log --
// no host in pass "" -- and set $status variable to 500 (logged by stream access log),
// which will indicate the problem to the user.
// https://nginx.org/en/docs/stream/ngx_stream_core_module.html#var_status
const emptyStringSocket = `""`
const (
// emptyStringSocket is used when the stream server has an invalid upstream. In this case, we pass the connection
// to the empty socket so that NGINX will close the connection with an error in the error log --
// no host in pass "" -- and set $status variable to 500 (logged by stream access log),
// which will indicate the problem to the user.
// https://nginx.org/en/docs/stream/ngx_stream_core_module.html#var_status
emptyStringSocket = `""`

// connectionClosedStreamServerSocket is used when we want to listen on a port but have no service configured,
// so we pass to this server that just returns an empty string to tell users that we are listening.
connectionClosedStreamServerSocket = "unix:/var/run/nginx/connection-closed-server.sock"
)

func executeMaps(conf dataplane.Configuration) []executeResult {
maps := buildAddHeaderMaps(append(conf.HTTPServers, conf.SSLServers...))
Expand Down Expand Up @@ -44,32 +50,44 @@ func createStreamMaps(conf dataplane.Configuration) []shared.Map {
return nil
}
portsToMap := make(map[int32]shared.Map)
portHasDefault := make(map[int32]struct{})
upstreams := make(map[string]dataplane.Upstream)

for _, u := range conf.StreamUpstreams {
upstreams[u.Name] = u
}

for _, server := range conf.TLSPassthroughServers {
streamMap, portInUse := portsToMap[server.Port]

socket := emptyStringSocket

if server.UpstreamName != "" {
if u, ok := upstreams[server.UpstreamName]; ok && server.UpstreamName != "" && len(u.Endpoints) > 0 {
socket = getSocketNameTLS(server.Port, server.Hostname)
}

if server.IsDefault {
socket = connectionClosedStreamServerSocket
}

mapParam := shared.MapParameter{
Value: server.Hostname,
Result: socket,
}

if !portInUse {
m := shared.Map{
Source: "$ssl_preread_server_name",
Variable: getTLSPassthroughVarName(server.Port),
Parameters: []shared.MapParameter{
mapParam,
},
streamMap = shared.Map{
Source: "$ssl_preread_server_name",
Variable: getTLSPassthroughVarName(server.Port),
Parameters: make([]shared.MapParameter, 0),
UseHostnames: true,
}
portsToMap[server.Port] = m
} else {
portsToMap[server.Port] = streamMap
}

// If the hostname is empty, we don't want to add an entry to the map. This case occurs when
// the gateway listener hostname is not specified
if !(server.Hostname == "") {
streamMap.Parameters = append(streamMap.Parameters, mapParam)
portsToMap[server.Port] = streamMap
}
Expand All @@ -82,6 +100,7 @@ func createStreamMaps(conf dataplane.Configuration) []shared.Map {

if server.IsDefault {
hostname = "default"
portHasDefault[server.Port] = struct{}{}
}

if portInUse {
Expand All @@ -95,7 +114,13 @@ func createStreamMaps(conf dataplane.Configuration) []shared.Map {

maps := make([]shared.Map, 0, len(portsToMap))

for _, m := range portsToMap {
for p, m := range portsToMap {
if _, ok := portHasDefault[p]; !ok {
m.Parameters = append(m.Parameters, shared.MapParameter{
Value: "default",
Result: connectionClosedStreamServerSocket,
})
}
maps = append(maps, m)
}

Expand Down
3 changes: 1 addition & 2 deletions internal/mode/static/nginx/config/maps_template.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,10 +3,9 @@ package config
const mapsTemplateText = `
{{ range $m := . }}
map {{ $m.Source }} {{ $m.Variable }} {
{{- if $m.UseHostnames -}}
{{- if $m.UseHostnames }}
hostnames;
{{ end }}
{{ range $p := $m.Parameters }}
{{ $p.Value }} {{ $p.Result }};
{{ end }}
Expand Down
Loading

0 comments on commit d58e9f0

Please sign in to comment.