Skip to content

Commit

Permalink
change docker compose using docker api sdk
Browse files Browse the repository at this point in the history
  • Loading branch information
zulkhair committed Aug 15, 2024
1 parent 69e78c9 commit f131fe1
Show file tree
Hide file tree
Showing 28 changed files with 1,602 additions and 45 deletions.
19 changes: 16 additions & 3 deletions cmd/world/cardinal/dev.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,8 +18,9 @@ import (

"pkg.world.dev/world-cli/common"
"pkg.world.dev/world-cli/common/config"
"pkg.world.dev/world-cli/common/docker"
"pkg.world.dev/world-cli/common/docker/service"
"pkg.world.dev/world-cli/common/logger"
"pkg.world.dev/world-cli/common/teacmd"
"pkg.world.dev/world-cli/tea/style"
)

Expand Down Expand Up @@ -228,10 +229,22 @@ func startRedis(ctx context.Context, cfg *config.Config) error {
// Create an error group for managing redis lifecycle
group := new(errgroup.Group)

// Create docker client
docker, err := docker.NewClient(cfg)
if err != nil {
return err
}
defer func() {
err := docker.Close()
if err != nil {
logger.Error("Failed to close docker client", err)
}
}()

// Start Redis container
group.Go(func() error {
cfg.Detach = true
if err := teacmd.DockerStart(cfg, []teacmd.DockerService{teacmd.DockerServiceRedis}); err != nil {
if err := docker.Start(ctx, cfg, service.Redis); err != nil {
return eris.Wrap(err, "Encountered an error with Redis")
}
return nil
Expand All @@ -243,7 +256,7 @@ func startRedis(ctx context.Context, cfg *config.Config) error {
// 2) The parent context is canceled for whatever reason.
group.Go(func() error {
<-ctx.Done()
if err := teacmd.DockerStop([]teacmd.DockerService{teacmd.DockerServiceRedis}); err != nil {
if err := docker.Stop(cfg, service.Redis); err != nil {
return err
}
return nil
Expand Down
24 changes: 21 additions & 3 deletions cmd/world/cardinal/purge.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,8 @@ import (

"github.com/spf13/cobra"

"pkg.world.dev/world-cli/common/teacmd"
"pkg.world.dev/world-cli/common/config"
"pkg.world.dev/world-cli/common/docker"
)

/////////////////
Expand All @@ -19,8 +20,25 @@ var purgeCmd = &cobra.Command{
Short: "Stop and reset the state of your Cardinal game shard",
Long: `Stop and reset the state of your Cardinal game shard.
This command stop all Docker services and remove all Docker volumes.`,
RunE: func(_ *cobra.Command, _ []string) error {
err := teacmd.DockerPurge()
RunE: func(cmd *cobra.Command, _ []string) error {
cfg, err := config.GetConfig(cmd)
if err != nil {
return err
}

// Create a new Docker client
docker, err := docker.NewClient(cfg)
if err != nil {
return err
}
defer func() {
err = docker.Close()
if err != nil {
fmt.Println("Failed to close docker client")
}
}()

err = docker.Purge(cfg)
if err != nil {
return err
}
Expand Down
27 changes: 15 additions & 12 deletions cmd/world/cardinal/restart.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,9 @@ import (
"github.com/spf13/cobra"

"pkg.world.dev/world-cli/common/config"
"pkg.world.dev/world-cli/common/teacmd"
"pkg.world.dev/world-cli/common/docker"
"pkg.world.dev/world-cli/common/docker/service"
"pkg.world.dev/world-cli/common/logger"
)

// restartCmd restarts your Cardinal game shard stack
Expand All @@ -31,18 +33,19 @@ This will restart the following Docker services:
return err
}

if cfg.Debug {
err = teacmd.DockerRestart(cfg, []teacmd.DockerService{
teacmd.DockerServiceCardinalDebug,
teacmd.DockerServiceNakama,
})
} else {
err = teacmd.DockerRestart(cfg, []teacmd.DockerService{
teacmd.DockerServiceCardinal,
teacmd.DockerServiceNakama,
})
// Create docker client
docker, err := docker.NewClient(cfg)
if err != nil {
return err
}

defer func() {
err := docker.Close()
if err != nil {
logger.Error("Failed to close docker client", err)
}
}()

err = docker.Restart(cmd.Context(), cfg, service.Cardinal, service.Nakama)
if err != nil {
return err
}
Expand Down
23 changes: 21 additions & 2 deletions cmd/world/cardinal/start.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,14 +4,17 @@ import (
"fmt"
"strings"

"github.com/google/uuid"
"github.com/rotisserie/eris"
"github.com/rs/zerolog"
"github.com/spf13/cobra"
"golang.org/x/sync/errgroup"

"pkg.world.dev/world-cli/common"
"pkg.world.dev/world-cli/common/config"
"pkg.world.dev/world-cli/common/teacmd"
"pkg.world.dev/world-cli/common/docker"
"pkg.world.dev/world-cli/common/docker/service"
"pkg.world.dev/world-cli/common/logger"
)

/////////////////
Expand Down Expand Up @@ -108,11 +111,27 @@ This will start the following Docker services and its dependencies:
fmt.Println("This may take a few minutes to rebuild the Docker images.")
fmt.Println("Use `world cardinal dev` to run Cardinal faster/easier in development mode.")

// Print CockroachDB password
cfg.DockerEnv["DB_PASSWORD"] = uuid.New().String()
printServiceAddress("DB Password", cfg.DockerEnv["DB_PASSWORD"])

group, ctx := errgroup.WithContext(cmd.Context())

// Create docker client
docker, err := docker.NewClient(cfg)
if err != nil {
return err
}
defer func() {
err := docker.Close()
if err != nil {
logger.Error("Failed to close docker client", err)
}
}()

// Start the World Engine stack
group.Go(func() error {
if err := teacmd.DockerStartAll(cfg); err != nil {
if err := docker.Start(ctx, cfg, service.NakamaDB, service.Redis, service.Cardinal, service.Nakama); err != nil {
return eris.Wrap(err, "Encountered an error with Docker")
}
return eris.Wrap(ErrGracefulExit, "Stack terminated")
Expand Down
26 changes: 23 additions & 3 deletions cmd/world/cardinal/stop.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,10 @@ import (

"github.com/spf13/cobra"

"pkg.world.dev/world-cli/common/teacmd"
"pkg.world.dev/world-cli/common/config"
"pkg.world.dev/world-cli/common/docker"
"pkg.world.dev/world-cli/common/docker/service"
"pkg.world.dev/world-cli/common/logger"
)

/////////////////
Expand All @@ -23,8 +26,25 @@ This will stop the following Docker services:
- Cardinal (Game shard)
- Nakama (Relay) + DB
- Redis (Cardinal dependency)`,
RunE: func(_ *cobra.Command, _ []string) error {
err := teacmd.DockerStopAll()
RunE: func(cmd *cobra.Command, _ []string) error {
cfg, err := config.GetConfig(cmd)
if err != nil {
return err
}

// Create docker client
docker, err := docker.NewClient(cfg)
if err != nil {
return err
}
defer func() {
err := docker.Close()
if err != nil {
logger.Error("Failed to close docker client", err)
}
}()

err = docker.Stop(cfg, service.Nakama, service.Cardinal, service.NakamaDB, service.Redis)
if err != nil {
return err
}
Expand Down
2 changes: 1 addition & 1 deletion cmd/world/root/login.go
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ var (
func getLoginCmd() *cobra.Command {
loginCmd := &cobra.Command{
Use: "login",
Short: "Authenticate using an access token",
Short: "Authenticate using an access token (under construction)",
RunE: func(cmd *cobra.Command, _ []string) error {
err := loginOnBrowser(cmd.Context())
if err != nil {
Expand Down
2 changes: 1 addition & 1 deletion cmd/world/root/root_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -132,7 +132,7 @@ func TestCreateStartStopRestartPurge(t *testing.T) {
assert.NilError(t, err)

// Start cardinal
rootCmd.SetArgs([]string{"cardinal", "start", "--build", "--detach", "--editor=false"})
rootCmd.SetArgs([]string{"cardinal", "start", "--detach", "--editor=false"})
err = rootCmd.Execute()
assert.NilError(t, err)

Expand Down
15 changes: 8 additions & 7 deletions common/config/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -28,13 +28,14 @@ var (
)

type Config struct {
RootDir string
GameDir string
Detach bool
Build bool
Debug bool
Timeout int
DockerEnv map[string]string
RootDir string
GameDir string
Detach bool
Build bool
Debug bool
BuildkitSupport bool
Timeout int
DockerEnv map[string]string
}

func AddConfigFlag(cmd *cobra.Command) {
Expand Down
138 changes: 138 additions & 0 deletions common/docker/client.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,138 @@
package docker

import (
"context"

"github.com/docker/docker/client"
"github.com/rotisserie/eris"

"pkg.world.dev/world-cli/common/config"
"pkg.world.dev/world-cli/common/docker/service"
"pkg.world.dev/world-cli/common/logger"
)

type Client struct {
cli *client.Client
cfg *config.Config
}

func NewClient(cfg *config.Config) (*Client, error) {
cli, err := client.NewClientWithOpts(client.FromEnv, client.WithAPIVersionNegotiation())
if err != nil {
return nil, eris.Wrap(err, "Failed to create docker client")
}

cfg.BuildkitSupport = checkBuildKitSupport(cli)

return &Client{
cli: cli,
cfg: cfg,
}, nil
}

func (c *Client) Close() error {
return c.cli.Close()
}

func (c *Client) Start(ctx context.Context, cfg *config.Config, //nolint:gocognit
services ...service.GetDockerService) error {
defer func() {
if !cfg.Detach {
err := c.Stop(cfg, services...)
if err != nil {
logger.Error("Failed to stop containers", err)
}
}
}()

namespace := cfg.DockerEnv["CARDINAL_NAMESPACE"]
err := c.createNetworkIfNotExists(namespace)
if err != nil {
return eris.Wrap(err, "Failed to create network")
}

err = c.createVolumeIfNotExists(namespace)
if err != nil {
return eris.Wrap(err, "Failed to create volume")
}

// var for storing container names
containers := make([]string, 0)

// iterate over configurations and create containers
for _, getService := range services {
service := getService(cfg)
if cfg.Build && service.Dockerfile.Script != "" {
for _, preImage := range service.Dockerfile.PrerequisiteImages {
if err := c.pullImageIfNotExists(ctx, preImage); err != nil {
return eris.Wrap(err, "Failed to pull prerequisite image")
}
}

if err := c.buildImage(ctx, service.Dockerfile, service.Image); err != nil {
return eris.Wrap(err, "Failed to build image")
}
} else {
if err := c.pullImageIfNotExists(ctx, service); err != nil {
return eris.Wrap(err, "Failed to pull image")
}
}

if err := c.createContainer(ctx, service); err != nil {
return eris.Wrap(err, "Failed to create container")
}

containers = append(containers, service.Name)
}

// log containers if not detached
if !cfg.Detach {
c.logContainers(ctx, containers)
}

return nil
}

func (c *Client) Stop(cfg *config.Config, services ...service.GetDockerService) error {
ctx := context.Background()
for _, getService := range services {
configuration := getService(cfg)
if err := c.stopAndRemoveContainer(ctx, configuration.Name); err != nil {
return eris.Wrap(err, "Failed to stop container")
}
}

return nil
}

func (c *Client) Purge(cfg *config.Config) error {
ctx := context.Background()
err := c.Stop(cfg, service.Nakama, service.NakamaDB,
service.Cardinal, service.Redis, service.CelestiaDevNet, service.EVM)
if err != nil {
return err
}

err = c.removeVolume(ctx, cfg.DockerEnv["CARDINAL_NAMESPACE"])
if err != nil {
return err
}

err = c.removeNetwork(ctx, cfg.DockerEnv["CARDINAL_NAMESPACE"])
if err != nil {
return err
}

return nil
}

func (c *Client) Restart(ctx context.Context, cfg *config.Config,
services ...service.GetDockerService) error {
// stop containers
err := c.Stop(cfg, services...)
if err != nil {
return err
}

return c.Start(ctx, cfg, services...)
}
Loading

0 comments on commit f131fe1

Please sign in to comment.