refactor: container status constants
This commit is contained in:
parent
f5bfa62330
commit
e3ca34e8e0
2
.gitignore
vendored
2
.gitignore
vendored
@ -1,2 +1,2 @@
|
|||||||
/octoplex.log
|
*.log
|
||||||
/mediamtx.yml
|
/mediamtx.yml
|
||||||
|
@ -185,7 +185,7 @@ func (a *Client) RunContainer(ctx context.Context, params RunContainerParams) (<
|
|||||||
sendError(fmt.Errorf("container create: %w", err))
|
sendError(fmt.Errorf("container create: %w", err))
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
containerStateC <- domain.Container{ID: createResp.ID, State: "created"}
|
containerStateC <- domain.Container{ID: createResp.ID, Status: domain.ContainerStatusCreated}
|
||||||
|
|
||||||
if err = a.apiClient.NetworkConnect(ctx, a.networkID, createResp.ID, nil); err != nil {
|
if err = a.apiClient.NetworkConnect(ctx, a.networkID, createResp.ID, nil); err != nil {
|
||||||
sendError(fmt.Errorf("network connect: %w", err))
|
sendError(fmt.Errorf("network connect: %w", err))
|
||||||
@ -198,7 +198,7 @@ func (a *Client) RunContainer(ctx context.Context, params RunContainerParams) (<
|
|||||||
}
|
}
|
||||||
a.logger.Info("Started container", "id", shortID(createResp.ID), "duration", time.Since(now))
|
a.logger.Info("Started container", "id", shortID(createResp.ID), "duration", time.Since(now))
|
||||||
|
|
||||||
containerStateC <- domain.Container{ID: createResp.ID, State: "running"}
|
containerStateC <- domain.Container{ID: createResp.ID, Status: domain.ContainerStatusRunning}
|
||||||
|
|
||||||
a.runContainerLoop(ctx, createResp.ID, params.NetworkCountConfig, containerStateC, errC)
|
a.runContainerLoop(ctx, createResp.ID, params.NetworkCountConfig, containerStateC, errC)
|
||||||
}()
|
}()
|
||||||
@ -216,7 +216,7 @@ func (a *Client) pullImageIfNeeded(ctx context.Context, imageName string, contai
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
containerStateC <- domain.Container{State: "pulling"}
|
containerStateC <- domain.Container{Status: domain.ContainerStatusPulling}
|
||||||
|
|
||||||
pullReader, err := a.apiClient.ImagePull(ctx, imageName, image.PullOptions{})
|
pullReader, err := a.apiClient.ImagePull(ctx, imageName, image.PullOptions{})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@ -292,7 +292,7 @@ func (a *Client) runContainerLoop(
|
|||||||
}
|
}
|
||||||
}()
|
}()
|
||||||
|
|
||||||
state := &domain.Container{ID: containerID, State: "running"}
|
state := &domain.Container{ID: containerID, Status: domain.ContainerStatusRunning}
|
||||||
sendState := func() { stateC <- *state }
|
sendState := func() { stateC <- *state }
|
||||||
sendState()
|
sendState()
|
||||||
|
|
||||||
@ -308,7 +308,7 @@ func (a *Client) runContainerLoop(
|
|||||||
containerState = "exited"
|
containerState = "exited"
|
||||||
}
|
}
|
||||||
|
|
||||||
state.State = containerState
|
state.Status = containerState
|
||||||
state.CPUPercent = 0
|
state.CPUPercent = 0
|
||||||
state.MemoryUsageBytes = 0
|
state.MemoryUsageBytes = 0
|
||||||
state.HealthState = "unhealthy"
|
state.HealthState = "unhealthy"
|
||||||
@ -338,7 +338,7 @@ func (a *Client) runContainerLoop(
|
|||||||
}
|
}
|
||||||
|
|
||||||
if evt.Action == "start" {
|
if evt.Action == "start" {
|
||||||
state.State = "running"
|
state.Status = domain.ContainerStatusRunning
|
||||||
sendState()
|
sendState()
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
@ -89,10 +89,10 @@ func TestClientRunContainer(t *testing.T) {
|
|||||||
require.NoError(t, <-errC)
|
require.NoError(t, <-errC)
|
||||||
}()
|
}()
|
||||||
|
|
||||||
assert.Equal(t, "pulling", (<-containerStateC).State)
|
assert.Equal(t, "pulling", (<-containerStateC).Status)
|
||||||
assert.Equal(t, "created", (<-containerStateC).State)
|
assert.Equal(t, "created", (<-containerStateC).Status)
|
||||||
assert.Equal(t, "running", (<-containerStateC).State)
|
assert.Equal(t, "running", (<-containerStateC).Status)
|
||||||
assert.Equal(t, "running", (<-containerStateC).State)
|
assert.Equal(t, "running", (<-containerStateC).Status)
|
||||||
|
|
||||||
// Enough time for events channel to receive a message:
|
// Enough time for events channel to receive a message:
|
||||||
time.Sleep(100 * time.Millisecond)
|
time.Sleep(100 * time.Millisecond)
|
||||||
@ -100,7 +100,7 @@ func TestClientRunContainer(t *testing.T) {
|
|||||||
containerWaitC <- dockercontainer.WaitResponse{StatusCode: 1}
|
containerWaitC <- dockercontainer.WaitResponse{StatusCode: 1}
|
||||||
|
|
||||||
state := <-containerStateC
|
state := <-containerStateC
|
||||||
assert.Equal(t, "exited", state.State)
|
assert.Equal(t, "exited", state.Status)
|
||||||
assert.Equal(t, "unhealthy", state.HealthState)
|
assert.Equal(t, "unhealthy", state.HealthState)
|
||||||
require.NotNil(t, state.ExitCode)
|
require.NotNil(t, state.ExitCode)
|
||||||
assert.Equal(t, 1, *state.ExitCode)
|
assert.Equal(t, 1, *state.ExitCode)
|
||||||
@ -146,8 +146,8 @@ func TestClientRunContainerErrorStartingContainer(t *testing.T) {
|
|||||||
HostConfig: &dockercontainer.HostConfig{},
|
HostConfig: &dockercontainer.HostConfig{},
|
||||||
})
|
})
|
||||||
|
|
||||||
assert.Equal(t, "pulling", (<-containerStateC).State)
|
assert.Equal(t, "pulling", (<-containerStateC).Status)
|
||||||
assert.Equal(t, "created", (<-containerStateC).State)
|
assert.Equal(t, "created", (<-containerStateC).Status)
|
||||||
|
|
||||||
err = <-errC
|
err = <-errC
|
||||||
require.EqualError(t, err, "container start: error starting container")
|
require.EqualError(t, err, "container start: error starting container")
|
||||||
|
@ -9,6 +9,7 @@ import (
|
|||||||
"time"
|
"time"
|
||||||
|
|
||||||
"git.netflux.io/rob/octoplex/container"
|
"git.netflux.io/rob/octoplex/container"
|
||||||
|
"git.netflux.io/rob/octoplex/domain"
|
||||||
"git.netflux.io/rob/octoplex/shortid"
|
"git.netflux.io/rob/octoplex/shortid"
|
||||||
"git.netflux.io/rob/octoplex/testhelpers"
|
"git.netflux.io/rob/octoplex/testhelpers"
|
||||||
typescontainer "github.com/docker/docker/api/types/container"
|
typescontainer "github.com/docker/docker/api/types/container"
|
||||||
@ -196,11 +197,11 @@ func TestContainerRestart(t *testing.T) {
|
|||||||
testhelpers.ChanRequireNoError(t, errC)
|
testhelpers.ChanRequireNoError(t, errC)
|
||||||
|
|
||||||
containerState := <-containerStateC
|
containerState := <-containerStateC
|
||||||
assert.Equal(t, "pulling", containerState.State)
|
assert.Equal(t, "pulling", containerState.Status)
|
||||||
containerState = <-containerStateC
|
containerState = <-containerStateC
|
||||||
assert.Equal(t, "created", containerState.State)
|
assert.Equal(t, "created", containerState.Status)
|
||||||
containerState = <-containerStateC
|
containerState = <-containerStateC
|
||||||
assert.Equal(t, "running", containerState.State)
|
assert.Equal(t, "running", containerState.Status)
|
||||||
|
|
||||||
err = nil // reset error
|
err = nil // reset error
|
||||||
done := make(chan struct{})
|
done := make(chan struct{})
|
||||||
@ -210,9 +211,9 @@ func TestContainerRestart(t *testing.T) {
|
|||||||
var count int
|
var count int
|
||||||
for {
|
for {
|
||||||
containerState = <-containerStateC
|
containerState = <-containerStateC
|
||||||
if containerState.State == "restarting" {
|
if containerState.Status == domain.ContainerStatusRestarting {
|
||||||
break
|
break
|
||||||
} else if containerState.State == "exited" {
|
} else if containerState.Status == domain.ContainerStatusExited {
|
||||||
err = errors.New("container exited unexpectedly")
|
err = errors.New("container exited unexpectedly")
|
||||||
} else if count >= 5 {
|
} else if count >= 5 {
|
||||||
err = errors.New("container did not enter restarting state")
|
err = errors.New("container did not enter restarting state")
|
||||||
|
@ -55,13 +55,24 @@ type Destination struct {
|
|||||||
URL string
|
URL string
|
||||||
}
|
}
|
||||||
|
|
||||||
// Container represents the current state of an individual container.
|
// Container status strings.
|
||||||
//
|
//
|
||||||
// The source of truth is always the Docker daemon, this struct is used only
|
// TODO: refactor to strictly reflect Docker status strings.
|
||||||
// for passing asynchronous state.
|
const (
|
||||||
|
ContainerStatusPulling = "pulling" // Does not correspond to a Docker status.
|
||||||
|
ContainerStatusCreated = "created"
|
||||||
|
ContainerStatusRunning = "running"
|
||||||
|
ContainerStatusPaused = "paused"
|
||||||
|
ContainerStatusRestarting = "restarting"
|
||||||
|
ContainerStatusRemoving = "removing"
|
||||||
|
ContainerStatusExited = "exited"
|
||||||
|
ContainerStatusDead = "dead"
|
||||||
|
)
|
||||||
|
|
||||||
|
// Container represents the current state of an individual container.
|
||||||
type Container struct {
|
type Container struct {
|
||||||
ID string
|
ID string
|
||||||
State string
|
Status string
|
||||||
HealthState string
|
HealthState string
|
||||||
CPUPercent float64
|
CPUPercent float64
|
||||||
MemoryUsageBytes uint64
|
MemoryUsageBytes uint64
|
||||||
|
@ -172,7 +172,7 @@ func (s *Actor) actorLoop(containerStateC <-chan domain.Container, errC <-chan e
|
|||||||
case containerState := <-containerStateC:
|
case containerState := <-containerStateC:
|
||||||
s.state.Container = containerState
|
s.state.Container = containerState
|
||||||
|
|
||||||
if s.state.Container.State == "exited" {
|
if s.state.Container.Status == domain.ContainerStatusExited {
|
||||||
fetchStateT.Stop()
|
fetchStateT.Stop()
|
||||||
s.handleContainerExit(nil)
|
s.handleContainerExit(nil)
|
||||||
}
|
}
|
||||||
|
@ -146,7 +146,7 @@ func (a *Actor) destLoop(url string, containerStateC <-chan domain.Container, er
|
|||||||
case containerState := <-containerStateC:
|
case containerState := <-containerStateC:
|
||||||
state.Container = containerState
|
state.Container = containerState
|
||||||
|
|
||||||
if containerState.State == "running" {
|
if containerState.Status == "running" {
|
||||||
if hasElapsedSince(5*time.Second, containerState.RxSince) {
|
if hasElapsedSince(5*time.Second, containerState.RxSince) {
|
||||||
state.Status = domain.DestinationStatusLive
|
state.Status = domain.DestinationStatusLive
|
||||||
} else {
|
} else {
|
||||||
|
@ -326,7 +326,7 @@ func (ui *UI) redrawFromState(state domain.AppState) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
ui.sourceViews.status.SetText("[black:green]receiving" + durStr)
|
ui.sourceViews.status.SetText("[black:green]receiving" + durStr)
|
||||||
} else if state.Source.Container.State == "running" && state.Source.Container.HealthState == "healthy" {
|
} else if state.Source.Container.Status == domain.ContainerStatusRunning && state.Source.Container.HealthState == "healthy" {
|
||||||
ui.sourceViews.status.SetText("[black:yellow]ready")
|
ui.sourceViews.status.SetText("[black:yellow]ready")
|
||||||
} else {
|
} else {
|
||||||
ui.sourceViews.status.SetText("[white:red]not ready")
|
ui.sourceViews.status.SetText("[white:red]not ready")
|
||||||
@ -335,19 +335,19 @@ func (ui *UI) redrawFromState(state domain.AppState) {
|
|||||||
ui.sourceViews.health.SetText("[white]" + cmp.Or(rightPad(state.Source.Container.HealthState, 9), dash))
|
ui.sourceViews.health.SetText("[white]" + cmp.Or(rightPad(state.Source.Container.HealthState, 9), dash))
|
||||||
|
|
||||||
cpuPercent := dash
|
cpuPercent := dash
|
||||||
if state.Source.Container.State == "running" {
|
if state.Source.Container.Status == domain.ContainerStatusRunning {
|
||||||
cpuPercent = fmt.Sprintf("%.1f", state.Source.Container.CPUPercent)
|
cpuPercent = fmt.Sprintf("%.1f", state.Source.Container.CPUPercent)
|
||||||
}
|
}
|
||||||
ui.sourceViews.cpu.SetText("[white]" + cpuPercent)
|
ui.sourceViews.cpu.SetText("[white]" + cpuPercent)
|
||||||
|
|
||||||
memUsage := dash
|
memUsage := dash
|
||||||
if state.Source.Container.State == "running" {
|
if state.Source.Container.Status == domain.ContainerStatusRunning {
|
||||||
memUsage = fmt.Sprintf("%.1f", float64(state.Source.Container.MemoryUsageBytes)/1024/1024)
|
memUsage = fmt.Sprintf("%.1f", float64(state.Source.Container.MemoryUsageBytes)/1024/1024)
|
||||||
}
|
}
|
||||||
ui.sourceViews.mem.SetText("[white]" + memUsage)
|
ui.sourceViews.mem.SetText("[white]" + memUsage)
|
||||||
|
|
||||||
rxRate := dash
|
rxRate := dash
|
||||||
if state.Source.Container.State == "running" {
|
if state.Source.Container.Status == domain.ContainerStatusRunning {
|
||||||
rxRate = fmt.Sprintf("%d", state.Source.Container.RxRate)
|
rxRate = fmt.Sprintf("%d", state.Source.Container.RxRate)
|
||||||
}
|
}
|
||||||
ui.sourceViews.rx.SetText("[white]" + rxRate)
|
ui.sourceViews.rx.SetText("[white]" + rxRate)
|
||||||
@ -385,7 +385,7 @@ func (ui *UI) redrawFromState(state domain.AppState) {
|
|||||||
ui.destView.SetCell(i+1, 2, tview.NewTableCell("[white]"+rightPad("off-air", statusLen)))
|
ui.destView.SetCell(i+1, 2, tview.NewTableCell("[white]"+rightPad("off-air", statusLen)))
|
||||||
}
|
}
|
||||||
|
|
||||||
ui.destView.SetCell(i+1, 3, tview.NewTableCell("[white]"+rightPad(cmp.Or(dest.Container.State, dash), 10)))
|
ui.destView.SetCell(i+1, 3, tview.NewTableCell("[white]"+rightPad(cmp.Or(dest.Container.Status, dash), 10)))
|
||||||
|
|
||||||
healthState := dash
|
healthState := dash
|
||||||
if dest.Status == domain.DestinationStatusLive {
|
if dest.Status == domain.DestinationStatusLive {
|
||||||
@ -394,19 +394,19 @@ func (ui *UI) redrawFromState(state domain.AppState) {
|
|||||||
ui.destView.SetCell(i+1, 4, tview.NewTableCell("[white]"+rightPad(healthState, 7)))
|
ui.destView.SetCell(i+1, 4, tview.NewTableCell("[white]"+rightPad(healthState, 7)))
|
||||||
|
|
||||||
cpuPercent := dash
|
cpuPercent := dash
|
||||||
if dest.Container.State == "running" {
|
if dest.Container.Status == domain.ContainerStatusRunning {
|
||||||
cpuPercent = fmt.Sprintf("%.1f", dest.Container.CPUPercent)
|
cpuPercent = fmt.Sprintf("%.1f", dest.Container.CPUPercent)
|
||||||
}
|
}
|
||||||
ui.destView.SetCell(i+1, 5, tview.NewTableCell("[white]"+rightPad(cpuPercent, 4)))
|
ui.destView.SetCell(i+1, 5, tview.NewTableCell("[white]"+rightPad(cpuPercent, 4)))
|
||||||
|
|
||||||
memoryUsage := dash
|
memoryUsage := dash
|
||||||
if dest.Container.State == "running" {
|
if dest.Container.Status == domain.ContainerStatusRunning {
|
||||||
memoryUsage = fmt.Sprintf("%.1f", float64(dest.Container.MemoryUsageBytes)/1000/1000)
|
memoryUsage = fmt.Sprintf("%.1f", float64(dest.Container.MemoryUsageBytes)/1000/1000)
|
||||||
}
|
}
|
||||||
ui.destView.SetCell(i+1, 6, tview.NewTableCell("[white]"+rightPad(memoryUsage, 4)))
|
ui.destView.SetCell(i+1, 6, tview.NewTableCell("[white]"+rightPad(memoryUsage, 4)))
|
||||||
|
|
||||||
txRate := dash
|
txRate := dash
|
||||||
if dest.Container.State == "running" {
|
if dest.Container.Status == domain.ContainerStatusRunning {
|
||||||
txRate = "[white]" + rightPad(strconv.Itoa(dest.Container.TxRate), 4)
|
txRate = "[white]" + rightPad(strconv.Itoa(dest.Container.TxRate), 4)
|
||||||
}
|
}
|
||||||
ui.destView.SetCell(i+1, 7, tview.NewTableCell(txRate))
|
ui.destView.SetCell(i+1, 7, tview.NewTableCell(txRate))
|
||||||
|
Loading…
x
Reference in New Issue
Block a user