Skip to content
Closed
Show file tree
Hide file tree
Changes from 4 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 9 additions & 0 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,10 @@ GATEAY_API_VERSION ?= v1.2.0
DASHBOARD_VERSION ?= dev
TEST_TIMEOUT ?= 45m

APISIX_IMAGE ?= apache/apisix:dev
APISIX_ADMIN_KEY ?= edd1c9f034335f136f87ad84b625c8f1
APISIX_NAMESPACE ?= apisix-standalone

# CRD Reference Documentation
CRD_REF_DOCS_VERSION ?= v0.1.0
CRD_REF_DOCS ?= $(LOCALBIN)/crd-ref-docs
Expand Down Expand Up @@ -111,6 +115,11 @@ e2e-test:
@kind get kubeconfig --name $(KIND_NAME) > $$KUBECONFIG
DASHBOARD_VERSION=$(DASHBOARD_VERSION) go test ./test/e2e/ -test.timeout=$(TEST_TIMEOUT) -v -ginkgo.v -ginkgo.focus="$(TEST_FOCUS)"

.PHONY: e2e-test-standalone
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

need add ci.

e2e-test-standalone:
@kind get kubeconfig --name $(KIND_NAME) > $$KUBECONFIG
APISIX_IMAGE=$(APISIX_IMAGE) APISIX_ADMIN_KEY=$(APISIX_ADMIN_KEY) APISIX_NAMESPACE=$(APISIX_NAMESPACE) go test ./test/e2e/apisix/ -test.timeout=$(TEST_TIMEOUT) -v -ginkgo.v -ginkgo.focus="$(TEST_FOCUS)"

.PHONY: download-api7ee3-chart
download-api7ee3-chart:
@helm repo add api7 https://charts.api7.ai || true
Expand Down
202 changes: 202 additions & 0 deletions go.sum

Large diffs are not rendered by default.

6 changes: 6 additions & 0 deletions test/e2e/e2e_test.go → test/e2e/api7_e2e_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -24,13 +24,19 @@ import (
"github.com/apache/apisix-ingress-controller/test/e2e/framework"
_ "github.com/apache/apisix-ingress-controller/test/e2e/gatewayapi"
_ "github.com/apache/apisix-ingress-controller/test/e2e/ingress"
"github.com/apache/apisix-ingress-controller/test/e2e/scaffold"
)

// Run e2e tests using the Ginkgo runner.
func TestE2E(t *testing.T) {
RegisterFailHandler(Fail)
f := framework.NewFramework()

// init newScaffold function
scaffold.NewScaffold = func(opts *scaffold.Options) scaffold.TestScaffold {
return scaffold.NewAPI7Scaffold(opts)
}

BeforeSuite(f.BeforeSuite)
AfterSuite(f.AfterSuite)

Expand Down
40 changes: 40 additions & 0 deletions test/e2e/apisix/basic.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
// Licensed 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.

package apisix

import (
. "github.com/onsi/ginkgo/v2"
. "github.com/onsi/gomega"

"github.com/apache/apisix-ingress-controller/test/e2e/scaffold"
)

var _ = Describe("APISIX Standalone Basic Tests", func() {
s := scaffold.NewScaffold(&scaffold.Options{
ControllerName: "apisix.apache.org/apisix-ingress-controller",
})

Describe("APISIX HTTP Proxy", func() {
It("should handle basic HTTP requests", func() {
httpClient := s.NewAPISIXClient()
Expect(httpClient).NotTo(BeNil())

// Test basic connectivity
resp := httpClient.GET("/anything").
Expect().
Status(200)

resp.JSON().Object().ContainsKey("url")
})
})
})
41 changes: 41 additions & 0 deletions test/e2e/apisix/e2e_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
// Licensed 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.

package apisix

import (
"fmt"
"testing"

. "github.com/onsi/ginkgo/v2"
. "github.com/onsi/gomega"

"github.com/apache/apisix-ingress-controller/test/e2e/framework"
"github.com/apache/apisix-ingress-controller/test/e2e/scaffold"
)

// TestAPISIXE2E runs e2e tests using the APISIX standalone mode
func TestAPISIXE2E(t *testing.T) {
RegisterFailHandler(Fail)
f := framework.NewAPISIXFramework()

// init newScaffold function
scaffold.NewScaffold = func(opts *scaffold.Options) scaffold.TestScaffold {
return scaffold.NewAPISIXScaffold(opts)
}

BeforeSuite(f.BeforeSuite)
AfterSuite(f.AfterSuite)

_, _ = fmt.Fprintf(GinkgoWriter, "Starting APISIX standalone e2e suite\n")
RunSpecs(t, "apisix standalone e2e suite")
}
156 changes: 156 additions & 0 deletions test/e2e/framework/apisix.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,156 @@
// Licensed 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.

package framework

import (
"bytes"
"context"
_ "embed"
"fmt"
"os"
"text/template"
"time"

"github.com/Masterminds/sprig/v3"
"github.com/gruntwork-io/terratest/modules/k8s"
"github.com/gruntwork-io/terratest/modules/testing"
corev1 "k8s.io/api/core/v1"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/util/wait"
)

//go:embed manifests/apisix-standalone.yaml
var apisixStandaloneTemplate string

// APISIXDeployOptions contains options for APISIX standalone deployment
type APISIXDeployOptions struct {
Namespace string
Image string
AdminKey string
ServiceType string
HTTPNodePort int32
HTTPSNodePort int32
AdminNodePort int32
}

// APISIXDeployer implements DataPlaneDeployer for APISIX standalone
type APISIXDeployer struct {
kubectlOpts *k8s.KubectlOptions
opts *APISIXDeployOptions
service *corev1.Service
t testing.TestingT
}

// NewAPISIXDeployer creates a new APISIX deployer
func NewAPISIXDeployer(t testing.TestingT, kubectlOpts *k8s.KubectlOptions, opts *APISIXDeployOptions) *APISIXDeployer {
if opts.Image == "" {
opts.Image = getEnvOrDefault("APISIX_IMAGE", "apache/apisix:dev")
}
if opts.AdminKey == "" {
opts.AdminKey = getEnvOrDefault("APISIX_ADMIN_KEY", "edd1c9f034335f136f87ad84b625c8f1")
}
if opts.Namespace == "" {
opts.Namespace = getEnvOrDefault("APISIX_NAMESPACE", "apisix-standalone")
}
if opts.ServiceType == "" {
opts.ServiceType = "ClusterIP"
}

return &APISIXDeployer{
kubectlOpts: kubectlOpts,
opts: opts,
t: t,
}
}

func (d *APISIXDeployer) GetService() *corev1.Service {
return d.service
}

// Deploy deploys APISIX standalone
func (d *APISIXDeployer) Deploy(ctx context.Context) error {
// Parse and execute template
tmpl, err := template.New("apisix-standalone").Funcs(sprig.TxtFuncMap()).Parse(apisixStandaloneTemplate)
if err != nil {
return fmt.Errorf("failed to parse template: %w", err)
}

var buf bytes.Buffer
if err := tmpl.Execute(&buf, d.opts); err != nil {
return fmt.Errorf("failed to execute template: %w", err)
}

// Apply the manifest
if err := k8s.KubectlApplyFromStringE(d.t, d.kubectlOpts, buf.String()); err != nil {
return fmt.Errorf("failed to apply APISIX manifest: %w", err)
}

// Wait for deployment to be ready
if err := d.waitForDeployment(ctx); err != nil {
return fmt.Errorf("failed to wait for deployment: %w", err)
}

// Get service
service, err := k8s.GetServiceE(d.t, d.kubectlOpts, "apisix")
if err != nil {
return fmt.Errorf("failed to get APISIX service: %w", err)
}
d.service = service

return nil
}

// Cleanup removes APISIX standalone deployment
func (d *APISIXDeployer) Cleanup(ctx context.Context) error {
// Delete namespace which will clean up all resources
return k8s.DeleteNamespaceE(d.t, d.kubectlOpts, d.opts.Namespace)
}

// waitForDeployment waits for the APISIX deployment to be ready
func (d *APISIXDeployer) waitForDeployment(ctx context.Context) error {

Check failure on line 120 in test/e2e/framework/apisix.go

View workflow job for this annotation

GitHub Actions / lint

(*APISIXDeployer).waitForDeployment - ctx is unused (unparam)
return wait.PollImmediate(5*time.Second, 5*time.Minute, func() (bool, error) {

Check failure on line 121 in test/e2e/framework/apisix.go

View workflow job for this annotation

GitHub Actions / lint

SA1019: wait.PollImmediate is deprecated: This method does not return errors from context, use PollUntilContextTimeout. Note that the new method will no longer return ErrWaitTimeout and instead return errors defined by the context package. Will be removed in a future release. (staticcheck)
pods, err := k8s.ListPodsE(d.t, d.kubectlOpts, metav1.ListOptions{
LabelSelector: "app=apisix",
})
if err != nil {
return false, err
}

if len(pods) == 0 {
return false, nil
}

for _, pod := range pods {
if pod.Status.Phase != corev1.PodRunning {
return false, nil
}

// Check if all containers are ready
for _, condition := range pod.Status.Conditions {
if condition.Type == corev1.PodReady && condition.Status != corev1.ConditionTrue {
return false, nil
}
}
}

return true, nil
})
}

// getEnvOrDefault returns environment variable value or default
func getEnvOrDefault(key, defaultValue string) string {
if value := os.Getenv(key); value != "" {
return value
}
return defaultValue
}
Loading
Loading