Skip to content

Commit e3595a3

Browse files
authored
Add First Class OpenShift support (#4001)
Problem: As a cluster operator managing traffic for an OpenShift cluster I want easily deploy NGF as my Gateway API implementation from the Operator Hub So that it is easier for me to try out and use NGF for my OpenShift environment. Solution: Add UBI based images and an Operator so we can begin the RedHat Operator Certification process and get NGF into the RedHat Certified OperatorHub
1 parent 6fc41cb commit e3595a3

File tree

73 files changed

+2693
-71
lines changed

Some content is hidden

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

73 files changed

+2693
-71
lines changed

.github/workflows/build.yml

Lines changed: 14 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,10 @@ on:
66
platforms:
77
required: true
88
type: string
9+
build-os:
10+
required: false
11+
type: string
12+
default: ''
913
image:
1014
required: true
1115
type: string
@@ -116,16 +120,17 @@ jobs:
116120
name=ghcr.io/${{ github.repository_owner }}/nginx-gateway-fabric/nginx,enable=${{ inputs.image == 'nginx' && github.event_name != 'pull_request' }}
117121
name=docker-mgmt.nginx.com/nginx-gateway-fabric/nginx-plus,enable=${{ inputs.image == 'plus' && github.event_name != 'pull_request' }}
118122
name=us-docker.pkg.dev/${{ secrets.GCP_PROJECT_ID }}/nginx-gateway-fabric/nginx-plus,enable=${{ inputs.image == 'plus' && github.event_name != 'pull_request' }}
123+
name=ghcr.io/${{ github.repository_owner }}/nginx-gateway-fabric/operator,enable=${{ inputs.image == 'operator' && github.event_name != 'pull_request' }}
119124
name=localhost:5000/nginx-gateway-fabric/${{ inputs.image }}
120125
flavor: |
121126
latest=${{ (inputs.tag != '' && 'true') || 'auto' }}
122127
tags: |
123-
type=semver,pattern={{version}}
124-
type=edge
125-
type=schedule
126-
type=ref,event=pr
127-
type=ref,event=branch,suffix=-rc,enable=${{ startsWith(github.ref, 'refs/heads/release') && inputs.tag == '' }}
128-
type=raw,value=${{ inputs.tag }},enable=${{ inputs.tag != '' }}
128+
type=semver,pattern={{version}},suffix=${{ inputs.build-os != '' && format('-{0}', inputs.build-os) || '' }}
129+
type=edge,suffix=${{ inputs.build-os != '' && format('-{0}', inputs.build-os) || '' }}
130+
type=schedule,suffix=${{ inputs.build-os != '' && format('-{0}', inputs.build-os) || '' }}
131+
type=ref,event=pr,suffix=${{ inputs.build-os != '' && format('-{0}', inputs.build-os) || '' }}
132+
type=ref,event=branch,suffix=-rc${{ inputs.build-os != '' && format('-{0}', inputs.build-os) || '' }},enable=${{ startsWith(github.ref, 'refs/heads/release') && inputs.tag == '' }}
133+
type=raw,value=${{ inputs.tag }},enable=${{ inputs.tag != '' }},suffix=${{ inputs.build-os != '' && format('-{0}', inputs.build-os) || '' }}
129134
labels: |
130135
org.opencontainers.image.documentation=https://docs.nginx.com/nginx-gateway-fabric
131136
org.opencontainers.image.vendor=NGINX Inc <[email protected]>
@@ -143,16 +148,16 @@ jobs:
143148
- name: Build Docker Image
144149
uses: docker/build-push-action@263435318d21b8e681c14492fe198d362a7d2c83 # v6.18.0
145150
with:
146-
file: build/Dockerfile${{ inputs.image == 'nginx' && '.nginx' || '' }}${{ inputs.image == 'plus' && '.nginxplus' || '' }}
151+
file: ${{ inputs.image == 'operator' && 'operators/Dockerfile' || (inputs.build-os != '' && format('build/{0}/Dockerfile{1}', inputs.build-os, inputs.image == 'nginx' && '.nginx' || inputs.image == 'plus' && '.nginxplus' || '') || format('build/Dockerfile{0}', inputs.image == 'nginx' && '.nginx' || inputs.image == 'plus' && '.nginxplus' || '')) }}
147152
context: "."
148153
target: ${{ inputs.image == 'ngf' && 'goreleaser' || '' }}
149154
tags: ${{ steps.meta.outputs.tags }}
150155
labels: ${{ steps.meta.outputs.labels }}
151156
annotations: ${{ steps.meta.outputs.annotations }}
152157
push: ${{ !inputs.dry_run }}
153158
platforms: ${{ inputs.platforms }}
154-
cache-from: type=gha,scope=${{ inputs.image }}
155-
cache-to: type=gha,scope=${{ inputs.image }},mode=max
159+
cache-from: type=gha,scope=${{ inputs.image }}${{ inputs.build-os != '' && format('-{0}', inputs.build-os) || '' }}
160+
cache-to: type=gha,scope=${{ inputs.image }}${{ inputs.build-os != '' && format('-{0}', inputs.build-os) || '' }},mode=max
156161
pull: true
157162
no-cache: ${{ github.event_name != 'pull_request' }}
158163
sbom: true

.github/workflows/ci.yml

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,10 @@ on:
2020
required: false
2121
type: string
2222
default: ''
23+
operator_version:
24+
required: false
25+
type: string
26+
default: ''
2327
dry_run:
2428
required: false
2529
type: boolean
@@ -350,10 +354,12 @@ jobs:
350354
matrix:
351355
image: [ngf, nginx]
352356
platforms: ["linux/arm64, linux/amd64"]
357+
build-os: ["", ubi]
353358
uses: ./.github/workflows/build.yml
354359
with:
355360
image: ${{ matrix.image }}
356361
platforms: ${{ matrix.platforms }}
362+
build-os: ${{ matrix.build-os }}
357363
tag: ${{ inputs.release_version || '' }}
358364
dry_run: ${{ inputs.dry_run || false}}
359365
runner: ${{ github.repository_owner == 'nginx' && (inputs.is_production_release || (github.event_name == 'push' && github.ref == 'refs/heads/main')) && 'ubuntu-24.04-amd64' || 'ubuntu-24.04' }}
@@ -368,9 +374,14 @@ jobs:
368374
name: Build Plus images
369375
needs: [vars, binary]
370376
uses: ./.github/workflows/build.yml
377+
strategy:
378+
fail-fast: false
379+
matrix:
380+
build-os: ["", ubi]
371381
with:
372382
image: plus
373383
platforms: "linux/arm64, linux/amd64"
384+
build-os: ${{ matrix.build-os }}
374385
tag: ${{ inputs.release_version || '' }}
375386
dry_run: ${{ inputs.dry_run || false }}
376387
runner: ${{ github.repository_owner == 'nginx' && (inputs.is_production_release || (github.event_name == 'push' && github.ref == 'refs/heads/main')) && 'ubuntu-24.04-amd64' || 'ubuntu-24.04' }}
@@ -381,13 +392,31 @@ jobs:
381392
id-token: write # for docker/login to login to NGINX registry
382393
secrets: inherit
383394

395+
build-operator:
396+
name: Build Operator images
397+
needs: [vars, binary]
398+
uses: ./.github/workflows/build.yml
399+
with:
400+
image: operator
401+
platforms: "linux/arm64, linux/amd64"
402+
tag: ${{ inputs.operator_version || '' }}
403+
dry_run: ${{ inputs.dry_run || false }}
404+
runner: ${{ github.repository_owner == 'nginx' && (inputs.is_production_release || (github.event_name == 'push' && github.ref == 'refs/heads/main')) && 'ubuntu-24.04-amd64' || 'ubuntu-24.04' }}
405+
permissions:
406+
contents: read # for docker/build-push-action to read repo content
407+
security-events: write # for github/codeql-action/upload-sarif to upload SARIF results
408+
packages: write # for docker/build-push-action to push to GHCR
409+
id-token: write # for docker/login to login to NGINX registry
410+
secrets: inherit
411+
384412
functional-tests:
385413
name: Functional tests
386414
needs: [vars, build-oss, build-plus]
387415
strategy:
388416
fail-fast: false
389417
matrix:
390418
image: [nginx, plus]
419+
build-os: ["", ubi]
391420
k8s-version:
392421
[
393422
"${{ needs.vars.outputs.min_k8s_version }}",
@@ -397,6 +426,7 @@ jobs:
397426
with:
398427
image: ${{ matrix.image }}
399428
k8s-version: ${{ matrix.k8s-version }}
429+
build-os: ${{ matrix.build-os }}
400430
secrets: inherit
401431
permissions:
402432
contents: read
@@ -408,6 +438,7 @@ jobs:
408438
fail-fast: false
409439
matrix:
410440
image: [nginx, plus]
441+
build-os: ["", ubi]
411442
k8s-version:
412443
[
413444
"${{ needs.vars.outputs.min_k8s_version }}",
@@ -419,6 +450,7 @@ jobs:
419450
image: ${{ matrix.image }}
420451
k8s-version: ${{ matrix.k8s-version }}
421452
enable-experimental: ${{ matrix.enable-experimental }}
453+
build-os: ${{ matrix.build-os }}
422454
production-release: ${{ inputs.is_production_release == true && (inputs.dry_run == false || inputs.dry_run == null) }}
423455
release_version: ${{ inputs.release_version }}
424456
secrets: inherit

.github/workflows/conformance.yml

Lines changed: 19 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,10 @@ on:
66
image:
77
required: true
88
type: string
9+
build-os:
10+
required: false
11+
type: string
12+
default: ''
913
k8s-version:
1014
required: true
1115
type: string
@@ -75,12 +79,12 @@ jobs:
7579
images: |
7680
name=ghcr.io/nginx/nginx-gateway-fabric
7781
tags: |
78-
type=semver,pattern={{version}}
79-
type=edge
80-
type=schedule
81-
type=ref,event=pr
82-
type=ref,event=branch,suffix=-rc,enable=${{ startsWith(github.ref, 'refs/heads/release') && !inputs.production-release }}
83-
type=raw,value={{inputs.release_version}},enable=${{ inputs.production-release && inputs.release_version != '' }}
82+
type=semver,pattern={{version}},suffix=${{ inputs.build-os != '' && format('-{0}', inputs.build-os) || '' }}
83+
type=edge,suffix=${{ inputs.build-os != '' && format('-{0}', inputs.build-os) || '' }}
84+
type=schedule,suffix=${{ inputs.build-os != '' && format('-{0}', inputs.build-os) || '' }}
85+
type=ref,event=pr,suffix=${{ inputs.build-os != '' && format('-{0}', inputs.build-os) || '' }}
86+
type=ref,event=branch,suffix=-rc${{ inputs.build-os != '' && format('-{0}', inputs.build-os) || '' }},enable=${{ startsWith(github.ref, 'refs/heads/release') && !inputs.production-release }}
87+
type=raw,value={{ inputs.release_version }},enable=${{ inputs.production-release && inputs.release_version != '' }},suffix=${{ inputs.build-os != '' && format('-{0}', inputs.build-os) || '' }}
8488
8589
- name: NGINX Docker meta
8690
id: nginx-meta
@@ -89,12 +93,12 @@ jobs:
8993
images: |
9094
name=ghcr.io/nginx/nginx-gateway-fabric/${{ inputs.image == 'plus' && 'nginx-plus' || inputs.image }}
9195
tags: |
92-
type=semver,pattern={{version}}
93-
type=edge
94-
type=schedule
95-
type=ref,event=pr
96-
type=ref,event=branch,suffix=-rc,enable=${{ startsWith(github.ref, 'refs/heads/release') && !inputs.production-release }}
97-
type=raw,value={{inputs.release_version}},enable=${{ inputs.production-release && inputs.release_version != '' }}
96+
type=semver,pattern={{version}},suffix=${{ inputs.build-os != '' && format('-{0}', inputs.build-os) || '' }}
97+
type=edge,suffix=${{ inputs.build-os != '' && format('-{0}', inputs.build-os) || '' }}
98+
type=schedule,suffix=${{ inputs.build-os != '' && format('-{0}', inputs.build-os) || '' }}
99+
type=ref,event=pr,suffix=${{ inputs.build-os != '' && format('-{0}', inputs.build-os) || '' }}
100+
type=ref,event=branch,suffix=-rc${{ inputs.build-os != '' && format('-{0}', inputs.build-os) || '' }},enable=${{ startsWith(github.ref, 'refs/heads/release') && !inputs.production-release }}
101+
type=raw,value={{ inputs.release_version }},enable=${{ inputs.production-release && inputs.release_version != '' }},suffix=${{ inputs.build-os != '' && format('-{0}', inputs.build-os) || '' }}
98102
99103
- name: Build binary
100104
uses: goreleaser/goreleaser-action@e435ccd777264be153ace6237001ef4d979d3a7a # v6.4.0
@@ -119,11 +123,11 @@ jobs:
119123
- name: Build NGINX Docker Image
120124
uses: docker/build-push-action@263435318d21b8e681c14492fe198d362a7d2c83 # v6.18.0
121125
with:
122-
file: build/Dockerfile${{ inputs.image == 'nginx' && '.nginx' || '' }}${{ inputs.image == 'plus' && '.nginxplus' || ''}}
126+
file: build${{ inputs.build-os != '' && format('/{0}', inputs.build-os) || '' }}/Dockerfile${{ inputs.image == 'nginx' && '.nginx' || '' }}${{ inputs.image == 'plus' && '.nginxplus' || '' }}
123127
tags: ${{ steps.nginx-meta.outputs.tags }}
124128
context: "."
125129
load: true
126-
cache-from: type=gha,scope=${{ inputs.image }}
130+
cache-from: type=gha,scope=${{ inputs.image }}${{ inputs.build-os != '' && format('-{0}', inputs.build-os) || '' }}
127131
pull: true
128132
build-args: |
129133
NJS_DIR=internal/controller/nginx/modules/src
@@ -178,7 +182,7 @@ jobs:
178182
if: ${{ inputs.enable-experimental }}
179183
uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4.6.2
180184
with:
181-
name: conformance-profile-${{ inputs.image }}-${{ inputs.k8s-version }}
185+
name: conformance-profile-${{ inputs.image }}-${{ inputs.k8s-version }}-${{ steps.ngf-meta.outputs.version }}
182186
path: ./tests/conformance-profile.yaml
183187

184188
- name: Upload profile to release

.github/workflows/functional.yml

Lines changed: 16 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,10 @@ on:
99
k8s-version:
1010
required: true
1111
type: string
12+
build-os:
13+
required: false
14+
type: string
15+
default: ''
1216

1317
defaults:
1418
run:
@@ -61,11 +65,11 @@ jobs:
6165
images: |
6266
name=ghcr.io/nginx/nginx-gateway-fabric
6367
tags: |
64-
type=semver,pattern={{version}}
65-
type=schedule
66-
type=edge
67-
type=ref,event=pr
68-
type=ref,event=branch,suffix=-rc,enable=${{ startsWith(github.ref, 'refs/heads/release') }}
68+
type=semver,pattern={{version}},suffix=${{ inputs.build-os != '' && format('-{0}', inputs.build-os) || '' }}
69+
type=schedule,suffix=${{ inputs.build-os != '' && format('-{0}', inputs.build-os) || '' }}
70+
type=edge,suffix=${{ inputs.build-os != '' && format('-{0}', inputs.build-os) || '' }}
71+
type=ref,event=pr,suffix=${{ inputs.build-os != '' && format('-{0}', inputs.build-os) || '' }}
72+
type=ref,event=branch,suffix=-rc${{ inputs.build-os != '' && format('-{0}', inputs.build-os) || '' }},enable=${{ startsWith(github.ref, 'refs/heads/release') }}
6973
7074
- name: NGINX Docker meta
7175
id: nginx-meta
@@ -74,11 +78,11 @@ jobs:
7478
images: |
7579
name=ghcr.io/nginx/nginx-gateway-fabric/${{ inputs.image == 'plus' && 'nginx-plus' || inputs.image }}
7680
tags: |
77-
type=semver,pattern={{version}}
78-
type=edge
79-
type=schedule
80-
type=ref,event=pr
81-
type=ref,event=branch,suffix=-rc,enable=${{ startsWith(github.ref, 'refs/heads/release') }}
81+
type=semver,pattern={{version}},suffix=${{ inputs.build-os != '' && format('-{0}', inputs.build-os) || '' }}
82+
type=schedule,suffix=${{ inputs.build-os != '' && format('-{0}', inputs.build-os) || '' }}
83+
type=edge,suffix=${{ inputs.build-os != '' && format('-{0}', inputs.build-os) || '' }}
84+
type=ref,event=pr,suffix=${{ inputs.build-os != '' && format('-{0}', inputs.build-os) || '' }}
85+
type=ref,event=branch,suffix=-rc${{ inputs.build-os != '' && format('-{0}', inputs.build-os) || '' }},enable=${{ startsWith(github.ref, 'refs/heads/release') }}
8286
8387
- name: Build binary
8488
uses: goreleaser/goreleaser-action@e435ccd777264be153ace6237001ef4d979d3a7a # v6.4.0
@@ -103,11 +107,11 @@ jobs:
103107
- name: Build NGINX Docker Image
104108
uses: docker/build-push-action@263435318d21b8e681c14492fe198d362a7d2c83 # v6.18.0
105109
with:
106-
file: build/Dockerfile${{ inputs.image == 'nginx' && '.nginx' || '' }}${{ inputs.image == 'plus' && '.nginxplus' || ''}}
110+
file: build${{ inputs.build-os != '' && format('/{0}', inputs.build-os) || '' }}/Dockerfile${{ inputs.image == 'nginx' && '.nginx' || '' }}${{ inputs.image == 'plus' && '.nginxplus' || '' }}
107111
tags: ${{ steps.nginx-meta.outputs.tags }}
108112
context: "."
109113
load: true
110-
cache-from: type=gha,scope=${{ inputs.image }}
114+
cache-from: type=gha,scope=${{ inputs.image }}${{ inputs.build-os != '' && format('-{0}', inputs.build-os) || '' }}
111115
pull: true
112116
build-args: |
113117
NJS_DIR=internal/controller/nginx/modules/src

.github/workflows/production-release.yml

Lines changed: 17 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,11 @@ on:
77
description: 'Release version (e.g., v2.0.3)'
88
required: true
99
type: string
10+
operator-version:
11+
description: 'Operator release version (e.g., v1.0.0). Optional'
12+
required: false
13+
type: string
14+
default: ''
1015
dry_run:
1116
description: 'If true, does a dry run of the production workflow'
1217
required: false
@@ -33,6 +38,7 @@ jobs:
3338
echo "Validating release from: ${GITHUB_REF}"
3439
3540
INPUT_VERSION="${{ github.event.inputs.version }}"
41+
INPUT_OPERATOR_VERSION="${{ github.event.inputs.operator-version }}"
3642
3743
# Validate version format
3844
if [[ ! "${INPUT_VERSION}" =~ ^v[0-9]+\.[0-9]+\.[0-9]+$ ]]; then
@@ -41,8 +47,17 @@ jobs:
4147
exit 1
4248
fi
4349
50+
# Validate version format if operator version is provided
51+
if [[ -n "${INPUT_OPERATOR_VERSION}" && ! "${INPUT_OPERATOR_VERSION}" =~ ^v[0-9]+\.[0-9]+\.[0-9]+$ ]]; then
52+
echo "❌ Invalid operator version format: ${INPUT_OPERATOR_VERSION}"
53+
echo "Expected format: v1.2.3"
54+
exit 1
55+
fi
56+
57+
4458
echo "✅ Valid release branch: ${GITHUB_REF}"
4559
echo "✅ Valid version format: ${INPUT_VERSION}"
60+
[[ -n "${INPUT_OPERATOR_VERSION}" ]] && echo "✅ Valid operator version format: ${INPUT_OPERATOR_VERSION}"
4661
4762
- name: Checkout Repository
4863
uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0
@@ -62,7 +77,7 @@ jobs:
6277
git tag -a "${VERSION}" -m "Release ${VERSION}"
6378
6479
if [[ "${{ inputs.dry_run }}" == "true" ]]; then
65-
echo "DRY RUN: Would push tag ${VERSION}"
80+
echo "DRY RUN: Would push tag ${VERSION} and operator tag ${{ github.event.inputs.operator-version || '' }}"
6681
git push --dry-run origin "${VERSION}"
6782
else
6883
git push origin "${VERSION}"
@@ -76,6 +91,7 @@ jobs:
7691
with:
7792
is_production_release: true
7893
release_version: ${{ github.event.inputs.version }}
94+
operator_version: ${{ github.event.inputs.operator-version }}
7995
dry_run: ${{ github.event.inputs.dry_run }}
8096
secrets: inherit
8197
permissions:

.pre-commit-config.yaml

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,6 @@ repos:
1010
- id: check-yaml
1111
args: [--allow-multiple-documents]
1212
exclude: (^charts/nginx-gateway-fabric/templates)
13-
- id: check-added-large-files
1413
- id: check-merge-conflict
1514
- id: check-case-conflict
1615
- id: check-vcs-permalinks

.yamllint.yaml

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,8 @@ rules:
2727
spaces: consistent
2828
indent-sequences: consistent
2929
check-multi-line-strings: true
30+
ignore: |
31+
operators/**/*
3032
key-duplicates: enable
3133
key-ordering: disable
3234
line-length:
@@ -38,6 +40,7 @@ rules:
3840
tests/suite/manifests/longevity/cronjob.yaml
3941
.goreleaser.yml
4042
charts/nginx-gateway-fabric/
43+
operators/config/crd/bases/gateway.nginx.org_nginxgatewayfabrics.yaml
4144
new-line-at-end-of-file: enable
4245
new-lines: enable
4346
octal-values: disable

0 commit comments

Comments
 (0)