Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
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
222 changes: 97 additions & 125 deletions cmd/start.go
Original file line number Diff line number Diff line change
@@ -1,25 +1,17 @@
package cmd

import (
"context"
"fmt"
"io"
"log"
"os"
"os/exec"
"strings"

"github.com/docker/docker/api/types/container"
"github.com/docker/docker/api/types/image"
"github.com/docker/docker/client"
"github.com/docker/go-connections/nat"

"github.com/microcks/microcks-cli/pkg/config"
"github.com/microcks/microcks-cli/pkg/connectors"
"github.com/microcks/microcks-cli/pkg/errors"
"github.com/spf13/cobra"
)

func NewStartCommand() *cobra.Command {
var (
hostIP string = "0.0.0.0"
name string
hostPort string
imageName string
Expand All @@ -41,62 +33,114 @@ microcks start --driver [driver you wnat either 'docker' or 'podman']
# Define name of your microcks container/instance
microcks start --name [name of you container/instance]`,
Run: func(cmd *cobra.Command, args []string) {
cfg, err := config.EnsureConfig(config.ConfigPath)

if err != nil {
log.Fatalf("Error loading config: %v", err)
}

cfg.Instance.Driver = driver
configFile, err := config.DefaultLocalConfigPath()
errors.CheckError(err)
localConfig, err := config.ReadLocalConfig(configFile)
errors.CheckError(err)

cli, err := createClient(cfg.Instance.Driver)

if err != nil {
fmt.Println(err)
return
if localConfig == nil {
localConfig = &config.LocalConfig{}
}

defer cli.Close()

if cfg.Instance.Status == "Running" {
fmt.Println("Microcks is already running.")
return
instance, _ := localConfig.GetInstance(name)
if instance == nil {
instance = &config.Instance{}
}

if cfg.Instance.Status == "Stopped" || cfg.Instance.Status == "Created" {
if err := startContainer(cfg.Instance.ContainerID, cli); err != nil {
fmt.Errorf("failed to start container: %v", err)
}
fmt.Println("Microcks started successfully...")
if instance.Status == "Running" {
fmt.Printf("Microcks instance with name %s is already running", name)
return
}

cfg.Instance.Name = name
cfg.Instance.Image = imageName
cfg.Instance.Port = hostPort
cfg.Instance.AutoRemove = autoRemove

containerID, err := createContainer(cfg, hostIP, cli)

if err != nil {
log.Fatalf("Failed to create a container: %v", err)
switch instance.Status {
case "Running":
fmt.Printf("Microcks instance with name %s is already running", name)
return
}
cfg.Instance.ContainerID = containerID
cfg.Instance.Status = "Created"
case "Exited":
containerClient, err := connectors.NewContainerClient(instance.Driver)
errors.CheckError(err)
defer containerClient.CloseClient()

if err := containerClient.StartContainer(instance.ContainerID); err != nil {
log.Fatalf("failed to start container: %v", err)
return
}
instance.Status = "Running"
default:
containerClient, err := connectors.NewContainerClient(driver)
errors.CheckError(err)
defer containerClient.CloseClient()

containerId, err := containerClient.CreateContainer(connectors.ContainerOpts{
Image: imageName,
Port: hostPort,
Name: name,
AutoRemove: autoRemove,
})
if err != nil {
log.Fatalf("Failed to create a container: %v", err)
return
}

if err := startContainer(cfg.Instance.ContainerID, cli); err != nil {
fmt.Errorf("failed to start container: %v", err)
return
}
cfg.Instance.Status = "Running"
err = config.SaveConfig(config.ConfigPath, cfg)
if err := containerClient.StartContainer(containerId); err != nil {
log.Fatalf("failed to start container: %v", err)
return
}

if err != nil {
log.Fatalf("Failed to save config: %v", err)
return
instance.ContainerID = containerId
instance.AutoRemove = autoRemove
instance.Name = name
instance.Image = imageName
instance.Port = hostPort
instance.Status = "Running"
instance.Driver = driver
}

//Store config and change context
localConfig.UpsertInstance(config.Instance{
ContainerID: instance.ContainerID,
Name: instance.Name,
Image: instance.Image,
Port: instance.Port,
Status: instance.Status,
Driver: instance.Driver,
AutoRemove: instance.AutoRemove,
})

server := fmt.Sprintf("http://localhost:%s", instance.Port)

localConfig.UpsertServer(config.Server{
Name: name,
Server: server,
InsecureTLS: true,
KeycloackEnable: false,
})

localConfig.UpserAuth(config.Auth{
Server: server,
ClientId: "",
ClientSecret: "",
})

localConfig.UpsertUser(config.User{
Name: server,
AuthToken: "",
RefreshToken: "",
})

localConfig.CurrentContext = server
localConfig.UpserContext(config.ContextRef{
Name: server,
Server: server,
User: server,
Instance: instance.Name,
})

// Save configs to config file
err = config.WriteLocalConfig(*localConfig, configFile)
errors.CheckError(err)

fmt.Printf("Microcks started successfully...")
},
}
Expand All @@ -107,75 +151,3 @@ microcks start --name [name of you container/instance]`,
startCmd.Flags().StringVar(&driver, "driver", "docker", "use --driver to change driver from docker to podman")
return startCmd
}

func createClient(driver string) (*client.Client, error) {

if driver != "docker" {
out, err := exec.Command("podman", "machine", "inspect", "--format", "{{.ConnectionInfo.PodmanSocket.Path}}").Output()
if err != nil {
fmt.Println(err)
}

err = os.Setenv("DOCKER_HOST", "unix://"+strings.TrimSpace(string(out)))
if err != nil {
fmt.Println(err)
}
}

cli, err := client.NewClientWithOpts(client.FromEnv, client.WithAPIVersionNegotiation())

if err != nil {
return nil, err
}

return cli, nil
}

func createContainer(cfg *config.Config, hostIP string, cli *client.Client) (string, error) {
ctx := context.Background()

// Define exposed port and bindings
exposedPort, _ := nat.NewPort("tcp", "8080")
portBindings := nat.PortMap{
exposedPort: []nat.PortBinding{
{
HostIP: hostIP,
HostPort: cfg.Instance.Port,
},
},
}

out, err := cli.ImagePull(ctx, cfg.Instance.Image, image.PullOptions{})
if err != nil {
return "", err
}
defer out.Close()
io.Copy(os.Stdout, out)

resp, err := cli.ContainerCreate(
ctx,
&container.Config{
Image: cfg.Instance.Image,
ExposedPorts: nat.PortSet{exposedPort: struct{}{}},
},
&container.HostConfig{
PortBindings: portBindings,
AutoRemove: cfg.Instance.AutoRemove,
}, nil, nil, cfg.Instance.Name)

if err != nil {
return "", err
}

return resp.ID, nil
}

func startContainer(cotainerID string, cli *client.Client) error {
ctx := context.Background()

if err := cli.ContainerStart(ctx, cotainerID, container.StartOptions{}); err != nil {
panic(err)
}

return nil
}
83 changes: 44 additions & 39 deletions cmd/stop.go
Original file line number Diff line number Diff line change
@@ -1,13 +1,12 @@
package cmd

import (
"context"
"fmt"
"log"

containertypes "github.com/docker/docker/api/types/container"
"github.com/docker/docker/client"
"github.com/microcks/microcks-cli/pkg/config"
"github.com/microcks/microcks-cli/pkg/connectors"
"github.com/microcks/microcks-cli/pkg/errors"
"github.com/spf13/cobra"
)

Expand All @@ -19,54 +18,60 @@ func NewStopCommand() *cobra.Command {
Long: "stop microcks instance",
Run: func(cmd *cobra.Command, args []string) {

cfg, err := config.LoadConfig(config.ConfigPath)
if err != nil {
log.Fatalf("Failed to load config: %v", err)
}
configFile, err := config.DefaultLocalConfigPath()
errors.CheckError(err)
localConfig, err := config.ReadLocalConfig(configFile)
errors.CheckError(err)

cli, err := createClient(cfg.Instance.Driver)

if err != nil {
fmt.Println(err)
if localConfig == nil {
fmt.Println("Config not found, nothing to stop")
return
}

stopContainer(cfg.Instance.ContainerID, cli)
ctx, err := localConfig.ResolveContext("")
errors.CheckError(err)
instance := ctx.Instance

cfg.Instance.Status = "Stopped"

if cfg.Instance.AutoRemove {
cfg.Instance = struct {
Name string "yaml:\"name\""
Image string "yaml:\"image\""
Status string "yaml:\"status\""
Port string "yaml:\"port\""
ContainerID string "yaml:\"containerID\""
AutoRemove bool "yaml:\"autoRemove\""
Driver string "yaml:\"driver\""
}{}
if instance.Name == "" {
fmt.Println("No instance is associated with this context")
return
}

err = config.SaveConfig(config.ConfigPath, cfg)
containerClient, err := connectors.NewContainerClient(instance.Driver)
errors.CheckError(err)
defer containerClient.CloseClient()

err = containerClient.StopContainer(instance.ContainerID)
if err != nil {
log.Fatalf("Failed to save config: %v", err)
log.Fatalf("Failed to stop a container: %v", err)
return
}

fmt.Println("Microcks stopped successfully...")
log.Printf("Instance %s stopped successfully", instance.Name)

// update configs

if instance.AutoRemove {
_, ok := localConfig.RemoveContext(ctx.Name)
if !ok {
log.Fatalf("Context %s does not exist", ctx.Name)
return
}
_ = localConfig.RemoveServer(ctx.Server.Server)
_ = localConfig.RemoveUser(ctx.User.Name)
_ = localConfig.RemoveAuth(ctx.Server.Server)
_ = localConfig.RemoveInstance(instance.Name)

localConfig.CurrentContext = ""
log.Printf("Instance %s removed successfully", instance.Name)
} else {
instance.Status = "Exited"
localConfig.UpsertInstance(instance)
log.Printf("Instance %s status update to Exited", instance.Name)
}
err = config.WriteLocalConfig(*localConfig, configFile)
errors.CheckError(err)
},
}

return stopCmd
}

func stopContainer(containerId string, cli *client.Client) {
ctx := context.Background()

fmt.Print("Stopping container ", containerId, "... ")
noWaitTimeout := 0 // to not wait for the container to exit gracefully
if err := cli.ContainerStop(ctx, containerId, containertypes.StopOptions{Timeout: &noWaitTimeout}); err != nil {
panic(err)
}
fmt.Println("Success")
}
Loading