Code cleanup, providing better commentary to decisions

This commit is contained in:
Dane Everitt 2022-01-30 12:56:25 -05:00
parent 0ec0fffa4d
commit c4ee82c4dc
4 changed files with 30 additions and 37 deletions

View File

@ -38,13 +38,13 @@ func (nw noopWriter) Write(b []byte) (int, error) {
} }
// Attach attaches to the docker container itself and ensures that we can pipe // Attach attaches to the docker container itself and ensures that we can pipe
// data in and out of the process stream. This should not be used for reading // data in and out of the process stream. This should always be called before
// console data as you *will* miss important output at the beginning because of // you have started the container, but after you've ensured it exists.
// the time delay with attaching to the output.
// //
// Calling this function will poll resources for the container in the background // Calling this function will poll resources for the container in the background
// until the provided context is canceled by the caller. Failure to cancel said // until the container is stopped. The context provided to this function is used
// context will cause background memory leaks as the goroutine will not exit. // for the purposes of attaching to the container, a seecond context is created
// within the function for managing polling.
func (e *Environment) Attach(ctx context.Context) error { func (e *Environment) Attach(ctx context.Context) error {
if e.IsAttached() { if e.IsAttached() {
return nil return nil

View File

@ -27,7 +27,6 @@ var _ environment.ProcessEnvironment = (*Environment)(nil)
type Environment struct { type Environment struct {
mu sync.RWMutex mu sync.RWMutex
eventMu sync.Once
// The public identifier for this environment. In this case it is the Docker container // The public identifier for this environment. In this case it is the Docker container
// name that will be used for all instances created under it. // name that will be used for all instances created under it.
@ -73,6 +72,7 @@ func New(id string, m *Metadata, c *environment.Configuration) (*Environment, er
meta: m, meta: m,
client: cli, client: cli,
st: system.NewAtomicString(environment.ProcessOfflineState), st: system.NewAtomicString(environment.ProcessOfflineState),
emitter: events.NewBus(),
} }
return e, nil return e, nil
@ -86,34 +86,33 @@ func (e *Environment) Type() string {
return "docker" return "docker"
} }
// Set if this process is currently attached to the process. // SetStream sets the current stream value from the Docker client. If a nil
// value is provided we assume that the stream is no longer operational and the
// instance is effectively offline.
func (e *Environment) SetStream(s *types.HijackedResponse) { func (e *Environment) SetStream(s *types.HijackedResponse) {
e.mu.Lock() e.mu.Lock()
defer e.mu.Unlock()
e.stream = s e.stream = s
e.mu.Unlock()
} }
// Determine if the this process is currently attached to the container. // IsAttached determine if the this process is currently attached to the
// container instance by checking if the stream is nil or not.
func (e *Environment) IsAttached() bool { func (e *Environment) IsAttached() bool {
e.mu.RLock() e.mu.RLock()
defer e.mu.RUnlock() defer e.mu.RUnlock()
return e.stream != nil return e.stream != nil
} }
// Events returns an event bus for the environment.
func (e *Environment) Events() *events.Bus { func (e *Environment) Events() *events.Bus {
e.eventMu.Do(func() {
e.emitter = events.NewBus()
})
return e.emitter return e.emitter
} }
// Determines if the container exists in this environment. The ID passed through should be the // Exists determines if the container exists in this environment. The ID passed
// server UUID since containers are created utilizing the server UUID as the name and docker // through should be the server UUID since containers are created utilizing the
// will work fine when using the container name as the lookup parameter in addition to the longer // server UUID as the name and docker will work fine when using the container
// ID auto-assigned when the container is created. // name as the lookup parameter in addition to the longer ID auto-assigned when
// the container is created.
func (e *Environment) Exists() (bool, error) { func (e *Environment) Exists() (bool, error) {
_, err := e.ContainerInspect(context.Background()) _, err := e.ContainerInspect(context.Background())
if err != nil { if err != nil {
@ -122,10 +121,8 @@ func (e *Environment) Exists() (bool, error) {
if client.IsErrNotFound(err) { if client.IsErrNotFound(err) {
return false, nil return false, nil
} }
return false, err return false, err
} }
return true, nil return true, nil
} }
@ -146,7 +143,7 @@ func (e *Environment) IsRunning(ctx context.Context) (bool, error) {
return c.State.Running, nil return c.State.Running, nil
} }
// Determine the container exit state and return the exit code and whether or not // ExitState returns the container exit state, the exit code and whether or not
// the container was killed by the OOM killer. // the container was killed by the OOM killer.
func (e *Environment) ExitState() (uint32, bool, error) { func (e *Environment) ExitState() (uint32, bool, error) {
c, err := e.ContainerInspect(context.Background()) c, err := e.ContainerInspect(context.Background())
@ -163,15 +160,13 @@ func (e *Environment) ExitState() (uint32, bool, error) {
if client.IsErrNotFound(err) { if client.IsErrNotFound(err) {
return 1, false, nil return 1, false, nil
} }
return 0, false, err return 0, false, err
} }
return uint32(c.State.ExitCode), c.State.OOMKilled, nil return uint32(c.State.ExitCode), c.State.OOMKilled, nil
} }
// Returns the environment configuration allowing a process to make modifications of the // Config returns the environment configuration allowing a process to make
// environment on the fly. // modifications of the environment on the fly.
func (e *Environment) Config() *environment.Configuration { func (e *Environment) Config() *environment.Configuration {
e.mu.RLock() e.mu.RLock()
defer e.mu.RUnlock() defer e.mu.RUnlock()
@ -179,12 +174,11 @@ func (e *Environment) Config() *environment.Configuration {
return e.Configuration return e.Configuration
} }
// Sets the stop configuration for the environment. // SetStopConfiguration sets the stop configuration for the environment.
func (e *Environment) SetStopConfiguration(c remote.ProcessStopConfiguration) { func (e *Environment) SetStopConfiguration(c remote.ProcessStopConfiguration) {
e.mu.Lock() e.mu.Lock()
defer e.mu.Unlock()
e.meta.Stop = c e.meta.Stop = c
e.mu.Unlock()
} }
func (e *Environment) SetImage(i string) { func (e *Environment) SetImage(i string) {

View File

@ -111,6 +111,13 @@ func (e *Environment) Start(ctx context.Context) error {
actx, cancel := context.WithTimeout(ctx, time.Second*30) actx, cancel := context.WithTimeout(ctx, time.Second*30)
defer cancel() defer cancel()
// You must attach to the instance _before_ you start the container. If you do this
// in the opposite order you'll enter a deadlock condition where we're attached to
// the instance successfully, but the container has already stopped and you'll get
// the entire program into a very confusing state.
//
// By explicitly attaching to the instance before we start it, we can immediately
// react to errors/output stopping/etc. when starting.
if err := e.Attach(actx); err != nil { if err := e.Attach(actx); err != nil {
return err return err
} }

View File

@ -239,14 +239,6 @@ func (s *Server) ReadLogfile(len int) ([]string, error) {
return s.Environment.Readlog(len) return s.Environment.Readlog(len)
} }
// Determine if the server is bootable in it's current state or not. This will not
// indicate why a server is not bootable, only if it is.
func (s *Server) IsBootable() bool {
exists, _ := s.Environment.Exists()
return exists
}
// Initializes a server instance. This will run through and ensure that the environment // Initializes a server instance. This will run through and ensure that the environment
// for the server is setup, and that all of the necessary files are created. // for the server is setup, and that all of the necessary files are created.
func (s *Server) CreateEnvironment() error { func (s *Server) CreateEnvironment() error {