Skip to content
Merged
Show file tree
Hide file tree
Changes from all 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
8 changes: 4 additions & 4 deletions PRD.md
Original file line number Diff line number Diff line change
Expand Up @@ -152,7 +152,7 @@ All runtime commands require `--gateway-group <id>` (or default from context).
- `a7 stream-route list|get|create|update|delete|export --gateway-group <id>`

#### Plugin Config
> **⚠️ NOT SUPPORTED**: Plugin configs are not exposed via the API7 EE Admin API. The `a7 plugin-config` commands exist for APISIX compatibility but will not work against API7 EE.
> **⚠️ NOT SUPPORTED**: Plugin configs are not exposed via the API7 EE Admin API, so a7 does not expose plugin-config commands.

#### Plugin Metadata
- `a7 plugin-metadata get|create|update|delete --gateway-group <id>` (no list — keyed by plugin name)
Expand Down Expand Up @@ -207,7 +207,7 @@ All runtime commands require `--gateway-group <id>` (or default from context).

### Phase 3 — CLI Usability ✅ COMPLETE
1. ✅ `-f/--file` flag: file-based create/update for all resource commands.
2. ✅ `export` subcommand for all applicable resources (route, service, consumer, ssl, global-rule, stream-route, plugin-config, proto).
2. ✅ `export` subcommand for all applicable resources (route, service, consumer, ssl, global-rule, stream-route, proto).
3. ✅ `--force` flag for delete commands (skip confirmation).
4. ✅ `--label` flag for list/export commands (label-based filtering).
5. 🔲 `--dry-run` flag for create/update commands.
Expand All @@ -229,7 +229,7 @@ All runtime commands require `--gateway-group <id>` (or default from context).
6. ✅ `docs/documentation-maintenance.md` — Doc update rules and templates.
7. ✅ `docs/roadmap.md` — Per-PR development plan for Phases 5-9.
8. ✅ `docs/api7ee-api-spec.md` — API7 EE Admin API reference (16 resources, dual-API).
9. ✅ `docs/user-guide/` — per-resource user guides (getting-started, configuration, route, service, upstream, consumer, ssl, plugin, global-rule, stream-route, plugin-config, plugin-metadata, credential, secret, proto, declarative-config, gateway-group, debug, bulk-operations).
9. ✅ `docs/user-guide/` — per-resource user guides (getting-started, configuration, route, service, upstream, consumer, ssl, plugin, global-rule, stream-route, plugin-metadata, credential, secret, proto, declarative-config, gateway-group, debug, bulk-operations).

### Phase 6 — AI Agent Skills ✅ COMPLETE
Port and adapt 40 SKILL.md files from a6, organized by category:
Expand All @@ -255,7 +255,7 @@ Port and adapt 40 SKILL.md files from a6, organized by category:
### Phase 8 — End-to-End Tests ✅ COMPLETE
1. ✅ `test/e2e/docker-compose.yml` — Docker Compose for API7 EE (Dashboard + DP Manager + Gateway + PostgreSQL).
2. ✅ `test/e2e/setup_test.go` — TestMain, binary build, admin/control API helpers, shared test utilities.
3. ✅ Per-resource E2E tests: route, service, consumer, ssl, plugin, global-rule, stream-route, plugin-config, plugin-metadata, credential, secret, proto, context, gateway-group.
3. ✅ Per-resource E2E tests: route, service, consumer, ssl, plugin, global-rule, stream-route, plugin-metadata, credential, secret, proto, context, gateway-group.
4. ✅ Declarative config E2E tests: dump, diff, sync, validate (config_test.go + config_sync_test.go).
5. ✅ Export and label E2E tests (integrated into resource test files).
6. ✅ Debug E2E tests: trace (JSON/method/headers/host/path) + logs (file mode).
Expand Down
4 changes: 2 additions & 2 deletions docs/ga-test-plan.md
Original file line number Diff line number Diff line change
Expand Up @@ -141,7 +141,7 @@ rejected — not present as broken commands.
| `a7 upstream ...` | command does not exist (unknown command error) |
| `a7 consumer-group ...` | command does not exist |
| `a7 service-template ...` | command does not exist |
| `a7 plugin-config ...` | **after Task #2**: command does not exist |
| `a7 plugin-config ...` | command does not exist |
| `a7 stream-route ...` | **works** — full CRUD (verified exposed by the control plane) |

Declarative config — these top-level sections must be **rejected with a clear error**:
Expand All @@ -150,7 +150,7 @@ Declarative config — these top-level sections must be **rejected with a clear
upstreams: [...] # -> validation error
consumer_groups: [...] # -> validation error
service_templates: [...] # -> validation error
plugin_configs: [...] # -> validation error (after Task #2)
plugin_configs: [...] # -> validation error
```

> Caveat: the control plane still accepts `plugin_configs` *inside batch config-validation
Expand Down
7 changes: 4 additions & 3 deletions pkg/api/types_config.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,10 +10,11 @@ type ConfigFile struct {
Consumers []Consumer `json:"consumers,omitempty" yaml:"consumers,omitempty"`
SSL []SSL `json:"ssl,omitempty" yaml:"ssl,omitempty"`
GlobalRules []GlobalRule `json:"global_rules,omitempty" yaml:"global_rules,omitempty"`
PluginConfigs []PluginConfig `json:"plugin_configs,omitempty" yaml:"plugin_configs,omitempty"`
ConsumerGroups []ConsumerGroup `json:"consumer_groups,omitempty" yaml:"consumer_groups,omitempty"`
// ServiceTemplates is captured only so the section can be explicitly
// rejected; API7 EE does not support it as a top-level resource.
// PluginConfigs and ServiceTemplates are captured only so the sections
// can be explicitly rejected; API7 EE does not expose them as top-level
// resources.
PluginConfigs []interface{} `json:"plugin_configs,omitempty" yaml:"plugin_configs,omitempty"`
ServiceTemplates []interface{} `json:"service_templates,omitempty" yaml:"service_templates,omitempty"`
StreamRoutes []StreamRoute `json:"stream_routes,omitempty" yaml:"stream_routes,omitempty"`
Protos []Proto `json:"protos,omitempty" yaml:"protos,omitempty"`
Expand Down
10 changes: 0 additions & 10 deletions pkg/api/types_plugin_config.go

This file was deleted.

20 changes: 7 additions & 13 deletions pkg/cmd/config/configutil/configutil.go
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,6 @@ type DiffResult struct {
Consumers ResourceDiff `json:"consumers"`
SSL ResourceDiff `json:"ssl"`
GlobalRules ResourceDiff `json:"global_rules"`
PluginConfigs ResourceDiff `json:"plugin_configs"`
StreamRoutes ResourceDiff `json:"stream_routes"`
Protos ResourceDiff `json:"protos"`
Secrets ResourceDiff `json:"secrets"`
Expand Down Expand Up @@ -73,7 +72,6 @@ func (r *DiffResult) Sections() []DiffSection {
return []DiffSection{
{Name: "services", Diff: r.Services},
{Name: "consumers", Diff: r.Consumers},
{Name: "plugin_configs", Diff: r.PluginConfigs},
{Name: "ssl", Diff: r.SSL},
{Name: "global_rules", Diff: r.GlobalRules},
{Name: "protos", Diff: r.Protos},
Expand Down Expand Up @@ -136,10 +134,6 @@ func FetchRemoteConfig(client *api.Client, gatewayGroup string) (*api.ConfigFile
if err != nil {
return nil, err
}
pluginConfigs, err := fetchPaginated[api.PluginConfig](client, "/apisix/admin/plugin_configs", query)
if err != nil {
return nil, err
}
streamRoutes, err := fetchPaginated[api.StreamRoute](client, "/apisix/admin/stream_routes", query)
if err != nil {
return nil, err
Expand All @@ -165,7 +159,6 @@ func FetchRemoteConfig(client *api.Client, gatewayGroup string) (*api.ConfigFile
Consumers: stripTimestampsFromSlice(consumers),
SSL: stripTimestampsFromSlice(ssl),
GlobalRules: stripTimestampsFromSlice(globalRules),
PluginConfigs: stripTimestampsFromSlice(pluginConfigs),
StreamRoutes: stripTimestampsFromSlice(streamRoutes),
Protos: stripTimestampsFromSlice(protos),
Secrets: stripTimestampsFromSlice(secrets),
Expand Down Expand Up @@ -196,7 +189,6 @@ func ComputeDiff(local, remote api.ConfigFile) (*DiffResult, error) {
{local.Consumers, remote.Consumers, "username", "consumers"},
{local.SSL, remote.SSL, "id", "ssl"},
{local.GlobalRules, remote.GlobalRules, "id", "global_rules"},
{local.PluginConfigs, remote.PluginConfigs, "id", "plugin_configs"},
{local.StreamRoutes, remote.StreamRoutes, "id", "stream_routes"},
{local.Protos, remote.Protos, "id", "protos"},
{local.Secrets, remote.Secrets, "id", "secrets"},
Expand Down Expand Up @@ -226,11 +218,10 @@ func ComputeDiff(local, remote api.ConfigFile) (*DiffResult, error) {
Consumers: diffs[2],
SSL: diffs[3],
GlobalRules: diffs[4],
PluginConfigs: diffs[5],
StreamRoutes: diffs[6],
Protos: diffs[7],
Secrets: diffs[8],
PluginMetadata: diffs[9],
StreamRoutes: diffs[5],
Protos: diffs[6],
Secrets: diffs[7],
PluginMetadata: diffs[8],
}, nil
}

Expand All @@ -246,6 +237,9 @@ func ValidateSupportedSections(cfg api.ConfigFile) error {
if cfg.ConsumerGroups != nil {
unsupported = append(unsupported, "consumer_groups")
}
if cfg.PluginConfigs != nil {
unsupported = append(unsupported, "plugin_configs")
}
if cfg.ServiceTemplates != nil {
unsupported = append(unsupported, "service_templates")
}
Expand Down
1 change: 0 additions & 1 deletion pkg/cmd/config/diff/diff_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,6 @@ func registerEmptyResources(reg *httpmock.Registry, skip map[string]bool) {
"/apisix/admin/consumers",
"/apisix/admin/ssls",
"/apisix/admin/global_rules",
"/apisix/admin/plugin_configs",
"/apisix/admin/stream_routes",
"/apisix/admin/protos",
"/apisix/admin/secret_providers",
Expand Down
1 change: 0 additions & 1 deletion pkg/cmd/config/dump/dump_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,6 @@ func registerEmptyResources(reg *httpmock.Registry, skip map[string]bool) {
"/apisix/admin/consumers",
"/apisix/admin/ssls",
"/apisix/admin/global_rules",
"/apisix/admin/plugin_configs",
"/apisix/admin/stream_routes",
"/apisix/admin/protos",
"/apisix/admin/secret_providers",
Expand Down
4 changes: 0 additions & 4 deletions pkg/cmd/config/sync/sync.go
Original file line number Diff line number Diff line change
Expand Up @@ -212,8 +212,6 @@ func putPathAndBody(resourceType, key string, payload map[string]interface{}) (s
return fmt.Sprintf("/apisix/admin/ssls/%s", key), payload, nil
case "global_rules":
return fmt.Sprintf("/apisix/admin/global_rules/%s", key), payload, nil
case "plugin_configs":
return fmt.Sprintf("/apisix/admin/plugin_configs/%s", key), payload, nil
case "stream_routes":
return fmt.Sprintf("/apisix/admin/stream_routes/%s", key), payload, nil
case "protos":
Expand All @@ -240,8 +238,6 @@ func deletePath(resourceType, key string) (string, error) {
return fmt.Sprintf("/apisix/admin/ssls/%s", key), nil
case "global_rules":
return fmt.Sprintf("/apisix/admin/global_rules/%s", key), nil
case "plugin_configs":
return fmt.Sprintf("/apisix/admin/plugin_configs/%s", key), nil
case "stream_routes":
return fmt.Sprintf("/apisix/admin/stream_routes/%s", key), nil
case "protos":
Expand Down
1 change: 0 additions & 1 deletion pkg/cmd/config/sync/sync_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,6 @@ func registerEmptyResources(reg *httpmock.Registry, skip map[string]bool) {
"/apisix/admin/consumers",
"/apisix/admin/ssls",
"/apisix/admin/global_rules",
"/apisix/admin/plugin_configs",
"/apisix/admin/stream_routes",
"/apisix/admin/protos",
"/apisix/admin/secret_providers",
Expand Down
4 changes: 3 additions & 1 deletion pkg/cmd/config/validate/validate.go
Original file line number Diff line number Diff line change
Expand Up @@ -107,6 +107,9 @@ func ValidateConfigFile(cfg api.ConfigFile) []string {
if cfg.ConsumerGroups != nil {
errs = append(errs, "consumer_groups are not supported by current API7 EE")
}
if cfg.PluginConfigs != nil {
errs = append(errs, "plugin_configs are not supported by current API7 EE")
}
if cfg.ServiceTemplates != nil {
errs = append(errs, "service_templates are not supported by current API7 EE")
}
Expand Down Expand Up @@ -161,7 +164,6 @@ func ValidateConfigFile(cfg api.ConfigFile) []string {

errs = append(errs, checkDuplicateIDs(cfg.SSL, func(s api.SSL) string { return s.ID }, "ssl")...)
errs = append(errs, checkDuplicateIDs(cfg.GlobalRules, func(g api.GlobalRule) string { return g.ID }, "global_rules")...)
errs = append(errs, checkDuplicateIDs(cfg.PluginConfigs, func(p api.PluginConfig) string { return p.ID }, "plugin_configs")...)
for i, item := range cfg.StreamRoutes {
if strings.TrimSpace(item.ServiceID) == "" {
errs = append(errs, fmt.Sprintf("stream_routes[%d]: service_id is required by API7 EE", i))
Expand Down
5 changes: 5 additions & 0 deletions pkg/cmd/config/validate/validate_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -307,6 +307,11 @@ func TestConfigValidate_EmptyUnsupportedSections(t *testing.T) {
body: "version: \"1\"\nconsumer_groups: []\n",
wantErr: "consumer_groups are not supported",
},
{
name: "plugin_configs",
body: "version: \"1\"\nplugin_configs: []\n",
wantErr: "plugin_configs are not supported",
},
{
name: "service_templates",
body: "version: \"1\"\nservice_templates: []\n",
Expand Down
141 changes: 0 additions & 141 deletions pkg/cmd/plugin-config/create/create.go

This file was deleted.

Loading
Loading