Skip to content

Commit 7ed7f88

Browse files
committed
Use new types to process resource changes
This commit plugs in the new types introduced in 0a39e3f to process changes to resources and generate NGINX configuration.
1 parent a9f91c1 commit 7ed7f88

File tree

27 files changed

+808
-506
lines changed

27 files changed

+808
-506
lines changed

README.md

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,6 @@ Before you can build and run the NGINX Kubernetes Gateway, make sure you have th
3434

3535
Set the `PREFIX` variable to the name of the registry you'd like to push the image to. By default, the image will be named `nginx-kubernetes-gateway:0.0.1`.
3636

37-
3837
1. Push the image to your container registry:
3938

4039
```
@@ -55,7 +54,6 @@ You can deploy NGINX Kubernetes Gateway on an existing Kubernetes 1.16+ cluster.
5554

5655
Make sure to substitute the image name with the name of the image you built.
5756

58-
5957
1. Install the Gateway CRDs:
6058

6159
```
@@ -89,6 +87,11 @@ You can deploy NGINX Kubernetes Gateway on an existing Kubernetes 1.16+ cluster.
8987
NAME READY STATUS RESTARTS AGE
9088
nginx-gateway-5d4f4c7db7-xk2kq 2/2 Running 0 112s
9189
```
90+
1. Create the Gateway resource:
91+
92+
```
93+
kubectl apply -f deploy/manifests/gateway.yaml
94+
```
9295
9396
## Expose NGINX Kubernetes Gateway
9497

cmd/gateway/main.go

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ import (
55
"os"
66

77
flag "github.com/spf13/pflag"
8+
"k8s.io/apimachinery/pkg/types"
89
"sigs.k8s.io/controller-runtime/pkg/log/zap"
910

1011
"github.com/nginxinc/nginx-kubernetes-gateway/internal/config"
@@ -36,6 +37,11 @@ func main() {
3637
conf := config.Config{
3738
GatewayCtlrName: *gatewayCtlrName,
3839
Logger: logger,
40+
// FIXME(pleshakov) Allow the cluster operator to customize this value
41+
GatewayNsName: types.NamespacedName{
42+
Namespace: "nginx-gateway",
43+
Name: "gateway",
44+
},
3945
}
4046

4147
MustValidateArguments(

deploy/manifests/gateway.yaml

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,6 @@ metadata:
88
spec:
99
gatewayClassName: nginx
1010
listeners:
11-
- name: my-listener
12-
hostname: example.com
13-
port: 8080
11+
- name: http
12+
port: 80
1413
protocol: HTTP

examples/advanced-routing/cafe-routes.yaml

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,10 @@ kind: HTTPRoute
33
metadata:
44
name: cafe
55
spec:
6+
parentRefs:
7+
- name: gateway
8+
namespace: nginx-gateway
9+
sectionName: http
610
hostnames:
711
- "cafe.example.com"
812
rules:
@@ -15,6 +19,10 @@ kind: HTTPRoute
1519
metadata:
1620
name: coffee
1721
spec:
22+
parentRefs:
23+
- name: gateway
24+
namespace: nginx-gateway
25+
sectionName: http
1826
hostnames:
1927
- "cafe.example.com"
2028
rules:
@@ -37,6 +45,10 @@ kind: HTTPRoute
3745
metadata:
3846
name: tea
3947
spec:
48+
parentRefs:
49+
- name: gateway
50+
namespace: nginx-gateway
51+
sectionName: http
4052
hostnames:
4153
- "cafe.example.com"
4254
rules:

examples/cafe-example/cafe-routes.yaml

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,10 @@ kind: HTTPRoute
33
metadata:
44
name: cafe
55
spec:
6+
parentRefs:
7+
- name: gateway
8+
namespace: nginx-gateway
9+
sectionName: http
610
hostnames:
711
- "cafe.example.com"
812
rules:
@@ -15,6 +19,10 @@ kind: HTTPRoute
1519
metadata:
1620
name: coffee
1721
spec:
22+
parentRefs:
23+
- name: gateway
24+
namespace: nginx-gateway
25+
sectionName: http
1826
hostnames:
1927
- "cafe.example.com"
2028
rules:
@@ -31,6 +39,10 @@ kind: HTTPRoute
3139
metadata:
3240
name: tea
3341
spec:
42+
parentRefs:
43+
- name: gateway
44+
namespace: nginx-gateway
45+
sectionName: http
3446
hostnames:
3547
- "cafe.example.com"
3648
rules:

internal/config/config.go

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,9 +2,13 @@ package config
22

33
import (
44
"github.com/go-logr/logr"
5+
"k8s.io/apimachinery/pkg/types"
56
)
67

78
type Config struct {
89
GatewayCtlrName string
910
Logger logr.Logger
11+
// GatewayNsName is the namespaced name of a Gateway resource that the Gateway will use.
12+
// The Gateway will ignore all other Gateway resources.
13+
GatewayNsName types.NamespacedName
1014
}

internal/events/loop.go

Lines changed: 63 additions & 84 deletions
Original file line numberDiff line numberDiff line change
@@ -8,42 +8,39 @@ import (
88
apiv1 "k8s.io/api/core/v1"
99
"sigs.k8s.io/gateway-api/apis/v1alpha2"
1010

11+
"github.com/nginxinc/nginx-kubernetes-gateway/internal/newstate"
1112
"github.com/nginxinc/nginx-kubernetes-gateway/internal/nginx/config"
1213
"github.com/nginxinc/nginx-kubernetes-gateway/internal/nginx/file"
1314
"github.com/nginxinc/nginx-kubernetes-gateway/internal/nginx/runtime"
1415
"github.com/nginxinc/nginx-kubernetes-gateway/internal/state"
15-
"github.com/nginxinc/nginx-kubernetes-gateway/internal/status"
1616
)
1717

1818
// EventLoop is the main event loop of the Gateway.
1919
type EventLoop struct {
20-
conf state.Configuration
20+
processor newstate.ChangeProcessor
2121
serviceStore state.ServiceStore
2222
generator config.Generator
2323
eventCh <-chan interface{}
2424
logger logr.Logger
25-
statusUpdater status.Updater
2625
nginxFileMgr file.Manager
2726
nginxRuntimeMgr runtime.Manager
2827
}
2928

3029
// NewEventLoop creates a new EventLoop.
3130
func NewEventLoop(
32-
conf state.Configuration,
31+
processor newstate.ChangeProcessor,
3332
serviceStore state.ServiceStore,
3433
generator config.Generator,
3534
eventCh <-chan interface{},
36-
statusUpdater status.Updater,
3735
logger logr.Logger,
3836
nginxFileMgr file.Manager,
3937
nginxRuntimeMgr runtime.Manager,
4038
) *EventLoop {
4139
return &EventLoop{
42-
conf: conf,
40+
processor: processor,
4341
serviceStore: serviceStore,
4442
generator: generator,
4543
eventCh: eventCh,
46-
statusUpdater: statusUpdater,
4744
logger: logger.WithName("eventLoop"),
4845
nginxFileMgr: nginxFileMgr,
4946
nginxRuntimeMgr: nginxRuntimeMgr,
@@ -58,112 +55,94 @@ func (el *EventLoop) Start(ctx context.Context) error {
5855
for {
5956
select {
6057
case <-ctx.Done():
58+
// although we always return nil, Start must return it to satisfy
59+
// "sigs.k8s.io/controller-runtime/pkg/manager".Runnable
6160
return nil
6261
case e := <-el.eventCh:
63-
err := el.handleEvent(ctx, e)
64-
if err != nil {
65-
return err
66-
}
62+
el.handleEvent(ctx, e)
6763
}
6864
}
6965
}
7066

7167
// FIXME(pleshakov): think about how to avoid using an interface{} here
72-
func (el *EventLoop) handleEvent(ctx context.Context, event interface{}) error {
73-
var changes []state.Change
74-
var updates []state.StatusUpdate
75-
var err error
76-
68+
func (el *EventLoop) handleEvent(ctx context.Context, event interface{}) {
7769
switch e := event.(type) {
7870
case *UpsertEvent:
79-
changes, updates, err = el.propagateUpsert(e)
71+
el.propagateUpsert(e)
8072
case *DeleteEvent:
81-
changes, updates, err = el.propagateDelete(e)
73+
el.propagateDelete(e)
8274
default:
83-
// FIXME(pleshakov): panic because it is a coding error
84-
return fmt.Errorf("unknown event type %T", e)
75+
panic(fmt.Errorf("unknown event type %T", e))
76+
}
77+
78+
changed, conf, statuses := el.processor.Process()
79+
if !changed {
80+
return
8581
}
8682

83+
err := el.updateNginx(ctx, conf)
84+
if err != nil {
85+
el.logger.Error(err, "Failed to update NGINX configuration")
86+
}
87+
88+
// FIXME(pleshakov) Update resource statuses instead of printing to stdout
89+
for name, s := range statuses.ListenerStatuses {
90+
fmt.Printf("Listener %q, Statuses: %v\n", name, s)
91+
}
92+
for nsname, s := range statuses.HTTPRouteStatuses {
93+
fmt.Printf("HTTPRoute %q, Statuses: %v\n", nsname, s)
94+
}
95+
}
96+
97+
func (el *EventLoop) updateNginx(ctx context.Context, conf newstate.Configuration) error {
98+
cfg, warnings := el.generator.Generate(conf)
99+
100+
// For now, we keep all http servers in one config
101+
// We might rethink that. For example, we can write each server to its file
102+
// or group servers in some way.
103+
err := el.nginxFileMgr.WriteHTTPServersConfig("http-servers", cfg)
87104
if err != nil {
88105
return err
89106
}
90107

91-
el.processChangesAndStatusUpdates(ctx, changes, updates)
92-
return nil
108+
for obj, objWarnings := range warnings {
109+
for _, w := range objWarnings {
110+
// FIXME(pleshakov): report warnings via Object status
111+
el.logger.Info("got warning while generating config",
112+
"kind", obj.GetObjectKind().GroupVersionKind().Kind,
113+
"namespace", obj.GetNamespace(),
114+
"name", obj.GetName(),
115+
"warning", w)
116+
}
117+
}
118+
119+
return el.nginxRuntimeMgr.Reload(ctx)
93120
}
94121

95-
func (el *EventLoop) propagateUpsert(e *UpsertEvent) ([]state.Change, []state.StatusUpdate, error) {
122+
func (el *EventLoop) propagateUpsert(e *UpsertEvent) {
96123
switch r := e.Resource.(type) {
124+
case *v1alpha2.Gateway:
125+
el.processor.CaptureUpsertChange(r)
97126
case *v1alpha2.HTTPRoute:
98-
changes, statusUpdates := el.conf.UpsertHTTPRoute(r)
99-
return changes, statusUpdates, nil
127+
el.processor.CaptureUpsertChange(r)
100128
case *apiv1.Service:
101-
el.serviceStore.Upsert(r)
102129
// FIXME(pleshakov): make sure the affected hosts are updated
103-
return nil, nil, nil
130+
el.serviceStore.Upsert(r)
131+
default:
132+
panic(fmt.Errorf("unknown resource type %T", e.Resource))
104133
}
105-
106-
// FIXME(pleshakov): panic because it is a coding error
107-
return nil, nil, fmt.Errorf("unknown resource type %T", e.Resource)
108134
}
109135

110-
func (el *EventLoop) propagateDelete(e *DeleteEvent) ([]state.Change, []state.StatusUpdate, error) {
136+
func (el *EventLoop) propagateDelete(e *DeleteEvent) {
111137
switch e.Type.(type) {
138+
case *v1alpha2.Gateway:
139+
el.processor.CaptureDeleteChange(e.Type, e.NamespacedName)
112140
case *v1alpha2.HTTPRoute:
113-
changes, statusUpdates := el.conf.DeleteHTTPRoute(e.NamespacedName)
114-
return changes, statusUpdates, nil
141+
el.processor.CaptureDeleteChange(e.Type, e.NamespacedName)
115142
case *apiv1.Service:
116-
el.serviceStore.Delete(e.NamespacedName)
117143
// FIXME(pleshakov): make sure the affected hosts are updated
118-
return nil, nil, nil
119-
}
120-
121-
// FIXME(pleshakov): panic because it is a coding error
122-
return nil, nil, fmt.Errorf("unknown resource type %T", e.Type)
123-
}
124-
125-
func (el *EventLoop) processChangesAndStatusUpdates(ctx context.Context, changes []state.Change, updates []state.StatusUpdate) {
126-
for _, c := range changes {
127-
el.logger.Info("Processing a change",
128-
"host", c.Host.Value)
129-
130-
if c.Op == state.Upsert {
131-
cfg, warnings := el.generator.GenerateForHost(c.Host)
132-
133-
for obj, objWarnings := range warnings {
134-
for _, w := range objWarnings {
135-
// FIXME(pleshakov): report warnings via Object status
136-
el.logger.Info("got warning while generating config",
137-
"kind", obj.GetObjectKind().GroupVersionKind().Kind,
138-
"namespace", obj.GetNamespace(),
139-
"name", obj.GetName(),
140-
"warning", w)
141-
}
142-
}
143-
144-
el.logger.Info("Writing configuration",
145-
"host", c.Host.Value)
146-
147-
err := el.nginxFileMgr.WriteServerConfig(c.Host.Value, cfg)
148-
if err != nil {
149-
el.logger.Error(err, "Failed to write configuration",
150-
"host", c.Host.Value)
151-
}
152-
} else {
153-
err := el.nginxFileMgr.DeleteServerConfig(c.Host.Value)
154-
if err != nil {
155-
el.logger.Error(err, "Failed to delete configuration",
156-
"host", c.Host.Value)
157-
}
158-
}
159-
}
160-
161-
if len(changes) > 0 {
162-
err := el.nginxRuntimeMgr.Reload(ctx)
163-
if err != nil {
164-
el.logger.Error(err, "Failed to reload NGINX")
165-
}
144+
el.serviceStore.Delete(e.NamespacedName)
145+
default:
146+
panic(fmt.Errorf("unknown resource type %T", e.Type))
166147
}
167-
168-
el.statusUpdater.ProcessStatusUpdates(ctx, updates)
169148
}

0 commit comments

Comments
 (0)