Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Make namespace configurable and improve config&logger handling #43

Merged
merged 5 commits into from
Mar 24, 2024
Merged
Show file tree
Hide file tree
Changes from 4 commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions README-JP.md
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ Pluginは [Releases](https://github.com/AzisabaNetwork/Kuvel/releases/latest)
からダウンロードできます。 `Kuvel.jar` をダウンロードしVelocityに導入してください。ダウンロード後、コンフィグの設定を行ってください。

```yml
namespace: ""
redis:
group-name: "production" # Redisサーバーが同じかつgroup-nameが同じサーバー間でのみ名前同期が行われます
connection:
Expand Down
6 changes: 6 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,8 @@ from [Releases](https://github.com/AzisabaNetwork/Kuvel/releases/latest). Downlo
install it into Velocity plugins directory. Also, you have to fill in the configuration file.

```yml
# The kubernetes namespace to use for the server discovery.
namespace: ""
# Server name synchronization by Redis is required in load-balanced environments using multiple Velocity.
redis:
group-name: "production"
Expand All @@ -29,6 +31,10 @@ redis:
password: "password"
```

Alternatively you can use environment variables to configure Kuvel. The environment variable will override
the config.yml and are `KUVEL_NAMESPACE`, `KUVEL_REDIS_GROUPNAME`, `KUVEL_REDIS_CONNECTION_HOSTNAME`,
`KUVEL_REDIS_CONNECTION_PORT`, `KUVEL_REDIS_CONNECTION_USERNAME`, and `KUVEL_REDIS_CONNECTION_PASSWORD`.

In order for Kuvel to monitor the server, you must request permission from Kubernetes to allow
Velocity pods discovery Minecraft servers. For Velocity pods, please allow get/list/watch to Pods
and ReplicaSets.
Expand Down
2 changes: 1 addition & 1 deletion pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@

<groupId>net.azisaba</groupId>
<artifactId>Kuvel</artifactId>
<version>2.0.2</version>
<version>2.1.0</version>
<packaging>jar</packaging>

<name>${project.artifactId}</name>
Expand Down
19 changes: 13 additions & 6 deletions src/main/java/net/azisaba/kuvel/Kuvel.java
Original file line number Diff line number Diff line change
Expand Up @@ -5,12 +5,15 @@
import com.velocitypowered.api.event.proxy.ProxyInitializeEvent;
import com.velocitypowered.api.event.proxy.ProxyShutdownEvent;
import com.velocitypowered.api.plugin.Plugin;
import com.velocitypowered.api.plugin.annotation.DataDirectory;
import com.velocitypowered.api.proxy.ProxyServer;
import io.fabric8.kubernetes.client.DefaultKubernetesClient;
import io.fabric8.kubernetes.client.KubernetesClient;

import java.io.File;
import java.nio.file.Path;
import java.util.Objects;
import java.util.concurrent.TimeUnit;
import java.util.logging.Logger;
import lombok.Getter;
import net.azisaba.kuvel.config.KuvelConfig;
import net.azisaba.kuvel.discovery.impl.redis.RedisLoadBalancerDiscovery;
Expand All @@ -20,11 +23,12 @@
import net.azisaba.kuvel.redis.ProxyIdProvider;
import net.azisaba.kuvel.redis.RedisConnectionLeader;
import net.azisaba.kuvel.redis.RedisSubscriberExecutor;
import org.slf4j.Logger;

@Plugin(
id = "kuvel",
name = "Kuvel",
version = "2.0.2",
version = "2.1.0",
url = "https://github.com/AzisabaNetwork/Kuvel",
description =
"Server-discovery Velocity plugin for Minecraft servers running in a Kubernetes cluster.",
Expand All @@ -34,6 +38,7 @@ public class Kuvel {

private final ProxyServer proxy;
private final Logger logger;
private final File dataDirectory;

private KubernetesClient client;
private KuvelServiceHandler kuvelServiceHandler;
Expand All @@ -44,9 +49,10 @@ public class Kuvel {
private KuvelConfig kuvelConfig;

@Inject
public Kuvel(ProxyServer server, Logger logger) {
public Kuvel(ProxyServer server, Logger logger, @DataDirectory Path dataDirectory) {
this.proxy = server;
this.logger = logger;
this.dataDirectory = dataDirectory.toFile();
}

@Subscribe
Expand All @@ -57,12 +63,11 @@ public void onProxyInitialization(ProxyInitializeEvent event) {
try {
kuvelConfig.load();
} catch (Exception e) {
logger.severe("Failed to load config file. Plugin feature will be disabled.");
e.printStackTrace();
logger.error("Failed to load config file. Plugin feature will be disabled.", e);
return;
}

kuvelServiceHandler = new KuvelServiceHandler(this, client);
kuvelServiceHandler = new KuvelServiceHandler(this, client, kuvelConfig.getNamespace());

Objects.requireNonNull(kuvelConfig.getRedisConnectionData());
Objects.requireNonNull(kuvelConfig.getProxyGroupName());
Expand All @@ -88,6 +93,7 @@ public void onProxyInitialization(ProxyInitializeEvent event) {
new RedisLoadBalancerDiscovery(
client,
this,
kuvelConfig.getNamespace(),
kuvelConfig.getRedisConnectionData().createJedisPool(),
kuvelConfig.getProxyGroupName(),
redisConnectionLeader,
Expand All @@ -97,6 +103,7 @@ public void onProxyInitialization(ProxyInitializeEvent event) {
new RedisServerDiscovery(
client,
this,
kuvelConfig.getNamespace(),
kuvelConfig.getRedisConnectionData().createJedisPool(),
kuvelConfig.getProxyGroupName(),
redisConnectionLeader,
Expand Down
5 changes: 3 additions & 2 deletions src/main/java/net/azisaba/kuvel/KuvelServiceHandler.java
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ public class KuvelServiceHandler {

private final Kuvel plugin;
private final KubernetesClient client;
private final String namespace;
private final HashMap<String, LoadBalancer> loadBalancerServerMap = new HashMap<>();

private final UidAndServerNameMap podUidAndServerNameMap = new UidAndServerNameMap();
Expand Down Expand Up @@ -125,7 +126,7 @@ private void updateLoadBalancerEndpoints(LoadBalancer loadBalancer) {
List<Pod> pods =
client
.pods()
.inAnyNamespace()
.inNamespace(namespace)
.withLabel(LabelKeys.ENABLE_SERVER_DISCOVERY.getKey(), "true")
.list()
.getItems();
Expand Down Expand Up @@ -251,7 +252,7 @@ public void registerPod(String podUid, String serverName) {
Optional<Pod> pod =
client
.pods()
.inAnyNamespace()
.inNamespace(namespace)
.withLabel(LabelKeys.ENABLE_SERVER_DISCOVERY.getKey(), "true")
.list()
.getItems()
Expand Down
30 changes: 23 additions & 7 deletions src/main/java/net/azisaba/kuvel/config/KuvelConfig.java
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

import java.io.File;
import java.io.IOException;
import java.util.Map;
import javax.annotation.Nullable;
import lombok.Getter;
import lombok.RequiredArgsConstructor;
Expand All @@ -14,31 +15,46 @@ public class KuvelConfig {

private final Kuvel plugin;

private static final String CONFIG_FILE_PATH = "./plugins/Kuvel/config.yml";
private static final String CONFIG_FILE_NAME = "config.yml";
Phoenix616 marked this conversation as resolved.
Show resolved Hide resolved

@Nullable private String namespace;
private boolean redisEnabled;
@Nullable private RedisConnectionData redisConnectionData;
@Nullable private String proxyGroupName;

public void load() throws IOException {
VelocityConfigLoader conf = VelocityConfigLoader.load(new File(CONFIG_FILE_PATH));
VelocityConfigLoader conf = VelocityConfigLoader.load(new File(plugin.getDataDirectory(), CONFIG_FILE_NAME));
conf.saveDefaultConfig();

String hostname = conf.getString("redis.connection.hostname");
Map<String, String> env = System.getenv();

namespace = env.getOrDefault("KUVEL_NAMESPACE", conf.getString("namespace", null));

String hostname = env.getOrDefault("KUVEL_REDIS_CONNECTION_HOSTNAME", conf.getString("redis.connection.hostname"));
int port = conf.getInt("redis.connection.port", -1);
String username = conf.getString("redis.connection.username");
String password = conf.getString("redis.connection.password");
if (env.containsKey("KUVEL_REDIS_CONNECTION_PORT")) {
try {
port = Integer.parseInt(env.get("KUVEL_REDIS_CONNECTION_PORT"));
} catch (NumberFormatException e) {
plugin
.getLogger()
.warn(
"Invalid port number for Redis connection specified in KUVEL_REDIS_CONNECTION_PORT environment variable. Using port " + port + " from config.yml.");
}
}
String username = env.getOrDefault("KUVEL_REDIS_CONNECTION_USERNAME", conf.getString("redis.connection.username"));
String password = env.getOrDefault("KUVEL_REDIS_CONNECTION_PASSWORD", conf.getString("redis.connection.password"));

if (hostname == null || port <= 0) {
redisEnabled = false;
plugin
.getLogger()
.warning(
.warn(
"Redis is enabled, but hostname or port is invalid. Redis sync will be disabled.");
} else {
redisConnectionData = new RedisConnectionData(hostname, port, username, password);
}

proxyGroupName = conf.getString("redis.group-name", null);
proxyGroupName = env.getOrDefault("KUVEL_REDIS_GROUPNAME", conf.getString("redis.group-name", null));
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ public class RedisLoadBalancerDiscovery implements LoadBalancerDiscovery {

private final KubernetesClient client;
private final Kuvel plugin;
private final String namespace;
private final JedisPool jedisPool;
private final String groupName;
private final RedisConnectionLeader redisConnectionLeader;
Expand All @@ -55,7 +56,7 @@ public void start() {
client
.apps()
.replicaSets()
.inAnyNamespace()
.inNamespace(namespace)
.withLabel(LabelKeys.ENABLE_SERVER_DISCOVERY.getKey(), "true")
.withLabel(LabelKeys.PREFERRED_SERVER_NAME.getKey())
.list()
Expand Down Expand Up @@ -241,7 +242,7 @@ public void registerLoadBalancersForStartup() {
client
.apps()
.replicaSets()
.inAnyNamespace()
.inNamespace(namespace)
.withLabel(LabelKeys.ENABLE_SERVER_DISCOVERY.getKey(), "true")
.withLabel(LabelKeys.PREFERRED_SERVER_NAME.getKey())
.list()
Expand Down Expand Up @@ -272,7 +273,7 @@ private ReplicaSet getReplicaSetFromUid(String uid) {
return client
.apps()
.replicaSets()
.inAnyNamespace()
.inNamespace(namespace)
.withLabel(LabelKeys.ENABLE_SERVER_DISCOVERY.getKey(), "true")
.withLabel(LabelKeys.PREFERRED_SERVER_NAME.getKey())
.list()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ public class RedisServerDiscovery implements ServerDiscovery {

private final KubernetesClient client;
private final Kuvel plugin;
private final String namespace;
private final JedisPool jedisPool;
private final String groupName;
private final RedisConnectionLeader redisConnectionLeader;
Expand All @@ -52,7 +53,7 @@ public void start() {
List<Pod> podList =
client
.pods()
.inAnyNamespace()
.inNamespace(namespace)
.withLabel(LabelKeys.ENABLE_SERVER_DISCOVERY.getKey(), "true")
.list()
.getItems();
Expand Down Expand Up @@ -113,7 +114,7 @@ public HashMap<String, Pod> getServersForStartup() {

client
.pods()
.inAnyNamespace()
.inNamespace(namespace)
.withLabel(LabelKeys.ENABLE_SERVER_DISCOVERY.getKey(), "true")
.withField("status.phase", "Running")
.list()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -120,6 +120,7 @@ private void runDiscoveryTask() {
new RedisLoadBalancerDiscovery(
plugin.getClient(),
plugin,
plugin.getKuvelConfig().getNamespace(),
plugin.getKuvelConfig().getRedisConnectionData().createJedisPool(),
plugin.getKuvelConfig().getProxyGroupName(),
this,
Expand All @@ -131,6 +132,7 @@ private void runDiscoveryTask() {
new RedisServerDiscovery(
plugin.getClient(),
plugin,
plugin.getKuvelConfig().getNamespace(),
plugin.getKuvelConfig().getRedisConnectionData().createJedisPool(),
plugin.getKuvelConfig().getProxyGroupName(),
this,
Expand Down
2 changes: 2 additions & 0 deletions src/main/resources/config.yml
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
# The kubernetes namespace to use for the server discovery.
namespace: ""
# Server name synchronization by Redis is required in load-balanced environments using multiple Velocity.
redis:
group-name: "production"
Expand Down