diff --git a/.gitmodules b/.gitmodules index 700e7536d5..08a7a0dc3c 100644 --- a/.gitmodules +++ b/.gitmodules @@ -20,3 +20,6 @@ [submodule "thirdparty/magic_enum"] path = thirdparty/magic_enum url = https://github.com/Neargye/magic_enum.git +[submodule "thirdparty/kubernetes-client-c"] + path = thirdparty/kubernetes-client-c + url = https://github.com/kubernetes-client/c diff --git a/dMasterServer/CMakeLists.txt b/dMasterServer/CMakeLists.txt index 2ebdee3765..a15edb35ba 100644 --- a/dMasterServer/CMakeLists.txt +++ b/dMasterServer/CMakeLists.txt @@ -1,16 +1,26 @@ set(DMASTERSERVER_SOURCES "InstanceManager.cpp" "ObjectIDManager.cpp" - "Start.cpp" ) add_library(dMasterServer ${DMASTERSERVER_SOURCES}) -add_executable(MasterServer "MasterServer.cpp") -add_compile_definitions(MasterServer PRIVATE PROJECT_VERSION="\"${PROJECT_VERSION}\"") - target_link_libraries(dMasterServer ${COMMON_LIBRARIES}) + +add_executable(MasterServer "MasterServer.cpp" "Start.cpp") +add_compile_definitions(MasterServer PRIVATE PROJECT_VERSION="\"${PROJECT_VERSION}\"") target_link_libraries(MasterServer ${COMMON_LIBRARIES} dMasterServer) +option(ENABLE_K8S "Whether to enable kubernetes support") + +if (${ENABLE_K8S}) + # See k8s folder + find_package(kubernetes CONFIG REQUIRED COMPONENTS kubernetes) + + add_executable(MasterServerK8s "MasterServer.cpp" "StartK8s.cpp") + add_compile_definitions(MasterServerK8s PRIVATE PROJECT_VERSION="\"${PROJECT_VERSION}\"") + target_link_libraries(MasterServerK8s PRIVATE ${COMMON_LIBRARIES} dMasterServer kubernetes::kubernetes) +endif() + if(WIN32) add_dependencies(MasterServer WorldServer AuthServer ChatServer) endif() diff --git a/dMasterServer/StartK8s.cpp b/dMasterServer/StartK8s.cpp new file mode 100644 index 0000000000..ac7d81469b --- /dev/null +++ b/dMasterServer/StartK8s.cpp @@ -0,0 +1,355 @@ +#include "Start.h" +#include "Logger.h" + +extern "C" { +#include +#include +#include +#include +#include +#include +} + +#include +#include +#include + +namespace k8s { + using DaemonSet = std::unique_ptr; + using Deployment = std::unique_ptr; + using PodSpec = std::unique_ptr; + using Pod = std::unique_ptr; +} + +class ApiClient { + char* basePath = NULL; + sslConfig_t* sslConfig = NULL; + list_t* apiKeys = NULL; + apiClient_t* k8sApiClient = NULL; + +public: + ApiClient(); + ~ApiClient(); + + k8s::DaemonSet CreateOrReplaceDeamonSet(const std::string& namespace_, k8s::DaemonSet& daemonset); + k8s::Deployment CreateOrReplaceDeployment(const std::string& namespace_, k8s::Deployment& deployment); + k8s::Pod SpawnPod(const std::string& namespace_, k8s::Pod& pod); +}; + +k8s::PodSpec CreatePodSpec(const std::string& entrypoint, int container_port, int host_port, const std::vector& args) { + v1_pod_spec_t* pod_spec = (v1_pod_spec_t*)calloc(1, sizeof(v1_pod_spec_t)); + pod_spec->restart_policy = strdup("OnFailure"); + + /* set containers for pod */ + list_t* containerlist = list_createList(); + v1_container_t* con = (v1_container_t*)calloc(1, sizeof(v1_container_t)); + con->name = strdup("darkflame-server"); + con->image = strdup("darkflame-server"); + con->image_pull_policy = strdup("IfNotPresent"); + + /* set command for container */ + list_t* commandlist = list_createList(); + char* cmd = strdup(entrypoint.c_str()); + list_addElement(commandlist, cmd); + con->command = commandlist; + + if (!args.empty()) { + list_t *arglist = list_createList(); + for (auto it = args.begin(); it != args.end(); it++) { + char *arg1 = strdup(it->c_str()); + list_addElement(arglist, arg1); + } + con->args = arglist; + } + + list_t* envfromlist = list_createList(); + char* secretName = strdup("db-secret"); + char* envPrefix = strdup("MYSQL_"); + v1_secret_env_source_t* secret = v1_secret_env_source_create(secretName, 0); + v1_env_from_source_t* src = v1_env_from_source_create(NULL, envPrefix, secret); + list_addElement(envfromlist, src); + con->env_from = envfromlist; + + list_t* envlist = list_createList(); + list_addElement(envlist, v1_env_var_create(strdup("MYSQL_HOST"), strdup("mariadb-service"), NULL)); + list_addElement(envlist, v1_env_var_create(strdup("MYSQL_USERNAME"), strdup("darkflame"), NULL)); + list_addElement(envlist, v1_env_var_create(strdup("DLU_CONFIG_DIR"), strdup("/app/config"), NULL)); + con->env = envlist; + + list_t* portlist = list_createList(); + list_addElement(portlist, v1_container_port_create(container_port, NULL, host_port, strdup("rakpeer"), strdup("UDP"))); + con->ports = portlist; + + /* set volume mounts for container */ + list_t* volumemounts = list_createList(); + + v1_volume_mount_t* volmou = (v1_volume_mount_t*)calloc(1, sizeof(v1_volume_mount_t)); + volmou->mount_path = strdup("/app/config"); + volmou->name = strdup("game-config"); + volmou->read_only = 1; + list_addElement(volumemounts, volmou); + + v1_volume_mount_t* volmou1 = (v1_volume_mount_t*)calloc(1, sizeof(v1_volume_mount_t)); + volmou1->mount_path = strdup("/app/vanity"); + volmou1->name = strdup("vanity"); + volmou1->read_only = 1; + list_addElement(volumemounts, volmou1); + + v1_volume_mount_t* volmou2 = (v1_volume_mount_t*)calloc(1, sizeof(v1_volume_mount_t)); + volmou2->mount_path = strdup("/app/res"); + volmou2->name = strdup("luclient"); + volmou2->read_only = 1; + list_addElement(volumemounts, volmou2); + + v1_volume_mount_t* volmou3 = (v1_volume_mount_t*)calloc(1, sizeof(v1_volume_mount_t)); + volmou3->mount_path = strdup("/app/resServer"); + volmou3->name = strdup("res-server"); + volmou3->read_only = 1; + list_addElement(volumemounts, volmou3); + + con->volume_mounts = volumemounts; + + list_addElement(containerlist, con); + pod_spec->containers = containerlist; + + /* set volumes for pod */ + list_t* volumelist = list_createList(); + + v1_volume_t* volume = (v1_volume_t*)calloc(1, sizeof(v1_volume_t)); + volume->name = strdup("game-config"); + v1_config_map_volume_source_t* config_map = (v1_config_map_volume_source_t*)calloc(1, sizeof(v1_config_map_volume_source_t)); + config_map->name = strdup("game-config"); + volume->config_map = config_map; + list_addElement(volumelist, volume); + + v1_volume_t* volume1 = (v1_volume_t*)calloc(1, sizeof(v1_volume_t)); + volume1->name = strdup("vanity"); + v1_config_map_volume_source_t* config_map1 = (v1_config_map_volume_source_t*)calloc(1, sizeof(v1_config_map_volume_source_t)); + config_map1->name = strdup("vanity"); + volume1->config_map = config_map1; + list_addElement(volumelist, volume1); + + v1_volume_t* volume2 = (v1_volume_t*)calloc(1, sizeof(v1_volume_t)); + volume2->name = strdup("luclient"); + v1_host_path_volume_source_t* host_path = (v1_host_path_volume_source_t*)calloc(1, sizeof(v1_host_path_volume_source_t)); + host_path->path = strdup("/luclient"); + volume2->host_path = host_path; + list_addElement(volumelist, volume2); + + v1_volume_t* volume3 = (v1_volume_t*)calloc(1, sizeof(v1_volume_t)); + volume3->name = strdup("res-server"); + v1_host_path_volume_source_t* host_path2 = (v1_host_path_volume_source_t*)calloc(1, sizeof(v1_host_path_volume_source_t)); + host_path2->path = strdup("/resServer"); + volume3->host_path = host_path2; + list_addElement(volumelist, volume3); + + pod_spec->volumes = volumelist; + + return std::move(k8s::PodSpec(pod_spec, v1_pod_spec_free)); +} + +k8s::DaemonSet CreateDeamonSet(const std::string& name, const std::string& app_label, k8s::PodSpec podSpec) { + v1_daemon_set_t* daemonsetinfo = (v1_daemon_set_t*)calloc(1, sizeof(v1_daemon_set_t)); + daemonsetinfo->api_version = strdup("apps/v1"); + daemonsetinfo->kind = strdup("DaemonSet"); + + daemonsetinfo->metadata = (v1_object_meta_t*)calloc(1, sizeof(v1_object_meta_t)); + daemonsetinfo->metadata->name = strdup(name.c_str()); + + daemonsetinfo->spec = (v1_daemon_set_spec_t*)calloc(1, sizeof(v1_daemon_set_spec_t)); + list_t* match_labels = list_createList(); + list_addElement(match_labels, keyValuePair_create(strdup("app.kubernetes.io/name"), strdup(app_label.c_str()))); + daemonsetinfo->spec->selector = (v1_label_selector_t*)calloc(1, sizeof(v1_label_selector_t)); + daemonsetinfo->spec->selector->match_labels = match_labels; + + v1_pod_template_spec_t* pod_template_spec = (v1_pod_template_spec_t*)calloc(1, sizeof(v1_pod_template_spec_t)); + pod_template_spec->metadata = (v1_object_meta_t*)calloc(1, sizeof(v1_object_meta_t)); + list_t* labels = list_createList(); + list_addElement(labels, keyValuePair_create(strdup("app.kubernetes.io/name"), strdup(app_label.c_str()))); + pod_template_spec->metadata->labels = labels; + pod_template_spec->spec = podSpec.release(); + + daemonsetinfo->spec->_template = pod_template_spec; + return std::move(k8s::DaemonSet(daemonsetinfo, v1_daemon_set_free)); +} + +k8s::Deployment CreateDeployment(const std::string& name, const std::string& app_label, k8s::PodSpec podSpec) { + v1_deployment_t* deployment = (v1_deployment_t*)calloc(1, sizeof(v1_deployment_t)); + deployment->api_version = strdup("apps/v1"); + deployment->kind = strdup("Deployment"); + + deployment->metadata = (v1_object_meta_t*)calloc(1, sizeof(v1_object_meta_t)); + deployment->metadata->name = strdup(name.c_str()); + + deployment->spec = (v1_deployment_spec_t*)calloc(1, sizeof(v1_deployment_spec_t)); + deployment->spec->replicas = 1; + + list_t* match_labels = list_createList(); + list_addElement(match_labels, keyValuePair_create(strdup("app.kubernetes.io/name"), strdup(app_label.c_str()))); + deployment->spec->selector = (v1_label_selector_t*)calloc(1, sizeof(v1_label_selector_t)); + deployment->spec->selector->match_labels = match_labels; + + v1_pod_template_spec_t* pod_template_spec = (v1_pod_template_spec_t*)calloc(1, sizeof(v1_pod_template_spec_t)); + pod_template_spec->metadata = (v1_object_meta_t*)calloc(1, sizeof(v1_object_meta_t)); + list_t* labels = list_createList(); + list_addElement(labels, keyValuePair_create(strdup("app.kubernetes.io/name"), strdup(app_label.c_str()))); + pod_template_spec->metadata->labels = labels; + pod_template_spec->spec = podSpec.release(); + + deployment->spec->_template = pod_template_spec; + return std::move(k8s::Deployment(deployment, v1_deployment_free)); +} + +char shiftNumbers(char c) { + return c < 'a' ? c - ('a' - 10 - '0') : c; +} + +k8s::Pod CreatePod(const std::string& name, const std::string& app_label, k8s::PodSpec podSpec) { + v1_pod_t* pod = (v1_pod_t*)calloc(1, sizeof(v1_pod_t)); + pod->api_version = strdup("v1"); + pod->kind = strdup("Pod"); + + std::uniform_int_distribution distribution('a' - 10, 'z'); + std::string pod_name = name + '-'; + for (int i = 0; i < 5; i++) { + pod_name += shiftNumbers(distribution(Game::randomEngine)); + } + + pod->metadata = (v1_object_meta_t*)calloc(1, sizeof(v1_object_meta_t)); + pod->metadata->name = strdup(pod_name.c_str()); + + list_t* labels = list_createList(); + list_addElement(labels, keyValuePair_create(strdup("app.kubernetes.io/name"), strdup(app_label.c_str()))); + pod->metadata->labels = labels; + + pod->spec = podSpec.release(); + return std::move(k8s::Pod(pod, v1_pod_free)); +} + +ApiClient::ApiClient() { + int rc = 0; + rc = load_incluster_config(&basePath, &sslConfig, &apiKeys); + if (0 == rc) { + k8sApiClient = apiClient_create_with_base_path(basePath, sslConfig, apiKeys); + } else { + throw std::runtime_error("Cannot load kubernetes configuration in cluster."); + } +} + +k8s::DaemonSet ApiClient::CreateOrReplaceDeamonSet(const std::string& namespace_, k8s::DaemonSet& daemonset) { + char* podNamespace = strdup(namespace_.c_str()); + + v1_daemon_set_t* created; + v1_daemon_set_t* existing = AppsV1API_readNamespacedDaemonSet(k8sApiClient, daemonset->metadata->name, podNamespace, NULL); + LOG("read code=%ld", k8sApiClient->response_code); + if (k8sApiClient->response_code == 200) { + daemonset->metadata->resource_version = existing->metadata->resource_version; + created = AppsV1API_replaceNamespacedDaemonSet(k8sApiClient, daemonset->metadata->name, podNamespace, daemonset.get(), NULL, NULL, NULL, NULL); + } else { + created = AppsV1API_createNamespacedDaemonSet(k8sApiClient, podNamespace, daemonset.get(), NULL, NULL, NULL, NULL); + } + LOG("code=%ld", k8sApiClient->response_code); + + free(podNamespace); + v1_daemon_set_free(existing); + return k8s::DaemonSet(created, v1_daemon_set_free); +} + +k8s::Pod ApiClient::SpawnPod(const std::string& namespace_, k8s::Pod& pod) { + char* podNamespace = strdup(namespace_.c_str()); + + // Kill the pod (if it exists) + //int grace_period_seconds = 0; + //v1_pod_t* existing = CoreV1API_deleteNamespacedPod(k8sApiClient, pod->metadata->name, podNamespace, NULL, NULL, &grace_period_seconds, NULL, NULL, NULL); + //LOG("read code=%ld", k8sApiClient->response_code); + // Spawn a new pod + v1_pod_t* created = CoreV1API_createNamespacedPod(k8sApiClient, podNamespace, pod.get(), NULL, NULL, NULL, NULL); + LOG("code=%ld", k8sApiClient->response_code); + + free(podNamespace); + //v1_pod_free(existing); + return k8s::Pod(created, v1_pod_free); +} + +k8s::Deployment ApiClient::CreateOrReplaceDeployment(const std::string& namespace_, k8s::Deployment& deployment) { + char* podNamespace = strdup(namespace_.c_str()); + + v1_deployment_t* created; + v1_deployment_t* existing = AppsV1API_readNamespacedDeployment(k8sApiClient, deployment->metadata->name, podNamespace, NULL); + LOG("read code=%ld", k8sApiClient->response_code); + if (k8sApiClient->response_code == 200) { + deployment->metadata->resource_version = existing->metadata->resource_version; + created = AppsV1API_replaceNamespacedDeployment(k8sApiClient, deployment->metadata->name, podNamespace, deployment.get(), NULL, NULL, NULL, NULL); + } else { + created = AppsV1API_createNamespacedDeployment(k8sApiClient, podNamespace, deployment.get(), NULL, NULL, NULL, NULL); + } + LOG("code=%ld", k8sApiClient->response_code); + + free(podNamespace); + v1_deployment_free(existing); + return k8s::Deployment(created, v1_deployment_free); +} + +ApiClient::~ApiClient() { + free_client_config(basePath, sslConfig, apiKeys); + basePath = NULL; + sslConfig = NULL; + apiKeys = NULL; + + apiClient_free(k8sApiClient); + k8sApiClient = NULL; + apiClient_unsetupGlobalEnv(); +} + +void StartAuthServer() { + if (Game::ShouldShutdown()) { + LOG("Currently shutting down. Auth will not be restarted."); + return; + } + LOG("Starting AuthServer"); + ApiClient apiClient; + k8s::PodSpec podSpec = CreatePodSpec("/app/AuthServer", 1001, 1001, {}); + //k8s::DaemonSet daemonset = CreateDeamonSet("auth-servers", "auth-server", podSpec); + k8s::Pod pod = CreatePod("auth-server-pod", "auth-server", std::move(podSpec)); + apiClient.SpawnPod("default", pod); + LOG("Done starting AuthServer"); +} + +void StartChatServer() { + if (Game::ShouldShutdown()) { + LOG("Currently shutting down. Chat will not be restarted."); + return; + } + LOG("Starting ChatServer"); + ApiClient apiClient; + k8s::PodSpec podSpec = CreatePodSpec("/app/ChatServer", 2005, 0, {}); + //k8s::Deployment deployment = CreateDeployment("chat-server", "chat-server", podSpec); + k8s::Pod pod = CreatePod("chat-server-pod", "chat-server", std::move(podSpec)); + apiClient.SpawnPod("default", pod); + LOG("Done starting ChatServer"); +} + +void StartWorldServer(LWOMAPID mapID, uint16_t port, LWOINSTANCEID instanceID, int maxPlayers, LWOCLONEID cloneID) { + LOG("Starting WorldServer %d %d %d (port %d)", mapID, instanceID, cloneID, port); + + std::vector args = { + "-zone", + std::to_string(mapID), + "-port", + std::to_string(port), + "-instance", + std::to_string(instanceID), + "-maxclients", + std::to_string(maxPlayers), + "-clone", + std::to_string(cloneID), + }; + + ApiClient apiClient; + int host_port = (int) port; // for now + k8s::PodSpec podSpec = CreatePodSpec("/app/WorldServer", (int) port, host_port, args); + std::string name = "world-" + std::to_string(mapID) + "-" + std::to_string(instanceID) + "-" + std::to_string(cloneID); + k8s::Pod pod = CreatePod(name, "world-server", std::move(podSpec)); + apiClient.SpawnPod("default", pod); + LOG("Done starting WorldServer"); +} diff --git a/k8s/DLU.Dockerfile b/k8s/DLU.Dockerfile new file mode 100644 index 0000000000..4313129a71 --- /dev/null +++ b/k8s/DLU.Dockerfile @@ -0,0 +1,49 @@ +FROM gcc:12 AS build + +RUN --mount=type=cache,id=build-apt-cache,target=/var/cache/apt \ + apt update && \ + apt install -y libssl-dev libcurl4-openssl-dev uncrustify git cmake && \ + rm -rf /var/lib/apt/lists/* + +WORKDIR /work +RUN git clone https://libwebsockets.org/repo/libwebsockets --depth 1 --branch v4.2-stable +RUN git clone https://github.com/yaml/libyaml --depth 1 --branch release/0.2.5 + +WORKDIR /work/libwebsockets/build +RUN cmake -DLWS_WITHOUT_TESTAPPS=ON -DLWS_WITHOUT_TEST_SERVER=ON -DLWS_WITHOUT_TEST_SERVER_EXTPOLL=ON \ + -DLWS_WITHOUT_TEST_PING=ON -DLWS_WITHOUT_TEST_CLIENT=ON -DCMAKE_C_FLAGS="-fpic" -DCMAKE_INSTALL_PREFIX=/usr/local .. +RUN make install + +WORKDIR /work/libyaml/build +RUN cmake -DCMAKE_INSTALL_PREFIX=/usr/local -DBUILD_TESTING=OFF -DBUILD_SHARED_LIBS=ON .. +RUN make install + +COPY ../thirdparty/kubernetes-client-c/kubernetes /work/kubernetes-client-c/ +WORKDIR /work/kubernetes-client-c/build +RUN cmake -DCMAKE_INSTALL_PREFIX=/usr/local .. +RUN make install + +FROM debian:12 + +RUN --mount=type=cache,id=build-apt-cache,target=/var/cache/apt \ + apt update && \ + apt install -y libssl3 libcurl4 && \ + rm -rf /var/lib/apt/lists/* + +WORKDIR /app +COPY build/mariadbcpp/src/mariadb_connector_cpp-build/libmariadb/libmariadb/libmariadb.so.3 /usr/local/lib +COPY --from=build /usr/local/lib/libkubernetes.so /usr/local/lib +COPY --from=build /usr/local/lib/libyaml.so /usr/local/lib +COPY --from=build /usr/local/lib/libwebsockets.so.18 /usr/local/lib +COPY --from=build /usr/local/lib/libwebsockets.so /usr/local/lib +COPY build/libmariadbcpp.so /usr/local/lib +RUN ldconfig +COPY build/MasterServerK8s /app/MasterServer +COPY build/AuthServer /app/AuthServer +COPY build/ChatServer /app/ChatServer +COPY build/WorldServer /app/WorldServer + +COPY build/migrations /app/migrations +COPY build/navmeshes /app/navmeshes + +ENTRYPOINT ["/app/MasterServer"] diff --git a/k8s/README.md b/k8s/README.md new file mode 100644 index 0000000000..0e70cb72fc --- /dev/null +++ b/k8s/README.md @@ -0,0 +1,31 @@ +## Kubernetes Setup + +Debian +``` +minikube start --driver kvm2 +minikube mount /path/to/client:/luclient +``` +or +``` +minikube start --mount --mount-options="ro" --mount-string="/path/to/client:/luclient" +``` + +Fish Shell +``` +eval $(minikube -p minikube docker-env) +``` + +To Build +``` +docker build -t darkflame-server -f ./k8s/DLU.Dockerfile . +``` + +Install +``` +kubectl apply -f secret.yml +kubectl apply -f mariadb.yml + +kubectl apply -f game-config.yml +kubectl apply -f vanity.yml +kubectl apply -f darkflame.yml +``` diff --git a/k8s/darkflame.yml b/k8s/darkflame.yml new file mode 100644 index 0000000000..fd923058f4 --- /dev/null +++ b/k8s/darkflame.yml @@ -0,0 +1,130 @@ +apiVersion: v1 +kind: ServiceAccount +metadata: + name: master-server +--- +apiVersion: rbac.authorization.k8s.io/v1 +kind: Role +metadata: + name: pod-creator +rules: +- apiGroups: [""] + resources: ["pods"] + verbs: ["create", "update", "patch", "get", "watch", "list", "delete"] +- apiGroups: ["apps"] + resources: ["daemonsets", "deployments"] + verbs: ["create", "update", "patch", "get", "watch", "list", "delete"] +--- +apiVersion: rbac.authorization.k8s.io/v1 +kind: RoleBinding +metadata: + name: master-server-pod-creator +roleRef: + apiGroup: rbac.authorization.k8s.io + kind: Role + name: pod-creator +subjects: +- kind: ServiceAccount + name: master-server +--- +apiVersion: apps/v1 +kind: Deployment +metadata: + name: master-server-deployment + labels: + app: master-server +spec: + replicas: 1 + selector: + matchLabels: + app: master-server + template: + metadata: + labels: + app: master-server + spec: + serviceAccountName: master-server + volumes: + - name: game-config + configMap: + name: game-config + - name: luclient + hostPath: + path: /luclient + - name: res-server + hostPath: + path: /resServer + containers: + - name: master-server + image: darkflame-server + imagePullPolicy: IfNotPresent + ports: + - containerPort: 2000 + protocol: UDP + name: master + env: + - name: MYSQL_HOST + value: mariadb-service + - name: MYSQL_USERNAME + value: darkflame + - name: MASTER_IP + value: master-service + - name: DLU_CONFIG_DIR + value: /app/config + envFrom: + - secretRef: + name: db-secret + prefix: MYSQL_ + volumeMounts: + - mountPath: "/app/res" + name: luclient + - mountPath: "/app/resServer" + name: res-server + - mountPath: "/app/config" + name: game-config +--- +apiVersion: v1 +kind: Service +metadata: + name: master-service +spec: + selector: + app: master-server + ports: + - name: master + protocol: UDP + port: 2000 + targetPort: master +#--- +#apiVersion: apps/v1 +#kind: Deployment +#metadata: +# name: auth-server-deployment +# labels: +# app: auth-server +#spec: +# replicas: 1 +# selector: +# matchLabels: +# app: auth-server +# template: +# metadata: +# labels: +# app: auth-server +# spec: +# containers: +# - name: auth-server +# image: darkflame-auth-server +# imagePullPolicy: IfNotPresent +# ports: +# - containerPort: 1001 +# name: auth +# env: +# - name: MYSQL_HOST +# value: mariadb-service +# - name: MYSQL_USERNAME +# value: darkflame +# envFrom: +# - secretRef: +# name: db-secret +# prefix: MYSQL_ diff --git a/k8s/game-config.yml b/k8s/game-config.yml new file mode 100644 index 0000000000..579e56c137 --- /dev/null +++ b/k8s/game-config.yml @@ -0,0 +1,87 @@ +apiVersion: v1 +kind: ConfigMap +metadata: + name: game-config +data: + authconfig.ini: | + port=1001 + dont_use_keys=0 + rewardcodes=4,30 + + chatconfig.ini: | + port=2005 + max_number_of_best_friends=5 + max_number_of_friends=50 + + masterconfig.ini: | + master_ip=localhost + port=2000 + world_port_start=3000 + use_sudo_auth=1 + use_sudo_chat=0 + use_sudo_world=0 + prestart_servers=1 + + sharedconfig.ini: | + log_to_console=1 + log_debug_statements=0 + external_ip=192.168.39.84 + dont_generate_dcf=0 + max_clients=999 + dump_folder= + client_location= + maximum_outgoing_bandwidth=80000 + maximum_mtu_size=1228 + client_net_version=171022 + default_team_loot=1 + + event_1=Talk_Like_A_Pirate + event_2= + event_3= + event_4= + event_5= + event_6= + event_7= + event_8= + + version_major=1 + version_current=10 + version_minor=64 + + worldconfig.ini: | + source=https://github.com/DarkflameUniverse/DarkflameServer + chat_server_port=2005 + disable_chat=0 + + phys_spatial_partitioning=1 + phys_sp_tilesize=102 + phys_sp_tilecount=24 + + disable_extra_backpack=0 + disable_vanity=0 + solo_racing=0 + disable_anti_speedhack=0 + check_fdb=0 + classic_survival_scoring=0 + pets_take_imagination=1 + disable_drops=0 + hardcore_mode=0 + hardcore_dropinventory_on_death=1 + hardcore_uscore_enemies_multiplier=2 + hardcore_lose_uscore_on_death_percent=10 + allow_nameplate_off=0 + log_ip_addresses_for_anti_cheat=1 + + help_0_summary=Got an issue? + help_1_summary=Stuck loading? + help_2_summary=Missing features? + help_3_summary=Get smashed? + help_4_summary=Want to contribute? + + help_0_description=Go to the DarkflameServer repository on GitHub to view issues and discussions about the server emulator!

Click Here to go there!

+ help_1_description=Try switching networks, using a VPN, or using your phone's hotspot to resolve the issue.

+ help_2_description=While DarkflameServer is a mostly complete emulator, there are still some features that aren't implemented. You can track these on the GitHub issues page.

+ help_3_description=Skill issue!

+ help_4_description=Visit Discussions on the DarkflameServer GitHub page
to ask questions and collaborate with other devs!

+ + allow_players_to_skip_cinematics=0 diff --git a/k8s/mariadb.yml b/k8s/mariadb.yml new file mode 100644 index 0000000000..338015e7b1 --- /dev/null +++ b/k8s/mariadb.yml @@ -0,0 +1,74 @@ +apiVersion: v1 +kind: PersistentVolume +metadata: + name: pv0001 +spec: + storageClassName: manual + accessModes: + - ReadWriteOnce + capacity: + storage: 5Gi + hostPath: + path: /data/pv0001/ +--- +apiVersion: v1 +kind: PersistentVolumeClaim +metadata: + name: db-pv-claim +spec: + storageClassName: manual + accessModes: + - ReadWriteOnce + resources: + requests: + storage: 3Gi +--- +apiVersion: apps/v1 +kind: Deployment +metadata: + name: mariadb-deployment + labels: + app: mariadb +spec: + replicas: 1 + selector: + matchLabels: + app: mariadb + template: + metadata: + labels: + app: mariadb + spec: + volumes: + - name: db-pv-storage + persistentVolumeClaim: + claimName: db-pv-claim + containers: + - name: mariadb + image: mariadb:11 + ports: + - containerPort: 3306 + name: tcp-db-svc + envFrom: + - secretRef: + name: db-secret + prefix: MARIADB_ + env: + - name: MARIADB_RANDOM_ROOT_PASSWORD + value: "1" + volumeMounts: + - mountPath: "/var/lib/mysql" + name: db-pv-storage +--- +apiVersion: v1 +kind: Service +metadata: + name: mariadb-service +spec: + selector: + app: mariadb + ports: + - name: mariadb + protocol: TCP + port: 3306 + targetPort: tcp-db-svc diff --git a/k8s/secret.yml b/k8s/secret.yml new file mode 100644 index 0000000000..a29bb45028 --- /dev/null +++ b/k8s/secret.yml @@ -0,0 +1,8 @@ +apiVersion: v1 +kind: Secret +metadata: + name: db-secret +data: + USER: ZGFya2ZsYW1l # darkflame + PASSWORD: Z2pOQDUjVFRFJkgmWWVlczVRM2EldFRD + DATABASE: ZGFya2ZsYW1l diff --git a/k8s/vanity.yml b/k8s/vanity.yml new file mode 100644 index 0000000000..6db65e3143 --- /dev/null +++ b/k8s/vanity.yml @@ -0,0 +1,49 @@ +apiVersion: v1 +kind: ConfigMap +metadata: + name: vanity +data: + NPC.xml: | + + + + TESTAMENT.md: | + # TESTAMENT TO THE POWER OF IMAGINATION + + May this be preserved for future generations, to experience what was destined to be lost + + May it serve as a gateway for opportunity and fellowship + + May it be a testament to the power of imagination + INFO.md: | + # SERVER INFO + + ## Version + __VERSION__ + + ## Source repository + __SOURCE__ + + ## License + __LICENSE__ + + ## Compiled on + __TIMESTAMP__ + CREDITS.md: | + # CREDITS + + ## DLU Team + DarwinAnim8or (Max) + Wincent01 + Mick + averysumner (codeshaunted) + Jon002 + Jonny + Xiphoseer + lcdr + Aaron K. + Neal + + ## Active Contributors + EmosewaMC + Jettford \ No newline at end of file diff --git a/thirdparty/CMakeMariaDBLists.txt b/thirdparty/CMakeMariaDBLists.txt index d7a17f28c4..c68fcdb37b 100644 --- a/thirdparty/CMakeMariaDBLists.txt +++ b/thirdparty/CMakeMariaDBLists.txt @@ -94,6 +94,7 @@ else() # Build from source ${MARIADB_EXTRA_CMAKE_ARGS} PREFIX "${PROJECT_BINARY_DIR}/mariadbcpp" BUILD_COMMAND cmake --build . --config RelWithDebInfo -j${MARIADB_CONNECTOR_COMPILE_JOBS} + BUILD_ALWAYS true INSTALL_COMMAND "") ExternalProject_Get_Property(mariadb_connector_cpp BINARY_DIR) diff --git a/thirdparty/kubernetes-client-c b/thirdparty/kubernetes-client-c new file mode 160000 index 0000000000..131583107a --- /dev/null +++ b/thirdparty/kubernetes-client-c @@ -0,0 +1 @@ +Subproject commit 131583107a939acf455f7df3bc9e3738981c310f