Skip to content

Commit 8e137ca

Browse files
committed
fix: Fixed Dockerfile not starting Server; fix: Fixed Wrong permissions for mounts; fix: Fixed permission for socket access; feat: added capability to use non-socket api endpoints; Added multiple alternative ctor for WolfApi.Api;
1 parent 526a860 commit 8e137ca

File tree

14 files changed

+137
-112
lines changed

14 files changed

+137
-112
lines changed

WolfApi/Api.cs

Lines changed: 51 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -1,38 +1,45 @@
1-
using System.Diagnostics.CodeAnalysis;
2-
using System.Threading.RateLimiting;
3-
41
namespace WolfApi;
52

3+
using Microsoft.Extensions.Logging.Abstractions;
64
using Microsoft.Extensions.Configuration;
75
using System.Collections.Concurrent;
86
using NSwagWolfApi;
97
using NSwagDocker;
108
using System.Net.Sockets;
119
using Microsoft.Extensions.Hosting;
1210
using Microsoft.Extensions.Logging;
11+
using System.Diagnostics.CodeAnalysis;
12+
using System.Threading.RateLimiting;
1313

14-
public partial class Api : IHostedService, IApiEventPublisher
14+
public partial class Api : IHostedService
1515
{
1616
public NSwagDocker DockerApi { get; }
1717
public NSwagWolfApi WolfApi { get; }
1818
private readonly ILogger<Api> _logger;
1919
private readonly HttpClient _httpClient;
2020

21+
public string WolfSocketPath { get; set; } = "unix:///etc/wolf/cfg/wolf.sock";
22+
public string BaseAddress { get; set; } = "http://localhost/api/v1/";
23+
2124
public ConcurrentQueue<Profile>? Profiles { get; private set; }
25+
26+
public Api() : this(NullLogger<Api>.Instance) { }
2227

28+
public Api(ILogger<Api> logger) :
29+
this(logger,
30+
new ConfigurationBuilder()
31+
.AddInMemoryCollection(new Dictionary<string, string>
32+
{
33+
{"SOCKET_PATH", "/etc/wolf/cfg/wolf.sock"}
34+
}!).Build())
35+
{ }
2336

24-
// ReSharper disable once ConvertToPrimaryConstructor
25-
public Api(WolfApiHttpClient httpClient, ILogger<Api> logger)
26-
{
27-
DockerApi = new(httpClient);
28-
WolfApi = new(httpClient);
29-
_httpClient = httpClient;
30-
_logger = logger;
31-
}
37+
public Api(IConfiguration config) : this(NullLogger<Api>.Instance, config) { }
3238

3339
public Api(ILogger<Api> logger, IConfiguration configuration)
3440
{
35-
configuration.GetValue<string>("SOCKET_PATH");
41+
var socketPath = configuration.GetValue<string?>("SOCKET_PATH") ?? WolfSocketPath;
42+
BaseAddress = configuration.GetValue<string?>("BASE_ADDRESS") ?? BaseAddress;
3643

3744
var options = new TokenBucketRateLimiterOptions
3845
{
@@ -44,29 +51,41 @@ public Api(ILogger<Api> logger, IConfiguration configuration)
4451
AutoReplenishment = true
4552
};
4653

47-
_httpClient = new HttpClient(
48-
handler: new ClientSideRateLimitedHandler(
49-
limiter: new TokenBucketRateLimiter(options),
50-
httpMessageHandler: new SocketsHttpHandler
51-
{
52-
ConnectCallback = async (_, token) =>
54+
if (socketPath.StartsWith("unix://"))
55+
{
56+
socketPath = socketPath["unix://".Length..];
57+
_httpClient = new HttpClient(
58+
handler: new ClientSideRateLimitedHandler(
59+
limiter: new TokenBucketRateLimiter(options),
60+
httpMessageHandler: new SocketsHttpHandler
5361
{
54-
var endpointPath = Environment.GetEnvironmentVariable("WOLF_SOCKET_PATH") ??
55-
"/etc/wolf/cfg/wolf.sock";
56-
57-
if (!Path.Exists(endpointPath))
62+
ConnectCallback = async (_, token) =>
5863
{
59-
throw new FileNotFoundException(endpointPath);
60-
}
64+
if (!Path.Exists(socketPath))
65+
{
66+
throw new FileNotFoundException(socketPath);
67+
}
6168

62-
var socket = new Socket(AddressFamily.Unix, SocketType.Stream, ProtocolType.IP);
63-
var endpoint = new UnixDomainSocketEndPoint(endpointPath);
64-
await socket.ConnectAsync(endpoint, token);
65-
return new NetworkStream(socket, ownsSocket: true);
69+
var socket = new Socket(AddressFamily.Unix, SocketType.Stream, ProtocolType.IP);
70+
var endpoint = new UnixDomainSocketEndPoint(socketPath);
71+
await socket.ConnectAsync(endpoint, token);
72+
return new NetworkStream(socket, ownsSocket: true);
73+
}
6674
}
67-
}
68-
)
69-
);
75+
)
76+
);
77+
}
78+
else
79+
{
80+
_httpClient = new HttpClient(
81+
handler: new ClientSideRateLimitedHandler(
82+
limiter: new TokenBucketRateLimiter(options),
83+
httpMessageHandler: new HttpClientHandler()
84+
)
85+
);
86+
}
87+
88+
7089

7190
DockerApi = new(_httpClient);
7291
WolfApi = new(_httpClient);
@@ -82,7 +101,6 @@ public async Task UpdateProfiles()
82101
{
83102
Profiles.Enqueue(profile);
84103
}
85-
//ProfilesUpdatedEvent?.Invoke(Profiles.ToList());
86104
await OnProfilesUpdatedEvent(profiles);
87105
}
88106

WolfApi/Components/DockerApi.cs

Lines changed: 3 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -53,13 +53,12 @@ public void PullImage(string imageName)
5353
var json = $$"""
5454
{ "image_name": "{{imageName}}" }
5555
""";
56-
57-
//DockerImagePullProgressEvent?.Invoke(imageName, 0.0);
56+
5857
await OnDockerImagePullProgressEvent(imageName, 0.0);
5958

6059
_logger.LogInformation("Pulling image: {img}", imageName);
6160

62-
var reqMsg = new HttpRequestMessage(HttpMethod.Post, "http://localhost/api/v1/docker/images/pull")
61+
var reqMsg = new HttpRequestMessage(HttpMethod.Post, $"{BaseAddress}docker/images/pull")
6362
{
6463
Content = new StringContent(json)
6564
};
@@ -88,17 +87,14 @@ public void PullImage(string imageName)
8887
if (parsed is null)
8988
continue;
9089

91-
9290
if (parsed.Success is not null && parsed.Success == true)
9391
{
9492
ExistingDockerImages[imageName] = true;
9593

9694
if (hasDownloaded)
9795
await OnDockerImageUpdatedEvent(imageName);
98-
//DockerImageUpdatedEvent?.Invoke(imageName);
9996
else
10097
await OnDockerImageAlreadyUptoDateEvent(imageName);
101-
//DockerImageAlreadyUptoDateEvent?.Invoke(imageName);
10298

10399
_logger.LogInformation("Image: {img} {status}", imageName,
104100
hasDownloaded ? "was Updated" : "is already up to Date");
@@ -135,7 +131,7 @@ public void PullImage(string imageName)
135131
isUnpacking = true;
136132
lastCurrent = current;
137133
var percentProgress = 100.0 * (current + (isUnpacking ? sizeTotal : 0)) / total;
138-
//DockerImagePullProgressEvent?.Invoke(imageName, percentProgress);
134+
139135
await OnDockerImagePullProgressEvent(imageName, percentProgress);
140136
}
141137
});
@@ -167,8 +163,4 @@ protected virtual Task OnDockerImagePullProgressEvent(string imageName, double p
167163
{
168164
return Task.CompletedTask;
169165
}
170-
171-
// public event IApiEventPublisher.ImageUpdatedEventHandler? DockerImageUpdatedEvent;
172-
// public event IApiEventPublisher.ImageAlreadyUptoDateEventHandler? DockerImageAlreadyUptoDateEvent;
173-
// public event IApiEventPublisher.ImagePullProgressEventHandler? DockerImagePullProgressEvent;
174166
}

WolfApi/Components/IconApi.cs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ public partial class Api
1414
if (app.Runner?.Image is null || !app.Runner.Image.Contains("ghcr.io/games-on-whales/"))
1515
return null;
1616

17-
var name = app.Runner.Image.Substring("ghcr.io/games-on-whales/".Length);
17+
var name = app.Runner.Image["ghcr.io/games-on-whales/".Length..];
1818
var idx = name.LastIndexOf(':');
1919
if (idx >= 0)
2020
name = name[..idx];
@@ -35,7 +35,7 @@ public partial class Api
3535
HttpResponseMessage message;
3636
try
3737
{
38-
message = await _httpClient.GetAsync($"http://localhost/api/v1/utils/get-icon?icon_path={iconPath}");
38+
message = await _httpClient.GetAsync($"{BaseAddress}utils/get-icon?icon_path={iconPath}");
3939
}
4040
catch (HttpRequestException e)
4141
{

WolfApi/Components/SseApi.cs

Lines changed: 2 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ public Task StartAsync(CancellationToken cancellationToken)
1111
{
1212
try
1313
{
14-
var stream = await _httpClient.GetStreamAsync($"http://localhost/api/v1/events", cancellationToken);
14+
var stream = await _httpClient.GetStreamAsync($"{BaseAddress}events", cancellationToken);
1515
var eventType = string.Empty;
1616
using var reader = new StreamReader(stream);
1717
while (!reader.EndOfStream)
@@ -82,7 +82,7 @@ private async Task FilterApiEvents(string @event, string data)
8282

8383
if (!operations.TryGetValue(@event, out var value))
8484
{
85-
_logger.LogWarning("{event} is not handled by WolfLeash, check for Updates", @event);
85+
_logger.LogWarning("{event} is not handled by this Client version, check for Updates", @event);
8686
return;
8787
}
8888

@@ -203,16 +203,4 @@ protected virtual Task OnStopLobbyEvent(string data)
203203
{
204204
return Task.CompletedTask;
205205
}
206-
207-
// public event IApiEventPublisher.ApiEventEventHandler? ApiEvent;
208-
//
209-
// public event IApiEventPublisher.ClientPairRequestEventHandler ClientPairRequestEvent;
210-
//
211-
// public event IApiEventPublisher.LobbyCreatedEventEventHandler? LobbyCreatedEvent;
212-
// public event IApiEventPublisher.LobbyStoppedEventEventHandler? LobbyStoppedEvent;
213-
// public event IApiEventPublisher.LobbyJoinEventEventHandler? LobbyJoinEvent;
214-
// public event IApiEventPublisher.LobbyLeaveEventEventHandler? LobbyLeaveEvent;
215-
// public event IApiEventPublisher.SseConnectionLostEventHandler? SseConnectionLostEvent;
216-
// public event IApiEventPublisher.DockerPullingImageEventHandler? DockerPullingImageEvent;
217-
// public event IApiEventPublisher.DockerPulledImageEventHandler? DockerPulledImageEvent;
218206
}

WolfApi/Components/WolfApiHttpClient.cs

Lines changed: 0 additions & 2 deletions
This file was deleted.

WolfApi/Interfaces/IApiEventPublisher.cs

Lines changed: 0 additions & 45 deletions
This file was deleted.

WolfLeash/Components/Classes/WolfApi.cs

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,6 @@ namespace WolfLeash.Components.Classes;
55

66
public class Api : WolfApi.Api
77
{
8-
public Api(WolfApiHttpClient httpClient, ILogger<WolfApi.Api> logger) : base(httpClient, logger) { }
98
public Api(ILogger<WolfApi.Api> logger, IConfiguration configuration) : base(logger, configuration) { }
109

1110
private static Task Raise<TSource, TEventArgs>(Func<TSource, TEventArgs, Task>? handlers, TSource source, TEventArgs args)
Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
#!/usr/bin/env bash
2+
3+
set -e
4+
5+
exit_script() {
6+
trap - SIGTERM SIGINT SIGQUIT SIGHUP ERR EXIT
7+
kill -- -$$
8+
if [ "$(id -u)" = "0" ]; then
9+
for init_script in /etc/cont-shutdown.d/*.sh ; do
10+
source "${init_script}"
11+
done
12+
fi
13+
exit 1
14+
}
15+
16+
trap exit_script SIGTERM SIGINT SIGQUIT SIGHUP ERR EXIT
17+
18+
# Execute all container init scripts. Only run this if the container is started as the root user
19+
if [ "$(id -u)" = "0" ]; then
20+
for init_script in /etc/cont-init.d/*.sh ; do
21+
source "${init_script}"
22+
done
23+
fi
24+
25+
socat UNIX-LISTEN:/app/wolf.sock,mode=600,user=${APP_UID},group=${APP_UID},reuseaddr,fork UNIX-CONNECT:/etc/wolf/cfg/wolf.sock 2> /dev/null &
26+
export "WOLF_SOCKET_PATH=unix:///app/wolf.sock"
27+
28+
echo "Starting Server"
29+
exec gosu "${APP_UID}" dotnet WolfLeash.dll &
30+
wait $!
Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
#!/usr/bin/env bash
2+
3+
set -e
4+
5+
chown ${APP_UID} -R /app
6+
chown ${APP_UID} -R /home/app

WolfLeash/Dockerfile

Lines changed: 40 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,45 @@ ARG BUILD_CONFIGURATION=Release
2020
RUN dotnet publish "./WolfLeash.csproj" -c $BUILD_CONFIGURATION -o /app/publish /p:UseAppHost=false
2121

2222
FROM base AS final
23+
24+
USER root
25+
26+
ARG TARGETARCH TARGETVARIANT
27+
ARG GOSU_VERSION=1.14
28+
29+
RUN <<_INSTALL_PACKAGES
30+
set -e
31+
32+
echo "**** Update apt database ****"
33+
apt-get update
34+
35+
echo "**** Install certificates ****"
36+
apt-get install -y --reinstall --no-install-recommends \
37+
ca-certificates
38+
39+
echo "**** Install base packages ****"
40+
apt-get install -y --no-install-recommends \
41+
fuse \
42+
libnss3 \
43+
wget \
44+
curl \
45+
jq \
46+
socat
47+
48+
echo "**** Install gosu ****"
49+
wget --progress=dot:giga \
50+
-O /usr/bin/gosu \
51+
"https://github.com/tianon/gosu/releases/download/${GOSU_VERSION}/gosu-${TARGETARCH}${TARGETVARIANT}"
52+
chmod +x /usr/bin/gosu
53+
54+
echo "**** Verify gosu works ****"
55+
gosu nobody true && echo "Working!"
56+
57+
_INSTALL_PACKAGES
58+
59+
#USER $APP_UID
60+
2361
WORKDIR /app
2462
COPY --from=publish /app/publish .
25-
ENTRYPOINT ["dotnet", "-c", "Release", "WolfLeash.dll"]
63+
COPY --chmod=755 WolfLeash/DockerOverlay /
64+
ENTRYPOINT ["/entrypoint.sh"]

0 commit comments

Comments
 (0)