-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathinspect.go
146 lines (135 loc) · 4.95 KB
/
inspect.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
package rove
import (
"encoding/json"
"fmt"
"io"
"strings"
"time"
"github.com/alessio/shellescape"
)
type InspectCommand struct {
Name string `arg:"" name:"name" help:"Name of service or task."`
ConfigFile string `flag:"" name:"config" help:"Config file." type:"path" default:".rove"`
Local bool `flag:"" name:"local" help:"Skip SSH and run on local machine."`
Machine string `flag:"" name:"machine" help:"Name of machine." default:""`
Json bool `flag:"" name:"json"`
}
func (cmd *InspectCommand) Do(conn SshRunner, stdin io.Reader) error {
return conn.
Run(fmt.Sprint("docker service inspect --format json ", cmd.Name), func(res string) error {
if cmd.Json {
var dockerInspect []map[string]any
if err := json.Unmarshal([]byte(res), &dockerInspect); err != nil {
fmt.Println("🚫 Could not parse docker service inspect JSON:\n", res)
return err
}
if len(dockerInspect) < 1 {
return fmt.Errorf("empty docker service inspect JSON: %s", dockerInspect)
}
out, err := json.MarshalIndent(dockerInspect[0], "", " ")
if err != nil {
fmt.Println("🚫 Could not format JSON:\n", dockerInspect[0])
return err
}
fmt.Println(string(out))
} else {
var dockerInspect []DockerServiceInspectJson
if err := json.Unmarshal([]byte(res), &dockerInspect); err != nil {
fmt.Println("🚫 Could not parse docker service inspect JSON:\n", res)
return err
}
old := &ServiceState{}
old.Env = dockerInspect[0].Spec.TaskTemplate.ContainerSpec.Env
// TODO: Mounts
// Networks
networksExisting := make([]string, 0)
networksExistingIds := make([]string, 0)
for _, network := range dockerInspect[0].Spec.TaskTemplate.Networks {
networksExistingIds = append(networksExistingIds, network.Target)
}
if len(networksExistingIds) > 0 {
commandNetworks := ShellCommand{
Name: "docker network ls --format json --no-trunc",
}
for _, networkId := range networksExistingIds {
commandNetworks.Flags = append(commandNetworks.Flags, ShellFlag{
Check: networkId != "",
Name: "filter",
Value: shellescape.Quote("id=" + networkId),
})
}
errNetwork := conn.
Run(commandNetworks.String(), func(resNetworks string) error {
for _, line := range strings.Split(strings.ReplaceAll(resNetworks, "\r\n", "\n"), "\n") {
if line != "" {
var dockerNetworkLs DockerNetworkLsJson
if err := json.Unmarshal([]byte(line), &dockerNetworkLs); err != nil {
fmt.Println("🚫 Could not parse docker network ls JSON:\n", line)
return err
}
networksExisting = append(networksExisting, dockerNetworkLs.Name)
}
}
return nil
}).
Error()
if errNetwork != nil {
return errNetwork
}
}
// Ports
portsExisting := make([]string, 0)
for _, entry := range dockerInspect[0].Spec.EndpointSpec.Ports {
port := fmt.Sprintf("%d:%d", entry.TargetPort, entry.PublishedPort)
portsExisting = append(portsExisting, port)
}
// Secrets
secretsExisting := make([]string, 0)
for _, secret := range dockerInspect[0].Spec.TaskTemplate.ContainerSpec.Secrets {
secretsExisting = append(secretsExisting, secret.SecretName)
}
old.Command = dockerInspect[0].Spec.TaskTemplate.ContainerSpec.Args
old.Image = strings.Split(dockerInspect[0].Spec.TaskTemplate.ContainerSpec.Image, "@")[0]
old.Init = dockerInspect[0].Spec.TaskTemplate.ContainerSpec.Init
old.Networks = networksExisting
old.Publish = portsExisting
old.Replicas = fmt.Sprint(dockerInspect[0].Spec.Mode.Replicated.Replicas)
old.Secrets = secretsExisting
if dockerInspect[0].Spec.UpdateConfig.Delay != 0 {
delayNs, _ := time.ParseDuration(fmt.Sprint(dockerInspect[0].Spec.UpdateConfig.Delay, "ns"))
old.UpdateDelay, _ = strings.CutSuffix(delayNs.String(), "m0s")
}
old.UpdateFailureAction = dockerInspect[0].Spec.UpdateConfig.FailureAction
if old.UpdateFailureAction == "pause" {
old.UpdateFailureAction = ""
}
old.UpdateOrder = dockerInspect[0].Spec.UpdateConfig.Order
if old.UpdateOrder == "stop-first" {
old.UpdateOrder = ""
}
old.UpdateParallelism = fmt.Sprint(dockerInspect[0].Spec.UpdateConfig.Parallelism)
if old.UpdateParallelism == "1" {
old.UpdateParallelism = ""
}
old.User = dockerInspect[0].Spec.TaskTemplate.ContainerSpec.User
old.WorkDir = dockerInspect[0].Spec.TaskTemplate.ContainerSpec.Dir
diffText, _ := old.Diff(old)
fmt.Printf("\nCurrent state of %s:\n\n", cmd.Name)
fmt.Printf(" service %s:\n", cmd.Name)
fmt.Print(diffText, "\n\n")
}
return nil
}).
OnError(func(err error) error {
if err != nil {
fmt.Println("🚫 Could not inspect service")
}
return err
}).
Error()
}
func (cmd *InspectCommand) Run() error {
return Database(cmd.ConfigFile, func() error {
return SshMachineByName(cmd.Local, cmd.Machine, cmd.Do)
})
}