Skip to content

Commit

Permalink
Extend agones test to check against previous versions as well (#1013)
Browse files Browse the repository at this point in the history
  • Loading branch information
Jake-Shadle authored Sep 5, 2024
1 parent c5bbe8a commit 9acd7c0
Show file tree
Hide file tree
Showing 8 changed files with 129 additions and 29 deletions.
1 change: 1 addition & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

4 changes: 3 additions & 1 deletion build/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@ endif
# Set this value if you want to use an external registry
REPOSITORY ?= ""
IMAGE_TAG ?= ${REPOSITORY}quilkin:$(package_version)
PREV_IMAGE_TAG ?= us-docker.pkg.dev/quilkin/release/quilkin:0.9.0
MINIKUBE_PROFILE ?= quilkin
CARGO_TARGET_DIR ?= /workspace/target/build-image
common_rust_args := -v $(project_path):/workspace -w /workspace \
Expand Down Expand Up @@ -214,6 +215,7 @@ test-agones:

run-test-agones: ensure-kube-dirs
run-test-agones:
docker image pull ${PREV_IMAGE_TAG}
docker run --rm $(DOCKER_RUN_ARGS) $(common_rust_args) -w /workspace/crates/agones \
--entrypoint=cargo $(BUILD_IMAGE_TAG) clippy --tests -- -D warnings
docker run --rm $(DOCKER_RUN_ARGS) $(common_rust_args) -w /workspace/crates/agones \
Expand All @@ -222,7 +224,7 @@ run-test-agones:
docker run --rm $(DOCKER_RUN_ARGS) $(common_rust_args) $(kube_mount_args) -w /workspace/crates/agones \
--entrypoint=kubectl $(BUILD_IMAGE_TAG) get ns
docker run --rm $(DOCKER_RUN_ARGS) $(common_rust_args) $(kube_mount_args) -w /workspace/crates/agones \
-e "RUST_BACKTRACE=1" -e "IMAGE_TAG=${IMAGE_TAG}" --entrypoint=cargo $(BUILD_IMAGE_TAG) test $(ARGS)
-e "RUST_BACKTRACE=1" -e "IMAGE_TAG=${IMAGE_TAG}" -e "PREV_IMAGE_TAG=${PREV_IMAGE_TAG}" --entrypoint=cargo $(BUILD_IMAGE_TAG) test $(ARGS)

# Convenience target to build and push quilkin images to a repository.
# Use `REPOSITORY` arg to specify the repository to push to.
Expand Down
1 change: 1 addition & 0 deletions crates/agones/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ workspace = true

[dependencies]
base64.workspace = true
either = "1.13"
futures.workspace = true
k8s-openapi.workspace = true
kube = { workspace = true, features = ["openssl-tls", "client", "derive", "runtime"] }
Expand Down
24 changes: 17 additions & 7 deletions crates/agones/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -60,10 +60,9 @@ mod provider;
mod relay;
mod sidecar;

#[allow(dead_code)]
static CLIENT: OnceCell<Client> = OnceCell::const_new();
#[allow(dead_code)]
const IMAGE_TAG: &str = "IMAGE_TAG";
pub static CLIENT: OnceCell<Client> = OnceCell::const_new();
pub const IMAGE_TAG: &str = "IMAGE_TAG";
pub const PREV_IMAGE_TAG: &str = "PREV_IMAGE_TAG";
const DELETE_DELAY_SECONDS: &str = "DELETE_DELAY_SECONDS";
/// A simple udp server that returns packets that are sent to it.
/// See: <https://github.com/googleforgames/agones/tree/main/examples/simple-game-server>
Expand All @@ -82,6 +81,7 @@ pub struct Client {
pub namespace: String,
/// The name and tag of the Quilkin image being tested
pub quilkin_image: String,
pub prev_quilkin_image: String,
}

impl Client {
Expand All @@ -100,7 +100,8 @@ impl Client {
Client {
kubernetes: client.clone(),
namespace: setup_namespace(client).await,
quilkin_image: env::var(IMAGE_TAG).unwrap(),
quilkin_image: env::var(IMAGE_TAG).expect(IMAGE_TAG),
prev_quilkin_image: env::var(PREV_IMAGE_TAG).expect(PREV_IMAGE_TAG),
}
})
.await
Expand Down Expand Up @@ -303,14 +304,15 @@ pub async fn create_agones_rbac_read_account(
rbac_name.into()
}

/// Create a Deployment with a singular Quilkin proxy, and return it's address.
/// Create a Deployment with a singular Quilkin proxy, and return its address.
/// The `name` variable is used as role={name} for label lookup.
pub async fn quilkin_proxy_deployment(
client: &Client,
deployments: Api<Deployment>,
name: String,
host_port: u16,
management_server: String,
current: bool,
) -> SocketAddr {
let pp = PostParams::default();
let mut container = quilkin_container(
Expand All @@ -320,6 +322,7 @@ pub async fn quilkin_proxy_deployment(
format!("--management-server={management_server}"),
]),
None,
current,
);

// we'll use a host port, since spinning up a load balancer takes a long time.
Expand Down Expand Up @@ -580,10 +583,17 @@ pub fn quilkin_container(
client: &Client,
args: Option<Vec<String>>,
volume_mount: Option<String>,
current: bool,
) -> Container {
let image = if current {
client.quilkin_image.clone()
} else {
client.prev_quilkin_image.clone()
};

let mut container = Container {
name: "quilkin".into(),
image: Some(client.quilkin_image.clone()),
image: Some(image),
args,
env: Some(vec![EnvVar {
name: "RUST_LOG".to_string(),
Expand Down
2 changes: 1 addition & 1 deletion crates/agones/src/pod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ mod tests {
..Default::default()
},
spec: Some(PodSpec {
containers: vec![quilkin_container(&client, Some(cmds), None)],
containers: vec![quilkin_container(&client, Some(cmds), None, true)],
..Default::default()
}),
status: None,
Expand Down
3 changes: 2 additions & 1 deletion crates/agones/src/provider.rs
Original file line number Diff line number Diff line change
Expand Up @@ -78,6 +78,7 @@ mod tests {
PROXY_DEPLOYMENT.into(),
7005,
"http://quilkin-manage-agones:7800".into(),
true,
)
.await;

Expand Down Expand Up @@ -210,7 +211,7 @@ mod tests {
..Default::default()
}),
spec: Some(PodSpec {
containers: vec![quilkin_container(client, Some(args), None)],
containers: vec![quilkin_container(client, Some(args), None, true)],
service_account_name: Some(rbac_name),
..Default::default()
}),
Expand Down
122 changes: 103 additions & 19 deletions crates/agones/src/relay.rs
Original file line number Diff line number Diff line change
Expand Up @@ -51,12 +51,23 @@ mod tests {
TOKEN_KEY,
};

const SLOW: Duration = Duration::from_secs(30);

#[tokio::test]
#[serial]
/// Test for Agones Provider integration. Since this will look at all GameServers in the namespace
/// for this test, we should only run Agones integration test in a serial manner, since they
/// could easily collide with each other.
async fn agones_token_router() {
run_test(true, true, true, 0).await;
run_test(true, true, false, 1).await;
run_test(true, false, true, 2).await;
run_test(false, true, true, 3).await;
}

async fn run_test(proxy: bool, relay: bool, agent: bool, id: u8) {
println!("running agones_token_router {id}");

let client = Client::new().await;
let config_maps: Api<ConfigMap> = client.namespaced_api();
let deployments: Api<Deployment> = client.namespaced_api();
Expand All @@ -67,15 +78,17 @@ mod tests {
let dp = DeleteParams::default();

let config_map = create_token_router_config(&config_maps).await;
agones_agent_deployment(&client, deployments.clone()).await;
let (relay_name, agent_name) =
agones_agent_deployment(&client, deployments.clone(), relay, agent, id).await;

let relay_proxy_name = "quilkin-relay-proxy";
let relay_proxy_name = format!("quilkin-relay-proxy-{id}");
let proxy_address = quilkin_proxy_deployment(
&client,
deployments.clone(),
relay_proxy_name.into(),
relay_proxy_name.clone(),
7005,
"http://quilkin-relay-agones:7800".into(),
format!("http://{relay_name}:7800"),
proxy,
)
.await;

Expand All @@ -98,8 +111,12 @@ mod tests {

// Proxy Deployment should be ready, since there is now an endpoint
if timeout(
Duration::from_secs(30),
await_condition(deployments.clone(), relay_proxy_name, is_deployment_ready()),
SLOW,
await_condition(
deployments.clone(),
&relay_proxy_name,
is_deployment_ready(),
),
)
.await
.is_err()
Expand Down Expand Up @@ -157,15 +174,77 @@ mod tests {
}
assert!(failed, "Packet should have failed");

println!("deleting resources...");
use either::Either;
let cm_name = config_map.name_unchecked();
// cleanup
config_maps
.delete(&config_map.name_unchecked(), &dp)
match config_maps
.delete(&cm_name, &dp)
.await
.unwrap();
.expect("failed to delete config map")
{
Either::Left(_) => {
timeout(
SLOW,
await_condition(
deployments.clone(),
&relay_proxy_name,
kube::runtime::conditions::is_deleted(&cm_name),
),
)
.await
.expect("failed to delete config map within timeout")
.expect("failed to delete config map");
println!("...config map deleted");
}
Either::Right(_) => {
println!("config map deleted");
}
}

async fn delete_deployment(dp: &Api<Deployment>, name: &str) -> Result<(), kube::Error> {
async fn inner(dp: &Api<Deployment>, name: &str) -> Result<(), kube::Error> {
if let Either::Left(d) = dp.delete(name, &DeleteParams::default()).await? {
await_condition(
dp.clone(),
name,
kube::runtime::conditions::is_deleted(&d.uid().unwrap()),
)
.await
.map_err(|err| kube::Error::Service(Box::new(err)))?;
}

Ok(())
}

timeout(SLOW, inner(dp, name)).await.map_err(|_err| {
kube::Error::Api(kube::error::ErrorResponse {
message: format!("failed to delete deployment {name} within {SLOW:?}"),
status: String::new(),
reason: String::new(),
code: 408,
})
})??;
println!("deployment {name} deleted");
Ok(())
}

tokio::try_join!(
delete_deployment(&deployments, &relay_proxy_name),
delete_deployment(&deployments, &agent_name),
delete_deployment(&deployments, &relay_name),
)
.expect("failed to delete deployment(s) within timeout");
}

/// Deploys the Agent and Relay Server Deployments and Services
async fn agones_agent_deployment(client: &Client, deployments: Api<Deployment>) {
async fn agones_agent_deployment(
client: &Client,
deployments: Api<Deployment>,
relay: bool,
agent: bool,
id: u8,
) -> (String, String) {
let service_accounts: Api<ServiceAccount> = client.namespaced_api();
let cluster_roles: Api<ClusterRole> = Api::all(client.kubernetes.clone());
let role_bindings: Api<RoleBinding> = client.namespaced_api();
Expand All @@ -177,6 +256,8 @@ mod tests {
create_agones_rbac_read_account(client, service_accounts, cluster_roles, role_bindings)
.await;

let relay_name = format!("quilkin-relay-agones-{id}");

// Setup the relay
let args = [
"relay",
Expand All @@ -189,7 +270,7 @@ mod tests {
let labels = BTreeMap::from([("role".to_string(), "relay".to_string())]);
let deployment = Deployment {
metadata: ObjectMeta {
name: Some("quilkin-relay-agones".into()),
name: Some(relay_name.clone()),
labels: Some(labels.clone()),
..Default::default()
},
Expand All @@ -205,7 +286,7 @@ mod tests {
..Default::default()
}),
spec: Some(PodSpec {
containers: vec![quilkin_container(client, Some(args), None)],
containers: vec![quilkin_container(client, Some(args), None, relay)],
service_account_name: Some(rbac_name.clone()),
..Default::default()
}),
Expand All @@ -219,7 +300,7 @@ mod tests {
// relay service
let service = Service {
metadata: ObjectMeta {
name: Some("quilkin-relay-agones".into()),
name: Some(relay_name.clone()),
..Default::default()
},
spec: Some(ServiceSpec {
Expand Down Expand Up @@ -248,8 +329,8 @@ mod tests {

let name = relay_deployment.name_unchecked();
let result = timeout(
Duration::from_secs(30),
await_condition(deployments.clone(), name.as_str(), is_deployment_ready()),
SLOW,
await_condition(deployments.clone(), &name, is_deployment_ready()),
)
.await;
if result.is_err() {
Expand All @@ -259,11 +340,13 @@ mod tests {
}
result.unwrap().expect("Should have a relay deployment");

let agent_name = format!("quilkin-agones-agent-{id}");

// agent deployment
let args = [
"agent",
"--relay",
"http://quilkin-relay-agones:7900",
&format!("http://{relay_name}:7900"),
"agones",
"--config-namespace",
client.namespace.as_str(),
Expand All @@ -275,7 +358,7 @@ mod tests {
let labels = BTreeMap::from([("role".to_string(), "agent".to_string())]);
let deployment = Deployment {
metadata: ObjectMeta {
name: Some("quilkin-agones-agent".into()),
name: Some(agent_name.clone()),
labels: Some(labels.clone()),
..Default::default()
},
Expand All @@ -291,7 +374,7 @@ mod tests {
..Default::default()
}),
spec: Some(PodSpec {
containers: vec![quilkin_container(client, Some(args), None)],
containers: vec![quilkin_container(client, Some(args), None, agent)],
service_account_name: Some(rbac_name),
..Default::default()
}),
Expand All @@ -303,7 +386,7 @@ mod tests {
let agent_deployment = deployments.create(&pp, &deployment).await.unwrap();
let name = agent_deployment.name_unchecked();
let result = timeout(
Duration::from_secs(30),
SLOW,
await_condition(deployments.clone(), name.as_str(), is_deployment_ready()),
)
.await;
Expand All @@ -312,5 +395,6 @@ mod tests {
panic!("Agent Deployment should be ready");
}
result.unwrap().expect("Should have an agent deployment");
(relay_name, agent_name)
}
}
1 change: 1 addition & 0 deletions crates/agones/src/sidecar.rs
Original file line number Diff line number Diff line change
Expand Up @@ -100,6 +100,7 @@ clusters:
&client,
Some(vec!["proxy".into()]),
Some(mount_name.clone()),
true,
));

template.volumes = Some(vec![Volume {
Expand Down

0 comments on commit 9acd7c0

Please sign in to comment.