Skip to content

Commit 2f1dc3f

Browse files
Merge pull request #4 from OctopusSolutionsEngineering/isaac/shared-test-containers
Adding support for shared test containers
2 parents 24df7b6 + e874bf3 commit 2f1dc3f

File tree

1 file changed

+123
-8
lines changed

1 file changed

+123
-8
lines changed

test/octopus_container_test_framework.go

Lines changed: 123 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ import (
1515
"github.com/testcontainers/testcontainers-go"
1616
"github.com/testcontainers/testcontainers-go/wait"
1717
orderedmap "github.com/wk8/go-ordered-map/v2"
18+
"log"
1819
"net/http"
1920
"os"
2021
"os/exec"
@@ -43,7 +44,7 @@ type OctopusContainer struct {
4344
URI string
4445
}
4546

46-
type mysqlContainer struct {
47+
type MysqlContainer struct {
4748
testcontainers.Container
4849
port string
4950
ip string
@@ -99,7 +100,7 @@ func (o *OctopusContainerTest) setupNetwork(ctx context.Context) (testcontainers
99100
}
100101

101102
// setupDatabase creates a MSSQL container
102-
func (o *OctopusContainerTest) setupDatabase(ctx context.Context, network string) (*mysqlContainer, error) {
103+
func (o *OctopusContainerTest) setupDatabase(ctx context.Context, network string) (*MysqlContainer, error) {
103104
req := testcontainers.ContainerRequest{
104105
Name: "mssql-" + uuid.New().String(),
105106
Image: "mcr.microsoft.com/mssql/server",
@@ -135,7 +136,7 @@ func (o *OctopusContainerTest) setupDatabase(ctx context.Context, network string
135136
return nil, err
136137
}
137138

138-
return &mysqlContainer{
139+
return &MysqlContainer{
139140
Container: container,
140141
ip: ip,
141142
port: mappedPort.Port(),
@@ -170,7 +171,7 @@ func (o *OctopusContainerTest) getRetryCount() uint {
170171
}
171172

172173
// setupOctopus creates an Octopus container
173-
func (o *OctopusContainerTest) setupOctopus(ctx context.Context, connString string, network string, t *testing.T) (*OctopusContainer, error) {
174+
func (o *OctopusContainerTest) setupOctopus(ctx context.Context, connString string, network string) (*OctopusContainer, error) {
174175
if os.Getenv("LICENSE") == "" {
175176
return nil, errors.New("the LICENSE environment variable must be set to a base 64 encoded Octopus license key")
176177
}
@@ -203,7 +204,7 @@ func (o *OctopusContainerTest) setupOctopus(ctx context.Context, connString stri
203204
network,
204205
},
205206
}
206-
t.Log("Creating Octopus container")
207+
log.Println("Creating Octopus container")
207208
container, err := testcontainers.GenericContainer(ctx, testcontainers.GenericContainerRequest{
208209
ContainerRequest: req,
209210
Started: true,
@@ -212,7 +213,7 @@ func (o *OctopusContainerTest) setupOctopus(ctx context.Context, connString stri
212213
if err != nil {
213214
return nil, err
214215
}
215-
t.Log("Finished creating Octopus container")
216+
log.Println("Finished creating Octopus container")
216217

217218
// Display the container logs
218219
if os.Getenv("OCTODISABLEOCTOCONTAINERLOGGING") != "true" {
@@ -237,7 +238,7 @@ func (o *OctopusContainerTest) setupOctopus(ctx context.Context, connString stri
237238
// createDockerInfrastructure attemptes to create the complete Docker stack containing a
238239
// network, MSSQL container, and Octopus container. The return values include as much of
239240
// the partial stack as possible in the case of an error.
240-
func (o *OctopusContainerTest) createDockerInfrastructure(t *testing.T, ctx context.Context) (testcontainers.Network, *OctopusContainer, *mysqlContainer, error) {
241+
func (o *OctopusContainerTest) createDockerInfrastructure(t *testing.T, ctx context.Context) (testcontainers.Network, *OctopusContainer, *MysqlContainer, error) {
241242

242243
network, networkName, err := o.setupNetwork(ctx)
243244
if err != nil {
@@ -262,7 +263,7 @@ func (o *OctopusContainerTest) createDockerInfrastructure(t *testing.T, ctx cont
262263
t.Log("SQL Server IP: " + sqlIp)
263264
t.Log("SQL Server Container Name: " + sqlName)
264265

265-
octopusContainer, err := o.setupOctopus(ctx, "Server="+sqlIp+",1433;Database=OctopusDeploy;User=sa;Password=Password01!", networkName, t)
266+
octopusContainer, err := o.setupOctopus(ctx, "Server="+sqlIp+",1433;Database=OctopusDeploy;User=sa;Password=Password01!", networkName)
266267
if err != nil {
267268
return network, octopusContainer, sqlServer, err
268269
}
@@ -283,6 +284,120 @@ func (o *OctopusContainerTest) createDockerInfrastructure(t *testing.T, ctx cont
283284
return network, octopusContainer, sqlServer, nil
284285
}
285286

287+
// ArrangeTestContainer is wrapper that initialises Octopus, and returns the container for future test runs
288+
func (o *OctopusContainerTest) ArrangeContainer(m *testing.M) (*OctopusContainer, *client.Client, *MysqlContainer, testcontainers.Network, error) {
289+
var octopusContainer *OctopusContainer
290+
var octoClient *client.Client
291+
var network testcontainers.Network
292+
var networkName string
293+
var sqlServer *MysqlContainer
294+
295+
err := retry.Do(
296+
func() error {
297+
ctx := context.Background()
298+
299+
var err error
300+
network, networkName, err = o.setupNetwork(ctx)
301+
if err != nil {
302+
return err
303+
}
304+
305+
sqlServer, err = o.setupDatabase(ctx, networkName)
306+
if err != nil {
307+
return err
308+
}
309+
310+
sqlIp, err := sqlServer.Container.ContainerIP(ctx)
311+
if err != nil {
312+
return err
313+
}
314+
315+
sqlName, err := sqlServer.Container.Name(ctx)
316+
if err != nil {
317+
return err
318+
}
319+
320+
log.Println("SQL Server IP: " + sqlIp)
321+
log.Println("SQL Server Container Name: " + sqlName)
322+
323+
octopusContainer, err = o.setupOctopus(ctx, "Server="+sqlIp+",1433;Database=OctopusDeploy;User=sa;Password=Password01!", networkName)
324+
if err != nil {
325+
return err
326+
}
327+
328+
octoIp, err := octopusContainer.Container.ContainerIP(ctx)
329+
if err != nil {
330+
return err
331+
}
332+
333+
octoName, err := octopusContainer.Container.Name(ctx)
334+
if err != nil {
335+
return err
336+
}
337+
338+
log.Println("Octopus IP: " + octoIp)
339+
log.Println("Octopus Container Name: " + octoName)
340+
341+
// give the server 5 minutes to start up
342+
err = lintwait.WaitForResource(func() error {
343+
resp, err := http.Get(octopusContainer.URI + "/api")
344+
if err != nil || resp.StatusCode != http.StatusOK {
345+
return errors.New("the api endpoint was not available")
346+
}
347+
return nil
348+
}, 5*time.Minute)
349+
350+
if err != nil {
351+
return err
352+
}
353+
354+
octoClient, err = octoclient.CreateClient(octopusContainer.URI, "", ApiKey)
355+
if err != nil {
356+
return err
357+
}
358+
359+
return nil
360+
},
361+
retry.Attempts(o.getRetryCount()),
362+
retry.Delay(30*time.Second),
363+
)
364+
365+
if err != nil {
366+
log.Println(err.Error())
367+
return nil, nil, nil, nil, err
368+
}
369+
370+
return octopusContainer, octoClient, sqlServer, network, nil
371+
}
372+
373+
// Clean up the container after the test is complete
374+
func (o *OctopusContainerTest) CleanUp(ctx context.Context, octoContainer *OctopusContainer, sqlServer *MysqlContainer, network testcontainers.Network) error {
375+
// Stop the containers
376+
stopTime := 1 * time.Minute
377+
if octoStopErr := octoContainer.Stop(ctx, &stopTime); octoStopErr != nil {
378+
log.Println("Failed to stop the Octopus container:", octoStopErr)
379+
}
380+
381+
if sqlStopErr := sqlServer.Container.Stop(ctx, &stopTime); sqlStopErr != nil {
382+
log.Println("Failed to stop the SQL Server container:", sqlStopErr)
383+
}
384+
385+
// Terminate the containers
386+
if octoTerminateErr := octoContainer.Terminate(ctx); octoTerminateErr != nil {
387+
log.Printf("Failed to terminate the Octopus container: %v", octoTerminateErr)
388+
}
389+
390+
if sqlTerminateErr := sqlServer.Container.Terminate(ctx); sqlTerminateErr != nil {
391+
log.Printf("Failed to terminate the SQL Server container: %v", sqlTerminateErr)
392+
}
393+
394+
if networkErr := network.Remove(ctx); networkErr != nil {
395+
log.Printf("Failed to remove network: %v", networkErr)
396+
}
397+
398+
return nil
399+
}
400+
286401
// ArrangeTest is wrapper that initialises Octopus, runs a test, and cleans up the containers
287402
func (o *OctopusContainerTest) ArrangeTest(t *testing.T, testFunc func(t *testing.T, container *OctopusContainer, client *client.Client) error) {
288403
err := retry.Do(

0 commit comments

Comments
 (0)