Skip to content

Commit 78d1f01

Browse files
committed
Add NGINX configuration for UpstreamSettingsPolicy
1 parent fe8b4dc commit 78d1f01

File tree

12 files changed

+932
-259
lines changed

12 files changed

+932
-259
lines changed

apis/v1alpha1/policy_methods.go

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,3 +31,15 @@ func (p *ObservabilityPolicy) GetPolicyStatus() v1alpha2.PolicyStatus {
3131
func (p *ObservabilityPolicy) SetPolicyStatus(status v1alpha2.PolicyStatus) {
3232
p.Status = status
3333
}
34+
35+
func (p *UpstreamSettingsPolicy) GetTargetRefs() []v1alpha2.LocalPolicyTargetReference {
36+
return p.Spec.TargetRefs
37+
}
38+
39+
func (p *UpstreamSettingsPolicy) GetPolicyStatus() v1alpha2.PolicyStatus {
40+
return p.Status
41+
}
42+
43+
func (p *UpstreamSettingsPolicy) SetPolicyStatus(status v1alpha2.PolicyStatus) {
44+
p.Status = status
45+
}

internal/mode/static/nginx/config/generator.go

Lines changed: 13 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -6,9 +6,11 @@ import (
66
"github.com/go-logr/logr"
77

88
ngfConfig "github.com/nginxinc/nginx-gateway-fabric/internal/mode/static/config"
9+
"github.com/nginxinc/nginx-gateway-fabric/internal/mode/static/nginx/config/http"
910
"github.com/nginxinc/nginx-gateway-fabric/internal/mode/static/nginx/config/policies"
1011
"github.com/nginxinc/nginx-gateway-fabric/internal/mode/static/nginx/config/policies/clientsettings"
1112
"github.com/nginxinc/nginx-gateway-fabric/internal/mode/static/nginx/config/policies/observability"
13+
"github.com/nginxinc/nginx-gateway-fabric/internal/mode/static/nginx/config/policies/upstreamsettings"
1214
"github.com/nginxinc/nginx-gateway-fabric/internal/mode/static/nginx/file"
1315
"github.com/nginxinc/nginx-gateway-fabric/internal/mode/static/state/dataplane"
1416
)
@@ -131,7 +133,10 @@ func (g GeneratorImpl) executeConfigTemplates(
131133
) []file.File {
132134
fileBytes := make(map[string][]byte)
133135

134-
for _, execute := range g.getExecuteFuncs(generator) {
136+
upstreams := g.createUpstreams(conf.Upstreams, upstreamsettings.NewProcessor())
137+
upstreamMap := g.createUpstreamMap(upstreams)
138+
139+
for _, execute := range g.getExecuteFuncs(generator, upstreams, upstreamMap) {
135140
results := execute(conf)
136141
for _, res := range results {
137142
fileBytes[res.dest] = append(fileBytes[res.dest], res.data...)
@@ -156,12 +161,16 @@ func (g GeneratorImpl) executeConfigTemplates(
156161
return files
157162
}
158163

159-
func (g GeneratorImpl) getExecuteFuncs(generator policies.Generator) []executeFunc {
164+
func (g GeneratorImpl) getExecuteFuncs(
165+
generator policies.Generator,
166+
upstreams []http.Upstream,
167+
upstreamMap UpstreamMap,
168+
) []executeFunc {
160169
return []executeFunc{
161170
executeMainConfig,
162171
executeBaseHTTPConfig,
163-
g.newExecuteServersFunc(generator),
164-
g.executeUpstreams,
172+
g.newExecuteServersFunc(generator, upstreamMap),
173+
g.newExecuteUpstreamsFunc(upstreams),
165174
executeSplitClients,
166175
executeMaps,
167176
executeTelemetry,

internal/mode/static/nginx/config/http/config.go

Lines changed: 10 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
11
package http
22

3-
import "github.com/nginxinc/nginx-gateway-fabric/internal/mode/static/nginx/config/shared"
3+
import (
4+
"github.com/nginxinc/nginx-gateway-fabric/internal/mode/static/nginx/config/shared"
5+
)
46

57
const (
68
InternalRoutePathPrefix = "/_ngf-internal"
@@ -82,9 +84,13 @@ const (
8284

8385
// Upstream holds all configuration for an HTTP upstream.
8486
type Upstream struct {
85-
Name string
86-
ZoneSize string // format: 512k, 1m
87-
Servers []UpstreamServer
87+
Name string
88+
ZoneSize string // format: 512k, 1m
89+
KeepAliveTime string
90+
KeepAliveTimeout string
91+
Servers []UpstreamServer
92+
KeepAliveConnections int32
93+
KeepAliveRequests int32
8894
}
8995

9096
// UpstreamServer holds all configuration for an HTTP upstream server.
Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
package policies
2+
3+
// UpstreamSettingsProcessor defines an interface for an UpstreamSettingsPolicy to implement the process function.
4+
type UpstreamSettingsProcessor interface {
5+
Process(policies []Policy) UpstreamSettings
6+
}
7+
8+
// UpstreamSettings contains settings from UpstreamSettingsPolicy.
9+
type UpstreamSettings struct {
10+
ZoneSize string
11+
KeepAliveTime string
12+
KeepAliveTimeout string
13+
KeepAliveConnections int32
14+
KeepAliveRequests int32
15+
}
Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,56 @@
1+
package upstreamsettings
2+
3+
import (
4+
ngfAPI "github.com/nginxinc/nginx-gateway-fabric/apis/v1alpha1"
5+
"github.com/nginxinc/nginx-gateway-fabric/internal/mode/static/nginx/config/policies"
6+
)
7+
8+
// Processor processes UpstreamSettingsPolicies.
9+
type Processor struct{}
10+
11+
// NewProcessor returns a new instance of Processor.
12+
func NewProcessor() *Processor {
13+
return &Processor{}
14+
}
15+
16+
// Process processes policy configuration for an upstream block.
17+
func (g Processor) Process(pols []policies.Policy) policies.UpstreamSettings {
18+
return processPolicies(pols)
19+
}
20+
21+
func processPolicies(pols []policies.Policy) policies.UpstreamSettings {
22+
upstreamSettings := policies.UpstreamSettings{}
23+
24+
for _, pol := range pols {
25+
usp, ok := pol.(*ngfAPI.UpstreamSettingsPolicy)
26+
if !ok {
27+
continue
28+
}
29+
30+
// we can assume that there will be no instance of two or more policies setting the same
31+
// field for the same service
32+
if usp.Spec.ZoneSize != nil {
33+
upstreamSettings.ZoneSize = string(*usp.Spec.ZoneSize)
34+
}
35+
36+
if usp.Spec.KeepAlive != nil {
37+
if usp.Spec.KeepAlive.Connections != nil {
38+
upstreamSettings.KeepAliveConnections = *usp.Spec.KeepAlive.Connections
39+
}
40+
41+
if usp.Spec.KeepAlive.Requests != nil {
42+
upstreamSettings.KeepAliveRequests = *usp.Spec.KeepAlive.Requests
43+
}
44+
45+
if usp.Spec.KeepAlive.Time != nil {
46+
upstreamSettings.KeepAliveTime = string(*usp.Spec.KeepAlive.Time)
47+
}
48+
49+
if usp.Spec.KeepAlive.Timeout != nil {
50+
upstreamSettings.KeepAliveTimeout = string(*usp.Spec.KeepAlive.Timeout)
51+
}
52+
}
53+
}
54+
55+
return upstreamSettings
56+
}
Lines changed: 166 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,166 @@
1+
package upstreamsettings
2+
3+
import (
4+
"testing"
5+
6+
. "github.com/onsi/gomega"
7+
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
8+
9+
ngfAPI "github.com/nginxinc/nginx-gateway-fabric/apis/v1alpha1"
10+
"github.com/nginxinc/nginx-gateway-fabric/internal/framework/helpers"
11+
"github.com/nginxinc/nginx-gateway-fabric/internal/mode/static/nginx/config/policies"
12+
)
13+
14+
func TestProcess(t *testing.T) {
15+
t.Parallel()
16+
17+
tests := []struct {
18+
name string
19+
expUpstreamSettings policies.UpstreamSettings
20+
policies []policies.Policy
21+
}{
22+
{
23+
name: "all fields populated",
24+
policies: []policies.Policy{
25+
&ngfAPI.UpstreamSettingsPolicy{
26+
ObjectMeta: metav1.ObjectMeta{
27+
Name: "usp",
28+
Namespace: "test",
29+
},
30+
Spec: ngfAPI.UpstreamSettingsPolicySpec{
31+
ZoneSize: helpers.GetPointer[ngfAPI.Size]("2m"),
32+
KeepAlive: helpers.GetPointer(ngfAPI.UpstreamKeepAlive{
33+
Connections: helpers.GetPointer(int32(1)),
34+
Requests: helpers.GetPointer(int32(1)),
35+
Time: helpers.GetPointer[ngfAPI.Duration]("5s"),
36+
Timeout: helpers.GetPointer[ngfAPI.Duration]("10s"),
37+
}),
38+
},
39+
},
40+
},
41+
expUpstreamSettings: policies.UpstreamSettings{
42+
ZoneSize: "2m",
43+
KeepAliveConnections: 1,
44+
KeepAliveRequests: 1,
45+
KeepAliveTime: "5s",
46+
KeepAliveTimeout: "10s",
47+
},
48+
},
49+
{
50+
name: "zoneSize set",
51+
policies: []policies.Policy{
52+
&ngfAPI.UpstreamSettingsPolicy{
53+
ObjectMeta: metav1.ObjectMeta{
54+
Name: "usp",
55+
Namespace: "test",
56+
},
57+
Spec: ngfAPI.UpstreamSettingsPolicySpec{
58+
ZoneSize: helpers.GetPointer[ngfAPI.Size]("2m"),
59+
},
60+
},
61+
},
62+
expUpstreamSettings: policies.UpstreamSettings{
63+
ZoneSize: "2m",
64+
},
65+
},
66+
{
67+
name: "keepAlive Connections set",
68+
policies: []policies.Policy{
69+
&ngfAPI.UpstreamSettingsPolicy{
70+
ObjectMeta: metav1.ObjectMeta{
71+
Name: "usp",
72+
Namespace: "test",
73+
},
74+
Spec: ngfAPI.UpstreamSettingsPolicySpec{
75+
KeepAlive: helpers.GetPointer(ngfAPI.UpstreamKeepAlive{
76+
Connections: helpers.GetPointer(int32(1)),
77+
}),
78+
},
79+
},
80+
},
81+
expUpstreamSettings: policies.UpstreamSettings{
82+
KeepAliveConnections: 1,
83+
},
84+
},
85+
{
86+
name: "keepAlive Requests set",
87+
policies: []policies.Policy{
88+
&ngfAPI.UpstreamSettingsPolicy{
89+
ObjectMeta: metav1.ObjectMeta{
90+
Name: "usp",
91+
Namespace: "test",
92+
},
93+
Spec: ngfAPI.UpstreamSettingsPolicySpec{
94+
KeepAlive: helpers.GetPointer(ngfAPI.UpstreamKeepAlive{
95+
Requests: helpers.GetPointer(int32(1)),
96+
}),
97+
},
98+
},
99+
},
100+
expUpstreamSettings: policies.UpstreamSettings{
101+
KeepAliveRequests: 1,
102+
},
103+
},
104+
{
105+
name: "keepAlive Time set",
106+
policies: []policies.Policy{
107+
&ngfAPI.UpstreamSettingsPolicy{
108+
ObjectMeta: metav1.ObjectMeta{
109+
Name: "usp",
110+
Namespace: "test",
111+
},
112+
Spec: ngfAPI.UpstreamSettingsPolicySpec{
113+
KeepAlive: helpers.GetPointer(ngfAPI.UpstreamKeepAlive{
114+
Time: helpers.GetPointer[ngfAPI.Duration]("5s"),
115+
}),
116+
},
117+
},
118+
},
119+
expUpstreamSettings: policies.UpstreamSettings{
120+
KeepAliveTime: "5s",
121+
},
122+
},
123+
{
124+
name: "keepAlive Timeout set",
125+
policies: []policies.Policy{
126+
&ngfAPI.UpstreamSettingsPolicy{
127+
ObjectMeta: metav1.ObjectMeta{
128+
Name: "usp",
129+
Namespace: "test",
130+
},
131+
Spec: ngfAPI.UpstreamSettingsPolicySpec{
132+
KeepAlive: helpers.GetPointer(ngfAPI.UpstreamKeepAlive{
133+
Timeout: helpers.GetPointer[ngfAPI.Duration]("10s"),
134+
}),
135+
},
136+
},
137+
},
138+
expUpstreamSettings: policies.UpstreamSettings{
139+
KeepAliveTimeout: "10s",
140+
},
141+
},
142+
{
143+
name: "no fields populated",
144+
policies: []policies.Policy{
145+
&ngfAPI.UpstreamSettingsPolicy{
146+
ObjectMeta: metav1.ObjectMeta{
147+
Name: "usp",
148+
Namespace: "test",
149+
},
150+
Spec: ngfAPI.UpstreamSettingsPolicySpec{},
151+
},
152+
},
153+
expUpstreamSettings: policies.UpstreamSettings{},
154+
},
155+
}
156+
157+
for _, test := range tests {
158+
t.Run(test.name, func(t *testing.T) {
159+
t.Parallel()
160+
g := NewWithT(t)
161+
processor := NewProcessor()
162+
163+
g.Expect(processor.Process(test.policies)).To(Equal(test.expUpstreamSettings))
164+
})
165+
}
166+
}

0 commit comments

Comments
 (0)