diff --git a/.github/workflows/pr-unit-tests.yaml b/.github/workflows/pr-unit-tests.yaml new file mode 100644 index 00000000000..187610773ec --- /dev/null +++ b/.github/workflows/pr-unit-tests.yaml @@ -0,0 +1,46 @@ +name: Unit Tests + +# This workflow invokes unit tests for the Gloo Gateway project +# It was introduced during the 1.17 quarter, where we added a new project (projects/gateway2) +# and therefore we only run those new tests here +# +# Our historical unit tests are run via CloudBuild +# Overtime, it would be valuable to consolidate these approaches + +on: + pull_request: + types: [opened, synchronize, reopened, ready_for_review] + +jobs: + # Runs the unit tests for `projects/gateway2` + kube_gateway_project: + name: projects/gateway2 + runs-on: ubuntu-22.04 + timeout-minutes: 10 + # Other unit tests are run by our CloudBuild runner + # These tests do run on Draft PRs, and so we maintain that consistency and run this job on Draft PRs as well + steps: + - uses: actions/checkout@v4 + - name: Setup Go + uses: actions/setup-go@v5 + with: + go-version-file: go.mod + - name: Build + run: go build -v ./projects/gateway2/... ./projects/gloo/cli/cmd + - name: Install Test Utils + shell: bash + run: make -C ./projects/gateway2/ install-go-tools + - name: Install Test Coverage Tools + shell: bash + run: make install-go-test-coverage + - name: Run Tests + shell: bash + env: + TEST_PKG: ./projects/gateway2/... + run: make go-test-with-coverage + - name: Validate Test Coverage + shell: bash + # The make will error if test coverage drops below a certain threshold + # We intentionally ignore the errors while we build out our test coverage, to establish a good baseline + # However, we should strive to establish a baseline, and then make it required on PRs + run: make --always-make --ignore-errors validate-test-coverage \ No newline at end of file diff --git a/.github/workflows/pr.yaml b/.github/workflows/pr.yaml deleted file mode 100644 index 6507c4866a4..00000000000 --- a/.github/workflows/pr.yaml +++ /dev/null @@ -1,23 +0,0 @@ -name: GGII Tests -on: - pull_request: - types: [opened, synchronize, reopened, ready_for_review] - -jobs: - test_gloo_gateway: - name: Build and Test Gloo Gateway - runs-on: ubuntu-22.04 - timeout-minutes: 10 - if: ${{ !github.event.pull_request.draft }} - steps: - - uses: actions/checkout@v4 - - name: Setup Go - uses: actions/setup-go@v5 - with: - go-version-file: go.mod - - name: Build - run: go build -v ./projects/gateway2/... ./projects/gloo/cli/cmd - - name: Install utils for env tests - run: make -C ./projects/gateway2/ install-go-tools - - name: Test with the Go CLI - run: go test ./projects/gateway2/... diff --git a/Makefile b/Makefile index 0ab78ffa6b7..a84e74db4a2 100644 --- a/Makefile +++ b/Makefile @@ -165,6 +165,10 @@ install-go-tools: mod-download ## Download and install Go dependencies go install github.com/golangci/golangci-lint/cmd/golangci-lint@$(LINTER_VERSION) go install github.com/quasilyte/go-ruleguard/cmd/ruleguard@v0.3.16 +.PHONY: install-go-test-coverage +install-go-test-coverage: + go install github.com/vladopajic/go-test-coverage/v2@v2.8.1 + .PHONY: check-format check-format: NOT_FORMATTED=$$(gofmt -l ./projects/ ./pkg/ ./test/) && if [ -n "$$NOT_FORMATTED" ]; then echo These files are not formatted: $$NOT_FORMATTED; exit 1; fi @@ -194,7 +198,7 @@ GINKGO_VERSION ?= $(shell echo $(shell go list -m github.com/onsi/ginkgo/v2) | c GINKGO_ENV ?= GOLANG_PROTOBUF_REGISTRATION_CONFLICT=ignore ACK_GINKGO_RC=true ACK_GINKGO_DEPRECATIONS=$(GINKGO_VERSION) GINKGO_FLAGS ?= -tags=purego --trace -progress -race --fail-fast -fail-on-pending --randomize-all --compilers=5 GINKGO_REPORT_FLAGS ?= --json-report=test-report.json --junit-report=junit.xml -output-dir=$(OUTPUT_DIR) -GINKGO_COVERAGE_FLAGS ?= --cover --covermode=count --coverprofile=coverage.cov +GINKGO_COVERAGE_FLAGS ?= --cover --covermode=atomic --coverprofile=coverage.cov TEST_PKG ?= ./... # Default to run all tests # This is a way for a user executing `make test` to be able to provide flags which we do not include by default @@ -237,6 +241,7 @@ test: ## Run all tests, or only run the test package at {TEST_PKG} if it is spec $(GINKGO_FLAGS) $(GINKGO_REPORT_FLAGS) $(GINKGO_USER_FLAGS) \ $(TEST_PKG) +# https://go.dev/blog/cover#heat-maps .PHONY: test-with-coverage test-with-coverage: GINKGO_FLAGS += $(GINKGO_COVERAGE_FLAGS) test-with-coverage: test @@ -277,7 +282,8 @@ GO_TEST_ENV ?= GOLANG_PROTOBUF_REGISTRATION_CONFLICT=ignore # Testings flags: https://pkg.go.dev/cmd/go#hdr-Testing_flags # The default timeout for a suite is 10 minutes, but this can be overridden by setting the -timeout flag. Currently set # to 25 minutes based on the time it takes to run the longest test setup (k8s_gw_test). -GO_TEST_ARGS ?= -timeout=25m -cpu=4 -race +GO_TEST_ARGS ?= -timeout=25m -cpu=4 -race -outputdir=$(OUTPUT_DIR) +GO_TEST_COVERAGE_ARGS ?= --cover --covermode=atomic --coverprofile=cover.out # This is a way for a user executing `make go-test` to be able to provide args which we do not include by default # For example, you may want to run tests multiple times, or with various timeouts @@ -290,6 +296,19 @@ go-test: clean-bug-report $(BUG_REPORT_DIR) # Ensure the bug_report dir is reset $(GO_TEST_ARGS) $(GO_TEST_USER_ARGS) \ $(TEST_PKG) +# https://go.dev/blog/cover#heat-maps +.PHONY: go-test-with-coverage +go-test-with-coverage: GO_TEST_ARGS += $(GO_TEST_COVERAGE_ARGS) +go-test-with-coverage: go-test + +.PHONY: validate-test-coverage +validate-test-coverage: + ${GOBIN}/go-test-coverage --config=./test_coverage.yml + +.PHONY: view-test-coverage +view-test-coverage: + go tool cover -html $(OUTPUT_DIR)/cover.out + #---------------------------------------------------------------------------------- # Clean #---------------------------------------------------------------------------------- diff --git a/README.md b/README.md index 9be4c5a1963..8e2c453b9e5 100644 --- a/README.md +++ b/README.md @@ -1,7 +1,7 @@

- Gloo Gateway v2 + Gloo Gateway
An Envoy-Powered API Gateway

@@ -11,89 +11,19 @@ > **Important** > Gloo Gateway is now a fully conformant Kubernetes Gateway API implementation! > -> The existing Gloo Edge v1 APIs were not changed and continue to be fully supported. +> The existing Gloo Edge APIs were not changed and continue to be fully supported. ## About Gloo Gateway Gloo Gateway is a powerful Kubernetes-native ingress controller and API gateway that is based on the Kubernetes Gateway API. It excels in function-level routing, supports legacy apps, microservices and serverless, offers robust discovery capabilities, integrates seamlessly with open-source projects, and is designed to support hybrid applications with various technologies, architectures, protocols, and clouds. -[**Installation**](https://docs.solo.io/gloo-gateway/v2/quickstart)   | -  [**Documentation**](https://docs.solo.io/gloo-gateway/v2)   | +[**Installation**](https://docs.solo.io/gateway/latest/quickstart/)   | +  [**Documentation**](https://docs.solo.io/gateway/latest/)   |   [**Blog**](https://www.solo.io/blog/?category=gloo)   |   [**Slack**](https://slack.solo.io)   |   [**Twitter**](https://twitter.com/soloio_inc) |   [**Enterprise Trial**](https://www.solo.io/free-trial/) -
Gloo Gateway v2 Architecture
- -## Quickstart with `glooctl` -Install Gloo Gateway and set up routing to the httpbin sample app. - -1. Install `glooctl`, the Gloo Gateway command line tool. - ```sh - curl -sL https://run.solo.io/gloo/install | GLOO_VERSION=v2.0.0-beta1 sh - export PATH=$HOME/.gloo/bin:$PATH - ``` - -2. Install the Gloo Gateway v2 control plane, and wait for it to come up. - ```sh - glooctl install - ``` - -3. Deploy the httpbin sample app, along with a Gateway and HTTPRoute to access it. - ```sh - kubectl -n httpbin apply -f https://raw.githubusercontent.com/solo-io/gloo/v2.0.x/projects/gateway2/examples/httpbin.yaml - ``` - -4. Port-forward the Gateway. - ```sh - kubectl port-forward deployment/gloo-proxy-http -n httpbin 8080:8080 - ``` - -5. Send a request through our new Gateway. - ```sh - curl -I localhost:8080/status/200 -H "host: www.example.com" -v - ``` - -Congratulations! You successfully installed Gloo Gateway and used an HTTP gateway to expose the httpbin sample app. - -> **Note** -> To learn more about Gloo Gateway's support for the Kubernetes Gateway API, see the [docs](https://docs.solo.io/gloo-gateway/v2/). - -## Quickstart with Helm - -1. Install the custom resources of the Kubernetes Gateway API. - ```sh - kubectl apply -f https://github.com/kubernetes-sigs/gateway-api/releases/download/v1.0.0/standard-install.yaml - ``` - -2. Install Gloo Gateway v2. This command creates the `gloo-system` namespace and installs the Gloo Gateway v2 control plane into it. - ```sh - helm install default -n gloo-system --create-namespace oci://ghcr.io/solo-io/helm-charts/gloo-gateway --version 2.0.0-beta1 - ``` - -3. Verify that the Gloo Gateway v2 control plane is up and running and that the `gloo-gateway` GatewayClass is created. - ```sh - kubectl get pods -n gloo-system - kubectl get gatewayclass gloo-gateway - ``` - -4. Deploy the httpbin sample app, along with a Gateway and HTTPRoute to access it. - ```sh - kubectl -n httpbin apply -f https://raw.githubusercontent.com/solo-io/gloo/v2.0.x/projects/gateway2/examples/httpbin.yaml - ``` - -5. Port-forward the Gateway. - ```sh - kubectl port-forward deployment/gloo-proxy-http -n httpbin 8080:8080 - ``` - -6. Send a request through our new Gateway. - ```sh - curl -I localhost:8080/status/200 -H "host: www.example.com" -v - ``` - -> **Note** -> To learn more about Gloo Gateway's support for the Kubernetes Gateway API, see the [docs](https://docs.solo.io/gloo-gateway/v2/). +
Gloo Gateway Architecture
### Using Gloo Gateway - **Kubernetes Gateway API**: Gloo Gateway is a feature-rich ingress controller, built on top of the Envoy Proxy and fully conformant with the Kubernetes Gateway API. @@ -113,14 +43,14 @@ C) Allow different teams in an organization choose different architectures. See ## Next Steps - Join us on our Slack channel: [https://slack.solo.io/](https://slack.solo.io/) - Follow us on Twitter: [https://twitter.com/soloio_inc](https://twitter.com/soloio_inc) -- Check out the docs: [https://docs.solo.io/gloo-gateway/v2](https://docs.solo.io/gloo-gateway/v2) -- Check out the code and contribute: [Contribution Guides](/devel/contributing) +- Check out the docs: [https://docs.solo.io/gateway/latest/](https://docs.solo.io/gateway/latest/) -## Thanks +## Contributing to Gloo Gateway +The [devel](devel) folder should be the starting point for understanding the code, and contributing to the product. +## Thanks **Gloo Gateway** would not be possible without the valuable open-source work of projects in the community. We would like to extend a special thank-you to [Envoy](https://www.envoyproxy.io). ## Security - *Reporting security issues* : We take Gloo Gateway's security very seriously. If you've found a security issue or a potential security issue in Gloo Gateway, please DO NOT file a public Github issue, instead send your report privately to [security@solo.io](mailto:security@solo.io). diff --git a/changelog/v1.17.0-rc6/backport-recent-changes.yaml b/changelog/v1.17.0-rc6/backport-recent-changes.yaml new file mode 100644 index 00000000000..86c754c932d --- /dev/null +++ b/changelog/v1.17.0-rc6/backport-recent-changes.yaml @@ -0,0 +1,25 @@ +changelog: + - type: NON_USER_FACING + issueLink: https://github.com/solo-io/solo-projects/issues/6026 + resolvesIssue: false + description: >- + Introduce code coverage tooling, introduce a basic check on projects/gateway2 tests + so that users have some feedback (that is not yet required). + + Update the `devel` folder to remove Gloo Edge references, and replace with Gloo Gateway + - type: NON_USER_FACING + description: >- + Resolve the iosnapshot/history_test flake, by ensuring that asynchronous operations + are provided time to complete. + - type: HELM + issueLink: https://github.com/solo-io/solo-projects/issues/6352 + resolvesIssue: false + description: >- + Introduce `gateway.validation.webhook.enablePolicyApi` which controls whether or not RouteOptions and + VirtualHostOptions CRs are subject to validation. By default, this value is true. + The validation of these Policy APIs only runs if the Kubernetes Gateway integration is enabled (`kubeGateway.enabled`). + - type: NON_USER_FACING + issueLink: https://github.com/solo-io/solo-projects/issues/6408 + resolvesIssue: false + description: >- + Avoid a race condition in the deployer module, but not using a long-lived context. \ No newline at end of file diff --git a/devel/README.md b/devel/README.md index f467191fdd6..3e1d691eb9d 100644 --- a/devel/README.md +++ b/devel/README.md @@ -1,15 +1,14 @@ -# Developing Gloo Edge +# Developing Gloo Gateway -Find tools and information to help you develop the Gloo Edge project. +Find tools and information to help you develop the Gloo Gateway project. +* `architecture`: Descriptions about high-level design and implementation details of various packages and features. * `contributing`: Information to help you contribute to the project, such as how to open issues, review pull requests, generate code, and backport fixes. * `debugging`: Troubleshooting steps for debugging frequent issues. * `testing`: Descriptions on how the tests work and how to use them. -* `tools`: A set of scripts and tools that are intended to help you develop the Gloo Edge project's codebase. Learn more about these tools in the short descriptions later in this readme. - -_**Note**: For tools that help maintain an installation of Gloo Edge (the product, not the project codebase), build those tools into the [CLI](/projects/gloo/cli) instead._ +* `tools`: A set of scripts and tools that are intended to help you develop the Gloo Gateway project's codebase. Learn more about these tools in the short descriptions later in this readme. Other resources: -* [Developer guide](https://docs.solo.io/gloo-edge/latest/guides/dev/) to set up your development environment and learn more about extending the functionality of the Gloo Edge project and related plug-ins. While written for external contributors, internal Solo developers might also find this guide helpful when onboarding. -* [Product documentation](https://docs.solo.io/gloo-edge/latest/) with guides for end users to use Gloo Edge as a product +* [Developer guide](https://docs.solo.io/gloo-edge/latest/guides/dev/) to set up your development environment and learn more about extending the functionality of the Gloo Gateway project and related plug-ins. While written for external contributors, internal Solo developers might also find this guide helpful when onboarding. +* [Product documentation](https://docs.solo.io/gloo-edge/latest/) with guides for end users to use Gloo Gateway as a product * [Guide to contribute to the documentation](https://docs.solo.io/gloo-edge/latest/contributing/documentation/) \ No newline at end of file diff --git a/devel/architecture/endpoint-discovery.md b/devel/architecture/endpoint-discovery.md index 93401ed2214..38d48dfab61 100644 --- a/devel/architecture/endpoint-discovery.md +++ b/devel/architecture/endpoint-discovery.md @@ -1,12 +1,12 @@ # Endpoint Discovery Service (EDS) ## Overview -Envoy supports a variety of mechanisms to configure [Service Discovery](https://www.envoyproxy.io/docs/envoy/latest/intro/arch_overview/upstream/service_discovery#arch-overview-service-discovery), the mechanism Envoy uses to resolve the members of the cluster. One of the more complex mechanisms is [EDS](https://www.envoyproxy.io/docs/envoy/latest/intro/arch_overview/upstream/service_discovery#endpoint-discovery-service-eds), where the xDS management server (Gloo Edge) provides the Endpoints for a given Cluster via an API. +Envoy supports a variety of mechanisms to configure [Service Discovery](https://www.envoyproxy.io/docs/envoy/latest/intro/arch_overview/upstream/service_discovery#arch-overview-service-discovery), the mechanism Envoy uses to resolve the members of the cluster. One of the more complex mechanisms is [EDS](https://www.envoyproxy.io/docs/envoy/latest/intro/arch_overview/upstream/service_discovery#endpoint-discovery-service-eds), where the xDS management server (Gloo Gateway) provides the Endpoints for a given Cluster via an API. -In Gloo Edge, Endpoints can be discovered dynamically via the Endpoint Discovery feature, and then served to the Envoy proxy via the EDS API. +In Gloo Gateway, Endpoints can be discovered dynamically via the Endpoint Discovery feature, and then served to the Envoy proxy via the EDS API. ## How it works -EDS runs in the [Gloo](/projects/gloo) component of Gloo Edge. +EDS runs in the [Gloo](/projects/gloo) component of Gloo Gateway. We rely on an [In Memory Endpoint Client](https://github.com/solo-io/gloo/blob/a39fb91c2fb122d5a34353dff891e0b0044bf1dc/projects/gloo/pkg/syncer/setup/setup_syncer.go#L469), meaning that when we “write” an Endpoint, it is just persisted in memory. In Memory clients signal updates to the emitter by two mechanisms: - [timed update](https://github.com/solo-io/solo-kit/blob/1f34a76bf919fd40a50e4504a837ee4b41b7f215/pkg/api/v1/clients/memory/resource_client.go#L238) diff --git a/devel/architecture/external-options.md b/devel/architecture/external-options.md index 1ed7691675f..61b9336513f 100644 --- a/devel/architecture/external-options.md +++ b/devel/architecture/external-options.md @@ -1,7 +1,7 @@ # External Options (VirtualHostOption and RouteOption) ## Overview -Gloo Edge supports decoupling certain resources from the definitions of options related to the resource. Currently there are two objects which support delegating options definition in this way: +Gloo Gateway supports decoupling certain resources from the definitions of options related to the resource. Currently there are two objects which support delegating options definition in this way: - A VirtualHost (exists on a VirtualService) can be configured with the separate resource [VirtualHostOption](./projects/gateway/api/v1/external_options.proto). - A Route (exists on a VirtualHost within a VirtualService or on a RouteTable) can be configured with the separate resource [RouteOption](./projects/gateway/api/v1/external_options.proto). diff --git a/devel/architecture/static_metadata.md b/devel/architecture/static_metadata.md index 6e692524376..28e778de2f3 100644 --- a/devel/architecture/static_metadata.md +++ b/devel/architecture/static_metadata.md @@ -8,7 +8,7 @@ The [Gloo Proxy Api](https://docs.solo.io/gloo-edge/latest/reference/api/github. This metadata is not required and the `resourceKind`, `resourceRef.name`, and `resourceRef.namespace` fields which compose the metadata are plain strings. -While the objects used to create the Proxy Api resources are and should be generally irrelevant to the functionality of Gloo Edge, they do provide user facing value as sources of names and labels. +While the objects used to create the Proxy Api resources are and should be generally irrelevant to the functionality of Gloo Gateway, they do provide user facing value as sources of names and labels. ## Current uses of this data ### Open Telemetry `service.name` diff --git a/devel/architecture/upstream-discovery.md b/devel/architecture/upstream-discovery.md index a1df5a6ef7d..87a7aaf8ab3 100644 --- a/devel/architecture/upstream-discovery.md +++ b/devel/architecture/upstream-discovery.md @@ -3,10 +3,10 @@ ## Overview A [Gloo Upstream](/projects/gloo/api/v1/upstream.proto) represents a destination for routing HTTP requests. An Upstream can be compared to [clusters](https://www.envoyproxy.io/docs/envoy/latest/api-v3/config/cluster/v3/cluster.proto) in Envoy terminology. -Upstreams can either be defined statically in a cluster, or can be discovered dynamically via Gloo Edge's Upstream Discovery feature. +Upstreams can either be defined statically in a cluster, or can be discovered dynamically via Gloo Gateway's Upstream Discovery feature. ## How it works -UDS runs in the [Discovery](/projects/discovery) component of Gloo Edge. +UDS runs in the [Discovery](/projects/discovery) component of Gloo Gateway. Create a [discovery emitter](https://github.com/solo-io/gloo/blob/8bbe175ea136178bfe8b4d103ae702d4965c4c75/projects/gloo/pkg/api/v1/discovery_snapshot_emitter.sk.go#L135), which is responsible for the following: - Emit a snapshot of the resources that are required for UDS to operate (Upstreams, Secrets, Kubernetes Namespaces) diff --git a/devel/contributing/backports.md b/devel/contributing/backports.md index b663d00b5e5..3079e32bc69 100644 --- a/devel/contributing/backports.md +++ b/devel/contributing/backports.md @@ -1,26 +1,26 @@ # Backports ## What is a backport? -A backport is a change that is introduced on the main branch, and then applied to a previous version of Gloo Edge. +A backport is a change that is introduced on the main branch, and then applied to a previous version of Gloo Gateway. ## When is backporting appropriate? For a backport to be appropriate it must fit the following criteria: -- The change must have a clear rationale for why it is needed on a previous version of Gloo Edge. +- The change must have a clear rationale for why it is needed on a previous version of Gloo Gateway. - The change must be a low-risk change, this typically means it is a bug fix or a non-breaking change. - The proposed change is targeted to a [supported, stable release branch](https://docs.solo.io/gloo-edge/latest/reference/support/). - If the change is a feature request, you must have explicit approval from the product and engineering teams. This approval can also be solicited on the backport prs themselves - Generally a backport for a feature should have been requested by at least one of these teams to be considered in the first place ## How to identify a backport -On the issue that tracks the desired functionality, apply a `release/1.N` label to indicate the version of Gloo Edge you wish the request to be supported on. +On the issue that tracks the desired functionality, apply a `release/1.N` label to indicate the version of Gloo Gateway you wish the request to be supported on. -For example, if there is a `release/1.14` label, that means the issue is targeted to be introduced first on the stable main branch, and then backported to Gloo Edge 1.14.x. +For example, if there is a `release/1.15` label, that means the issue is targeted to be introduced first on the stable main branch, and then backported to Gloo Gateway 1.15.x. ## How to create a backport -First, create a PR to introduce the change on the main branch. Doing so ensures that changes are tested and reviewed before being applied to a previous version of Gloo Edge. Also, given that we use [protocol buffers](https://developers.google.com/protocol-buffers) for our API definitions, introducing API changes to our main branch first ensures we will not have API compatibility issues when backporting. +First, create a PR to introduce the change on the main branch. Doing so ensures that changes are tested and reviewed before being applied to a previous version of Gloo Gateway. Also, given that we use [protocol buffers](https://developers.google.com/protocol-buffers) for our API definitions, introducing API changes to our main branch first ensures we will not have API compatibility issues when backporting. Once the change has been merged into the main branch, create a PR to backport the change to the desired release branch. The PR should be titled `[BRANCH NAME]: ` (ie `[1.14]: Original PR Title`). To create a backport branch we recommend the following: -- Use [cherry-pick](https://git-scm.com/docs/git-cherry-pick) to apply changes to a previous version of Gloo Edge. +- Use [cherry-pick](https://git-scm.com/docs/git-cherry-pick) to apply changes to a previous version of Gloo Gateway. - Resolve any conflicts that have arisen due to drift between LTS branches - If there is significant drift that causes the cherry-pick to be non-trivial, consider re-implementing the change from scratch rather than "backporting" - Modify the changelog to be in the proper directory diff --git a/devel/contributing/documentation.md b/devel/contributing/documentation.md index 7db20162543..3476857a7bc 100644 --- a/devel/contributing/documentation.md +++ b/devel/contributing/documentation.md @@ -1,10 +1,10 @@ # Documentation -The docs for Gloo Edge are built from the contents that can be found in the [docs/content](/docs/content) directory of this repository. +The docs for Gloo Gateway are built from the contents that can be found in the [docs/content](/docs/content) directory of this repository. -Improving the documentation, including by adding examples or use cases, is the easiest way to contribute to Gloo Edge. If you see a piece of content that can be better, open a PR with an improvement, it doesn't matter how small! +Improving the documentation, including by adding examples or use cases, is the easiest way to contribute to Gloo Gateway. If you see a piece of content that can be better, open a PR with an improvement, it doesn't matter how small! -For more information on how to contribute to the documentation, check out the contribution guidelines in the [Gloo Edge documentation](https://docs.solo.io/gloo-edge/latest/contributing). +For more information on how to contribute to the documentation, check out the contribution guidelines in the [Gloo Gateway documentation](https://docs.solo.io/gloo-edge/latest/contributing). ## Auto-generated Docs Please note that some of our documentation is auto-generated from source code. This includes: diff --git a/devel/contributing/issues.md b/devel/contributing/issues.md index 5d81ff6c7a9..57019a02b5e 100644 --- a/devel/contributing/issues.md +++ b/devel/contributing/issues.md @@ -1,6 +1,6 @@ # Filing Issues -GitHub issues are the main way for reporting bugs and requesting features in Gloo Edge. +GitHub issues are the main way for reporting bugs and requesting features in Gloo Gateway. If you encounter a bug or have a feature request, please take the following approach: 1. Search for existing issues. @@ -13,7 +13,7 @@ If you encounter a bug or have a feature request, please take the following appr - Issues can include links to private resources, such as Slack conversations or private code. - Private Enterprise issues can be used to track Open Source work. - The more details about the issue, the better. Please include the following information: - - Gloo Edge version + - Gloo Gateway version - Kubernetes version - Operating system - Steps to reproduce @@ -32,7 +32,7 @@ If you encounter a bug or have a feature request, please take the following appr - Copy the error message from the failed job (logs are discarded after a few months). ## Security Issues -We take Gloo Edge's security very seriously. If you've found a security issue or a potential security issue in Gloo Edge, please **DO NOT** file a public Github issue. +We take Gloo Gateway's security very seriously. If you've found a security issue or a potential security issue in Gloo Gateway, please **DO NOT** file a public Github issue. *Instead, send your report privately to security@solo.io* diff --git a/devel/contributing/pull-request-reviews.md b/devel/contributing/pull-request-reviews.md index 6f8bfdb7f13..717469b3e21 100644 --- a/devel/contributing/pull-request-reviews.md +++ b/devel/contributing/pull-request-reviews.md @@ -1,6 +1,6 @@ # Pull Request Reviews -This doc explains the best practices for reviewing a pull request in the [Gloo Edge project](https://github.com/solo-io/gloo). +This doc explains the best practices for reviewing a pull request in the [Gloo Gateway project](https://github.com/solo-io/gloo). If you are looking to contribute to the project, check out the [writing pull requests guide](pull-requests.md). - [Reviewing Pull Requests](#reviewing-pull-requests) @@ -60,9 +60,9 @@ After pulling down the code, you should try running the tests locally to ensure ## Approving Pull Requests ### Code Maintainers -Solo.io has a dedicated team maintaining the Gloo Edge project. When you submit a PR for Gloo Edge, one of these maintainers will initiate the automation on your PR, and provide a review. +Solo.io has a dedicated team maintaining the Gloo Gateway project. When you submit a PR for Gloo Gateway, one of these maintainers will initiate the automation on your PR, and provide a review. -If there are particular areas of the codebase that are being modified, it is important to identify subject-matter experts (SME) for those changes. If you do know know who this is, use the `@solo-io/gloo-edge-leads` GitHub handle to tag the Gloo Edge technical leads, and they will identify the SMEs. If you can explicitly identify the domains that are being affected, it is easier to identify the relevant parties to review the code. +If there are particular areas of the codebase that are being modified, it is important to identify subject-matter experts (SME) for those changes. If you do not know the SME, use the `@solo-io/gloo-edge-leads` GitHub handle to tag the Gloo Gateway technical leads, and they will identify the SMEs. If you can explicitly identify the domains that are being affected, it is easier to identify the relevant parties to review the code. ### Requirements Each PR requires 2 maintainers to approve the changes. The intention here is to distribute knowledge across more people, and provide an opportunity for broader perspective when reviewing the changes. diff --git a/devel/contributing/pull-requests.md b/devel/contributing/pull-requests.md index 051474b7f6e..755615ac8d3 100644 --- a/devel/contributing/pull-requests.md +++ b/devel/contributing/pull-requests.md @@ -1,6 +1,6 @@ # Pull Requests -This doc explains the best practices for submitting a pull request to the [Gloo Edge project](https://github.com/solo-io/gloo). +This doc explains the best practices for submitting a pull request to the [Gloo Gateway project](https://github.com/solo-io/gloo). It should serve as a reference for all contributors, and be useful especially useful to new and infrequent submitters. # Submission Process @@ -36,7 +36,7 @@ Small PRs are more likely to be reviewed quickly and thoroughly. If the PR takes #### Use Commits to Tell the Story Having a series of discrete commits makes it easier to understand the idea of the PR, and break up the review into smaller chunks -When PRs merge in Gloo Edge, they are squashed into a single commit, so it is not necessary to squash your commits before merging. +When PRs merge in Gloo Gateway, they are squashed into a single commit, so it is not necessary to squash your commits before merging. #### Avoid Squashing Previous Commits and Using Force Pushes This can make it difficult to understand the history of the PR, and can make it difficult to understand the changes in the future. @@ -65,4 +65,4 @@ The PR body is generally the first place reviewers will look to gather context o - Enumerate all changes, even/especially minor ones, so the reviewer knows they are intentional - Link any relevant Slack conversations or design documents in the PR body so that they are not lost -When a PR merges into the target branch in Gloo Edge, the changes are squashed into a single commit, whose message is the PR title. As such, it is important to have a clear title that describes the change \ No newline at end of file +When a PR merges into the target branch in Gloo Gateway, the changes are squashed into a single commit, whose message is the PR title. As such, it is important to have a clear title that describes the change \ No newline at end of file diff --git a/devel/debugging/envoy-segfault.md b/devel/debugging/envoy-segfault.md index 85c3f5cbe4a..445bc40729e 100644 --- a/devel/debugging/envoy-segfault.md +++ b/devel/debugging/envoy-segfault.md @@ -1,6 +1,6 @@ # Envoy Segmentation Fault -When a segmentation fault occurs in the gateway-proxy pod, the stack trace is not visible. If you are running Gloo Edge Enterprise, replace the default docker image in that pod, with the debug replica: +When a segmentation fault occurs in the proxy pod running Envoy, the stack trace is not visible. If you are running Gloo Gateway Enterprise, replace the default docker image in that pod with the debug replica: Original Image: ```bash diff --git a/devel/testing/aws-tests.md b/devel/testing/aws-tests.md index 7796e72cc10..d9ec39f161f 100644 --- a/devel/testing/aws-tests.md +++ b/devel/testing/aws-tests.md @@ -4,7 +4,7 @@ See [e2e-tests](./e2e-tests.md) for more details about e2e tests in general ### Lambda Tests -**These steps can only be taken if you are a Gloo Edge maintainer** +**These steps can only be taken if you are a Gloo Gateway maintainer** You will need to do the following to run the [AWS Lambda Tests](/test/e2e/aws_test.go) locally: 1. Obtain an AWS IAM User account that is part of the Solo.io organization diff --git a/devel/testing/e2e-tests.md b/devel/testing/e2e-tests.md index 3e810973ee6..786cd2b85ca 100644 --- a/devel/testing/e2e-tests.md +++ b/devel/testing/e2e-tests.md @@ -9,7 +9,7 @@ These end-to-end tests do not require Kubernetes, and persist configuration in m - [Local Development](#local-development) ## Background -This is the most common and preferred type of end-to-end test, since it is the quickest to set up and easiest to debug. Additionally, Gloo Edge may be run using various backing stores; these tests provide a single space to validate the translation of Gloo resources into Envoy resources, independently of where Gloo Edge is deployed. These test do not rely on Kubernetes, so if there is any Kubernetes behavior that needs to be tested, write a [kubernetes end-to-end test](../kube2e) instead. +This is the most common and preferred type of end-to-end test, since it is the quickest to set up and easiest to debug. Additionally, Gloo Gateway may be run using various backing stores; these tests provide a single space to validate the translation of Gloo resources into Envoy resources, independently of where Gloo Gateway is deployed. These test do not rely on Kubernetes, so if there is any Kubernetes behavior that needs to be tested, write a [kubernetes end-to-end test](../../test/kubernetes/e2e) instead. ### Where are the tests? The tests are located in the [test/e2e](/test/e2e) folder diff --git a/devel/testing/flaky-tests.md b/devel/testing/flaky-tests.md index a9deaafc78d..e81b0d08e6a 100644 --- a/devel/testing/flaky-tests.md +++ b/devel/testing/flaky-tests.md @@ -1,6 +1,6 @@ # Test Flakes -Tests must account for the eventually consistent nature of Gloo Edge. Writing deterministic end-to-end tests can be challenging, and at times a test will fail in our CI pipeline non-deterministically. We refer to these failures as flakes. We have found the most common flakes occur as a result of: +Tests must account for the eventually consistent nature of Gloo Gateway. Writing deterministic end-to-end tests can be challenging, and at times a test will fail in our CI pipeline non-deterministically. We refer to these failures as flakes. We have found the most common flakes occur as a result of: 1. **Test pollution**: another test in the same suite does not clean up resources 2. **Eventual consistency**: the test does not wait long enough for resources to be applied and processed correctly diff --git a/devel/testing/kube-e2e-tests.md b/devel/testing/kube-e2e-tests.md index ce79ee717e5..2fb06762e70 100644 --- a/devel/testing/kube-e2e-tests.md +++ b/devel/testing/kube-e2e-tests.md @@ -1,5 +1,5 @@ # Kubernetes End-to-End tests -These end-to-end tests install each of the 3 Gloo Edge flavors (`gateway`, `ingress`, and `knative`) in a Kubernetes cluster, and run +These end-to-end tests install each of the 3 Gloo Gateway flavors (`gateway`, `ingress`, and `knative`) in a Kubernetes cluster, and run end-to-end tests against them. - [Background](#background) @@ -8,11 +8,11 @@ end-to-end tests against them. - [Local Development](#local-development) ## Background -Kubernetes may be relied on for scheduling, persistence or security. These tests validate that Gloo Edge can successfully operate within a Kubernetes cluster. +Kubernetes may be relied on for scheduling, persistence or security. These tests validate that Gloo Gateway can successfully operate within a Kubernetes cluster. ### How do the tests work? Kubernetes end-to-end tests: -1. Install Gloo Edge in Kubernetes cluster [using Helm](https://github.com/solo-io/gloo/blob/1f457f4ef5f32aedabc58ef164aeea92acbf481e/test/kube2e/gateway/gateway_suite_test.go#L84) +1. Install Gloo Gateway in Kubernetes cluster [using Helm](https://github.com/solo-io/gloo/blob/1f457f4ef5f32aedabc58ef164aeea92acbf481e/test/kube2e/gateway/gateway_suite_test.go#L84) 1. Apply Gloo resources using Kubernetes resource clients 1. Execute requests against the Envoy proxy and confirm the expected response. This validates that the Gloo resources have been picked up by the controllers, were been translated correctly into Envoy configuration, the configuration was sent to the Envoy proxy, and the proxy behaves appropriately. diff --git a/devel/testing/run-tests.md b/devel/testing/run-tests.md index 852c7f430dd..b3c4f3e2b3f 100644 --- a/devel/testing/run-tests.md +++ b/devel/testing/run-tests.md @@ -14,7 +14,7 @@ - [INVALID_TEST_REQS](#invalid_test_reqs) ## Background -Gloo Edge testing leverages the [Ginkgo](https://onsi.github.io/ginkgo/) test framework. As outlined in the linked documentation, Ginkgo pairs with the [Gomega](https://onsi.github.io/gomega/) matcher library to provide a BDD-style testing framework. For more details about how to write tests, check out our [writing tests docs](writing-tests.md). +Gloo Gateway testing leverages the [Ginkgo](https://onsi.github.io/ginkgo/) test framework. As outlined in the linked documentation, Ginkgo pairs with the [Gomega](https://onsi.github.io/gomega/) matcher library to provide a BDD-style testing framework. For more details about how to write tests, check out our [writing tests docs](writing-tests.md). ## Common Make Targets There are a few common make targets that can be used to run tests @@ -65,7 +65,7 @@ TEST_PKG=test/... make test ``` #### WAIT_ON_FAIL -The `WAIT_ON_FAIL` environment variable can be used to prevent Ginkgo from cleaning up the Gloo Edge installation in case of failure. This is useful to inspect resources created by the test. A command to resume the test run (and thus clean up resources) will be logged to the output. +The `WAIT_ON_FAIL` environment variable can be used to prevent Ginkgo from cleaning up the Gloo Gateway installation in case of failure. This is useful to inspect resources created by the test. A command to resume the test run (and thus clean up resources) will be logged to the output. See [the definition](/test/testutils/env.go) for more details about when it can be used. diff --git a/devel/tools/README.md b/devel/tools/README.md index 577cdf9f46e..2e12c380cae 100644 --- a/devel/tools/README.md +++ b/devel/tools/README.md @@ -1,4 +1,5 @@ # Developer Tools +_**Note**: For tools that help maintain an installation of Gloo Gateway (the product, not the project codebase), build those tools into the [CLI](/projects/gloo/cli) instead._ ## Changelog creation tool diff --git a/docs/content/reference/values.txt b/docs/content/reference/values.txt index fe56c7e897d..939af0a27c2 100644 --- a/docs/content/reference/values.txt +++ b/docs/content/reference/values.txt @@ -454,6 +454,7 @@ |gateway.validation.webhook.timeoutSeconds|int||the timeout for the webhook, defaults to 10| |gateway.validation.webhook.extraAnnotations.NAME|string||extra annotations to add to the webhook| |gateway.validation.webhook.skipDeleteValidationResources[]|string||resource types in this list will not use webhook valdaition for DELETEs. Use '*' to skip validation for all resources. Valid values are 'virtualservices', 'routetables','upstreams', 'secrets', 'ratelimitconfigs', and '*'. Invalid values will be accepted but will not be used.| +|gateway.validation.webhook.enablePolicyApi|bool|true|enable validation of Policy Api resources (RouteOptions, VirtualHostOptions) (default: true). NOTE: This only applies if the Kubernetes Gateway Integration is also enabled (kubeGateway.enabled).| |gateway.validation.webhook.kubeResourceOverride.NAME|interface||override fields in the generated resource by specifying the yaml structure to override under the top-level key.| |gateway.validation.validationServerGrpcMaxSizeBytes|int|104857600|gRPC max message size in bytes for the gloo validation server| |gateway.validation.livenessProbeEnabled|bool||Set to true to enable a liveness probe for the gateway (default is false). You must also set the 'Probes' value to true.| diff --git a/install/README.md b/install/README.md index b070e7b811f..90e0d162f0d 100644 --- a/install/README.md +++ b/install/README.md @@ -1,4 +1,4 @@ -# Installing Gloo Edge +# Installing Gloo Gateway ...[onto a local filesystem](https://docs.solo.io/gloo-edge/latest/installation/gateway/development/docker-compose-file/) ...[onto a Consul](https://docs.solo.io/gloo-edge/latest/installation/gateway/development/docker-compose-consul/) diff --git a/install/helm/gloo/generate/values.go b/install/helm/gloo/generate/values.go index f37a29bcf41..225212451e1 100644 --- a/install/helm/gloo/generate/values.go +++ b/install/helm/gloo/generate/values.go @@ -450,6 +450,12 @@ type Webhook struct { TimeoutSeconds *int `json:"timeoutSeconds,omitempty" desc:"the timeout for the webhook, defaults to 10"` ExtraAnnotations map[string]string `json:"extraAnnotations,omitempty" desc:"extra annotations to add to the webhook"` SkipDeleteValidationResources []string `json:"skipDeleteValidationResources,omitempty" desc:"resource types in this list will not use webhook valdaition for DELETEs. Use '*' to skip validation for all resources. Valid values are 'virtualservices', 'routetables','upstreams', 'secrets', 'ratelimitconfigs', and '*'. Invalid values will be accepted but will not be used."` + // EnablePolicyApi provides granular access to users to opt-out of Policy validation + // There are some known race conditions in our Gloo Gateway processes resource references, + // even when allowWarnings=true: https://github.com/solo-io/solo-projects/issues/6321 + // As a result, this is intended as a short-term solution to provide users a way to opt-out of Policy API validation. + // The desired long-term strategy is that our validation logic is stable, and users can leverage it + EnablePolicyApi *bool `json:"enablePolicyApi,omitempty" desc:"enable validation of Policy Api resources (RouteOptions, VirtualHostOptions) (default: true). NOTE: This only applies if the Kubernetes Gateway Integration is also enabled (kubeGateway.enabled)."` *KubeResourceOverride } diff --git a/install/helm/gloo/templates/5-gateway-validation-webhook-configuration.yaml b/install/helm/gloo/templates/5-gateway-validation-webhook-configuration.yaml index 22af9833e46..34f34e98363 100644 --- a/install/helm/gloo/templates/5-gateway-validation-webhook-configuration.yaml +++ b/install/helm/gloo/templates/5-gateway-validation-webhook-configuration.yaml @@ -24,7 +24,7 @@ webhooks: path: "/validation" caBundle: "" # update manually or use certgen job or cert-manager's ca-injector rules: -{{- if .Values.kubeGateway.enabled }} +{{- if and .Values.kubeGateway.enabled .Values.gateway.validation.webhook.enablePolicyApi }} - operations: [ "CREATE", "UPDATE" ] # RouteOption and VirtualHostOption DELETEs are not supported. # Their validation is currently limited to usage as Kube Gateway API Policies @@ -33,7 +33,7 @@ webhooks: apiGroups: ["gateway.solo.io"] apiVersions: ["v1"] resources: ["routeoptions", "virtualhostoptions"] -{{- end }}{{/* if .Values.kubeGateway.enabled */}} +{{- end }}{{/* if and .Values.kubeGateway.enabled .Values.gateway.validation.webhook.enablePolicyApi */}} - operations: {{ include "gloo.webhookvalidation.operationsForResource" (list "virtualservices" .Values.gateway.validation.webhook.skipDeleteValidationResources) }} apiGroups: ["gateway.solo.io"] apiVersions: ["v1"] diff --git a/install/helm/gloo/values-template.yaml b/install/helm/gloo/values-template.yaml index 7a2b44da679..062e057ddf0 100644 --- a/install/helm/gloo/values-template.yaml +++ b/install/helm/gloo/values-template.yaml @@ -113,6 +113,10 @@ gateway: enabled: true disableHelmHook: false extraAnnotations: {} + # We have learned that defaulting validation behavior leads to unintentional usage of it + # https://github.com/solo-io/gloo/issues/9309 + # As a result, for our Policy API, we default it to on, and provide users the way to opt-out of it + enablePolicyApi: true certGenJob: enabled: true image: diff --git a/install/test/5-gateway-validation-webhook-configuration_test.go b/install/test/5-gateway-validation-webhook-configuration_test.go index 9d5fc5357d0..62a437c4455 100644 --- a/install/test/5-gateway-validation-webhook-configuration_test.go +++ b/install/test/5-gateway-validation-webhook-configuration_test.go @@ -1,11 +1,16 @@ package test import ( + "encoding/json" "fmt" "regexp" "strconv" "strings" + "github.com/golang/protobuf/ptypes/wrappers" + "github.com/onsi/gomega/types" + v1 "k8s.io/api/admissionregistration/v1" + . "github.com/onsi/ginkgo/v2" . "github.com/onsi/gomega" gloostringutils "github.com/solo-io/gloo/pkg/utils/stringutils" @@ -15,6 +20,10 @@ import ( "sigs.k8s.io/yaml" ) +const ( + validatingWebhookConfigurationKind = "ValidatingWebhookConfiguration" +) + var _ = Describe("WebhookValidationConfiguration helm test", func() { var allTests = func(rendererTestCase renderTestCase) { @@ -55,6 +64,115 @@ var _ = Describe("WebhookValidationConfiguration helm test", func() { Entry("all", []string{"*"}, 5), Entry("empty", []string{}, 0), ) + + Context("enablePolicyApi", func() { + + // containPolicyApiOperation returns a GomegaMatcher which will assert that a provided ValidatingWebhookConfiguration + // contains the Rule that includes the Policy APIs + containPolicyApiOperation := func() types.GomegaMatcher { + policyApiOperation := v1.RuleWithOperations{ + Operations: []v1.OperationType{ + v1.Create, + v1.Update, + }, + Rule: v1.Rule{ + APIGroups: []string{"gateway.solo.io"}, + APIVersions: []string{"v1"}, + Resources: []string{"routeoptions", "virtualhostoptions"}, + }, + } + return WithTransform(func(config *v1.ValidatingWebhookConfiguration) []v1.RuleWithOperations { + if config == nil { + return nil + } + return config.Webhooks[0].Rules + }, ContainElement(policyApiOperation)) + } + + type enablePolicyApiCase struct { + enableKubeGatewayApi *wrappers.BoolValue + enablePolicyApi *wrappers.BoolValue + expectedWebhookConfiguration types.GomegaMatcher + } + + DescribeTable("respects helm values", + func(testCase enablePolicyApiCase) { + var valuesArgs []string + if testCase.enableKubeGatewayApi != nil { + valuesArgs = append(valuesArgs, fmt.Sprintf(`kubeGateway.enabled=%t`, testCase.enableKubeGatewayApi.GetValue())) + } + if testCase.enablePolicyApi != nil { + valuesArgs = append(valuesArgs, fmt.Sprintf(`gateway.validation.webhook.enablePolicyApi=%t`, testCase.enablePolicyApi.GetValue())) + } + + prepareMakefile(namespace, helmValues{ + valuesArgs: valuesArgs, + }) + + testManifest.ExpectUnstructured( + validatingWebhookConfigurationKind, + "", // ValidatingWebhookConfiguration is cluster-scoped + fmt.Sprintf("gloo-gateway-validation-webhook-%s", namespace), + ).To(WithTransform(func(unstructuredVwc *unstructured.Unstructured) *v1.ValidatingWebhookConfiguration { + // convert the unstructured validating webhook configuration to a structured object + if unstructuredVwc == nil { + return nil + } + + rawJson, err := json.Marshal(unstructuredVwc.Object) + if err != nil { + return nil + } + + var structuredVwc *v1.ValidatingWebhookConfiguration + err = json.Unmarshal(rawJson, &structuredVwc) + if err != nil { + return nil + } + + return structuredVwc + }, testCase.expectedWebhookConfiguration)) + }, + Entry("unset", enablePolicyApiCase{ + enableKubeGatewayApi: nil, + enablePolicyApi: nil, + expectedWebhookConfiguration: Not(containPolicyApiOperation()), + }), + Entry("enableKubeGatewayApi=false,", enablePolicyApiCase{ + enableKubeGatewayApi: &wrappers.BoolValue{Value: false}, + enablePolicyApi: nil, + expectedWebhookConfiguration: Not(containPolicyApiOperation()), + }), + Entry("enableKubeGatewayApi=true,", enablePolicyApiCase{ + enableKubeGatewayApi: &wrappers.BoolValue{Value: true}, + enablePolicyApi: nil, // default is true + expectedWebhookConfiguration: containPolicyApiOperation(), + }), + Entry("enableKubeGatewayApi=true, enablePolicyApi=true", enablePolicyApiCase{ + enableKubeGatewayApi: &wrappers.BoolValue{Value: true}, + enablePolicyApi: &wrappers.BoolValue{Value: true}, + expectedWebhookConfiguration: containPolicyApiOperation(), + }), + // This is the critical test case, which demonstrates that a user can enabled the K8s Gateway Integration, + // but disable validation for the Policy APIs + Entry("enableKubeGatewayApi=false, enablePolicyApi=true", enablePolicyApiCase{ + enableKubeGatewayApi: &wrappers.BoolValue{Value: false}, + enablePolicyApi: &wrappers.BoolValue{Value: true}, + expectedWebhookConfiguration: Not(containPolicyApiOperation()), + }), + Entry("enableKubeGatewayApi=false, enablePolicyApi=true", enablePolicyApiCase{ + enableKubeGatewayApi: &wrappers.BoolValue{Value: false}, + enablePolicyApi: &wrappers.BoolValue{Value: true}, + expectedWebhookConfiguration: Not(containPolicyApiOperation()), + }), + Entry("enableKubeGatewayApi=false, enablePolicyApi=false", enablePolicyApiCase{ + enableKubeGatewayApi: &wrappers.BoolValue{Value: false}, + enablePolicyApi: &wrappers.BoolValue{Value: false}, + expectedWebhookConfiguration: Not(containPolicyApiOperation()), + }), + ) + }) + } runTests(allTests) }) diff --git a/projects/envoyinit/README.md b/projects/envoyinit/README.md index 7873f3a1633..63c83c297b6 100644 --- a/projects/envoyinit/README.md +++ b/projects/envoyinit/README.md @@ -1,14 +1,14 @@ # Envoyinit -The running instance of Envoy. In Gloo Edge, this is commonly referred to as the `gateway-proxy` component. +The running instance of Envoy. In Gloo Gateway, this is commonly referred to as the `gateway-proxy` component. ## Background The [Envoy Proxy](https://www.envoyproxy.io/) is a cloud-native, high-performance, service proxy. ### Source Code -The Gloo Edge service proxies provide all the functionality of the [open source Envoy Proxy](https://github.com/solo-io/envoy-gloo), in addition to some custom extensions. The source code for these proxies is maintained at [envoy-gloo](https://github.com/solo-io/envoy-gloo) +The Gloo Gateway service proxies provide all the functionality of the [open source Envoy Proxy](https://github.com/solo-io/envoy-gloo), in addition to some custom extensions. The source code for these proxies is maintained at [envoy-gloo](https://github.com/solo-io/envoy-gloo) ### Versioning -In the [Makefile](https://github.com/solo-io/gloo/blob/main/Makefile), the `ENVOY_GLOO_IMAGE` value defines the version of `envoy-gloo` that Gloo Edge depends on. +In the [Makefile](https://github.com/solo-io/gloo/blob/main/Makefile), the `ENVOY_GLOO_IMAGE` value defines the version of `envoy-gloo` that Gloo Gateway depends on. Envoy publishes new minor releases [each quarter](https://www.envoyproxy.io/docs/envoy/latest/version_history/version_history#). Gloo attempts to follow this cadence, and increment our minor version of `envoy-gloo` as well. @@ -28,15 +28,15 @@ make gloo-envoy-wrapper-docker -B ``` ## Release -During a Gloo Edge release, the `gloo-envoy-wrapper` image is published to the [Google Cloud Registry](https://console.cloud.google.com/gcr/images/gloo-edge/GLOBAL) and the [Quay repository](https://quay.io/repository/solo-io/gloo-envoy-wrapper). +During a Gloo Gateway release, the `gloo-envoy-wrapper` image is published to the [Google Cloud Registry](https://console.cloud.google.com/gcr/images/gloo-edge/GLOBAL) and the [Quay repository](https://quay.io/repository/solo-io/gloo-envoy-wrapper). ## Configuration -Envoy [configuration](https://www.envoyproxy.io/docs/envoy/latest/configuration/configuration) can be provided either statically or dynamically. In Gloo Edge, we leverage both of these patterns: at initialization time, the proxy is provided with basic boostrap configuration, and then all future updates are provided dynamically by the control-plane. +Envoy [configuration](https://www.envoyproxy.io/docs/envoy/latest/configuration/configuration) can be provided either statically or dynamically. In Gloo Gateway, we leverage both of these patterns: at initialization time, the proxy is provided with basic boostrap configuration, and then all future updates are provided dynamically by the control-plane. ### Static Envoy is configured with [Bootstrap configuration](https://www.envoyproxy.io/docs/envoy/latest/configuration/overview/bootstrap). This provides static server configuration and configures Envoy to access dynamic configuration from the Gloo control plane. -In Gloo Edge, Envoy configuration is processed in the following order: +In Gloo Gateway, Envoy configuration is processed in the following order: 1. The bootstrap configuration is defined in a [ConfigMap](https://github.com/solo-io/gloo/blob/main/install/helm/gloo/templates/9-gateway-proxy-configmap.yaml) 2. The ConfigMap is mounted as a volume on the Pod diff --git a/projects/gateway2/deployer/deployer.go b/projects/gateway2/deployer/deployer.go index 22938ff3673..9f66f8fd96e 100644 --- a/projects/gateway2/deployer/deployer.go +++ b/projects/gateway2/deployer/deployer.go @@ -120,7 +120,7 @@ func (d *Deployer) GetGvksToWatch(ctx context.Context) ([]schema.GroupVersionKin }, } - objs, err := d.renderChartToObjects(ctx, emptyGw, vals) + objs, err := d.renderChartToObjects(emptyGw, vals) if err != nil { return nil, err } @@ -144,8 +144,8 @@ func jsonConvert(in *helmConfig, out interface{}) error { return json.Unmarshal(b, out) } -func (d *Deployer) renderChartToObjects(ctx context.Context, gw *api.Gateway, vals map[string]any) ([]client.Object, error) { - objs, err := d.Render(ctx, gw.Name, gw.Namespace, vals) +func (d *Deployer) renderChartToObjects(gw *api.Gateway, vals map[string]any) ([]client.Object, error) { + objs, err := d.Render(gw.Name, gw.Namespace, vals) if err != nil { return nil, err } @@ -323,17 +323,26 @@ func (d *Deployer) getValues(gw *api.Gateway, gwParam *v1alpha1.GatewayParameter return vals, nil } -func (d *Deployer) Render(ctx context.Context, name, ns string, vals map[string]any) ([]client.Object, error) { +// Render relies on a `helm install` to render the Chart with the injected values +// It returns the list of Objects that are rendered, and an optional error if rendering failed, +// or converting the rendered manifests to objects failed. +func (d *Deployer) Render(name, ns string, vals map[string]any) ([]client.Object, error) { mem := driver.NewMemory() mem.SetNamespace(ns) cfg := &action.Configuration{ Releases: storage.Init(mem), } - client := action.NewInstall(cfg) - client.Namespace = ns - client.ReleaseName = name - client.ClientOnly = true - release, err := client.RunWithContext(ctx, d.chart, vals) + install := action.NewInstall(cfg) + install.Namespace = ns + install.ReleaseName = name + + // We rely on the Install object in `clientOnly` mode + // This means that there is no i/o (i.e. no reads/writes to k8s) that would need to be cancelled. + // This essentially guarantees that this function terminates quickly and doesn't block the rest of the controller. + install.ClientOnly = true + installCtx := context.Background() + + release, err := install.RunWithContext(installCtx, d.chart, vals) if err != nil { return nil, fmt.Errorf("failed to render helm chart for gateway %s.%s: %w", ns, name, err) } @@ -372,7 +381,7 @@ func (d *Deployer) GetObjsToDeploy(ctx context.Context, gw *api.Gateway) ([]clie if err != nil { return nil, fmt.Errorf("failed to convert helm values for gateway %s.%s: %w", gw.GetNamespace(), gw.GetName(), err) } - objs, err := d.renderChartToObjects(ctx, gw, convertedVals) + objs, err := d.renderChartToObjects(gw, convertedVals) if err != nil { return nil, fmt.Errorf("failed to get objects to deploy for gateway %s.%s: %w", gw.GetNamespace(), gw.GetName(), err) } diff --git a/projects/gloo/cli/pkg/cmd/install/kubegateway/install.go b/projects/gloo/cli/pkg/cmd/install/kubegateway/install.go index cda159166f9..70490374063 100644 --- a/projects/gloo/cli/pkg/cmd/install/kubegateway/install.go +++ b/projects/gloo/cli/pkg/cmd/install/kubegateway/install.go @@ -80,7 +80,7 @@ func install(opts *options.Options, installOpts *Options) error { fmt.Printf("Skipping Gateway CRDs as they exist...\n") } - objs, err := dep.Render(ctx, "default", installOpts.Namespace, vals) + objs, err := dep.Render("default", installOpts.Namespace, vals) if err != nil { return err } diff --git a/projects/gloo/cli/pkg/cmd/install/kubegateway/uninstall.go b/projects/gloo/cli/pkg/cmd/install/kubegateway/uninstall.go index 3f1dca2fa08..37424ce7d00 100644 --- a/projects/gloo/cli/pkg/cmd/install/kubegateway/uninstall.go +++ b/projects/gloo/cli/pkg/cmd/install/kubegateway/uninstall.go @@ -34,7 +34,7 @@ func uninstall(opts *options.Options, installOpts *Options) error { return err } - objs, err := dep.Render(ctx, "default", installOpts.Namespace, map[string]any{}) + objs, err := dep.Render("default", installOpts.Namespace, map[string]any{}) if err != nil { return err } diff --git a/projects/gloo/pkg/servers/iosnapshot/history_test.go b/projects/gloo/pkg/servers/iosnapshot/history_test.go index 42c25f3db4d..bc399798f0a 100644 --- a/projects/gloo/pkg/servers/iosnapshot/history_test.go +++ b/projects/gloo/pkg/servers/iosnapshot/history_test.go @@ -144,7 +144,7 @@ var _ = Describe("History", func() { Status: apiv1.HTTPRouteStatus{}, }, } - history.SetKubeGatewayClient(clientBuilder.WithObjects(clientObjects...).Build()) + setClientOnHistory(ctx, history, clientBuilder.WithObjects(clientObjects...)) inputSnapshotBytes, err := history.GetInputSnapshot(ctx) Expect(err).NotTo(HaveOccurred()) @@ -181,7 +181,7 @@ var _ = Describe("History", func() { Status: apiv1.GatewayStatus{}, }, } - history.SetKubeGatewayClient(clientBuilder.WithObjects(clientObjects...).Build()) + setClientOnHistory(ctx, history, clientBuilder.WithObjects(clientObjects...)) inputSnapshotBytes, err := history.GetInputSnapshot(ctx) Expect(err).NotTo(HaveOccurred()) @@ -199,8 +199,11 @@ var _ = Describe("History", func() { var gatewayList apiv1.GatewayList err = json.Unmarshal(gatewayBytes, &gatewayList) Expect(err).NotTo(HaveOccurred()) - Expect(gatewayList.Items).To(HaveLen(1)) - Expect(gatewayList.Items[0].GetName()).To(Equal("kubernetes-gateway")) + + Expect(gatewayList.Items).To(ContainElement( + WithTransform(func(gateway apiv1.Gateway) string { + return gateway.GetName() + }, Equal("kubernetes-gateway")))) }) }) @@ -257,3 +260,44 @@ func setSnapshotOnHistory(ctx context.Context, history History, snap *v1snap.Api WithTimeout(time.Second*5). Should(Succeed(), "setting snapshot is asynchronous, so block until snapshot is processed") } + +// setClientOnHistory sets the Kubernetes Client on the history, and blocks until it has been processed +// This is a utility method to help developers write tests, without having to worry about the asynchronous +// nature of the `Set` API on the History +func setClientOnHistory(ctx context.Context, history History, builder *fake.ClientBuilder) { + gwSignalObject := &apiv1.Gateway{ + TypeMeta: metav1.TypeMeta{}, + ObjectMeta: metav1.ObjectMeta{ + Name: "gw-signal", + Namespace: defaults.GlooSystem, + }, + } + + history.SetKubeGatewayClient(builder.WithObjects(gwSignalObject).Build()) + + Eventually(func(g Gomega) { + inputSnapshotBytes, err := history.GetInputSnapshot(ctx) + g.Expect(err).NotTo(HaveOccurred()) + + returnedData := map[string]interface{}{} + err = json.Unmarshal(inputSnapshotBytes, &returnedData) + g.Expect(err).NotTo(HaveOccurred()) + + gatewayKey := fmt.Sprintf("%s.%s", wellknown.GatewayGroup, wellknown.GatewayKind) + g.Expect(returnedData).To(HaveKey(gatewayKey), "Gateway should be included in input snap") + + gatewayBytes, err := json.Marshal(returnedData[gatewayKey]) + g.Expect(err).NotTo(HaveOccurred()) + + var gatewayList apiv1.GatewayList + err = json.Unmarshal(gatewayBytes, &gatewayList) + g.Expect(err).NotTo(HaveOccurred()) + g.Expect(gatewayList.Items).To(ContainElement( + WithTransform(func(gateway apiv1.Gateway) string { + return gateway.GetName() + }, Equal("gw-signal")))) + }). + WithPolling(time.Millisecond*100). + WithTimeout(time.Second*5). + Should(Succeed(), "setting client is asynchronous, so block until client is processed") +} diff --git a/test_coverage.yml b/test_coverage.yml new file mode 100644 index 00000000000..df07bc29b5d --- /dev/null +++ b/test_coverage.yml @@ -0,0 +1,44 @@ +# ref: https://github.com/vladopajic/go-test-coverage/blob/a5134457f681defa8eada436f1bcda10407f4f8b/.testcoverage.example.yml + +# (mandatory) +# Path to coverprofile file (output of `go test -coverprofile` command) +profile: _output/cover.out + +# Holds coverage thresholds percentages, values should be in range [0-100] +# We should strive to increase these percentages over time +threshold: + # (optional; default 0) + # The minimum coverage that each file should have + file: 50 + + # (optional; default 0) + # The minimum coverage that each package should have + package: 50 + + # (optional; default 0) + # The minimum total coverage project should have + total: 50 + +# Holds regexp rules which will override thresholds for matched files or packages +# using their paths. +# +# First rule from this list that matches file or package is going to apply +# new threshold to it. If project has multiple rules that match same path, +# override rules should be listed in order from specific to more general rules. +override: + # Calls to external library, which is tested + - threshold: 0 + path: ^projects/gateway2/generate.go + # The only code at the top-level of the `projects/gateway2` package is code generation + - threshold: 0 + path: ^projects/gateway2$ + +# Holds regexp rules which will exclude matched files or packages +# from coverage statistics +exclude: + # Exclude files or packages matching their paths + paths: + # Exclude the protobuf generated files (pb.go, pb.equal.go, pb.hash.go) + - \.pb\.go$ + - \.pb\.hash\.go$ + - \.pb\.equal\.go$ \ No newline at end of file