This is an automated email from the ASF dual-hosted git repository. ronething pushed a commit to branch master in repository https://gitbox.apache.org/repos/asf/apisix-ingress-controller.git
The following commit(s) were added to refs/heads/master by this push: new cfa8fd51 feat: support apisix provider type and add ingress docs (#2427) cfa8fd51 is described below commit cfa8fd5159ef8c899dfc7d311365e26c6f2392e1 Author: Ashing Zheng <axing...@gmail.com> AuthorDate: Thu Jun 26 16:58:08 2025 +0800 feat: support apisix provider type and add ingress docs (#2427) Signed-off-by: ashing <axing...@gmail.com> --- .github/workflows/apisix-conformance-test.yml | 7 + .github/workflows/apisix-e2e-test.yml | 6 + api/v2/apisixtls_types.go | 2 +- charts/templates/configmap.yaml | 2 + charts/values.yaml | 1 + ...tls.yaml => apisix.apache.org_apisixtlses.yaml} | 4 +- config/crd/kustomization.yaml | 2 +- config/rbac/role.yaml | 13 +- docs/assets/images/upgrade-to-architecture.png | Bin 0 -> 283739 bytes docs/upgrade-guide.md | 171 +++++++++++++++++++++ internal/controller/config/config.go | 2 +- internal/controller/config/types.go | 1 + internal/manager/controllers.go | 6 +- internal/provider/adc/adc.go | 7 +- internal/provider/adc/executor.go | 14 +- test/conformance/apisix/suite_test.go | 2 +- test/e2e/framework/apisix_consts.go | 11 +- test/e2e/framework/assertion.go | 2 +- test/e2e/framework/manifests/apisix.yaml | 125 +++++++++++++++ test/e2e/framework/manifests/etcd.yaml | 58 +++++++ test/e2e/framework/manifests/ingress.yaml | 4 +- test/e2e/gatewayapi/httproute.go | 15 +- test/e2e/scaffold/adc.go | 5 + test/e2e/scaffold/apisix_deployer.go | 25 ++- 24 files changed, 454 insertions(+), 31 deletions(-) diff --git a/.github/workflows/apisix-conformance-test.yml b/.github/workflows/apisix-conformance-test.yml index 555b9988..2b65eb31 100644 --- a/.github/workflows/apisix-conformance-test.yml +++ b/.github/workflows/apisix-conformance-test.yml @@ -53,6 +53,11 @@ jobs: timeout-minutes: 60 needs: - prepare + strategy: + matrix: + provider_type: + - apisix-standalone + - apisix runs-on: ubuntu-latest steps: - name: Checkout @@ -96,6 +101,8 @@ jobs: - name: Run Conformance Test shell: bash continue-on-error: true + env: + PROVIDER_TYPE: ${{ matrix.provider_type }} run: | make conformance-test-standalone diff --git a/.github/workflows/apisix-e2e-test.yml b/.github/workflows/apisix-e2e-test.yml index b7f0f83e..a193015c 100644 --- a/.github/workflows/apisix-e2e-test.yml +++ b/.github/workflows/apisix-e2e-test.yml @@ -52,6 +52,11 @@ jobs: e2e-test: needs: - prepare + strategy: + matrix: + provider_type: + - apisix-standalone + - apisix runs-on: ubuntu-latest steps: - name: Checkout @@ -100,5 +105,6 @@ jobs: shell: bash env: TEST_DIR: "./test/e2e/apisix/" + PROVIDER_TYPE: ${{ matrix.provider_type }} run: | make e2e-test diff --git a/api/v2/apisixtls_types.go b/api/v2/apisixtls_types.go index b790cd81..31d3b336 100644 --- a/api/v2/apisixtls_types.go +++ b/api/v2/apisixtls_types.go @@ -41,7 +41,7 @@ type ApisixTlsStatus = ApisixStatus // +kubebuilder:object:root=true // +kubebuilder:subresource:status -// +kubebuilder:resource:shortName=atls +// +kubebuilder:resource:shortName=atls,path=apisixtlses // ApisixTls is the Schema for the apisixtls API. type ApisixTls struct { diff --git a/charts/templates/configmap.yaml b/charts/templates/configmap.yaml index 2e241b2c..1a56b773 100644 --- a/charts/templates/configmap.yaml +++ b/charts/templates/configmap.yaml @@ -32,6 +32,8 @@ data: exec_adc_timeout: {{ .Values.config.execADCTimeout | default "15s" }} provider: + type: {{ .Values.config.provider.type | default "apisix-standalone" }} + sync_period: {{ .Values.config.provider.syncPeriod | default "0s" }} init_sync_delay: {{ .Values.config.provider.initSyncDelay | default "20m" }} diff --git a/charts/values.yaml b/charts/values.yaml index 1ad0833f..6cbb258b 100644 --- a/charts/values.yaml +++ b/charts/values.yaml @@ -52,5 +52,6 @@ config: secureMetrics: "" execADCTimeout: "15s" provider: + type: "apisix-standalone" syncPeriod: "0s" initSyncDelay: "20m" diff --git a/config/crd/bases/apisix.apache.org_apisixtls.yaml b/config/crd/bases/apisix.apache.org_apisixtlses.yaml similarity index 99% rename from config/crd/bases/apisix.apache.org_apisixtls.yaml rename to config/crd/bases/apisix.apache.org_apisixtlses.yaml index 43d666c1..c384301f 100644 --- a/config/crd/bases/apisix.apache.org_apisixtls.yaml +++ b/config/crd/bases/apisix.apache.org_apisixtlses.yaml @@ -4,13 +4,13 @@ kind: CustomResourceDefinition metadata: annotations: controller-gen.kubebuilder.io/version: v0.17.2 - name: apisixtls.apisix.apache.org + name: apisixtlses.apisix.apache.org spec: group: apisix.apache.org names: kind: ApisixTls listKind: ApisixTlsList - plural: apisixtls + plural: apisixtlses shortNames: - atls singular: apisixtls diff --git a/config/crd/kustomization.yaml b/config/crd/kustomization.yaml index dd3231be..31b55ab7 100644 --- a/config/crd/kustomization.yaml +++ b/config/crd/kustomization.yaml @@ -10,7 +10,7 @@ resources: - bases/apisix.apache.org_apisixroutes.yaml - bases/apisix.apache.org_apisixconsumers.yaml - bases/apisix.apache.org_apisixglobalrules.yaml -- bases/apisix.apache.org_apisixtls.yaml +- bases/apisix.apache.org_apisixtlses.yaml - bases/apisix.apache.org_apisixupstreams.yaml - bases/apisix.apache.org_apisixpluginconfigs.yaml # +kubebuilder:scaffold:crdkustomizeresource diff --git a/config/rbac/role.yaml b/config/rbac/role.yaml index 516b74be..388c7cd2 100644 --- a/config/rbac/role.yaml +++ b/config/rbac/role.yaml @@ -29,7 +29,7 @@ rules: - apisixglobalrules - apisixpluginconfigs - apisixroutes - - apisixtls + - apisixtlses - apisixupstreams - backendtrafficpolicies - consumers @@ -47,7 +47,7 @@ rules: - apisixglobalrules/status - apisixpluginconfigs/status - apisixroutes/status - - apisixtls/status + - apisixtlses/status - apisixupstreams/status - backendtrafficpolicies/status - consumers/status @@ -91,6 +91,7 @@ rules: - gatewayclasses/status - gateways/status - httproutes/status + - referencegrants/status verbs: - get - update @@ -102,6 +103,14 @@ rules: - get - list - watch +- apiGroups: + - gateway.networking.k8s.io + resources: + - referencegrants + verbs: + - list + - update + - watch - apiGroups: - networking.k8s.io resources: diff --git a/docs/assets/images/upgrade-to-architecture.png b/docs/assets/images/upgrade-to-architecture.png new file mode 100644 index 00000000..9370e35b Binary files /dev/null and b/docs/assets/images/upgrade-to-architecture.png differ diff --git a/docs/upgrade-guide.md b/docs/upgrade-guide.md new file mode 100644 index 00000000..297fff7b --- /dev/null +++ b/docs/upgrade-guide.md @@ -0,0 +1,171 @@ +# APISIX Ingress Controller Upgrade Guide + +## Upgrading from 1.x.x to 2.0.0: Key Changes and Considerations + +This document outlines the major updates, configuration compatibility changes, API behavior differences, and critical considerations when upgrading the APISIX Ingress Controller from version 1.x.x to 2.0.0. Please read carefully and assess the impact on your existing system before proceeding with the upgrade. + +### APISIX Version Dependency (Data Plane) + +The `apisix-standalone` mode is supported only with **APISIX 3.13.0**. When using this mode, it is mandatory to upgrade the data plane APISIX instance along with the Ingress Controller. + +### Architecture Changes + +#### Architecture in 1.x.x + +There were two main deployment architectures in 1.x.x: + +| Mode | Description | Issue | +| -------------- | -------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------ | +| Admin API Mode | Runs a separate etcd instance, with APISIX Admin API managing data plane configuration | Complex to deploy; high maintenance overhead for etcd | +| Mock-ETCD Mode | APISIX and the Ingress Controller are deployed in the same Pod, mocking etcd endpoints | Stateless Ingress cannot persist revision info; may lead to data inconsistency | + +#### Architecture in 2.0.0 + + + +##### Mock-ETCD Mode Deprecated + +The mock-etcd architecture is no longer supported. This mode introduced significant reliability issues: stateless ingress controllers could not persist revision metadata, leading to memory pollution in the data plane and data inconsistencies. + +The following configuration block has been removed: + +```yaml +etcdserver: + enabled: false + listen_address: ":12379" + prefix: /apisix + ssl_key_encrypt_salt: edd1c9f0985e76a2 +``` + +##### Controller-Only Configuration Source + +In 2.0.0, all data plane configurations must originate from the Ingress Controller. Configurations via Admin API or any external methods are no longer supported and will be ignored or may cause errors. + +### Ingress Configuration Changes + +#### Configuration Path Changes + +| Old Path | New Path | +| ------------------------ | -------------------- | +| `kubernetes.election_id` | `leader_election_id` | + +#### Removed Configuration Fields + +| Configuration Path | Description | +| -------------------- | ---------------------------------------- | +| `kubernetes.*` | Multi-namespace control / sync interval | +| `plugin_metadata_cm` | Plugin metadata ConfigMap | +| `log_rotation_*` | Log rotation settings | +| `apisix.*` | Static Admin API configuration | +| `etcdserver.*` | Configuration for mock-etcd (deprecated) | + +#### Example: Legacy Configuration Removed in 2.0.0 + +```yaml +apisix: + admin_api_version: v3 + default_cluster_base_url: "http://127.0.0.1:9180/apisix/admin" + default_cluster_admin_key: "" + default_cluster_name: "default" +``` + +#### New Configuration via `GatewayProxy` CRD + +From version 2.0.0, the data plane must be connected via the `GatewayProxy` CRD: + +```yaml +apiVersion: networking.k8s.io/v1 +kind: IngressClass +metadata: + name: apisix +spec: + controller: "apisix.apache.org/apisix-ingress-controller" + parameters: + apiGroup: "apisix.apache.org" + kind: "GatewayProxy" + name: "apisix-proxy-config" + namespace: "default" + scope: "Namespace" +--- +apiVersion: apisix.apache.org/v1alpha1 +kind: GatewayProxy +metadata: + name: apisix-proxy-config + namespace: default +spec: + provider: + type: ControlPlane + controlPlane: + endpoints: + - https://127.0.0.1:9180 + auth: + type: AdminKey + adminKey: + value: "" +``` + +### API Changes + +#### `ApisixUpstream` + +Due to current limitations in the ADC (API Definition Controller) component, the following fields are not yet supported: + +* `spec.discovery`: Service Discovery +* `spec.healthCheck`: Health Checking + +More details: [ADC Backend Differences](https://github.com/api7/adc/blob/2449ca81e3c61169f8c1e59efb4c1173a766bce2/libs/backend-apisix-standalone/README.md#differences-in-upstream) + +#### Limited Support for Ingress Annotations + +Ingress annotations used in version 1.x.x are not fully supported in 2.0.0. If your existing setup relies on any of the following annotations, validate compatibility or consider delaying the upgrade. + +| Ingress Annotations | +| ------------------------------------------------------ | +| `k8s.apisix.apache.org/use-regex` | +| `k8s.apisix.apache.org/enable-websocket` | +| `k8s.apisix.apache.org/plugin-config-name` | +| `k8s.apisix.apache.org/upstream-scheme` | +| `k8s.apisix.apache.org/upstream-retries` | +| `k8s.apisix.apache.org/upstream-connect-timeout` | +| `k8s.apisix.apache.org/upstream-read-timeout` | +| `k8s.apisix.apache.org/upstream-send-timeout` | +| `k8s.apisix.apache.org/enable-cors` | +| `k8s.apisix.apache.org/cors-allow-origin` | +| `k8s.apisix.apache.org/cors-allow-headers` | +| `k8s.apisix.apache.org/cors-allow-methods` | +| `k8s.apisix.apache.org/enable-csrf` | +| `k8s.apisix.apache.org/csrf-key` | +| `k8s.apisix.apache.org/http-to-https` | +| `k8s.apisix.apache.org/http-redirect` | +| `k8s.apisix.apache.org/http-redirect-code` | +| `k8s.apisix.apache.org/rewrite-target` | +| `k8s.apisix.apache.org/rewrite-target-regex` | +| `k8s.apisix.apache.org/rewrite-target-regex-template` | +| `k8s.apisix.apache.org/enable-response-rewrite` | +| `k8s.apisix.apache.org/response-rewrite-status-code` | +| `k8s.apisix.apache.org/response-rewrite-body` | +| `k8s.apisix.apache.org/response-rewrite-body-base64` | +| `k8s.apisix.apache.org/response-rewrite-add-header` | +| `k8s.apisix.apache.org/response-rewrite-set-header` | +| `k8s.apisix.apache.org/response-rewrite-remove-header` | +| `k8s.apisix.apache.org/auth-uri` | +| `k8s.apisix.apache.org/auth-ssl-verify` | +| `k8s.apisix.apache.org/auth-request-headers` | +| `k8s.apisix.apache.org/auth-upstream-headers` | +| `k8s.apisix.apache.org/auth-client-headers` | +| `k8s.apisix.apache.org/allowlist-source-range` | +| `k8s.apisix.apache.org/blocklist-source-range` | +| `k8s.apisix.apache.org/http-allow-methods` | +| `k8s.apisix.apache.org/http-block-methods` | +| `k8s.apisix.apache.org/auth-type` | +| `k8s.apisix.apache.org/svc-namespace` | + +### Summary + +| Category | Description | +| ---------------- | ---------------------------------------------------------------------------------------------------- | +| Architecture | The `mock-etcd` component has been removed. Configuration is now centralized through the Controller. | +| Configuration | Static configuration fields have been removed. Use `GatewayProxy` CRD to configure the data plane. | +| Data Plane | Requires APISIX version 3.13.0 running in `standalone` mode. | +| API | Some fields in `Ingress Annotations` and `ApisixUpstream` are not yet supported. | +| Upgrade Strategy | Blue-green deployment or canary release is recommended before full switchover. | diff --git a/internal/controller/config/config.go b/internal/controller/config/config.go index 6d1a256a..774f2728 100644 --- a/internal/controller/config/config.go +++ b/internal/controller/config/config.go @@ -118,7 +118,7 @@ func (c *Config) Validate() error { func validateProvider(config ProviderConfig) error { switch config.Type { - case ProviderTypeStandalone: + case ProviderTypeStandalone, ProviderTypeAPISIX: if config.SyncPeriod.Duration <= 0 { return fmt.Errorf("sync_period must be greater than 0 for standalone provider") } diff --git a/internal/controller/config/types.go b/internal/controller/config/types.go index 01f7d3cb..8669268f 100644 --- a/internal/controller/config/types.go +++ b/internal/controller/config/types.go @@ -26,6 +26,7 @@ type ProviderType string const ( ProviderTypeStandalone ProviderType = "apisix-standalone" ProviderTypeAPI7EE ProviderType = "api7ee" + ProviderTypeAPISIX ProviderType = "apisix" ) const ( diff --git a/internal/manager/controllers.go b/internal/manager/controllers.go index b877b168..0e24a812 100644 --- a/internal/manager/controllers.go +++ b/internal/manager/controllers.go @@ -43,7 +43,7 @@ import ( // +kubebuilder:rbac:groups=apisix.apache.org,resources=apisixglobalrules,verbs=get;list;watch // +kubebuilder:rbac:groups=apisix.apache.org,resources=apisixpluginconfigs,verbs=get;list;watch // +kubebuilder:rbac:groups=apisix.apache.org,resources=apisixroutes,verbs=get;list;watch -// +kubebuilder:rbac:groups=apisix.apache.org,resources=apisixtls,verbs=get;list;watch +// +kubebuilder:rbac:groups=apisix.apache.org,resources=apisixtlses,verbs=get;list;watch // +kubebuilder:rbac:groups=apisix.apache.org,resources=apisixupstreams,verbs=get;list;watch // CustomResourceDefinition v2 status @@ -51,7 +51,7 @@ import ( // +kubebuilder:rbac:groups=apisix.apache.org,resources=apisixglobalrules/status,verbs=get;update // +kubebuilder:rbac:groups=apisix.apache.org,resources=apisixpluginconfigs/status,verbs=get;update // +kubebuilder:rbac:groups=apisix.apache.org,resources=apisixroutes/status,verbs=get;update -// +kubebuilder:rbac:groups=apisix.apache.org,resources=apisixtls/status,verbs=get;update +// +kubebuilder:rbac:groups=apisix.apache.org,resources=apisixtlses/status,verbs=get;update // +kubebuilder:rbac:groups=apisix.apache.org,resources=apisixupstreams/status,verbs=get;update // CustomResourceDefinition @@ -71,6 +71,8 @@ import ( // +kubebuilder:rbac:groups=gateway.networking.k8s.io,resources=gateways/status,verbs=get;update // +kubebuilder:rbac:groups=gateway.networking.k8s.io,resources=httproutes,verbs=get;list;watch // +kubebuilder:rbac:groups=gateway.networking.k8s.io,resources=httproutes/status,verbs=get;update +// +kubebuilder:rbac:groups=gateway.networking.k8s.io,resources=referencegrants,verbs=list;watch;update +// +kubebuilder:rbac:groups=gateway.networking.k8s.io,resources=referencegrants/status,verbs=get;update // Networking // +kubebuilder:rbac:groups=networking.k8s.io,resources=ingresses,verbs=get;list;watch;update diff --git a/internal/provider/adc/adc.go b/internal/provider/adc/adc.go index 761069c2..96f6338e 100644 --- a/internal/provider/adc/adc.go +++ b/internal/provider/adc/adc.go @@ -20,12 +20,12 @@ package adc import ( "context" "encoding/json" - "errors" "os" "sync" "time" "github.com/api7/gopkg/pkg/log" + "github.com/pkg/errors" "go.uber.org/zap" networkingv1 "k8s.io/api/networking/v1" "sigs.k8s.io/controller-runtime/pkg/client" @@ -53,6 +53,7 @@ type BackendMode string const ( BackendModeAPISIXStandalone string = "apisix-standalone" BackendModeAPI7EE string = "api7ee" + BackendModeAPISIX string = "apisix" ) type adcClient struct { @@ -193,7 +194,7 @@ func (d *adcClient) Update(ctx context.Context, tctx *provider.TranslateContext, // This mode is full synchronization, // which only needs to be saved in cache // and triggered by a timer for synchronization - if d.BackendMode == BackendModeAPISIXStandalone || apiv2.Is(obj) { + if d.BackendMode == BackendModeAPISIXStandalone || d.BackendMode == BackendModeAPISIX || apiv2.Is(obj) { return nil } @@ -254,7 +255,7 @@ func (d *adcClient) Delete(ctx context.Context, obj client.Object) error { log.Debugw("successfully deleted resources from store", zap.Any("object", obj)) switch d.BackendMode { - case BackendModeAPISIXStandalone: + case BackendModeAPISIXStandalone, BackendModeAPISIX: // Full synchronization is performed on a gateway by gateway basis // and it is not possible to perform scheduled synchronization // on deleted gateway level resources diff --git a/internal/provider/adc/executor.go b/internal/provider/adc/executor.go index 7bedf554..e931f56e 100644 --- a/internal/provider/adc/executor.go +++ b/internal/provider/adc/executor.go @@ -51,15 +51,19 @@ func (e *DefaultADCExecutor) Execute(ctx context.Context, mode string, config ad func (e *DefaultADCExecutor) runADC(ctx context.Context, mode string, config adcConfig, args []string) error { for _, addr := range config.ServerAddrs { - ctxWithTimeout, cancel := context.WithTimeout(ctx, 15*time.Second) - defer cancel() - if err := e.runForSingleServer(ctxWithTimeout, addr, mode, config, args); err != nil { + if err := e.runForSingleServerWithTimeout(ctx, addr, mode, config, args); err != nil { return err } } return nil } +func (e *DefaultADCExecutor) runForSingleServerWithTimeout(ctx context.Context, serverAddr, mode string, config adcConfig, args []string) error { + ctx, cancel := context.WithTimeout(ctx, 15*time.Second) + defer cancel() + return e.runForSingleServer(ctx, serverAddr, mode, config, args) +} + func (e *DefaultADCExecutor) runForSingleServer(ctx context.Context, serverAddr, mode string, config adcConfig, args []string) error { cmdArgs := append([]string{}, args...) if !config.TlsVerify { @@ -113,6 +117,10 @@ func (e *DefaultADCExecutor) buildCmdError(runErr error, stdout, stderr []byte) func (e *DefaultADCExecutor) handleOutput(output []byte) error { var result adctypes.SyncResult + if index := strings.IndexByte(string(output), '{'); index > 0 { + log.Warnf("extra output: %s", string(output[:index])) + output = output[index:] + } if err := json.Unmarshal(output, &result); err != nil { log.Errorw("failed to unmarshal adc output", zap.Error(err), diff --git a/test/conformance/apisix/suite_test.go b/test/conformance/apisix/suite_test.go index bfaa8a19..2f9c47c7 100644 --- a/test/conformance/apisix/suite_test.go +++ b/test/conformance/apisix/suite_test.go @@ -166,7 +166,7 @@ func TestMain(m *testing.M) { Namespace: namespace, StatusAddress: address, InitSyncDelay: 1 * time.Minute, - ProviderType: "apisix-standalone", + ProviderType: framework.ProviderType, ProviderSyncPeriod: 10 * time.Millisecond, }) diff --git a/test/e2e/framework/apisix_consts.go b/test/e2e/framework/apisix_consts.go index bde8855d..7c162fdf 100644 --- a/test/e2e/framework/apisix_consts.go +++ b/test/e2e/framework/apisix_consts.go @@ -18,16 +18,25 @@ package framework import ( + "cmp" _ "embed" + "os" "text/template" "github.com/Masterminds/sprig/v3" ) var ( - //go:embed manifests/apisix-standalone.yaml + ProviderType = cmp.Or(os.Getenv("PROVIDER_TYPE"), "apisix-standalone") +) + +var ( + //go:embed manifests/apisix.yaml apisixStandaloneTemplate string APISIXStandaloneTpl *template.Template + + //go:embed manifests/etcd.yaml + EtcdSpec string ) var ( diff --git a/test/e2e/framework/assertion.go b/test/e2e/framework/assertion.go index 6a22fb0c..70d374fa 100644 --- a/test/e2e/framework/assertion.go +++ b/test/e2e/framework/assertion.go @@ -116,7 +116,7 @@ func APIv2MustHaveCondition(t testing.TestingT, cli client.Client, timeout time. } err := PollUntilAPIv2MustHaveStatus(cli, timeout, nn, obj, f) - require.NoError(t, err, "error waiting status to have a Condition matching %+v", nn, cond) + require.NoError(t, err, "error waiting %s status to have a Condition matching %+v", nn, cond) } func PollUntilAPIv2MustHaveStatus(cli client.Client, timeout time.Duration, nn types.NamespacedName, obj client.Object, f func(client.Object) bool) error { diff --git a/test/e2e/framework/manifests/apisix.yaml b/test/e2e/framework/manifests/apisix.yaml new file mode 100644 index 00000000..61d19763 --- /dev/null +++ b/test/e2e/framework/manifests/apisix.yaml @@ -0,0 +1,125 @@ +# Licensed to the Apache Software Foundation (ASF) under one +# or more contributor license agreements. See the NOTICE file +# distributed with this work for additional information +# regarding copyright ownership. The ASF licenses this file +# to you under the Apache License, Version 2.0 (the +# "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, +# software distributed under the License is distributed on an +# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +# KIND, either express or implied. See the License for the +# specific language governing permissions and limitations +# under the License. + +apiVersion: v1 +kind: ConfigMap +metadata: + name: apisix-conf +data: + config.yaml: | + deployment: + role: traditional + role_traditional: + # on backend mode apisix-standalone, config_provider is "yaml" + # on backend mode apisix, config_provider is "etcd" + config_provider: {{ .ConfigProvider | default "yaml" }} + admin: + allow_admin: + - 0.0.0.0/0 + admin_key: + - key: {{ .AdminKey }} + name: admin + role: admin + {{- if eq .ConfigProvider "etcd" }} + etcd: + host: + - "http://etcd:2379" + {{- end }} + nginx_config: + worker_processes: 2 + error_log_level: info +--- +apiVersion: apps/v1 +kind: Deployment +metadata: + name: apisix + labels: + app.kubernetes.io/name: apisix +spec: + replicas: 1 + selector: + matchLabels: + app.kubernetes.io/name: apisix + template: + metadata: + labels: + app.kubernetes.io/name: apisix + spec: + initContainers: + - name: config-setup + image: apache/apisix:dev + command: + - sh + - -c + - | + echo "Copying default config directory to writable volume" + cp -r /usr/local/apisix/conf/* /tmp/apisix-conf/ + echo "Overwriting config.yaml with custom configuration" + cp /tmp/config-source/config.yaml /tmp/apisix-conf/config.yaml + echo "Config setup completed successfully" + ls -la /tmp/apisix-conf/ + volumeMounts: + - name: config-source + mountPath: /tmp/config-source + - name: config-writable + mountPath: /tmp/apisix-conf + containers: + - name: apisix + image: apache/apisix:dev + ports: + - name: http + containerPort: 9080 + protocol: TCP + - name: https + containerPort: 9443 + protocol: TCP + - name: admin + containerPort: 9180 + protocol: TCP + volumeMounts: + - name: config-writable + mountPath: /usr/local/apisix/conf + volumes: + - name: config-source + configMap: + name: apisix-conf + - name: config-writable + emptyDir: {} +--- +apiVersion: v1 +kind: Service +metadata: + name: {{ .ServiceName }} + labels: + app.kubernetes.io/name: apisix +spec: + ports: + - port: {{ .ServiceHTTPPort }} + name: http + protocol: TCP + targetPort: 9080 + - port: {{ .ServiceHTTPSPort }} + name: https + protocol: TCP + targetPort: 9443 + - port: 9180 + name: admin + protocol: TCP + targetPort: 9180 + selector: + app.kubernetes.io/name: apisix + type: {{ .ServiceType | default "NodePort" }} diff --git a/test/e2e/framework/manifests/etcd.yaml b/test/e2e/framework/manifests/etcd.yaml new file mode 100644 index 00000000..1ada9ccc --- /dev/null +++ b/test/e2e/framework/manifests/etcd.yaml @@ -0,0 +1,58 @@ +# Licensed to the Apache Software Foundation (ASF) under one +# or more contributor license agreements. See the NOTICE file +# distributed with this work for additional information +# regarding copyright ownership. The ASF licenses this file +# to you under the Apache License, Version 2.0 (the +# "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, +# software distributed under the License is distributed on an +# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +# KIND, either express or implied. See the License for the +# specific language governing permissions and limitations +# under the License. + +--- +apiVersion: apps/v1 +kind: Deployment +metadata: + name: etcd +spec: + replicas: 1 + selector: + matchLabels: + app: etcd + template: + metadata: + labels: + app: etcd + spec: + containers: + - name: etcd + image: quay.io/coreos/etcd:v3.5.0 + command: + - etcd + - --data-dir=/etcd-data + - --name=node1 + - --initial-advertise-peer-urls=http://0.0.0.0:2380 + - --listen-peer-urls=http://0.0.0.0:2380 + - --advertise-client-urls=http://0.0.0.0:2379 + - --listen-client-urls=http://0.0.0.0:2379 + - --initial-cluster=node1=http://0.0.0.0:2380 + ports: + - containerPort: 2379 + - containerPort: 2380 +--- +apiVersion: v1 +kind: Service +metadata: + name: etcd +spec: + ports: + - port: 2379 + targetPort: 2379 + selector: + app: etcd diff --git a/test/e2e/framework/manifests/ingress.yaml b/test/e2e/framework/manifests/ingress.yaml index 7b47f969..52a8b222 100644 --- a/test/e2e/framework/manifests/ingress.yaml +++ b/test/e2e/framework/manifests/ingress.yaml @@ -129,7 +129,7 @@ rules: - apisixglobalrules - apisixpluginconfigs - apisixroutes - - apisixtls + - apisixtlses - apisixupstreams - backendtrafficpolicies - consumers @@ -147,7 +147,7 @@ rules: - apisixglobalrules/status - apisixpluginconfigs/status - apisixroutes/status - - apisixtls/status + - apisixtlses/status - apisixupstreams/status - backendtrafficpolicies/status - consumers/status diff --git a/test/e2e/gatewayapi/httproute.go b/test/e2e/gatewayapi/httproute.go index cf8de912..4239b2f6 100644 --- a/test/e2e/gatewayapi/httproute.go +++ b/test/e2e/gatewayapi/httproute.go @@ -529,7 +529,7 @@ spec: By("create HTTPRoute") ResourceApplied("HTTPRoute", "httpbin", exactRouteByGet, 1) - By("access daataplane to check the HTTPRoute") + By("access dataplane to check the HTTPRoute") s.NewAPISIXClient(). GET("/get"). WithHost("httpbin.example"). @@ -539,13 +539,14 @@ spec: By("delete Gateway") err := s.DeleteResource("Gateway", "apisix") Expect(err).NotTo(HaveOccurred(), "deleting Gateway") - time.Sleep(5 * time.Second) - s.NewAPISIXClient(). - GET("/get"). - WithHost("httpbin.example"). - Expect(). - Status(404) + Eventually(func() int { + return s.NewAPISIXClient(). + GET("/get"). + WithHost("httpbin.example"). + Expect(). + Raw().StatusCode + }).WithTimeout(5 * time.Second).ProbeEvery(time.Second).Should(Equal(http.StatusNotFound)) }) It("Proxy External Service", func() { diff --git a/test/e2e/scaffold/adc.go b/test/e2e/scaffold/adc.go index ef075689..18d7d78c 100644 --- a/test/e2e/scaffold/adc.go +++ b/test/e2e/scaffold/adc.go @@ -31,6 +31,7 @@ import ( adctypes "github.com/apache/apisix-ingress-controller/api/adc" "github.com/apache/apisix-ingress-controller/internal/provider/adc/translator" + "github.com/apache/apisix-ingress-controller/test/e2e/framework" ) // DataplaneResource defines the interface for accessing dataplane resources @@ -98,6 +99,7 @@ func (a *adcDataplaneResource) Consumer() ConsumerResource { } func init() { + // dashboard sdk log l, err := log.NewLogger( log.WithOutputFile("stderr"), log.WithLogLevel("debug"), @@ -135,6 +137,9 @@ func (a *adcDataplaneResource) dumpResources(ctx context.Context) (*translator.T "ADC_SERVER=" + a.serverAddr, "ADC_TOKEN=" + a.token, } + if framework.ProviderType != "" { + adcEnv = append(adcEnv, "ADC_BACKEND="+framework.ProviderType) + } var stdout, stderr bytes.Buffer cmd := exec.CommandContext(ctxWithTimeout, "adc", args...) diff --git a/test/e2e/scaffold/apisix_deployer.go b/test/e2e/scaffold/apisix_deployer.go index ef3e052e..a875e0b9 100644 --- a/test/e2e/scaffold/apisix_deployer.go +++ b/test/e2e/scaffold/apisix_deployer.go @@ -29,6 +29,7 @@ import ( corev1 "k8s.io/api/core/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "github.com/apache/apisix-ingress-controller/internal/provider/adc" "github.com/apache/apisix-ingress-controller/pkg/utils" "github.com/apache/apisix-ingress-controller/test/e2e/framework" ) @@ -41,6 +42,8 @@ type APISIXDeployOptions struct { ServiceType string ServiceHTTPPort int ServiceHTTPSPort int + + ConfigProvider string } type APISIXDeployer struct { @@ -181,7 +184,7 @@ func (s *APISIXDeployer) newAPISIXTunnels(serviceName string) error { func (s *APISIXDeployer) deployDataplane(opts *APISIXDeployOptions) *corev1.Service { if opts.ServiceName == "" { - opts.ServiceName = "apisix-standalone" + opts.ServiceName = framework.ProviderType } if opts.ServiceHTTPPort == 0 { @@ -191,12 +194,24 @@ func (s *APISIXDeployer) deployDataplane(opts *APISIXDeployOptions) *corev1.Serv if opts.ServiceHTTPSPort == 0 { opts.ServiceHTTPSPort = 443 } + opts.ConfigProvider = "yaml" + + kubectlOpts := k8s.NewKubectlOptions("", "", opts.Namespace) + + if framework.ProviderType == adc.BackendModeAPISIX { + opts.ConfigProvider = "etcd" + // deploy etcd + k8s.KubectlApplyFromString(s.GinkgoT, kubectlOpts, framework.EtcdSpec) + err := framework.WaitPodsAvailable(s.GinkgoT, kubectlOpts, metav1.ListOptions{ + LabelSelector: "app=etcd", + }) + Expect(err).ToNot(HaveOccurred(), "waiting for etcd pod ready") + } buf := bytes.NewBuffer(nil) err := framework.APISIXStandaloneTpl.Execute(buf, opts) Expect(err).ToNot(HaveOccurred(), "executing template") - kubectlOpts := k8s.NewKubectlOptions("", "", opts.Namespace) k8s.KubectlApplyFromString(s.GinkgoT, kubectlOpts, buf.String()) err = framework.WaitPodsAvailable(s.GinkgoT, kubectlOpts, metav1.ListOptions{ @@ -223,8 +238,9 @@ func (s *APISIXDeployer) deployDataplane(opts *APISIXDeployOptions) *corev1.Serv func (s *APISIXDeployer) DeployIngress() { s.Framework.DeployIngress(framework.IngressDeployOpts{ - ProviderSyncPeriod: 200 * time.Millisecond, ControllerName: s.opts.ControllerName, + ProviderType: framework.ProviderType, + ProviderSyncPeriod: 200 * time.Millisecond, Namespace: s.namespace, Replicas: 1, }) @@ -232,8 +248,9 @@ func (s *APISIXDeployer) DeployIngress() { func (s *APISIXDeployer) ScaleIngress(replicas int) { s.Framework.DeployIngress(framework.IngressDeployOpts{ - ProviderSyncPeriod: 200 * time.Millisecond, ControllerName: s.opts.ControllerName, + ProviderType: framework.ProviderType, + ProviderSyncPeriod: 200 * time.Millisecond, Namespace: s.namespace, Replicas: replicas, })