refactor: перемещены все тестовые скрипты в scripts/
This commit is contained in:
Executable
+818
@@ -0,0 +1,818 @@
|
||||
#!/usr/bin/env bash
|
||||
# test_simple_function.sh — интеграционные тесты fission_simple_function
|
||||
# Запуск: bash test_simple_function.sh
|
||||
# Требования: terraform + kubectl в PATH, kubeconfig в ~/.kube/config
|
||||
set -uo pipefail
|
||||
|
||||
PASS=0; FAIL=0; SKIP=0
|
||||
NAMESPACE="default"
|
||||
TESTDIR="/tmp/sless-sf-tests"
|
||||
KUBECONFIG_PATH="/home/naeel/.kube/config"
|
||||
PROVIDER_NS="default"
|
||||
|
||||
# уникальный префикс — не пересекаемся с prod
|
||||
RUN_ID="sf$(date +%s | tail -c 6)"
|
||||
|
||||
TF_PROVIDER='
|
||||
terraform {
|
||||
required_providers {
|
||||
fission = { source = "nail/fission" }
|
||||
}
|
||||
}
|
||||
provider "fission" {
|
||||
kubeconfig_path = "/home/naeel/.kube/config"
|
||||
namespace = "default"
|
||||
}
|
||||
'
|
||||
|
||||
green() { echo -e "\033[32m$*\033[0m"; }
|
||||
red() { echo -e "\033[31m$*\033[0m"; }
|
||||
yellow(){ echo -e "\033[33m$*\033[0m"; }
|
||||
|
||||
pass() { PASS=$((PASS+1)); green " PASS: $1"; }
|
||||
fail() { FAIL=$((FAIL+1)); red " FAIL: $1"; }
|
||||
skip() { SKIP=$((SKIP+1)); yellow " SKIP: $1"; }
|
||||
|
||||
# ── helpers ──────────────────────────────────────────────────────────────────
|
||||
|
||||
kube_exists() {
|
||||
local kind=$1 name=$2
|
||||
kubectl get "${kind}" -n "${NAMESPACE}" "${name}" &>/dev/null
|
||||
}
|
||||
|
||||
kube_gone() {
|
||||
local kind=$1 name=$2
|
||||
! kubectl get "${kind}" -n "${NAMESPACE}" "${name}" &>/dev/null
|
||||
}
|
||||
|
||||
tf_apply() {
|
||||
local dir=$1
|
||||
terraform -chdir="${dir}" apply -auto-approve -no-color 2>&1
|
||||
}
|
||||
|
||||
tf_destroy() {
|
||||
local dir=$1
|
||||
terraform -chdir="${dir}" destroy -auto-approve -no-color 2>&1
|
||||
}
|
||||
|
||||
tf_plan_exitcode() {
|
||||
# 0=no-changes, 1=error, 2=changes
|
||||
local dir=$1
|
||||
terraform -chdir="${dir}" plan -detailed-exitcode -no-color 2>&1
|
||||
echo $?
|
||||
}
|
||||
|
||||
wait_package_ready() {
|
||||
local name=$1 retries=30
|
||||
for ((i=0; i<retries; i++)); do
|
||||
local status
|
||||
status=$(kubectl get packages.fission.io -n "${NAMESPACE}" "${name}" \
|
||||
-o jsonpath='{.status.buildstatus}' 2>/dev/null || echo "")
|
||||
# для literal packages buildstatus пустой — это нормально
|
||||
[[ "$status" == "succeeded" || "$status" == "" ]] && return 0
|
||||
sleep 2
|
||||
done
|
||||
return 1
|
||||
}
|
||||
|
||||
# ── setup / teardown ─────────────────────────────────────────────────────────
|
||||
|
||||
}
|
||||
|
||||
EOF
|
||||
setup_workdir() {
|
||||
local name=$1
|
||||
local dir="${TESTDIR}/${name}"
|
||||
rm -rf "${dir}"
|
||||
mkdir -p "${dir}"
|
||||
echo "${dir}"
|
||||
}
|
||||
|
||||
write_provider() {
|
||||
local dir=$1
|
||||
cat > "${dir}/main.tf" <<EOF
|
||||
${TF_PROVIDER}
|
||||
EOF
|
||||
}
|
||||
|
||||
# ── code fixtures ─────────────────────────────────────────────────────────────
|
||||
|
||||
write_js_v1() {
|
||||
local dir=$1
|
||||
mkdir -p "${dir}"
|
||||
cat > "${dir}/main.js" <<'EOF'
|
||||
exports.handler = async (ctx) => ({
|
||||
body: JSON.stringify({ msg: "hello-v1", ts: Date.now() }),
|
||||
headers: { "Content-Type": "application/json" },
|
||||
});
|
||||
EOF
|
||||
}
|
||||
|
||||
write_js_v2() {
|
||||
local dir=$1
|
||||
mkdir -p "${dir}"
|
||||
cat > "${dir}/main.js" <<'EOF'
|
||||
exports.handler = async (ctx) => ({
|
||||
body: JSON.stringify({ msg: "hello-v2-updated", ts: Date.now() }),
|
||||
headers: { "Content-Type": "application/json" },
|
||||
});
|
||||
EOF
|
||||
}
|
||||
|
||||
write_python() {
|
||||
local dir=$1
|
||||
mkdir -p "${dir}"
|
||||
cat > "${dir}/main.py" <<'EOF'
|
||||
def main():
|
||||
return {"status": 200, "body": '{"msg":"hello-python"}'}
|
||||
EOF
|
||||
}
|
||||
|
||||
write_ruby() {
|
||||
local dir=$1
|
||||
mkdir -p "${dir}"
|
||||
cat > "${dir}/main.rb" <<'EOF'
|
||||
def main(ctx)
|
||||
{ body: "hello-ruby", status_code: 200 }
|
||||
end
|
||||
EOF
|
||||
}
|
||||
|
||||
write_php() {
|
||||
local dir=$1
|
||||
mkdir -p "${dir}"
|
||||
cat > "${dir}/main.php" <<'EOF'
|
||||
<?php
|
||||
function main($context) {
|
||||
return ["body" => "hello-php"];
|
||||
}
|
||||
EOF
|
||||
}
|
||||
|
||||
write_perl() {
|
||||
local dir=$1
|
||||
mkdir -p "${dir}"
|
||||
cat > "${dir}/main.pl" <<'EOF'
|
||||
sub main {
|
||||
my ($context) = @_;
|
||||
return { body => "hello-perl" };
|
||||
}
|
||||
1;
|
||||
EOF
|
||||
}
|
||||
|
||||
<<<<<<< HEAD
|
||||
=======
|
||||
EOF
|
||||
cat > "${dir}/go.mod" <<'EOF'
|
||||
module fn
|
||||
|
||||
go 1.21
|
||||
EOF
|
||||
}
|
||||
|
||||
>>>>>>> d21e1ac (feat: restore cron page, email in navbar, metrics pipeline v1.3.19)
|
||||
# ─────────────────────────────────────────────────────────────────────────────
|
||||
echo ""
|
||||
echo "================================================================"
|
||||
echo " fission_simple_function — интеграционные тесты"
|
||||
echo " Run ID: ${RUN_ID}"
|
||||
echo "================================================================"
|
||||
mkdir -p "${TESTDIR}"
|
||||
|
||||
# ════════════════════════════════════════════════════════════════════════
|
||||
echo ""
|
||||
echo ">>> T01: nodejs — create с HTTPTrigger, verify k8s, destroy"
|
||||
# ════════════════════════════════════════════════════════════════════════
|
||||
T01="${RUN_ID}-node-basic"
|
||||
D=$(setup_workdir "t01")
|
||||
write_provider "${D}"
|
||||
write_js_v1 "${D}/code"
|
||||
cat >> "${D}/main.tf" <<EOF
|
||||
resource "fission_simple_function" "fn" {
|
||||
name = "${T01}"
|
||||
runtime = "nodejs"
|
||||
code_dir = "\${path.module}/code"
|
||||
url = "/test/${T01}"
|
||||
methods = ["GET"]
|
||||
}
|
||||
EOF
|
||||
|
||||
OUT=$(tf_apply "${D}")
|
||||
if echo "${OUT}" | grep -q "Apply complete"; then
|
||||
pass "T01: terraform apply OK"
|
||||
else
|
||||
fail "T01: terraform apply FAILED"
|
||||
echo "${OUT}" | tail -20
|
||||
fi
|
||||
|
||||
kube_exists "functions.fission.io" "${T01}" \
|
||||
&& pass "T01: Function создана в k8s" || fail "T01: Function не найдена в k8s"
|
||||
kube_exists "packages.fission.io" "${T01}-pkg" \
|
||||
&& pass "T01: Package создан в k8s" || fail "T01: Package не найден в k8s"
|
||||
kube_exists "httptriggers.fission.io" "${T01}-trigger" \
|
||||
&& pass "T01: HTTPTrigger создан в k8s" || fail "T01: HTTPTrigger не найден в k8s"
|
||||
kube_exists "environments.fission.io" "simple-nodejs-env" \
|
||||
&& pass "T01: Environment simple-nodejs-env создан" || fail "T01: Environment не найден"
|
||||
|
||||
OUT=$(tf_destroy "${D}")
|
||||
echo "${OUT}" | grep -q "Destroy complete" \
|
||||
&& pass "T01: terraform destroy OK" || fail "T01: terraform destroy FAILED"
|
||||
|
||||
kube_gone "functions.fission.io" "${T01}" && pass "T01: Function удалена после destroy" || fail "T01: Function осталась после destroy"
|
||||
kube_gone "packages.fission.io" "${T01}-pkg" && pass "T01: Package удалён после destroy" || fail "T01: Package остался после destroy"
|
||||
kube_gone "httptriggers.fission.io" "${T01}-trigger" && pass "T01: Trigger удалён после destroy" || fail "T01: Trigger остался после destroy"
|
||||
|
||||
# ════════════════════════════════════════════════════════════════════════
|
||||
echo ""
|
||||
echo ">>> T02: python — create БЕЗ url (нет HTTPTrigger)"
|
||||
# ════════════════════════════════════════════════════════════════════════
|
||||
T02="${RUN_ID}-py-notrigger"
|
||||
D=$(setup_workdir "t02")
|
||||
write_provider "${D}"
|
||||
write_python "${D}/code"
|
||||
cat >> "${D}/main.tf" <<EOF
|
||||
resource "fission_simple_function" "fn" {
|
||||
name = "${T02}"
|
||||
runtime = "python"
|
||||
code_dir = "\${path.module}/code"
|
||||
}
|
||||
EOF
|
||||
|
||||
tf_apply "${D}" | grep -q "Apply complete" \
|
||||
&& pass "T02: apply OK" || fail "T02: apply FAILED"
|
||||
kube_exists "functions.fission.io" "${T02}" && pass "T02: Function создана" || fail "T02: Function не найдена"
|
||||
kube_exists "packages.fission.io" "${T02}-pkg" && pass "T02: Package создан" || fail "T02: Package не найден"
|
||||
kube_gone "httptriggers.fission.io" "${T02}-trigger" \
|
||||
&& pass "T02: HTTPTrigger НЕ создан (url не задан)" || fail "T02: HTTPTrigger создан — не должен был"
|
||||
kube_exists "environments.fission.io" "simple-python-env" \
|
||||
&& pass "T02: Environment simple-python-env создан" || fail "T02: Environment не найден"
|
||||
|
||||
tf_destroy "${D}" | grep -q "Destroy complete" && pass "T02: destroy OK" || fail "T02: destroy FAILED"
|
||||
kube_gone "functions.fission.io" "${T02}" && pass "T02: Function удалена" || fail "T02: Function осталась"
|
||||
|
||||
# ════════════════════════════════════════════════════════════════════════
|
||||
echo ""
|
||||
echo ">>> T04: ruby — create с URL"
|
||||
# ════════════════════════════════════════════════════════════════════════
|
||||
T04="${RUN_ID}-ruby"
|
||||
D=$(setup_workdir "t04")
|
||||
write_provider "${D}"
|
||||
write_ruby "${D}/code"
|
||||
cat >> "${D}/main.tf" <<EOF
|
||||
resource "fission_simple_function" "fn" {
|
||||
name = "${T04}"
|
||||
runtime = "ruby"
|
||||
code_dir = "\${path.module}/code"
|
||||
url = "/test/${T04}"
|
||||
methods = ["GET"]
|
||||
}
|
||||
EOF
|
||||
|
||||
tf_apply "${D}" | grep -q "Apply complete" \
|
||||
&& pass "T04: ruby apply OK" || fail "T04: ruby apply FAILED"
|
||||
kube_exists "environments.fission.io" "simple-ruby-env" \
|
||||
&& pass "T04: simple-ruby-env создан" || fail "T04: simple-ruby-env не найден"
|
||||
kube_exists "httptriggers.fission.io" "${T04}-trigger" \
|
||||
&& pass "T04: Trigger создан" || fail "T04: Trigger не найден"
|
||||
tf_destroy "${D}" | grep -q "Destroy complete" && pass "T04: destroy OK" || fail "T04: destroy FAILED"
|
||||
|
||||
# ════════════════════════════════════════════════════════════════════════
|
||||
echo ""
|
||||
echo ">>> T05: php — create с URL"
|
||||
# ════════════════════════════════════════════════════════════════════════
|
||||
T05="${RUN_ID}-php"
|
||||
D=$(setup_workdir "t05")
|
||||
write_provider "${D}"
|
||||
write_php "${D}/code"
|
||||
cat >> "${D}/main.tf" <<EOF
|
||||
resource "fission_simple_function" "fn" {
|
||||
name = "${T05}"
|
||||
runtime = "php"
|
||||
code_dir = "\${path.module}/code"
|
||||
url = "/test/${T05}"
|
||||
methods = ["GET"]
|
||||
}
|
||||
EOF
|
||||
|
||||
tf_apply "${D}" | grep -q "Apply complete" \
|
||||
&& pass "T05: php apply OK" || fail "T05: php apply FAILED"
|
||||
kube_exists "environments.fission.io" "simple-php-env" \
|
||||
&& pass "T05: simple-php-env создан" || fail "T05: simple-php-env не найден"
|
||||
kube_exists "functions.fission.io" "${T05}" \
|
||||
&& pass "T05: Function создана" || fail "T05: Function не найдена"
|
||||
tf_destroy "${D}" | grep -q "Destroy complete" && pass "T05: destroy OK" || fail "T05: destroy FAILED"
|
||||
|
||||
# ════════════════════════════════════════════════════════════════════════
|
||||
echo ""
|
||||
echo ">>> T06: perl — create с URL"
|
||||
# ════════════════════════════════════════════════════════════════════════
|
||||
T06="${RUN_ID}-perl"
|
||||
D=$(setup_workdir "t06")
|
||||
write_provider "${D}"
|
||||
write_perl "${D}/code"
|
||||
cat >> "${D}/main.tf" <<EOF
|
||||
resource "fission_simple_function" "fn" {
|
||||
name = "${T06}"
|
||||
runtime = "perl"
|
||||
code_dir = "\${path.module}/code"
|
||||
url = "/test/${T06}"
|
||||
methods = ["GET"]
|
||||
}
|
||||
EOF
|
||||
|
||||
tf_apply "${D}" | grep -q "Apply complete" \
|
||||
&& pass "T06: perl apply OK" || fail "T06: perl apply FAILED"
|
||||
kube_exists "environments.fission.io" "simple-perl-env" \
|
||||
&& pass "T06: simple-perl-env создан" || fail "T06: simple-perl-env не найден"
|
||||
kube_exists "functions.fission.io" "${T06}" \
|
||||
&& pass "T06: Function создана" || fail "T06: Function не найдена"
|
||||
tf_destroy "${D}" | grep -q "Destroy complete" && pass "T06: destroy OK" || fail "T06: destroy FAILED"
|
||||
|
||||
# ════════════════════════════════════════════════════════════════════════
|
||||
echo ""
|
||||
echo ">>> T07: code_hash drift detection — update пересчитывает хеш и обновляет Package"
|
||||
# ════════════════════════════════════════════════════════════════════════
|
||||
T07="${RUN_ID}-drift"
|
||||
D=$(setup_workdir "t07")
|
||||
write_provider "${D}"
|
||||
write_js_v1 "${D}/code"
|
||||
cat >> "${D}/main.tf" <<EOF
|
||||
resource "fission_simple_function" "fn" {
|
||||
name = "${T07}"
|
||||
runtime = "nodejs"
|
||||
code_dir = "\${path.module}/code"
|
||||
}
|
||||
EOF
|
||||
|
||||
tf_apply "${D}" | grep -q "Apply complete" && pass "T07: apply v1 OK" || fail "T07: apply v1 FAILED"
|
||||
|
||||
HASH1=$(terraform -chdir="${D}" show -json 2>/dev/null \
|
||||
| python3 -c "import sys,json; r=json.load(sys.stdin)['values']['root_module']['resources']; print(r[0]['values']['code_hash'])" 2>/dev/null || echo "?")
|
||||
|
||||
# Обновляем код (v2)
|
||||
write_js_v2 "${D}/code"
|
||||
|
||||
OUT=$(tf_apply "${D}")
|
||||
echo "${OUT}" | grep -q "Apply complete" && pass "T07: apply v2 OK" || fail "T07: apply v2 FAILED"
|
||||
|
||||
HASH2=$(terraform -chdir="${D}" show -json 2>/dev/null \
|
||||
| python3 -c "import sys,json; r=json.load(sys.stdin)['values']['root_module']['resources']; print(r[0]['values']['code_hash'])" 2>/dev/null || echo "?")
|
||||
|
||||
[ "${HASH1}" != "${HASH2}" ] && [ "${HASH1}" != "?" ] && [ "${HASH2}" != "?" ] \
|
||||
&& pass "T07: code_hash изменился (${HASH1:0:8}… → ${HASH2:0:8}…)" \
|
||||
|| fail "T07: code_hash не изменился или не читается (h1=${HASH1:0:8}, h2=${HASH2:0:8})"
|
||||
|
||||
echo "${OUT}" | grep -qE "fission_simple_function.fn.*updated|updated.*fission_simple_function.fn" \
|
||||
&& pass "T07: Package был обновлён (update in apply output)" \
|
||||
|| { echo "${OUT}" | grep -q "1 updated" && pass "T07: 1 ресурс обновлён" || fail "T07: Обновление не обнаружено в output"; }
|
||||
|
||||
tf_destroy "${D}" | grep -q "Destroy complete" && pass "T07: destroy OK" || fail "T07: destroy FAILED"
|
||||
|
||||
# ════════════════════════════════════════════════════════════════════════
|
||||
echo ""
|
||||
echo ">>> T08: добавление url (update — создание Trigger)"
|
||||
# ════════════════════════════════════════════════════════════════════════
|
||||
T08="${RUN_ID}-addurl"
|
||||
D=$(setup_workdir "t08")
|
||||
write_provider "${D}"
|
||||
write_js_v1 "${D}/code"
|
||||
|
||||
# Apply без url
|
||||
cat > "${D}/main.tf" <<EOF
|
||||
${TF_PROVIDER}
|
||||
resource "fission_simple_function" "fn" {
|
||||
name = "${T08}"
|
||||
runtime = "nodejs"
|
||||
code_dir = "\${path.module}/code"
|
||||
}
|
||||
EOF
|
||||
|
||||
tf_apply "${D}" | grep -q "Apply complete" && pass "T08: apply (no url) OK" || fail "T08: apply (no url) FAILED"
|
||||
kube_gone "httptriggers.fission.io" "${T08}-trigger" \
|
||||
&& pass "T08: Trigger не создан (нет url)" || fail "T08: Trigger создан без url"
|
||||
|
||||
# Добавляем url
|
||||
cat > "${D}/main.tf" <<EOF
|
||||
${TF_PROVIDER}
|
||||
resource "fission_simple_function" "fn" {
|
||||
name = "${T08}"
|
||||
runtime = "nodejs"
|
||||
code_dir = "\${path.module}/code"
|
||||
url = "/test/${T08}"
|
||||
methods = ["GET", "POST"]
|
||||
}
|
||||
EOF
|
||||
|
||||
tf_apply "${D}" | grep -q "Apply complete" && pass "T08: apply (with url) OK" || fail "T08: apply (with url) FAILED"
|
||||
kube_exists "httptriggers.fission.io" "${T08}-trigger" \
|
||||
&& pass "T08: Trigger создан после добавления url" || fail "T08: Trigger не создан после update"
|
||||
|
||||
tf_destroy "${D}" | grep -q "Destroy complete" && pass "T08: destroy OK" || fail "T08: destroy FAILED"
|
||||
kube_gone "httptriggers.fission.io" "${T08}-trigger" \
|
||||
&& pass "T08: Trigger удалён при destroy" || fail "T08: Trigger остался"
|
||||
|
||||
# ════════════════════════════════════════════════════════════════════════
|
||||
echo ""
|
||||
echo ">>> T09: удаление url (update — удаление Trigger)"
|
||||
# ════════════════════════════════════════════════════════════════════════
|
||||
T09="${RUN_ID}-rmurl"
|
||||
D=$(setup_workdir "t09")
|
||||
write_provider "${D}"
|
||||
write_js_v1 "${D}/code"
|
||||
|
||||
# Apply с url
|
||||
cat > "${D}/main.tf" <<EOF
|
||||
${TF_PROVIDER}
|
||||
resource "fission_simple_function" "fn" {
|
||||
name = "${T09}"
|
||||
runtime = "nodejs"
|
||||
code_dir = "\${path.module}/code"
|
||||
url = "/test/${T09}"
|
||||
methods = ["GET"]
|
||||
}
|
||||
EOF
|
||||
|
||||
tf_apply "${D}" | grep -q "Apply complete" && pass "T09: apply (with url) OK" || fail "T09: apply (with url) FAILED"
|
||||
kube_exists "httptriggers.fission.io" "${T09}-trigger" \
|
||||
&& pass "T09: Trigger создан" || fail "T09: Trigger не создан"
|
||||
|
||||
# Убираем url
|
||||
cat > "${D}/main.tf" <<EOF
|
||||
${TF_PROVIDER}
|
||||
resource "fission_simple_function" "fn" {
|
||||
name = "${T09}"
|
||||
runtime = "nodejs"
|
||||
code_dir = "\${path.module}/code"
|
||||
}
|
||||
EOF
|
||||
|
||||
tf_apply "${D}" | grep -q "Apply complete" && pass "T09: apply (url removed) OK" || fail "T09: apply (url removed) FAILED"
|
||||
kube_gone "httptriggers.fission.io" "${T09}-trigger" \
|
||||
&& pass "T09: Trigger удалён после убирания url" || fail "T09: Trigger остался после убирания url"
|
||||
|
||||
tf_destroy "${D}" | grep -q "Destroy complete" && pass "T09: destroy OK" || fail "T09: destroy FAILED"
|
||||
|
||||
# ════════════════════════════════════════════════════════════════════════
|
||||
echo ""
|
||||
echo ">>> T10: изменение url (update Trigger)"
|
||||
# ════════════════════════════════════════════════════════════════════════
|
||||
T10="${RUN_ID}-churl"
|
||||
D=$(setup_workdir "t10")
|
||||
write_provider "${D}"
|
||||
write_js_v1 "${D}/code"
|
||||
|
||||
cat > "${D}/main.tf" <<EOF
|
||||
${TF_PROVIDER}
|
||||
resource "fission_simple_function" "fn" {
|
||||
name = "${T10}"
|
||||
runtime = "nodejs"
|
||||
code_dir = "\${path.module}/code"
|
||||
url = "/test/${T10}/v1"
|
||||
methods = ["GET"]
|
||||
}
|
||||
EOF
|
||||
|
||||
tf_apply "${D}" | grep -q "Apply complete" && pass "T10: apply v1 url OK" || fail "T10: apply v1 url FAILED"
|
||||
|
||||
URL_BEFORE=$(kubectl get httptriggers.fission.io -n "${NAMESPACE}" "${T10}-trigger" \
|
||||
-o jsonpath='{.spec.relativeurl}' 2>/dev/null || echo "?")
|
||||
|
||||
cat > "${D}/main.tf" <<EOF
|
||||
${TF_PROVIDER}
|
||||
resource "fission_simple_function" "fn" {
|
||||
name = "${T10}"
|
||||
runtime = "nodejs"
|
||||
code_dir = "\${path.module}/code"
|
||||
url = "/test/${T10}/v2"
|
||||
methods = ["GET", "PUT"]
|
||||
}
|
||||
EOF
|
||||
|
||||
tf_apply "${D}" | grep -q "Apply complete" && pass "T10: apply v2 url OK" || fail "T10: apply v2 url FAILED"
|
||||
|
||||
URL_AFTER=$(kubectl get httptriggers.fission.io -n "${NAMESPACE}" "${T10}-trigger" \
|
||||
-o jsonpath='{.spec.relativeurl}' 2>/dev/null || echo "?")
|
||||
|
||||
[ "${URL_BEFORE}" = "/test/${T10}/v1" ] && [ "${URL_AFTER}" = "/test/${T10}/v2" ] \
|
||||
&& pass "T10: URL обновлён (/v1 → /v2)" \
|
||||
|| fail "T10: URL не обновлён (before='${URL_BEFORE}', after='${URL_AFTER}')"
|
||||
|
||||
tf_destroy "${D}" | grep -q "Destroy complete" && pass "T10: destroy OK" || fail "T10: destroy FAILED"
|
||||
|
||||
# ════════════════════════════════════════════════════════════════════════
|
||||
echo ""
|
||||
echo ">>> T11: plan без изменений → 0 changes"
|
||||
# ════════════════════════════════════════════════════════════════════════
|
||||
T11="${RUN_ID}-nochange"
|
||||
D=$(setup_workdir "t11")
|
||||
write_provider "${D}"
|
||||
write_js_v1 "${D}/code"
|
||||
cat >> "${D}/main.tf" <<EOF
|
||||
resource "fission_simple_function" "fn" {
|
||||
name = "${T11}"
|
||||
runtime = "nodejs"
|
||||
code_dir = "\${path.module}/code"
|
||||
url = "/test/${T11}"
|
||||
methods = ["GET"]
|
||||
}
|
||||
EOF
|
||||
|
||||
tf_apply "${D}" | grep -q "Apply complete" && pass "T11: initial apply OK" || fail "T11: initial apply FAILED"
|
||||
|
||||
PLAN_OUT=$(terraform -chdir="${D}" plan -no-color 2>&1)
|
||||
echo "${PLAN_OUT}" | grep -qE "No changes|0 to add, 0 to change, 0 to destroy" \
|
||||
&& pass "T11: повторный plan показывает 0 changes" \
|
||||
|| fail "T11: повторный plan показывает изменения (не idempotent)"
|
||||
|
||||
tf_destroy "${D}" | grep -q "Destroy complete" && pass "T11: destroy OK" || fail "T11: destroy FAILED"
|
||||
|
||||
# ════════════════════════════════════════════════════════════════════════
|
||||
echo ""
|
||||
echo ">>> T12: auto-env idempotency — два ресурса делят один environment"
|
||||
# ════════════════════════════════════════════════════════════════════════
|
||||
T12A="${RUN_ID}-shared-a"
|
||||
T12B="${RUN_ID}-shared-b"
|
||||
D=$(setup_workdir "t12")
|
||||
write_provider "${D}"
|
||||
write_js_v1 "${D}/code-a"
|
||||
write_js_v1 "${D}/code-b"
|
||||
cat >> "${D}/main.tf" <<EOF
|
||||
resource "fission_simple_function" "fn_a" {
|
||||
name = "${T12A}"
|
||||
runtime = "nodejs"
|
||||
code_dir = "\${path.module}/code-a"
|
||||
}
|
||||
resource "fission_simple_function" "fn_b" {
|
||||
name = "${T12B}"
|
||||
runtime = "nodejs"
|
||||
code_dir = "\${path.module}/code-b"
|
||||
}
|
||||
EOF
|
||||
|
||||
tf_apply "${D}" | grep -q "Apply complete" && pass "T12: apply двух функций OK" || fail "T12: apply двух функций FAILED"
|
||||
kube_exists "functions.fission.io" "${T12A}" && pass "T12: fn_a создана" || fail "T12: fn_a не создана"
|
||||
kube_exists "functions.fission.io" "${T12B}" && pass "T12: fn_b создана" || fail "T12: fn_b не создана"
|
||||
|
||||
# Environment должен быть один (один simple-nodejs-env)
|
||||
ENV_COUNT=$(kubectl get environments.fission.io -n "${NAMESPACE}" -o name 2>/dev/null \
|
||||
| grep -c "simple-nodejs-env" || echo "0")
|
||||
[ "${ENV_COUNT}" -eq 1 ] \
|
||||
&& pass "T12: ровно 1 экземпляр simple-nodejs-env (shared)" \
|
||||
|| fail "T12: ENV_COUNT=${ENV_COUNT} (ожидалось 1)"
|
||||
|
||||
tf_destroy "${D}" | grep -q "Destroy complete" && pass "T12: destroy OK" || fail "T12: destroy FAILED"
|
||||
kube_gone "functions.fission.io" "${T12A}" && pass "T12: fn_a удалена" || fail "T12: fn_a осталась"
|
||||
kube_gone "functions.fission.io" "${T12B}" && pass "T12: fn_b удалена" || fail "T12: fn_b осталась"
|
||||
|
||||
# ════════════════════════════════════════════════════════════════════════
|
||||
echo ""
|
||||
echo ">>> T13: невалидный runtime → apply завершается ошибкой"
|
||||
# ════════════════════════════════════════════════════════════════════════
|
||||
T13="${RUN_ID}-badruntime"
|
||||
D=$(setup_workdir "t13")
|
||||
write_provider "${D}"
|
||||
write_js_v1 "${D}/code"
|
||||
cat >> "${D}/main.tf" <<EOF
|
||||
resource "fission_simple_function" "fn" {
|
||||
name = "${T13}"
|
||||
runtime = "cobol"
|
||||
code_dir = "\${path.module}/code"
|
||||
}
|
||||
EOF
|
||||
|
||||
OUT=$(tf_apply "${D}" 2>&1 || true)
|
||||
echo "${OUT}" | grep -qiE "Error|error|cobol|неподдерживаемый|unsupported" \
|
||||
&& pass "T13: apply с runtime=cobol выдал ошибку" \
|
||||
|| fail "T13: apply не выдал ошибку для runtime=cobol"
|
||||
kube_gone "functions.fission.io" "${T13}" \
|
||||
&& pass "T13: Function не создана" || fail "T13: Function создана для плохого runtime"
|
||||
|
||||
# ════════════════════════════════════════════════════════════════════════
|
||||
echo ""
|
||||
echo ">>> T14: terraform import (namespace/name)"
|
||||
# ════════════════════════════════════════════════════════════════════════
|
||||
T14="${RUN_ID}-import"
|
||||
D=$(setup_workdir "t14")
|
||||
write_provider "${D}"
|
||||
write_js_v1 "${D}/code"
|
||||
cat >> "${D}/main.tf" <<EOF
|
||||
resource "fission_simple_function" "fn" {
|
||||
name = "${T14}"
|
||||
runtime = "nodejs"
|
||||
code_dir = "\${path.module}/code"
|
||||
url = "/test/${T14}"
|
||||
methods = ["GET"]
|
||||
}
|
||||
EOF
|
||||
|
||||
# Создаём через apply
|
||||
tf_apply "${D}" | grep -q "Apply complete" && pass "T14: initial apply OK" || fail "T14: initial apply FAILED"
|
||||
|
||||
# Удаляем state, импортируем обратно
|
||||
terraform -chdir="${D}" state rm fission_simple_function.fn &>/dev/null || true
|
||||
IMP_OUT=$(terraform -chdir="${D}" import -no-color \
|
||||
fission_simple_function.fn "default/${T14}" 2>&1)
|
||||
echo "${IMP_OUT}" | grep -qiE "Import successful|import" \
|
||||
&& pass "T14: import выполнен" || fail "T14: import не прошёл: $(echo "${IMP_OUT}" | tail -5)"
|
||||
|
||||
# Plan после import должен показать изменения (code_dir/hash не в k8s state)
|
||||
# — это нормально, просто убеждаемся что plan не падает с ошибкой
|
||||
PLAN_OUT=$(terraform -chdir="${D}" plan -no-color 2>&1)
|
||||
echo $? | grep -qE "^[012]$" && pass "T14: plan после import не падает" || fail "T14: plan после import упал"
|
||||
|
||||
tf_destroy "${D}" | grep -q "Destroy complete" && pass "T14: destroy OK" || fail "T14: destroy FAILED"
|
||||
|
||||
# ════════════════════════════════════════════════════════════════════════
|
||||
echo ""
|
||||
echo ">>> T15: nodejs — методы по умолчанию [GET]"
|
||||
# ════════════════════════════════════════════════════════════════════════
|
||||
T15="${RUN_ID}-defmethods"
|
||||
D=$(setup_workdir "t15")
|
||||
write_provider "${D}"
|
||||
write_js_v1 "${D}/code"
|
||||
cat >> "${D}/main.tf" <<EOF
|
||||
resource "fission_simple_function" "fn" {
|
||||
name = "${T15}"
|
||||
runtime = "nodejs"
|
||||
code_dir = "\${path.module}/code"
|
||||
url = "/test/${T15}"
|
||||
}
|
||||
EOF
|
||||
|
||||
tf_apply "${D}" | grep -q "Apply complete" && pass "T15: apply (no methods) OK" || fail "T15: apply FAILED"
|
||||
|
||||
METHODS=$(kubectl get httptriggers.fission.io -n "${NAMESPACE}" "${T15}-trigger" \
|
||||
-o jsonpath='{.spec.methods[*]}' 2>/dev/null || echo "?")
|
||||
echo "${METHODS}" | grep -q "GET" \
|
||||
&& pass "T15: default method=GET в k8s: '${METHODS}'" \
|
||||
|| fail "T15: методы не GET: '${METHODS}'"
|
||||
|
||||
tf_destroy "${D}" | grep -q "Destroy complete" && pass "T15: destroy OK" || fail "T15: destroy FAILED"
|
||||
|
||||
# ════════════════════════════════════════════════════════════════════════
|
||||
echo ""
|
||||
echo ">>> T16: Package.spec для nodejs — deployment (не source)"
|
||||
# ════════════════════════════════════════════════════════════════════════
|
||||
T16="${RUN_ID}-nodepkg"
|
||||
D=$(setup_workdir "t16")
|
||||
write_provider "${D}"
|
||||
write_js_v1 "${D}/code"
|
||||
cat >> "${D}/main.tf" <<EOF
|
||||
resource "fission_simple_function" "fn" {
|
||||
name = "${T16}"
|
||||
runtime = "nodejs"
|
||||
code_dir = "\${path.module}/code"
|
||||
}
|
||||
EOF
|
||||
|
||||
tf_apply "${D}" | grep -q "Apply complete" && pass "T16: apply OK" || fail "T16: apply FAILED"
|
||||
|
||||
SRC=$(kubectl get packages.fission.io -n "${NAMESPACE}" "${T16}-pkg" \
|
||||
-o jsonpath='{.spec.source.type}' 2>/dev/null || echo "")
|
||||
DEP=$(kubectl get packages.fission.io -n "${NAMESPACE}" "${T16}-pkg" \
|
||||
-o jsonpath='{.spec.deployment.type}' 2>/dev/null || echo "")
|
||||
[ -z "${SRC}" ] && [ "${DEP}" = "literal" ] \
|
||||
&& pass "T16: nodejs Package использует deployment.literal (не source)" \
|
||||
|| fail "T16: pkg spec — source.type='${SRC}', deployment.type='${DEP}'"
|
||||
|
||||
tf_destroy "${D}" | grep -q "Destroy complete" && pass "T16: destroy OK" || fail "T16: destroy FAILED"
|
||||
|
||||
# ════════════════════════════════════════════════════════════════════════
|
||||
echo ""
|
||||
echo ">>> T17: namespace вычисляется из провайдера"
|
||||
# ════════════════════════════════════════════════════════════════════════
|
||||
T17="${RUN_ID}-ns"
|
||||
D=$(setup_workdir "t17")
|
||||
write_js_v1 "${D}/code"
|
||||
# Провайдер без явного namespace в ресурсе
|
||||
cat > "${D}/main.tf" <<EOF
|
||||
${TF_PROVIDER}
|
||||
resource "fission_simple_function" "fn" {
|
||||
name = "${T17}"
|
||||
runtime = "nodejs"
|
||||
code_dir = "\${path.module}/code"
|
||||
}
|
||||
EOF
|
||||
|
||||
tf_apply "${D}" | grep -q "Apply complete" && pass "T17: apply OK" || fail "T17: apply FAILED"
|
||||
|
||||
NS=$(terraform -chdir="${D}" show -json 2>/dev/null \
|
||||
| python3 -c "import sys,json; r=json.load(sys.stdin)['values']['root_module']['resources']; print(r[0]['values']['namespace'])" 2>/dev/null || echo "?")
|
||||
[ "${NS}" = "default" ] \
|
||||
&& pass "T17: namespace=default из провайдера (state: ${NS})" \
|
||||
|| fail "T17: namespace='${NS}' (ожидалось 'default')"
|
||||
|
||||
tf_destroy "${D}" | grep -q "Destroy complete" && pass "T17: destroy OK" || fail "T17: destroy FAILED"
|
||||
|
||||
# ════════════════════════════════════════════════════════════════════════
|
||||
echo ""
|
||||
echo ">>> T18: computed поля environment_name/package_name/trigger_name в state"
|
||||
# ════════════════════════════════════════════════════════════════════════
|
||||
T18="${RUN_ID}-computed"
|
||||
D=$(setup_workdir "t18")
|
||||
write_provider "${D}"
|
||||
write_js_v1 "${D}/code"
|
||||
cat >> "${D}/main.tf" <<EOF
|
||||
resource "fission_simple_function" "fn" {
|
||||
name = "${T18}"
|
||||
runtime = "nodejs"
|
||||
code_dir = "\${path.module}/code"
|
||||
url = "/test/${T18}"
|
||||
methods = ["GET"]
|
||||
}
|
||||
EOF
|
||||
|
||||
tf_apply "${D}" | grep -q "Apply complete" && pass "T18: apply OK" || fail "T18: apply FAILED"
|
||||
|
||||
SHOW=$(terraform -chdir="${D}" show -json 2>/dev/null \
|
||||
| python3 -c "
|
||||
import sys, json
|
||||
r = json.load(sys.stdin)['values']['root_module']['resources'][0]['values']
|
||||
print(r.get('environment_name','?'))
|
||||
print(r.get('package_name','?'))
|
||||
print(r.get('trigger_name','?'))
|
||||
print(r.get('code_hash','?'))
|
||||
" 2>/dev/null || echo "?
|
||||
?
|
||||
?
|
||||
?")
|
||||
|
||||
ENV_NAME=$(echo "${SHOW}" | sed -n '1p')
|
||||
PKG_NAME=$(echo "${SHOW}" | sed -n '2p')
|
||||
TRG_NAME=$(echo "${SHOW}" | sed -n '3p')
|
||||
HASH_VAL=$(echo "${SHOW}" | sed -n '4p')
|
||||
|
||||
[ "${ENV_NAME}" = "simple-nodejs-env" ] && pass "T18: environment_name='${ENV_NAME}'" || fail "T18: environment_name='${ENV_NAME}'"
|
||||
[ "${PKG_NAME}" = "${T18}-pkg" ] && pass "T18: package_name='${PKG_NAME}'" || fail "T18: package_name='${PKG_NAME}'"
|
||||
[ "${TRG_NAME}" = "${T18}-trigger" ] && pass "T18: trigger_name='${TRG_NAME}'" || fail "T18: trigger_name='${TRG_NAME}'"
|
||||
[[ "${HASH_VAL}" =~ ^[0-9a-f]{64}$ ]] && pass "T18: code_hash выглядит как sha256" || fail "T18: code_hash='${HASH_VAL}'"
|
||||
|
||||
tf_destroy "${D}" | grep -q "Destroy complete" && pass "T18: destroy OK" || fail "T18: destroy FAILED"
|
||||
|
||||
# ════════════════════════════════════════════════════════════════════════
|
||||
echo ""
|
||||
echo ">>> T19: повторный apply одного ресурса — idempotency (no drift)"
|
||||
# ════════════════════════════════════════════════════════════════════════
|
||||
T19="${RUN_ID}-idem"
|
||||
D=$(setup_workdir "t19")
|
||||
write_provider "${D}"
|
||||
write_js_v1 "${D}/code"
|
||||
cat >> "${D}/main.tf" <<EOF
|
||||
resource "fission_simple_function" "fn" {
|
||||
name = "${T19}"
|
||||
runtime = "nodejs"
|
||||
code_dir = "\${path.module}/code"
|
||||
url = "/test/${T19}"
|
||||
methods = ["GET", "POST"]
|
||||
}
|
||||
EOF
|
||||
|
||||
tf_apply "${D}" | grep -q "Apply complete" && pass "T19: первый apply OK" || fail "T19: первый apply FAILED"
|
||||
|
||||
OUT2=$(tf_apply "${D}")
|
||||
echo "${OUT2}" | grep -qE "Apply complete.*0 added, 0 changed, 0 destroyed" \
|
||||
&& pass "T19: второй apply — 0 changes (idempotent)" \
|
||||
|| fail "T19: второй apply не idempotent: $(echo "${OUT2}" | grep -E 'added|changed|destroyed' | tail -2)"
|
||||
|
||||
tf_destroy "${D}" | grep -q "Destroy complete" && pass "T19: destroy OK" || fail "T19: destroy FAILED"
|
||||
|
||||
# ════════════════════════════════════════════════════════════════════════
|
||||
echo ""
|
||||
echo ">>> T20: destroy без trigger (url не задан) — нет паники"
|
||||
# ════════════════════════════════════════════════════════════════════════
|
||||
T20="${RUN_ID}-notrig-del"
|
||||
D=$(setup_workdir "t20")
|
||||
write_provider "${D}"
|
||||
write_python "${D}/code"
|
||||
cat >> "${D}/main.tf" <<EOF
|
||||
resource "fission_simple_function" "fn" {
|
||||
name = "${T20}"
|
||||
runtime = "python"
|
||||
code_dir = "\${path.module}/code"
|
||||
}
|
||||
EOF
|
||||
|
||||
tf_apply "${D}" | grep -q "Apply complete" && pass "T20: apply OK" || fail "T20: apply FAILED"
|
||||
OUT=$(tf_destroy "${D}")
|
||||
echo "${OUT}" | grep -q "Destroy complete" \
|
||||
&& pass "T20: destroy OK (нет паники без trigger)" \
|
||||
|| fail "T20: destroy FAILED"
|
||||
echo "${OUT}" | grep -qi "panic\|nil pointer" \
|
||||
&& fail "T20: PANIC в destroy!" || pass "T20: нет паники при destroy"
|
||||
|
||||
# ─────────────────────────────────────────────────────────────────────────────
|
||||
echo ""
|
||||
echo "================================================================"
|
||||
if [ "${FAIL}" -eq 0 ]; then
|
||||
green " ИТОГ: PASS=${PASS} FAIL=${FAIL} SKIP=${SKIP} — ВСЕ ТЕСТЫ ПРОШЛИ"
|
||||
else
|
||||
red " ИТОГ: PASS=${PASS} FAIL=${FAIL} SKIP=${SKIP} — ЕСТЬ ПРОВАЛЫ"
|
||||
fi
|
||||
echo "================================================================"
|
||||
echo ""
|
||||
|
||||
# Очистка temp dirs
|
||||
rm -rf "${TESTDIR}"
|
||||
|
||||
[ "${FAIL}" -eq 0 ]
|
||||
Reference in New Issue
Block a user