@@ -158,34 +158,20 @@ type legacyExecSession struct {
158
158
PID int `json:"pid"`
159
159
}
160
160
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 {
174
162
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 )
176
164
}
177
165
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 )
179
167
}
180
168
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 )
187
170
}
171
+ return nil
172
+ }
188
173
174
+ func (c * Container ) getUniqueExecSessionID () string {
189
175
// Generate an ID for our new exec session
190
176
sessionID := stringid .GenerateRandomID ()
191
177
found := true
@@ -202,20 +188,52 @@ func (c *Container) ExecCreate(config *ExecConfig) (string, error) {
202
188
sessionID = stringid .GenerateRandomID ()
203
189
}
204
190
}
191
+ return sessionID
192
+ }
205
193
206
- // Make our new exec session
194
+ func ( c * Container ) createExecSession ( config * ExecConfig ) ( * ExecSession , error ) {
207
195
session := new (ExecSession )
208
- session .Id = sessionID
196
+ session .Id = c . getUniqueExecSessionID ()
209
197
session .ContainerId = c .ID ()
210
198
session .State = define .ExecStateCreated
211
199
session .Config = new (ExecConfig )
212
200
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 )
214
202
}
215
203
216
204
if len (session .Config .ExitCommand ) > 0 {
217
205
session .Config .ExitCommand = append (session .Config .ExitCommand , []string {session .ID (), c .ID ()}... )
218
206
}
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
+ }
219
237
220
238
if c .state .ExecSessions == nil {
221
239
c .state .ExecSessions = make (map [string ]* ExecSession )
@@ -232,7 +250,7 @@ func (c *Container) ExecCreate(config *ExecConfig) (string, error) {
232
250
233
251
logrus .Infof ("Created exec session %s in container %s" , session .ID (), c .ID ())
234
252
235
- return sessionID , nil
253
+ return session . Id , nil
236
254
}
237
255
238
256
// ExecStart starts an exec session in the container, but does not attach to it.
@@ -775,6 +793,68 @@ func (c *Container) ExecResize(sessionID string, newSize resize.TerminalSize) er
775
793
return c .ociRuntime .ExecAttachResize (c , sessionID , newSize )
776
794
}
777
795
796
+ func (c * Container ) healthCheckExec (config * ExecConfig , streams * define.AttachStreams ) (int , error ) {
797
+ unlock := true
798
+ if ! c .batched {
799
+ c .lock .Lock ()
800
+ defer func () {
801
+ if unlock {
802
+ c .lock .Unlock ()
803
+ }
804
+ }()
805
+
806
+ if err := c .syncContainer (); err != nil {
807
+ return - 1 , err
808
+ }
809
+ }
810
+
811
+ if err := c .verifyExecConfig (config ); err != nil {
812
+ return - 1 , err
813
+ }
814
+
815
+ if ! c .ensureState (define .ContainerStateRunning ) {
816
+ return - 1 , fmt .Errorf ("can only create exec sessions on running containers: %w" , define .ErrCtrStateInvalid )
817
+ }
818
+
819
+ session , err := c .createExecSession (config )
820
+ if err != nil {
821
+ return - 1 , err
822
+ }
823
+
824
+ if c .state .ExecSessions == nil {
825
+ c .state .ExecSessions = make (map [string ]* ExecSession )
826
+ }
827
+ c .state .ExecSessions [session .ID ()] = session
828
+ defer delete (c .state .ExecSessions , session .ID ())
829
+
830
+ opts , err := prepareForExec (c , session )
831
+ if err != nil {
832
+ return - 1 , err
833
+ }
834
+ defer func () {
835
+ if err := c .cleanupExecBundle (session .ID ()); err != nil {
836
+ logrus .Errorf ("Container %s light exec session cleanup error: %v" , c .ID (), err )
837
+ }
838
+ }()
839
+
840
+ pid , attachErrChan , err := c .ociRuntime .ExecContainer (c , session .ID (), opts , streams , nil )
841
+ if err != nil {
842
+ return - 1 , err
843
+ }
844
+
845
+ if ! c .batched {
846
+ c .lock .Unlock ()
847
+ unlock = false
848
+ }
849
+
850
+ err = <- attachErrChan
851
+ if err != nil {
852
+ return - 1 , fmt .Errorf ("container %s light exec session with pid: %d error: %v" , c .ID (), pid , err )
853
+ }
854
+
855
+ return c .readExecExitCode (session .ID ())
856
+ }
857
+
778
858
func (c * Container ) Exec (config * ExecConfig , streams * define.AttachStreams , resize <- chan resize.TerminalSize ) (int , error ) {
779
859
return c .exec (config , streams , resize , false )
780
860
}
0 commit comments