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 return err
} }
Containers, Networks = p.Containers, p.Networks Containers, Networks = p.Containers, p.Networks
for i := range p.Containers { for i := range Containers {
p.Containers[i].Init(conn, Networks) Containers[i].Init(conn, Networks)
} }
slices.SortFunc(Containers, func(a, b container.Container) bool { slices.SortFunc(Containers, func(a, b container.Container) bool {
return a.Name < b.Name return a.Name < b.Name

View File

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