From 6d0907e7bc587419093608368687f09f90c9a71a Mon Sep 17 00:00:00 2001 From: Siegfried Weber Date: Fri, 23 Jul 2021 10:48:58 +0200 Subject: [PATCH] Test environment variable KUBECONFIG in pods --- tests/environment.rs | 73 ++++++++++++++++++++++++++++++++++++++ tests/repository.rs | 47 ++++++++---------------- tests/util/mod.rs | 1 + tests/util/result.rs | 36 +++++++++++++++++++ tests/util/services.rs | 4 +++ tests/util/test_package.rs | 7 ++-- 6 files changed, 134 insertions(+), 34 deletions(-) create mode 100644 tests/environment.rs create mode 100644 tests/util/result.rs diff --git a/tests/environment.rs b/tests/environment.rs new file mode 100644 index 0000000..d67bab3 --- /dev/null +++ b/tests/environment.rs @@ -0,0 +1,73 @@ +mod util; + +use anyhow::Result; +use integration_test_commons::test::prelude::*; + +use util::{ + repository::{StackableRepository, StackableRepositoryInstance}, + result::TestResult, + test_package::TestPackage, +}; + +#[tokio::test] +async fn kubeconfig_should_be_set() -> Result<()> { + let client = KubeClient::new().await?; + + let mut result = TestResult::default(); + + // Set up repository and pod + + // The job terminates successfully if the content of the environment + // variable KUBECONFIG is not empty. + let job = TestPackage { + name: String::from("kubeconfig-test-job"), + version: String::from("1.0.0"), + job: true, + script: String::from(indoc!( + r#" + #!/bin/sh + + test -n "$KUBECONFIG" + "# + )), + }; + + let repository = StackableRepository { + name: String::from("kubeconfig-test-repository"), + packages: vec![job.to_owned()], + }; + let repository_result = StackableRepositoryInstance::new(&repository, &client).await; + result.combine(&repository_result); + + let pod_result = client + .create(&job.pod_spec("agent-service-integration-test-kubeconfig")) + .await; + result.combine(&pod_result); + + // Verify that the job terminated successfully + + if let Ok(pod) = &pod_result { + let job_result = client + .verify_status::(&pod, |pod| { + let phase = pod.status.as_ref().and_then(|status| status.phase.as_ref()); + phase == Some(&String::from("Succeeded")) + }) + .await; + result.combine(&job_result); + } + + // Tear down pod and repository + + if let Ok(pod) = pod_result { + let deletion_result = client.delete(pod).await; + result.combine(&deletion_result); + } + if let Ok(repository) = repository_result { + let close_result = repository.close(&client).await; + result.combine(&close_result); + } + + // Return test result + + result.into() +} diff --git a/tests/repository.rs b/tests/repository.rs index 1ca9bce..1b9b2eb 100644 --- a/tests/repository.rs +++ b/tests/repository.rs @@ -1,13 +1,12 @@ mod util; -use std::fmt::Debug; - -use anyhow::{anyhow, Result}; +use anyhow::Result; use integration_test_commons::test::prelude::*; use uuid::Uuid; use crate::util::{ repository::{StackableRepository, StackableRepositoryInstance}, + result::TestResult, services::noop_service, }; @@ -15,7 +14,7 @@ use crate::util::{ async fn invalid_or_unreachable_repositories_should_be_ignored() -> Result<()> { let client = KubeClient::new().await?; - let mut result = Ok(()); + let mut result = TestResult::default(); // Set up repositories and pod @@ -36,7 +35,7 @@ async fn invalid_or_unreachable_repositories_should_be_ignored() -> Result<()> { " )) .await; - combine(&mut result, &repository0_result); + result.combine(&repository0_result); let repository1_result = client .create::(indoc!( @@ -53,14 +52,14 @@ async fn invalid_or_unreachable_repositories_should_be_ignored() -> Result<()> { " )) .await; - combine(&mut result, &repository1_result); + result.combine(&repository1_result); let empty_repository = StackableRepository { name: String::from("2-empty-repository"), packages: Vec::new(), }; let repository2_result = StackableRepositoryInstance::new(&empty_repository, &client).await; - combine(&mut result, &repository2_result); + result.combine(&repository2_result); let mut service = noop_service(); // Add a UUID to the service name to circumvent the package cache @@ -72,60 +71,44 @@ async fn invalid_or_unreachable_repositories_should_be_ignored() -> Result<()> { }; let repository3_result = StackableRepositoryInstance::new(&repository_with_service, &client).await; - combine(&mut result, &repository3_result); + result.combine(&repository3_result); let pod_result = client .create::(&service.pod_spec("agent-service-integration-test-repository")) .await; - combine(&mut result, &pod_result); + result.combine(&pod_result); // Verify that the pod was downloaded, started, and is ready if let Ok(pod) = &pod_result { let pod_ready = client.verify_pod_condition(&pod, "Ready").await; - combine(&mut result, &pod_ready); + result.combine(&pod_ready); } // Tear down pod and repositories if let Ok(pod) = pod_result { let deletion_result = client.delete(pod).await; - combine(&mut result, &deletion_result); + result.combine(&deletion_result); } if let Ok(repository3) = repository3_result { let close_result = repository3.close(&client).await; - combine(&mut result, &close_result); + result.combine(&close_result); } if let Ok(repository2) = repository2_result { let close_result = repository2.close(&client).await; - combine(&mut result, &close_result); + result.combine(&close_result); } if let Ok(repository1) = repository1_result { let close_result = client.delete(repository1).await; - combine(&mut result, &close_result); + result.combine(&close_result); } if let Ok(repository0) = repository0_result { let close_result = client.delete(repository0).await; - combine(&mut result, &close_result); + result.combine(&close_result); } // Return test result - result -} - -/// Applies the AND operation to the given results -/// -/// If `result` contains already an error then `other_result` is -/// ignored else if `other_result` contains an error then it is applied -/// on `result`. -fn combine(result: &mut Result<()>, other_result: &Result) -where - E: Debug, -{ - if result.is_ok() { - if let Err(error) = other_result { - *result = Err(anyhow!("{:?}", error)) - } - } + result.into() } diff --git a/tests/util/mod.rs b/tests/util/mod.rs index a989509..7ba2ffc 100644 --- a/tests/util/mod.rs +++ b/tests/util/mod.rs @@ -1,3 +1,4 @@ pub mod repository; +pub mod result; pub mod services; pub mod test_package; diff --git a/tests/util/result.rs b/tests/util/result.rs new file mode 100644 index 0000000..852f6b2 --- /dev/null +++ b/tests/util/result.rs @@ -0,0 +1,36 @@ +use std::fmt::Debug; + +use anyhow::{anyhow, Result}; + +/// Wraps a `Result` and provides helper methods for testing +pub struct TestResult(Result<()>); + +impl Default for TestResult { + fn default() -> Self { + TestResult(Ok(())) + } +} + +impl From for Result<()> { + fn from(result: TestResult) -> Self { + result.0 + } +} + +impl TestResult { + /// Applies the AND operation to the given results + /// + /// If `result` contains already an error then `other_result` is + /// ignored else if `other_result` contains an error then it is + /// applied on `result`. + pub fn combine(&mut self, other_result: &Result) + where + E: Debug, + { + if self.0.is_ok() { + if let Err(error) = other_result { + self.0 = Err(anyhow!("{:?}", error)) + } + } + } +} diff --git a/tests/util/services.rs b/tests/util/services.rs index 92acc2e..74a97de 100644 --- a/tests/util/services.rs +++ b/tests/util/services.rs @@ -31,6 +31,7 @@ pub fn echo_service() -> TestPackage { TestPackage { name: String::from("echo-service"), version: String::from("1.0.0"), + job: false, script: String::from(indoc!( r#" #!/bin/sh @@ -54,6 +55,7 @@ pub fn exit_service() -> TestPackage { TestPackage { name: String::from("exit-service"), version: String::from("1.0.0"), + job: true, script: String::from(indoc!( " #!/bin/sh @@ -70,6 +72,7 @@ pub fn noop_service() -> TestPackage { TestPackage { name: String::from("noop-service"), version: String::from("1.0.0"), + job: false, script: String::from(indoc!( " #!/bin/sh @@ -94,6 +97,7 @@ pub fn nostop_service() -> TestPackage { TestPackage { name: String::from("nostop-service"), version: String::from("1.0.1"), + job: false, script: String::from(indoc!( " #!/bin/sh diff --git a/tests/util/test_package.rs b/tests/util/test_package.rs index 103c342..1d23fff 100644 --- a/tests/util/test_package.rs +++ b/tests/util/test_package.rs @@ -5,6 +5,7 @@ use flate2::{write::GzEncoder, Compression}; pub struct TestPackage { pub name: String, pub version: String, + pub job: bool, pub script: String, } @@ -57,15 +58,17 @@ impl TestPackage { - {command} nodeSelector: kubernetes.io/arch: stackable-linux + restartPolicy: {restart_policy} tolerations: - key: kubernetes.io/arch operator: Equal value: stackable-linux ", - pod_name = pod_name, + command = self.command(), package_name = self.name, package_version = self.version, - command = self.command() + pod_name = pod_name, + restart_policy = if self.job { "Never" } else { "Always" }, ) } }