Skip to content

Commit

Permalink
Test crossplane
Browse files Browse the repository at this point in the history
  • Loading branch information
rikatz committed Sep 29, 2024
1 parent 00f7bfb commit 2479b96
Show file tree
Hide file tree
Showing 8 changed files with 300 additions and 57 deletions.
5 changes: 3 additions & 2 deletions internal/ingress/controller/nginx.go
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,7 @@ import (
"k8s.io/ingress-nginx/internal/ingress/controller/process"
"k8s.io/ingress-nginx/internal/ingress/controller/store"
ngx_template "k8s.io/ingress-nginx/internal/ingress/controller/template"
"k8s.io/ingress-nginx/internal/ingress/controller/template/crossplane"
"k8s.io/ingress-nginx/internal/ingress/metric"
"k8s.io/ingress-nginx/internal/ingress/status"
ing_net "k8s.io/ingress-nginx/internal/net"
Expand Down Expand Up @@ -158,7 +159,7 @@ func NewNGINXController(config *Configuration, mc metric.Collector) *NGINXContro
}

onTemplateChange := func() {
template, err := ngx_template.NewTemplate(nginx.TemplatePath)
template, err := crossplane.NewTemplate()
if err != nil {
// this error is different from the rest because it must be clear why nginx is not working
klog.ErrorS(err, "Error loading new template")
Expand All @@ -170,7 +171,7 @@ func NewNGINXController(config *Configuration, mc metric.Collector) *NGINXContro
n.syncQueue.EnqueueTask(task.GetDummyObject("template-change"))
}

ngxTpl, err := ngx_template.NewTemplate(nginx.TemplatePath)
ngxTpl, err := crossplane.NewTemplate()
if err != nil {
klog.Fatalf("Invalid NGINX configuration template: %v", err)
}
Expand Down
49 changes: 47 additions & 2 deletions internal/ingress/controller/template/crossplane/crossplane.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,10 +18,12 @@ package crossplane

import (
"bytes"
"os"

ngx_crossplane "github.com/nginxinc/nginx-go-crossplane"

"k8s.io/ingress-nginx/internal/ingress/controller/config"
"k8s.io/ingress-nginx/internal/ingress/controller/template/crossplane/extramodules"
)

/*
Expand All @@ -41,7 +43,7 @@ type Template struct {
mimeFile string
}

func NewTemplate() *Template {
func NewTemplate() (*Template, error) {
lua := ngx_crossplane.Lua{}
return &Template{
mimeFile: "/etc/nginx/mime.types",
Expand All @@ -50,7 +52,7 @@ func NewTemplate() *Template {
lua.RegisterBuilder(),
},
},
}
}, nil
}

func (c *Template) SetMimeFile(file string) {
Expand All @@ -72,5 +74,48 @@ func (c *Template) Write(conf *config.TemplateConfig) ([]byte, error) {
var buf bytes.Buffer

err := ngx_crossplane.Build(&buf, *c.config, &ngx_crossplane.BuildOptions{})
if err != nil {
return nil, err
}

lua := ngx_crossplane.Lua{}
options := ngx_crossplane.ParseOptions{
ErrorOnUnknownDirectives: true,
StopParsingOnError: true,
IgnoreDirectives: []string{"more_clear_headers",
"more_set_headers",
"opentelemetry_config",
"opentelemetry",
"opentelemetry_propagate",
"opentelemetry_trust_incoming_spans"}, // TODO: Add more_set_headers
DirectiveSources: []ngx_crossplane.MatchFunc{
ngx_crossplane.DefaultDirectivesMatchFunc,
ngx_crossplane.MatchLuaLatest,
extramodules.BrotliMatchFn,
},
LexOptions: ngx_crossplane.LexOptions{
Lexers: []ngx_crossplane.RegisterLexer{lua.RegisterLexer()},
},
}

tmpFile, err := os.CreateTemp("", "")
if err != nil {
return nil, err
}
defer func() {
_ = os.Remove(tmpFile.Name())
_ = tmpFile.Close()
}()

_, err = tmpFile.Write(buf.Bytes())
if err != nil {
return nil, err
}

_, err = ngx_crossplane.Parse(tmpFile.Name(), &options)
if err != nil {
return nil, err
}

return buf.Bytes(), err
}
Original file line number Diff line number Diff line change
Expand Up @@ -102,7 +102,8 @@ func TestCrossplaneTemplate(t *testing.T) {
require.NoError(t, err)
require.NoError(t, mimeFile.Close())

tpl := crossplane.NewTemplate()
tpl, err := crossplane.NewTemplate()
require.NoError(t, err)

t.Run("it should be able to marshall and unmarshall the default configuration", func(t *testing.T) {
tplConfig := defaultConfig()
Expand Down Expand Up @@ -190,10 +191,12 @@ func TestCrossplaneTemplate(t *testing.T) {
Backend: "somebackend",
ClientBodyBufferSize: "512k",
Proxy: proxy.Config{
ProxyBuffering: "on",
RequestBuffering: "on",
BuffersNumber: 10,
BufferSize: "1024k",
ProxyHTTPVersion: "1.1",
NextUpstream: "10.10.10.10",
},
ExternalAuth: authreq.Config{
AuthCacheDuration: []string{"60s"},
Expand Down Expand Up @@ -334,7 +337,9 @@ func TestCrossplaneTemplate(t *testing.T) {
tplConfig.Cfg.UpstreamKeepaliveTimeout = 200
tplConfig.Cfg.UpstreamKeepaliveRequests = 15

tpl = crossplane.NewTemplate()
tpl, err = crossplane.NewTemplate()
require.NoError(t, err)

tpl.SetMimeFile(mimeFile.Name())
content, err := tpl.Write(tplConfig)
require.NoError(t, err)
Expand Down
64 changes: 64 additions & 0 deletions internal/ingress/controller/template/crossplane/location.go
Original file line number Diff line number Diff line change
Expand Up @@ -338,6 +338,9 @@ func (c *Template) buildAllowedLocation(server *ingress.Server, location *ingres
buildDirective("proxy_http_version", location.Proxy.ProxyHTTPVersion),
buildDirective("proxy_cookie_domain", location.Proxy.CookieDomain),
buildDirective("proxy_cookie_path", location.Proxy.CookiePath),
buildDirective("proxy_next_upstream_timeout", location.Proxy.NextUpstreamTimeout),
buildDirective("proxy_next_upstream_tries", location.Proxy.NextUpstreamTries),
buildDirective("proxy_next_upstream", buildNextUpstream(location.Proxy.NextUpstream, c.tplConfig.Cfg.RetryNonIdempotent)),
)

if isValidByteSize(location.Proxy.ProxyMaxTempFileSize, true) {
Expand All @@ -364,6 +367,67 @@ func (c *Template) buildAllowedLocation(server *ingress.Server, location *ingres
dir = append(dir, buildDirective(proxySetHeader, k, v))
}

for k, v := range location.CustomHeaders.Headers {
dir = append(dir, buildDirective("more_set_headers", fmt.Sprintf("%s: %s", k, strings.ReplaceAll(v, `$`, `${literal_dollar}`))))
}

if strings.HasPrefix(location.Backend, "custom-default-backend-") {
dir = append(dir,
buildDirective("proxy_set_header", "X-Code", "503"),
buildDirective("proxy_set_header", "X-Format", "$http_accept"),
buildDirective("proxy_set_header", "X-Namespace", "$namespace"),
buildDirective("proxy_set_header", "X-Ingress-Name", "$ingress_name"),
buildDirective("proxy_set_header", "X-Service-Name", "$service_name"),
buildDirective("proxy_set_header", "X-Service-Port", "$service_port"),
buildDirective("proxy_set_header", "X-Request-ID", "$req_id"),
)
}

if location.Satisfy != "" {
dir = append(dir, buildDirective("satisfy", location.Satisfy))
}

if len(location.CustomHTTPErrors) > 0 && !location.DisableProxyInterceptErrors {
dir = append(dir, buildDirective("proxy_intercept_errors", "on"))
}

for _, errorcode := range location.CustomHTTPErrors {
dir = append(dir, buildDirective(
"error_page",
errorcode, "=",
fmt.Sprintf("@custom_%s_%d", location.DefaultBackendUpstreamName, errorcode)),
)
}

switch location.BackendProtocol {
case "GRPC", "GRPCS":
dir = append(dir,
buildDirective("grpc_connect_timeout", seconds(location.Proxy.ConnectTimeout)),
buildDirective("grpc_send_timeout", seconds(location.Proxy.SendTimeout)),
buildDirective("grpc_read_timeout", seconds(location.Proxy.ReadTimeout)),
)
case "FCGI":
dir = append(dir, buildDirective("include", "/etc/nginx/fastcgi_params"))
if location.FastCGI.Index != "" {
dir = append(dir, buildDirective("fastcgi_index", location.FastCGI.Index))
}
for k, v := range location.FastCGI.Params {
dir = append(dir, buildDirective("fastcgi_param", k, v))
}
}

if location.Redirect.URL != "" {
dir = append(dir, buildDirective("return", location.Redirect.Code, location.Redirect.URL))
}

dir = append(dir, buildProxyPass(c.tplConfig.Backends, location)...)

if location.Proxy.ProxyRedirectFrom == "default" || location.Proxy.ProxyRedirectFrom == "off" {
dir = append(dir, buildDirective("proxy_redirect", location.Proxy.ProxyRedirectFrom))
} else if location.Proxy.ProxyRedirectTo != "off" {
dir = append(dir, buildDirective("proxy_redirect", location.Proxy.ProxyRedirectFrom, location.Proxy.ProxyRedirectTo))
}

return dir
}

Expand Down
59 changes: 46 additions & 13 deletions internal/ingress/controller/template/crossplane/server.go
Original file line number Diff line number Diff line change
Expand Up @@ -52,23 +52,56 @@ func (c *Template) buildServerDirective(server *ingress.Server) *ngx_crossplane.
})
serverBlock = append(serverBlock, matchCNBlock)
}
// TODO: This part should be reserved to SSL Configurations

/* MISSING (I don't know where this if ends...)
{{ if not (empty $server.AuthTLSError) }}
# {{ $server.AuthTLSError }}
return 403;
{{ else }}
*/
serverBlock = append(serverBlock, c.buildCertificateDirectives(server)...)
// END
if server.AuthTLSError != "" {
serverBlock = append(serverBlock, buildDirective("return", 403))
} else {

serverBlock = append(serverBlock, buildCustomErrorLocationsPerServer(server, c.tplConfig.EnableMetrics)...)
serverBlock = append(serverBlock, c.buildCertificateDirectives(server)...)
serverBlock = append(serverBlock, buildCustomErrorLocationsPerServer(server, c.tplConfig.EnableMetrics)...)
serverBlock = append(serverBlock, buildMirrorLocationDirective(server.Locations)...)

serverBlock = append(serverBlock, buildMirrorLocationDirective(server.Locations)...)
// The other locations should come here!
serverBlock = append(serverBlock, c.buildServerLocations(server, server.Locations)...)

// The other locations should come here!
serverBlock = append(serverBlock, c.buildServerLocations(server, server.Locations)...)
}

// "/healthz" location
if server.Hostname == "_" {
dirs := ngx_crossplane.Directives{
buildDirective("access_log", "off"),
buildDirective("return", "200"),
}
if cfg.EnableOpentelemetry {
dirs = append(dirs, buildDirective("opentelemetry", "off"))
}
healthLocation := buildBlockDirective("location",
[]string{c.tplConfig.HealthzURI}, dirs)
serverBlock = append(serverBlock, healthLocation)
}

// "/nginx_status" location
statusLocationDirs := ngx_crossplane.Directives{}
if cfg.EnableOpentelemetry {
statusLocationDirs = append(statusLocationDirs, buildDirective("opentelemetry", "off"))
}

for _, v := range c.tplConfig.NginxStatusIpv4Whitelist {
statusLocationDirs = append(statusLocationDirs, buildDirective("allow", v))
}

if c.tplConfig.IsIPV6Enabled {
for _, v := range c.tplConfig.NginxStatusIpv6Whitelist {
statusLocationDirs = append(statusLocationDirs, buildDirective("allow", v))
}
}
statusLocationDirs = append(statusLocationDirs,
buildDirective("deny", "all"),
buildDirective("access_log", "off"),
buildDirective("stub_status", "on"))

serverBlock = append(serverBlock, buildBlockDirective("location", []string{"/nginx_status"}, statusLocationDirs))
// End of "nginx_status" location

// DO NOT MOVE! THIS IS THE END DIRECTIVE OF SERVERS
serverBlock = append(serverBlock, buildCustomErrorLocation("upstream-default-backend", cfg.CustomHTTPErrors, c.tplConfig.EnableMetrics)...)
Expand Down
Loading

0 comments on commit 2479b96

Please sign in to comment.