Skip to content

Commit 4440e1a

Browse files
committed
Add offline mode and ignore pull errors in case the image already exists
1 parent b5f3367 commit 4440e1a

File tree

5 files changed

+40
-9
lines changed

5 files changed

+40
-9
lines changed

launcher/internal/config/config.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@ func SetupWithName(configPath string, configName string) error {
2626
viper.AddConfigPath(".")
2727
viper.SetDefault("dataPath", configPath)
2828
viper.SetDefault("closeAfterLaunch", false)
29+
viper.SetDefault("offlineMode", false)
2930
viper.SetDefault("autostart.docker.path", util.GetDockerExecPath())
3031
viper.SetDefault("autostart.docker.enabled", runtime.GOOS == "darwin")
3132
viper.SetDefault("autostart.xserver.path", util.GetXserverExecPath())

launcher/internal/container/container.go

Lines changed: 35 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ import (
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
154158
func (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
243272
func (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{

launcher/internal/container/sasm.go

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -8,8 +8,6 @@ import (
88
"github.com/keinenclue/sasm-docker/launcher/internal/config"
99
)
1010

11-
const image string = "ghcr.io/keinenclue/sasm-docker"
12-
1311
// NewSasmContainer creates a new launchable sasm container
1412
func NewSasmContainer() (*LaunchableContainer, error) {
1513
containerEnv := []string{}
@@ -27,7 +25,7 @@ func NewSasmContainer() (*LaunchableContainer, error) {
2725
containerBinds = append(containerBinds, config.Get("dataPath").(string)+"/.config:/root/.config")
2826
containerBinds = append(containerBinds, config.Get("dataPath").(string)+"/Projects:/usr/share/sasm/Projects")
2927

30-
return newContainer(image, "sasm_docker_container", containerEnv, containerBinds, func(c *LaunchableContainer) {
28+
return newContainer("ghcr.io/keinenclue/sasm-docker", "sasm_docker_container", containerEnv, containerBinds, func(c *LaunchableContainer) {
3129
var e error
3230
if runtime.GOOS == "darwin" {
3331
c := exec.Command("/opt/X11/bin/xhost", "+localhost")

launcher/internal/gui/launchTab.go

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -127,6 +127,8 @@ func handleContainerEvent(app fyne.App, layerProgress map[string]*widget.Progres
127127
launchAppendLog("CONTAINER", event.Data.(string))
128128
case c.LogMessage:
129129
launchAppendLog("LOG", event.Data.(string))
130+
case c.ErrorMessage:
131+
launchAppendLog("ERROR", event.Data.(string))
130132
}
131133
}
132134
}

launcher/internal/gui/settingsTab.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@ func newSettingsTab(w fyne.Window) fyne.CanvasObject {
2020
c := newConfigSection(vBox)
2121
newPathConfig("dataPath", "Data path", w, c, false)
2222
newSwitchConfig("closeAfterLaunch", "Close after successfull launch", c)
23+
newSwitchConfig("offlineMode", "Offline mode", c)
2324

2425
c = newConfigSection(vBox)
2526
newSwitchConfig("autostart.docker.enabled", "Enable Docker autostart", c)

0 commit comments

Comments
 (0)