Skip to content

Commit afb8ab2

Browse files
authored
Merge branch 'main' into docs/helm-docs
2 parents ec062cc + 01a18c6 commit afb8ab2

13 files changed

+140
-54
lines changed

.github/workflows/lint.yml

+5
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,10 @@ jobs:
2323
lint:
2424
name: Lint
2525
runs-on: ubuntu-22.04
26+
strategy:
27+
fail-fast: false
28+
matrix:
29+
directory: [., tests] # we need to run golangci-lint for every module https://github.com/golangci/golangci-lint/issues/828
2630
steps:
2731
- name: Checkout Repository
2832
uses: actions/checkout@a5ac7e51b41094c92402da3b24376905380afc29 # v4.1.6
@@ -36,6 +40,7 @@ jobs:
3640
uses: golangci/golangci-lint-action@a4f60bb28d35aeee14e6880718e0c85ff1882e64 # v6.0.1
3741
with:
3842
args: --timeout 10m0s
43+
working-directory: ${{ matrix.directory }}
3944

4045
njs-lint:
4146
name: NJS Lint

.golangci.yml

-1
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,6 @@ linters-settings:
1717
- name: error-strings
1818
- name: errorf
1919
- name: exported
20-
- name: if-return
2120
- name: increment-decrement
2221
- name: indent-error-flow
2322
- name: package-comments

.pre-commit-config.yaml

+7
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,13 @@ repos:
4141
rev: v1.59.0
4242
hooks:
4343
- id: golangci-lint-full
44+
name: golangci-lint-root
45+
alias: golangci-lint-root
46+
47+
- id: golangci-lint-full
48+
name: golangci-lint-tests
49+
alias: golangci-lint-tests
50+
entry: bash -c 'cd tests && golangci-lint run --fix --config $OLDPWD/.golangci.yml'
4451

4552
# Rules are in .markdownlint-cli2.yaml file
4653
# See https://github.com/DavidAnson/markdownlint/blob/main/doc/Rules.md for rule descriptions

Makefile

+10-2
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,9 @@ GO_LINKER_FlAGS_VARS = -X main.version=${VERSION} -X main.commit=${GIT_COMMIT} -
2525
GO_LINKER_FLAGS_OPTIMIZATIONS = -s -w
2626
GO_LINKER_FLAGS = $(GO_LINKER_FLAGS_OPTIMIZATIONS) $(GO_LINKER_FlAGS_VARS)
2727

28+
# tools versions
29+
GOLANGCI_LINT_VERSION := $(shell awk '/repo:.*golangci-lint/{getline; if ($$1 == "rev:") {sub(/^v/, "", $$2); print $$2}}' $(SELF_DIR).pre-commit-config.yaml)
30+
2831
# variables that can be overridden by the user
2932
PREFIX ?= nginx-gateway-fabric## The name of the NGF image. For example, nginx-gateway-fabric
3033
NGINX_PREFIX ?= $(PREFIX)/nginx## The name of the nginx image. For example: nginx-gateway-fabric/nginx
@@ -168,9 +171,14 @@ njs-fmt: ## Run prettier against the njs httpmatches module
168171
vet: ## Run go vet against code
169172
go vet ./...
170173

174+
.PHONY: check-golangci-lint
175+
check-golangci-lint:
176+
@golangci-lint --version || (code=$$?; printf "\033[0;31mError\033[0m: there was a problem with golangci-lint. Follow the docs to install it https://golangci-lint.run/welcome/install/\n"; exit $$code)
177+
@golangci-lint --version | grep -q $(GOLANGCI_LINT_VERSION) || (printf "\033[0;33mWarning\033[0m: your golangci-lint version is different from the one specified in .pre-commit-config.yaml. The recommended version is $(GOLANGCI_LINT_VERSION)\n")
178+
171179
.PHONY: lint
172-
lint: ## Run golangci-lint against code
173-
docker run --pull always --rm -v $(CURDIR):/nginx-gateway-fabric -w /nginx-gateway-fabric -v $(shell go env GOCACHE):/cache/go -e GOCACHE=/cache/go -e GOLANGCI_LINT_CACHE=/cache/go -v $(shell go env GOPATH)/pkg:/go/pkg golangci/golangci-lint:latest golangci-lint --color always run
180+
lint: check-golangci-lint ## Run golangci-lint against code
181+
golangci-lint run
174182

175183
.PHONY: unit-test
176184
unit-test: ## Run unit tests for the go code

internal/mode/static/handler.go

+8-8
Original file line numberDiff line numberDiff line change
@@ -282,9 +282,9 @@ func (h *eventHandlerImpl) updateStatuses(ctx context.Context, logger logr.Logge
282282
func (h *eventHandlerImpl) parseAndCaptureEvent(ctx context.Context, logger logr.Logger, event interface{}) {
283283
switch e := event.(type) {
284284
case *events.UpsertEvent:
285-
filterKey := objectFilterKey(e.Resource, client.ObjectKeyFromObject(e.Resource))
285+
upFilterKey := objectFilterKey(e.Resource, client.ObjectKeyFromObject(e.Resource))
286286

287-
if filter, ok := h.objectFilters[filterKey]; ok {
287+
if filter, ok := h.objectFilters[upFilterKey]; ok {
288288
filter.upsert(ctx, logger, e.Resource)
289289
if !filter.captureChangeInGraph {
290290
return
@@ -293,9 +293,9 @@ func (h *eventHandlerImpl) parseAndCaptureEvent(ctx context.Context, logger logr
293293

294294
h.cfg.processor.CaptureUpsertChange(e.Resource)
295295
case *events.DeleteEvent:
296-
filterKey := objectFilterKey(e.Type, e.NamespacedName)
296+
delFilterKey := objectFilterKey(e.Type, e.NamespacedName)
297297

298-
if filter, ok := h.objectFilters[filterKey]; ok {
298+
if filter, ok := h.objectFilters[delFilterKey]; ok {
299299
filter.delete(ctx, logger, e.NamespacedName)
300300
if !filter.captureChangeInGraph {
301301
return
@@ -359,14 +359,14 @@ func (h *eventHandlerImpl) updateUpstreamServers(
359359
}
360360

361361
for _, u := range conf.Upstreams {
362-
upstream := upstream{
362+
confUpstream := upstream{
363363
name: u.Name,
364364
servers: ngxConfig.ConvertEndpoints(u.Endpoints),
365365
}
366366

367-
if u, ok := prevUpstreams[upstream.name]; ok {
368-
if !serversEqual(upstream.servers, u.Peers) {
369-
upstreams = append(upstreams, upstream)
367+
if u, ok := prevUpstreams[confUpstream.name]; ok {
368+
if !serversEqual(confUpstream.servers, u.Peers) {
369+
upstreams = append(upstreams, confUpstream)
370370
}
371371
}
372372
}

tests/Makefile

+2-3
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,6 @@ GW_API_VERSION ?= $(shell sed -n 's/.*ref=v\(.*\)/\1/p' ../config/crd/gateway-ap
99
GW_API_PREV_VERSION ?= 1.0.0## Supported Gateway API version from previous NGF release
1010
GW_SERVICE_TYPE = NodePort## Service type to use for the gateway
1111
GW_SVC_GKE_INTERNAL = false
12-
K8S_VERSION ?= latest## Kubernetes version to use. Expected format: 1.24 (major.minor) or latest
1312
NGF_VERSION ?= $(shell git describe --tags $(shell git rev-list --tags --max-count=1))## NGF version to be tested (defaults to latest tag)
1413
PULL_POLICY = Never## Pull policy for the images
1514
PROVISIONER_MANIFEST = conformance/provisioner/provisioner.yaml
@@ -114,7 +113,7 @@ stop-longevity-test: nfr-test ## Stop the longevity test and collects results
114113
--label-filter "nfr" $(GINKGO_FLAGS) ./suite -- --gateway-api-version=$(GW_API_VERSION) \
115114
--gateway-api-prev-version=$(GW_API_PREV_VERSION) --image-tag=$(TAG) --version-under-test=$(NGF_VERSION) \
116115
--plus-enabled=$(PLUS_ENABLED) --ngf-image-repo=$(PREFIX) --nginx-image-repo=$(NGINX_PREFIX) --nginx-plus-image-repo=$(NGINX_PLUS_PREFIX) \
117-
--pull-policy=$(PULL_POLICY) --k8s-version=$(K8S_VERSION) --service-type=$(GW_SERVICE_TYPE) \
116+
--pull-policy=$(PULL_POLICY) --service-type=$(GW_SERVICE_TYPE) \
118117
--is-gke-internal-lb=$(GW_SVC_GKE_INTERNAL)
119118

120119
.PHONY: test
@@ -124,7 +123,7 @@ test: ## Runs the functional tests on your default k8s cluster
124123
--gateway-api-version=$(GW_API_VERSION) --gateway-api-prev-version=$(GW_API_PREV_VERSION) \
125124
--image-tag=$(TAG) --version-under-test=$(NGF_VERSION) \
126125
--plus-enabled=$(PLUS_ENABLED) --ngf-image-repo=$(PREFIX) --nginx-image-repo=$(NGINX_PREFIX) --nginx-plus-image-repo=$(NGINX_PLUS_PREFIX) \
127-
--pull-policy=$(PULL_POLICY) --k8s-version=$(K8S_VERSION) --service-type=$(GW_SERVICE_TYPE) \
126+
--pull-policy=$(PULL_POLICY) --service-type=$(GW_SERVICE_TYPE) \
128127
--is-gke-internal-lb=$(GW_SVC_GKE_INTERNAL)
129128

130129
.PHONY: test-with-plus

tests/framework/ngf.go

+1-1
Original file line numberDiff line numberDiff line change
@@ -43,7 +43,7 @@ func InstallGatewayAPI(apiVersion string) ([]byte, error) {
4343
}
4444

4545
// UninstallGatewayAPI uninstalls the specified version of the Gateway API resources.
46-
func UninstallGatewayAPI(apiVersion, k8sVersion string) ([]byte, error) {
46+
func UninstallGatewayAPI(apiVersion string) ([]byte, error) {
4747
apiPath := fmt.Sprintf("%s/v%s/standard-install.yaml", gwInstallBasePath, apiVersion)
4848

4949
output, err := exec.Command("kubectl", "delete", "-f", apiPath).CombinedOutput()

tests/framework/portforward.go

+1-2
Original file line numberDiff line numberDiff line change
@@ -3,13 +3,12 @@ package framework
33
import (
44
"bytes"
55
"fmt"
6+
"log/slog"
67
"net/http"
78
"net/url"
89
"path"
910
"time"
1011

11-
"log/slog"
12-
1312
"k8s.io/client-go/rest"
1413
"k8s.io/client-go/tools/portforward"
1514
"k8s.io/client-go/transport/spdy"

tests/framework/prometheus.go

+7-5
Original file line numberDiff line numberDiff line change
@@ -61,6 +61,7 @@ func InstallPrometheus(
6161

6262
scrapeInterval := fmt.Sprintf("%ds", int(cfg.ScrapeInterval.Seconds()))
6363

64+
// nolint:gosec
6465
output, err = exec.Command(
6566
"helm",
6667
"install",
@@ -134,13 +135,12 @@ const (
134135

135136
// PrometheusInstance represents a Prometheus instance in the cluster.
136137
type PrometheusInstance struct {
138+
apiClient v1.API
137139
podIP string
138140
podName string
139141
podNamespace string
140-
portForward bool
141142
queryTimeout time.Duration
142-
143-
apiClient v1.API
143+
portForward bool
144144
}
145145

146146
// PortForward starts port forwarding to the Prometheus instance.
@@ -165,7 +165,7 @@ func (ins *PrometheusInstance) getAPIClient() (v1.API, error) {
165165
}
166166

167167
cfg := api.Config{
168-
Address: fmt.Sprintf("%s", endpoint),
168+
Address: endpoint,
169169
}
170170

171171
c, err := api.NewClient(cfg)
@@ -227,7 +227,9 @@ func (ins *PrometheusInstance) QueryRange(query string, promRange v1.Range) (mod
227227
}
228228

229229
// QueryRangeWithCtx sends a range query to Prometheus with the specified context.
230-
func (ins *PrometheusInstance) QueryRangeWithCtx(ctx context.Context, query string, promRange v1.Range) (model.Value, error) {
230+
func (ins *PrometheusInstance) QueryRangeWithCtx(ctx context.Context,
231+
query string, promRange v1.Range,
232+
) (model.Value, error) {
231233
if err := ins.ensureAPIClient(); err != nil {
232234
return nil, err
233235
}

tests/framework/resourcemanager.go

+56-2
Original file line numberDiff line numberDiff line change
@@ -307,7 +307,7 @@ func (rm *ResourceManager) WaitForAppsToBeReady(namespace string) error {
307307
}
308308

309309
// WaitForAppsToBeReadyWithCtx waits for all apps in the specified namespace to be ready or
310-
// until the provided context is cancelled.
310+
// until the provided context is canceled.
311311
func (rm *ResourceManager) WaitForAppsToBeReadyWithCtx(ctx context.Context, namespace string) error {
312312
if err := rm.WaitForPodsToBeReady(ctx, namespace); err != nil {
313313
return err
@@ -325,7 +325,7 @@ func (rm *ResourceManager) WaitForAppsToBeReadyWithCtx(ctx context.Context, name
325325
}
326326

327327
// WaitForPodsToBeReady waits for all Pods in the specified namespace to be ready or
328-
// until the provided context is cancelled.
328+
// until the provided context is canceled.
329329
func (rm *ResourceManager) WaitForPodsToBeReady(ctx context.Context, namespace string) error {
330330
return wait.PollUntilContextCancel(
331331
ctx,
@@ -683,3 +683,57 @@ func countNumberOfReadyParents(parents []v1.RouteParentStatus) int {
683683

684684
return readyCount
685685
}
686+
687+
func (rm *ResourceManager) WaitForAppsToBeReadyWithPodCount(namespace string, podCount int) error {
688+
ctx, cancel := context.WithTimeout(context.Background(), rm.TimeoutConfig.CreateTimeout)
689+
defer cancel()
690+
691+
return rm.WaitForAppsToBeReadyWithCtxWithPodCount(ctx, namespace, podCount)
692+
}
693+
694+
func (rm *ResourceManager) WaitForAppsToBeReadyWithCtxWithPodCount(
695+
ctx context.Context,
696+
namespace string,
697+
podCount int,
698+
) error {
699+
if err := rm.WaitForPodsToBeReadyWithCount(ctx, namespace, podCount); err != nil {
700+
return err
701+
}
702+
703+
if err := rm.waitForHTTPRoutesToBeReady(ctx, namespace); err != nil {
704+
return err
705+
}
706+
707+
if err := rm.waitForGRPCRoutesToBeReady(ctx, namespace); err != nil {
708+
return err
709+
}
710+
711+
return rm.waitForGatewaysToBeReady(ctx, namespace)
712+
}
713+
714+
// WaitForPodsToBeReady waits for all Pods in the specified namespace to be ready or
715+
// until the provided context is canceled.
716+
func (rm *ResourceManager) WaitForPodsToBeReadyWithCount(ctx context.Context, namespace string, count int) error {
717+
return wait.PollUntilContextCancel(
718+
ctx,
719+
500*time.Millisecond,
720+
true, /* poll immediately */
721+
func(ctx context.Context) (bool, error) {
722+
var podList core.PodList
723+
if err := rm.K8sClient.List(ctx, &podList, client.InNamespace(namespace)); err != nil {
724+
return false, err
725+
}
726+
727+
var podsReady int
728+
for _, pod := range podList.Items {
729+
for _, cond := range pod.Status.Conditions {
730+
if cond.Type == core.PodReady && cond.Status == core.ConditionTrue {
731+
podsReady++
732+
}
733+
}
734+
}
735+
736+
return podsReady == count, nil
737+
},
738+
)
739+
}

tests/suite/graceful_recovery_test.go

+31-11
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,7 @@ const (
2828

2929
// Since checkContainerLogsForErrors may experience interference from previous tests (as explained in the function
3030
// documentation), this test is recommended to be run separate from other nfr tests.
31-
var _ = Describe("Graceful Recovery test", Ordered, Label("nfr", "graceful-recovery"), func() {
31+
var _ = Describe("Graceful Recovery test", Ordered, Label("functional", "graceful-recovery"), func() {
3232
files := []string{
3333
"graceful-recovery/cafe.yaml",
3434
"graceful-recovery/cafe-secret.yaml",
@@ -38,8 +38,10 @@ var _ = Describe("Graceful Recovery test", Ordered, Label("nfr", "graceful-recov
3838

3939
var ns core.Namespace
4040

41-
teaURL := "https://cafe.example.com/tea"
42-
coffeeURL := "http://cafe.example.com/coffee"
41+
baseHTTPURL := "http://cafe.example.com"
42+
baseHTTPSURL := "https://cafe.example.com"
43+
teaURL := baseHTTPSURL + "/tea"
44+
coffeeURL := baseHTTPURL + "/coffee"
4345

4446
var ngfPodName string
4547

@@ -56,6 +58,12 @@ var _ = Describe("Graceful Recovery test", Ordered, Label("nfr", "graceful-recov
5658
Expect(podNames).To(HaveLen(1))
5759

5860
ngfPodName = podNames[0]
61+
if portFwdPort != 0 {
62+
coffeeURL = fmt.Sprintf("%s:%d/coffee", baseHTTPURL, portFwdPort)
63+
}
64+
if portFwdHTTPSPort != 0 {
65+
teaURL = fmt.Sprintf("%s:%d/tea", baseHTTPSURL, portFwdHTTPSPort)
66+
}
5967
})
6068

6169
BeforeEach(func() {
@@ -67,7 +75,7 @@ var _ = Describe("Graceful Recovery test", Ordered, Label("nfr", "graceful-recov
6775

6876
Expect(resourceManager.Apply([]client.Object{&ns})).To(Succeed())
6977
Expect(resourceManager.ApplyFromFiles(files, ns.Name)).To(Succeed())
70-
Expect(resourceManager.WaitForAppsToBeReady(ns.Name)).To(Succeed())
78+
Expect(resourceManager.WaitForAppsToBeReadyWithPodCount(ns.Name, 2)).To(Succeed())
7179

7280
Eventually(
7381
func() error {
@@ -101,7 +109,7 @@ func runRecoveryTest(teaURL, coffeeURL, ngfPodName, containerName string, files
101109
)
102110

103111
if containerName != nginxContainerName {
104-
// Since we have already deployed resources and ran resourceManager.WaitForAppsToBeReady(ns.Name) earlier,
112+
// Since we have already deployed resources and ran resourceManager.WaitForAppsToBeReadyWithPodCount earlier,
105113
// we know that the applications are ready at this point. This could only be the case if NGF has written
106114
// statuses, which could only be the case if NGF has the leader lease. Since there is only one instance
107115
// of NGF in this test, we can be certain that this is the correct leaseholder name.
@@ -140,7 +148,7 @@ func runRecoveryTest(teaURL, coffeeURL, ngfPodName, containerName string, files
140148
Should(Succeed())
141149

142150
Expect(resourceManager.ApplyFromFiles(files, ns.Name)).To(Succeed())
143-
Expect(resourceManager.WaitForAppsToBeReady(ns.Name)).To(Succeed())
151+
Expect(resourceManager.WaitForAppsToBeReadyWithPodCount(ns.Name, 2)).To(Succeed())
144152

145153
Eventually(
146154
func() error {
@@ -191,7 +199,8 @@ func checkContainerRestart(ngfPodName, containerName string, currentRestartCount
191199
}
192200

193201
if restartCount != currentRestartCount+1 {
194-
return fmt.Errorf("expected current restart count: %d to match incremented restart count: %d", restartCount, currentRestartCount+1)
202+
return fmt.Errorf("expected current restart count: %d to match incremented restart count: %d",
203+
restartCount, currentRestartCount+1)
195204
}
196205

197206
return nil
@@ -264,7 +273,11 @@ func checkContainerLogsForErrors(ngfPodName string) {
264273
Expect(line).ToNot(ContainSubstring("[alert]"), line)
265274
Expect(line).ToNot(ContainSubstring("[emerg]"), line)
266275
if strings.Contains(line, "[error]") {
267-
Expect(line).To(ContainSubstring("connect() failed (111: Connection refused)"), line)
276+
expectedError1 := "connect() failed (111: Connection refused)"
277+
// FIXME(salonichf5) remove this error message check
278+
// when https://github.com/nginxinc/nginx-gateway-fabric/issues/2090 is completed.
279+
expectedError2 := "no live upstreams while connecting to upstream"
280+
Expect(line).To(Or(ContainSubstring(expectedError1), ContainSubstring(expectedError2)))
268281
}
269282
}
270283

@@ -274,7 +287,14 @@ func checkContainerLogsForErrors(ngfPodName string) {
274287
&core.PodLogOptions{Container: ngfContainerName},
275288
)
276289
Expect(err).ToNot(HaveOccurred())
277-
Expect(logs).ToNot(ContainSubstring("\"level\":\"error\""), logs)
290+
291+
for _, line := range strings.Split(logs, "\n") {
292+
if *plusEnabled && strings.Contains(line, "\"level\":\"error\"") {
293+
Expect(line).To(ContainSubstring("Usage reporting must be enabled when using NGINX Plus"), line)
294+
} else {
295+
Expect(line).ToNot(ContainSubstring("\"level\":\"error\""), line)
296+
}
297+
}
278298
}
279299

280300
func checkLeaderLeaseChange(originalLeaseName string) error {
@@ -314,7 +334,7 @@ func getContainerRestartCount(ngfPodName, containerName string) (int, error) {
314334

315335
var ngfPod core.Pod
316336
if err := k8sClient.Get(ctx, types.NamespacedName{Namespace: ngfNamespace, Name: ngfPodName}, &ngfPod); err != nil {
317-
return 0, fmt.Errorf("error retriving NGF Pod: %w", err)
337+
return 0, fmt.Errorf("error retrieving NGF Pod: %w", err)
318338
}
319339

320340
var restartCount int
@@ -333,7 +353,7 @@ func runNodeDebuggerJob(ngfPodName, jobScript string) (*v1.Job, error) {
333353

334354
var ngfPod core.Pod
335355
if err := k8sClient.Get(ctx, types.NamespacedName{Namespace: ngfNamespace, Name: ngfPodName}, &ngfPod); err != nil {
336-
return nil, fmt.Errorf("error retriving NGF Pod: %w", err)
356+
return nil, fmt.Errorf("error retrieving NGF Pod: %w", err)
337357
}
338358

339359
b, err := resourceManager.GetFileContents("graceful-recovery/node-debugger-job.yaml")

0 commit comments

Comments
 (0)