44 "bufio"
55 "context"
66 "encoding/json"
7+ "errors"
78 "fmt"
89 "io"
910 "strings"
@@ -13,6 +14,7 @@ import (
1314 "github.com/docker/docker/api/types"
1415 "github.com/docker/docker/api/types/container"
1516 "github.com/docker/docker/client"
17+ "github.com/keinenclue/sasm-docker/launcher/internal/config"
1618 "github.com/pterodactyl/wings/system"
1719)
1820
@@ -92,6 +94,8 @@ const (
9294 ConsoleOutput
9395 // LogMessage means there was some important log from docker
9496 LogMessage
97+ // ErrorMessage means there was some error log from docker
98+ ErrorMessage
9599)
96100
97101// OnContainerEventFuc is the type of a callback function which gets called on every container event
@@ -153,14 +157,17 @@ func newContainer(image string, containerID string, containerEnv []string, conta
153157// Launch launches the container
154158func (c * LaunchableContainer ) Launch () error {
155159 var err error
160+ var imageExists bool
161+ offlineMode := config .Get ("offlineMode" ).(bool )
162+
156163 c .setState (LaunchingState )
157164 c .isLaunching = true
158165
159166 defer func () {
160167 c .isLaunching = false
161168 if err != nil {
162169 c .handleContainerEvent (Event {
163- Type : LogMessage ,
170+ Type : ErrorMessage ,
164171 Data : err .Error (),
165172 })
166173 c .setState (OfflineState )
@@ -179,8 +186,14 @@ func (c *LaunchableContainer) Launch() error {
179186 return err
180187 }
181188
182- if err = c .Pull (); err != nil {
189+ imageExists , _ = c .ImageExists ()
190+ if ! imageExists && offlineMode {
191+ err = errors .New ("The image is not pulled yet and offline mode is enabled! Please disable offline mode and try again!" )
183192 return err
193+ } else if ! offlineMode {
194+ if err = c .Pull (); err != nil && ! imageExists {
195+ return err
196+ }
184197 }
185198
186199 if err = c .Start (); err != nil {
@@ -199,7 +212,7 @@ func (c *LaunchableContainer) WaitForDockerDaemon() error {
199212 var err error
200213 var retryCount = 0
201214
202- _ , err = dockerClient .ContainerList (context . Background () , types.ContainerListOptions {})
215+ _ , err = dockerClient .ContainerList (ctx , types.ContainerListOptions {})
203216 for err != nil && (client .IsErrConnectionFailed (err ) ||
204217 strings .HasSuffix (err .Error (), "connection refused" )) && retryCount < 12 {
205218 retryCount ++
@@ -211,7 +224,7 @@ func (c *LaunchableContainer) WaitForDockerDaemon() error {
211224 Type : LogMessage ,
212225 Data : fmt .Sprintf ("Waiting for the docker daemon to start, tried %d times to connect" , retryCount ),
213226 })
214- _ , err = dockerClient .ContainerList (context . Background () , types.ContainerListOptions {})
227+ _ , err = dockerClient .ContainerList (ctx , types.ContainerListOptions {})
215228 time .Sleep (time .Second * 5 )
216229 }
217230
@@ -239,12 +252,28 @@ func (c *LaunchableContainer) Remove() error {
239252 return nil
240253}
241254
255+ // ImageExists checks if the image exists
256+ func (c * LaunchableContainer ) ImageExists () (bool , error ) {
257+ images , err := dockerClient .ImageList (ctx , types.ImageListOptions {})
258+ if err != nil {
259+ return false , err
260+ }
261+
262+ for _ , image := range images {
263+ if len (image .RepoTags ) > 0 && (image .RepoTags [0 ] == c .image || image .RepoTags [0 ] == c .image + ":latest" ) {
264+ return true , nil
265+ }
266+ }
267+
268+ return false , nil
269+ }
270+
242271// Pull pulls the container
243272func (c * LaunchableContainer ) Pull () error {
244273 c .setState (PullingState )
245274 defer c .setState (OfflineState )
246275
247- reader , err := dockerClient .ImagePull (ctx , image , types.ImagePullOptions {})
276+ reader , err := dockerClient .ImagePull (ctx , c . image , types.ImagePullOptions {})
248277 if err != nil {
249278 return err
250279 }
@@ -275,7 +304,7 @@ func (c *LaunchableContainer) Start() error {
275304 cont , err := dockerClient .ContainerCreate (
276305 ctx ,
277306 & container.Config {
278- Image : image ,
307+ Image : c . image ,
279308 Env : c .containerEnv ,
280309 },
281310 & container.HostConfig {
0 commit comments