test: add live acceptance CRUD test and document test flow
This commit is contained in:
@@ -52,6 +52,13 @@ cd terraform/provider
|
||||
go test ./...
|
||||
```
|
||||
|
||||
Acceptance-тест (реальный кластер, опционально):
|
||||
|
||||
```bash
|
||||
cd terraform/provider
|
||||
ACCEPTANCE_TEST=1 KUBECONFIG=/home/naeel/.kube/config go test ./internal/client -run TestAcceptanceFissionCRUD -v
|
||||
```
|
||||
|
||||
Импорт существующего ресурса (пример):
|
||||
|
||||
```bash
|
||||
|
||||
@@ -128,3 +128,14 @@
|
||||
|
||||
### Следующий шаг
|
||||
- Добавить acceptance-тесты с опциональным запуском по env-флагу.
|
||||
|
||||
### Обновление этапа (acceptance тест)
|
||||
- Добавлен acceptance-тест `terraform/provider/internal/client/client_acceptance_test.go`.
|
||||
- Тест выполняет живой CRUD в кластере для цепочки:
|
||||
- Environment -> Package -> Function -> HTTPTrigger
|
||||
- Запуск теста:
|
||||
- `ACCEPTANCE_TEST=1 KUBECONFIG=/home/naeel/.kube/config go test ./internal/client -run TestAcceptanceFissionCRUD -v`
|
||||
- Результат: PASS.
|
||||
|
||||
### Следующий шаг
|
||||
- Расширить acceptance-тест проверкой реального HTTP-вызова функции через ingress.
|
||||
|
||||
@@ -156,3 +156,19 @@
|
||||
- Повторный `terraform apply` успешен.
|
||||
- Финальная проверка endpoint:
|
||||
- `GET /tf-hello` -> `hello from fission via terraform`.
|
||||
|
||||
---
|
||||
|
||||
Агент: GitHub Copilot
|
||||
Модель: GPT-5.3-Codex
|
||||
|
||||
## План (до действий, этап 9)
|
||||
1. Добавить acceptance-тест для реального CRUD через `internal/client`.
|
||||
2. Прогнать unit + acceptance тесты.
|
||||
3. Зафиксировать результат в документации.
|
||||
|
||||
## Результат (после действий, этап 9)
|
||||
- Добавлен `internal/client/client_acceptance_test.go`.
|
||||
- Unit-тесты: PASS.
|
||||
- Acceptance-тест `TestAcceptanceFissionCRUD`: PASS.
|
||||
- Тест создает и удаляет Environment/Package/Function/HTTPTrigger в реальном кластере.
|
||||
|
||||
@@ -0,0 +1,171 @@
|
||||
package client
|
||||
|
||||
import (
|
||||
"context"
|
||||
"encoding/base64"
|
||||
"fmt"
|
||||
"os"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
|
||||
"k8s.io/apimachinery/pkg/runtime/schema"
|
||||
)
|
||||
|
||||
// TestAcceptanceFissionCRUD выполняет интеграционный CRUD тест в реальном кластере.
|
||||
func TestAcceptanceFissionCRUD(t *testing.T) {
|
||||
if os.Getenv("ACCEPTANCE_TEST") != "1" {
|
||||
t.Skip("set ACCEPTANCE_TEST=1 to run acceptance tests")
|
||||
}
|
||||
|
||||
kubeconfigPath := os.Getenv("KUBECONFIG")
|
||||
if kubeconfigPath == "" {
|
||||
kubeconfigPath = "/home/naeel/.kube/config"
|
||||
}
|
||||
|
||||
namespace := os.Getenv("FISSION_NAMESPACE")
|
||||
if namespace == "" {
|
||||
namespace = "default"
|
||||
}
|
||||
|
||||
c, err := New(kubeconfigPath, os.Getenv("KUBE_CONTEXT"), namespace)
|
||||
if err != nil {
|
||||
t.Fatalf("create client: %v", err)
|
||||
}
|
||||
|
||||
ctx := context.Background()
|
||||
suffix := time.Now().UnixNano()
|
||||
envName := fmt.Sprintf("acc-env-%d", suffix)
|
||||
pkgName := fmt.Sprintf("acc-pkg-%d", suffix)
|
||||
fnName := fmt.Sprintf("acc-fn-%d", suffix)
|
||||
triggerName := fmt.Sprintf("acc-tr-%d", suffix)
|
||||
urlPath := fmt.Sprintf("/acc-%d", suffix)
|
||||
|
||||
envObj := &unstructured.Unstructured{Object: map[string]interface{}{
|
||||
"apiVersion": "fission.io/v1",
|
||||
"kind": "Environment",
|
||||
"metadata": map[string]interface{}{
|
||||
"name": envName,
|
||||
"namespace": namespace,
|
||||
},
|
||||
"spec": map[string]interface{}{
|
||||
"version": 3,
|
||||
"runtime": map[string]interface{}{
|
||||
"image": "ghcr.io/fission/python-env",
|
||||
},
|
||||
"poolsize": 1,
|
||||
},
|
||||
}}
|
||||
|
||||
if _, err = c.CreateEnvironment(ctx, envObj); err != nil {
|
||||
t.Fatalf("create environment: %v", err)
|
||||
}
|
||||
defer func() { _ = c.DeleteEnvironment(ctx, namespace, envName) }()
|
||||
|
||||
if _, err = c.GetEnvironment(ctx, namespace, envName); err != nil {
|
||||
t.Fatalf("get environment: %v", err)
|
||||
}
|
||||
|
||||
literal := base64.StdEncoding.EncodeToString([]byte("def main():\n return 'ok from acceptance'\n"))
|
||||
pkgObj := &unstructured.Unstructured{Object: map[string]interface{}{
|
||||
"apiVersion": "fission.io/v1",
|
||||
"kind": "Package",
|
||||
"metadata": map[string]interface{}{
|
||||
"name": pkgName,
|
||||
"namespace": namespace,
|
||||
},
|
||||
"spec": map[string]interface{}{
|
||||
"deployment": map[string]interface{}{
|
||||
"type": "literal",
|
||||
"literal": literal,
|
||||
},
|
||||
"environment": map[string]interface{}{
|
||||
"name": envName,
|
||||
"namespace": namespace,
|
||||
},
|
||||
"source": map[string]interface{}{},
|
||||
},
|
||||
}}
|
||||
|
||||
if _, err = c.CreatePackage(ctx, pkgObj); err != nil {
|
||||
t.Fatalf("create package: %v", err)
|
||||
}
|
||||
defer func() { _ = c.DeletePackage(ctx, namespace, pkgName) }()
|
||||
|
||||
if _, err = c.GetPackage(ctx, namespace, pkgName); err != nil {
|
||||
t.Fatalf("get package: %v", err)
|
||||
}
|
||||
|
||||
fnObj := &unstructured.Unstructured{Object: map[string]interface{}{
|
||||
"apiVersion": "fission.io/v1",
|
||||
"kind": "Function",
|
||||
"metadata": map[string]interface{}{
|
||||
"name": fnName,
|
||||
"namespace": namespace,
|
||||
},
|
||||
"spec": map[string]interface{}{
|
||||
"environment": map[string]interface{}{
|
||||
"name": envName,
|
||||
"namespace": namespace,
|
||||
},
|
||||
"InvokeStrategy": map[string]interface{}{
|
||||
"ExecutionStrategy": map[string]interface{}{
|
||||
"ExecutorType": "poolmgr",
|
||||
},
|
||||
"StrategyType": "execution",
|
||||
},
|
||||
"package": map[string]interface{}{
|
||||
"packageref": map[string]interface{}{
|
||||
"name": pkgName,
|
||||
"namespace": namespace,
|
||||
},
|
||||
"functionName": "main.main",
|
||||
},
|
||||
},
|
||||
}}
|
||||
|
||||
if _, err = c.CreateFunction(ctx, fnObj); err != nil {
|
||||
t.Fatalf("create function: %v", err)
|
||||
}
|
||||
defer func() { _ = c.DeleteFunction(ctx, namespace, fnName) }()
|
||||
|
||||
if _, err = c.GetFunction(ctx, namespace, fnName); err != nil {
|
||||
t.Fatalf("get function: %v", err)
|
||||
}
|
||||
|
||||
trObj := &unstructured.Unstructured{Object: map[string]interface{}{
|
||||
"apiVersion": "fission.io/v1",
|
||||
"kind": "HTTPTrigger",
|
||||
"metadata": map[string]interface{}{
|
||||
"name": triggerName,
|
||||
"namespace": namespace,
|
||||
},
|
||||
"spec": map[string]interface{}{
|
||||
"relativeurl": urlPath,
|
||||
"methods": []interface{}{"GET"},
|
||||
"functionref": map[string]interface{}{
|
||||
"type": "name",
|
||||
"name": fnName,
|
||||
},
|
||||
"createingress": false,
|
||||
},
|
||||
}}
|
||||
|
||||
if _, err = c.CreateHTTPTrigger(ctx, trObj); err != nil {
|
||||
t.Fatalf("create http trigger: %v", err)
|
||||
}
|
||||
defer func() { _ = c.DeleteHTTPTrigger(ctx, namespace, triggerName) }()
|
||||
|
||||
if _, err = c.GetHTTPTrigger(ctx, namespace, triggerName); err != nil {
|
||||
t.Fatalf("get http trigger: %v", err)
|
||||
}
|
||||
|
||||
gvr := schema.GroupVersionResource{Group: "fission.io", Version: "v1", Resource: "httptriggers"}
|
||||
if err = c.DynClient.Resource(gvr).Namespace(namespace).Delete(ctx, triggerName, metav1.DeleteOptions{}); err != nil {
|
||||
t.Fatalf("delete trigger via dynamic client: %v", err)
|
||||
}
|
||||
if err = c.DeleteHTTPTrigger(ctx, namespace, triggerName); err == nil {
|
||||
t.Fatalf("expected not found error after trigger deletion")
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user