mod common;
use common::run_lua;
use wiremock::matchers::{method, path};
use wiremock::{Mock, MockServer, ResponseTemplate};
#[tokio::test]
async fn test_require_kargo() {
let script = r#"
local kargo = require("assay.kargo")
assert.not_nil(kargo)
assert.not_nil(kargo.client)
"#;
run_lua(script).await.unwrap();
}
#[tokio::test]
async fn test_kargo_stages_list() {
let server = MockServer::start().await;
Mock::given(method("GET"))
.and(path(
"/apis/kargo.akuity.io/v1alpha1/namespaces/jeebon-test/stages",
))
.respond_with(ResponseTemplate::new(200).set_body_json(serde_json::json!({
"apiVersion": "kargo.akuity.io/v1alpha1",
"kind": "StageList",
"items": [
{
"apiVersion": "kargo.akuity.io/v1alpha1",
"kind": "Stage",
"metadata": {"name": "test", "namespace": "jeebon-test"},
"status": {"phase": "Steady"}
},
{
"apiVersion": "kargo.akuity.io/v1alpha1",
"kind": "Stage",
"metadata": {"name": "dev", "namespace": "jeebon-test"},
"status": {"phase": "Promoting"}
}
]
})))
.mount(&server)
.await;
let script = format!(
r#"
local kargo = require("assay.kargo")
local c = kargo.client("{}", "fake-token")
local stages = c.stages:list("jeebon-test")
assert.eq(#stages, 2)
assert.eq(stages[1].metadata.name, "test")
assert.eq(stages[1].status.phase, "Steady")
assert.eq(stages[2].metadata.name, "dev")
"#,
server.uri()
);
run_lua(&script).await.unwrap();
}
#[tokio::test]
async fn test_kargo_stage_get() {
let server = MockServer::start().await;
Mock::given(method("GET"))
.and(path(
"/apis/kargo.akuity.io/v1alpha1/namespaces/jeebon-test/stages/test",
))
.respond_with(ResponseTemplate::new(200).set_body_json(serde_json::json!({
"apiVersion": "kargo.akuity.io/v1alpha1",
"kind": "Stage",
"metadata": {"name": "test", "namespace": "jeebon-test"},
"spec": {
"subscriptions": {"warehouse": "main"},
"promotionMechanisms": {"argoCDAppUpdates": [{"appName": "jeebon-test"}]}
},
"status": {
"phase": "Steady",
"currentFreightId": "freight-abc123",
"health": {"status": "Healthy"},
"conditions": [
{"type": "Healthy", "status": "True", "reason": "AllHealthy"}
]
}
})))
.mount(&server)
.await;
let script = format!(
r#"
local kargo = require("assay.kargo")
local c = kargo.client("{}", "fake-token")
local s = c.stages:get("jeebon-test", "test")
assert.eq(s.metadata.name, "test")
assert.eq(s.status.phase, "Steady")
assert.eq(s.status.currentFreightId, "freight-abc123")
assert.eq(s.status.health.status, "Healthy")
"#,
server.uri()
);
run_lua(&script).await.unwrap();
}
#[tokio::test]
async fn test_kargo_stage_status() {
let server = MockServer::start().await;
Mock::given(method("GET"))
.and(path(
"/apis/kargo.akuity.io/v1alpha1/namespaces/jeebon-test/stages/test",
))
.respond_with(ResponseTemplate::new(200).set_body_json(serde_json::json!({
"apiVersion": "kargo.akuity.io/v1alpha1",
"kind": "Stage",
"metadata": {"name": "test", "namespace": "jeebon-test"},
"status": {
"phase": "Steady",
"currentFreightId": "freight-abc123",
"health": {"status": "Healthy"},
"conditions": [
{"type": "Healthy", "status": "True", "reason": "AllHealthy"}
]
}
})))
.mount(&server)
.await;
let script = format!(
r#"
local kargo = require("assay.kargo")
local c = kargo.client("{}", "fake-token")
local st = c.stages:status("jeebon-test", "test")
assert.eq(st.phase, "Steady")
assert.eq(st.current_freight_id, "freight-abc123")
assert.eq(st.health.status, "Healthy")
assert.eq(#st.conditions, 1)
assert.eq(st.conditions[1].type, "Healthy")
"#,
server.uri()
);
run_lua(&script).await.unwrap();
}
#[tokio::test]
async fn test_kargo_is_stage_healthy_steady() {
let server = MockServer::start().await;
Mock::given(method("GET"))
.and(path(
"/apis/kargo.akuity.io/v1alpha1/namespaces/jeebon-test/stages/test",
))
.respond_with(ResponseTemplate::new(200).set_body_json(serde_json::json!({
"apiVersion": "kargo.akuity.io/v1alpha1",
"kind": "Stage",
"metadata": {"name": "test", "namespace": "jeebon-test"},
"status": {"phase": "Steady"}
})))
.mount(&server)
.await;
let script = format!(
r#"
local kargo = require("assay.kargo")
local c = kargo.client("{}", "fake-token")
local healthy = c.stages:is_healthy("jeebon-test", "test")
assert.eq(healthy, true)
"#,
server.uri()
);
run_lua(&script).await.unwrap();
}
#[tokio::test]
async fn test_kargo_is_stage_healthy_condition() {
let server = MockServer::start().await;
Mock::given(method("GET"))
.and(path(
"/apis/kargo.akuity.io/v1alpha1/namespaces/jeebon-test/stages/test",
))
.respond_with(ResponseTemplate::new(200).set_body_json(serde_json::json!({
"apiVersion": "kargo.akuity.io/v1alpha1",
"kind": "Stage",
"metadata": {"name": "test", "namespace": "jeebon-test"},
"status": {
"phase": "Promoting",
"conditions": [
{"type": "Healthy", "status": "True", "reason": "AllHealthy"}
]
}
})))
.mount(&server)
.await;
let script = format!(
r#"
local kargo = require("assay.kargo")
local c = kargo.client("{}", "fake-token")
local healthy = c.stages:is_healthy("jeebon-test", "test")
assert.eq(healthy, true)
"#,
server.uri()
);
run_lua(&script).await.unwrap();
}
#[tokio::test]
async fn test_kargo_is_stage_unhealthy() {
let server = MockServer::start().await;
Mock::given(method("GET"))
.and(path(
"/apis/kargo.akuity.io/v1alpha1/namespaces/jeebon-test/stages/broken",
))
.respond_with(ResponseTemplate::new(200).set_body_json(serde_json::json!({
"apiVersion": "kargo.akuity.io/v1alpha1",
"kind": "Stage",
"metadata": {"name": "broken", "namespace": "jeebon-test"},
"status": {
"phase": "Failed",
"conditions": [
{"type": "Healthy", "status": "False", "reason": "PromotionFailed"}
]
}
})))
.mount(&server)
.await;
let script = format!(
r#"
local kargo = require("assay.kargo")
local c = kargo.client("{}", "fake-token")
local healthy = c.stages:is_healthy("jeebon-test", "broken")
assert.eq(healthy, false)
"#,
server.uri()
);
run_lua(&script).await.unwrap();
}
#[tokio::test]
async fn test_kargo_freight_list() {
let server = MockServer::start().await;
Mock::given(method("GET"))
.and(path(
"/apis/kargo.akuity.io/v1alpha1/namespaces/jeebon-test/freight",
))
.respond_with(ResponseTemplate::new(200).set_body_json(serde_json::json!({
"apiVersion": "kargo.akuity.io/v1alpha1",
"kind": "FreightList",
"items": [
{
"apiVersion": "kargo.akuity.io/v1alpha1",
"kind": "Freight",
"metadata": {"name": "freight-abc123", "namespace": "jeebon-test"},
"status": {
"verifiedIn": {"test": {}},
"approvedFor": {"dev": {}}
}
},
{
"apiVersion": "kargo.akuity.io/v1alpha1",
"kind": "Freight",
"metadata": {"name": "freight-def456", "namespace": "jeebon-test"},
"status": {
"verifiedIn": {},
"approvedFor": {}
}
}
]
})))
.mount(&server)
.await;
let script = format!(
r#"
local kargo = require("assay.kargo")
local c = kargo.client("{}", "fake-token")
local freight = c.freight:list("jeebon-test")
assert.eq(#freight, 2)
assert.eq(freight[1].metadata.name, "freight-abc123")
assert.eq(freight[2].metadata.name, "freight-def456")
"#,
server.uri()
);
run_lua(&script).await.unwrap();
}
#[tokio::test]
async fn test_kargo_freight_get() {
let server = MockServer::start().await;
Mock::given(method("GET"))
.and(path(
"/apis/kargo.akuity.io/v1alpha1/namespaces/jeebon-test/freight/freight-abc123",
))
.respond_with(ResponseTemplate::new(200).set_body_json(serde_json::json!({
"apiVersion": "kargo.akuity.io/v1alpha1",
"kind": "Freight",
"metadata": {"name": "freight-abc123", "namespace": "jeebon-test"},
"spec": {
"commits": [{"repoURL": "https://github.com/org/repo", "id": "abc123"}],
"images": [{"repoURL": "ghcr.io/org/app", "tag": "v1.2.3"}]
},
"status": {
"verifiedIn": {"test": {}},
"approvedFor": {"dev": {}}
}
})))
.mount(&server)
.await;
let script = format!(
r#"
local kargo = require("assay.kargo")
local c = kargo.client("{}", "fake-token")
local f = c.freight:get("jeebon-test", "freight-abc123")
assert.eq(f.metadata.name, "freight-abc123")
assert.eq(f.spec.images[1].tag, "v1.2.3")
assert.eq(f.spec.commits[1].id, "abc123")
"#,
server.uri()
);
run_lua(&script).await.unwrap();
}
#[tokio::test]
async fn test_kargo_freight_status() {
let server = MockServer::start().await;
Mock::given(method("GET"))
.and(path(
"/apis/kargo.akuity.io/v1alpha1/namespaces/jeebon-test/freight/freight-abc123",
))
.respond_with(ResponseTemplate::new(200).set_body_json(serde_json::json!({
"apiVersion": "kargo.akuity.io/v1alpha1",
"kind": "Freight",
"metadata": {"name": "freight-abc123", "namespace": "jeebon-test"},
"status": {
"verifiedIn": {"test": {}},
"approvedFor": {"dev": {}}
}
})))
.mount(&server)
.await;
let script = format!(
r#"
local kargo = require("assay.kargo")
local c = kargo.client("{}", "fake-token")
local st = c.freight:status("jeebon-test", "freight-abc123")
assert.not_nil(st.verifiedIn)
assert.not_nil(st.approvedFor)
"#,
server.uri()
);
run_lua(&script).await.unwrap();
}
#[tokio::test]
async fn test_kargo_promotions_list() {
let server = MockServer::start().await;
Mock::given(method("GET"))
.and(path(
"/apis/kargo.akuity.io/v1alpha1/namespaces/jeebon-test/promotions",
))
.respond_with(ResponseTemplate::new(200).set_body_json(serde_json::json!({
"apiVersion": "kargo.akuity.io/v1alpha1",
"kind": "PromotionList",
"items": [
{
"apiVersion": "kargo.akuity.io/v1alpha1",
"kind": "Promotion",
"metadata": {"name": "test-abc", "namespace": "jeebon-test"},
"spec": {"stage": "test", "freight": "freight-abc123"},
"status": {"phase": "Succeeded"}
},
{
"apiVersion": "kargo.akuity.io/v1alpha1",
"kind": "Promotion",
"metadata": {"name": "test-def", "namespace": "jeebon-test"},
"spec": {"stage": "test", "freight": "freight-def456"},
"status": {"phase": "Running"}
}
]
})))
.mount(&server)
.await;
let script = format!(
r#"
local kargo = require("assay.kargo")
local c = kargo.client("{}", "fake-token")
local promos = c.promotions:list("jeebon-test")
assert.eq(#promos, 2)
assert.eq(promos[1].metadata.name, "test-abc")
assert.eq(promos[1].status.phase, "Succeeded")
assert.eq(promos[2].status.phase, "Running")
"#,
server.uri()
);
run_lua(&script).await.unwrap();
}
#[tokio::test]
async fn test_kargo_promote() {
let server = MockServer::start().await;
Mock::given(method("POST"))
.and(path(
"/apis/kargo.akuity.io/v1alpha1/namespaces/jeebon-test/promotions",
))
.respond_with(ResponseTemplate::new(201).set_body_json(serde_json::json!({
"apiVersion": "kargo.akuity.io/v1alpha1",
"kind": "Promotion",
"metadata": {
"name": "test-x7k9z",
"namespace": "jeebon-test",
"generateName": "test-"
},
"spec": {
"stage": "test",
"freight": "freight-abc123"
},
"status": {
"phase": "Pending"
}
})))
.mount(&server)
.await;
let script = format!(
r#"
local kargo = require("assay.kargo")
local c = kargo.client("{}", "fake-token")
local promo = c.promotions:create("jeebon-test", "test", "freight-abc123")
assert.eq(promo.metadata.name, "test-x7k9z")
assert.eq(promo.spec.stage, "test")
assert.eq(promo.spec.freight, "freight-abc123")
assert.eq(promo.status.phase, "Pending")
"#,
server.uri()
);
run_lua(&script).await.unwrap();
}
#[tokio::test]
async fn test_kargo_promotion_status() {
let server = MockServer::start().await;
Mock::given(method("GET"))
.and(path(
"/apis/kargo.akuity.io/v1alpha1/namespaces/jeebon-test/promotions/test-abc",
))
.respond_with(ResponseTemplate::new(200).set_body_json(serde_json::json!({
"apiVersion": "kargo.akuity.io/v1alpha1",
"kind": "Promotion",
"metadata": {"name": "test-abc", "namespace": "jeebon-test"},
"spec": {"stage": "test", "freight": "freight-abc123"},
"status": {
"phase": "Succeeded",
"message": "Promotion completed successfully",
"freightId": "freight-abc123"
}
})))
.mount(&server)
.await;
let script = format!(
r#"
local kargo = require("assay.kargo")
local c = kargo.client("{}", "fake-token")
local st = c.promotions:status("jeebon-test", "test-abc")
assert.eq(st.phase, "Succeeded")
assert.eq(st.message, "Promotion completed successfully")
assert.eq(st.freight_id, "freight-abc123")
"#,
server.uri()
);
run_lua(&script).await.unwrap();
}
#[tokio::test]
async fn test_kargo_warehouses_list() {
let server = MockServer::start().await;
Mock::given(method("GET"))
.and(path(
"/apis/kargo.akuity.io/v1alpha1/namespaces/jeebon-test/warehouses",
))
.respond_with(ResponseTemplate::new(200).set_body_json(serde_json::json!({
"apiVersion": "kargo.akuity.io/v1alpha1",
"kind": "WarehouseList",
"items": [
{
"apiVersion": "kargo.akuity.io/v1alpha1",
"kind": "Warehouse",
"metadata": {"name": "main", "namespace": "jeebon-test"},
"spec": {
"subscriptions": [
{"image": {"repoURL": "ghcr.io/org/app", "semverConstraint": ">=1.0.0"}}
]
}
}
]
})))
.mount(&server)
.await;
let script = format!(
r#"
local kargo = require("assay.kargo")
local c = kargo.client("{}", "fake-token")
local wh = c.warehouses:list("jeebon-test")
assert.eq(#wh, 1)
assert.eq(wh[1].metadata.name, "main")
"#,
server.uri()
);
run_lua(&script).await.unwrap();
}
#[tokio::test]
async fn test_kargo_warehouse_get() {
let server = MockServer::start().await;
Mock::given(method("GET"))
.and(path(
"/apis/kargo.akuity.io/v1alpha1/namespaces/jeebon-test/warehouses/main",
))
.respond_with(ResponseTemplate::new(200).set_body_json(serde_json::json!({
"apiVersion": "kargo.akuity.io/v1alpha1",
"kind": "Warehouse",
"metadata": {"name": "main", "namespace": "jeebon-test"},
"spec": {
"subscriptions": [
{"image": {"repoURL": "ghcr.io/org/app", "semverConstraint": ">=1.0.0"}}
]
}
})))
.mount(&server)
.await;
let script = format!(
r#"
local kargo = require("assay.kargo")
local c = kargo.client("{}", "fake-token")
local wh = c.warehouses:get("jeebon-test", "main")
assert.eq(wh.metadata.name, "main")
assert.eq(wh.kind, "Warehouse")
"#,
server.uri()
);
run_lua(&script).await.unwrap();
}
#[tokio::test]
async fn test_kargo_projects_list() {
let server = MockServer::start().await;
Mock::given(method("GET"))
.and(path("/apis/kargo.akuity.io/v1alpha1/projects"))
.respond_with(ResponseTemplate::new(200).set_body_json(serde_json::json!({
"apiVersion": "kargo.akuity.io/v1alpha1",
"kind": "ProjectList",
"items": [
{
"apiVersion": "kargo.akuity.io/v1alpha1",
"kind": "Project",
"metadata": {"name": "jeebon-test"},
"status": {"phase": "Ready"}
},
{
"apiVersion": "kargo.akuity.io/v1alpha1",
"kind": "Project",
"metadata": {"name": "jeebon-dev"},
"status": {"phase": "Ready"}
}
]
})))
.mount(&server)
.await;
let script = format!(
r#"
local kargo = require("assay.kargo")
local c = kargo.client("{}", "fake-token")
local projects = c.projects:list()
assert.eq(#projects, 2)
assert.eq(projects[1].metadata.name, "jeebon-test")
assert.eq(projects[2].metadata.name, "jeebon-dev")
"#,
server.uri()
);
run_lua(&script).await.unwrap();
}
#[tokio::test]
async fn test_kargo_project_get() {
let server = MockServer::start().await;
Mock::given(method("GET"))
.and(path("/apis/kargo.akuity.io/v1alpha1/projects/jeebon-test"))
.respond_with(ResponseTemplate::new(200).set_body_json(serde_json::json!({
"apiVersion": "kargo.akuity.io/v1alpha1",
"kind": "Project",
"metadata": {"name": "jeebon-test"},
"status": {"phase": "Ready"}
})))
.mount(&server)
.await;
let script = format!(
r#"
local kargo = require("assay.kargo")
local c = kargo.client("{}", "fake-token")
local p = c.projects:get("jeebon-test")
assert.eq(p.metadata.name, "jeebon-test")
assert.eq(p.status.phase, "Ready")
"#,
server.uri()
);
run_lua(&script).await.unwrap();
}
#[tokio::test]
async fn test_kargo_pipeline_status() {
let server = MockServer::start().await;
Mock::given(method("GET"))
.and(path(
"/apis/kargo.akuity.io/v1alpha1/namespaces/jeebon-test/stages",
))
.respond_with(ResponseTemplate::new(200).set_body_json(serde_json::json!({
"apiVersion": "kargo.akuity.io/v1alpha1",
"kind": "StageList",
"items": [
{
"apiVersion": "kargo.akuity.io/v1alpha1",
"kind": "Stage",
"metadata": {"name": "test", "namespace": "jeebon-test"},
"status": {
"phase": "Steady",
"currentFreightId": "freight-abc123"
}
},
{
"apiVersion": "kargo.akuity.io/v1alpha1",
"kind": "Stage",
"metadata": {"name": "dev", "namespace": "jeebon-test"},
"status": {
"phase": "Promoting",
"currentFreightId": "freight-def456",
"conditions": [
{"type": "Healthy", "status": "True", "reason": "AllHealthy"}
]
}
},
{
"apiVersion": "kargo.akuity.io/v1alpha1",
"kind": "Stage",
"metadata": {"name": "prod", "namespace": "jeebon-test"},
"status": {
"phase": "Failed",
"currentFreightId": "freight-old789",
"conditions": [
{"type": "Healthy", "status": "False", "reason": "PromotionFailed"}
]
}
}
]
})))
.mount(&server)
.await;
let script = format!(
r#"
local kargo = require("assay.kargo")
local c = kargo.client("{}", "fake-token")
local ps = c.stages:pipeline_status("jeebon-test")
assert.eq(#ps, 3)
assert.eq(ps[1].name, "test")
assert.eq(ps[1].phase, "Steady")
assert.eq(ps[1].freight, "freight-abc123")
assert.eq(ps[1].healthy, true)
assert.eq(ps[2].name, "dev")
assert.eq(ps[2].phase, "Promoting")
assert.eq(ps[2].healthy, true)
assert.eq(ps[3].name, "prod")
assert.eq(ps[3].phase, "Failed")
assert.eq(ps[3].freight, "freight-old789")
assert.eq(ps[3].healthy, false)
"#,
server.uri()
);
run_lua(&script).await.unwrap();
}
#[tokio::test]
async fn test_kargo_url_trailing_slash_stripped() {
let server = MockServer::start().await;
Mock::given(method("GET"))
.and(path("/apis/kargo.akuity.io/v1alpha1/projects/jeebon-test"))
.respond_with(ResponseTemplate::new(200).set_body_json(serde_json::json!({
"apiVersion": "kargo.akuity.io/v1alpha1",
"kind": "Project",
"metadata": {"name": "jeebon-test"}
})))
.mount(&server)
.await;
let script = format!(
r#"
local kargo = require("assay.kargo")
local c = kargo.client("{}///", "fake-token")
local p = c.projects:get("jeebon-test")
assert.eq(p.metadata.name, "jeebon-test")
"#,
server.uri()
);
run_lua(&script).await.unwrap();
}