diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index a564eab2ba..ff7fa5f8a9 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -145,6 +145,9 @@ jobs: filters: | charts: - charts/nginx-gateway-fabric/**/* + rbac: + - operators/config/rbac/role.yaml + - charts/nginx-gateway-fabric/templates/clusterrole.yaml - name: Output Variables id: vars @@ -164,6 +167,10 @@ jobs: - name: Check if all the generated files are up to date run: make generate-all && git diff --exit-code + - name: Verify Operator RBAC Synchronization + if: steps.filter.outputs.rbac == 'true' + run: ./operators/scripts/verify-rbac-sync.sh + unit-tests: name: Unit Tests runs-on: ubuntu-24.04 @@ -460,6 +467,27 @@ jobs: id-token: write # for docker/login to login to NGINX registry secrets: inherit + redhat-certification: + name: Submit images for RedHat certification + needs: [build-oss, build-operator] + if: ${{ inputs.is_production_release }} + strategy: + fail-fast: false + matrix: + include: + - image: ngf + tag: ${{ inputs.release_version }} + - image: nginx + tag: ${{ inputs.release_version }} + - image: operator + tag: ${{ inputs.operator_version }} + uses: ./.github/workflows/redhat-certification.yml + with: + image: ${{ matrix.image }} + tag: ${{ matrix.tag }} + dry_run: ${{ inputs.dry_run }} + secrets: inherit + functional-tests: name: Functional tests needs: [vars, build-oss, build-plus] diff --git a/.github/workflows/operator-bundle-pr.yml b/.github/workflows/operator-bundle-pr.yml new file mode 100644 index 0000000000..c4b5ba1fff --- /dev/null +++ b/.github/workflows/operator-bundle-pr.yml @@ -0,0 +1,104 @@ +name: Operator Bundle PR + +on: + workflow_dispatch: + inputs: + operator-version: + description: "Operator version for bundle generation" + required: true + default: "0.0.0" + submit-to-redhat: + description: "Submit bundle to RedHat certified-operators repo" + required: false + type: boolean + default: false + +defaults: + run: + shell: bash + +permissions: + contents: read + +jobs: + bundle: + runs-on: ubuntu-24.04 + permissions: + contents: write + pull-requests: write + steps: + - name: Checkout Repository + uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0 + + - name: Setup Go + uses: actions/setup-go@3041bf56c941b39c61721a86cd11f3bb1338122a # v5.2.0 + with: + go-version-file: go.mod + + - name: Install operator-sdk + run: | + OPERATOR_SDK_VERSION=v1.42.0 # renovate: datasource=github-tags depName=operator-framework/operator-sdk + curl -sSLo /tmp/operator-sdk https://github.com/operator-framework/operator-sdk/releases/download/${OPERATOR_SDK_VERSION}/operator-sdk_linux-amd64 + chmod +x /tmp/operator-sdk + sudo mv /tmp/operator-sdk /usr/local/bin/operator-sdk + + - name: Generate Bundle + working-directory: operators + run: | + make bundle-release + + - name: Create Pull Request + uses: peter-evans/create-pull-request@271a8d0340265f705b14b6d32b9829c1cb33d45e # v7.0.8 + with: + token: ${{ secrets.GITHUB_TOKEN }} + commit-message: Generate operator bundle for v${{ inputs.operator-version }} + title: Operator Bundle v${{ inputs.operator-version }} + draft: true + delete-branch: true + branch: operator/bundle-${{ inputs.operator-version }} + author: nginx-bot + committer: nginx-bot + body: | + This automated PR generates the operator bundle for v${{ inputs.operator-version }}. + + ## What's Changed + - Updated NGF image versions in sample manifests using image digests + - Generated bundle manifests and metadata + - Updated ClusterServiceVersion with proper annotations and descriptors + - Added OpenShift compatibility annotations + + - name: Checkout certified-operators repo + if: ${{ inputs.submit-to-redhat }} + uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0 + with: + token: ${{ secrets.NGINX_PAT }} + repository: nginx-bot/certified-operators + path: certified-operators + + - name: Update certified-operators repo + if: ${{ inputs.submit-to-redhat }} + working-directory: certified-operators/operators/nginx-gateway-fabric-operator + run: | + mkdir v${{ inputs.operator-version }} + cp -R ../../../operators/bundle/manifests v${{ inputs.operator-version }}/ + cp -R ../../../operators/bundle/metadata v${{ inputs.operator-version }}/ + + - name: Commit and push to certified-operators + if: ${{ inputs.submit-to-redhat }} + uses: stefanzweifel/git-auto-commit-action@28e16e81777b558cc906c8750092100bbb34c5e3 # v7.0.0 + with: + commit_message: operator nginx-gateway-fabric-operator (v${{ inputs.operator-version }}) + commit_author: nginx-bot + commit_user_name: nginx-bot + commit_user_email: integrations@nginx.com + create_branch: true + branch: update-nginx-gateway-fabric-operator-to-v${{ inputs.operator-version }} + repository: certified-operators + + - name: Create PR to RedHat certified-operators + if: ${{ inputs.submit-to-redhat }} + working-directory: certified-operators + run: | + gh pr create --title "operator nginx-gateway-fabric-operator (v${{ inputs.operator-version }})" --body "Update nginx-gateway-fabric-operator to v${{ inputs.operator-version }}" --head nginx-bot:update-nginx-gateway-fabric-operator-to-v${{ inputs.operator-version }} --base main --repo redhat-openshift-ecosystem/certified-operators + env: + GITHUB_TOKEN: ${{ secrets.NGINX_PAT }} diff --git a/.github/workflows/redhat-certification.yml b/.github/workflows/redhat-certification.yml new file mode 100644 index 0000000000..1a3aad1552 --- /dev/null +++ b/.github/workflows/redhat-certification.yml @@ -0,0 +1,78 @@ +name: RedHat Certification + +on: + workflow_call: + inputs: + image: + description: "Image type to certify (ngf, nginx, operator)" + required: true + type: string + tag: + description: "Image tag to certify" + required: true + type: string + dry_run: + description: "Run preflight checks without submitting" + required: false + type: boolean + default: false + +defaults: + run: + shell: bash + +permissions: + contents: read + +jobs: + certify: + name: Submit ${{ inputs.image }} image for certification + runs-on: ubuntu-24.04 + steps: + - name: Set image reference + id: image + run: | + case "${{ inputs.image }}" in + ngf) + echo "ref=ghcr.io/${{ github.repository_owner }}/nginx-gateway-fabric:${{ inputs.tag }}-ubi" >> $GITHUB_OUTPUT + ;; + nginx) + echo "ref=ghcr.io/${{ github.repository_owner }}/nginx-gateway-fabric/nginx:${{ inputs.tag }}-ubi" >> $GITHUB_OUTPUT + ;; + operator) + echo "ref=ghcr.io/${{ github.repository_owner }}/nginx-gateway-fabric/operator:${{ inputs.tag }}" >> $GITHUB_OUTPUT + ;; + *) + echo "Error: Unknown image type: ${{ inputs.image }}" + exit 1 + ;; + esac + + - name: Set component ID environment variable + run: | + case "${{ inputs.image }}" in + ngf) + echo "COMPONENT_ID=${{ secrets.CERTIFICATION_COMPONENT_ID_NGF }}" >> $GITHUB_ENV + ;; + nginx) + echo "COMPONENT_ID=${{ secrets.CERTIFICATION_COMPONENT_ID_NGINX }}" >> $GITHUB_ENV + ;; + operator) + echo "COMPONENT_ID=${{ secrets.CERTIFICATION_COMPONENT_ID_OPERATOR }}" >> $GITHUB_ENV + ;; + esac + + - name: Install preflight + run: | + PREFLIGHT_VERSION=1.14.1 # renovate: datasource=github-tags depName=redhat-openshift-ecosystem/openshift-preflight + curl -sSLo /tmp/preflight https://github.com/redhat-openshift-ecosystem/openshift-preflight/releases/download/${PREFLIGHT_VERSION}/preflight-linux-amd64 + chmod +x /tmp/preflight + sudo mv /tmp/preflight /usr/local/bin/preflight + preflight version + + - name: Run preflight check${{ !inputs.dry_run && ' and submit' || '' }} + run: | + preflight check container ${{ steps.image.outputs.ref }} \ + --pyxis-api-token="${{ secrets.PYXIS_API_TOKEN }}" \ + --certification-component-id="${COMPONENT_ID}" \ + ${{ !inputs.dry_run && '--submit' || '' }} diff --git a/.github/workflows/release-pr.yml b/.github/workflows/release-pr.yml index 4723710f76..3f80d3f0e8 100644 --- a/.github/workflows/release-pr.yml +++ b/.github/workflows/release-pr.yml @@ -7,6 +7,10 @@ on: description: "Version to release" required: true default: "0.0.0" + operator-version: + description: "Operator version to release" + required: true + default: "0.0.0" defaults: run: @@ -55,6 +59,22 @@ jobs: include: "charts/nginx-gateway-fabric/*.yaml" regex: false + - name: Find and Replace + uses: jacobtomlinson/gha-find-replace@f1069b438f125e5395d84d1c6fd3b559a7880cb5 # 3.0.5 + with: + find: "edge" + replace: ${{ inputs.operator-version }} + include: "operators/Dockerfile" + regex: false + + - name: Find and Replace + uses: jacobtomlinson/gha-find-replace@f1069b438f125e5395d84d1c6fd3b559a7880cb5 # 3.0.5 + with: + find: "VERSION ?= edge" + replace: "VERSION ?= ${{ inputs.operator-version }}" + include: "operators/Makefile" + regex: false + - name: Find and Replace uses: jacobtomlinson/gha-find-replace@f1069b438f125e5395d84d1c6fd3b559a7880cb5 # 3.0.5 with: diff --git a/.yamllint.yaml b/.yamllint.yaml index 6b5af8a6ec..0dc1e9ec90 100644 --- a/.yamllint.yaml +++ b/.yamllint.yaml @@ -29,6 +29,7 @@ rules: check-multi-line-strings: true ignore: | operators/**/* + .github/workflows/redhat-certification.yml key-duplicates: enable key-ordering: disable line-length: diff --git a/Makefile b/Makefile index c2acdaf0b6..f0845d6702 100644 --- a/Makefile +++ b/Makefile @@ -165,7 +165,11 @@ generate-helm-schema: ## Generate the Helm chart schema go run github.com/dadav/helm-schema/cmd/helm-schema@$(HELM_SCHEMA_VERSION) --chart-search-root=charts --add-schema-reference "--skip-auto-generation=required,additionalProperties" --append-newline .PHONY: generate-all -generate-all: generate generate-crds generate-helm-schema generate-manifests generate-api-docs generate-helm-docs ## Generate all the necessary files +generate-all: generate generate-crds generate-helm-schema generate-manifests generate-api-docs generate-helm-docs verify-operator-rbac ## Generate all the necessary files + +.PHONY: verify-operator-rbac +verify-operator-rbac: ## Verify operator RBAC is in sync with Helm chart + @./operators/scripts/verify-rbac-sync.sh .PHONY: clean clean: ## Clean the build diff --git a/docs/developer/release-process.md b/docs/developer/release-process.md index a4f94455c6..e22cd2e748 100644 --- a/docs/developer/release-process.md +++ b/docs/developer/release-process.md @@ -69,22 +69,34 @@ To create a new release, follow these steps: - Build NGF, NGINX and NGINX Plus container images with the release tag `X.Y.Z` and push them to the registries. - Package and publish the Helm chart to the registry. - Create a GitHub release with an autogenerated changelog and attached release artifacts. -7. Prepare and merge a PR into the main branch to update with similar information that you did in the release branch docs PR. Specifically: + - Automatically submit UBI images for RedHat certification: The NGF, NGINX, and Operator UBI images are automatically submitted to the RedHat Partner Portal for preflight certification. +7. Operator Bundle Generation: + - You can generate and submit the operator bundle by running the [Operator Bundle PR workflow](https://github.com/nginx/nginx-gateway-fabric/actions/workflows/operator-bundle-pr.yml) with the following inputs: + - Set `operator-version` to the operator version (e.g., `1.0.1`, without the `v` prefix) + - Set `submit-to-redhat` to `true` if you want to automatically open a PR to the [RedHat certified-operators repository](https://github.com/redhat-openshift-ecosystem/certified-operators) + - This workflow will: + - Generate the operator bundle manifests using image digests + - Create a draft PR in the NGF repository with the bundle changes + - If `submit-to-redhat` is enabled, automatically fork and open a PR to the RedHat certified-operators repo + - Review and merge the internal bundle PR once approved + - Monitor the RedHat certified-operators PR for review feedback +8. Prepare and merge a PR into the main branch to update with similar information that you did in the release branch docs and operator bundle PRs. Specifically: 1. [README](/README.md) to include the information about the latest release. 2. [changelog](/CHANGELOG.md). 3. Helm chart `version` field. 4. `GW_API_PREV_VERSION` in tests Makefile, if necessary. 5. Any references in the docs to the previous release. 6. Any installation instructions to ensure that the supported Gateway API and NGF versions are correct. Specifically, helm README. -8. Prepare and merge a PR into the main branch of the [documentation repository](https://github.com/nginx/documentation) from the relevant release branch, such as `ngf-release-2.0`. + 7. The operator bundle changes. +9. Prepare and merge a PR into the main branch of the [documentation repository](https://github.com/nginx/documentation) from the relevant release branch, such as `ngf-release-2.0`. - In the NGF repo, run `make generate-api-docs` and copy the generated file from `docs/api/content.md` into the documentation repo to `content/ngf/reference/api.md`. - Update the HTML file located at `layouts/shortcodes/version-ngf.html` with the latest version. Ensure you do not add an empty line to the file. - Documentation is built and deployed automatically from `main`, and will trigger when merging to it. - Create a new branch for the next release version, in the format `ngf-release-.`, substituting the *i* placeholders for major and minor version numbers. -9. Close the issue created in Step 1. -10. Ensure that the [associated milestone](https://github.com/nginx/nginx-gateway-fabric/milestones) is closed. -11. Verify that published artifacts in the release can be installed properly. -12. Submit the `conformance-profile.yaml` artifact from the release to the [Gateway API repo](https://github.com/kubernetes-sigs/gateway-api/tree/main/conformance/reports). +10. Close the issue created in Step 1. +11. Ensure that the [associated milestone](https://github.com/nginx/nginx-gateway-fabric/milestones) is closed. +12. Verify that published artifacts in the release can be installed properly. +13. Submit the `conformance-profile.yaml` artifact from the release to the [Gateway API repo](https://github.com/kubernetes-sigs/gateway-api/tree/main/conformance/reports). - Create a fork of the repository - Name the file based on the requirements of the [README](https://github.com/kubernetes-sigs/gateway-api/blob/main/conformance/reports/README.md). Update the README in the ngf directory and update the site source if necessary (see following example). - Open a PR. [Example](https://github.com/kubernetes-sigs/gateway-api/pull/3149) @@ -105,5 +117,5 @@ To create a new release, follow these steps: branch. 4. Test the release branch for release-readiness. 5. If a problem is found, return to Step 2. -6. Follow Steps 5-7 from the [Major or Minor Release](#major-or-minor-release) section. +6. Follow Steps 5-8 from the [Major or Minor Release](#major-or-minor-release) section. 7. Prepare and merge a PR into the main branch of the [documentation repository](https://github.com/nginx/documentation) to update the NGF version in `layouts/shortcodes/version-ngf.html`. If any of our APIs have changed, in the NGF repo, run `make generate-api-docs` and copy the generated file from `docs/api/content.md` into the documentation repo to `content/ngf/reference/api.md`. diff --git a/operators/Dockerfile b/operators/Dockerfile index 30b9ca87e0..8207660139 100644 --- a/operators/Dockerfile +++ b/operators/Dockerfile @@ -10,7 +10,7 @@ COPY LICENSE /licenses/LICENSE LABEL name="nginx-gateway-fabric-operator" \ maintainer="kubernetes@nginx.com" \ vendor="F5 NGINX" \ - version="1.0.0" \ + version="edge" \ release="1" \ summary="NGINX Gateway Fabric Operator" \ description="Helm-based operator for NGINX Gateway Fabric" diff --git a/operators/Makefile b/operators/Makefile index 2b0f08a7c8..5848e8ff63 100644 --- a/operators/Makefile +++ b/operators/Makefile @@ -1,6 +1,6 @@ # VERSION defines the project version for the bundle. # Update this value when you upgrade the version of the operator. -VERSION ?= 1.0.1 +VERSION ?= edge # renovate: datasource=github-tags depName=operator-framework/operator-sdk OPERATOR_SDK_VERSION ?= v1.42.0 @@ -41,6 +41,10 @@ all: docker-build help: ## Display this help. @awk 'BEGIN {FS = ":.*##"; printf "\nUsage:\n make \033[36m\033[0m\n"} /^[a-zA-Z_0-9-]+:.*?##/ { printf " \033[36m%-15s\033[0m %s\n", $$1, $$2 } /^##@/ { printf "\n\033[1m%s\033[0m\n", substr($$0, 5) } ' $(MAKEFILE_LIST) +.PHONY: verify-rbac +verify-rbac: ## Verify operator RBAC includes all Helm chart permissions. + @./scripts/verify-rbac-sync.sh + ##@ Build .PHONY: run @@ -140,7 +144,7 @@ endif endif .PHONY: bundle -bundle: kustomize operator-sdk ## Generate bundle manifests and metadata, then validate generated files. +bundle: verify-rbac kustomize operator-sdk ## Generate bundle manifests and metadata, then validate generated files. $(OPERATOR_SDK) generate kustomize manifests -q cd config/manager && $(KUSTOMIZE) edit set image controller=$(IMG) $(KUSTOMIZE) build config/manifests | $(OPERATOR_SDK) generate bundle $(BUNDLE_GEN_FLAGS) diff --git a/operators/README.md b/operators/README.md index 883c0817b4..acf16fbd0a 100644 --- a/operators/README.md +++ b/operators/README.md @@ -94,33 +94,64 @@ operator-sdk scorecard bundle/ ### Releases -Once NGF has released, we can prepare the Operator release using the published NGF images. +The Operator release process is largely automated. Once NGF has released, follow these steps: -The Operator image is built using the Helm Chart from the root directory, so those changes are kept in sync by running `make docker-build` from the release branch (to be automated). The Operator image can be published and certified at the same time as the UBI based NGF control plane and OSS data plane images (instructions to follow, to be automated). +#### Automated Release Process -Once the images are certified and published, we can create the bundle for certification. This is mostly a scripted (note: to be automated) process. -However, there are a few items that need to be kept in sync manually: +1. Production Release: During the NGF production release (via the CI workflow), set the `operator_version` input to the new operator version (e.g., `v1.0.1`). This will: + - Build and push the operator image with the release tag + - Automatically submit the operator UBI image for RedHat certification via preflight -1. RBAC: - The Operator requires RBAC rules to include permissions for anything the NGF Helm chart - can deploy (e.g. Pods, ConfigMaps, Gateways, HPAs, etc), and all permissions that NGF - itself has permissions for (e.g. all the Gateway APIs etc). +2. Bundle Generation: After the production release completes, run the [Operator Bundle PR workflow](https://github.com/nginx/nginx-gateway-fabric/actions/workflows/operator-bundle-pr.yml): + - Set `operator-version` to the operator version without the `v` prefix (e.g., `1.0.1`) + - Set `submit-to-redhat` to `true` to automatically submit to the RedHat certified-operators repository - If the RBAC permissions either for or of the underlying Helm Chart changes, these need to be updated in [RBAC manifest](config/rbac/role.yaml). + This workflow will: + - Generate bundle manifests with NGF image versions updated to use image digests + - Create a draft PR in the NGF repository with the bundle changes + - If enabled, automatically: + - Fork and update the [RedHat certified-operators repository](https://github.com/redhat-openshift-ecosystem/certified-operators) + - Create a branch with the new bundle version + - Open a PR to the upstream certified-operators repo - The next time `make bundle` is ran, these RBAC changes will be reflected in the resulting bundle manifests. +3. Review and Merge: + - Review and merge the internal bundle PR once approved + - Monitor the RedHat certified-operators PR for review feedback from RedHat + - Ensure the bundle PR changes are duplicated back to the main branch as well -2. Sample manifest: - The [example manifest](config/samples/gateway_v1alpha1_nginxgatewayfabric.yaml) may need to be updated either to add new important fields, or to change existing entries. +#### RBAC Synchronization -3. Operator version: - Update the VERSION in the Makefile to reflect the version of the Operator being released. +The Operator requires RBAC rules that include: -When you are ready to release the bundle, run `make bundle-release`. This will update the NGF image version tags, and create the bundle manifests. +- Permissions for anything the NGF Helm chart can deploy (e.g. Pods, ConfigMaps, Gateways, HPAs, etc) +- All permissions that NGF itself has (e.g. all the Gateway API resources) -To test the bundle locally, follow the `Building and Testing the Operator Locally` above. +Automated Verification: A CI check runs automatically on PRs that modify RBAC files to ensure the operator RBAC includes all permissions from the Helm chart. You can also verify locally: -To submit the bundle for certification, open a PR in the [RedHat Certified Operators repo](https://github.com/redhat-openshift-ecosystem/certified-operators) using your a branch from your own fork (Note: must have RedHat Portal access) following the guidelines in the repo. +```bash +./operators/scripts/verify-rbac-sync.sh +``` + +The verification script: + +- Renders the Helm chart with all features enabled to extract the maximum permission set +- Compares operator RBAC permissions with the rendered chart +- Handles wildcard permissions (`verbs: ["*"]`) correctly +- Fails if any required permissions are missing + +If RBAC permissions in the Helm chart change, update [config/rbac/role.yaml](config/rbac/role.yaml) accordingly. The next time `make bundle` runs, these RBAC changes will be reflected in the bundle manifests. + +#### Manual Items to Check + +Before releasing, verify these items are up-to-date: + +1. Sample manifest: The [example manifest](config/samples/gateway_v1alpha1_nginxgatewayfabric.yaml) may need updates to add new important fields or change existing entries. + +2. Operator version: The VERSION in the [Makefile](Makefile) is automatically updated during the release process, but verify it matches the intended release version. + +#### Local Testing + +To test the operator bundle locally before releasing, follow the [Building and Testing the Operator Locally](#building-and-testing-the-operator-locally) instructions above. ## License diff --git a/operators/scripts/verify-rbac-sync.sh b/operators/scripts/verify-rbac-sync.sh new file mode 100755 index 0000000000..9764728f8c --- /dev/null +++ b/operators/scripts/verify-rbac-sync.sh @@ -0,0 +1,110 @@ +#!/bin/bash +# verify-rbac-sync.sh - Verify operator RBAC includes all permissions from NGF Helm chart + +set -e + +SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" +OPERATOR_RBAC="$SCRIPT_DIR/../config/rbac/role.yaml" +HELM_CHART_DIR="$SCRIPT_DIR/../../charts/nginx-gateway-fabric" + +echo "Verifying RBAC synchronization..." +echo "Operator RBAC: $OPERATOR_RBAC" +echo "Helm Chart: $HELM_CHART_DIR" +echo "" + +# Check if required tools are installed +if ! command -v yq &>/dev/null; then + echo "Error: yq is not installed. Please install yq to run this script." + echo "Installation: brew install yq (macOS) or see https://github.com/mikefarah/yq" + exit 1 +fi + +if ! command -v helm &>/dev/null; then + echo "Error: helm is not installed. Please install helm to run this script." + echo "Installation: brew install helm (macOS) or see https://helm.sh/docs/intro/install/" + exit 1 +fi + +# Render Helm chart with ALL features enabled to get maximum set of permissions +echo "Rendering Helm chart with all features enabled..." +HELM_RENDERED=$(helm template test "$HELM_CHART_DIR" \ + --set nginxGateway.gwAPIExperimentalFeatures.enable=true \ + --set nginxGateway.gwAPIInferenceExtension.enable=true \ + --set nginxGateway.snippetsFilters.enable=true \ + --set nginxGateway.leaderElection.enable=true \ + --set nginxGateway.productTelemetry.enable=true \ + --set nginx.plus=true \ + 2>/dev/null) + +# Extract ClusterRole rules from rendered template +echo "Extracting Helm chart RBAC rules (all possible permissions)..." +HELM_RULES=$(echo "$HELM_RENDERED" | yq eval 'select(.kind == "ClusterRole") | .rules[] | .apiGroups[] as $group | .resources[] as $res | .verbs[] | $group + "/" + $res + "/" + .' - 2>/dev/null | sort -u) + +# Extract operator RBAC rules including wildcard expansion +echo "Extracting operator RBAC rules..." +# Get rules with explicit verbs +OPERATOR_EXPLICIT=$(yq eval '.rules[] | select(.verbs[] != "*") | .apiGroups[] as $group | .resources[] as $res | .verbs[] | $group + "/" + $res + "/" + .' "$OPERATOR_RBAC" 2>/dev/null | sort -u) + +# Get rules with wildcard verbs - these match ANY verb for the apiGroup/resource combo +OPERATOR_WILDCARDS=$(yq eval '.rules[] | select(.verbs[] == "*") | .apiGroups[] as $group | .resources[] | $group + "/" + .' "$OPERATOR_RBAC" 2>/dev/null | sort -u) + +# Create temp file for missing rules +MISSING_TEMP=$(mktemp) + +# Check each Helm rule +echo "$HELM_RULES" | while IFS= read -r helm_rule; do + if [ -n "$helm_rule" ]; then + # Extract apiGroup/resource from the rule + api_group_resource=$(echo "$helm_rule" | cut -d'/' -f1-2) + + # Check if this rule is explicitly in operator RBAC + if ! echo "$OPERATOR_EXPLICIT" | grep -qF "$helm_rule"; then + # Check if operator has wildcard for this apiGroup/resource + if ! echo "$OPERATOR_WILDCARDS" | grep -qF "$api_group_resource"; then + echo "$helm_rule" >>"$MISSING_TEMP" + fi + fi + fi +done + +# Read missing rules +if [ -s "$MISSING_TEMP" ]; then + MISSING_RULES=$(cat "$MISSING_TEMP" | sort -u) + rm "$MISSING_TEMP" + + echo "✗ FAILURE: Operator RBAC is missing the following permissions required by the Helm chart:" + echo "" + + # Group by API group for better readability + CURRENT_API_GROUP="" + echo "$MISSING_RULES" | while IFS= read -r rule; do + if [ -n "$rule" ]; then + apiGroup=$(echo "$rule" | cut -d'/' -f1) + resource=$(echo "$rule" | cut -d'/' -f2) + verb=$(echo "$rule" | cut -d'/' -f3) + + # Display empty string as "core" for readability + display_group="$apiGroup" + [ -z "$apiGroup" ] && display_group='core ("")' + + if [ "$apiGroup" != "$CURRENT_API_GROUP" ]; then + if [ -n "$CURRENT_API_GROUP" ]; then + echo "" + fi + echo " API Group: $display_group" + CURRENT_API_GROUP="$apiGroup" + fi + echo " - resource: $resource, verb: $verb" + fi + done + echo "" + echo "Please update $OPERATOR_RBAC to include these permissions." + echo "The operator must have all permissions that NGF requires (including conditional features)," + echo "plus additional permissions to manage Deployments, Services, ConfigMaps, and other resources." + exit 1 +else + rm "$MISSING_TEMP" + echo "✓ SUCCESS: Operator RBAC includes all permissions from Helm chart" + echo " (including wildcard permissions that cover specific verbs)" + exit 0 +fi