Skip to content

Commit 7458904

Browse files
authored
Merge pull request #117 from rchicoli/add-template-options
Add location-snippets, server-snippets and http-snippets
2 parents c63c31f + 03a7ce9 commit 7458904

File tree

11 files changed

+125
-11
lines changed

11 files changed

+125
-11
lines changed

examples/customization/README.md

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,9 @@ The table below summarizes some of the options. More options (extensions) are av
3131
| N/A | `real-ip-header` | Sets the value of the [real_ip_header](http://nginx.org/en/docs/http/ngx_http_realip_module.html#real_ip_header) directive. | `X-Real-IP`|
3232
| N/A | `real-ip-recursive` | Enables or disables the [real_ip_recursive](http://nginx.org/en/docs/http/ngx_http_realip_module.html#real_ip_recursive) directive. | `False`|
3333
| `nginx.org/server-tokens` | `server-tokens` | Enables or disables the [server_tokens](http://nginx.org/en/docs/http/ngx_http_core_module.html#server_tokens) directive. Additionally, with the NGINX Plus controller, you can specify a custom string value. The empty string value disables the emission of the “Server” field. | `True`|
34+
| N/A | `http-snippets` | Sets a custom snippet in http context. | N/A |
35+
| `nginx.org/location-snippets` | `location-snippets` | Sets a custom snippet in location context. | N/A |
36+
| `nginx.org/server-snippets` | `server-snippets` | Sets a custom snippet in server context. | N/A |
3437

3538
## Using ConfigMaps
3639

examples/customization/cafe-ingress-with-annotations.yaml

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,17 @@ metadata:
66
nginx.org/proxy-connect-timeout: "30s"
77
nginx.org/proxy-read-timeout: "20s"
88
nginx.org/client-max-body-size: "4m"
9+
nginx.org/location-snippets: |
10+
if ($ssl_client_verify = SUCCESS) {
11+
set $auth_basic off;
12+
}
13+
if ($ssl_client_verify != SUCCESS) {
14+
set $auth_basic "Restricted";
15+
}
16+
auth_basic $auth_basic;
17+
auth_basic_user_file "/var/run/secrets/nginx.org/auth-basic-file";
18+
nginx.org/server-snippets: |
19+
ssl_verify_client optional;
920
spec:
1021
rules:
1122
- host: cafe.example.com

examples/customization/nginx-config.yaml

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,3 +32,15 @@ data:
3232
real-ip-header: "proxy_protocol" # default is X-Real-IP. Sets the value of the real_ip_header directive. http://nginx.org/en/docs/http/ngx_http_realip_module.html#real_ip_header
3333
real-ip-recursive: "True" # default is "False". Enables or disables the real_ip_recursive directive. See http://nginx.org/en/docs/http/ngx_http_realip_module.html#real_ip_recursive
3434
server-tokens: "False" # default is "True". Enables or disables the server_tokens directive. See http://nginx.org/en/docs/http/ngx_http_core_module.html#server_tokens
35+
http-snippets: | # Pipe is used for multiple line snippets. Make sure the snippet is not a default value, in order to avoid duplication.
36+
map $uri $new_uri {
37+
/old.html /index.html;
38+
}
39+
server-snippets: | # No default. Pipe is used for multiple line snippets. Make sure the snippet is not a default value, in order to avoid duplication.
40+
# Old website redirect
41+
if ($new_uri) {
42+
rewrite ^ $new_uri permanent;
43+
}
44+
location-snippets: | # No default. Pipe is used for multiple line snippets. Make sure the snippet is not a default value, in order to avoid duplication.
45+
proxy_temp_path /var/nginx/proxy_temp;
46+
charset koi8-r;

nginx-controller/controller/controller.go

Lines changed: 27 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -375,14 +375,14 @@ func (lbc *LoadBalancerController) syncCfgm(key string) {
375375
if proxyReadTimeout, exists := cfgm.Data["proxy-read-timeout"]; exists {
376376
cfg.ProxyReadTimeout = proxyReadTimeout
377377
}
378-
if proxyHideHeaders, exists, err := nginx.GetMapKeyAsStringSlice(cfgm.Data, "proxy-hide-headers", cfgm); exists {
378+
if proxyHideHeaders, exists, err := nginx.GetMapKeyAsStringSlice(cfgm.Data, "proxy-hide-headers", cfgm, ","); exists {
379379
if err != nil {
380380
glog.Error(err)
381381
} else {
382382
cfg.ProxyHideHeaders = proxyHideHeaders
383383
}
384384
}
385-
if proxyPassHeaders, exists, err := nginx.GetMapKeyAsStringSlice(cfgm.Data, "proxy-pass-headers", cfgm); exists {
385+
if proxyPassHeaders, exists, err := nginx.GetMapKeyAsStringSlice(cfgm.Data, "proxy-pass-headers", cfgm, ","); exists {
386386
if err != nil {
387387
glog.Error(err)
388388
} else {
@@ -405,7 +405,7 @@ func (lbc *LoadBalancerController) syncCfgm(key string) {
405405
cfg.HTTP2 = HTTP2
406406
}
407407
}
408-
if redirectToHTTPS, exists,err := nginx.GetMapKeyAsBool(cfgm.Data, "redirect-to-https", cfgm); exists {
408+
if redirectToHTTPS, exists, err := nginx.GetMapKeyAsBool(cfgm.Data, "redirect-to-https", cfgm); exists {
409409
if err != nil {
410410
glog.Error(err)
411411
} else {
@@ -457,7 +457,7 @@ func (lbc *LoadBalancerController) syncCfgm(key string) {
457457
if realIPHeader, exists := cfgm.Data["real-ip-header"]; exists {
458458
cfg.RealIPHeader = realIPHeader
459459
}
460-
if setRealIPFrom, exists, err := nginx.GetMapKeyAsStringSlice(cfgm.Data, "set-real-ip-from", cfgm); exists {
460+
if setRealIPFrom, exists, err := nginx.GetMapKeyAsStringSlice(cfgm.Data, "set-real-ip-from", cfgm, ","); exists {
461461
if err != nil {
462462
glog.Error(err)
463463
} else {
@@ -515,6 +515,29 @@ func (lbc *LoadBalancerController) syncCfgm(key string) {
515515
if proxyMaxTempFileSize, exists := cfgm.Data["proxy-max-temp-file-size"]; exists {
516516
cfg.ProxyMaxTempFileSize = proxyMaxTempFileSize
517517
}
518+
519+
if mainHTTPSnippets, exists, err := nginx.GetMapKeyAsStringSlice(cfgm.Data, "http-snippets", cfgm, "\n"); exists {
520+
if err != nil {
521+
glog.Error(err)
522+
} else {
523+
cfg.MainHTTPSnippets = mainHTTPSnippets
524+
}
525+
}
526+
if locationSnippets, exists, err := nginx.GetMapKeyAsStringSlice(cfgm.Data, "location-snippets", cfgm, "\n"); exists {
527+
if err != nil {
528+
glog.Error(err)
529+
} else {
530+
cfg.LocationSnippets = locationSnippets
531+
}
532+
}
533+
if serverSnippets, exists, err := nginx.GetMapKeyAsStringSlice(cfgm.Data, "server-snippets", cfgm, "\n"); exists {
534+
if err != nil {
535+
glog.Error(err)
536+
} else {
537+
cfg.ServerSnippets = serverSnippets
538+
}
539+
}
540+
518541
}
519542
lbc.cnf.UpdateConfig(cfg)
520543

nginx-controller/nginx/config.go

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,12 +2,15 @@ package nginx
22

33
// Config holds NGINX configuration parameters
44
type Config struct {
5+
LocationSnippets []string
6+
ServerSnippets []string
57
ServerTokens bool
68
ProxyConnectTimeout string
79
ProxyReadTimeout string
810
ClientMaxBodySize string
911
HTTP2 bool
1012
RedirectToHTTPS bool
13+
MainHTTPSnippets []string
1114
MainServerNamesHashBucketSize string
1215
MainServerNamesHashMaxSize string
1316
MainLogFormat string

nginx-controller/nginx/configurator.go

Lines changed: 22 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -121,6 +121,7 @@ func (cnf *Configurator) generateNginxCfg(ingEx *IngressEx, pems map[string]stri
121121
RealIPRecursive: ingCfg.RealIPRecursive,
122122
ProxyHideHeaders: ingCfg.ProxyHideHeaders,
123123
ProxyPassHeaders: ingCfg.ProxyPassHeaders,
124+
ServerSnippets: ingCfg.ServerSnippets,
124125
}
125126

126127
if pemFile, ok := pems[serverName]; ok {
@@ -173,6 +174,7 @@ func (cnf *Configurator) generateNginxCfg(ingEx *IngressEx, pems map[string]stri
173174
RealIPRecursive: ingCfg.RealIPRecursive,
174175
ProxyHideHeaders: ingCfg.ProxyHideHeaders,
175176
ProxyPassHeaders: ingCfg.ProxyPassHeaders,
177+
ServerSnippets: ingCfg.ServerSnippets,
176178
}
177179

178180
if pemFile, ok := pems[emptyHost]; ok {
@@ -204,20 +206,36 @@ func (cnf *Configurator) createConfig(ingEx *IngressEx) Config {
204206
ingCfg.ServerTokens = serverTokens
205207
}
206208
}
209+
210+
if serverSnippets, exists, err := GetMapKeyAsStringSlice(ingEx.Ingress.Annotations, "nginx.org/server-snippets", ingEx.Ingress, "\n"); exists {
211+
if err != nil {
212+
glog.Error(err)
213+
} else {
214+
ingCfg.ServerSnippets = serverSnippets
215+
}
216+
}
217+
if locationSnippets, exists, err := GetMapKeyAsStringSlice(ingEx.Ingress.Annotations, "nginx.org/location-snippets", ingEx.Ingress, "\n"); exists {
218+
if err != nil {
219+
glog.Error(err)
220+
} else {
221+
ingCfg.LocationSnippets = locationSnippets
222+
}
223+
}
224+
207225
if proxyConnectTimeout, exists := ingEx.Ingress.Annotations["nginx.org/proxy-connect-timeout"]; exists {
208226
ingCfg.ProxyConnectTimeout = proxyConnectTimeout
209227
}
210228
if proxyReadTimeout, exists := ingEx.Ingress.Annotations["nginx.org/proxy-read-timeout"]; exists {
211229
ingCfg.ProxyReadTimeout = proxyReadTimeout
212230
}
213-
if proxyHideHeaders, exists, err := GetMapKeyAsStringSlice(ingEx.Ingress.Annotations, "nginx.org/proxy-hide-headers", ingEx.Ingress); exists {
231+
if proxyHideHeaders, exists, err := GetMapKeyAsStringSlice(ingEx.Ingress.Annotations, "nginx.org/proxy-hide-headers", ingEx.Ingress, ","); exists {
214232
if err != nil {
215233
glog.Error(err)
216234
} else {
217235
ingCfg.ProxyHideHeaders = proxyHideHeaders
218236
}
219237
}
220-
if proxyPassHeaders, exists, err := GetMapKeyAsStringSlice(ingEx.Ingress.Annotations, "nginx.org/proxy-pass-headers", ingEx.Ingress); exists {
238+
if proxyPassHeaders, exists, err := GetMapKeyAsStringSlice(ingEx.Ingress.Annotations, "nginx.org/proxy-pass-headers", ingEx.Ingress, ","); exists {
221239
if err != nil {
222240
glog.Error(err)
223241
} else {
@@ -366,6 +384,7 @@ func createLocation(path string, upstream Upstream, cfg *Config, websocket bool,
366384
ProxyBuffers: cfg.ProxyBuffers,
367385
ProxyBufferSize: cfg.ProxyBufferSize,
368386
ProxyMaxTempFileSize: cfg.ProxyMaxTempFileSize,
387+
LocationSnippets: cfg.LocationSnippets,
369388
}
370389

371390
return loc
@@ -433,6 +452,7 @@ func (cnf *Configurator) UpdateConfig(config *Config) {
433452

434453
cnf.config = config
435454
mainCfg := &NginxMainConfig{
455+
HTTPSnippets: config.MainHTTPSnippets,
436456
ServerNamesHashBucketSize: config.MainServerNamesHashBucketSize,
437457
ServerNamesHashMaxSize: config.MainServerNamesHashMaxSize,
438458
LogFormat: config.MainLogFormat,

nginx-controller/nginx/convert.go

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -40,10 +40,10 @@ func GetMapKeyAsInt(m map[string]string, key string, context apiObject) (int64,
4040
return 0, false, nil
4141
}
4242

43-
// GetMapKeyAsStringSlice tries to find and parse a key in the map as string slice splitting it on ','
44-
func GetMapKeyAsStringSlice(m map[string]string, key string, context apiObject) ([]string, bool, error) {
43+
// GetMapKeyAsStringSlice tries to find and parse a key in the map as string slice splitting it on delimiter
44+
func GetMapKeyAsStringSlice(m map[string]string, key string, context apiObject, delimiter string) ([]string, bool, error) {
4545
if str, exists := m[key]; exists {
46-
slice := strings.Split(str, ",")
46+
slice := strings.Split(str, delimiter)
4747
return slice, exists, nil
4848
}
4949
return nil, false, nil

nginx-controller/nginx/convert_test.go

Lines changed: 25 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -164,7 +164,7 @@ func TestGetMapKeyAsStringSlice(t *testing.T) {
164164
"key": "1.String,2.String,3.String",
165165
}
166166

167-
slice, exists, err := GetMapKeyAsStringSlice(configMap.Data, "key", &configMap)
167+
slice, exists, err := GetMapKeyAsStringSlice(configMap.Data, "key", &configMap, ",")
168168
if err != nil {
169169
t.Errorf("Unexpected error: %v", err)
170170
}
@@ -176,13 +176,36 @@ func TestGetMapKeyAsStringSlice(t *testing.T) {
176176
if !reflect.DeepEqual(expected, slice) {
177177
t.Errorf("Unexpected return value:\nGot: %#v\nExpected: %#v", slice, expected)
178178
}
179+
180+
}
181+
182+
func TestGetMapKeyAsStringSliceMultilineSnippets(t *testing.T) {
183+
configMap := configMap
184+
configMap.Data = map[string]string{
185+
"server-snippets": `
186+
if ($new_uri) {
187+
rewrite ^ $new_uri permanent;
188+
}`,
189+
}
190+
slice, exists, err := GetMapKeyAsStringSlice(configMap.Data, "server-snippets", &configMap, "\n")
191+
if err != nil {
192+
t.Errorf("Unexpected error: %v", err)
193+
}
194+
if !exists {
195+
t.Errorf("The key 'server-snippets' must exist in the configMap")
196+
}
197+
expected := []string{"", "\t\t\tif ($new_uri) {", "\t\t\t\trewrite ^ $new_uri permanent;", "\t\t\t}"}
198+
t.Log(expected)
199+
if !reflect.DeepEqual(expected, slice) {
200+
t.Errorf("Unexpected return value:\nGot: %#v\nExpected: %#v", slice, expected)
201+
}
179202
}
180203

181204
func TestGetMapKeyAsStringSliceNotFound(t *testing.T) {
182205
configMap := configMap
183206
configMap.Data = map[string]string{}
184207

185-
_, exists, _ := GetMapKeyAsStringSlice(configMap.Data, "key", &configMap)
208+
_, exists, _ := GetMapKeyAsStringSlice(configMap.Data, "key", &configMap, ",")
186209
if exists {
187210
t.Errorf("The key 'key' must not exist in the configMap")
188211
}

nginx-controller/nginx/ingress.tmpl

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,13 +40,24 @@ server {
4040
}
4141
{{- end}}
4242

43+
{{- if $server.ServerSnippets}}
44+
{{range $value := $server.ServerSnippets}}
45+
{{$value}}{{end}}
46+
{{- end}}
47+
4348
{{range $location := $server.Locations}}
4449
location {{$location.Path}} {
4550
proxy_http_version 1.1;
4651
{{if $location.Websocket}}
4752
proxy_set_header Upgrade $http_upgrade;
4853
proxy_set_header Connection $connection_upgrade;
4954
{{end}}
55+
56+
{{- if $location.LocationSnippets}}
57+
{{range $value := $location.LocationSnippets}}
58+
{{$value}}{{end}}
59+
{{- end}}
60+
5061
proxy_connect_timeout {{$location.ProxyConnectTimeout}};
5162
proxy_read_timeout {{$location.ProxyReadTimeout}};
5263
client_max_body_size {{$location.ClientMaxBodySize}};

nginx-controller/nginx/nginx.conf.tmpl

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,11 @@ http {
1515
include /etc/nginx/mime.types;
1616
default_type application/octet-stream;
1717

18+
{{- if .HTTPSnippets}}
19+
{{range $value := .HTTPSnippets}}
20+
{{$value}}{{end}}
21+
{{- end}}
22+
1823
{{if .LogFormat -}}
1924
log_format main '{{.LogFormat}}';
2025
{{- else -}}

0 commit comments

Comments
 (0)