Skip to content

Commit 8c396cd

Browse files
authored
Merge branch 'nginxinc:main' into test/add-runtime-manager-tests
2 parents 0b42d66 + 530f25f commit 8c396cd

File tree

80 files changed

+2461
-731
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

80 files changed

+2461
-731
lines changed

.github/workflows/dependency-review.yml

+1-1
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,6 @@ jobs:
1515
uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1
1616

1717
- name: "Dependency Review"
18-
uses: actions/dependency-review-action@80f10bf419f34980065523f5efca7ebed17576aa # v4.1.0
18+
uses: actions/dependency-review-action@9129d7d40b8c12c1ed0f60400d00c92d437adcce # v4.1.3
1919
with:
2020
config-file: "nginxinc/k8s-common/dependency-review-config.yml@main"

.github/workflows/fossa.yml

+1-1
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,6 @@ jobs:
2222
uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1
2323

2424
- name: Scan
25-
uses: fossas/fossa-action@f61a4c0c263690f2ddb54b9822a719c25a7b608f # v1.3.1
25+
uses: fossas/fossa-action@47ef11b1e1e3812e88dae436ccbd2d0cbd1adab0 # v1.3.3
2626
with:
2727
api-key: ${{ secrets.FOSSA_TOKEN }}

.github/workflows/nginx-bot.yml

+35
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
name: NGINX Bot
2+
3+
on:
4+
issues:
5+
types:
6+
- opened
7+
- reopened
8+
- edited
9+
pull_request:
10+
types:
11+
- opened
12+
- reopened
13+
- edited
14+
15+
concurrency:
16+
group: ${{ github.event.issue.number || github.event.pull_request.number }}-bot
17+
cancel-in-progress: true
18+
19+
permissions:
20+
issues: write
21+
pull-requests: write
22+
23+
jobs:
24+
comment:
25+
name: Run the bot
26+
runs-on: ubuntu-22.04
27+
steps:
28+
- name: Bot Action
29+
uses: lucacome/nginx-bot@main
30+
with:
31+
pr-assignee-from-issue: 583
32+
warn-missing-issue: true
33+
missing-issue-message: |
34+
Please make sure to include the issue number in the PR description to automatically close the issue when the PR is merged.
35+
See [Linking a pull request to an issue](https://docs.github.com/en/issues/tracking-your-work-with-issues/linking-a-pull-request-to-an-issue) and our [Pull Request Guidelines](../docs/developer/pull-request.md) for more information.

.goreleaser.yml

+3
Original file line numberDiff line numberDiff line change
@@ -66,3 +66,6 @@ release:
6666
extra_files:
6767
- glob: ./build/out/crds.yaml
6868
- glob: ./deploy/manifests/nginx-gateway.yaml
69+
- glob: ./deploy/manifests/nginx-plus-gateway.yaml
70+
- glob: ./deploy/manifests/nginx-gateway-experimental.yaml
71+
- glob: ./deploy/manifests/nginx-plus-gateway-experimental.yaml

Makefile

+1-1
Original file line numberDiff line numberDiff line change
@@ -45,7 +45,7 @@ build-images-with-plus: build-ngf-image build-nginx-plus-image ## Build the NGF
4545

4646
.PHONY: build-ngf-image
4747
build-ngf-image: check-for-docker build ## Build the NGF docker image
48-
docker build --platform linux/$(GOARCH) --target $(strip $(TARGET)) -f build/Dockerfile -t $(strip $(PREFIX)):$(strip $(TAG)) .
48+
docker build --platform linux/$(GOARCH) --build-arg BUILD_AGENT=$(BUILD_AGENT) --target $(strip $(TARGET)) -f build/Dockerfile -t $(strip $(PREFIX)):$(strip $(TAG)) .
4949

5050
.PHONY: build-nginx-image
5151
build-nginx-image: check-for-docker ## Build the custom nginx image

build/Dockerfile

+2
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,8 @@ RUN setcap 'cap_kill=+ep' /usr/bin/gateway
2727

2828
FROM scratch as common
2929
USER 102:1001
30+
ARG BUILD_AGENT
31+
ENV BUILD_AGENT=${BUILD_AGENT}
3032
ENTRYPOINT [ "/usr/bin/gateway" ]
3133

3234
FROM common as container

cmd/gateway/commands.go

+93-20
Original file line numberDiff line numberDiff line change
@@ -44,19 +44,24 @@ func createRootCommand() *cobra.Command {
4444
func createStaticModeCommand() *cobra.Command {
4545
// flag names
4646
const (
47-
gatewayFlag = "gateway"
48-
configFlag = "config"
49-
serviceFlag = "service"
50-
updateGCStatusFlag = "update-gatewayclass-status"
51-
metricsDisableFlag = "metrics-disable"
52-
metricsSecureFlag = "metrics-secure-serving"
53-
metricsPortFlag = "metrics-port"
54-
healthDisableFlag = "health-disable"
55-
healthPortFlag = "health-port"
56-
leaderElectionDisableFlag = "leader-election-disable"
57-
leaderElectionLockNameFlag = "leader-election-lock-name"
58-
plusFlag = "nginx-plus"
59-
gwAPIExperimentalFlag = "gateway-api-experimental-features"
47+
gatewayFlag = "gateway"
48+
configFlag = "config"
49+
serviceFlag = "service"
50+
updateGCStatusFlag = "update-gatewayclass-status"
51+
metricsDisableFlag = "metrics-disable"
52+
metricsSecureFlag = "metrics-secure-serving"
53+
metricsPortFlag = "metrics-port"
54+
healthDisableFlag = "health-disable"
55+
healthPortFlag = "health-port"
56+
leaderElectionDisableFlag = "leader-election-disable"
57+
leaderElectionLockNameFlag = "leader-election-lock-name"
58+
productTelemetryDisableFlag = "product-telemetry-disable"
59+
plusFlag = "nginx-plus"
60+
gwAPIExperimentalFlag = "gateway-api-experimental-features"
61+
usageReportSecretFlag = "usage-report-secret"
62+
usageReportServerURLFlag = "usage-report-server-url"
63+
usageReportSkipVerifyFlag = "usage-report-skip-verify"
64+
usageReportClusterNameFlag = "usage-report-cluster-name"
6065
)
6166

6267
// flag values
@@ -95,9 +100,19 @@ func createStaticModeCommand() *cobra.Command {
95100
value: "nginx-gateway-leader-election-lock",
96101
}
97102

98-
plus bool
99-
100103
gwExperimentalFeatures bool
104+
105+
disableProductTelemetry bool
106+
107+
plus bool
108+
usageReportSkipVerify bool
109+
usageReportClusterName = stringValidatingValue{
110+
validator: validateQualifiedName,
111+
}
112+
usageReportSecretName = namespacedNameValue{}
113+
usageReportServerURL = stringValidatingValue{
114+
validator: validateURL,
115+
}
101116
)
102117

103118
cmd := &cobra.Command{
@@ -134,6 +149,11 @@ func createStaticModeCommand() *cobra.Command {
134149
return errors.New("POD_NAME environment variable must be set")
135150
}
136151

152+
imageSource := os.Getenv("BUILD_AGENT")
153+
if imageSource != "gha" && imageSource != "local" {
154+
imageSource = "unknown"
155+
}
156+
137157
period, err := time.ParseDuration(telemetryReportPeriod)
138158
if err != nil {
139159
return fmt.Errorf("error parsing telemetry report period: %w", err)
@@ -144,6 +164,20 @@ func createStaticModeCommand() *cobra.Command {
144164
gwNsName = &gateway.value
145165
}
146166

167+
var usageReportConfig *config.UsageReportConfig
168+
if cmd.Flags().Changed(usageReportSecretFlag) {
169+
if !plus {
170+
return errors.New("usage-report arguments are only valid if using nginx-plus")
171+
}
172+
173+
usageReportConfig = &config.UsageReportConfig{
174+
SecretNsName: usageReportSecretName.value,
175+
ServerURL: usageReportServerURL.value,
176+
ClusterDisplayName: usageReportClusterName.value,
177+
InsecureSkipVerify: usageReportSkipVerify,
178+
}
179+
}
180+
147181
conf := config.Config{
148182
GatewayCtlrName: gatewayCtlrName.value,
149183
ConfigName: configName.String(),
@@ -167,15 +201,20 @@ func createStaticModeCommand() *cobra.Command {
167201
Port: metricsListenPort.value,
168202
Secure: metricsSecure,
169203
},
170-
LeaderElection: config.LeaderElection{
204+
LeaderElection: config.LeaderElectionConfig{
171205
Enabled: !disableLeaderElection,
172206
LockName: leaderElectionLockName.String(),
173207
Identity: podName,
174208
},
175-
Plus: plus,
176-
TelemetryReportPeriod: period,
177-
Version: version,
178-
ExperimentalFeatures: gwExperimentalFeatures,
209+
UsageReportConfig: usageReportConfig,
210+
ProductTelemetryConfig: config.ProductTelemetryConfig{
211+
TelemetryReportPeriod: period,
212+
Enabled: !disableProductTelemetry,
213+
},
214+
Plus: plus,
215+
Version: version,
216+
ExperimentalFeatures: gwExperimentalFeatures,
217+
ImageSource: imageSource,
179218
}
180219

181220
if err := static.StartManager(conf); err != nil {
@@ -282,6 +321,13 @@ func createStaticModeCommand() *cobra.Command {
282321
"A Lease object with this name will be created in the same Namespace as the controller.",
283322
)
284323

324+
cmd.Flags().BoolVar(
325+
&disableProductTelemetry,
326+
productTelemetryDisableFlag,
327+
false,
328+
"Disable the collection of product telemetry.",
329+
)
330+
285331
cmd.Flags().BoolVar(
286332
&plus,
287333
plusFlag,
@@ -297,6 +343,33 @@ func createStaticModeCommand() *cobra.Command {
297343
"Requires the Gateway APIs installed from the experimental channel.",
298344
)
299345

346+
cmd.Flags().Var(
347+
&usageReportSecretName,
348+
usageReportSecretFlag,
349+
"The namespace/name of the Secret containing the credentials for NGINX Plus usage reporting.",
350+
)
351+
352+
cmd.Flags().Var(
353+
&usageReportServerURL,
354+
usageReportServerURLFlag,
355+
"The base server URL of the NGINX Plus usage reporting server.",
356+
)
357+
358+
cmd.MarkFlagsRequiredTogether(usageReportSecretFlag, usageReportServerURLFlag)
359+
360+
cmd.Flags().Var(
361+
&usageReportClusterName,
362+
usageReportClusterNameFlag,
363+
"The display name of the Kubernetes cluster in the NGINX Plus usage reporting server.",
364+
)
365+
366+
cmd.Flags().BoolVar(
367+
&usageReportSkipVerify,
368+
usageReportSkipVerifyFlag,
369+
false,
370+
"Disable client verification of the NGINX Plus usage reporting server certificate.",
371+
)
372+
300373
return cmd
301374
}
302375

cmd/gateway/commands_test.go

+63
Original file line numberDiff line numberDiff line change
@@ -155,6 +155,9 @@ func TestStaticModeCmdFlagValidation(t *testing.T) {
155155
"--health-disable",
156156
"--leader-election-lock-name=my-lock",
157157
"--leader-election-disable=false",
158+
"--usage-report-secret=default/my-secret",
159+
"--usage-report-server-url=https://my-api.com",
160+
"--usage-report-cluster-name=my-cluster",
158161
},
159162
wantErr: false,
160163
},
@@ -310,6 +313,66 @@ func TestStaticModeCmdFlagValidation(t *testing.T) {
310313
wantErr: true,
311314
expectedErrPrefix: `invalid argument "" for "--leader-election-disable" flag: strconv.ParseBool`,
312315
},
316+
{
317+
name: "usage-report-secret is set to empty string",
318+
args: []string{
319+
"--usage-report-secret=",
320+
},
321+
wantErr: true,
322+
expectedErrPrefix: `invalid argument "" for "--usage-report-secret" flag: must be set`,
323+
},
324+
{
325+
name: "usage-report-secret is invalid",
326+
args: []string{
327+
"--usage-report-secret=my-secret", // no namespace
328+
},
329+
wantErr: true,
330+
expectedErrPrefix: `invalid argument "my-secret" for "--usage-report-secret" flag: invalid format; ` +
331+
"must be NAMESPACE/NAME",
332+
},
333+
{
334+
name: "usage-report-server-url is set to empty string",
335+
args: []string{
336+
"--usage-report-server-url=",
337+
},
338+
wantErr: true,
339+
expectedErrPrefix: `invalid argument "" for "--usage-report-server-url" flag: must be set`,
340+
},
341+
{
342+
name: "usage-report-server-url is an invalid url",
343+
args: []string{
344+
"--usage-report-server-url=invalid",
345+
},
346+
wantErr: true,
347+
expectedErrPrefix: `invalid argument "invalid" for "--usage-report-server-url" flag: "invalid" must be a valid URL`,
348+
},
349+
{
350+
name: "usage secret and server url not specified together",
351+
args: []string{
352+
"--gateway-ctlr-name=gateway.nginx.org/nginx-gateway",
353+
"--gatewayclass=nginx",
354+
"--usage-report-server-url=http://example.com",
355+
},
356+
wantErr: true,
357+
expectedErrPrefix: "if any flags in the group [usage-report-secret usage-report-server-url] " +
358+
"are set they must all be set",
359+
},
360+
{
361+
name: "usage-report-cluster-name is set to empty string",
362+
args: []string{
363+
"--usage-report-cluster-name=",
364+
},
365+
wantErr: true,
366+
expectedErrPrefix: `invalid argument "" for "--usage-report-cluster-name" flag: must be set`,
367+
},
368+
{
369+
name: "usage-report-cluster-name is invalid",
370+
args: []string{
371+
"--usage-report-cluster-name=$invalid*(#)",
372+
},
373+
wantErr: true,
374+
expectedErrPrefix: `invalid argument "$invalid*(#)" for "--usage-report-cluster-name" flag: invalid format`,
375+
},
313376
}
314377

315378
// common flags validation is tested separately

cmd/gateway/validation.go

+33
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ import (
44
"errors"
55
"fmt"
66
"net"
7+
"net/url"
78
"regexp"
89
"strings"
910

@@ -89,6 +90,38 @@ func parseNamespacedResourceName(value string) (types.NamespacedName, error) {
8990
}, nil
9091
}
9192

93+
func validateQualifiedName(name string) error {
94+
if len(name) == 0 {
95+
return errors.New("must be set")
96+
}
97+
98+
messages := validation.IsQualifiedName(name)
99+
if len(messages) > 0 {
100+
msg := strings.Join(messages, "; ")
101+
return fmt.Errorf("invalid format: %s", msg)
102+
}
103+
104+
return nil
105+
}
106+
107+
func validateURL(value string) error {
108+
if len(value) == 0 {
109+
return errors.New("must be set")
110+
}
111+
val, err := url.Parse(value)
112+
if err != nil {
113+
return fmt.Errorf("%q must be a valid URL: %w", value, err)
114+
}
115+
if val.Scheme == "" {
116+
return fmt.Errorf("%q must be a valid URL: bad scheme", value)
117+
}
118+
if val.Host == "" {
119+
return fmt.Errorf("%q must be a valid URL: bad host", value)
120+
}
121+
122+
return nil
123+
}
124+
92125
func validateIP(ip string) error {
93126
if ip == "" {
94127
return errors.New("IP address must be set")

0 commit comments

Comments
 (0)