Skip to content
This repository was archived by the owner on Dec 21, 2021. It is now read-only.
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
73 changes: 73 additions & 0 deletions tests/environment.rs
Original file line number Diff line number Diff line change
@@ -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, |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()
}
47 changes: 15 additions & 32 deletions tests/repository.rs
Original file line number Diff line number Diff line change
@@ -1,21 +1,20 @@
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,
};

#[tokio::test]
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

Expand All @@ -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::<Repository>(indoc!(
Expand All @@ -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
Expand All @@ -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::<Pod>(&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<T, E>(result: &mut Result<()>, other_result: &Result<T, E>)
where
E: Debug,
{
if result.is_ok() {
if let Err(error) = other_result {
*result = Err(anyhow!("{:?}", error))
}
}
result.into()
}
1 change: 1 addition & 0 deletions tests/util/mod.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
pub mod repository;
pub mod result;
pub mod services;
pub mod test_package;
36 changes: 36 additions & 0 deletions tests/util/result.rs
Original file line number Diff line number Diff line change
@@ -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<TestResult> 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<T, E>(&mut self, other_result: &Result<T, E>)
where
E: Debug,
{
if self.0.is_ok() {
if let Err(error) = other_result {
self.0 = Err(anyhow!("{:?}", error))
}
}
}
}
4 changes: 4 additions & 0 deletions tests/util/services.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -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
Expand All @@ -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
Expand All @@ -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
Expand Down
7 changes: 5 additions & 2 deletions tests/util/test_package.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ use flate2::{write::GzEncoder, Compression};
pub struct TestPackage {
pub name: String,
pub version: String,
pub job: bool,
pub script: String,
}

Expand Down Expand Up @@ -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" },
)
}
}