Skip to content
Merged
Show file tree
Hide file tree
Changes from 1 commit
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
39 changes: 39 additions & 0 deletions server/internal/resource/migrations/1_1_0.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
package migrations

import (
"github.com/pgEdge/control-plane/server/internal/ds"
"github.com/pgEdge/control-plane/server/internal/resource"
)

var _ resource.StateMigration = (*Version_1_1_0)(nil)

// Version_1_1_0 removes swarm.service_user_role resources and scrubs
// references to them from all other resources' dependency lists.
// Services now use connect_as to reference database_users directly.
type Version_1_1_0 struct{}

func (v *Version_1_1_0) Version() *ds.Version {
return resource.StateVersion_1_1_0
}

func (v *Version_1_1_0) Run(state *resource.State) error {
const serviceUserRoleType resource.Type = "swarm.service_user_role"

// 1. Delete all service_user_role resources from state
delete(state.Resources, serviceUserRoleType)

// 2. Remove service_user_role from all other resources' dependency lists
for _, resources := range state.Resources {
for _, data := range resources {
filtered := data.Dependencies[:0]
for _, dep := range data.Dependencies {
if dep.Type != serviceUserRoleType {
filtered = append(filtered, dep)
}
}
data.Dependencies = filtered
}
Comment thread
rshoemaker marked this conversation as resolved.
}

return nil
}
168 changes: 168 additions & 0 deletions server/internal/resource/migrations/1_1_0_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,168 @@
package migrations_test

import (
"testing"

"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"

"github.com/pgEdge/control-plane/server/internal/resource"
"github.com/pgEdge/control-plane/server/internal/resource/migrations"
)

func TestVersion_1_1_0(t *testing.T) {
serviceUserRoleType := resource.Type("swarm.service_user_role")
mcpConfigType := resource.Type("swarm.mcp_config")
serviceInstanceSpecType := resource.Type("swarm.service_instance_spec")
networkType := resource.Type("swarm.network")
dirType := resource.Type("swarm.dir")

svcRoleRO := resource.Identifier{ID: "appmcp-ro", Type: serviceUserRoleType}
svcRoleRW := resource.Identifier{ID: "appmcp-rw", Type: serviceUserRoleType}
networkDep := resource.Identifier{ID: "db-network", Type: networkType}
dirDep := resource.Identifier{ID: "data-dir", Type: dirType}

t.Run("removes service_user_role resources", func(t *testing.T) {
state := &resource.State{
Version: resource.StateVersion_1_0_0.Clone(),
Resources: map[resource.Type]map[string]*resource.ResourceData{
serviceUserRoleType: {
"appmcp-ro": {Identifier: svcRoleRO},
"appmcp-rw": {Identifier: svcRoleRW},
},
mcpConfigType: {
"mcp-cfg": {
Identifier: resource.Identifier{ID: "mcp-cfg", Type: mcpConfigType},
Dependencies: []resource.Identifier{dirDep, svcRoleRO, svcRoleRW},
},
},
serviceInstanceSpecType: {
"svc-spec": {
Identifier: resource.Identifier{ID: "svc-spec", Type: serviceInstanceSpecType},
Dependencies: []resource.Identifier{networkDep, svcRoleRO, svcRoleRW},
},
},
},
}

migration := &migrations.Version_1_1_0{}
err := migration.Run(state)
require.NoError(t, err)

// service_user_role resources should be gone
_, exists := state.Resources[serviceUserRoleType]
assert.False(t, exists, "service_user_role resources should be deleted")

// mcp_config should have service_user_role deps removed
mcpCfg := state.Resources[mcpConfigType]["mcp-cfg"]
require.NotNil(t, mcpCfg)
assert.Equal(t, []resource.Identifier{dirDep}, mcpCfg.Dependencies)

// service_instance_spec should have service_user_role deps removed
svcSpec := state.Resources[serviceInstanceSpecType]["svc-spec"]
require.NotNil(t, svcSpec)
assert.Equal(t, []resource.Identifier{networkDep}, svcSpec.Dependencies)
})

t.Run("removes service_user_role resources across all service types", func(t *testing.T) {
ragConfigType := resource.Type("swarm.rag_config")
postgrestConfigType := resource.Type("swarm.postgrest_config")

mcpRO := resource.Identifier{ID: "appmcp-ro", Type: serviceUserRoleType}
mcpRW := resource.Identifier{ID: "appmcp-rw", Type: serviceUserRoleType}
ragRO := resource.Identifier{ID: "apprag-ro", Type: serviceUserRoleType}
prstRO := resource.Identifier{ID: "appprst-ro", Type: serviceUserRoleType}
prstRW := resource.Identifier{ID: "appprst-rw", Type: serviceUserRoleType}

state := &resource.State{
Version: resource.StateVersion_1_0_0.Clone(),
Resources: map[resource.Type]map[string]*resource.ResourceData{
serviceUserRoleType: {
"appmcp-ro": {Identifier: mcpRO},
"appmcp-rw": {Identifier: mcpRW},
"apprag-ro": {Identifier: ragRO},
"appprst-ro": {Identifier: prstRO},
"appprst-rw": {Identifier: prstRW},
},
mcpConfigType: {
"mcp-cfg": {
Identifier: resource.Identifier{ID: "mcp-cfg", Type: mcpConfigType},
Dependencies: []resource.Identifier{dirDep, mcpRO, mcpRW},
},
},
ragConfigType: {
"rag-cfg": {
Identifier: resource.Identifier{ID: "rag-cfg", Type: ragConfigType},
Dependencies: []resource.Identifier{dirDep, ragRO},
},
},
postgrestConfigType: {
"prst-cfg": {
Identifier: resource.Identifier{ID: "prst-cfg", Type: postgrestConfigType},
Dependencies: []resource.Identifier{dirDep, prstRO, prstRW},
},
},
serviceInstanceSpecType: {
"svc-spec": {
Identifier: resource.Identifier{ID: "svc-spec", Type: serviceInstanceSpecType},
Dependencies: []resource.Identifier{networkDep, mcpRO, mcpRW, ragRO, prstRO, prstRW},
},
},
},
}

migration := &migrations.Version_1_1_0{}
err := migration.Run(state)
require.NoError(t, err)

// All service_user_role resources should be gone
_, exists := state.Resources[serviceUserRoleType]
assert.False(t, exists, "service_user_role resources should be deleted")

// MCP config: only dirDep remains
assert.Equal(t, []resource.Identifier{dirDep}, state.Resources[mcpConfigType]["mcp-cfg"].Dependencies)

// RAG config: only dirDep remains
assert.Equal(t, []resource.Identifier{dirDep}, state.Resources[ragConfigType]["rag-cfg"].Dependencies)

// PostgREST config: only dirDep remains
assert.Equal(t, []resource.Identifier{dirDep}, state.Resources[postgrestConfigType]["prst-cfg"].Dependencies)

// service_instance_spec: only networkDep remains
assert.Equal(t, []resource.Identifier{networkDep}, state.Resources[serviceInstanceSpecType]["svc-spec"].Dependencies)
})

t.Run("no-op when no service_user_role resources exist", func(t *testing.T) {
state := &resource.State{
Version: resource.StateVersion_1_0_0.Clone(),
Resources: map[resource.Type]map[string]*resource.ResourceData{
mcpConfigType: {
"mcp-cfg": {
Identifier: resource.Identifier{ID: "mcp-cfg", Type: mcpConfigType},
Dependencies: []resource.Identifier{dirDep},
},
},
},
}

migration := &migrations.Version_1_1_0{}
err := migration.Run(state)
require.NoError(t, err)

// mcp_config should be untouched
mcpCfg := state.Resources[mcpConfigType]["mcp-cfg"]
require.NotNil(t, mcpCfg)
assert.Equal(t, []resource.Identifier{dirDep}, mcpCfg.Dependencies)
})

t.Run("empty state", func(t *testing.T) {
state := &resource.State{
Version: resource.StateVersion_1_0_0.Clone(),
Resources: map[resource.Type]map[string]*resource.ResourceData{},
}

migration := &migrations.Version_1_1_0{}
err := migration.Run(state)
require.NoError(t, err)
})
}
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
{
"version": "1.0.0",
"version": "1.1.0",
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Having these change on every update is going to be a nuisance. We should probably switch 1_0_0_test.go to not use NewState:

diff --git a/server/internal/resource/migrations/1_0_0_test.go b/server/internal/resource/migrations/1_0_0_test.go
index 703880a2..fb74a858 100644
--- a/server/internal/resource/migrations/1_0_0_test.go
+++ b/server/internal/resource/migrations/1_0_0_test.go
@@ -139,7 +139,10 @@ func TestVersion_1_0_0(t *testing.T) {
 		},
 	} {
 		t.Run(tc.name, func(t *testing.T) {
-			state := resource.NewState()
+			state := &resource.State{
+				Version:   resource.StateVersion_1_0_0,
+				Resources: map[resource.Type]map[string]*resource.ResourceData{},
+			}
 			state.Add(tc.in...)
 
 			migration := &migrations.Version_1_0_0{}

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fixed.

"resources": {}
}
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
{
"version": "1.0.0",
"version": "1.1.0",
"resources": {
"database.instance": {
"instance-1": {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
{
"version": "1.0.0",
"version": "1.1.0",
"resources": {
"database.instance": {
"instance-1": {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
{
"version": "1.0.0",
"version": "1.1.0",
"resources": {
"database.instance": {
"instance-1": {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
{
"version": "1.0.0",
"version": "1.1.0",
"resources": {
"database.instance": {
"instance-1": {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
{
"version": "1.0.0",
"version": "1.1.0",
"resources": {
"database.instance": {
"instance-1": {
Expand Down
1 change: 1 addition & 0 deletions server/internal/resource/migrations/provide.go
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ func provideStateMigrations(i *do.Injector) {
do.Provide(i, func(i *do.Injector) (*resource.StateMigrations, error) {
return resource.NewStateMigrations([]resource.StateMigration{
&Version_1_0_0{},
&Version_1_1_0{},
}), nil
})
}
3 changes: 2 additions & 1 deletion server/internal/resource/state.go
Original file line number Diff line number Diff line change
Expand Up @@ -15,8 +15,9 @@ import (

var (
StateVersion_1_0_0 = ds.MustParseVersion("1.0.0")
StateVersion_1_1_0 = ds.MustParseVersion("1.1.0")

CurrentVersion = StateVersion_1_0_0
CurrentVersion = StateVersion_1_1_0
)

var (
Expand Down