From e50b0b2e125f98096abf6419d5ed025783147cc0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=A9r=C3=A9my=20Levilain?= Date: Sat, 5 Nov 2022 22:10:12 +0100 Subject: [PATCH] feat: add support for world and plugins --- ...ulkermc.io_minecraftserverdeployments.yaml | 81 ++++++++++++++++++ .../bases/shulkermc.io_minecraftservers.yaml | 74 +++++++++++++++++ .../src/minecraftserver_controller.go | 2 + .../minecraftserverdeployment_controller.go | 5 +- .../src/proxydeployment_controller.go | 5 +- libs/crds/v1alpha1/mincraftserver_types.go | 11 ++- libs/crds/v1alpha1/resourceref_types.go | 42 ++++++++++ libs/crds/v1alpha1/zz_generated.deepcopy.go | 67 +++++++++++++++ libs/resources/src/minecraftserver/builder.go | 4 + .../src/minecraftserver/configmap.go | 27 ++++-- libs/resources/src/minecraftserver/pod.go | 83 ++++++++++++++----- libs/resources/src/proxy/configmap.go | 30 ++++--- libs/resources/src/proxy/pod.go | 4 + libs/resources/src/resourceref.go | 76 +++++++++++++++++ .../proxyagent/features/limbo/LimboFeature.kt | 6 +- test/bases/cluster.yaml | 5 -- test/bases/minecraftserver-lobby.yaml | 28 ------- test/bases/proxy.yaml | 29 ------- test/kustomization.yaml | 4 - 19 files changed, 465 insertions(+), 118 deletions(-) create mode 100644 libs/crds/v1alpha1/resourceref_types.go create mode 100644 libs/resources/src/resourceref.go delete mode 100644 test/bases/cluster.yaml delete mode 100644 test/bases/minecraftserver-lobby.yaml delete mode 100644 test/bases/proxy.yaml delete mode 100644 test/kustomization.yaml diff --git a/config/crd/bases/shulkermc.io_minecraftserverdeployments.yaml b/config/crd/bases/shulkermc.io_minecraftserverdeployments.yaml index 50b204c6..bcd27b7f 100644 --- a/config/crd/bases/shulkermc.io_minecraftserverdeployments.yaml +++ b/config/crd/bases/shulkermc.io_minecraftserverdeployments.yaml @@ -105,6 +105,47 @@ spec: description: Number of maximum players that can connect to the MinecraftServer. type: integer + plugins: + description: List of references to plugins to download. + items: + properties: + url: + description: Direct URL of the resource to download. + type: string + urlFrom: + description: Source of the resource URL. Cannot + be used if value is not empty. + properties: + mavenRef: + description: Reference to a Maven artiact to + use as source. + properties: + artifactId: + description: Artifact ID of the Maven artifact + to download. + type: string + credentialsSecretName: + description: Name of the Kubernetes Secret + containing the repository credentials. + The secret must contains a username and + password keys. + type: string + groupId: + description: Group ID of the Maven artifact + to download. + type: string + repository: + description: URL to the Maven repository + to download the artifact from. + type: string + version: + description: Version of the Maven artifact + to download. + type: string + type: object + type: object + type: object + type: array proxyForwardingMode: default: Velocity description: Type of forwarding the proxies are using @@ -113,6 +154,46 @@ spec: - BungeeCord - Velocity type: string + world: + description: Reference to a world to download and extract. + Gzipped tarball only. + properties: + url: + description: Direct URL of the resource to download. + type: string + urlFrom: + description: Source of the resource URL. Cannot be + used if value is not empty. + properties: + mavenRef: + description: Reference to a Maven artiact to use + as source. + properties: + artifactId: + description: Artifact ID of the Maven artifact + to download. + type: string + credentialsSecretName: + description: Name of the Kubernetes Secret + containing the repository credentials. The + secret must contains a username and password + keys. + type: string + groupId: + description: Group ID of the Maven artifact + to download. + type: string + repository: + description: URL to the Maven repository to + download the artifact from. + type: string + version: + description: Version of the Maven artifact + to download. + type: string + type: object + type: object + type: object type: object podOverrides: description: Overrides for values to be injected in the created diff --git a/config/crd/bases/shulkermc.io_minecraftservers.yaml b/config/crd/bases/shulkermc.io_minecraftservers.yaml index 7f324be1..bbe6f916 100644 --- a/config/crd/bases/shulkermc.io_minecraftservers.yaml +++ b/config/crd/bases/shulkermc.io_minecraftservers.yaml @@ -80,6 +80,44 @@ spec: description: Number of maximum players that can connect to the MinecraftServer. type: integer + plugins: + description: List of references to plugins to download. + items: + properties: + url: + description: Direct URL of the resource to download. + type: string + urlFrom: + description: Source of the resource URL. Cannot be used + if value is not empty. + properties: + mavenRef: + description: Reference to a Maven artiact to use as + source. + properties: + artifactId: + description: Artifact ID of the Maven artifact to + download. + type: string + credentialsSecretName: + description: Name of the Kubernetes Secret containing + the repository credentials. The secret must contains + a username and password keys. + type: string + groupId: + description: Group ID of the Maven artifact to download. + type: string + repository: + description: URL to the Maven repository to download + the artifact from. + type: string + version: + description: Version of the Maven artifact to download. + type: string + type: object + type: object + type: object + type: array proxyForwardingMode: default: Velocity description: Type of forwarding the proxies are using between @@ -88,6 +126,42 @@ spec: - BungeeCord - Velocity type: string + world: + description: Reference to a world to download and extract. Gzipped + tarball only. + properties: + url: + description: Direct URL of the resource to download. + type: string + urlFrom: + description: Source of the resource URL. Cannot be used if + value is not empty. + properties: + mavenRef: + description: Reference to a Maven artiact to use as source. + properties: + artifactId: + description: Artifact ID of the Maven artifact to + download. + type: string + credentialsSecretName: + description: Name of the Kubernetes Secret containing + the repository credentials. The secret must contains + a username and password keys. + type: string + groupId: + description: Group ID of the Maven artifact to download. + type: string + repository: + description: URL to the Maven repository to download + the artifact from. + type: string + version: + description: Version of the Maven artifact to download. + type: string + type: object + type: object + type: object type: object podOverrides: description: Overrides for values to be injected in the created Pod diff --git a/libs/controllers/src/minecraftserver_controller.go b/libs/controllers/src/minecraftserver_controller.go index aac1ebbb..76a8bae9 100644 --- a/libs/controllers/src/minecraftserver_controller.go +++ b/libs/controllers/src/minecraftserver_controller.go @@ -57,6 +57,8 @@ func (r *MinecraftServerReconciler) Reconcile(ctx context.Context, req ctrl.Requ resourceBuilder := resources.MinecraftServerResourceBuilder{ Instance: minecraftServer, Scheme: r.Scheme, + Client: r.Client, + Ctx: ctx, } builders, dirtyBuilders := resourceBuilder.ResourceBuilders() diff --git a/libs/controllers/src/minecraftserverdeployment_controller.go b/libs/controllers/src/minecraftserverdeployment_controller.go index 9aaf541f..5ab76d49 100644 --- a/libs/controllers/src/minecraftserverdeployment_controller.go +++ b/libs/controllers/src/minecraftserverdeployment_controller.go @@ -113,9 +113,8 @@ func (r *MinecraftServerDeploymentReconciler) Reconcile(ctx context.Context, req minecraftServer.Labels = labels minecraftServer.Spec = minecraftServerDeployment.Spec.Template.Spec minecraftServer.Spec.ClusterRef = minecraftServerDeployment.Spec.ClusterRef - minecraftServer.Spec.Configuration = shulkermciov1alpha1.MinecraftServerConfigurationSpec{ - ExistingConfigMapName: resourceBuilder.GetConfigMapName(), - } + minecraftServer.Spec.Configuration = minecraftServerDeployment.Spec.Template.Spec.Configuration + minecraftServer.Spec.Configuration.ExistingConfigMapName = resourceBuilder.GetConfigMapName() if err := controllerutil.SetControllerReference(minecraftServerDeployment, &minecraftServer, r.Scheme); err != nil { err = fmt.Errorf("failed setting controller reference for MinecraftServer: %v", err) diff --git a/libs/controllers/src/proxydeployment_controller.go b/libs/controllers/src/proxydeployment_controller.go index f3fb6e98..9801a313 100644 --- a/libs/controllers/src/proxydeployment_controller.go +++ b/libs/controllers/src/proxydeployment_controller.go @@ -116,9 +116,8 @@ func (r *ProxyDeploymentReconciler) Reconcile(ctx context.Context, req ctrl.Requ proxy.Labels = labels proxy.Spec = proxyDeployment.Spec.Template.Spec proxy.Spec.ClusterRef = proxyDeployment.Spec.ClusterRef - proxy.Spec.Configuration = shulkermciov1alpha1.ProxyConfigurationSpec{ - ExistingConfigMapName: resourceBuilder.GetConfigMapName(), - } + proxy.Spec.Configuration = proxyDeployment.Spec.Template.Spec.Configuration + proxy.Spec.Configuration.ExistingConfigMapName = resourceBuilder.GetConfigMapName() if err := controllerutil.SetControllerReference(proxyDeployment, &proxy, r.Scheme); err != nil { err = fmt.Errorf("failed setting controller reference for Proxy: %v", err) diff --git a/libs/crds/v1alpha1/mincraftserver_types.go b/libs/crds/v1alpha1/mincraftserver_types.go index 930233d0..db8cc2ec 100644 --- a/libs/crds/v1alpha1/mincraftserver_types.go +++ b/libs/crds/v1alpha1/mincraftserver_types.go @@ -71,9 +71,18 @@ const ( type MinecraftServerConfigurationSpec struct { // Name of an optional ConfigMap already containing the server // configuration. - //+optional + // +optional ExistingConfigMapName string `json:"existingConfigMapName,omitempty"` + // Reference to a world to download and extract. Gzipped tarball + // only. + //+optional + World *ResourceRef `json:"world,omitempty"` + + // List of references to plugins to download. + //+optional + Plugins []ResourceRef `json:"plugins,omitempty"` + // Number of maximum players that can connect to the MinecraftServer. //+kubebuilder:default=20 MaxPlayers *int16 `json:"maxPlayers,omitempty"` diff --git a/libs/crds/v1alpha1/resourceref_types.go b/libs/crds/v1alpha1/resourceref_types.go new file mode 100644 index 00000000..5dd12dfc --- /dev/null +++ b/libs/crds/v1alpha1/resourceref_types.go @@ -0,0 +1,42 @@ +package v1alpha1 + +type ResourceRef struct { + // Direct URL of the resource to download. + // +optional + Url string `json:"url,omitempty"` + + // Source of the resource URL. Cannot be used if value is not + // empty. + // +optional + UrlFrom *ResourceRefSource `json:"urlFrom,omitempty"` +} + +type ResourceRefSource struct { + // Reference to a Maven artiact to use as source. + // +optional + MavenRef *ResourceRefMavenSelector `json:"mavenRef,omitempty"` +} + +type ResourceRefMavenSelector struct { + // URL to the Maven repository to download the artifact from. + //+kubebuilder:validation:Required + Repository string `json:"repository,omitempty"` + + // Group ID of the Maven artifact to download. + //+kubebuilder:validation:Required + GroupId string `json:"groupId,omitempty"` + + // Artifact ID of the Maven artifact to download. + //+kubebuilder:validation:Required + ArtifactId string `json:"artifactId,omitempty"` + + // Version of the Maven artifact to download. + //+kubebuilder:validation:Required + Version string `json:"version,omitempty"` + + // Name of the Kubernetes Secret containing the repository + // credentials. The secret must contains a username + // and password keys. + //+optional + CredentialsSecretName string `json:"credentialsSecretName,omitempty"` +} diff --git a/libs/crds/v1alpha1/zz_generated.deepcopy.go b/libs/crds/v1alpha1/zz_generated.deepcopy.go index c4a88aff..eb06d41a 100644 --- a/libs/crds/v1alpha1/zz_generated.deepcopy.go +++ b/libs/crds/v1alpha1/zz_generated.deepcopy.go @@ -150,6 +150,18 @@ func (in *MinecraftServer) DeepCopyObject() runtime.Object { // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *MinecraftServerConfigurationSpec) DeepCopyInto(out *MinecraftServerConfigurationSpec) { *out = *in + if in.World != nil { + in, out := &in.World, &out.World + *out = new(ResourceRef) + (*in).DeepCopyInto(*out) + } + if in.Plugins != nil { + in, out := &in.Plugins, &out.Plugins + *out = make([]ResourceRef, len(*in)) + for i := range *in { + (*in)[i].DeepCopyInto(&(*out)[i]) + } + } if in.MaxPlayers != nil { in, out := &in.MaxPlayers, &out.MaxPlayers *out = new(int16) @@ -700,3 +712,58 @@ func (in *ProxyVersionSpec) DeepCopy() *ProxyVersionSpec { in.DeepCopyInto(out) return out } + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *ResourceRef) DeepCopyInto(out *ResourceRef) { + *out = *in + if in.UrlFrom != nil { + in, out := &in.UrlFrom, &out.UrlFrom + *out = new(ResourceRefSource) + (*in).DeepCopyInto(*out) + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ResourceRef. +func (in *ResourceRef) DeepCopy() *ResourceRef { + if in == nil { + return nil + } + out := new(ResourceRef) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *ResourceRefMavenSelector) DeepCopyInto(out *ResourceRefMavenSelector) { + *out = *in +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ResourceRefMavenSelector. +func (in *ResourceRefMavenSelector) DeepCopy() *ResourceRefMavenSelector { + if in == nil { + return nil + } + out := new(ResourceRefMavenSelector) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *ResourceRefSource) DeepCopyInto(out *ResourceRefSource) { + *out = *in + if in.MavenRef != nil { + in, out := &in.MavenRef, &out.MavenRef + *out = new(ResourceRefMavenSelector) + **out = **in + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ResourceRefSource. +func (in *ResourceRefSource) DeepCopy() *ResourceRefSource { + if in == nil { + return nil + } + out := new(ResourceRefSource) + in.DeepCopyInto(out) + return out +} diff --git a/libs/resources/src/minecraftserver/builder.go b/libs/resources/src/minecraftserver/builder.go index 70288db7..4ab652d2 100644 --- a/libs/resources/src/minecraftserver/builder.go +++ b/libs/resources/src/minecraftserver/builder.go @@ -6,16 +6,20 @@ SPDX-License-Identifier: GPL-3.0-or-later package resources import ( + "context" "fmt" shulkermciov1alpha1 "github.com/iamblueslime/shulker/libs/crds/v1alpha1" common "github.com/iamblueslime/shulker/libs/resources/src" "k8s.io/apimachinery/pkg/runtime" + "sigs.k8s.io/controller-runtime/pkg/client" ) type MinecraftServerResourceBuilder struct { Instance *shulkermciov1alpha1.MinecraftServer Scheme *runtime.Scheme + Client client.Client + Ctx context.Context } func (b *MinecraftServerResourceBuilder) ResourceBuilders() ([]common.ResourceBuilder, []common.ResourceBuilder) { diff --git a/libs/resources/src/minecraftserver/configmap.go b/libs/resources/src/minecraftserver/configmap.go index 862b1efc..64d626d9 100644 --- a/libs/resources/src/minecraftserver/configmap.go +++ b/libs/resources/src/minecraftserver/configmap.go @@ -64,17 +64,28 @@ func GetConfigMapDataFromConfigSpec(spec *shulkermciov1alpha1.MinecraftServerCon set -euo pipefail set -o xtrace - cp "$SHULKER_CONFIG_DIR/server.properties" "$SERVER_CONFIG_DIR/server.properties" + cp "${SHULKER_CONFIG_DIR}/server.properties" "${SERVER_CONFIG_DIR}/server.properties" if [ "${TYPE}" == "BUKKIT" ]; then - cp "$SHULKER_CONFIG_DIR/bukkit-config.yml" "$SERVER_CONFIG_DIR/bukkit.yml" + cp "${SHULKER_CONFIG_DIR}/bukkit-config.yml" "${SERVER_CONFIG_DIR}/bukkit.yml" elif [ "${TYPE}" == "SPIGOT" ]; then - cp "$SHULKER_CONFIG_DIR/bukkit-config.yml" "$SERVER_CONFIG_DIR/bukkit.yml" - cp "$SHULKER_CONFIG_DIR/spigot-config.yml" "$SERVER_CONFIG_DIR/spigot.yml" + cp "${SHULKER_CONFIG_DIR}/bukkit-config.yml" "${SERVER_CONFIG_DIR}/bukkit.yml" + cp "${SHULKER_CONFIG_DIR}/spigot-config.yml" "${SERVER_CONFIG_DIR}/spigot.yml" elif [ "${TYPE}" == "PAPER" ]; then - cp "$SHULKER_CONFIG_DIR/bukkit-config.yml" "$SERVER_CONFIG_DIR/bukkit.yml" - cp "$SHULKER_CONFIG_DIR/spigot-config.yml" "$SERVER_CONFIG_DIR/spigot.yml" - mkdir -p "$SERVER_CONFIG_DIR/config" - cp "$SHULKER_CONFIG_DIR/paper-global-config.yml" "$SERVER_CONFIG_DIR/config/paper-global.yml" + cp "${SHULKER_CONFIG_DIR}/bukkit-config.yml" "${SERVER_CONFIG_DIR}/bukkit.yml" + cp "${SHULKER_CONFIG_DIR}/spigot-config.yml" "${SERVER_CONFIG_DIR}/spigot.yml" + mkdir -p "${SERVER_CONFIG_DIR}/config" + cp "${SHULKER_CONFIG_DIR}/paper-global-config.yml" "${SERVER_CONFIG_DIR}/config/paper-global.yml" + fi + + if [ "${SERVER_WORLD_URL}" != "" ]; then + (cd "${SERVER_CONFIG_DIR}" && wget "${SERVER_WORLD_URL}" -O - | tar -xzv) + fi + + if [ "${SERVER_PLUGIN_URLS}" != "" ]; then + mkdir -p "${SERVER_CONFIG_DIR}/plugins" + for plugin_url in ${SERVER_PLUGIN_URLS//;/ }; do + (cd "${SERVER_CONFIG_DIR}/plugins" && wget "${plugin_url}") + done fi `) diff --git a/libs/resources/src/minecraftserver/pod.go b/libs/resources/src/minecraftserver/pod.go index 1f9b1b44..96d2e5e7 100644 --- a/libs/resources/src/minecraftserver/pod.go +++ b/libs/resources/src/minecraftserver/pod.go @@ -7,6 +7,7 @@ package resources import ( "fmt" + "strings" corev1 "k8s.io/api/core/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" @@ -14,6 +15,7 @@ import ( "sigs.k8s.io/controller-runtime/pkg/controller/controllerutil" shulkermciov1alpha1 "github.com/iamblueslime/shulker/libs/crds/v1alpha1" + resources "github.com/iamblueslime/shulker/libs/resources/src" ) const minecraftServerShulkerConfigDir = "/mnt/shulker/config" @@ -41,30 +43,18 @@ func (b *MinecraftServerResourcePodBuilder) Build() (client.Object, error) { func (b *MinecraftServerResourcePodBuilder) Update(object client.Object) error { pod := object.(*corev1.Pod) + initEnv, err := b.getInitEnv() + if err != nil { + return err + } + pod.Spec = corev1.PodSpec{ InitContainers: []corev1.Container{ { - Image: "alpine:latest", - Name: "init-fs", - Command: []string{"sh", fmt.Sprintf("%s/init-fs.sh", minecraftServerShulkerConfigDir)}, - Env: []corev1.EnvVar{ - { - Name: "SHULKER_CONFIG_DIR", - Value: minecraftServerShulkerConfigDir, - }, - { - Name: "SERVER_CONFIG_DIR", - Value: minecraftServerConfigDir, - }, - { - Name: "SERVER_DATA_DIR", - Value: minecraftServerDataDir, - }, - { - Name: "TYPE", - Value: getTypeFromVersionChannel(b.Instance.Spec.Version.Channel), - }, - }, + Image: "alpine:latest", + Name: "init-fs", + Command: []string{"sh", fmt.Sprintf("%s/init-fs.sh", minecraftServerShulkerConfigDir)}, + Env: initEnv, SecurityContext: b.getSecurityContext(), VolumeMounts: []corev1.VolumeMount{ { @@ -199,6 +189,57 @@ func getVersionEnvFromVersionChannel(channel shulkermciov1alpha1.MinecraftServer return "VERSION" } +func (b *MinecraftServerResourcePodBuilder) getInitEnv() ([]corev1.EnvVar, error) { + resourceRefResolver := resources.ResourceRefResolver{ + Client: b.Client, + Ctx: b.Ctx, + Namespace: b.Instance.Namespace, + } + + worldUrl, err := resourceRefResolver.ResolveUrl(b.Instance.Spec.Configuration.World) + if err != nil { + return []corev1.EnvVar{}, nil + } + + var pluginUrls []string + for _, ref := range b.Instance.Spec.Configuration.Plugins { + pluginUrl, err := resourceRefResolver.ResolveUrl(&ref) + if err != nil { + return []corev1.EnvVar{}, nil + } + pluginUrls = append(pluginUrls, pluginUrl) + } + + env := []corev1.EnvVar{ + { + Name: "SHULKER_CONFIG_DIR", + Value: minecraftServerShulkerConfigDir, + }, + { + Name: "SERVER_CONFIG_DIR", + Value: minecraftServerConfigDir, + }, + { + Name: "SERVER_DATA_DIR", + Value: minecraftServerDataDir, + }, + { + Name: "TYPE", + Value: getTypeFromVersionChannel(b.Instance.Spec.Version.Channel), + }, + { + Name: "SERVER_WORLD_URL", + Value: worldUrl, + }, + { + Name: "SERVER_PLUGIN_URLS", + Value: strings.Join(pluginUrls, ";"), + }, + } + + return env, nil +} + func (b *MinecraftServerResourcePodBuilder) getEnv() []corev1.EnvVar { env := []corev1.EnvVar{ { diff --git a/libs/resources/src/proxy/configmap.go b/libs/resources/src/proxy/configmap.go index 2493a4d0..ae92430d 100644 --- a/libs/resources/src/proxy/configmap.go +++ b/libs/resources/src/proxy/configmap.go @@ -66,30 +66,34 @@ func GetConfigMapDataFromConfigSpec(spec *shulkermciov1alpha1.ProxyConfiguration set -euo pipefail set -o xtrace - cp "$SHULKER_CONFIG_DIR/probe-readiness.sh" "$PROXY_DATA_DIR/probe-readiness.sh" - cat "$SHULKER_CONFIG_DIR/server-icon.png" | base64 -d > "$PROXY_DATA_DIR/server-icon.png" + cp "${SHULKER_CONFIG_DIR}/probe-readiness.sh" "${PROXY_DATA_DIR}/probe-readiness.sh" + cat "${SHULKER_CONFIG_DIR}/server-icon.png" | base64 -d > "${PROXY_DATA_DIR}/server-icon.png" if [ "${TYPE}" == "VELOCITY" ]; then - cp "$SHULKER_CONFIG_DIR/velocity-config.toml" "$PROXY_DATA_DIR/velocity.toml" - echo "dummy" > "$PROXY_DATA_DIR/forwarding.secret" + cp "${SHULKER_CONFIG_DIR}/velocity-config.toml" "${PROXY_DATA_DIR}/velocity.toml" + echo "dummy" > "${PROXY_DATA_DIR}/forwarding.secret" else - cp "$SHULKER_CONFIG_DIR/bungeecord-config.yml" "$PROXY_DATA_DIR/config.yml" + cp "${SHULKER_CONFIG_DIR}/bungeecord-config.yml" "${PROXY_DATA_DIR}/config.yml" fi mkdir -p "${PROXY_DATA_DIR}/plugins" - (cd "${PROXY_DATA_DIR}/plugins" && wget https://maven.jeremylvln.fr/artifactory/shulker/io/shulkermc/shulker-proxy-agent-velocity/0.0.1/shulker-proxy-agent-velocity-0.0.1.jar) + if [ "${TYPE}" == "VELOCITY" ]; then + (cd "${PROXY_DATA_DIR}/plugins" && wget https://maven.jeremylvln.fr/artifactory/shulker/io/shulkermc/shulker-proxy-agent-velocity/${SHULKER_PROXY_AGENT_VERSION}/shulker-proxy-agent-velocity-${SHULKER_PROXY_AGENT_VERSION}.jar) + else + (cd "${PROXY_DATA_DIR}/plugins" && wget https://maven.jeremylvln.fr/artifactory/shulker/io/shulkermc/shulker-proxy-agent-bungeecord/${SHULKER_PROXY_AGENT_VERSION}/shulker-proxy-agent-bungeecord-${SHULKER_PROXY_AGENT_VERSION}.jar) + fi `) configMapData["probe-readiness.sh"] = trimScript(` - #!/bin/sh - set -euo pipefail - set -o xtrace + #!/bin/sh + set -euo pipefail + set -o xtrace - if [ -f "/tmp/drain-lock" ]; then - echo "Drain lock found" && exit 1 - fi + if [ -f "/tmp/drain-lock" ]; then + echo "Drain lock found" && exit 1 + fi - bash /health.sh + bash /health.sh `) if spec.ServerIcon != "" { diff --git a/libs/resources/src/proxy/pod.go b/libs/resources/src/proxy/pod.go index 65ddc639..29f043ae 100644 --- a/libs/resources/src/proxy/pod.go +++ b/libs/resources/src/proxy/pod.go @@ -61,6 +61,10 @@ func (b *ProxyResourcePodBuilder) Update(object client.Object) error { Name: "TYPE", Value: getTypeFromVersionChannel(b.Instance.Spec.Version.Channel), }, + { + Name: "SHULKER_PROXY_AGENT_VERSION", + Value: "0.0.1", + }, }, SecurityContext: b.getSecurityContext(), VolumeMounts: []corev1.VolumeMount{ diff --git a/libs/resources/src/resourceref.go b/libs/resources/src/resourceref.go new file mode 100644 index 00000000..45f12775 --- /dev/null +++ b/libs/resources/src/resourceref.go @@ -0,0 +1,76 @@ +package resources + +import ( + "context" + "errors" + "fmt" + "net/url" + "strings" + + "github.com/iamblueslime/shulker/libs/crds/v1alpha1" + corev1 "k8s.io/api/core/v1" + "k8s.io/apimachinery/pkg/types" + "sigs.k8s.io/controller-runtime/pkg/client" +) + +type ResourceRefResolver struct { + client.Client + Ctx context.Context + Namespace string +} + +func (r *ResourceRefResolver) ResolveUrl(resourceRef *v1alpha1.ResourceRef) (string, error) { + if resourceRef == nil { + return "", errors.New("resourceRef is nil") + } + + if resourceRef.Url != "" { + return resourceRef.Url, nil + } + + if resourceRef.UrlFrom != nil { + if resourceRef.UrlFrom.MavenRef != nil { + return r.resolveMavenRefUrl(resourceRef.UrlFrom.MavenRef) + } + } + + return "", errors.New("no resourceRef combination") +} + +func (r *ResourceRefResolver) resolveMavenRefUrl(mavenSelector *v1alpha1.ResourceRefMavenSelector) (string, error) { + mavenUrl, err := url.Parse(fmt.Sprintf( + "%[1]s/%[2]s/%[3]s/%[4]s/%[3]s-%[4]s.jar", + mavenSelector.Repository, + strings.ReplaceAll(mavenSelector.GroupId, ".", "/"), + mavenSelector.ArtifactId, + mavenSelector.Version, + )) + if err != nil { + return "", err + } + + if mavenSelector.CredentialsSecretName != "" { + secret := &corev1.Secret{} + err := r.Get(r.Ctx, types.NamespacedName{ + Namespace: r.Namespace, + Name: mavenSelector.CredentialsSecretName, + }, secret) + if err != nil { + return "", err + } + + username, ok := secret.Data["username"] + if !ok { + return "", errors.New("missing username in credential secret") + } + + password, ok := secret.Data["password"] + if !ok { + return "", errors.New("missing password in credential secret") + } + + mavenUrl.User = url.UserPassword(string(username), string(password)) + } + + return mavenUrl.String(), nil +} diff --git a/support/shulker-proxy-agent-common/src/main/kotlin/io/shulkermc/proxyagent/features/limbo/LimboFeature.kt b/support/shulker-proxy-agent-common/src/main/kotlin/io/shulkermc/proxyagent/features/limbo/LimboFeature.kt index 871b1c7b..74cf048f 100644 --- a/support/shulker-proxy-agent-common/src/main/kotlin/io/shulkermc/proxyagent/features/limbo/LimboFeature.kt +++ b/support/shulker-proxy-agent-common/src/main/kotlin/io/shulkermc/proxyagent/features/limbo/LimboFeature.kt @@ -29,10 +29,10 @@ class LimboFeature( if (limboServers.hasNext()) { val firstLimboServer = limboServers.next() - ServerPreConnectHookResult(Optional.of(firstLimboServer)) - } else { - player.disconnect(MSG_NO_LIMBO_FOUND) + return ServerPreConnectHookResult(Optional.of(firstLimboServer)) } + + player.disconnect(MSG_NO_LIMBO_FOUND) } return ServerPreConnectHookResult(Optional.empty()) diff --git a/test/bases/cluster.yaml b/test/bases/cluster.yaml deleted file mode 100644 index cde31d25..00000000 --- a/test/bases/cluster.yaml +++ /dev/null @@ -1,5 +0,0 @@ -apiVersion: shulkermc.io/v1alpha1 -kind: MinecraftCluster -metadata: - name: my-cluster -spec: {} diff --git a/test/bases/minecraftserver-lobby.yaml b/test/bases/minecraftserver-lobby.yaml deleted file mode 100644 index 96a74de5..00000000 --- a/test/bases/minecraftserver-lobby.yaml +++ /dev/null @@ -1,28 +0,0 @@ -apiVersion: shulkermc.io/v1alpha1 -kind: MinecraftServerDeployment -metadata: - name: lobby -spec: - clusterRef: - name: my-cluster - replicas: 1 - template: - spec: - tags: - - limbo - version: - channel: Paper - name: '1.19.2' - config: - maxPlayers: 100 - podOverrides: - affinity: - nodeAffinity: - preferredDuringSchedulingIgnoredDuringExecution: - - weight: 1 - preference: - matchExpressions: - - key: cloud.google.com/gke-preemptible - operator: In - values: - - 'true' diff --git a/test/bases/proxy.yaml b/test/bases/proxy.yaml deleted file mode 100644 index 1d512774..00000000 --- a/test/bases/proxy.yaml +++ /dev/null @@ -1,29 +0,0 @@ -apiVersion: shulkermc.io/v1alpha1 -kind: ProxyDeployment -metadata: - name: proxy -spec: - clusterRef: - name: my-cluster - replicas: 1 - service: - type: LoadBalancer - externalTrafficPolicy: Local - template: - spec: - version: - channel: Velocity - name: latest - config: - maxPlayers: 100 - podOverrides: - affinity: - nodeAffinity: - preferredDuringSchedulingIgnoredDuringExecution: - - weight: 1 - preference: - matchExpressions: - - key: cloud.google.com/gke-preemptible - operator: In - values: - - 'true' diff --git a/test/kustomization.yaml b/test/kustomization.yaml deleted file mode 100644 index 211b3537..00000000 --- a/test/kustomization.yaml +++ /dev/null @@ -1,4 +0,0 @@ -resources: -- bases/cluster.yaml -- bases/proxy.yaml -- bases/minecraftserver-lobby.yaml