1
+ package commands
2
+
3
+ import (
4
+ "context"
5
+ "os"
6
+ "path/filepath"
7
+ "testing"
8
+
9
+ "github.com/stretchr/testify/assert"
10
+ "github.com/stretchr/testify/require"
11
+
12
+ "github.com/docker/mcp-gateway/cmd/docker-mcp/catalog"
13
+ )
14
+
15
+ func TestDockerCatalogProtection (t * testing.T ) {
16
+ // Create temporary home directory
17
+ tempHome := t .TempDir ()
18
+ originalHome := os .Getenv ("HOME" )
19
+ defer func () {
20
+ if originalHome != "" {
21
+ os .Setenv ("HOME" , originalHome )
22
+ }
23
+ }()
24
+
25
+ if err := os .Setenv ("HOME" , tempHome ); err != nil {
26
+ t .Fatal (err )
27
+ }
28
+
29
+ // Create the MCP directory structure
30
+ mcpDir := filepath .Join (tempHome , ".docker" , "mcp" )
31
+ catalogsDir := filepath .Join (mcpDir , "catalogs" )
32
+ require .NoError (t , os .MkdirAll (catalogsDir , 0755 ))
33
+
34
+ // Initialize the catalog system
35
+ ctx := context .Background ()
36
+ require .NoError (t , catalog .Init (ctx ))
37
+
38
+ t .Run ("TestCreateDockerCatalogPrevented" , func (t * testing.T ) {
39
+ err := catalog .Create (catalog .DockerCatalogName )
40
+ assert .Error (t , err )
41
+ assert .Contains (t , err .Error (), "cannot create catalog 'docker-mcp' as it is reserved for Docker's official catalog" )
42
+ })
43
+
44
+ t .Run ("TestRemoveDockerCatalogPrevented" , func (t * testing.T ) {
45
+ err := catalog .Rm (catalog .DockerCatalogName )
46
+ assert .Error (t , err )
47
+ assert .Contains (t , err .Error (), "cannot remove catalog 'docker-mcp' as it is managed by Docker" )
48
+ })
49
+
50
+ t .Run ("TestForkToDockerCatalogPrevented" , func (t * testing.T ) {
51
+ // First create a source catalog to fork from
52
+ require .NoError (t , catalog .Create ("source-catalog" ))
53
+
54
+ err := catalog .Fork ("source-catalog" , catalog .DockerCatalogName )
55
+ assert .Error (t , err )
56
+ assert .Contains (t , err .Error (), "cannot create catalog 'docker-mcp' as it is reserved for Docker's official catalog" )
57
+ })
58
+
59
+ t .Run ("TestForkFromDockerCatalogAllowed" , func (t * testing.T ) {
60
+ // Create a minimal docker-mcp.yaml file to fork from
61
+ dockerCatalog := `
62
+ registry:
63
+ test-server:
64
+ title: "Test Server"
65
+ description: "A test server"
66
+ image: "test/server:latest"
67
+ `
68
+ dockerCatalogPath := filepath .Join (catalogsDir , "docker-mcp.yaml" )
69
+ require .NoError (t , os .WriteFile (dockerCatalogPath , []byte (dockerCatalog ), 0644 ))
70
+
71
+ // Forking FROM Docker catalog should work
72
+ err := catalog .Fork (catalog .DockerCatalogName , "my-docker-fork" )
73
+ assert .NoError (t , err )
74
+
75
+ // Verify the fork was created
76
+ cfg , err := catalog .ReadConfig ()
77
+ require .NoError (t , err )
78
+ _ , exists := cfg .Catalogs ["my-docker-fork" ]
79
+ assert .True (t , exists )
80
+ })
81
+
82
+ t .Run ("TestAddToDockerCatalogPrevented" , func (t * testing.T ) {
83
+ // Create a source catalog file
84
+ sourceCatalog := `
85
+ registry:
86
+ source-server:
87
+ title: "Source Server"
88
+ description: "A source server"
89
+ image: "source/server:latest"
90
+ `
91
+ sourcePath := filepath .Join (catalogsDir , "source.yaml" )
92
+ require .NoError (t , os .WriteFile (sourcePath , []byte (sourceCatalog ), 0644 ))
93
+
94
+ // Try to add to Docker catalog
95
+ args := catalog .ParseAddArgs (catalog .DockerCatalogName , "test-server" , sourcePath )
96
+ err := catalog .ValidateArgs (* args )
97
+ assert .Error (t , err )
98
+ assert .Contains (t , err .Error (), "cannot add servers to catalog 'docker-mcp' as it is managed by Docker" )
99
+ })
100
+
101
+ t .Run ("TestExportDockerCatalogPrevented" , func (t * testing.T ) {
102
+ outputPath := filepath .Join (tempHome , "exported-docker.yaml" )
103
+ err := catalog .Export (ctx , catalog .DockerCatalogName , outputPath )
104
+ assert .Error (t , err )
105
+ assert .Contains (t , err .Error (), "cannot export the Docker MCP catalog as it is managed by Docker" )
106
+ })
107
+
108
+ t .Run ("TestExportDockerCatalogFilenamePrevented" , func (t * testing.T ) {
109
+ outputPath := filepath .Join (tempHome , "exported-docker.yaml" )
110
+ err := catalog .Export (ctx , catalog .DockerCatalogFilename , outputPath )
111
+ assert .Error (t , err )
112
+ assert .Contains (t , err .Error (), "cannot export the Docker MCP catalog as it is managed by Docker" )
113
+ })
114
+
115
+ t .Run ("TestNormalCatalogOperationsStillWork" , func (t * testing.T ) {
116
+ // Create a normal catalog
117
+ err := catalog .Create ("normal-catalog" )
118
+ assert .NoError (t , err )
119
+
120
+ // Verify it exists
121
+ cfg , err := catalog .ReadConfig ()
122
+ require .NoError (t , err )
123
+ _ , exists := cfg .Catalogs ["normal-catalog" ]
124
+ assert .True (t , exists )
125
+
126
+ // Fork it
127
+ err = catalog .Fork ("normal-catalog" , "forked-catalog" )
128
+ assert .NoError (t , err )
129
+
130
+ // Add to it (create source file first)
131
+ sourceCatalog := `
132
+ registry:
133
+ normal-server:
134
+ title: "Normal Server"
135
+ description: "A normal server"
136
+ image: "normal/server:latest"
137
+ `
138
+ sourcePath := filepath .Join (catalogsDir , "normal-source.yaml" )
139
+ require .NoError (t , os .WriteFile (sourcePath , []byte (sourceCatalog ), 0644 ))
140
+
141
+ args := catalog .ParseAddArgs ("normal-catalog" , "normal-server" , sourcePath )
142
+ err = catalog .ValidateArgs (* args )
143
+ assert .NoError (t , err )
144
+
145
+ err = catalog .Add (* args , false )
146
+ assert .NoError (t , err )
147
+
148
+ // Export it
149
+ outputPath := filepath .Join (tempHome , "exported-normal.yaml" )
150
+ err = catalog .Export (ctx , "normal-catalog" , outputPath )
151
+ assert .NoError (t , err )
152
+
153
+ // Verify export file exists
154
+ _ , err = os .Stat (outputPath )
155
+ assert .NoError (t , err )
156
+
157
+ // Remove it
158
+ err = catalog .Rm ("normal-catalog" )
159
+ assert .NoError (t , err )
160
+
161
+ // Verify it's gone
162
+ cfg , err = catalog .ReadConfig ()
163
+ require .NoError (t , err )
164
+ _ , exists = cfg .Catalogs ["normal-catalog" ]
165
+ assert .False (t , exists )
166
+ })
167
+ }
0 commit comments