Skip to content

Commit

Permalink
feat: support the override of agones health check in proxy and minecr…
Browse files Browse the repository at this point in the history
…aft template
  • Loading branch information
HookWoods committed Sep 3, 2024
1 parent ee0108a commit 630f66b
Show file tree
Hide file tree
Showing 11 changed files with 235 additions and 16 deletions.
24 changes: 24 additions & 0 deletions kube/helm/templates/crds/shulkermc.io_minecraftserverfleets.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -1005,6 +1005,30 @@ spec:
type: object
nullable: true
type: array
health:
description: Overrides Agones Health checks
nullable: true
properties:
disabled:
description: Specify whether the health check should be disabled.
nullable: true
type: boolean
failureThreshold:
description: Specify how much health failure is tolerated before the GameServer is considered unhealthy.
format: int32
nullable: true
type: integer
initialDelaySeconds:
description: Specify the initial delay in seconds before the first health check is performed.
format: int32
nullable: true
type: integer
periodSeconds:
description: Specify the period in seconds between health checks.
format: int32
nullable: true
type: integer
type: object
image:
description: Image to use as replacement for the built-in one
nullable: true
Expand Down
24 changes: 24 additions & 0 deletions kube/helm/templates/crds/shulkermc.io_minecraftservers.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -776,6 +776,30 @@ spec:
type: object
nullable: true
type: array
health:
description: Overrides Agones Health checks
nullable: true
properties:
disabled:
description: Specify whether the health check should be disabled.
nullable: true
type: boolean
failureThreshold:
description: Specify how much health failure is tolerated before the GameServer is considered unhealthy.
format: int32
nullable: true
type: integer
initialDelaySeconds:
description: Specify the initial delay in seconds before the first health check is performed.
format: int32
nullable: true
type: integer
periodSeconds:
description: Specify the period in seconds between health checks.
format: int32
nullable: true
type: integer
type: object
image:
description: Image to use as replacement for the built-in one
nullable: true
Expand Down
24 changes: 24 additions & 0 deletions kube/helm/templates/crds/shulkermc.io_proxyfleets.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -984,6 +984,30 @@ spec:
type: object
nullable: true
type: array
health:
description: Overrides Agones Health checks
nullable: true
properties:
disabled:
description: Specify whether the health check should be disabled.
nullable: true
type: boolean
failureThreshold:
description: Specify how much health failure is tolerated before the GameServer is considered unhealthy.
format: int32
nullable: true
type: integer
initialDelaySeconds:
description: Specify the initial delay in seconds before the first health check is performed.
format: int32
nullable: true
type: integer
periodSeconds:
description: Specify the period in seconds between health checks.
format: int32
nullable: true
type: integer
type: object
image:
description: Image to use as replacement for the built-in one
nullable: true
Expand Down
7 changes: 7 additions & 0 deletions packages/google-agones-crds/src/v1/game_server.rs
Original file line number Diff line number Diff line change
Expand Up @@ -33,12 +33,19 @@ pub struct GameServerPortSpec {
#[derive(Deserialize, Serialize, Clone, Debug, JsonSchema, Default)]
#[serde(rename_all = "camelCase")]
pub struct GameServerHealthSpec {
/// Specify whether the health check should be disabled.
#[serde(skip_serializing_if = "Option::is_none")]
pub disabled: Option<bool>,

/// Specify the period in seconds between health checks.
#[serde(skip_serializing_if = "Option::is_none")]
pub period_seconds: Option<i32>,

/// Specify how much health failure is tolerated before the GameServer is considered unhealthy.
#[serde(skip_serializing_if = "Option::is_none")]
pub failure_threshold: Option<i32>,

/// Specify the initial delay in seconds before the first health check is performed.
#[serde(skip_serializing_if = "Option::is_none")]
pub initial_delay_seconds: Option<i32>,
}
Expand Down
8 changes: 6 additions & 2 deletions packages/shulker-crds/src/v1alpha1/minecraft_server.rs
Original file line number Diff line number Diff line change
@@ -1,13 +1,13 @@
use std::collections::BTreeMap;

use super::minecraft_cluster::MinecraftClusterRef;
use google_agones_crds::v1::game_server::GameServerHealthSpec;
use k8s_openapi::apimachinery::pkg::apis::meta::v1::Condition;
use kube::CustomResource;
use schemars::JsonSchema;
use serde::{Deserialize, Serialize};
use strum::{Display, IntoStaticStr};

use super::minecraft_cluster::MinecraftClusterRef;

use crate::{condition::HasConditions, resourceref::ResourceRefSpec, schemas::ImageOverrideSpec};

#[derive(CustomResource, Deserialize, Serialize, Clone, Debug, JsonSchema, Default)]
Expand Down Expand Up @@ -206,6 +206,10 @@ pub struct MinecraftServerPodOverridesSpec {
/// Extra ports to add to the created `Pod`'s main container
#[serde(skip_serializing_if = "Option::is_none")]
pub ports: Option<Vec<k8s_openapi::api::core::v1::ContainerPort>>,

/// Overrides Agones Health checks
#[serde(skip_serializing_if = "Option::is_none")]
pub health: Option<GameServerHealthSpec>,
}

/// The status object of `MinecraftServer`
Expand Down
8 changes: 6 additions & 2 deletions packages/shulker-crds/src/v1alpha1/proxy_fleet.rs
Original file line number Diff line number Diff line change
@@ -1,13 +1,13 @@
use std::collections::BTreeMap;

use super::minecraft_cluster::MinecraftClusterRef;
use google_agones_crds::v1::game_server::GameServerHealthSpec;
use k8s_openapi::apimachinery::pkg::apis::meta::v1::Condition;
use kube::CustomResource;
use schemars::JsonSchema;
use serde::{Deserialize, Serialize};
use strum::{Display, IntoStaticStr};

use super::minecraft_cluster::MinecraftClusterRef;

use crate::{
condition::HasConditions,
resourceref::ResourceRefSpec,
Expand Down Expand Up @@ -221,6 +221,10 @@ pub struct ProxyFleetTemplatePodOverridesSpec {
/// Extra ports to add to the created `Pod`'s main container
#[serde(skip_serializing_if = "Option::is_none")]
pub ports: Option<Vec<k8s_openapi::api::core::v1::ContainerPort>>,

/// Overrides Agones Health checks
#[serde(skip_serializing_if = "Option::is_none")]
pub health: Option<GameServerHealthSpec>,
}

#[derive(Deserialize, Serialize, Clone, Debug, Default, JsonSchema)]
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -74,6 +74,7 @@ lazy_static! {
volume_mounts: None,
volumes: None,
ports: None,
health: None,
})
},
status: None,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -153,18 +153,42 @@ impl<'a> GameServerBuilder {
) -> Result<GameServerSpec, anyhow::Error> {
let pod_template_spec =
Self::get_pod_template_spec(resourceref_resolver, context, minecraft_server).await?;
let spec = &minecraft_server.spec;

// Default health configuration
let default_health = GameServerHealthSpec {
disabled: Some(false),
initial_delay_seconds: Some(30),
period_seconds: Some(15),
failure_threshold: Some(5),
};

// Initialize health_spec with the default values
let mut health_spec = default_health.clone();

// Check if pod_overrides is present
if let Some(pod_overrides) = &spec.pod_overrides {
// Check if health is present within pod_overrides
if let Some(health) = &pod_overrides.health {
// Override the defaults with the values from health if they are present
health_spec.disabled = health.disabled.or(default_health.disabled);
health_spec.initial_delay_seconds = health
.initial_delay_seconds
.or(default_health.initial_delay_seconds);
health_spec.period_seconds =
health.period_seconds.or(default_health.period_seconds);
health_spec.failure_threshold = health
.failure_threshold
.or(default_health.failure_threshold);
}
}

let game_server_spec = GameServerSpec {
ports: Some(vec![]),
eviction: Some(GameServerEvictionSpec {
safe: "OnUpgrade".to_string(),
}),
health: Some(GameServerHealthSpec {
disabled: Some(false),
initial_delay_seconds: Some(30),
period_seconds: Some(15),
failure_threshold: Some(5),
}),
health: Some(health_spec),
template: pod_template_spec,
};

Expand Down Expand Up @@ -628,6 +652,7 @@ impl<'a> GameServerBuilder {

#[cfg(test)]
mod tests {
use google_agones_crds::v1::game_server::GameServerHealthSpec;
use k8s_openapi::api::core::v1::{
ContainerPort, EmptyDirVolumeSource, LocalObjectReference, Volume, VolumeMount,
};
Expand Down Expand Up @@ -1073,6 +1098,43 @@ mod tests {
);
}

#[tokio::test]
async fn get_health_settings_from_pod_overrides() {
// G
let client = create_client_mock();
let resourceref_resolver = ResourceRefResolver::new(client);
let mut server = TEST_SERVER.clone();
server.spec.pod_overrides.as_mut().unwrap().health = Some(GameServerHealthSpec {
disabled: Some(true),
initial_delay_seconds: Some(10),
period_seconds: Some(20),
failure_threshold: Some(3),
});
let context = super::GameServerBuilderContext {
cluster: &TEST_CLUSTER,
agent_config: &AgentConfig {
maven_repository: constants::SHULKER_PLUGIN_REPOSITORY.to_string(),
version: constants::SHULKER_PLUGIN_VERSION.to_string(),
},
};

// W
let game_server_spec = super::GameServerBuilder::get_game_server_spec(
&resourceref_resolver,
&context,
&server,
)
.await
.unwrap();

// T
let health_spec = game_server_spec.health.unwrap();
assert_eq!(health_spec.disabled, Some(true));
assert_eq!(health_spec.initial_delay_seconds, Some(10));
assert_eq!(health_spec.period_seconds, Some(20));
assert_eq!(health_spec.failure_threshold, Some(3));
}

#[tokio::test]
async fn get_env_merges_env_overrides() {
// G
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -95,6 +95,7 @@ lazy_static! {
volume_mounts: None,
volumes: None,
ports: None,
health: None,
})
},
},
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -85,6 +85,7 @@ lazy_static! {
volume_mounts: None,
volumes: None,
ports: None,
health: None,
})
},
},
Expand Down
79 changes: 73 additions & 6 deletions packages/shulker-operator/src/reconcilers/proxy_fleet/fleet.rs
Original file line number Diff line number Diff line change
Expand Up @@ -158,17 +158,42 @@ impl<'a> FleetBuilder {
proxy_fleet: &ProxyFleet,
) -> Result<GameServerSpec, anyhow::Error> {
let pod_template_spec = self.get_pod_template_spec(context, proxy_fleet).await?;
let spec = &proxy_fleet.spec.template.spec;

// Default health configuration
let default_health = GameServerHealthSpec {
disabled: Some(false),
initial_delay_seconds: Some(30),
period_seconds: Some(15),
failure_threshold: Some(5),
};

// Initialize health_spec with the default values
let mut health_spec = default_health.clone();

// Check if pod_overrides is present
if let Some(pod_overrides) = &spec.pod_overrides {
// Check if health is present within pod_overrides
if let Some(health) = &pod_overrides.health {
// Override the defaults with the values from health if they are present
health_spec.disabled = health.disabled.or(default_health.disabled);
health_spec.initial_delay_seconds = health
.initial_delay_seconds
.or(default_health.initial_delay_seconds);
health_spec.period_seconds =
health.period_seconds.or(default_health.period_seconds);
health_spec.failure_threshold = health
.failure_threshold
.or(default_health.failure_threshold);
}
}

let game_server_spec = GameServerSpec {
ports: Some(vec![]),
eviction: Some(GameServerEvictionSpec {
safe: "OnUpgrade".to_string(),
}),
health: Some(GameServerHealthSpec {
disabled: Some(false),
initial_delay_seconds: Some(30),
period_seconds: Some(10),
failure_threshold: Some(5),
}),
health: Some(health_spec),
template: pod_template_spec,
};

Expand Down Expand Up @@ -695,6 +720,7 @@ impl<'a> FleetBuilder {

#[cfg(test)]
mod tests {
use google_agones_crds::v1::game_server::GameServerHealthSpec;
use k8s_openapi::api::core::v1::{
ContainerPort, EmptyDirVolumeSource, LocalObjectReference, Volume, VolumeMount,
};
Expand Down Expand Up @@ -928,6 +954,47 @@ mod tests {
);
}

#[tokio::test]
async fn get_health_settings_from_pod_overrides() {
// G
let client = create_client_mock();
let builder = super::FleetBuilder::new(client);
let mut proxy_fleet = TEST_PROXY_FLEET.clone();
proxy_fleet
.spec
.template
.spec
.pod_overrides
.as_mut()
.unwrap()
.health = Some(GameServerHealthSpec {
disabled: Some(true),
initial_delay_seconds: Some(10),
period_seconds: Some(20),
failure_threshold: Some(3),
});
let context = super::FleetBuilderContext {
cluster: &TEST_CLUSTER,
agent_config: &AgentConfig {
maven_repository: constants::SHULKER_PLUGIN_REPOSITORY.to_string(),
version: constants::SHULKER_PLUGIN_VERSION.to_string(),
},
};

// W
let game_server_spec =
super::FleetBuilder::get_game_server_spec(&builder, &context, &proxy_fleet)
.await
.unwrap();

// T
let health_spec = game_server_spec.health.unwrap();
assert_eq!(health_spec.disabled, Some(true));
assert_eq!(health_spec.initial_delay_seconds, Some(10));
assert_eq!(health_spec.period_seconds, Some(20));
assert_eq!(health_spec.failure_threshold, Some(3));
}

#[tokio::test]
async fn get_pod_template_spec_contains_image_pull_secrets() {
// G
Expand Down

0 comments on commit 630f66b

Please sign in to comment.