mirror of
https://github.com/DeBrosOfficial/network.git
synced 2026-01-30 09:53:03 +00:00
233 lines
7.2 KiB
Go
233 lines
7.2 KiB
Go
//go:build e2e
|
|
|
|
package deployments_test
|
|
|
|
import (
|
|
"bytes"
|
|
"encoding/json"
|
|
"fmt"
|
|
"io"
|
|
"net/http"
|
|
"os"
|
|
"os/exec"
|
|
"path/filepath"
|
|
"testing"
|
|
"time"
|
|
|
|
"github.com/DeBrosOfficial/network/e2e"
|
|
"github.com/stretchr/testify/assert"
|
|
"github.com/stretchr/testify/require"
|
|
)
|
|
|
|
// TestDeploymentRollback_FullFlow tests the complete rollback workflow:
|
|
// 1. Deploy v1
|
|
// 2. Update to v2
|
|
// 3. Verify v2 content
|
|
// 4. Rollback to v1
|
|
// 5. Verify v1 content is restored
|
|
func TestDeploymentRollback_FullFlow(t *testing.T) {
|
|
env, err := e2e.LoadTestEnv()
|
|
require.NoError(t, err, "Failed to load test environment")
|
|
|
|
deploymentName := fmt.Sprintf("rollback-test-%d", time.Now().Unix())
|
|
tarballPathV1 := filepath.Join("../../testdata/apps/react-app")
|
|
var deploymentID string
|
|
|
|
// Cleanup after test
|
|
defer func() {
|
|
if !env.SkipCleanup && deploymentID != "" {
|
|
e2e.DeleteDeployment(t, env, deploymentID)
|
|
}
|
|
}()
|
|
|
|
t.Run("Deploy v1", func(t *testing.T) {
|
|
deploymentID = e2e.CreateTestDeployment(t, env, deploymentName, tarballPathV1)
|
|
require.NotEmpty(t, deploymentID, "Deployment ID should not be empty")
|
|
t.Logf("Created deployment v1: %s (ID: %s)", deploymentName, deploymentID)
|
|
})
|
|
|
|
t.Run("Verify v1 deployment", func(t *testing.T) {
|
|
deployment := e2e.GetDeployment(t, env, deploymentID)
|
|
|
|
version, ok := deployment["version"].(float64)
|
|
require.True(t, ok, "Version should be a number")
|
|
assert.Equal(t, float64(1), version, "Initial version should be 1")
|
|
|
|
contentCID, ok := deployment["content_cid"].(string)
|
|
require.True(t, ok, "Content CID should be a string")
|
|
assert.NotEmpty(t, contentCID, "Content CID should not be empty")
|
|
|
|
t.Logf("v1 version: %v, CID: %s", version, contentCID)
|
|
})
|
|
|
|
var v1CID string
|
|
t.Run("Save v1 CID", func(t *testing.T) {
|
|
deployment := e2e.GetDeployment(t, env, deploymentID)
|
|
v1CID = deployment["content_cid"].(string)
|
|
t.Logf("Saved v1 CID: %s", v1CID)
|
|
})
|
|
|
|
t.Run("Update to v2", func(t *testing.T) {
|
|
// Update the deployment with the same tarball (simulates a new version)
|
|
updateDeployment(t, env, deploymentName, tarballPathV1)
|
|
|
|
// Wait for update to complete
|
|
time.Sleep(2 * time.Second)
|
|
})
|
|
|
|
t.Run("Verify v2 deployment", func(t *testing.T) {
|
|
deployment := e2e.GetDeployment(t, env, deploymentID)
|
|
|
|
version, ok := deployment["version"].(float64)
|
|
require.True(t, ok, "Version should be a number")
|
|
assert.Equal(t, float64(2), version, "Version should be 2 after update")
|
|
|
|
t.Logf("v2 version: %v", version)
|
|
})
|
|
|
|
t.Run("List deployment versions", func(t *testing.T) {
|
|
versions := listVersions(t, env, deploymentName)
|
|
t.Logf("Available versions: %+v", versions)
|
|
|
|
// Should have at least 2 versions in history
|
|
assert.GreaterOrEqual(t, len(versions), 1, "Should have version history")
|
|
})
|
|
|
|
t.Run("Rollback to v1", func(t *testing.T) {
|
|
rollbackDeployment(t, env, deploymentName, 1)
|
|
|
|
// Wait for rollback to complete
|
|
time.Sleep(2 * time.Second)
|
|
})
|
|
|
|
t.Run("Verify rollback succeeded", func(t *testing.T) {
|
|
deployment := e2e.GetDeployment(t, env, deploymentID)
|
|
|
|
version, ok := deployment["version"].(float64)
|
|
require.True(t, ok, "Version should be a number")
|
|
// Note: Version number increases even on rollback (it's a new deployment version)
|
|
// But the content_cid should be the same as v1
|
|
t.Logf("Post-rollback version: %v", version)
|
|
|
|
contentCID, ok := deployment["content_cid"].(string)
|
|
require.True(t, ok, "Content CID should be a string")
|
|
assert.Equal(t, v1CID, contentCID, "Content CID should match v1 after rollback")
|
|
|
|
t.Logf("Rollback verified - content CID matches v1: %s", contentCID)
|
|
})
|
|
}
|
|
|
|
// updateDeployment updates an existing static deployment
|
|
func updateDeployment(t *testing.T, env *e2e.E2ETestEnv, name, tarballPath string) {
|
|
t.Helper()
|
|
|
|
var fileData []byte
|
|
info, err := os.Stat(tarballPath)
|
|
require.NoError(t, err)
|
|
if info.IsDir() {
|
|
fileData, err = exec.Command("tar", "-czf", "-", "-C", tarballPath, ".").Output()
|
|
require.NoError(t, err)
|
|
} else {
|
|
file, err := os.Open(tarballPath)
|
|
require.NoError(t, err, "Failed to open tarball")
|
|
defer file.Close()
|
|
fileData, _ = io.ReadAll(file)
|
|
}
|
|
|
|
// Create multipart form
|
|
body := &bytes.Buffer{}
|
|
boundary := "----WebKitFormBoundary7MA4YWxkTrZu0gW"
|
|
|
|
// Write name field
|
|
body.WriteString("--" + boundary + "\r\n")
|
|
body.WriteString("Content-Disposition: form-data; name=\"name\"\r\n\r\n")
|
|
body.WriteString(name + "\r\n")
|
|
|
|
// Write tarball file
|
|
body.WriteString("--" + boundary + "\r\n")
|
|
body.WriteString("Content-Disposition: form-data; name=\"tarball\"; filename=\"app.tar.gz\"\r\n")
|
|
body.WriteString("Content-Type: application/gzip\r\n\r\n")
|
|
|
|
body.Write(fileData)
|
|
body.WriteString("\r\n--" + boundary + "--\r\n")
|
|
|
|
req, err := http.NewRequest("POST", env.GatewayURL+"/v1/deployments/static/update", body)
|
|
require.NoError(t, err, "Failed to create request")
|
|
|
|
req.Header.Set("Content-Type", "multipart/form-data; boundary="+boundary)
|
|
req.Header.Set("Authorization", "Bearer "+env.APIKey)
|
|
|
|
resp, err := env.HTTPClient.Do(req)
|
|
require.NoError(t, err, "Failed to execute request")
|
|
defer resp.Body.Close()
|
|
|
|
if resp.StatusCode != http.StatusOK {
|
|
bodyBytes, _ := io.ReadAll(resp.Body)
|
|
t.Fatalf("Update failed with status %d: %s", resp.StatusCode, string(bodyBytes))
|
|
}
|
|
|
|
var result map[string]interface{}
|
|
require.NoError(t, json.NewDecoder(resp.Body).Decode(&result), "Failed to decode response")
|
|
t.Logf("Update response: %+v", result)
|
|
}
|
|
|
|
// listVersions lists available versions for a deployment
|
|
func listVersions(t *testing.T, env *e2e.E2ETestEnv, name string) []map[string]interface{} {
|
|
t.Helper()
|
|
|
|
req, err := http.NewRequest("GET", env.GatewayURL+"/v1/deployments/versions?name="+name, nil)
|
|
require.NoError(t, err, "Failed to create request")
|
|
|
|
req.Header.Set("Authorization", "Bearer "+env.APIKey)
|
|
|
|
resp, err := env.HTTPClient.Do(req)
|
|
require.NoError(t, err, "Failed to execute request")
|
|
defer resp.Body.Close()
|
|
|
|
if resp.StatusCode != http.StatusOK {
|
|
bodyBytes, _ := io.ReadAll(resp.Body)
|
|
t.Logf("List versions returned status %d: %s", resp.StatusCode, string(bodyBytes))
|
|
return nil
|
|
}
|
|
|
|
var result struct {
|
|
Versions []map[string]interface{} `json:"versions"`
|
|
}
|
|
if err := json.NewDecoder(resp.Body).Decode(&result); err != nil {
|
|
t.Logf("Failed to decode versions: %v", err)
|
|
return nil
|
|
}
|
|
|
|
return result.Versions
|
|
}
|
|
|
|
// rollbackDeployment triggers a rollback to a specific version
|
|
func rollbackDeployment(t *testing.T, env *e2e.E2ETestEnv, name string, targetVersion int) {
|
|
t.Helper()
|
|
|
|
reqBody := map[string]interface{}{
|
|
"name": name,
|
|
"version": targetVersion,
|
|
}
|
|
bodyBytes, _ := json.Marshal(reqBody)
|
|
|
|
req, err := http.NewRequest("POST", env.GatewayURL+"/v1/deployments/rollback", bytes.NewBuffer(bodyBytes))
|
|
require.NoError(t, err, "Failed to create request")
|
|
|
|
req.Header.Set("Content-Type", "application/json")
|
|
req.Header.Set("Authorization", "Bearer "+env.APIKey)
|
|
|
|
resp, err := env.HTTPClient.Do(req)
|
|
require.NoError(t, err, "Failed to execute request")
|
|
defer resp.Body.Close()
|
|
|
|
if resp.StatusCode != http.StatusOK {
|
|
bodyBytes, _ := io.ReadAll(resp.Body)
|
|
t.Fatalf("Rollback failed with status %d: %s", resp.StatusCode, string(bodyBytes))
|
|
}
|
|
|
|
var result map[string]interface{}
|
|
require.NoError(t, json.NewDecoder(resp.Body).Decode(&result), "Failed to decode response")
|
|
t.Logf("Rollback response: %+v", result)
|
|
}
|