Skip to content

Commit 889cfad

Browse files
authored
Add Event Loop (#56)
1 parent 697b433 commit 889cfad

File tree

18 files changed

+716
-18
lines changed

18 files changed

+716
-18
lines changed

Makefile

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,10 @@ ifeq (${TARGET},local)
2222
CGO_ENABLED=0 GOOS=linux go build -trimpath -a -ldflags "-s -w -X main.version=${VERSION} -X main.commit=${GIT_COMMIT} -X main.date=${DATE}" -o $(OUT_DIR)/gateway github.com/nginxinc/nginx-gateway-kubernetes/cmd/gateway
2323
endif
2424

25+
.PHONY: generate
26+
generate:
27+
go generate ./...
28+
2529
.PHONY: out_dir
2630
out_dir:
2731
mkdir -p $(OUT_DIR)

cmd/gateway/main.go

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

77
"github.com/nginxinc/nginx-gateway-kubernetes/internal/config"
8-
"github.com/nginxinc/nginx-gateway-kubernetes/internal/controller"
8+
"github.com/nginxinc/nginx-gateway-kubernetes/internal/manager"
99

1010
flag "github.com/spf13/pflag"
1111
"sigs.k8s.io/controller-runtime/pkg/log/zap"
1212
)
1313

1414
const (
15-
domain string = "gateway.nginx.org"
15+
domain string = "k8s-gateway.nginx.org"
1616
)
1717

1818
var (
@@ -48,7 +48,7 @@ func main() {
4848
"commit", commit,
4949
"date", date)
5050

51-
err := controller.Start(conf)
51+
err := manager.Start(conf)
5252
if err != nil {
5353
logger.Error(err, "Failed to start control loop")
5454
os.Exit(1)

deploy/manifests/nginx-gateway.yaml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ rules:
1919
resources:
2020
- gatewayclasses
2121
- gateways
22+
- httproutes
2223
verbs:
2324
- list
2425
- watch
Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
apiVersion: gateway.networking.k8s.io/v1alpha2
2+
kind: HTTPRoute
3+
metadata:
4+
name: cafe
5+
spec:
6+
hostnames:
7+
- "cafe.example.com"
8+
rules:
9+
- backendRefs:
10+
- name: main
11+
port: 80
12+
---
13+
apiVersion: gateway.networking.k8s.io/v1alpha2
14+
kind: HTTPRoute
15+
metadata:
16+
name: coffee
17+
spec:
18+
hostnames:
19+
- "cafe.example.com"
20+
rules:
21+
- matches:
22+
- path:
23+
type: PathPrefix
24+
value: /coffee
25+
backendRefs:
26+
- name: coffee
27+
port: 80
28+
---
29+
apiVersion: gateway.networking.k8s.io/v1alpha2
30+
kind: HTTPRoute
31+
metadata:
32+
name: tea
33+
spec:
34+
hostnames:
35+
- "cafe.example.com"
36+
rules:
37+
- matches:
38+
- path:
39+
type: PathPrefix
40+
value: /tea
41+
backendRefs:
42+
- name: tea
43+
port: 80

go.mod

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ go 1.17
55
require (
66
github.com/go-logr/logr v1.2.0
77
github.com/google/go-cmp v0.5.6
8+
github.com/maxbrunsfeld/counterfeiter/v6 v6.4.1
89
github.com/onsi/ginkgo v1.16.5
910
github.com/onsi/ginkgo/v2 v2.1.1
1011
github.com/onsi/gomega v1.17.0

go.sum

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -364,6 +364,8 @@ github.com/mattn/go-runewidth v0.0.2/go.mod h1:LwmH8dsx7+W8Uxz3IHJYH5QSwggIsqBzp
364364
github.com/matttproud/golang_protobuf_extensions v1.0.1/go.mod h1:D8He9yQNgCq6Z5Ld7szi9bcBfOoFv/3dc6xSMkL2PC0=
365365
github.com/matttproud/golang_protobuf_extensions v1.0.2-0.20181231171920-c182affec369 h1:I0XW9+e1XWDxdcEniV4rQAIOPUGDq67JSCiRCgGCZLI=
366366
github.com/matttproud/golang_protobuf_extensions v1.0.2-0.20181231171920-c182affec369/go.mod h1:BSXmuO+STAnVfrANrmjBb36TMTDstsz7MSK+HVaYKv4=
367+
github.com/maxbrunsfeld/counterfeiter/v6 v6.4.1 h1:hZD/8vBuw7x1WqRXD/WGjVjipbbo/HcDBgySYYbrUSk=
368+
github.com/maxbrunsfeld/counterfeiter/v6 v6.4.1/go.mod h1:DK1Cjkc0E49ShgRVs5jy5ASrM15svSnem3K/hiSGD8o=
367369
github.com/miekg/dns v1.0.14/go.mod h1:W1PPwlIAgtquWBMBEV9nkV9Cazfe8ScdGz/Lj7v3Nrg=
368370
github.com/mitchellh/cli v1.0.0/go.mod h1:hNIlj7HEI86fIcpObd7a0FcrxTWetlwJDGcceTlRvqc=
369371
github.com/mitchellh/go-homedir v1.0.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0=
@@ -410,6 +412,7 @@ github.com/onsi/gomega v0.0.0-20170829124025-dcabb60a477c/go.mod h1:C1qb7wdrVGGV
410412
github.com/onsi/gomega v1.7.0/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1CpauHY=
411413
github.com/onsi/gomega v1.7.1/go.mod h1:XdKZgCCFLUoM/7CFJVPcG8C1xQ1AJ0vpAezJrB7JYyY=
412414
github.com/onsi/gomega v1.10.1/go.mod h1:iN09h71vgCQne3DLsj+A5owkum+a2tYe+TOCB1ybHNo=
415+
github.com/onsi/gomega v1.11.0/go.mod h1:azGKhqFUon9Vuj0YmTfLSmx0FUwqXYSTl5re8lQLTUg=
413416
github.com/onsi/gomega v1.14.0/go.mod h1:cIuvLEne0aoVhAgh/O6ac0Op8WWw9H6eYCriF+tEHG0=
414417
github.com/onsi/gomega v1.16.0/go.mod h1:HnhC7FXeEQY45zxNK3PPoIUhzk/80Xly9PcubAlGdZY=
415418
github.com/onsi/gomega v1.17.0 h1:9Luw4uT5HTjHTN8+aNcSThgH1vdXnmdJ8xIfZ4wyTRE=
@@ -460,6 +463,8 @@ github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFR
460463
github.com/russross/blackfriday/v2 v2.0.1/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM=
461464
github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM=
462465
github.com/ryanuber/columnize v0.0.0-20160712163229-9b3edd62028f/go.mod h1:sm1tb6uqfes/u+d4ooFouqFdy9/2g9QGwK3SQygK0Ts=
466+
github.com/sclevine/spec v1.4.0 h1:z/Q9idDcay5m5irkZ28M7PtQM4aOISzOpj4bUPkDee8=
467+
github.com/sclevine/spec v1.4.0/go.mod h1:LvpgJaFyvQzRvc1kaDs0bulYwzC70PbiYjC4QnFHkOM=
463468
github.com/sean-/seed v0.0.0-20170313163322-e2103e2c3529/go.mod h1:DxrIzT+xaE7yg65j358z/aeFdxmN0P9QXhEzd20vsDc=
464469
github.com/shurcooL/sanitized_anchor_name v1.0.0/go.mod h1:1NzhyTcUVG4SuEtjjoZeVRXNmyL/1OwPU0+IJeTBvfc=
465470
github.com/sirupsen/logrus v1.2.0/go.mod h1:LxeOpSwHxABJmUn/MG1IvRgCAasNZTLOkJPxbbu5VWo=
@@ -657,6 +662,7 @@ golang.org/x/net v0.0.0-20210119194325-5f4716e94777/go.mod h1:m0MpNAwzfU5UDzcl9v
657662
golang.org/x/net v0.0.0-20210224082022-3d97a244fca7/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
658663
golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
659664
golang.org/x/net v0.0.0-20210316092652-d523dce5a7f4/go.mod h1:RBQZq4jEuRlivfhVLdyRGr576XBO4/greRjx4P4O3yc=
665+
golang.org/x/net v0.0.0-20210331212208-0fccb6fa2b5c/go.mod h1:p54w0d4576C0XHj96bSt6lcn1PtDYWL6XObtHCRCNQM=
660666
golang.org/x/net v0.0.0-20210405180319-a5a99cb37ef4/go.mod h1:p54w0d4576C0XHj96bSt6lcn1PtDYWL6XObtHCRCNQM=
661667
golang.org/x/net v0.0.0-20210428140749-89ef3d95e781/go.mod h1:OJAsFXCWl8Ukc7SiCT/9KSuxbyM7479/AVlXFRxuMCk=
662668
golang.org/x/net v0.0.0-20210520170846-37e1c6afe023/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
@@ -962,8 +968,9 @@ gopkg.in/alecthomas/kingpin.v2 v2.2.6/go.mod h1:FMv+mEhP44yOT+4EoQTLFTRgOQ1FBLks
962968
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
963969
gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
964970
gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
965-
gopkg.in/check.v1 v1.0.0-20200227125254-8fa46927fb4f h1:BLraFXnmrev5lT+xlilqcH8XK9/i0At2xKjWk4p6zsU=
966971
gopkg.in/check.v1 v1.0.0-20200227125254-8fa46927fb4f/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
972+
gopkg.in/check.v1 v1.0.0-20200902074654-038fdea0a05b h1:QRR6H1YWRnHb4Y/HeNFCTJLFVxaq6wH4YuVdsUOr75U=
973+
gopkg.in/check.v1 v1.0.0-20200902074654-038fdea0a05b/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
967974
gopkg.in/cheggaaa/pb.v1 v1.0.25/go.mod h1:V/YB90LKu/1FcN3WVnfiiE5oMCibMjukxqG/qStrOgw=
968975
gopkg.in/errgo.v2 v2.1.0/go.mod h1:hNsd1EY+bozCKY1Ytp96fpM3vjJbqLJn88ws8XvfDNI=
969976
gopkg.in/fsnotify.v1 v1.4.7/go.mod h1:Tz8NjZHkW78fSQdbUxIjBTcgA1z1m8ZHf0WmKUhAMys=

internal/events/event.go

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
package events
2+
3+
import (
4+
"k8s.io/apimachinery/pkg/types"
5+
"sigs.k8s.io/controller-runtime/pkg/client"
6+
)
7+
8+
// UpsertEvent represents upserting a resource.
9+
type UpsertEvent struct {
10+
// Resource is the resource that is being upserted.
11+
Resource client.Object
12+
}
13+
14+
// DeleteEvent representing deleting a resource.
15+
type DeleteEvent struct {
16+
// NamespacedName is the namespace & name of the deleted resource.
17+
NamespacedName types.NamespacedName
18+
// Type is the resource type. For example, if the event is for *v1alpha2.HTTPRoute, pass &v1alpha2.HTTPRoute{} as Type.
19+
Type client.Object
20+
}

internal/events/events_suit_test.go

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
package events_test
2+
3+
import (
4+
. "github.com/onsi/ginkgo/v2"
5+
. "github.com/onsi/gomega"
6+
7+
"testing"
8+
)
9+
10+
func TestState(t *testing.T) {
11+
RegisterFailHandler(Fail)
12+
RunSpecs(t, "Events Suite")
13+
}

internal/events/loop.go

Lines changed: 108 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,108 @@
1+
package events
2+
3+
import (
4+
"context"
5+
"fmt"
6+
7+
"github.com/go-logr/logr"
8+
"github.com/nginxinc/nginx-gateway-kubernetes/internal/state"
9+
"sigs.k8s.io/gateway-api/apis/v1alpha2"
10+
)
11+
12+
// EventLoop is the main event loop of the Gateway.
13+
type EventLoop struct {
14+
conf state.Configuration
15+
eventCh <-chan interface{}
16+
logger logr.Logger
17+
}
18+
19+
// NewEventLoop creates a new EventLoop.
20+
func NewEventLoop(conf state.Configuration, eventCh <-chan interface{}, logger logr.Logger) *EventLoop {
21+
return &EventLoop{
22+
conf: conf,
23+
eventCh: eventCh,
24+
logger: logger.WithName("eventLoop"),
25+
}
26+
}
27+
28+
// Start starts the EventLoop.
29+
// The method will block until the EventLoop stops:
30+
// - if it stops because of an error, the Start will return the error.
31+
// - if it stops normally, the Start will return nil.
32+
func (el *EventLoop) Start(ctx context.Context) error {
33+
for {
34+
select {
35+
case <-ctx.Done():
36+
return nil
37+
case e := <-el.eventCh:
38+
err := el.handleEvent(e)
39+
if err != nil {
40+
return err
41+
}
42+
}
43+
}
44+
}
45+
46+
// TO-DO: think about how to avoid using an interface{} here
47+
func (el *EventLoop) handleEvent(event interface{}) error {
48+
var changes []state.Change
49+
var updates []state.StatusUpdate
50+
var err error
51+
52+
switch e := event.(type) {
53+
case *UpsertEvent:
54+
changes, updates, err = el.propagateUpsert(e)
55+
case *DeleteEvent:
56+
changes, updates, err = el.propagateDelete(e)
57+
default:
58+
return fmt.Errorf("unknown event type %T", e)
59+
}
60+
61+
if err != nil {
62+
return err
63+
}
64+
65+
el.processChangesAndStatusUpdates(changes, updates)
66+
67+
return nil
68+
}
69+
70+
func (el *EventLoop) propagateUpsert(e *UpsertEvent) ([]state.Change, []state.StatusUpdate, error) {
71+
switch r := e.Resource.(type) {
72+
case *v1alpha2.HTTPRoute:
73+
changes, statusUpdates := el.conf.UpsertHTTPRoute(r)
74+
return changes, statusUpdates, nil
75+
}
76+
77+
return nil, nil, fmt.Errorf("unknown resource type %T", e.Resource)
78+
}
79+
80+
func (el *EventLoop) propagateDelete(e *DeleteEvent) ([]state.Change, []state.StatusUpdate, error) {
81+
switch e.Type.(type) {
82+
case *v1alpha2.HTTPRoute:
83+
changes, statusUpdates := el.conf.DeleteHTTPRoute(e.NamespacedName)
84+
return changes, statusUpdates, nil
85+
}
86+
87+
return nil, nil, fmt.Errorf("unknown resource type %T", e.Type)
88+
}
89+
90+
func (el *EventLoop) processChangesAndStatusUpdates(changes []state.Change, updates []state.StatusUpdate) {
91+
for _, c := range changes {
92+
el.logger.Info("Processing a change",
93+
"host", c.Host.Value)
94+
95+
// TO-DO: This code is temporary. We will remove it once we have a component that processes changes.
96+
fmt.Printf("%+v\n", c)
97+
}
98+
99+
for _, u := range updates {
100+
// TO-DO: in the next iteration, the update will include the namespace/name of the resource instead of
101+
// runtime.Object, so it will be easy to get the resource namespace/name and include it in the log output
102+
el.logger.Info("Processing a status update",
103+
"gvk", u.Object.GetObjectKind().GroupVersionKind().String())
104+
105+
// TO-DO: This code is temporary. We will remove it once we have a component that updates statuses.
106+
fmt.Printf("%+v\n", u)
107+
}
108+
}

0 commit comments

Comments
 (0)