diff --git a/test/e2e/config_sync_test.go b/test/e2e/config_sync_test.go index 9445872..e4ae1a3 100644 --- a/test/e2e/config_sync_test.go +++ b/test/e2e/config_sync_test.go @@ -3,7 +3,6 @@ package e2e import ( - "encoding/json" "fmt" "os" "path/filepath" @@ -172,13 +171,23 @@ routes: require.NoError(t, err, "stdout=%s stderr=%s", stdout, stderr) assert.Contains(t, stdout, "Sync completed") - stdout, stderr, err = runA7WithEnv(env, "route", "get", routeID, "-g", gatewayGroup, "-o", "json") - require.NoError(t, err, stderr) var route map[string]interface{} - require.NoError(t, json.Unmarshal([]byte(stdout), &route)) + runA7JSON(t, env, &route, "route", "get", routeID, "-g", gatewayGroup, "-o", "json") assert.Equal(t, routeID, route["id"]) assert.Equal(t, routeID, route["name"]) assert.Equal(t, svcID, route["service_id"]) + + dumpFile := filepath.Join(t.TempDir(), "sync-create-dump.yaml") + _, stderr, err = runA7WithEnv(env, "config", "dump", "-g", gatewayGroup, "-f", dumpFile) + require.NoError(t, err, stderr) + dumped, err := os.ReadFile(dumpFile) + require.NoError(t, err) + var dumpedCfg map[string]interface{} + require.NoError(t, yaml.Unmarshal(dumped, &dumpedCfg)) + services := requireJSONArray(t, dumpedCfg["services"], "dump.services") + routes := requireJSONArray(t, dumpedCfg["routes"], "dump.routes") + assert.NotEmpty(t, filterResourcesByID(services, svcID)) + assert.NotEmpty(t, filterResourcesByID(routes, routeID)) } func TestConfigSync_DeleteFalse(t *testing.T) { diff --git a/test/e2e/consumer_test.go b/test/e2e/consumer_test.go index 1d672bf..5f3b6b7 100644 --- a/test/e2e/consumer_test.go +++ b/test/e2e/consumer_test.go @@ -123,9 +123,10 @@ func TestConsumer_CRUD(t *testing.T) { assert.Contains(t, stdout, username) // Get JSON - stdout, stderr, err = runA7WithEnv(env, "consumer", "get", username, "-g", gatewayGroup, "-o", "json") - require.NoError(t, err, stderr) - assert.Contains(t, stdout, username) + var consumer map[string]interface{} + runA7JSON(t, env, &consumer, "consumer", "get", username, "-g", gatewayGroup, "-o", "json") + assert.Equal(t, username, consumer["username"]) + assert.Equal(t, "e2e test consumer", consumer["desc"]) // Update updateJSON := fmt.Sprintf(`{ @@ -137,10 +138,14 @@ func TestConsumer_CRUD(t *testing.T) { stdout, stderr, err = runA7WithEnv(env, "consumer", "update", username, "-f", tmpFile, "-g", gatewayGroup) require.NoError(t, err, stderr) + runA7JSON(t, env, &consumer, "consumer", "get", username, "-g", gatewayGroup, "-o", "json") + assert.Equal(t, "updated consumer", consumer["desc"]) // Delete stdout, stderr, err = runA7WithEnv(env, "consumer", "delete", username, "--force", "-g", gatewayGroup) require.NoError(t, err, stderr) + _, _, err = runA7WithEnv(env, "consumer", "get", username, "-g", gatewayGroup) + assert.Error(t, err) } func TestConsumer_Export(t *testing.T) { @@ -151,9 +156,9 @@ func TestConsumer_Export(t *testing.T) { createTestConsumerViaCLI(t, env, username) // Use get -o json (export is batch-only, cobra.NoArgs). - stdout, stderr, err := runA7WithEnv(env, "consumer", "get", username, "-g", gatewayGroup, "-o", "json") - require.NoError(t, err, stderr) - assert.Contains(t, stdout, username) + var consumer map[string]interface{} + runA7JSON(t, env, &consumer, "consumer", "get", username, "-g", gatewayGroup, "-o", "json") + assert.Equal(t, username, consumer["username"]) } func TestConsumer_WithKeyAuth(t *testing.T) { diff --git a/test/e2e/credential_test.go b/test/e2e/credential_test.go index b568cde..ee98277 100644 --- a/test/e2e/credential_test.go +++ b/test/e2e/credential_test.go @@ -59,7 +59,7 @@ func TestCredential_CRUD(t *testing.T) { stdout, stderr, err := runA7WithEnv(env, "credential", "create", credID, "--consumer", username, "-f", tmpFile, "-g", gatewayGroup) - require.NoError(t, err, "stdout=%s stderr=%s", stdout, stderr) + require.NoError(t, err, "credential create failed") // Get stdout, stderr, err = runA7WithEnv(env, "credential", "get", credID, @@ -68,15 +68,20 @@ func TestCredential_CRUD(t *testing.T) { assert.Contains(t, stdout, credID) // Get JSON - stdout, stderr, err = runA7WithEnv(env, "credential", "get", credID, + var credential map[string]interface{} + runA7JSON(t, env, &credential, "credential", "get", credID, "--consumer", username, "-g", gatewayGroup, "-o", "json") - require.NoError(t, err, stderr) - assert.Contains(t, stdout, "key-auth") + assert.Equal(t, credID, credential["id"]) + plugins := requireJSONObject(t, credential["plugins"], "credential.plugins") + assert.Contains(t, plugins, "key-auth") // Delete credential stdout, stderr, err = runA7WithEnv(env, "credential", "delete", credID, "--consumer", username, "--force", "-g", gatewayGroup) require.NoError(t, err, stderr) + _, _, err = runA7WithEnv(env, "credential", "get", credID, + "--consumer", username, "-g", gatewayGroup) + assert.Error(t, err) } func TestCredential_RequiresConsumerFlag(t *testing.T) { diff --git a/test/e2e/global_rule_test.go b/test/e2e/global_rule_test.go index 4617276..f09cb64 100644 --- a/test/e2e/global_rule_test.go +++ b/test/e2e/global_rule_test.go @@ -6,7 +6,6 @@ import ( "fmt" "os" "path/filepath" - "strings" "testing" "github.com/stretchr/testify/assert" @@ -64,9 +63,11 @@ func TestGlobalRule_CRUD(t *testing.T) { assert.Contains(t, stdout, grID) // Get JSON - stdout, stderr, err = runA7WithEnv(env, "global-rule", "get", grID, "-g", gatewayGroup, "-o", "json") - require.NoError(t, err, stderr) - assert.Contains(t, stdout, "prometheus") + var globalRule map[string]interface{} + runA7JSON(t, env, &globalRule, "global-rule", "get", grID, "-g", gatewayGroup, "-o", "json") + assert.Equal(t, grID, globalRule["id"]) + plugins := requireJSONObject(t, globalRule["plugins"], "global_rule.plugins") + assert.Contains(t, plugins, "prometheus") // Update — API7 EE requires exactly one plugin per global rule. updateJSON := fmt.Sprintf(`{ @@ -82,13 +83,16 @@ func TestGlobalRule_CRUD(t *testing.T) { require.NoError(t, err, stderr) // Export (use get -o json; export is batch-only with cobra.NoArgs) - stdout, stderr, err = runA7WithEnv(env, "global-rule", "get", grID, "-g", gatewayGroup, "-o", "json") - require.NoError(t, err, stderr) - assert.Contains(t, stdout, "prometheus") + runA7JSON(t, env, &globalRule, "global-rule", "get", grID, "-g", gatewayGroup, "-o", "json") + plugins = requireJSONObject(t, globalRule["plugins"], "global_rule.plugins") + prometheus := requireJSONObject(t, plugins["prometheus"], "global_rule.plugins.prometheus") + assert.Equal(t, true, prometheus["prefer_name"]) // Delete stdout, stderr, err = runA7WithEnv(env, "global-rule", "delete", grID, "--force", "-g", gatewayGroup) require.NoError(t, err, stderr) + _, _, err = runA7WithEnv(env, "global-rule", "get", grID, "-g", gatewayGroup) + assert.Error(t, err) } func TestGlobalRule_DeleteNonexistent(t *testing.T) { @@ -122,8 +126,11 @@ func TestGlobalRule_SkillExample(t *testing.T) { require.NoError(t, err, stderr) // Verify - stdout, stderr, err := runA7WithEnv(env, "global-rule", "get", grID, "-g", gatewayGroup, "-o", "json") - require.NoError(t, err, stderr) - assert.Contains(t, stdout, "ip-restriction") - _ = strings.Contains(stdout, "whitelist") // ensure plugin config persisted + var globalRule map[string]interface{} + runA7JSON(t, env, &globalRule, "global-rule", "get", grID, "-g", gatewayGroup, "-o", "json") + assert.Equal(t, grID, globalRule["id"]) + plugins := requireJSONObject(t, globalRule["plugins"], "global_rule.plugins") + ipRestriction := requireJSONObject(t, plugins["ip-restriction"], "global_rule.plugins.ip-restriction") + whitelist := requireJSONArray(t, ipRestriction["whitelist"], "global_rule.plugins.ip-restriction.whitelist") + assert.Contains(t, whitelist, "10.0.0.0/8") } diff --git a/test/e2e/plugin_metadata_test.go b/test/e2e/plugin_metadata_test.go index 4cf8af2..b8b875f 100644 --- a/test/e2e/plugin_metadata_test.go +++ b/test/e2e/plugin_metadata_test.go @@ -54,11 +54,19 @@ func TestPluginMetadata_CRUD(t *testing.T) { assert.Contains(t, stdout, pluginName) // Get JSON - stdout, stderr, err = runA7WithEnv(env, "plugin-metadata", "get", pluginName, "-g", gatewayGroup, "-o", "json") - require.NoError(t, err, stderr) - assert.Contains(t, stdout, "log_format") + var metadata map[string]interface{} + runA7JSON(t, env, &metadata, "plugin-metadata", "get", pluginName, "-g", gatewayGroup, "-o", "json") + logFormatValue := metadata["log_format"] + if logFormatValue == nil { + wrapped := requireJSONObject(t, metadata["metadata"], "plugin_metadata.metadata") + logFormatValue = wrapped["log_format"] + } + logFormat := requireJSONObject(t, logFormatValue, "plugin_metadata.log_format") + assert.Equal(t, "$remote_addr", logFormat["client_ip"]) // Delete stdout, stderr, err = runA7WithEnv(env, "plugin-metadata", "delete", pluginName, "--force", "-g", gatewayGroup) require.NoError(t, err, stderr) + _, _, err = runA7WithEnv(env, "plugin-metadata", "get", pluginName, "-g", gatewayGroup) + assert.Error(t, err) } diff --git a/test/e2e/proto_test.go b/test/e2e/proto_test.go index 27a6941..ee5e191 100644 --- a/test/e2e/proto_test.go +++ b/test/e2e/proto_test.go @@ -61,18 +61,24 @@ func TestProto_CRUD(t *testing.T) { assert.Contains(t, stdout, protoID) // Get JSON - stdout, stderr, err = runA7WithEnv(env, "proto", "get", protoID, "-g", gatewayGroup, "-o", "json") - require.NoError(t, err, stderr) - assert.Contains(t, stdout, "helloworld") + var proto map[string]interface{} + runA7JSON(t, env, &proto, "proto", "get", protoID, "-g", gatewayGroup, "-o", "json") + assert.Equal(t, protoID, proto["id"]) + content, ok := proto["content"].(string) + require.True(t, ok, "proto.content should be a string") + assert.Contains(t, content, "helloworld") // Export (use get -o json; export is batch-only with cobra.NoArgs) - stdout, stderr, err = runA7WithEnv(env, "proto", "get", protoID, "-g", gatewayGroup, "-o", "json") - require.NoError(t, err, stderr) - assert.Contains(t, stdout, "helloworld") + runA7JSON(t, env, &proto, "proto", "get", protoID, "-g", gatewayGroup, "-o", "json") + content, ok = proto["content"].(string) + require.True(t, ok, "proto.content should be a string") + assert.Contains(t, content, "helloworld") // Delete stdout, stderr, err = runA7WithEnv(env, "proto", "delete", protoID, "--force", "-g", gatewayGroup) require.NoError(t, err, stderr) + _, _, err = runA7WithEnv(env, "proto", "get", protoID, "-g", gatewayGroup) + assert.Error(t, err) } func TestProto_DeleteNonexistent(t *testing.T) { diff --git a/test/e2e/route_test.go b/test/e2e/route_test.go index cddb5da..752afad 100644 --- a/test/e2e/route_test.go +++ b/test/e2e/route_test.go @@ -3,7 +3,6 @@ package e2e import ( - "encoding/json" "fmt" "io" "net/http" @@ -91,9 +90,11 @@ func TestRoute_CRUD(t *testing.T) { assert.Contains(t, stdout, routeID) // Get JSON - stdout, stderr, err = runA7WithEnv(env, "route", "get", routeID, "-g", gatewayGroup, "-o", "json") - require.NoError(t, err, stderr) - assert.Contains(t, stdout, routeID) + var route map[string]interface{} + runA7JSON(t, env, &route, "route", "get", routeID, "-g", gatewayGroup, "-o", "json") + assert.Equal(t, routeID, route["id"]) + assert.Equal(t, "e2e-route-crud", route["name"]) + assert.Equal(t, svcID, route["service_id"]) // Update via file updateJSON := fmt.Sprintf(`{ @@ -109,13 +110,17 @@ func TestRoute_CRUD(t *testing.T) { require.NoError(t, err, stderr) // Verify update - stdout, stderr, err = runA7WithEnv(env, "route", "get", routeID, "-g", gatewayGroup, "-o", "json") - require.NoError(t, err, stderr) - assert.Contains(t, stdout, "/test-updated") + runA7JSON(t, env, &route, "route", "get", routeID, "-g", gatewayGroup, "-o", "json") + assert.Equal(t, "e2e-route-crud-updated", route["name"]) + assert.Equal(t, svcID, route["service_id"]) + paths := requireJSONArray(t, route["paths"], "route.paths") + assert.Contains(t, paths, "/test-updated") // Delete stdout, stderr, err = runA7WithEnv(env, "route", "delete", routeID, "--force", "-g", gatewayGroup) require.NoError(t, err, stderr) + _, _, err = runA7WithEnv(env, "route", "get", routeID, "-g", gatewayGroup) + assert.Error(t, err) } func TestRoute_CreateWithFlags(t *testing.T) { @@ -145,9 +150,16 @@ func TestRoute_CreateWithFlags(t *testing.T) { require.NoError(t, err, "stdout=%s stderr=%s", stdout, stderr) // Verify - stdout, stderr, err = runA7WithEnv(env, "route", "get", routeID, "-g", gatewayGroup, "-o", "json") - require.NoError(t, err, stderr) - assert.Contains(t, stdout, "flagged-route") + var route map[string]interface{} + runA7JSON(t, env, &route, "route", "get", routeID, "-g", gatewayGroup, "-o", "json") + assert.Equal(t, routeID, route["id"]) + assert.Equal(t, "flagged-route", route["name"]) + assert.Equal(t, svcID, route["service_id"]) + methods := requireJSONArray(t, route["methods"], "route.methods") + assert.Contains(t, methods, "GET") + labels := requireJSONObject(t, route["labels"], "route.labels") + assert.Equal(t, "test", labels["env"]) + assert.Equal(t, "e2e", labels["team"]) } func TestRoute_CreateWithPlugins(t *testing.T) { @@ -179,9 +191,12 @@ func TestRoute_CreateWithPlugins(t *testing.T) { require.NoError(t, err, "stdout=%s stderr=%s", stdout, stderr) // Verify plugin - stdout, stderr, err = runA7WithEnv(env, "route", "get", routeID, "-g", gatewayGroup, "-o", "json") - require.NoError(t, err, stderr) - assert.Contains(t, stdout, "proxy-rewrite") + var route map[string]interface{} + runA7JSON(t, env, &route, "route", "get", routeID, "-g", gatewayGroup, "-o", "json") + assert.Equal(t, routeID, route["id"]) + assert.Equal(t, svcID, route["service_id"]) + plugins := requireJSONObject(t, route["plugins"], "route.plugins") + assert.Contains(t, plugins, "proxy-rewrite") } func TestRoute_Export(t *testing.T) { @@ -207,11 +222,9 @@ func TestRoute_Export(t *testing.T) { require.NoError(t, err, "stdout=%s stderr=%s", stdout, stderr) // Use 'get -o json' to export a single route (export is batch, no positional ID). - stdout, stderr, err = runA7WithEnv(env, "route", "get", routeID, "-g", gatewayGroup, "-o", "json") - require.NoError(t, err, stderr) - var exported map[string]interface{} - require.NoError(t, json.Unmarshal([]byte(stdout), &exported), "should be valid JSON") + runA7JSON(t, env, &exported, "route", "get", routeID, "-g", gatewayGroup, "-o", "json") + assert.Equal(t, routeID, exported["id"]) } func TestRoute_ExportYAML(t *testing.T) { diff --git a/test/e2e/secret_test.go b/test/e2e/secret_test.go index 34700fa..492ce3c 100644 --- a/test/e2e/secret_test.go +++ b/test/e2e/secret_test.go @@ -66,7 +66,7 @@ func TestSecret_CRUD(t *testing.T) { // Create stdout, stderr, err := runA7WithEnv(env, "secret", "create", secretID, "-f", tmpFile, "-g", gatewayGroup) if err != nil { - t.Skipf("secret create failed (vault may not be configured): %s %s", stdout, stderr) + t.Skip("secret create failed (vault may not be configured)") } // Get @@ -75,13 +75,32 @@ func TestSecret_CRUD(t *testing.T) { assert.Contains(t, stdout, "vault") // Get JSON - stdout, stderr, err = runA7WithEnv(env, "secret", "get", secretID, "-g", gatewayGroup, "-o", "json") - require.NoError(t, err, stderr) - assert.Contains(t, stdout, "vault.example.com") + var secret map[string]interface{} + runA7JSON(t, env, &secret, "secret", "get", secretID, "-g", gatewayGroup, "-o", "json") + assert.Equal(t, secretID, secret["id"]) + assert.Equal(t, "https://vault.example.com", secret["uri"]) + assert.Equal(t, "kv/apisix", secret["prefix"]) + + // Update and verify readback. + updateJSON := `{ + "uri": "https://vault-updated.example.com", + "prefix": "kv/apisix-updated", + "token": "updated-vault-token" + }` + updateFile := filepath.Join(t.TempDir(), "secret-update.json") + require.NoError(t, os.WriteFile(updateFile, []byte(updateJSON), 0644)) + stdout, stderr, err = runA7WithEnv(env, "secret", "update", secretID, "-f", updateFile, "-g", gatewayGroup) + require.NoError(t, err, "secret update failed") + + runA7JSON(t, env, &secret, "secret", "get", secretID, "-g", gatewayGroup, "-o", "json") + assert.Equal(t, "https://vault-updated.example.com", secret["uri"]) + assert.Equal(t, "kv/apisix-updated", secret["prefix"]) // Delete stdout, stderr, err = runA7WithEnv(env, "secret", "delete", secretID, "--force", "-g", gatewayGroup) require.NoError(t, err, stderr) + _, _, err = runA7WithEnv(env, "secret", "get", secretID, "-g", gatewayGroup) + assert.Error(t, err) } func TestSecret_DeleteNonexistent(t *testing.T) { diff --git a/test/e2e/service_template_test.go b/test/e2e/service_template_test.go index 23a9b45..bf838d0 100644 --- a/test/e2e/service_template_test.go +++ b/test/e2e/service_template_test.go @@ -117,9 +117,10 @@ func TestServiceTemplate_CRUD(t *testing.T) { assert.Contains(t, stdout, stName) // Get JSON - stdout, stderr, err = runA7WithEnv(env, "service-template", "get", stID, "-o", "json") - require.NoError(t, err, stderr) - assert.Contains(t, stdout, stName) + var template map[string]interface{} + runA7JSON(t, env, &template, "service-template", "get", stID, "-o", "json") + assert.Equal(t, stID, fmt.Sprint(template["id"])) + assert.Equal(t, stName, template["name"]) // Update via file updateJSON := `{ @@ -139,13 +140,14 @@ func TestServiceTemplate_CRUD(t *testing.T) { require.NoError(t, err, stderr) // Verify update - stdout, stderr, err = runA7WithEnv(env, "service-template", "get", stID, "-o", "json") - require.NoError(t, err, stderr) - assert.Contains(t, stdout, "e2e-template-updated") + runA7JSON(t, env, &template, "service-template", "get", stID, "-o", "json") + assert.Equal(t, "e2e-template-updated", template["name"]) // Delete stdout, stderr, err = runA7WithEnv(env, "service-template", "delete", stID, "--force") require.NoError(t, err, stderr) + _, _, err = runA7WithEnv(env, "service-template", "get", stID) + assert.Error(t, err) } func TestServiceTemplate_CreateWithName(t *testing.T) { diff --git a/test/e2e/service_test.go b/test/e2e/service_test.go index 0eb5a5e..f586c9f 100644 --- a/test/e2e/service_test.go +++ b/test/e2e/service_test.go @@ -85,9 +85,10 @@ func TestService_CRUD(t *testing.T) { assert.Contains(t, stdout, svcID) // Get JSON - stdout, stderr, err = runA7WithEnv(env, "service", "get", svcID, "-g", gatewayGroup, "-o", "json") - require.NoError(t, err, stderr) - assert.Contains(t, stdout, svcID) + var service map[string]interface{} + runA7JSON(t, env, &service, "service", "get", svcID, "-g", gatewayGroup, "-o", "json") + assert.Equal(t, svcID, service["id"]) + assert.Equal(t, "e2e-svc-"+svcID, service["name"]) // Update updateJSON := fmt.Sprintf(`{ @@ -105,13 +106,14 @@ func TestService_CRUD(t *testing.T) { require.NoError(t, err, stderr) // Verify update - stdout, stderr, err = runA7WithEnv(env, "service", "get", svcID, "-g", gatewayGroup, "-o", "json") - require.NoError(t, err, stderr) - assert.Contains(t, stdout, "e2e-svc-updated") + runA7JSON(t, env, &service, "service", "get", svcID, "-g", gatewayGroup, "-o", "json") + assert.Equal(t, "e2e-svc-updated", service["name"]) // Delete stdout, stderr, err = runA7WithEnv(env, "service", "delete", svcID, "--force", "-g", gatewayGroup) require.NoError(t, err, stderr) + _, _, err = runA7WithEnv(env, "service", "get", svcID, "-g", gatewayGroup) + assert.Error(t, err) } func TestService_Export(t *testing.T) { @@ -122,9 +124,9 @@ func TestService_Export(t *testing.T) { createTestServiceViaCLI(t, env, svcID) // export is batch-only (cobra.NoArgs); use "get -o json" for single-resource export. - stdout, stderr, err := runA7WithEnv(env, "service", "get", svcID, "-g", gatewayGroup, "-o", "json") - require.NoError(t, err, stderr) - assert.Contains(t, stdout, svcID) + var service map[string]interface{} + runA7JSON(t, env, &service, "service", "get", svcID, "-g", gatewayGroup, "-o", "json") + assert.Equal(t, svcID, service["id"]) } func TestService_WithPlugins(t *testing.T) { @@ -152,9 +154,11 @@ func TestService_WithPlugins(t *testing.T) { _, stderr, err := runA7WithEnv(env, "service", "create", "-f", tmpFile, "-g", gatewayGroup) require.NoError(t, err, stderr) - stdout, stderr, err := runA7WithEnv(env, "service", "get", svcID, "-g", gatewayGroup, "-o", "json") - require.NoError(t, err, stderr) - assert.Contains(t, stdout, "proxy-rewrite") + var service map[string]interface{} + runA7JSON(t, env, &service, "service", "get", svcID, "-g", gatewayGroup, "-o", "json") + assert.Equal(t, svcID, service["id"]) + plugins := requireJSONObject(t, service["plugins"], "service.plugins") + assert.Contains(t, plugins, "proxy-rewrite") } func TestService_RouteWithServiceID(t *testing.T) { @@ -180,7 +184,8 @@ func TestService_RouteWithServiceID(t *testing.T) { _, stderr, err := runA7WithEnv(env, "route", "create", "-f", tmpFile, "-g", gatewayGroup) require.NoError(t, err, stderr) - stdout, stderr, err := runA7WithEnv(env, "route", "get", routeID, "-g", gatewayGroup, "-o", "json") - require.NoError(t, err, stderr) - assert.Contains(t, stdout, svcID) + var route map[string]interface{} + runA7JSON(t, env, &route, "route", "get", routeID, "-g", gatewayGroup, "-o", "json") + assert.Equal(t, routeID, route["id"]) + assert.Equal(t, svcID, route["service_id"]) } diff --git a/test/e2e/setup_test.go b/test/e2e/setup_test.go index 1f4376d..bc5fbd8 100644 --- a/test/e2e/setup_test.go +++ b/test/e2e/setup_test.go @@ -28,6 +28,7 @@ import ( "os" "os/exec" "path/filepath" + "reflect" "strings" "testing" "time" @@ -179,6 +180,35 @@ func runA7WithEnv(env []string, args ...string) (string, string, error) { return stdout.String(), stderr.String(), err } +// runA7JSON executes a7 and decodes stdout as JSON. Callers should pass +// command arguments that already request JSON output, usually with "-o json". +func runA7JSON(t testTB, env []string, out interface{}, args ...string) string { + t.Helper() + stdout, _, err := runA7WithEnv(env, args...) + require.NoError(t, err, "a7 command failed: args=%v", args) + + value := reflect.ValueOf(out) + require.True(t, value.Kind() == reflect.Ptr && !value.IsNil(), "out must be a non-nil pointer") + value.Elem().Set(reflect.Zero(value.Elem().Type())) + + require.NoError(t, json.Unmarshal([]byte(stdout), out), "a7 returned non-JSON output: args=%v", args) + return stdout +} + +func requireJSONObject(t testTB, value interface{}, name string) map[string]interface{} { + t.Helper() + object, ok := value.(map[string]interface{}) + require.True(t, ok, "%s should be a JSON object", name) + return object +} + +func requireJSONArray(t testTB, value interface{}, name string) []interface{} { + t.Helper() + array, ok := value.([]interface{}) + require.True(t, ok, "%s should be a JSON array", name) + return array +} + // adminAPI sends an HTTP request to the API7 EE Dashboard API. // Used for test setup and cleanup — not for testing the CLI itself. // Uses insecureClient because API7 EE typically uses self-signed certs. diff --git a/test/e2e/ssl_test.go b/test/e2e/ssl_test.go index 833046e..0e6e61a 100644 --- a/test/e2e/ssl_test.go +++ b/test/e2e/ssl_test.go @@ -69,7 +69,7 @@ func TestSSL_CRUD(t *testing.T) { require.NoError(t, os.WriteFile(tmpFile, []byte(sslJSON), 0644)) stdout, stderr, err := runA7WithEnv(env, "ssl", "create", "-f", tmpFile, "-g", gatewayGroup) - require.NoError(t, err, "stdout=%s stderr=%s", stdout, stderr) + require.NoError(t, err, "ssl create failed") // Get stdout, stderr, err = runA7WithEnv(env, "ssl", "get", sslID, "-g", gatewayGroup) @@ -77,18 +77,22 @@ func TestSSL_CRUD(t *testing.T) { assert.Contains(t, stdout, sslID) // Get JSON - stdout, stderr, err = runA7WithEnv(env, "ssl", "get", sslID, "-g", gatewayGroup, "-o", "json") - require.NoError(t, err, stderr) - assert.Contains(t, stdout, "e2e-test.example.com") + var ssl map[string]interface{} + runA7JSON(t, env, &ssl, "ssl", "get", sslID, "-g", gatewayGroup, "-o", "json") + assert.Equal(t, sslID, ssl["id"]) + snis := requireJSONArray(t, ssl["snis"], "ssl.snis") + assert.Contains(t, snis, "e2e-test.example.com") // Export (use get -o json; export is batch-only with cobra.NoArgs) - stdout, stderr, err = runA7WithEnv(env, "ssl", "get", sslID, "-g", gatewayGroup, "-o", "json") - require.NoError(t, err, stderr) - assert.Contains(t, stdout, "e2e-test.example.com") + runA7JSON(t, env, &ssl, "ssl", "get", sslID, "-g", gatewayGroup, "-o", "json") + snis = requireJSONArray(t, ssl["snis"], "ssl.snis") + assert.Contains(t, snis, "e2e-test.example.com") // Delete stdout, stderr, err = runA7WithEnv(env, "ssl", "delete", sslID, "--force", "-g", gatewayGroup) require.NoError(t, err, stderr) + _, _, err = runA7WithEnv(env, "ssl", "get", sslID, "-g", gatewayGroup) + assert.Error(t, err) } func TestSSL_DeleteNonexistent(t *testing.T) { diff --git a/test/e2e/stream_route_test.go b/test/e2e/stream_route_test.go index 10ee147..45cd57a 100644 --- a/test/e2e/stream_route_test.go +++ b/test/e2e/stream_route_test.go @@ -87,19 +87,34 @@ func TestStreamRoute_CRUD(t *testing.T) { assert.Contains(t, stdout, srID) // Get JSON - stdout, stderr, err = runA7WithEnv(env, "stream-route", "get", srID, "-g", gatewayGroup, "-o", "json") - require.NoError(t, err, stderr) - assert.Contains(t, stdout, "19090") - assert.Contains(t, stdout, "stream route e2e") + var streamRoute map[string]interface{} + runA7JSON(t, env, &streamRoute, "stream-route", "get", srID, "-g", gatewayGroup, "-o", "json") + assert.Equal(t, srID, streamRoute["id"]) + assert.Equal(t, float64(19090), streamRoute["server_port"]) + assert.Equal(t, "stream route e2e", streamRoute["desc"]) + + // Update and verify readback. + updateJSON := fmt.Sprintf(`{ + "id": %q, + "name": "e2e-stream-route-updated", + "service_id": %q, + "server_port": 19091, + "desc": "stream route e2e updated" + }`, srID, svcID) + updateFile := filepath.Join(t.TempDir(), "stream-route-update.json") + require.NoError(t, os.WriteFile(updateFile, []byte(updateJSON), 0644)) + stdout, stderr, err = runA7WithEnv(env, "stream-route", "update", srID, "-f", updateFile, "-g", gatewayGroup) + require.NoError(t, err, "stdout=%s stderr=%s", stdout, stderr) - // Export (use get -o json; export is batch-only with cobra.NoArgs) - stdout, stderr, err = runA7WithEnv(env, "stream-route", "get", srID, "-g", gatewayGroup, "-o", "json") - require.NoError(t, err, stderr) - assert.Contains(t, stdout, "19090") + runA7JSON(t, env, &streamRoute, "stream-route", "get", srID, "-g", gatewayGroup, "-o", "json") + assert.Equal(t, float64(19091), streamRoute["server_port"]) + assert.Equal(t, "stream route e2e updated", streamRoute["desc"]) // Delete stdout, stderr, err = runA7WithEnv(env, "stream-route", "delete", srID, "--force", "-g", gatewayGroup) require.NoError(t, err, stderr) + _, _, err = runA7WithEnv(env, "stream-route", "get", srID, "-g", gatewayGroup) + assert.Error(t, err) } func TestStreamRoute_DeleteNonexistent(t *testing.T) {