Skip to content

Commit 3702839

Browse files
committed
fixes #108 feat: Add support for start and stop command
Signed-off-by: Harsh4902 <harshparmar4902@gmail.com>
1 parent c511571 commit 3702839

6 files changed

Lines changed: 463 additions & 2 deletions

File tree

cmd/cmd.go

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -46,4 +46,6 @@ func init() {
4646
rootCmd.AddCommand(NewVersionCommand())
4747
rootCmd.AddCommand(NewTestCommand())
4848
rootCmd.AddCommand(NewImportURLCommand())
49+
rootCmd.AddCommand(NewStartCommand())
50+
rootCmd.AddCommand(NewStopCommand())
4951
}

cmd/start.go

Lines changed: 143 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,143 @@
1+
package cmd
2+
3+
import (
4+
"context"
5+
"fmt"
6+
"io"
7+
"log"
8+
"os"
9+
10+
"github.com/docker/docker/api/types/container"
11+
"github.com/docker/docker/api/types/image"
12+
"github.com/docker/docker/client"
13+
"github.com/docker/go-connections/nat"
14+
"github.com/microcks/microcks-cli/pkg/config"
15+
"github.com/spf13/cobra"
16+
)
17+
18+
func NewStartCommand() *cobra.Command {
19+
var (
20+
hostIP string = "0.0.0.0"
21+
name string
22+
hostPort string
23+
imageName string
24+
autoRemove bool
25+
)
26+
var startCmd = &cobra.Command{
27+
Use: "start",
28+
Short: "start microcks instance",
29+
Example: `# Start a Microcks instance
30+
microcks start
31+
32+
# Define your port (by default 8585)
33+
microcks start --port [Port you want]`,
34+
Run: func(cmd *cobra.Command, args []string) {
35+
cfg, err := config.EnsureConfig(config.ConfigPath)
36+
37+
if err != nil {
38+
log.Fatalf("Error loading config: %v", err)
39+
}
40+
41+
if cfg.Instance.Status == "Running" {
42+
fmt.Println("Microcks is already running.")
43+
return
44+
}
45+
46+
if cfg.Instance.Status == "Stopped" {
47+
if err := startContainer(cfg.Instance.ContainerID); err != nil {
48+
fmt.Errorf("failed to start container: %v", err)
49+
}
50+
fmt.Println("Microcks started successfully...")
51+
return
52+
}
53+
54+
cfg.Instance.Name = name
55+
cfg.Instance.Image = imageName
56+
cfg.Instance.Port = hostPort
57+
cfg.Instance.AutoRemove = autoRemove
58+
59+
containerID, err := createContainer(cfg, hostIP)
60+
61+
if err != nil {
62+
log.Fatalf("Failed to create a container: %v", err)
63+
}
64+
cfg.Instance.ContainerID = containerID
65+
66+
if err := startContainer(cfg.Instance.ContainerID); err != nil {
67+
fmt.Errorf("failed to start container: %v", err)
68+
}
69+
70+
err = config.SaveConfig(config.ConfigPath, cfg)
71+
72+
if err != nil {
73+
log.Fatalf("Failed to save config: %v", err)
74+
}
75+
76+
fmt.Printf("Microcks started successfully...")
77+
},
78+
}
79+
startCmd.Flags().StringVar(&name, "name", "microcks", "name for you microcks instance")
80+
startCmd.Flags().StringVar(&hostPort, "port", "8585", "")
81+
startCmd.Flags().StringVar(&imageName, "image", "quay.io/microcks/microcks-uber:latest-native", "image which will be used to create a container")
82+
startCmd.Flags().BoolVar(&autoRemove, "rm", false, "mimic of '--rm' flag of dokcer to automatically remove the container when it exits")
83+
return startCmd
84+
}
85+
86+
func createContainer(cfg *config.Config, hostIP string) (string, error) {
87+
ctx := context.Background()
88+
cli, err := client.NewClientWithOpts(client.FromEnv, client.WithAPIVersionNegotiation())
89+
if err != nil {
90+
return "", err
91+
}
92+
defer cli.Close()
93+
94+
// Define exposed port and bindings
95+
exposedPort, _ := nat.NewPort("tcp", "8080")
96+
portBindings := nat.PortMap{
97+
exposedPort: []nat.PortBinding{
98+
{
99+
HostIP: hostIP,
100+
HostPort: cfg.Instance.Port,
101+
},
102+
},
103+
}
104+
105+
out, err := cli.ImagePull(ctx, cfg.Instance.Image, image.PullOptions{})
106+
if err != nil {
107+
return "", err
108+
}
109+
defer out.Close()
110+
io.Copy(os.Stdout, out)
111+
112+
resp, err := cli.ContainerCreate(
113+
ctx,
114+
&container.Config{
115+
Image: cfg.Instance.Image,
116+
ExposedPorts: nat.PortSet{exposedPort: struct{}{}},
117+
},
118+
&container.HostConfig{
119+
PortBindings: portBindings,
120+
AutoRemove: cfg.Instance.AutoRemove,
121+
}, nil, nil, cfg.Instance.Name)
122+
123+
if err != nil {
124+
return "", err
125+
}
126+
127+
return resp.ID, nil
128+
}
129+
130+
func startContainer(cotainerID string) error {
131+
ctx := context.Background()
132+
cli, err := client.NewClientWithOpts(client.FromEnv, client.WithAPIVersionNegotiation())
133+
if err != nil {
134+
return err
135+
}
136+
defer cli.Close()
137+
138+
if err := cli.ContainerStart(ctx, cotainerID, container.StartOptions{}); err != nil {
139+
panic(err)
140+
}
141+
142+
return nil
143+
}

cmd/stop.go

Lines changed: 69 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,69 @@
1+
package cmd
2+
3+
import (
4+
"context"
5+
"fmt"
6+
"log"
7+
8+
containertypes "github.com/docker/docker/api/types/container"
9+
"github.com/docker/docker/client"
10+
"github.com/microcks/microcks-cli/pkg/config"
11+
"github.com/spf13/cobra"
12+
)
13+
14+
func NewStopCommand() *cobra.Command {
15+
16+
var stopCmd = &cobra.Command{
17+
Use: "stop",
18+
Short: "stop microcks instance",
19+
Long: "stop microcks instance",
20+
Run: func(cmd *cobra.Command, args []string) {
21+
22+
cfg, err := config.LoadConfig(config.ConfigPath)
23+
if err != nil {
24+
log.Fatalf("Failed to load config: %v", err)
25+
}
26+
27+
stopContainer(cfg.Instance.ContainerID)
28+
29+
cfg.Instance.Status = "Stopped"
30+
31+
if cfg.Instance.AutoRemove {
32+
cfg.Instance = struct {
33+
Name string "yaml:\"name\""
34+
Image string "yaml:\"image\""
35+
Status string "yaml:\"status\""
36+
Port string "yaml:\"port\""
37+
ContainerID string "yaml:\"containerID\""
38+
AutoRemove bool "yaml:\"autoRemove\""
39+
}{}
40+
}
41+
42+
err = config.SaveConfig(config.ConfigPath, cfg)
43+
44+
if err != nil {
45+
log.Fatalf("Failed to save config: %v", err)
46+
}
47+
48+
fmt.Println("Microcks stopped successfully...")
49+
},
50+
}
51+
52+
return stopCmd
53+
}
54+
55+
func stopContainer(containerId string) {
56+
ctx := context.Background()
57+
cli, err := client.NewClientWithOpts(client.FromEnv, client.WithAPIVersionNegotiation())
58+
if err != nil {
59+
panic(err)
60+
}
61+
defer cli.Close()
62+
63+
fmt.Print("Stopping container ", containerId, "... ")
64+
noWaitTimeout := 0 // to not wait for the container to exit gracefully
65+
if err := cli.ContainerStop(ctx, containerId, containertypes.StopOptions{Timeout: &noWaitTimeout}); err != nil {
66+
panic(err)
67+
}
68+
fmt.Println("Success")
69+
}

go.mod

Lines changed: 37 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,40 @@
11
module github.com/microcks/microcks-cli
22

3-
go 1.12
3+
go 1.23.0
44

5-
require github.com/spf13/cobra v1.9.1
5+
toolchain go1.24.1
6+
7+
require (
8+
github.com/docker/docker v28.0.4+incompatible
9+
github.com/docker/go-connections v0.5.0
10+
github.com/spf13/cobra v1.9.1
11+
gopkg.in/yaml.v2 v2.4.0
12+
)
13+
14+
require (
15+
github.com/Microsoft/go-winio v0.4.14 // indirect
16+
github.com/containerd/log v0.1.0 // indirect
17+
github.com/distribution/reference v0.6.0 // indirect
18+
github.com/docker/go-units v0.5.0 // indirect
19+
github.com/felixge/httpsnoop v1.0.4 // indirect
20+
github.com/go-logr/logr v1.4.2 // indirect
21+
github.com/go-logr/stdr v1.2.2 // indirect
22+
github.com/gogo/protobuf v1.3.2 // indirect
23+
github.com/inconshreveable/mousetrap v1.1.0 // indirect
24+
github.com/moby/docker-image-spec v1.3.1 // indirect
25+
github.com/moby/term v0.5.2 // indirect
26+
github.com/morikuni/aec v1.0.0 // indirect
27+
github.com/opencontainers/go-digest v1.0.0 // indirect
28+
github.com/opencontainers/image-spec v1.1.1 // indirect
29+
github.com/pkg/errors v0.9.1 // indirect
30+
github.com/spf13/pflag v1.0.6 // indirect
31+
go.opentelemetry.io/auto/sdk v1.1.0 // indirect
32+
go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.60.0 // indirect
33+
go.opentelemetry.io/otel v1.35.0 // indirect
34+
go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.35.0 // indirect
35+
go.opentelemetry.io/otel/metric v1.35.0 // indirect
36+
go.opentelemetry.io/otel/trace v1.35.0 // indirect
37+
golang.org/x/sys v0.30.0 // indirect
38+
golang.org/x/time v0.11.0 // indirect
39+
gotest.tools/v3 v3.5.2 // indirect
40+
)

0 commit comments

Comments
 (0)