mod common;
use common::run_lua;
use wiremock::matchers::{method, path};
use wiremock::{Mock, MockServer, ResponseTemplate};
#[tokio::test]
async fn test_require_velero() {
let script = r#"
local velero = require("assay.velero")
assert.not_nil(velero)
assert.not_nil(velero.client)
"#;
run_lua(script).await.unwrap();
}
#[tokio::test]
async fn test_velero_backups_list() {
let server = MockServer::start().await;
Mock::given(method("GET"))
.and(path("/apis/velero.io/v1/namespaces/velero/backups"))
.respond_with(ResponseTemplate::new(200).set_body_json(serde_json::json!({
"apiVersion": "velero.io/v1",
"kind": "BackupList",
"items": [
{
"apiVersion": "velero.io/v1",
"kind": "Backup",
"metadata": {"name": "daily-20260210", "namespace": "velero"},
"status": {"phase": "Completed"}
},
{
"apiVersion": "velero.io/v1",
"kind": "Backup",
"metadata": {"name": "daily-20260209", "namespace": "velero"},
"status": {"phase": "Completed"}
}
]
})))
.mount(&server)
.await;
let script = format!(
r#"
local velero = require("assay.velero")
local c = velero.client("{}", "fake-token")
local backups = c.backups:list()
assert.eq(#backups, 2)
assert.eq(backups[1].metadata.name, "daily-20260210")
assert.eq(backups[2].metadata.name, "daily-20260209")
"#,
server.uri()
);
run_lua(&script).await.unwrap();
}
#[tokio::test]
async fn test_velero_backup_get() {
let server = MockServer::start().await;
Mock::given(method("GET"))
.and(path(
"/apis/velero.io/v1/namespaces/velero/backups/daily-20260210",
))
.respond_with(ResponseTemplate::new(200).set_body_json(serde_json::json!({
"apiVersion": "velero.io/v1",
"kind": "Backup",
"metadata": {"name": "daily-20260210", "namespace": "velero"},
"spec": {
"includedNamespaces": ["jeebon-test"],
"storageLocation": "default",
"ttl": "720h0m0s"
},
"status": {
"phase": "Completed",
"startTimestamp": "2026-02-10T02:00:00Z",
"completionTimestamp": "2026-02-10T02:05:30Z",
"expiration": "2026-03-12T02:00:00Z",
"errors": 0,
"warnings": 1,
"itemsBackedUp": 142,
"totalItems": 142
}
})))
.mount(&server)
.await;
let script = format!(
r#"
local velero = require("assay.velero")
local c = velero.client("{}", "fake-token")
local b = c.backups:get("daily-20260210")
assert.eq(b.metadata.name, "daily-20260210")
assert.eq(b.spec.storageLocation, "default")
assert.eq(b.status.phase, "Completed")
"#,
server.uri()
);
run_lua(&script).await.unwrap();
}
#[tokio::test]
async fn test_velero_backup_status() {
let server = MockServer::start().await;
Mock::given(method("GET"))
.and(path(
"/apis/velero.io/v1/namespaces/velero/backups/daily-20260210",
))
.respond_with(ResponseTemplate::new(200).set_body_json(serde_json::json!({
"apiVersion": "velero.io/v1",
"kind": "Backup",
"metadata": {"name": "daily-20260210", "namespace": "velero"},
"status": {
"phase": "Completed",
"startTimestamp": "2026-02-10T02:00:00Z",
"completionTimestamp": "2026-02-10T02:05:30Z",
"expiration": "2026-03-12T02:00:00Z",
"errors": 0,
"warnings": 2,
"itemsBackedUp": 142,
"totalItems": 150
}
})))
.mount(&server)
.await;
let script = format!(
r#"
local velero = require("assay.velero")
local c = velero.client("{}", "fake-token")
local s = c.backups:status("daily-20260210")
assert.eq(s.phase, "Completed")
assert.eq(s.started, "2026-02-10T02:00:00Z")
assert.eq(s.completed, "2026-02-10T02:05:30Z")
assert.eq(s.expiration, "2026-03-12T02:00:00Z")
assert.eq(s.errors, 0)
assert.eq(s.warnings, 2)
assert.eq(s.items_backed_up, 142)
assert.eq(s.items_total, 150)
"#,
server.uri()
);
run_lua(&script).await.unwrap();
}
#[tokio::test]
async fn test_velero_is_backup_completed_true() {
let server = MockServer::start().await;
Mock::given(method("GET"))
.and(path(
"/apis/velero.io/v1/namespaces/velero/backups/daily-20260210",
))
.respond_with(ResponseTemplate::new(200).set_body_json(serde_json::json!({
"apiVersion": "velero.io/v1",
"kind": "Backup",
"metadata": {"name": "daily-20260210"},
"status": {"phase": "Completed"}
})))
.mount(&server)
.await;
let script = format!(
r#"
local velero = require("assay.velero")
local c = velero.client("{}", "fake-token")
assert.eq(c.backups:is_completed("daily-20260210"), true)
"#,
server.uri()
);
run_lua(&script).await.unwrap();
}
#[tokio::test]
async fn test_velero_is_backup_completed_false() {
let server = MockServer::start().await;
Mock::given(method("GET"))
.and(path(
"/apis/velero.io/v1/namespaces/velero/backups/daily-20260210",
))
.respond_with(ResponseTemplate::new(200).set_body_json(serde_json::json!({
"apiVersion": "velero.io/v1",
"kind": "Backup",
"metadata": {"name": "daily-20260210"},
"status": {"phase": "InProgress"}
})))
.mount(&server)
.await;
let script = format!(
r#"
local velero = require("assay.velero")
local c = velero.client("{}", "fake-token")
assert.eq(c.backups:is_completed("daily-20260210"), false)
"#,
server.uri()
);
run_lua(&script).await.unwrap();
}
#[tokio::test]
async fn test_velero_is_backup_failed() {
let server = MockServer::start().await;
Mock::given(method("GET"))
.and(path(
"/apis/velero.io/v1/namespaces/velero/backups/broken-backup",
))
.respond_with(ResponseTemplate::new(200).set_body_json(serde_json::json!({
"apiVersion": "velero.io/v1",
"kind": "Backup",
"metadata": {"name": "broken-backup"},
"status": {"phase": "Failed"}
})))
.mount(&server)
.await;
let script = format!(
r#"
local velero = require("assay.velero")
local c = velero.client("{}", "fake-token")
assert.eq(c.backups:is_failed("broken-backup"), true)
"#,
server.uri()
);
run_lua(&script).await.unwrap();
}
#[tokio::test]
async fn test_velero_is_backup_failed_partially() {
let server = MockServer::start().await;
Mock::given(method("GET"))
.and(path(
"/apis/velero.io/v1/namespaces/velero/backups/partial-backup",
))
.respond_with(ResponseTemplate::new(200).set_body_json(serde_json::json!({
"apiVersion": "velero.io/v1",
"kind": "Backup",
"metadata": {"name": "partial-backup"},
"status": {"phase": "PartiallyFailed"}
})))
.mount(&server)
.await;
let script = format!(
r#"
local velero = require("assay.velero")
local c = velero.client("{}", "fake-token")
assert.eq(c.backups:is_failed("partial-backup"), true)
"#,
server.uri()
);
run_lua(&script).await.unwrap();
}
#[tokio::test]
async fn test_velero_latest_backup() {
let server = MockServer::start().await;
Mock::given(method("GET"))
.and(path("/apis/velero.io/v1/namespaces/velero/backups"))
.respond_with(ResponseTemplate::new(200).set_body_json(serde_json::json!({
"apiVersion": "velero.io/v1",
"kind": "BackupList",
"items": [
{
"metadata": {
"name": "daily-20260208",
"creationTimestamp": "2026-02-08T02:00:00Z",
"labels": {"velero.io/schedule-name": "daily"}
},
"status": {"phase": "Completed"}
},
{
"metadata": {
"name": "daily-20260210",
"creationTimestamp": "2026-02-10T02:00:00Z",
"labels": {"velero.io/schedule-name": "daily"}
},
"status": {"phase": "Completed"}
},
{
"metadata": {
"name": "daily-20260209",
"creationTimestamp": "2026-02-09T02:00:00Z",
"labels": {"velero.io/schedule-name": "daily"}
},
"status": {"phase": "Completed"}
},
{
"metadata": {
"name": "weekly-20260207",
"creationTimestamp": "2026-02-07T02:00:00Z",
"labels": {"velero.io/schedule-name": "weekly"}
},
"status": {"phase": "Completed"}
}
]
})))
.mount(&server)
.await;
let script = format!(
r#"
local velero = require("assay.velero")
local c = velero.client("{}", "fake-token")
local latest = c.backups:latest("daily")
assert.not_nil(latest)
assert.eq(latest.metadata.name, "daily-20260210")
"#,
server.uri()
);
run_lua(&script).await.unwrap();
}
#[tokio::test]
async fn test_velero_latest_backup_no_match() {
let server = MockServer::start().await;
Mock::given(method("GET"))
.and(path("/apis/velero.io/v1/namespaces/velero/backups"))
.respond_with(ResponseTemplate::new(200).set_body_json(serde_json::json!({
"apiVersion": "velero.io/v1",
"kind": "BackupList",
"items": [
{
"metadata": {
"name": "daily-20260210",
"creationTimestamp": "2026-02-10T02:00:00Z",
"labels": {"velero.io/schedule-name": "daily"}
},
"status": {"phase": "Completed"}
}
]
})))
.mount(&server)
.await;
let script = format!(
r#"
local velero = require("assay.velero")
local c = velero.client("{}", "fake-token")
local latest = c.backups:latest("nonexistent-schedule")
assert.eq(latest, nil)
"#,
server.uri()
);
run_lua(&script).await.unwrap();
}
#[tokio::test]
async fn test_velero_restores_list() {
let server = MockServer::start().await;
Mock::given(method("GET"))
.and(path("/apis/velero.io/v1/namespaces/velero/restores"))
.respond_with(ResponseTemplate::new(200).set_body_json(serde_json::json!({
"apiVersion": "velero.io/v1",
"kind": "RestoreList",
"items": [
{
"apiVersion": "velero.io/v1",
"kind": "Restore",
"metadata": {"name": "restore-20260210", "namespace": "velero"},
"status": {"phase": "Completed"}
}
]
})))
.mount(&server)
.await;
let script = format!(
r#"
local velero = require("assay.velero")
local c = velero.client("{}", "fake-token")
local restores = c.restores:list()
assert.eq(#restores, 1)
assert.eq(restores[1].metadata.name, "restore-20260210")
"#,
server.uri()
);
run_lua(&script).await.unwrap();
}
#[tokio::test]
async fn test_velero_restore_status() {
let server = MockServer::start().await;
Mock::given(method("GET"))
.and(path(
"/apis/velero.io/v1/namespaces/velero/restores/restore-20260210",
))
.respond_with(ResponseTemplate::new(200).set_body_json(serde_json::json!({
"apiVersion": "velero.io/v1",
"kind": "Restore",
"metadata": {"name": "restore-20260210", "namespace": "velero"},
"status": {
"phase": "Completed",
"startTimestamp": "2026-02-10T10:00:00Z",
"completionTimestamp": "2026-02-10T10:12:00Z",
"errors": 0,
"warnings": 3
}
})))
.mount(&server)
.await;
let script = format!(
r#"
local velero = require("assay.velero")
local c = velero.client("{}", "fake-token")
local s = c.restores:status("restore-20260210")
assert.eq(s.phase, "Completed")
assert.eq(s.started, "2026-02-10T10:00:00Z")
assert.eq(s.completed, "2026-02-10T10:12:00Z")
assert.eq(s.errors, 0)
assert.eq(s.warnings, 3)
"#,
server.uri()
);
run_lua(&script).await.unwrap();
}
#[tokio::test]
async fn test_velero_is_restore_completed() {
let server = MockServer::start().await;
Mock::given(method("GET"))
.and(path(
"/apis/velero.io/v1/namespaces/velero/restores/restore-20260210",
))
.respond_with(ResponseTemplate::new(200).set_body_json(serde_json::json!({
"apiVersion": "velero.io/v1",
"kind": "Restore",
"metadata": {"name": "restore-20260210"},
"status": {"phase": "Completed"}
})))
.mount(&server)
.await;
let script = format!(
r#"
local velero = require("assay.velero")
local c = velero.client("{}", "fake-token")
assert.eq(c.restores:is_completed("restore-20260210"), true)
"#,
server.uri()
);
run_lua(&script).await.unwrap();
}
#[tokio::test]
async fn test_velero_is_restore_completed_false() {
let server = MockServer::start().await;
Mock::given(method("GET"))
.and(path(
"/apis/velero.io/v1/namespaces/velero/restores/restore-20260210",
))
.respond_with(ResponseTemplate::new(200).set_body_json(serde_json::json!({
"apiVersion": "velero.io/v1",
"kind": "Restore",
"metadata": {"name": "restore-20260210"},
"status": {"phase": "InProgress"}
})))
.mount(&server)
.await;
let script = format!(
r#"
local velero = require("assay.velero")
local c = velero.client("{}", "fake-token")
assert.eq(c.restores:is_completed("restore-20260210"), false)
"#,
server.uri()
);
run_lua(&script).await.unwrap();
}
#[tokio::test]
async fn test_velero_schedules_list() {
let server = MockServer::start().await;
Mock::given(method("GET"))
.and(path("/apis/velero.io/v1/namespaces/velero/schedules"))
.respond_with(ResponseTemplate::new(200).set_body_json(serde_json::json!({
"apiVersion": "velero.io/v1",
"kind": "ScheduleList",
"items": [
{
"apiVersion": "velero.io/v1",
"kind": "Schedule",
"metadata": {"name": "daily", "namespace": "velero"},
"spec": {"schedule": "0 2 * * *"},
"status": {"phase": "Enabled", "lastBackup": "2026-02-10T02:00:00Z"}
},
{
"apiVersion": "velero.io/v1",
"kind": "Schedule",
"metadata": {"name": "weekly", "namespace": "velero"},
"spec": {"schedule": "0 3 * * 0"},
"status": {"phase": "Enabled", "lastBackup": "2026-02-09T03:00:00Z"}
}
]
})))
.mount(&server)
.await;
let script = format!(
r#"
local velero = require("assay.velero")
local c = velero.client("{}", "fake-token")
local schedules = c.schedules:list()
assert.eq(#schedules, 2)
assert.eq(schedules[1].metadata.name, "daily")
assert.eq(schedules[2].metadata.name, "weekly")
"#,
server.uri()
);
run_lua(&script).await.unwrap();
}
#[tokio::test]
async fn test_velero_schedule_status() {
let server = MockServer::start().await;
Mock::given(method("GET"))
.and(path("/apis/velero.io/v1/namespaces/velero/schedules/daily"))
.respond_with(ResponseTemplate::new(200).set_body_json(serde_json::json!({
"apiVersion": "velero.io/v1",
"kind": "Schedule",
"metadata": {"name": "daily", "namespace": "velero"},
"status": {
"phase": "Enabled",
"lastBackup": "2026-02-10T02:00:00Z",
"validationErrors": []
}
})))
.mount(&server)
.await;
let script = format!(
r#"
local velero = require("assay.velero")
local c = velero.client("{}", "fake-token")
local s = c.schedules:status("daily")
assert.eq(s.phase, "Enabled")
assert.eq(s.last_backup, "2026-02-10T02:00:00Z")
assert.eq(#s.validation_errors, 0)
"#,
server.uri()
);
run_lua(&script).await.unwrap();
}
#[tokio::test]
async fn test_velero_is_schedule_enabled_true() {
let server = MockServer::start().await;
Mock::given(method("GET"))
.and(path("/apis/velero.io/v1/namespaces/velero/schedules/daily"))
.respond_with(ResponseTemplate::new(200).set_body_json(serde_json::json!({
"apiVersion": "velero.io/v1",
"kind": "Schedule",
"metadata": {"name": "daily"},
"status": {"phase": "Enabled"}
})))
.mount(&server)
.await;
let script = format!(
r#"
local velero = require("assay.velero")
local c = velero.client("{}", "fake-token")
assert.eq(c.schedules:is_enabled("daily"), true)
"#,
server.uri()
);
run_lua(&script).await.unwrap();
}
#[tokio::test]
async fn test_velero_is_schedule_enabled_false() {
let server = MockServer::start().await;
Mock::given(method("GET"))
.and(path(
"/apis/velero.io/v1/namespaces/velero/schedules/paused",
))
.respond_with(ResponseTemplate::new(200).set_body_json(serde_json::json!({
"apiVersion": "velero.io/v1",
"kind": "Schedule",
"metadata": {"name": "paused"},
"status": {"phase": "FailedValidation"}
})))
.mount(&server)
.await;
let script = format!(
r#"
local velero = require("assay.velero")
local c = velero.client("{}", "fake-token")
assert.eq(c.schedules:is_enabled("paused"), false)
"#,
server.uri()
);
run_lua(&script).await.unwrap();
}
#[tokio::test]
async fn test_velero_backup_storage_locations() {
let server = MockServer::start().await;
Mock::given(method("GET"))
.and(path(
"/apis/velero.io/v1/namespaces/velero/backupstoragelocations",
))
.respond_with(ResponseTemplate::new(200).set_body_json(serde_json::json!({
"apiVersion": "velero.io/v1",
"kind": "BackupStorageLocationList",
"items": [
{
"apiVersion": "velero.io/v1",
"kind": "BackupStorageLocation",
"metadata": {"name": "default", "namespace": "velero"},
"spec": {"provider": "aws", "objectStorage": {"bucket": "velero-backups"}},
"status": {"phase": "Available", "lastSyncedTime": "2026-02-10T12:00:00Z"}
}
]
})))
.mount(&server)
.await;
let script = format!(
r#"
local velero = require("assay.velero")
local c = velero.client("{}", "fake-token")
local bsls = c.storage_locations:list()
assert.eq(#bsls, 1)
assert.eq(bsls[1].metadata.name, "default")
assert.eq(bsls[1].spec.provider, "aws")
"#,
server.uri()
);
run_lua(&script).await.unwrap();
}
#[tokio::test]
async fn test_velero_is_bsl_available_true() {
let server = MockServer::start().await;
Mock::given(method("GET"))
.and(path(
"/apis/velero.io/v1/namespaces/velero/backupstoragelocations/default",
))
.respond_with(ResponseTemplate::new(200).set_body_json(serde_json::json!({
"apiVersion": "velero.io/v1",
"kind": "BackupStorageLocation",
"metadata": {"name": "default"},
"status": {"phase": "Available"}
})))
.mount(&server)
.await;
let script = format!(
r#"
local velero = require("assay.velero")
local c = velero.client("{}", "fake-token")
assert.eq(c.storage_locations:is_available("default"), true)
"#,
server.uri()
);
run_lua(&script).await.unwrap();
}
#[tokio::test]
async fn test_velero_is_bsl_available_false() {
let server = MockServer::start().await;
Mock::given(method("GET"))
.and(path(
"/apis/velero.io/v1/namespaces/velero/backupstoragelocations/broken",
))
.respond_with(ResponseTemplate::new(200).set_body_json(serde_json::json!({
"apiVersion": "velero.io/v1",
"kind": "BackupStorageLocation",
"metadata": {"name": "broken"},
"status": {"phase": "Unavailable"}
})))
.mount(&server)
.await;
let script = format!(
r#"
local velero = require("assay.velero")
local c = velero.client("{}", "fake-token")
assert.eq(c.storage_locations:is_available("broken"), false)
"#,
server.uri()
);
run_lua(&script).await.unwrap();
}
#[tokio::test]
async fn test_velero_all_schedules_enabled() {
let server = MockServer::start().await;
Mock::given(method("GET"))
.and(path("/apis/velero.io/v1/namespaces/velero/schedules"))
.respond_with(ResponseTemplate::new(200).set_body_json(serde_json::json!({
"apiVersion": "velero.io/v1",
"kind": "ScheduleList",
"items": [
{
"metadata": {"name": "daily"},
"status": {"phase": "Enabled"}
},
{
"metadata": {"name": "weekly"},
"status": {"phase": "Enabled"}
},
{
"metadata": {"name": "broken-schedule"},
"status": {"phase": "FailedValidation"}
}
]
})))
.mount(&server)
.await;
let script = format!(
r#"
local velero = require("assay.velero")
local c = velero.client("{}", "fake-token")
local result = c.schedules:all_enabled()
assert.eq(result.enabled, 2)
assert.eq(result.disabled, 1)
assert.eq(result.total, 3)
assert.eq(result.disabled_names[1], "broken-schedule")
"#,
server.uri()
);
run_lua(&script).await.unwrap();
}
#[tokio::test]
async fn test_velero_all_bsl_available() {
let server = MockServer::start().await;
Mock::given(method("GET"))
.and(path(
"/apis/velero.io/v1/namespaces/velero/backupstoragelocations",
))
.respond_with(ResponseTemplate::new(200).set_body_json(serde_json::json!({
"apiVersion": "velero.io/v1",
"kind": "BackupStorageLocationList",
"items": [
{
"metadata": {"name": "default"},
"status": {"phase": "Available"}
},
{
"metadata": {"name": "secondary"},
"status": {"phase": "Unavailable"}
}
]
})))
.mount(&server)
.await;
let script = format!(
r#"
local velero = require("assay.velero")
local c = velero.client("{}", "fake-token")
local result = c.storage_locations:all_available()
assert.eq(result.available, 1)
assert.eq(result.unavailable, 1)
assert.eq(result.total, 2)
assert.eq(result.unavailable_names[1], "secondary")
"#,
server.uri()
);
run_lua(&script).await.unwrap();
}
#[tokio::test]
async fn test_velero_custom_namespace() {
let server = MockServer::start().await;
Mock::given(method("GET"))
.and(path("/apis/velero.io/v1/namespaces/custom-ns/backups"))
.respond_with(ResponseTemplate::new(200).set_body_json(serde_json::json!({
"apiVersion": "velero.io/v1",
"kind": "BackupList",
"items": [
{
"metadata": {"name": "backup-1", "namespace": "custom-ns"},
"status": {"phase": "Completed"}
}
]
})))
.mount(&server)
.await;
let script = format!(
r#"
local velero = require("assay.velero")
local c = velero.client("{}", "fake-token", "custom-ns")
local backups = c.backups:list()
assert.eq(#backups, 1)
assert.eq(backups[1].metadata.name, "backup-1")
"#,
server.uri()
);
run_lua(&script).await.unwrap();
}