Skip to content

Commit

Permalink
feat(gateway): add gateway e2e test (#343)
Browse files Browse the repository at this point in the history
* feat(gateway): add gateway e2e test

* feat(gateway): add test readme

* feat(gateway): opt test
  • Loading branch information
skyoct authored Sep 26, 2022
1 parent 4ba3973 commit e823060
Show file tree
Hide file tree
Showing 14 changed files with 709 additions and 5 deletions.
4 changes: 4 additions & 0 deletions controllers/gateway/api/v1/gateway_types.go
Original file line number Diff line number Diff line change
Expand Up @@ -74,6 +74,10 @@ type GatewayStatus struct {

// WebsiteRoutes 是静态站点路由
WebsiteRoutes map[string]*GatewayRoute `json:"websiteRoutes,omitempty"`

// Conditions
// - Type: Ready
Conditions []metav1.Condition `json:"conditions,omitempty"`
}

type GatewayRoute struct {
Expand Down
69 changes: 69 additions & 0 deletions controllers/gateway/config/crd/bases/gateway.laf.dev_gateways.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -91,6 +91,75 @@ spec:
type: object
description: BucketRoutes 是存储桶路由
type: object
conditions:
description: 'Conditions - Type: Ready'
items:
description: "Condition contains details for one aspect of the current
state of this API Resource. --- This struct is intended for direct
use as an array at the field path .status.conditions. For example,
\n type FooStatus struct{ // Represents the observations of a
foo's current state. // Known .status.conditions.type are: \"Available\",
\"Progressing\", and \"Degraded\" // +patchMergeKey=type // +patchStrategy=merge
// +listType=map // +listMapKey=type Conditions []metav1.Condition
`json:\"conditions,omitempty\" patchStrategy:\"merge\" patchMergeKey:\"type\"
protobuf:\"bytes,1,rep,name=conditions\"` \n // other fields }"
properties:
lastTransitionTime:
description: lastTransitionTime is the last time the condition
transitioned from one status to another. This should be when
the underlying condition changed. If that is not known, then
using the time when the API field changed is acceptable.
format: date-time
type: string
message:
description: message is a human readable message indicating
details about the transition. This may be an empty string.
maxLength: 32768
type: string
observedGeneration:
description: observedGeneration represents the .metadata.generation
that the condition was set based upon. For instance, if .metadata.generation
is currently 12, but the .status.conditions[x].observedGeneration
is 9, the condition is out of date with respect to the current
state of the instance.
format: int64
minimum: 0
type: integer
reason:
description: reason contains a programmatic identifier indicating
the reason for the condition's last transition. Producers
of specific condition types may define expected values and
meanings for this field, and whether the values are considered
a guaranteed API. The value should be a CamelCase string.
This field may not be empty.
maxLength: 1024
minLength: 1
pattern: ^[A-Za-z]([A-Za-z0-9_,:]*[A-Za-z0-9_])?$
type: string
status:
description: status of the condition, one of True, False, Unknown.
enum:
- "True"
- "False"
- Unknown
type: string
type:
description: type of condition in CamelCase or in foo.example.com/CamelCase.
--- Many .condition.type values are consistent across resources
like Available, but because arbitrary conditions can be useful
(see .node.status.conditions), the ability to deconflict is
important. The regex it matches is (dns1123SubdomainFmt/)?(qualifiedNameFmt)
maxLength: 316
pattern: ^([a-z0-9]([-a-z0-9]*[a-z0-9])?(\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*/)?(([A-Za-z0-9][-A-Za-z0-9_.]*)?[A-Za-z0-9])$
type: string
required:
- lastTransitionTime
- message
- reason
- status
- type
type: object
type: array
websiteRoutes:
additionalProperties:
properties:
Expand Down
30 changes: 25 additions & 5 deletions controllers/gateway/controllers/gateway_controller.go
Original file line number Diff line number Diff line change
Expand Up @@ -20,10 +20,12 @@ import (
"context"
"errors"
ossv1 "github.com/labring/laf/controllers/oss/api/v1"
"github.com/labring/laf/pkg/util"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/types"
"k8s.io/client-go/util/retry"
"laf/pkg/util"
"sigs.k8s.io/controller-runtime/pkg/controller/controllerutil"
"time"

apierrors "k8s.io/apimachinery/pkg/api/errors"
"k8s.io/apimachinery/pkg/runtime"
Expand Down Expand Up @@ -84,6 +86,24 @@ func (r *GatewayReconciler) apply(ctx context.Context, gateway *gatewayv1.Gatewa
return result, err
}

// update ready condition
if util.IsConditionTrue(gateway.Status.Conditions, "Ready") == false {
condition := metav1.Condition{
Type: "Ready",
Status: metav1.ConditionTrue,
LastTransitionTime: metav1.NewTime(time.Now()),
Reason: "GatewayReady",
Message: "Gateway is ready",
}

util.SetCondition(&gateway.Status.Conditions, condition)
if err := r.updateStatus(ctx, types.NamespacedName{Name: gateway.Name, Namespace: gateway.Namespace}, gateway.Status.DeepCopy()); err != nil {
return ctrl.Result{}, err
}
_log.Info("Updated gateway condition to ready", "gateway", gateway.Name)
return ctrl.Result{}, nil
}

_log.Info("apply gateway: name success", "name", gateway.Name)

return ctrl.Result{}, nil
Expand Down Expand Up @@ -117,7 +137,7 @@ func (r *GatewayReconciler) applyApp(ctx context.Context, gateway *gatewayv1.Gat
appRoute := &gatewayv1.Route{
ObjectMeta: ctrl.ObjectMeta{
Name: "app",
Namespace: gateway.Spec.AppId,
Namespace: gateway.Namespace,
},
Spec: gatewayv1.RouteSpec{
Domain: routeStatus.Domain,
Expand Down Expand Up @@ -213,7 +233,7 @@ func (r *GatewayReconciler) addBuckets(ctx context.Context, gateway *gatewayv1.G
}
// get store
store := ossv1.Store{}
err = r.Get(ctx, client.ObjectKey{Namespace: gateway.Namespace, Name: user.Status.StoreName}, &store)
err = r.Get(ctx, client.ObjectKey{Namespace: user.Status.StoreNamespace, Name: user.Status.StoreName}, &store)
if err != nil {
return ctrl.Result{}, err
}
Expand All @@ -237,7 +257,7 @@ func (r *GatewayReconciler) addBuckets(ctx context.Context, gateway *gatewayv1.G
bucketRoute := &gatewayv1.Route{
ObjectMeta: ctrl.ObjectMeta{
Name: "bucket-" + bucketName,
Namespace: gateway.Spec.AppId,
Namespace: gateway.Namespace,
},
Spec: gatewayv1.RouteSpec{
Domain: routeStatus.Domain,
Expand Down Expand Up @@ -279,7 +299,7 @@ func (r *GatewayReconciler) deleteBuckets(ctx context.Context, gateway *gatewayv
route := &gatewayv1.Route{}

// 删除名称为test的route
if err := r.Get(ctx, client.ObjectKey{Namespace: gateway.Spec.AppId, Name: "bucket-" + bucketName}, route); err != nil {
if err := r.Get(ctx, client.ObjectKey{Namespace: gateway.Namespace, Name: "bucket-" + bucketName}, route); err != nil {
if apierrors.IsNotFound(err) {
continue
}
Expand Down
39 changes: 39 additions & 0 deletions controllers/gateway/tests/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
# Gateway tests

## How to use

TODO: Install apisix in test code

### install apisix and forward port

```shell
helm repo add apisix https://charts.apiseven.com
helm repo update
helm install apisix apisix/apisix --create-namespace --namespace apisix
kubectl port-forward service/apisix-gateway 19180:9180 -n apisix
```

### install crds and run controller

```shell
cd controllers/oss && make install
cd controllers/gateway && make install
go main.go
```

### run test

```shell
cd controllers/gateway
go test tests/e2e/gateway_test.go

```

### uninstall apisix

```
helm uninstall apisix -n apisix
```



71 changes: 71 additions & 0 deletions controllers/gateway/tests/api/domain.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
package api

import (
testapi "github.com/labring/laf/tests/api"
"github.com/labring/laf/tests/util"
)

const appDomainYaml = `
apiVersion: gateway.laf.dev/v1
kind: Domain
metadata:
name: {{ .name }}
namespace: {{ .namespace }}
spec:
backendType: app
cluster:
key: edd1c9f034335f136f87ad84b625c8f1
url: http://localhost:19180/apisix/admin
domain: app.laf.win
region: default
`

func createAppDomain(name, namespace string) {
template, err := util.RenderTemplate(appDomainYaml, map[string]string{
"name": name,
"namespace": namespace,
})
if err != nil {
panic(err)
}
_, err = testapi.KubeApply(template)
if err != nil {
panic(err)
}

}

const bucketDomainYaml = `
apiVersion: gateway.laf.dev/v1
kind: Domain
metadata:
name: {{ .name }}
namespace: {{ .namespace }}
spec:
backendType: bucket
cluster:
key: edd1c9f034335f136f87ad84b625c8f1
url: http://localhost:19180/apisix/admin
domain: oss.laf.win
region: default
`

func createBucketDomain(name, namespace string) {
template, err := util.RenderTemplate(bucketDomainYaml, map[string]string{
"name": name,
"namespace": namespace,
})
if err != nil {
panic(err)
}
_, err = testapi.KubeApply(template)
if err != nil {
panic(err)
}
}

func CreateDomain(name, namespace string) {
createAppDomain(name+"-app", namespace)
createBucketDomain(name+"-bucket", namespace)
}
1 change: 1 addition & 0 deletions controllers/gateway/tests/api/domain_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
package api
104 changes: 104 additions & 0 deletions controllers/gateway/tests/api/gateway.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,104 @@
package api

import (
"fmt"
testapi "github.com/labring/laf/tests/api"
"github.com/labring/laf/tests/util"
)

const systemNamespace = "testing-system"
const testNamespace = "testing"

const gatewayYaml = `
apiVersion: gateway.laf.dev/v1
kind: Gateway
metadata:
name: {{ .name }}
namespace: {{ .namespace }}
spec:
appid: {{ .appId }}
`

// CreateGateway create a gateway
func CreateGateway(name, namespace, appId string) {
template, err := util.RenderTemplate(gatewayYaml, map[string]string{
"name": name,
"namespace": namespace,
"appId": appId,
})
if err != nil {
panic(err)
}
_, err = testapi.KubeApply(template)
if err != nil {
panic(err)
}
}

const gatewayBucketYaml = `
apiVersion: gateway.laf.dev/v1
kind: Gateway
metadata:
name: {{ .name }}
namespace: {{ .namespace }}
spec:
appid: testing
buckets: ["{{ .bucketName }}"]
`

// AddGatewayBucket add gateway bucket
func AddGatewayBucket(name, namespace, appId, bucketName string) {
template, err := util.RenderTemplate(gatewayBucketYaml, map[string]string{
"name": name,
"namespace": namespace,
"appId": appId,
"bucketName": bucketName,
})
if err != nil {
panic(err)
}
_, err = testapi.KubeApply(template)
if err != nil {
panic(err)
}
}

// DeleteGatewayBucket delete gateway bucket
func DeleteGatewayBucket(name, namespace, appId string) {
template, err := util.RenderTemplate(gatewayYaml, map[string]string{
"name": name,
"namespace": namespace,
"appId": appId,
})
if err != nil {
panic(err)
}
_, err = testapi.KubeApply(template)
if err != nil {
panic(err)
}
}

// DeleteGateway delete gateway
func DeleteGateway(name, namespace, appId string) {
template, err := util.RenderTemplate(gatewayYaml, map[string]string{
"name": name,
"namespace": namespace,
"appId": appId,
})
if err != nil {
panic(err)
}
_, err = testapi.KubeDelete(template)
if err != nil {
panic(err)
}
}

func WaitForGatewayReady(name string, namespace string) {
cmd := fmt.Sprintf("kubectl wait --for=condition=ready --timeout=60s gateways.gateway.laf.dev/%s -n %s", name, namespace)
_, err := testapi.Exec(cmd)
if err != nil {
panic(err)
}
}
1 change: 1 addition & 0 deletions controllers/gateway/tests/api/gateway_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
package api
Loading

0 comments on commit e823060

Please sign in to comment.