Implement locking on cdata

This commit is contained in:
Joel Elkins 2022-08-15 02:32:27 -05:00
parent ee6abfd1bb
commit 4d1aa7117c
No known key found for this signature in database
GPG Key ID: 133589DC38921AE2
2 changed files with 28 additions and 15 deletions

View File

@ -118,8 +118,8 @@ func Init(conn context.Context) error {
return err
}
Containers, Networks = p.Containers, p.Networks
for i := range p.Containers {
p.Containers[i].Init(conn, Networks)
for i := range Containers {
Containers[i].Init(conn, Networks)
}
slices.SortFunc(Containers, func(a, b container.Container) bool {
return a.Name < b.Name

View File

@ -27,6 +27,7 @@ import (
"fmt"
"net"
"os/exec"
"sync"
cmd "gitea.elkins.co/Networking/ccl/internal/pkg/command"
"gitea.elkins.co/Networking/ccl/internal/pkg/network"
@ -61,6 +62,7 @@ type Container struct {
conn context.Context
cdata *define.InspectContainerData
cdataLock sync.Mutex
wasRunning bool
}
@ -105,19 +107,23 @@ func (c *Container) Init(conn context.Context, nets []network.Network) error {
return fmt.Errorf("conn is nil: %s", c.Name)
}
c.conn = conn
c.cdataLock.Lock()
defer c.cdataLock.Unlock()
err := c.populateCData()
c.wasRunning = err != nil && c.IsRunning()
c.wasRunning = c.IsRunning()
return err
}
func (c *Container) LogEntry() *log.Entry {
f := log.Fields{
"container": c.Name,
"wasRunning": c.wasRunning,
}
if c.cdata != nil && c.cdata.ID != "" {
f["id"] = c.cdata.ID[:12] + "…"
}
if c.cdata.State != nil {
if c.cdata != nil && c.cdata.State != nil {
f["state"] = c.cdata.State.Status
}
return log.WithFields(f)
@ -239,6 +245,8 @@ func (c *Container) CreateCommands() cmd.CommandSet {
}),
cmd.NewFunc("validate_spec", spec.Validate),
cmd.NewFunc("do_create", func() error {
c.cdataLock.Lock()
defer c.cdataLock.Unlock()
_, err := containers.CreateWithSpec(c.conn, &spec, nil)
if err != nil {
return err
@ -259,11 +267,15 @@ func (c *Container) RecreateCommands() cmd.CommandSet {
func (c *Container) RemoveCommands() cmd.CommandSet {
return c.newCommandSet("remove", cmd.Commands{
cmd.NewFunc("remove_if_exists", func() error {
c.cdataLock.Lock()
defer c.cdataLock.Unlock()
c.populateCData()
if c.cdata.ID == "" {
return nil
}
yes := true
_, err := containers.Remove(c.conn, c.cdata.ID, &containers.RemoveOptions{Force: &yes})
c.cdata = nil
return err
}),
})
@ -272,6 +284,9 @@ func (c *Container) RemoveCommands() cmd.CommandSet {
func (c *Container) StartCommands() cmd.CommandSet {
return c.newCommandSet("START", cmd.Commands{
cmd.NewFunc("start_container", func() error {
c.cdataLock.Lock()
defer c.cdataLock.Unlock()
c.populateCData()
if c.IsRunning() {
c.LogEntry().Debugln("Container start was commanded but it is already running. Not a problem.")
return nil
@ -327,18 +342,19 @@ func (c *Container) UpdateCommands() cmd.CommandSet {
}
func (c *Container) ConditionalStartCommands() cmd.CommandSet {
return c.newCommandSet("CONDSTART", cmd.Commands{
cmd.NewConditional("restart_if_was_running",
func() bool { return c.wasRunning },
cmd.NewSet(c.StartCommands()),
cmd.NewNop(),
),
if c.wasRunning {
return c.StartCommands()
}
return c.newCommandSet("NOP", cmd.Commands{
cmd.NewNop(),
})
}
func (c *Container) StopCommands() cmd.CommandSet {
return c.newCommandSet("STOP", cmd.Commands{
cmd.NewFunc("stop_if_running", func() error {
c.cdataLock.Lock()
defer c.cdataLock.Unlock()
if !c.IsRunning() {
c.LogEntry().Debugln("Container stop was commanded but it wasn't running. Not a problem.")
return nil
@ -362,14 +378,11 @@ func (c *Container) StopCommands() cmd.CommandSet {
}
func (c *Container) populateCData() error {
// TODO: locking?
c.cdata = nil
var err error
no := false
c.cdata, err = containers.Inspect(c.conn, c.Name, &containers.InspectOptions{Size: &no})
if err != nil {
return err
}
return nil
return err
}
func (c *Container) Pid() int {