Skip to content

Commit a2e6f31

Browse files
committed
Run HealthCheck without creating and removing the ExecSession in the database
Signed-off-by: Jan Rodák <[email protected]>
1 parent 1194557 commit a2e6f31

File tree

2 files changed

+97
-26
lines changed

2 files changed

+97
-26
lines changed

Diff for: libpod/container_exec.go

+96-25
Original file line numberDiff line numberDiff line change
@@ -158,34 +158,20 @@ type legacyExecSession struct {
158158
PID int `json:"pid"`
159159
}
160160

161-
// ExecCreate creates a new exec session for the container.
162-
// The session is not started. The ID of the new exec session will be returned.
163-
func (c *Container) ExecCreate(config *ExecConfig) (string, error) {
164-
if !c.batched {
165-
c.lock.Lock()
166-
defer c.lock.Unlock()
167-
168-
if err := c.syncContainer(); err != nil {
169-
return "", err
170-
}
171-
}
172-
173-
// Verify our config
161+
func (c *Container) verifyExecConfig(config *ExecConfig) error {
174162
if config == nil {
175-
return "", fmt.Errorf("must provide a configuration to ExecCreate: %w", define.ErrInvalidArg)
163+
return fmt.Errorf("must provide a configuration to ExecCreate: %w", define.ErrInvalidArg)
176164
}
177165
if len(config.Command) == 0 {
178-
return "", fmt.Errorf("must provide a non-empty command to start an exec session: %w", define.ErrInvalidArg)
166+
return fmt.Errorf("must provide a non-empty command to start an exec session: %w", define.ErrInvalidArg)
179167
}
180168
if config.ExitCommandDelay > 0 && len(config.ExitCommand) == 0 {
181-
return "", fmt.Errorf("must provide a non-empty exit command if giving an exit command delay: %w", define.ErrInvalidArg)
182-
}
183-
184-
// Verify that we are in a good state to continue
185-
if !c.ensureState(define.ContainerStateRunning) {
186-
return "", fmt.Errorf("can only create exec sessions on running containers: %w", define.ErrCtrStateInvalid)
169+
return fmt.Errorf("must provide a non-empty exit command if giving an exit command delay: %w", define.ErrInvalidArg)
187170
}
171+
return nil
172+
}
188173

174+
func (c *Container) getUniqueExecSessionID() string {
189175
// Generate an ID for our new exec session
190176
sessionID := stringid.GenerateRandomID()
191177
found := true
@@ -202,20 +188,52 @@ func (c *Container) ExecCreate(config *ExecConfig) (string, error) {
202188
sessionID = stringid.GenerateRandomID()
203189
}
204190
}
191+
return sessionID
192+
}
205193

206-
// Make our new exec session
194+
func (c *Container) createExecSession(config *ExecConfig) (*ExecSession, error) {
207195
session := new(ExecSession)
208-
session.Id = sessionID
196+
session.Id = c.getUniqueExecSessionID()
209197
session.ContainerId = c.ID()
210198
session.State = define.ExecStateCreated
211199
session.Config = new(ExecConfig)
212200
if err := JSONDeepCopy(config, session.Config); err != nil {
213-
return "", fmt.Errorf("copying exec configuration into exec session: %w", err)
201+
return nil, fmt.Errorf("copying exec configuration into exec session: %w", err)
214202
}
215203

216204
if len(session.Config.ExitCommand) > 0 {
217205
session.Config.ExitCommand = append(session.Config.ExitCommand, []string{session.ID(), c.ID()}...)
218206
}
207+
return session, nil
208+
}
209+
210+
// ExecCreate creates a new exec session for the container.
211+
// The session is not started. The ID of the new exec session will be returned.
212+
func (c *Container) ExecCreate(config *ExecConfig) (string, error) {
213+
if !c.batched {
214+
c.lock.Lock()
215+
defer c.lock.Unlock()
216+
217+
if err := c.syncContainer(); err != nil {
218+
return "", err
219+
}
220+
}
221+
222+
// Verify our config
223+
if err := c.verifyExecConfig(config); err != nil {
224+
return "", err
225+
}
226+
227+
// Verify that we are in a good state to continue
228+
if !c.ensureState(define.ContainerStateRunning) {
229+
return "", fmt.Errorf("can only create exec sessions on running containers: %w", define.ErrCtrStateInvalid)
230+
}
231+
232+
// Make our new exec session
233+
session, err := c.createExecSession(config)
234+
if err != nil {
235+
return "", err
236+
}
219237

220238
if c.state.ExecSessions == nil {
221239
c.state.ExecSessions = make(map[string]*ExecSession)
@@ -232,7 +250,7 @@ func (c *Container) ExecCreate(config *ExecConfig) (string, error) {
232250

233251
logrus.Infof("Created exec session %s in container %s", session.ID(), c.ID())
234252

235-
return sessionID, nil
253+
return session.Id, nil
236254
}
237255

238256
// ExecStart starts an exec session in the container, but does not attach to it.
@@ -757,6 +775,59 @@ func (c *Container) ExecResize(sessionID string, newSize resize.TerminalSize) er
757775
return c.ociRuntime.ExecAttachResize(c, sessionID, newSize)
758776
}
759777

778+
func (c *Container) healthCheckExec(config *ExecConfig, streams *define.AttachStreams) (exitCode int, retErr error) {
779+
if !c.batched {
780+
c.lock.Lock()
781+
defer c.lock.Unlock()
782+
783+
if err := c.syncContainer(); err != nil {
784+
return -1, err
785+
}
786+
}
787+
788+
if err := c.verifyExecConfig(config); err != nil {
789+
return -1, err
790+
}
791+
792+
if !c.ensureState(define.ContainerStateRunning) {
793+
return -1, fmt.Errorf("can only create exec sessions on running containers: %w", define.ErrCtrStateInvalid)
794+
}
795+
796+
session, err := c.createExecSession(config)
797+
if err != nil {
798+
return -1, err
799+
}
800+
801+
if c.state.ExecSessions == nil {
802+
c.state.ExecSessions = make(map[string]*ExecSession)
803+
}
804+
c.state.ExecSessions[session.ID()] = session
805+
defer delete(c.state.ExecSessions, session.ID())
806+
807+
opts, err := prepareForExec(c, session)
808+
if err != nil {
809+
return -1, err
810+
}
811+
defer func() {
812+
if err := c.cleanupExecBundle(session.ID()); err != nil {
813+
logrus.Errorf("Container %s light exec session cleanup error: %v", c.ID(), err)
814+
}
815+
}()
816+
817+
pid, attachErrChan, err := c.ociRuntime.ExecContainer(c, session.ID(), opts, streams, nil)
818+
if err != nil {
819+
return -1, err
820+
}
821+
822+
err = <-attachErrChan
823+
if err != nil {
824+
logrus.Errorf("Container %s light exec session with pid: %d error: %v", c.ID(), pid, err)
825+
return -1, err
826+
}
827+
828+
return c.readExecExitCode(session.ID())
829+
}
830+
760831
func (c *Container) Exec(config *ExecConfig, streams *define.AttachStreams, resize <-chan resize.TerminalSize) (int, error) {
761832
return c.exec(config, streams, resize, false)
762833
}

Diff for: libpod/healthcheck.go

+1-1
Original file line numberDiff line numberDiff line change
@@ -97,7 +97,7 @@ func (c *Container) runHealthCheck(ctx context.Context, isStartup bool) (define.
9797
hcResult := define.HealthCheckSuccess
9898
config := new(ExecConfig)
9999
config.Command = newCommand
100-
exitCode, hcErr := c.exec(config, streams, nil, true)
100+
exitCode, hcErr := c.healthCheckExec(config, streams)
101101
if hcErr != nil {
102102
hcResult = define.HealthCheckFailure
103103
if errors.Is(hcErr, define.ErrOCIRuntimeNotFound) ||

0 commit comments

Comments
 (0)