-
Notifications
You must be signed in to change notification settings - Fork 7
/
containersstate.go
149 lines (116 loc) · 3.73 KB
/
containersstate.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
147
148
149
package container
import (
"fmt"
"github.com/flexkube/libflexkube/pkg/container/runtime/docker"
"github.com/flexkube/libflexkube/pkg/container/types"
)
const (
// StatusMissing is a value, which is set to ContainerStatus.Status field,
// if stored container ID is not found.
StatusMissing = "gone"
)
// ContainersStateInterface represents 'constainersState' capabilities.
type ContainersStateInterface interface {
// CheckState updates the state of all previously configured containers
// and their configuration on the host
CheckState() error
// RemoveContainer removes the container by ID.
RemoveContainer(containerName string) error
// CreateAndStart is a helper, which creates and spawns given container.
CreateAndStart(containerName string) error
// Export converts unexported containersState to exported type, so it can be serialized and stored.
Export() ContainersState
}
// ContainersState represents states of multiple containers.
type ContainersState map[string]*HostConfiguredContainer
// containerState is a validated version of ContainersState, which can be used to perform operations.
type containersState map[string]*hostConfiguredContainer
// New validates ContainersState struct and returns operational containerState.
func (s ContainersState) New() (ContainersStateInterface, error) {
if s == nil {
s = ContainersState{}
}
state := containersState{}
for name, container := range s {
m, err := container.New()
if err != nil {
return nil, err
}
state[name] = m.(*hostConfiguredContainer)
}
return state, nil
}
// CheckState updates the state of all previously configured containers
// and their configuration on the host.
func (s containersState) CheckState() error {
for _, hcc := range s {
if err := hcc.Status(); err != nil {
return err
}
if hcc.container.Status().ID == "" {
hcc.container.SetStatus(types.ContainerStatus{
Status: StatusMissing,
})
}
if err := hcc.ConfigurationStatus(); err != nil {
return err
}
}
return nil
}
// RemoveContainer removes the container by ID.
func (s containersState) RemoveContainer(containerName string) error {
if _, exists := s[containerName]; !exists {
return fmt.Errorf("can't remove non-existing container")
}
status := s[containerName].container.Status()
if status.Running() || status.Restarting() {
if err := s[containerName].Stop(); err != nil {
return fmt.Errorf("failed stopping container: %w", err)
}
}
if s[containerName].container.Status().Exists() {
if err := s[containerName].Delete(); err != nil {
return fmt.Errorf("failed removing container: %w", err)
}
}
delete(s, containerName)
return nil
}
// CreateAndStart is a helper, which creates and spawns given container.
func (s containersState) CreateAndStart(containerName string) error {
if _, exists := s[containerName]; !exists {
return fmt.Errorf("can't create non-existing container")
}
if err := s[containerName].Create(); err != nil {
return fmt.Errorf("failed creating new container: %w", err)
}
if err := s[containerName].Start(); err != nil {
return fmt.Errorf("failed starting container: %w", err)
}
return nil
}
// Export converts unexported containersState to exported type, so it can be serialized and stored.
func (s containersState) Export() ContainersState {
cs := ContainersState{}
for i, m := range s {
h := &HostConfiguredContainer{
Container: Container{
Config: m.container.Config(),
Runtime: RuntimeConfig{
Docker: m.container.RuntimeConfig().(*docker.Config),
},
},
Host: m.host,
ConfigFiles: m.configFiles,
}
if s := m.container.Status(); s.ID != "" && s.Status != "" {
h.Container.Status = s
}
if h.ConfigFiles == nil {
h.ConfigFiles = map[string]string{}
}
cs[i] = h
}
return cs
}