77 "strings"
88
99 "github.com/testcontainers/testcontainers-go"
10+ tcexec "github.com/testcontainers/testcontainers-go/exec"
1011 tcnetwork "github.com/testcontainers/testcontainers-go/network"
1112)
1213
@@ -59,24 +60,18 @@ func (c *EtcdContainer) Terminate(ctx context.Context, opts ...testcontainers.Te
5960
6061// Run creates an instance of the etcd container type
6162func Run (ctx context.Context , img string , opts ... testcontainers.ContainerCustomizer ) (* EtcdContainer , error ) {
62- req := testcontainers.ContainerRequest {
63- Image : img ,
64- ExposedPorts : []string {clientPort , peerPort },
65- Cmd : []string {},
63+ moduleOpts := []testcontainers.ContainerCustomizer {
64+ testcontainers .WithExposedPorts (clientPort , peerPort ),
6665 }
6766
68- genericContainerReq := testcontainers.GenericContainerRequest {
69- ContainerRequest : req ,
70- Started : true ,
71- }
67+ moduleOpts = append (moduleOpts , opts ... )
7268
73- settings := defaultOptions (& req )
69+ settings := defaultOptions ()
7470 for _ , opt := range opts {
7571 if apply , ok := opt .(Option ); ok {
76- apply (& settings )
77- }
78- if err := opt .Customize (& genericContainerReq ); err != nil {
79- return nil , err
72+ if err := apply (& settings ); err != nil {
73+ return nil , fmt .Errorf ("apply option: %w" , err )
74+ }
8075 }
8176 }
8277
@@ -86,7 +81,7 @@ func Run(ctx context.Context, img string, opts ...testcontainers.ContainerCustom
8681 }
8782
8883 // configure CMD with the nodes
89- genericContainerReq . Cmd = configureCMD (settings )
84+ moduleOpts = append ( moduleOpts , testcontainers . WithCmd ( configureCMD (settings ) ... ) )
9085
9186 // Initialise the etcd container with the current settings.
9287 // The cluster network, if needed, is already part of the settings,
@@ -96,21 +91,33 @@ func Run(ctx context.Context, img string, opts ...testcontainers.ContainerCustom
9691
9792 if settings .clusterNetwork != nil {
9893 // apply the network to the current node
99- err := tcnetwork .WithNetwork ([]string {settings .nodeNames [settings .currentNode ]}, settings .clusterNetwork )(& genericContainerReq )
100- if err != nil {
101- return c , fmt .Errorf ("with network: %w" , err )
102- }
94+ moduleOpts = append (moduleOpts , tcnetwork .WithNetwork ([]string {settings .nodeNames [settings .currentNode ]}, settings .clusterNetwork ))
95+ }
96+
97+ if settings .mountDataDir {
98+ moduleOpts = append (moduleOpts , testcontainers .WithAdditionalLifecycleHooks (testcontainers.ContainerLifecycleHooks {
99+ PostStarts : []testcontainers.ContainerHook {
100+ func (ctx context.Context , c testcontainers.Container ) error {
101+ _ , _ , err := c .Exec (ctx , []string {"chmod" , "o+rwx" , "-R" , dataDir }, tcexec .Multiplexed ())
102+ if err != nil {
103+ return fmt .Errorf ("chmod etcd data dir: %w" , err )
104+ }
105+
106+ return nil
107+ },
108+ },
109+ }))
103110 }
104111
105- if c .Container , err = testcontainers .GenericContainer (ctx , genericContainerReq ); err != nil {
106- return c , fmt .Errorf ("generic container : %w" , err )
112+ if c .Container , err = testcontainers .Run (ctx , img , moduleOpts ... ); err != nil {
113+ return c , fmt .Errorf ("run etcd : %w" , err )
107114 }
108115
109116 // only the first node creates the cluster
110117 if settings .currentNode == 0 {
111118 for i := 1 ; i < len (settings .nodeNames ); i ++ {
112119 // move to the next node
113- childNode , err := Run (ctx , req . Image , append (clusterOpts , withCurrentNode (i ))... )
120+ childNode , err := Run (ctx , img , append (clusterOpts , withCurrentNode (i ))... )
114121 if err != nil {
115122 // return the parent cluster node and the error, so the caller can clean up.
116123 return c , fmt .Errorf ("run cluster node: %w" , err )
0 commit comments