From 0e99cd9e36dbaa02c14d6b6bfc66d0b794c32b11 Mon Sep 17 00:00:00 2001 From: Rohith Jayawardene Date: Wed, 28 Aug 2024 09:07:27 +0100 Subject: [PATCH] [E2E] - Job Status (#1492) * [E2E] - Job Status The status conditions on later versions of kubernetes has changed * fix: increasing on the timeout * fix: adjusting the ci --- test/e2e/integration/apply.bats | 30 +++--- test/e2e/integration/checkov.bats | 56 +++++------ test/e2e/integration/cloud/aws/costs.bats | 22 ++--- test/e2e/integration/contexts.bats | 46 ++++----- .../e2e/integration/custom-state-backend.bats | 96 +++++++++---------- test/e2e/integration/drift.bats | 30 +++--- test/e2e/integration/infracost.bats | 26 ++--- test/e2e/integration/plan.bats | 74 +++++++------- test/e2e/integration/private.bats | 44 ++++----- .../integration/provider-state-backend.bats | 94 +++++++++--------- test/e2e/integration/setup.bats | 54 +++++------ 11 files changed, 286 insertions(+), 286 deletions(-) diff --git a/test/e2e/integration/apply.bats b/test/e2e/integration/apply.bats index fafdf3994..b36b84284 100644 --- a/test/e2e/integration/apply.bats +++ b/test/e2e/integration/apply.bats @@ -22,51 +22,51 @@ setup() { } teardown() { - [[ -n "$BATS_TEST_COMPLETED" ]] || touch ${BATS_PARENT_TMPNAME}.skip + [[ -n $BATS_TEST_COMPLETED ]] || touch ${BATS_PARENT_TMPNAME}.skip } @test "We should be able to approve the terraform configuration" { runit "kubectl -n ${APP_NAMESPACE} annotate configurations.terraform.appvia.io ${RESOURCE_NAME} \"terraform.appvia.io/apply\"=true --overwrite" - [[ "$status" -eq 0 ]] + [[ $status -eq 0 ]] } @test "We should have a job created in the terraform-system ready to run" { labels="terraform.appvia.io/configuration=${RESOURCE_NAME},terraform.appvia.io/stage=apply" - retry 50 "kubectl -n ${NAMESPACE} get job -l ${labels} -o json" "jq -r '.items[0].status.conditions[0].type' | grep -q Complete" - [[ "$status" -eq 0 ]] + retry 50 "kubectl -n ${NAMESPACE} get job -l ${labels} -o json" "jq -r '.items[0].status.conditions[0].type' | egrep -q '(Complete|SuccessCriteriaMet)'" + [[ $status -eq 0 ]] runit "kubectl -n ${NAMESPACE} get job -l ${labels} -o json" "jq -r '.items[0].status.conditions[0].status' | grep -q True" - [[ "$status" -eq 0 ]] + [[ $status -eq 0 ]] } @test "We should have a job created in the application namespace ready to watch apply" { labels="terraform.appvia.io/configuration=${RESOURCE_NAME},terraform.appvia.io/stage=apply" - retry 10 "kubectl -n ${APP_NAMESPACE} get job -l ${labels} -o json" "jq -r '.items[0].status.conditions[0].type' | grep -q Complete" - [[ "$status" -eq 0 ]] + retry 10 "kubectl -n ${APP_NAMESPACE} get job -l ${labels} -o json" "jq -r '.items[0].status.conditions[0].type' | egrep -q '(Complete|SuccessCriteriaMet)'" + [[ $status -eq 0 ]] runit "kubectl -n ${APP_NAMESPACE} get job -l ${labels} -o json" "jq -r '.items[0].status.conditions[0].status' | grep -q True" - [[ "$status" -eq 0 ]] + [[ $status -eq 0 ]] } @test "We should have a configuration sucessfully applied" { runit "kubectl -n ${APP_NAMESPACE} get configuration ${RESOURCE_NAME} -o json" "jq -r '.status.conditions[3].name' | grep -q 'Terraform Apply'" - [[ "$status" -eq 0 ]] + [[ $status -eq 0 ]] runit "kubectl -n ${APP_NAMESPACE} get configuration ${RESOURCE_NAME} -o json" "jq -r '.status.conditions[3].reason' | grep -q 'Ready'" - [[ "$status" -eq 0 ]] + [[ $status -eq 0 ]] runit "kubectl -n ${APP_NAMESPACE} get configuration ${RESOURCE_NAME} -o json" "jq -r '.status.conditions[3].status' | grep -q 'True'" - [[ "$status" -eq 0 ]] + [[ $status -eq 0 ]] runit "kubectl -n ${APP_NAMESPACE} get configuration ${RESOURCE_NAME} -o json" "jq -r '.status.conditions[3].type' | grep -q 'TerraformApply'" - [[ "$status" -eq 0 ]] + [[ $status -eq 0 ]] } @test "We should be able to view the logs from the apply" { POD=$(kubectl -n ${APP_NAMESPACE} get pod -l terraform.appvia.io/configuration=${RESOURCE_NAME} -l terraform.appvia.io/stage=apply -o json | jq -r '.items[0].metadata.name') - [[ "$status" -eq 0 ]] + [[ $status -eq 0 ]] runit "kubectl -n ${APP_NAMESPACE} logs ${POD} 2>&1" "grep -q '\[build\] completed'" - [[ "$status" -eq 0 ]] + [[ $status -eq 0 ]] } @test "We should have the terraform version on the status" { runit "kubectl -n ${APP_NAMESPACE} get configuration ${RESOURCE_NAME} -o json" "jq -r '.status.terraformVersion' | grep -q '[0-9]\+\.[0-9]\+\.[0-9]\+'" - [[ "$status" -eq 0 ]] + [[ $status -eq 0 ]] } diff --git a/test/e2e/integration/checkov.bats b/test/e2e/integration/checkov.bats index 057e5cb78..b730695a6 100644 --- a/test/e2e/integration/checkov.bats +++ b/test/e2e/integration/checkov.bats @@ -19,22 +19,22 @@ load ../lib/helper setup() { [[ ! -f ${BATS_PARENT_TMPNAME}.skip ]] || skip "skip remaining tests" - [[ "${CLOUD}" == "aws" ]] || skip "skip for non-aws cloud" + [[ ${CLOUD} == "aws" ]] || skip "skip for non-aws cloud" } teardown() { - [[ -n "$BATS_TEST_COMPLETED" ]] || touch ${BATS_PARENT_TMPNAME}.skip + [[ -n $BATS_TEST_COMPLETED ]] || touch ${BATS_PARENT_TMPNAME}.skip } @test "We should clean the environment before running the tests" { runit "kubectl -n ${APP_NAMESPACE} delete po --all" - [[ "${status}" -eq 0 ]] + [[ ${status} -eq 0 ]] runit "kubectl -n ${APP_NAMESPACE} delete jobs --all" - [[ "${status}" -eq 0 ]] + [[ ${status} -eq 0 ]] } @test "We should be able to create a checkov policy to block resources" { - cat < ${BATS_TMPDIR}/resource.yaml + cat << EOF > ${BATS_TMPDIR}/resource.yaml apiVersion: terraform.appvia.io/v1alpha1 kind: Policy metadata: @@ -46,13 +46,13 @@ spec: skipChecks: [] EOF runit "kubectl apply -f ${BATS_TMPDIR}/resource.yaml" - [[ "$status" -eq 0 ]] + [[ $status -eq 0 ]] runit "kubectl get policies.terraform.appvia.io denied" - [[ "$status" -eq 0 ]] + [[ $status -eq 0 ]] } @test "We should be create a configuration to verify the policy blocks" { - cat <> ${BATS_TMPDIR}/resource.yaml + cat << EOF >> ${BATS_TMPDIR}/resource.yaml --- apiVersion: terraform.appvia.io/v1alpha1 kind: Configuration @@ -67,74 +67,74 @@ spec: bucket_name: ${RESOURCE_NAME}-co EOF runit "kubectl -n ${APP_NAMESPACE} apply -f ${BATS_TMPDIR}/resource.yaml" - [[ "$status" -eq 0 ]] + [[ $status -eq 0 ]] runit "kubectl -n ${APP_NAMESPACE} get configuration ${RESOURCE_NAME}-co" - [[ "$status" -eq 0 ]] + [[ $status -eq 0 ]] } @test "We should have a job created in the terraform namespace running the plan" { labels="terraform.appvia.io/configuration=${RESOURCE_NAME}-co,terraform.appvia.io/stage=plan" runit "kubectl -n ${NAMESPACE} get job -l ${labels}" - [[ "$status" -eq 0 ]] + [[ $status -eq 0 ]] } @test "We should have a watcher job created in the configuration namespace" { labels="terraform.appvia.io/configuration=${RESOURCE_NAME}-co,terraform.appvia.io/stage=plan" runit "kubectl -n ${APP_NAMESPACE} get job -l ${labels}" - [[ "$status" -eq 0 ]] + [[ $status -eq 0 ]] } @test "We should have a completed watcher job in the application namespace" { labels="terraform.appvia.io/configuration=${RESOURCE_NAME}-co,terraform.appvia.io/stage=plan" - retry 10 "kubectl -n ${APP_NAMESPACE} get job -l ${labels} -o json" "jq -r '.items[0].status.conditions[0].type' | grep -q Complete" - [[ "$status" -eq 0 ]] + retry 30 "kubectl -n ${APP_NAMESPACE} get job -l ${labels} -o json" "jq -r '.items[0].status.conditions[0].type' | egrep -q '(Complete|SuccessCriteriaMet)'" + [[ $status -eq 0 ]] runit "kubectl -n ${APP_NAMESPACE} get job -l ${labels} -o json" "jq -r '.items[0].status.conditions[0].status' | grep -q True" - [[ "$status" -eq 0 ]] + [[ $status -eq 0 ]] } @test "We should have a secret containing the evaluation in the terraform namespace" { UUID=$(kubectl -n ${APP_NAMESPACE} get configuration ${RESOURCE_NAME}-co -o json | jq -r '.metadata.uid') - [[ "$status" -eq 0 ]] + [[ $status -eq 0 ]] runit "kubectl -n ${NAMESPACE} get secret policy-${UUID}" - [[ "$status" -eq 0 ]] + [[ $status -eq 0 ]] runit "kubectl -n ${NAMESPACE} get secret policy-${UUID} -o json" "jq -r '.data.results_json.json'" - [[ "$status" -eq 0 ]] + [[ $status -eq 0 ]] } @test "We should have a copy the policy report in the configuration namespace" { UUID=$(kubectl -n ${APP_NAMESPACE} get configuration ${RESOURCE_NAME}-co -o json | jq -r '.metadata.uid') - [[ "$status" -eq 0 ]] + [[ $status -eq 0 ]] runit "kubectl -n ${APP_NAMESPACE} get secret policy-${UUID}" - [[ "$status" -eq 0 ]] + [[ $status -eq 0 ]] runit "kubectl -n ${APP_NAMESPACE} get secret policy-${UUID} -o json" "jq -r '.data.results_json.json'" - [[ "$status" -eq 0 ]] + [[ $status -eq 0 ]] } @test "We should see the conditions indicate the configuration failed policy" { POD=$(kubectl -n ${APP_NAMESPACE} get pod -l terraform.appvia.io/configuration=${RESOURCE_NAME}-co -l terraform.appvia.io/stage=plan -o json | jq -r '.items[0].metadata.name') - [[ "$status" -eq 0 ]] + [[ $status -eq 0 ]] runit "kubectl -n ${APP_NAMESPACE} logs ${POD} 2>&1" "grep -q 'EVALUATING AGAINST SECURITY POLICY'" - [[ "$status" -eq 0 ]] + [[ $status -eq 0 ]] runit "kubectl -n ${APP_NAMESPACE} logs ${POD} 2>&1" "grep -q 'FAILED for resource'" - [[ "$status" -eq 0 ]] + [[ $status -eq 0 ]] } @test "We should have a event indicating the configuration failed policy" { expected="Configuration has failed security policy, refusing to continue" runit "kubectl -n ${APP_NAMESPACE} get event" "grep -q 'Configuration has failed security policy, refusing to continue'" - [[ "$status" -eq 0 ]] + [[ $status -eq 0 ]] } @test "We should be able to cleanup the environment" { runit "kubectl -n ${APP_NAMESPACE} delete configuration ${RESOURCE_NAME}-co" - [[ "$status" -eq 0 ]] + [[ $status -eq 0 ]] runit "kubectl -n ${APP_NAMESPACE} delete po --all" - [[ "$status" -eq 0 ]] + [[ $status -eq 0 ]] runit "kubectl delete policy denied" - [[ "$status" -eq 0 ]] + [[ $status -eq 0 ]] } diff --git a/test/e2e/integration/cloud/aws/costs.bats b/test/e2e/integration/cloud/aws/costs.bats index 0f7ab368c..4a01dc514 100644 --- a/test/e2e/integration/cloud/aws/costs.bats +++ b/test/e2e/integration/cloud/aws/costs.bats @@ -22,15 +22,15 @@ setup() { } teardown() { - [[ -n "$BATS_TEST_COMPLETED" ]] || touch ${BATS_PARENT_TMPNAME}.skip + [[ -n $BATS_TEST_COMPLETED ]] || touch ${BATS_PARENT_TMPNAME}.skip } @test "We should have a token for the infracost integration" { - [[ -n "$INFRACOST_TOKEN" ]] || touch ${BATS_PARENT_TMPNAME}.skip + [[ -n $INFRACOST_TOKEN ]] || touch ${BATS_PARENT_TMPNAME}.skip } @test "We should be able to create a configuration which costs money on aws" { - cat < ${BATS_TMPDIR}/resource.yml + cat << EOF > ${BATS_TMPDIR}/resource.yml --- apiVersion: terraform.appvia.io/v1alpha1 kind: Configuration @@ -46,33 +46,33 @@ spec: instance_type: m5.8xlarge EOF runit "kubectl -n ${APP_NAMESPACE} apply -f ${BATS_TMPDIR}/resource.yml" - [[ "$status" -eq 0 ]] + [[ $status -eq 0 ]] } @test "We should have a job created in the terraform-system running the plan" { labels="terraform.appvia.io/configuration=compute,terraform.appvia.io/stage=plan" runit "kubectl -n ${NAMESPACE} get job -l ${labels}" - [[ "$status" -eq 0 ]] + [[ $status -eq 0 ]] } @test "We should see the terraform plan complete successfully" { labels="terraform.appvia.io/configuration=compute,terraform.appvia.io/stage=plan" - retry 50 "kubectl -n ${NAMESPACE} get job -l ${labels} -o json" "jq -r '.items[0].status.conditions[0].type' | grep -q Complete" - [[ "$status" -eq 0 ]] + retry 50 "kubectl -n ${NAMESPACE} get job -l ${labels} -o json" "jq -r '.items[0].status.conditions[0].type' | egrep -q '(Complete|SuccessCriteriaMet)'" + [[ $status -eq 0 ]] runit "kubectl -n ${NAMESPACE} get job -l ${labels} -o json" "jq -r '.items[0].status.conditions[0].status' | grep -q True" - [[ "$status" -eq 0 ]] + [[ $status -eq 0 ]] } @test "We should the predicted costs available on the status" { runit "kubectl -n ${APP_NAMESPACE} get configuration compute -o json" "jq -r '.status.costs.enabled' | grep -q 'true'" - [[ "$status" -eq 0 ]] + [[ $status -eq 0 ]] runit "kubectl -n ${APP_NAMESPACE} get configuration compute -o json" "jq -r '.status.costs.monthly' | grep -q '^\$[0-9\.]*'" - [[ "$status" -eq 0 ]] + [[ $status -eq 0 ]] } @test "We should be able to destroy the aws configuration for costs" { runit "kubectl -n ${APP_NAMESPACE} delete -f ${BATS_TMPDIR}/resource.yml --wait=false" - [[ "$status" -eq 0 ]] + [[ $status -eq 0 ]] } diff --git a/test/e2e/integration/contexts.bats b/test/e2e/integration/contexts.bats index 34d3db505..4962aff5d 100644 --- a/test/e2e/integration/contexts.bats +++ b/test/e2e/integration/contexts.bats @@ -23,16 +23,16 @@ setup() { } teardown() { - [[ -n "$BATS_TEST_COMPLETED" ]] || touch ${BATS_PARENT_TMPNAME}.skip + [[ -n $BATS_TEST_COMPLETED ]] || touch ${BATS_PARENT_TMPNAME}.skip } @test "We should be able to retrieve a list of contexts" { runit "kubectl get contexts.terraform.appvia.io" - [[ "${status}" -eq 0 ]] + [[ ${status} -eq 0 ]] } @test "We should be able to create a configuration context" { - cat < ${BATS_TMPDIR}/resource.yaml + cat << EOF > ${BATS_TMPDIR}/resource.yaml apiVersion: terraform.appvia.io/v1alpha1 kind: Context metadata: @@ -44,13 +44,13 @@ spec: value: true EOF runit "kubectl apply -f ${BATS_TMPDIR}/resource.yaml" - [[ "${status}" -eq 0 ]] + [[ ${status} -eq 0 ]] runit "kubectl get contexts.terraform.appvia.io default" - [[ "${status}" -eq 0 ]] + [[ ${status} -eq 0 ]] } @test "We should be able to update the terranetes context" { - cat < ${BATS_TMPDIR}/resource.yaml + cat << EOF > ${BATS_TMPDIR}/resource.yaml apiVersion: terraform.appvia.io/v1alpha1 kind: Context metadata: @@ -65,15 +65,15 @@ spec: value: true EOF runit "kubectl apply -f ${BATS_TMPDIR}/resource.yaml" - [[ "${status}" -eq 0 ]] + [[ ${status} -eq 0 ]] runit "kubectl get contexts.terraform.appvia.io default" - [[ "${status}" -eq 0 ]] + [[ ${status} -eq 0 ]] } @test "We should be able to use a context within a configuration" { namespace="context-check" - cat < ${BATS_TMPDIR}/resource.yaml + cat << EOF > ${BATS_TMPDIR}/resource.yaml apiVersion: v1 kind: Namespace metadata: @@ -83,13 +83,13 @@ metadata: EOF runit "kubectl apply -f ${BATS_TMPDIR}/resource.yaml" - [[ "${status}" -eq 0 ]] + [[ ${status} -eq 0 ]] runit "kubectl -n ${namespace} delete job --all" - [[ "${status}" -eq 0 ]] + [[ ${status} -eq 0 ]] runit "kubectl -n ${namespace} delete pod --all" - [[ "${status}" -eq 0 ]] + [[ ${status} -eq 0 ]] - cat < ${BATS_TMPDIR}/resource.yaml + cat << EOF > ${BATS_TMPDIR}/resource.yaml --- apiVersion: terraform.appvia.io/v1alpha1 kind: Configuration @@ -109,17 +109,17 @@ spec: unused: $(date +"%s") EOF runit "kubectl -n ${namespace} apply -f ${BATS_TMPDIR}/resource.yaml" - [[ "$status" -eq 0 ]] + [[ $status -eq 0 ]] } @test "We should have successfully ran the terraform plan" { namespace="context-check" labels="terraform.appvia.io/configuration=${RESOURCE_NAME},terraform.appvia.io/stage=plan" - retry 30 "kubectl -n ${namespace} get job -l ${labels} -o json" "jq -r '.items[0].status.conditions[0].type' | grep -q Complete" - [[ "$status" -eq 0 ]] + retry 30 "kubectl -n ${namespace} get job -l ${labels} -o json" "jq -r '.items[0].status.conditions[0].type' | egrep -q '(Complete|SuccessCriteriaMet)'" + [[ $status -eq 0 ]] runit "kubectl -n ${namespace} get job -l ${labels} -o json" "jq -r '.items[0].status.conditions[0].status' | grep -q True" - [[ "$status" -eq 0 ]] + [[ $status -eq 0 ]] } @test "We should be able to view the logs and see expected output" { @@ -127,26 +127,26 @@ EOF labels="-l terraform.appvia.io/configuration=${RESOURCE_NAME} -l terraform.appvia.io/stage=plan" POD=$(kubectl -n ${namespace} get pod ${labels} -o json | jq -r '.items[0].metadata.name') - [[ "$status" -eq 0 ]] + [[ $status -eq 0 ]] runit "kubectl -n ${namespace} logs ${POD} 2>&1" "grep -q 'We expect to see this'" - [[ "$status" -eq 0 ]] + [[ $status -eq 0 ]] } @test "We should not be able to delete context when in use" { runit "kubectl delete contexts.terraform.appvia.io default 2>&1" "grep -q 'resource in use by configuration'" - [[ "${status}" -eq 0 ]] + [[ ${status} -eq 0 ]] } @test "We should be able to delete a configuration" { namespace="context-check" runit "kubectl -n ${namespace} delete configuration ${RESOURCE_NAME}" - [[ "$status" -eq 0 ]] + [[ $status -eq 0 ]] } @test "We should be able to delete the configuration context" { runit "kubectl delete contexts.terraform.appvia.io default" - [[ "${status}" -eq 0 ]] + [[ ${status} -eq 0 ]] runit "kubectl get contexts.terraform.appvia.io default 2>&1" "grep -q NotFound" - [[ "${status}" -eq 0 ]] + [[ ${status} -eq 0 ]] } diff --git a/test/e2e/integration/custom-state-backend.bats b/test/e2e/integration/custom-state-backend.bats index 7c058a921..3eb7d00a7 100644 --- a/test/e2e/integration/custom-state-backend.bats +++ b/test/e2e/integration/custom-state-backend.bats @@ -22,29 +22,29 @@ setup() { } teardown() { - [[ -n "$BATS_TEST_COMPLETED" ]] || touch ${BATS_PARENT_TMPNAME}.skip + [[ -n $BATS_TEST_COMPLETED ]] || touch ${BATS_PARENT_TMPNAME}.skip } @test "We should be able to delete all resource before checking custom state" { runit "kubectl -n ${APP_NAMESPACE} delete jobs --all" - [[ "$status" -eq 0 ]] + [[ $status -eq 0 ]] runit "kubectl -n ${APP_NAMESPACE} delete pods --all" - [[ "$status" -eq 0 ]] + [[ $status -eq 0 ]] runit "kubectl -n ${APP_NAMESPACE} delete configurations --all" - [[ "$status" -eq 0 ]] + [[ $status -eq 0 ]] } @test "We should be able to clear the terraform-system namespace" { runit "kubectl -n terraform-system delete jobs --all" - [[ "$status" -eq 0 ]] + [[ $status -eq 0 ]] runit "kubectl -n terraform-system delete pods --all" - [[ "$status" -eq 0 ]] + [[ $status -eq 0 ]] } @test "We should be able to create a custom backend configuration secret" { runit "kubectl -n terraform-system delete secret terraform-backend-config || true" - [[ "$status" -eq 0 ]] - cat < ${BATS_TMPDIR}/resource.yaml 2>/dev/null + [[ $status -eq 0 ]] + cat << EOF > ${BATS_TMPDIR}/resource.yaml 2> /dev/null terraform { backend "s3" { bucket = "terranetes-controller-custom-state-e2e" @@ -56,14 +56,14 @@ terraform { } EOF runit "kubectl -n terraform-system create secret generic terraform-backend-config --from-file=backend.tf=${BATS_TMPDIR}/resource.yaml 2>/dev/null" - [[ "$status" -eq 0 ]] + [[ $status -eq 0 ]] } @test "We should be able to update the controller to use a custom backend" { CHART="charts/terranetes-controller" - if [[ "${USE_CHART}" == "false" ]]; then - cat < ${BATS_TMPDIR}/my_values.yaml + if [[ ${USE_CHART} == "false" ]]; then + cat << EOF > ${BATS_TMPDIR}/my_values.yaml controller: backend: name: terraform-backend-config @@ -77,7 +77,7 @@ EOF else CHART="appvia/terranetes-controller" - cat < ${BATS_TMPDIR}/my_values.yaml + cat << EOF > ${BATS_TMPDIR}/my_values.yaml controller: backend: name: terraform-backend-config @@ -87,11 +87,11 @@ EOF fi runit "helm upgrade terranetes-controller ${CHART} -n ${NAMESPACE} --values ${BATS_TMPDIR}/my_values.yaml" - [[ "$status" -eq 0 ]] + [[ $status -eq 0 ]] } @test "We should be able to create a configuration with a custom backend" { - cat < ${BATS_TMPDIR}/resource.yaml + cat << EOF > ${BATS_TMPDIR}/resource.yaml --- apiVersion: terraform.appvia.io/v1alpha1 kind: Configuration @@ -106,120 +106,120 @@ spec: EOF runit "kubectl -n ${APP_NAMESPACE} apply -f ${BATS_TMPDIR}/resource.yaml" - [[ "$status" -eq 0 ]] + [[ $status -eq 0 ]] } @test "We should have a completed watcher for the configuration plan" { labels="terraform.appvia.io/configuration=${RESOURCE_NAME},terraform.appvia.io/stage=plan" - retry 50 "kubectl -n ${APP_NAMESPACE} get job -l ${labels} -o json" "jq -r '.items[0].status.conditions[0].type' | grep -q Complete" - [[ "$status" -eq 0 ]] + retry 50 "kubectl -n ${APP_NAMESPACE} get job -l ${labels} -o json" "jq -r '.items[0].status.conditions[0].type' | egrep -q '(Complete|SuccessCriteriaMet)'" + [[ $status -eq 0 ]] runit "kubectl -n ${APP_NAMESPACE} get job -l ${labels} -o json" "jq -r '.items[0].status.conditions[0].status' | grep -q True" - [[ "$status" -eq 0 ]] + [[ $status -eq 0 ]] } @test "We should be able to watch the logs of the confuration" { labels="-l terraform.appvia.io/configuration=${RESOURCE_NAME} -l terraform.appvia.io/stage=plan" POD=$(kubectl -n ${APP_NAMESPACE} get pod ${labels} -o json | jq -r '.items[0].metadata.name') - [[ "$status" -eq 0 ]] + [[ $status -eq 0 ]] runit "kubectl -n ${APP_NAMESPACE} logs ${POD} 2>&1" "grep -q '\[build\] completed'" - [[ "$status" -eq 0 ]] + [[ $status -eq 0 ]] } @test "We should have a configuration in pending approval" { expected="Waiting for terraform apply annotation to be set to true" runit "kubectl -n ${APP_NAMESPACE} get configuration ${RESOURCE_NAME} -o json" "jq -r '.status.conditions[3].name' | grep -q 'Terraform Apply'" - [[ "$status" -eq 0 ]] + [[ $status -eq 0 ]] runit "kubectl -n ${APP_NAMESPACE} get configuration ${RESOURCE_NAME} -o json" "jq -r '.status.conditions[3].reason' | grep -q 'ActionRequired'" - [[ "$status" -eq 0 ]] + [[ $status -eq 0 ]] runit "kubectl -n ${APP_NAMESPACE} get configuration ${RESOURCE_NAME} -o json" "jq -r '.status.conditions[3].status' | grep -q 'False'" - [[ "$status" -eq 0 ]] + [[ $status -eq 0 ]] runit "kubectl -n ${APP_NAMESPACE} get configuration ${RESOURCE_NAME} -o json" "jq -r '.status.conditions[3].type' | grep -q 'TerraformApply'" - [[ "$status" -eq 0 ]] + [[ $status -eq 0 ]] runit "kubectl -n ${APP_NAMESPACE} get configuration ${RESOURCE_NAME} -o json" "jq -r '.status.conditions[3].message' | grep -q '${expected}'" - [[ "$status" -eq 0 ]] + [[ $status -eq 0 ]] } @test "We should be able to approve the terraform configuration" { runit "kubectl -n ${APP_NAMESPACE} annotate configurations.terraform.appvia.io ${RESOURCE_NAME} \"terraform.appvia.io/apply\"=true --overwrite" - [[ "$status" -eq 0 ]] + [[ $status -eq 0 ]] } @test "We should have a completed watcher for the configuration apply" { labels="terraform.appvia.io/configuration=${RESOURCE_NAME},terraform.appvia.io/stage=apply" - retry 30 "kubectl -n ${APP_NAMESPACE} get job -l ${labels} -o json" "jq -r '.items[0].status.conditions[0].type' | grep -q Complete" - [[ "$status" -eq 0 ]] + retry 30 "kubectl -n ${APP_NAMESPACE} get job -l ${labels} -o json" "jq -r '.items[0].status.conditions[0].type' | egrep -q '(Complete|SuccessCriteriaMet)'" + [[ $status -eq 0 ]] runit "kubectl -n ${APP_NAMESPACE} get job -l ${labels} -o json" "jq -r '.items[0].status.conditions[0].status' | grep -q True" - [[ "$status" -eq 0 ]] + [[ $status -eq 0 ]] } @test "We should have a configuration sucessfully applied" { runit "kubectl -n ${APP_NAMESPACE} get configuration ${RESOURCE_NAME} -o json" "jq -r '.status.conditions[3].name' | grep -q 'Terraform Apply'" - [[ "$status" -eq 0 ]] + [[ $status -eq 0 ]] runit "kubectl -n ${APP_NAMESPACE} get configuration ${RESOURCE_NAME} -o json" "jq -r '.status.conditions[3].reason' | grep -q 'Ready'" - [[ "$status" -eq 0 ]] + [[ $status -eq 0 ]] runit "kubectl -n ${APP_NAMESPACE} get configuration ${RESOURCE_NAME} -o json" "jq -r '.status.conditions[3].status' | grep -q 'True'" - [[ "$status" -eq 0 ]] + [[ $status -eq 0 ]] runit "kubectl -n ${APP_NAMESPACE} get configuration ${RESOURCE_NAME} -o json" "jq -r '.status.conditions[3].type' | grep -q 'TerraformApply'" - [[ "$status" -eq 0 ]] + [[ $status -eq 0 ]] } @test "We should have the custom backend defined in it's configuration secret" { ID=$(kubectl -n ${APP_NAMESPACE} get configuration ${RESOURCE_NAME} -o json | jq -r '.metadata.uid') - [[ "$status" -eq 0 ]] + [[ $status -eq 0 ]] SECRET_NAME="config-${ID}" runit "kubectl -n terraform-system get secret ${SECRET_NAME} -o json" "jq '.data[\"backend.tf\"]' -r" - [[ "$status" -eq 0 ]] + [[ $status -eq 0 ]] } @test "We should be able to view the logs from the terraform apply" { labels="-l terraform.appvia.io/configuration=${RESOURCE_NAME} -l terraform.appvia.io/stage=apply" POD=$(kubectl -n ${APP_NAMESPACE} get pod ${labels} -o json | jq -r '.items[0].metadata.name') - [[ "$status" -eq 0 ]] + [[ $status -eq 0 ]] runit "kubectl -n ${APP_NAMESPACE} logs ${POD} 2>&1" "grep -q '\[build\] completed'" - [[ "$status" -eq 0 ]] + [[ $status -eq 0 ]] } @test "We should have a terraform state secret in the terraform-system namespace" { ID=$(kubectl -n ${APP_NAMESPACE} get configuration ${RESOURCE_NAME} -o json | jq -r '.metadata.uid') - [[ "$status" -eq 0 ]] + [[ $status -eq 0 ]] SECRET_NAME="tfstate-default-${ID}" runit "kubectl -n terraform-system get secret ${SECRET_NAME}" - [[ "$status" -eq 0 ]] + [[ $status -eq 0 ]] } @test "We should have a application secret in the configuration namespace" { retry 10 "kubectl -n ${APP_NAMESPACE} get secret custom-secret" - [[ "$status" -eq 0 ]] + [[ $status -eq 0 ]] } @test "We should have the configuration secret in the application namespace" { runit "kubectl -n ${APP_NAMESPACE} get secret custom-secret -o json" "jq .data.NUMBER | grep -q -v null" - [[ "$status" -eq 0 ]] + [[ $status -eq 0 ]] } @test "We should be able to delete the configuration" { ID=$(kubectl -n ${APP_NAMESPACE} get configuration ${RESOURCE_NAME} -o json | jq -r '.metadata.uid') runit "kubectl -n ${APP_NAMESPACE} delete configuration ${RESOURCE_NAME}" - [[ "$status" -eq 0 ]] + [[ $status -eq 0 ]] runit "kubectl -n terraform-system get secret config-${ID} 2>&1" "grep -qi 'not found'" - [[ "$status" -eq 0 ]] + [[ $status -eq 0 ]] runit "kubectl -n terraform-system get secret tfstate-default-${ID} 2>&1" "grep -qi 'not found'" - [[ "$status" -eq 0 ]] + [[ $status -eq 0 ]] } @test "We should be able to revert the changes to the terranetes controller" { CHART="charts/terranetes-controller" - if [[ "${USE_CHART}" == "false" ]]; then - cat < ${BATS_TMPDIR}/my_values.yaml + if [[ ${USE_CHART} == "false" ]]; then + cat << EOF > ${BATS_TMPDIR}/my_values.yaml replicaCount: 1 controller: images: @@ -231,7 +231,7 @@ controller: EOF else CHART="appvia/terranetes-controller" - cat < ${BATS_TMPDIR}/my_values.yaml + cat << EOF > ${BATS_TMPDIR}/my_values.yaml controller: costs: secret: infracost-api @@ -239,5 +239,5 @@ EOF fi runit "helm upgrade terranetes-controller ${CHART} -n ${NAMESPACE} --values ${BATS_TMPDIR}/my_values.yaml" - [[ "$status" -eq 0 ]] + [[ $status -eq 0 ]] } diff --git a/test/e2e/integration/drift.bats b/test/e2e/integration/drift.bats index f9872a712..8c9f81130 100644 --- a/test/e2e/integration/drift.bats +++ b/test/e2e/integration/drift.bats @@ -23,62 +23,62 @@ setup() { } teardown() { - [[ -n "$BATS_TEST_COMPLETED" ]] || touch ${BATS_PARENT_TMPNAME}.skip + [[ -n $BATS_TEST_COMPLETED ]] || touch ${BATS_PARENT_TMPNAME}.skip } @test "We should have a configuration currently insync" { runit "kubectl -n ${APP_NAMESPACE} get configuration ${RESOURCE_NAME} -o json" "jq -r '.status.resourceStatus' | grep -q 'InSync'" - [[ "$status" -eq 0 ]] + [[ $status -eq 0 ]] runit "kubectl -n ${NAMESPACE} delete job --all" - [[ "$status" -eq 0 ]] + [[ $status -eq 0 ]] } @test "We should be able to delete a cloud resource to simulate drift" { runit "aws s3 rb s3://${BUCKET}" - [[ "$status" -eq 0 ]] + [[ $status -eq 0 ]] } @test "We should be able to force a drift check via an annotation" { runit "kubectl -n ${APP_NAMESPACE} annotate configurations ${RESOURCE_NAME} 'terraform.appvia.io/drift'=$(date +'%s') --overwrite" - [[ "$status" -eq 0 ]] + [[ $status -eq 0 ]] } @test "We should have a job created in the terraform-system running the plan" { labels="terraform.appvia.io/configuration=${RESOURCE_NAME},terraform.appvia.io/stage=plan" retry 10 "kubectl -n ${NAMESPACE} get job -l ${labels}" - [[ "$status" -eq 0 ]] + [[ $status -eq 0 ]] } @test "We should see the terraform plan complete successfully after drift" { labels="terraform.appvia.io/configuration=${RESOURCE_NAME},terraform.appvia.io/stage=plan" - retry 80 "kubectl -n ${NAMESPACE} get job -l ${labels} -o json" "jq -r '.items[0].status.conditions[0].type' | grep -q Complete" - [[ "$status" -eq 0 ]] + retry 80 "kubectl -n ${NAMESPACE} get job -l ${labels} -o json" "jq -r '.items[0].status.conditions[0].type' | egrep -q '(Complete|SuccessCriteriaMet)'" + [[ $status -eq 0 ]] runit "kubectl -n ${NAMESPACE} get job -l ${labels} -o json" "jq -r '.items[0].status.conditions[0].status' | grep -q True" - [[ "$status" -eq 0 ]] + [[ $status -eq 0 ]] } @test "We should see the configuration is now out of sync" { runit "kubectl -n ${APP_NAMESPACE} get configuration ${RESOURCE_NAME} -o json" "jq -r '.status.resourceStatus' | grep -q 'OutOfSync'" - [[ "$status" -eq 0 ]] + [[ $status -eq 0 ]] } @test "We should be able to patch the configuration as auto apply and synchronize the resources again" { runit "kubectl -n ${APP_NAMESPACE} patch configuration ${RESOURCE_NAME} --type merge -p '{\"spec\":{\"enableAutoApproval\":true}}'" - [[ "$status" -eq 0 ]] + [[ $status -eq 0 ]] } @test "We should have an apply job created in the terraform-system namespace" { labels="terraform.appvia.io/configuration=${RESOURCE_NAME},terraform.appvia.io/stage=apply" - retry 50 "kubectl -n ${NAMESPACE} get job -l ${labels} -o json" "jq -r '.items[0].status.conditions[0].type' | grep -q Complete" - [[ "$status" -eq 0 ]] + retry 50 "kubectl -n ${NAMESPACE} get job -l ${labels} -o json" "jq -r '.items[0].status.conditions[0].type' | egrep -q '(Complete|SuccessCriteriaMet)'" + [[ $status -eq 0 ]] runit "kubectl -n ${NAMESPACE} get job -l ${labels} -o json" "jq -r '.items[0].status.conditions[0].status' | grep -q True" - [[ "$status" -eq 0 ]] + [[ $status -eq 0 ]] } @test "We should see the configuration again in sync" { runit "kubectl -n ${APP_NAMESPACE} get configuration ${RESOURCE_NAME} -o json" "jq -r '.status.resourceStatus' | grep -q 'InSync'" - [[ "$status" -eq 0 ]] + [[ $status -eq 0 ]] } diff --git a/test/e2e/integration/infracost.bats b/test/e2e/integration/infracost.bats index 10f216ea3..86e530dcc 100644 --- a/test/e2e/integration/infracost.bats +++ b/test/e2e/integration/infracost.bats @@ -22,48 +22,48 @@ setup() { } teardown() { - [[ -n "$BATS_TEST_COMPLETED" ]] || touch ${BATS_PARENT_TMPNAME}.skip + [[ -n $BATS_TEST_COMPLETED ]] || touch ${BATS_PARENT_TMPNAME}.skip } @test "We should skip infracost when not running on aws cloud" { - [[ -z "${INFRACOST_API_KEY}" ]] && touch ${BATS_PARENT_TMPNAME}.skip - [[ "${CLOUD}" == "aws" ]] || touch ${BATS_PARENT_TMPNAME}.skip + [[ -z ${INFRACOST_API_KEY} ]] && touch ${BATS_PARENT_TMPNAME}.skip + [[ ${CLOUD} == "aws" ]] || touch ${BATS_PARENT_TMPNAME}.skip } @test "We should have a job created in the terraform-system running the plan" { labels="terraform.appvia.io/configuration=compute,terraform.appvia.io/stage=plan" runit "kubectl -n ${NAMESPACE} get job -l ${labels}" - [[ "$status" -eq 0 ]] + [[ $status -eq 0 ]] } @test "We should see the terraform plan complete successfully" { labels="terraform.appvia.io/configuration=compute,terraform.appvia.io/stage=plan" - retry 50 "kubectl -n ${NAMESPACE} get job -l ${labels} -o json" "jq -r '.items[0].status.conditions[0].type' | grep -q Complete" - [[ "$status" -eq 0 ]] + retry 50 "kubectl -n ${NAMESPACE} get job -l ${labels} -o json" "jq -r '.items[0].status.conditions[0].type' | egrep -q '(Complete|SuccessCriteriaMet)'" + [[ $status -eq 0 ]] runit "kubectl -n ${NAMESPACE} get job -l ${labels} -o json" "jq -r '.items[0].status.conditions[0].status' | grep -q True" - [[ "$status" -eq 0 ]] + [[ $status -eq 0 ]] } @test "We should the predicted costs available on the status" { runit "kubectl -n ${APP_NAMESPACE} get configuration compute -o json" "jq -r '.status.costs.enabled' | grep -q 'true'" - [[ "$status" -eq 0 ]] + [[ $status -eq 0 ]] runit "kubectl -n ${APP_NAMESPACE} get configuration compute -o json" "jq -r '.status.costs.monthly' | grep -q '^\$[0-9\.]*'" - [[ "$status" -eq 0 ]] + [[ $status -eq 0 ]] } @test "We should see infracost breakdown in the watcher logs" { POD=$(kubectl -n ${APP_NAMESPACE} get pod -l terraform.appvia.io/configuration=${RESOURCE_NAME} -l terraform.appvia.io/stage=plan -o json | jq -r '.items[0].metadata.name') - [[ "$status" -eq 0 ]] + [[ $status -eq 0 ]] runit "kubectl -n ${APP_NAMESPACE} logs ${POD} 2>&1" "grep -q 'EVALUATING THE COSTS'" - [[ "$status" -eq 0 ]] + [[ $status -eq 0 ]] runit "kubectl -n ${APP_NAMESPACE} logs ${POD} 2>&1" "grep -q 'OVERALL TOTAL'" - [[ "$status" -eq 0 ]] + [[ $status -eq 0 ]] } @test "We should be able to destroy the aws configuration for costs" { runit "kubectl -n ${APP_NAMESPACE} delete -f ${BATS_TMPDIR}/resource.yml" - [[ "$status" -eq 0 ]] + [[ $status -eq 0 ]] } diff --git a/test/e2e/integration/plan.bats b/test/e2e/integration/plan.bats index d5294519a..f515976c9 100644 --- a/test/e2e/integration/plan.bats +++ b/test/e2e/integration/plan.bats @@ -22,126 +22,126 @@ setup() { } teardown() { - [[ -n "$BATS_TEST_COMPLETED" ]] || touch ${BATS_PARENT_TMPNAME}.skip + [[ -n $BATS_TEST_COMPLETED ]] || touch ${BATS_PARENT_TMPNAME}.skip } @test "We should have a condition indicating the provider is ready" { runit "kubectl -n ${APP_NAMESPACE} get configuration ${RESOURCE_NAME} -o json" "jq -r '.status.conditions[0].name' | grep -q 'Provider ready'" - [[ "$status" -eq 0 ]] + [[ $status -eq 0 ]] runit "kubectl -n ${APP_NAMESPACE} get configuration ${RESOURCE_NAME} -o json" "jq -r '.status.conditions[0].status' | grep -q 'True'" - [[ "$status" -eq 0 ]] + [[ $status -eq 0 ]] } @test "We should have a job created in the terraform-system running the plan" { labels="terraform.appvia.io/configuration=${RESOURCE_NAME},terraform.appvia.io/stage=plan" runit "kubectl -n ${NAMESPACE} get job -l ${labels}" - [[ "$status" -eq 0 ]] + [[ $status -eq 0 ]] } @test "We should have a watcher job created in the configuration namespace" { labels="terraform.appvia.io/configuration=${RESOURCE_NAME},terraform.appvia.io/stage=plan" runit "kubectl -n ${APP_NAMESPACE} get job -l ${labels}" - [[ "$status" -eq 0 ]] + [[ $status -eq 0 ]] } @test "We should see the terraform plan complete successfully" { labels="terraform.appvia.io/configuration=${RESOURCE_NAME},terraform.appvia.io/stage=plan" - retry 50 "kubectl -n ${NAMESPACE} get job -l ${labels} -o json" "jq -r '.items[0].status.conditions[0].type' | grep -q Complete" - [[ "$status" -eq 0 ]] + retry 50 "kubectl -n ${NAMESPACE} get job -l ${labels} -o json" "jq -r '.items[0].status.conditions[0].type' | egrep -q '(Complete|SuccessCriteriaMet)'" + [[ $status -eq 0 ]] runit "kubectl -n ${NAMESPACE} get job -l ${labels} -o json" "jq -r '.items[0].status.conditions[0].status' | grep -q True" - [[ "$status" -eq 0 ]] + [[ $status -eq 0 ]] } @test "We should have a completed watcher job in the application namespace" { labels="terraform.appvia.io/configuration=${RESOURCE_NAME},terraform.appvia.io/stage=plan" - retry 10 "kubectl -n ${APP_NAMESPACE} get job -l ${labels} -o json" "jq -r '.items[0].status.conditions[0].type' | grep -q Complete" - [[ "$status" -eq 0 ]] + retry 30 "kubectl -n ${APP_NAMESPACE} get job -l ${labels} -o json" "jq -r '.items[0].status.conditions[0].type' | egrep -q '(Complete|SuccessCriteriaMet)'" + [[ $status -eq 0 ]] runit "kubectl -n ${APP_NAMESPACE} get job -l ${labels} -o json" "jq -r '.items[0].status.conditions[0].status' | grep -q True" - [[ "$status" -eq 0 ]] + [[ $status -eq 0 ]] } @test "We should have a secret containing the terraform plan" { UUID=$(kubectl -n ${APP_NAMESPACE} get configuration ${RESOURCE_NAME} -o json | jq -r '.metadata.uid') - [[ "$status" -eq 0 ]] + [[ $status -eq 0 ]] runit "kubectl -n ${NAMESPACE} get secret tfplan-out-${UUID}" - [[ "$status" -eq 0 ]] + [[ $status -eq 0 ]] runit "kubectl -n ${NAMESPACE} get secret tfplan-out-${UUID} -o json" "jq -r '.data[\"plan.out\"]'" - [[ "$status" -eq 0 ]] + [[ $status -eq 0 ]] } @test "We should have a secret containing the terraform plan in json" { UUID=$(kubectl -n ${APP_NAMESPACE} get configuration ${RESOURCE_NAME} -o json | jq -r '.metadata.uid') - [[ "$status" -eq 0 ]] + [[ $status -eq 0 ]] runit "kubectl -n ${NAMESPACE} get secret tfplan-json-${UUID}" - [[ "$status" -eq 0 ]] + [[ $status -eq 0 ]] runit "kubectl -n ${NAMESPACE} get secret tfplan-json-${UUID} -o json" "jq -r '.data[\"plan.json\"]'" - [[ "$status" -eq 0 ]] + [[ $status -eq 0 ]] } @test "We should have a configuration in pending approval" { expected="Waiting for terraform apply annotation to be set to true" runit "kubectl -n ${APP_NAMESPACE} get configuration ${RESOURCE_NAME} -o json" "jq -r '.status.conditions[3].name' | grep -q 'Terraform Apply'" - [[ "$status" -eq 0 ]] + [[ $status -eq 0 ]] runit "kubectl -n ${APP_NAMESPACE} get configuration ${RESOURCE_NAME} -o json" "jq -r '.status.conditions[3].reason' | grep -q 'ActionRequired'" - [[ "$status" -eq 0 ]] + [[ $status -eq 0 ]] runit "kubectl -n ${APP_NAMESPACE} get configuration ${RESOURCE_NAME} -o json" "jq -r '.status.conditions[3].status' | grep -q 'False'" - [[ "$status" -eq 0 ]] + [[ $status -eq 0 ]] runit "kubectl -n ${APP_NAMESPACE} get configuration ${RESOURCE_NAME} -o json" "jq -r '.status.conditions[3].type' | grep -q 'TerraformApply'" - [[ "$status" -eq 0 ]] + [[ $status -eq 0 ]] runit "kubectl -n ${APP_NAMESPACE} get configuration ${RESOURCE_NAME} -o json" "jq -r '.status.conditions[3].message' | grep -q '${expected}'" - [[ "$status" -eq 0 ]] + [[ $status -eq 0 ]] } @test "We should be able to view the logs from the plan" { POD=$(kubectl -n ${APP_NAMESPACE} get pod -l terraform.appvia.io/configuration=${RESOURCE_NAME} -l terraform.appvia.io/stage=plan -o json | jq -r '.items[0].metadata.name') - [[ "$status" -eq 0 ]] + [[ $status -eq 0 ]] runit "kubectl -n ${APP_NAMESPACE} logs ${POD} 2>&1" "grep -q '\[build\] completed'" - [[ "$status" -eq 0 ]] + [[ $status -eq 0 ]] } @test "We should have a secret in the terraform namespace containing the report" { - [[ "${INFRACOST_API_KEY}" == "" ]] && skip "INFRACOST_API_KEY is not set" + [[ ${INFRACOST_API_KEY} == "" ]] && skip "INFRACOST_API_KEY is not set" UUID=$(kubectl -n ${APP_NAMESPACE} get configuration ${RESOURCE_NAME} -o json | jq -r '.metadata.uid') - [[ "$status" -eq 0 ]] + [[ $status -eq 0 ]] runit "kubectl -n ${NAMESPACE} get secret costs-${UUID}" - [[ "$status" -eq 0 ]] + [[ $status -eq 0 ]] runit "kubectl -n ${NAMESPACE} get secret costs-${UUID} -o json" "jq -r '.data[\"costs.json\"]'" - [[ "$status" -eq 0 ]] + [[ $status -eq 0 ]] } @test "We should see the cost integration is enabled" { - [[ "${INFRACOST_API_KEY}" == "" ]] && skip "INFRACOST_API_KEY is not set" + [[ ${INFRACOST_API_KEY} == "" ]] && skip "INFRACOST_API_KEY is not set" runit "kubectl -n ${APP_NAMESPACE} get configuration ${RESOURCE_NAME} -o json" "jq -r '.status.costs.enabled' | grep -q true" - [[ "$status" -eq 0 ]] + [[ $status -eq 0 ]] } @test "We should see the cost associated to the configuration" { - [[ "${INFRACOST_API_KEY}" == "" ]] && skip "INFRACOST_API_KEY is not set" + [[ ${INFRACOST_API_KEY} == "" ]] && skip "INFRACOST_API_KEY is not set" runit "kubectl -n ${APP_NAMESPACE} get configuration ${RESOURCE_NAME} -o json" "jq -r '.status.costs.monthly' | grep -q '\$0'" - [[ "$status" -eq 0 ]] + [[ $status -eq 0 ]] runit "kubectl -n ${APP_NAMESPACE} get configuration ${RESOURCE_NAME} -o json" "jq -r '.status.costs.hourly' | grep -q '\$0'" - [[ "$status" -eq 0 ]] + [[ $status -eq 0 ]] } @test "We should have a copy of the infracost report in the configuration namespace" { - [[ "${INFRACOST_API_KEY}" == "" ]] && skip "INFRACOST_API_KEY is not set" + [[ ${INFRACOST_API_KEY} == "" ]] && skip "INFRACOST_API_KEY is not set" UUID=$(kubectl -n ${APP_NAMESPACE} get configuration ${RESOURCE_NAME} -o json | jq -r '.metadata.uid') - [[ "$status" -eq 0 ]] + [[ $status -eq 0 ]] runit "kubectl -n ${APP_NAMESPACE} get secret costs-${UUID}" - [[ "$status" -eq 0 ]] + [[ $status -eq 0 ]] runit "kubectl -n ${APP_NAMESPACE} get secret costs-${UUID} -o json" "jq -r '.data[\"costs.json\"]'" - [[ "$status" -eq 0 ]] + [[ $status -eq 0 ]] } diff --git a/test/e2e/integration/private.bats b/test/e2e/integration/private.bats index 18f9d51a1..e088fee0b 100644 --- a/test/e2e/integration/private.bats +++ b/test/e2e/integration/private.bats @@ -23,25 +23,25 @@ setup() { } teardown() { - [[ -n "$BATS_TEST_COMPLETED" ]] || touch ${BATS_PARENT_TMPNAME}.skip + [[ -n $BATS_TEST_COMPLETED ]] || touch ${BATS_PARENT_TMPNAME}.skip } @test "We should be able to create a ssh key for authentication to a private repository" { kubectl -n ${APP_NAMESPACE} get secret ssh && skip "ssh secret already exists" - cat < ${BATS_TEST_DIRNAME}/ssh-key + cat << EOF > ${BATS_TEST_DIRNAME}/ssh-key ${E2E_SSH_DEPLOYMENT_KEY} EOF runit "kubectl -n ${APP_NAMESPACE} create secret generic ssh --from-file=SSH_AUTH_KEY=${BATS_TEST_DIRNAME}/ssh-key" - [[ "$status" -eq 0 ]] + [[ $status -eq 0 ]] runit "kubectl -n ${APP_NAMESPACE} get secret ssh" - [[ "$status" -eq 0 ]] + [[ $status -eq 0 ]] runit "rm -f ${BATS_TEST_DIRNAME}/ssh-key" - [[ "$status" -eq 0 ]] + [[ $status -eq 0 ]] } @test "We should be able to create a configuration from a private repository" { -cat < ${BATS_TMPDIR}/resource.yaml + cat << EOF > ${BATS_TMPDIR}/resource.yaml --- apiVersion: terraform.appvia.io/v1alpha1 kind: Configuration @@ -55,54 +55,54 @@ spec: name: $CLOUD EOF runit "kubectl -n ${APP_NAMESPACE} apply -f ${BATS_TMPDIR}/resource.yaml" - [[ "$status" -eq 0 ]] + [[ $status -eq 0 ]] runit "kubectl -n ${APP_NAMESPACE} get configuration ${RESOURCE_NAME}" - [[ "$status" -eq 0 ]] + [[ $status -eq 0 ]] } @test "We should have a job created in the terraform-system running the plan" { labels="terraform.appvia.io/configuration=${RESOURCE_NAME},terraform.appvia.io/stage=plan" runit "kubectl -n ${NAMESPACE} get job -l ${labels}" - [[ "$status" -eq 0 ]] + [[ $status -eq 0 ]] } @test "We should see the terraform plan complete successfully" { labels="terraform.appvia.io/configuration=${RESOURCE_NAME},terraform.appvia.io/stage=plan" - retry 50 "kubectl -n ${NAMESPACE} get job -l ${labels} -o json" "jq -r '.items[0].status.conditions[0].type' | grep -q Complete" - [[ "$status" -eq 0 ]] + retry 50 "kubectl -n ${NAMESPACE} get job -l ${labels} -o json" "jq -r '.items[0].status.conditions[0].type' | egrep -q '(Complete|SuccessCriteriaMet)'" + [[ $status -eq 0 ]] runit "kubectl -n ${NAMESPACE} get job -l ${labels} -o json" "jq -r '.items[0].status.conditions[0].status' | grep -q True" - [[ "$status" -eq 0 ]] + [[ $status -eq 0 ]] } @test "We should have a completed watcher job in the application namespace" { labels="terraform.appvia.io/configuration=${RESOURCE_NAME},terraform.appvia.io/stage=plan" - retry 10 "kubectl -n ${APP_NAMESPACE} get job -l ${labels} -o json" "jq -r '.items[0].status.conditions[0].type' | grep -q Complete" - [[ "$status" -eq 0 ]] + retry 30 "kubectl -n ${APP_NAMESPACE} get job -l ${labels} -o json" "jq -r '.items[0].status.conditions[0].type' | egrep -q '(Complete|SuccessCriteriaMet)'" + [[ $status -eq 0 ]] runit "kubectl -n ${APP_NAMESPACE} get job -l ${labels} -o json" "jq -r '.items[0].status.conditions[0].status' | grep -q True" - [[ "$status" -eq 0 ]] + [[ $status -eq 0 ]] } @test "We should have a configuration in pending approval" { expected="Waiting for terraform apply annotation to be set to true" runit "kubectl -n ${APP_NAMESPACE} get configuration ${RESOURCE_NAME} -o json" "jq -r '.status.conditions[3].name' | grep -q 'Terraform Apply'" - [[ "$status" -eq 0 ]] + [[ $status -eq 0 ]] runit "kubectl -n ${APP_NAMESPACE} get configuration ${RESOURCE_NAME} -o json" "jq -r '.status.conditions[3].reason' | grep -q 'ActionRequired'" - [[ "$status" -eq 0 ]] + [[ $status -eq 0 ]] runit "kubectl -n ${APP_NAMESPACE} get configuration ${RESOURCE_NAME} -o json" "jq -r '.status.conditions[3].status' | grep -q 'False'" - [[ "$status" -eq 0 ]] + [[ $status -eq 0 ]] runit "kubectl -n ${APP_NAMESPACE} get configuration ${RESOURCE_NAME} -o json" "jq -r '.status.conditions[3].type' | grep -q 'TerraformApply'" - [[ "$status" -eq 0 ]] + [[ $status -eq 0 ]] runit "kubectl -n ${APP_NAMESPACE} get configuration ${RESOURCE_NAME} -o json" "jq -r '.status.conditions[3].message' | grep -q '${expected}'" - [[ "$status" -eq 0 ]] + [[ $status -eq 0 ]] } @test "We should be able to delete the configuration" { runit "kubectl -n ${APP_NAMESPACE} delete configuration ${RESOURCE_NAME}" - [[ "$status" -eq 0 ]] + [[ $status -eq 0 ]] runit "kubectl -n ${APP_NAMESPACE} delete po --all" - [[ "$status" -eq 0 ]] + [[ $status -eq 0 ]] } diff --git a/test/e2e/integration/provider-state-backend.bats b/test/e2e/integration/provider-state-backend.bats index cedc24c55..9b4b1d7ec 100644 --- a/test/e2e/integration/provider-state-backend.bats +++ b/test/e2e/integration/provider-state-backend.bats @@ -22,7 +22,7 @@ setup() { } teardown() { - [[ -n "$BATS_TEST_COMPLETED" ]] || touch ${BATS_PARENT_TMPNAME}.skip + [[ -n $BATS_TEST_COMPLETED ]] || touch ${BATS_PARENT_TMPNAME}.skip } @test "We should be able to create a cloud credential" { @@ -33,26 +33,26 @@ teardown() { fi runit "kubectl -n ${NAMESPACE} create secret generic aws --from-literal=AWS_ACCESS_KEY_ID=${AWS_ACCESS_KEY_ID} --from-literal=AWS_SECRET_ACCESS_KEY=${AWS_SECRET_ACCESS_KEY} --from-literal=AWS_REGION=${AWS_REGION} >/dev/null 2>&1" - [[ "$status" -eq 0 ]] + [[ $status -eq 0 ]] runit "kubectl -n ${NAMESPACE} get secret aws" - [[ "$status" -eq 0 ]] + [[ $status -eq 0 ]] } @test "We should be able to delete all resource before checking custom provider state" { runit "kubectl -n ${APP_NAMESPACE} delete jobs --all" - [[ "$status" -eq 0 ]] + [[ $status -eq 0 ]] runit "kubectl -n ${APP_NAMESPACE} delete pods --all" - [[ "$status" -eq 0 ]] + [[ $status -eq 0 ]] runit "kubectl -n ${APP_NAMESPACE} delete configurations --all" - [[ "$status" -eq 0 ]] + [[ $status -eq 0 ]] runit "kubectl -n ${APP_NAMESPACE} delete cloudresources --all" - [[ "$status" -eq 0 ]] + [[ $status -eq 0 ]] } @test "We should be able to create a custom backend configuration secret" { runit "kubectl -n terraform-system delete secret terraform-backend-config || true" - [[ "$status" -eq 0 ]] - cat < ${BATS_TMPDIR}/resource.yaml 2>/dev/null + [[ $status -eq 0 ]] + cat << EOF > ${BATS_TMPDIR}/resource.yaml 2> /dev/null terraform { backend "s3" { bucket = "terranetes-controller-state-e2e-ci" @@ -64,11 +64,11 @@ terraform { } EOF runit "kubectl -n terraform-system create secret generic terraform-backend-config --from-file=backend.tf=${BATS_TMPDIR}/resource.yaml 2>/dev/null" - [[ "$status" -eq 0 ]] + [[ $status -eq 0 ]] } @test "We should be able to create a provider using custom state" { - cat < ${BATS_TMPDIR}/resource.yaml + cat << EOF > ${BATS_TMPDIR}/resource.yaml --- apiVersion: terraform.appvia.io/v1alpha1 kind: Provider @@ -85,13 +85,13 @@ spec: name: terraform-backend-config EOF runit "kubectl apply -f ${BATS_TMPDIR}/resource.yaml" - [[ "$status" -eq 0 ]] + [[ $status -eq 0 ]] runit "kubectl get provider ${CLOUD}" - [[ "$status" -eq 0 ]] + [[ $status -eq 0 ]] } @test "We should be able to create a configuration with a custom provider backend" { - cat < ${BATS_TMPDIR}/resource.yaml + cat << EOF > ${BATS_TMPDIR}/resource.yaml --- apiVersion: terraform.appvia.io/v1alpha1 kind: Configuration @@ -106,83 +106,83 @@ spec: EOF runit "kubectl -n ${APP_NAMESPACE} apply -f ${BATS_TMPDIR}/resource.yaml" - [[ "$status" -eq 0 ]] + [[ $status -eq 0 ]] } @test "We should have a completed watcher for the configuration plan" { labels="terraform.appvia.io/configuration=${RESOURCE_NAME},terraform.appvia.io/stage=plan" - retry 30 "kubectl -n ${APP_NAMESPACE} get job -l ${labels} -o json" "jq -r '.items[0].status.conditions[0].type' | grep -q Complete" - [[ "$status" -eq 0 ]] + retry 30 "kubectl -n ${APP_NAMESPACE} get job -l ${labels} -o json" "jq -r '.items[0].status.conditions[0].type' | egrep -q '(Complete|SuccessCriteriaMet)'" + [[ $status -eq 0 ]] runit "kubectl -n ${APP_NAMESPACE} get job -l ${labels} -o json" "jq -r '.items[0].status.conditions[0].status' | grep -q True" - [[ "$status" -eq 0 ]] + [[ $status -eq 0 ]] } @test "We should be able to watch the logs of the confuration" { labels="-l terraform.appvia.io/configuration=${RESOURCE_NAME} -l terraform.appvia.io/stage=plan" POD=$(kubectl -n ${APP_NAMESPACE} get pod ${labels} -o json | jq -r '.items[0].metadata.name') - [[ "$status" -eq 0 ]] + [[ $status -eq 0 ]] runit "kubectl -n ${APP_NAMESPACE} logs ${POD} 2>&1" "grep -q '\[build\] completed'" - [[ "$status" -eq 0 ]] + [[ $status -eq 0 ]] } @test "We should have a configuration in pending approval" { expected="Waiting for terraform apply annotation to be set to true" runit "kubectl -n ${APP_NAMESPACE} get configuration ${RESOURCE_NAME} -o json" "jq -r '.status.conditions[3].name' | grep -q 'Terraform Apply'" - [[ "$status" -eq 0 ]] + [[ $status -eq 0 ]] runit "kubectl -n ${APP_NAMESPACE} get configuration ${RESOURCE_NAME} -o json" "jq -r '.status.conditions[3].reason' | grep -q 'ActionRequired'" - [[ "$status" -eq 0 ]] + [[ $status -eq 0 ]] runit "kubectl -n ${APP_NAMESPACE} get configuration ${RESOURCE_NAME} -o json" "jq -r '.status.conditions[3].status' | grep -q 'False'" - [[ "$status" -eq 0 ]] + [[ $status -eq 0 ]] runit "kubectl -n ${APP_NAMESPACE} get configuration ${RESOURCE_NAME} -o json" "jq -r '.status.conditions[3].type' | grep -q 'TerraformApply'" - [[ "$status" -eq 0 ]] + [[ $status -eq 0 ]] runit "kubectl -n ${APP_NAMESPACE} get configuration ${RESOURCE_NAME} -o json" "jq -r '.status.conditions[3].message' | grep -q '${expected}'" - [[ "$status" -eq 0 ]] + [[ $status -eq 0 ]] } @test "We should be able to approve the terraform configuration" { runit "kubectl -n ${APP_NAMESPACE} annotate configurations.terraform.appvia.io ${RESOURCE_NAME} \"terraform.appvia.io/apply\"=true --overwrite" - [[ "$status" -eq 0 ]] + [[ $status -eq 0 ]] } @test "We should have a completed watcher for the configuration apply" { labels="terraform.appvia.io/configuration=${RESOURCE_NAME},terraform.appvia.io/stage=apply" - retry 30 "kubectl -n ${APP_NAMESPACE} get job -l ${labels} -o json" "jq -r '.items[0].status.conditions[0].type' | grep -q Complete" - [[ "$status" -eq 0 ]] + retry 30 "kubectl -n ${APP_NAMESPACE} get job -l ${labels} -o json" "jq -r '.items[0].status.conditions[0].type' | egrep -q '(Complete|SuccessCriteriaMet)'" + [[ $status -eq 0 ]] runit "kubectl -n ${APP_NAMESPACE} get job -l ${labels} -o json" "jq -r '.items[0].status.conditions[0].status' | grep -q True" - [[ "$status" -eq 0 ]] + [[ $status -eq 0 ]] } @test "We should have a configuration sucessfully applied" { runit "kubectl -n ${APP_NAMESPACE} get configuration ${RESOURCE_NAME} -o json" "jq -r '.status.conditions[3].name' | grep -q 'Terraform Apply'" - [[ "$status" -eq 0 ]] + [[ $status -eq 0 ]] runit "kubectl -n ${APP_NAMESPACE} get configuration ${RESOURCE_NAME} -o json" "jq -r '.status.conditions[3].reason' | grep -q 'Ready'" - [[ "$status" -eq 0 ]] + [[ $status -eq 0 ]] runit "kubectl -n ${APP_NAMESPACE} get configuration ${RESOURCE_NAME} -o json" "jq -r '.status.conditions[3].status' | grep -q 'True'" - [[ "$status" -eq 0 ]] + [[ $status -eq 0 ]] runit "kubectl -n ${APP_NAMESPACE} get configuration ${RESOURCE_NAME} -o json" "jq -r '.status.conditions[3].type' | grep -q 'TerraformApply'" - [[ "$status" -eq 0 ]] + [[ $status -eq 0 ]] } @test "We should have the custom backend defined in it's configuration secret" { ID=$(kubectl -n ${APP_NAMESPACE} get configuration ${RESOURCE_NAME} -o json | jq -r '.metadata.uid') - [[ "$status" -eq 0 ]] + [[ $status -eq 0 ]] SECRET_NAME="config-${ID}" runit "kubectl -n terraform-system get secret ${SECRET_NAME} -o json" "jq '.data[\"backend.tf\"]' -r" - [[ "$status" -eq 0 ]] + [[ $status -eq 0 ]] } @test "We should be able to view the logs from the terraform apply" { labels="-l terraform.appvia.io/configuration=${RESOURCE_NAME} -l terraform.appvia.io/stage=apply" POD=$(kubectl -n ${APP_NAMESPACE} get pod ${labels} -o json | jq -r '.items[0].metadata.name') - [[ "$status" -eq 0 ]] + [[ $status -eq 0 ]] runit "kubectl -n ${APP_NAMESPACE} logs ${POD} 2>&1" "grep -q '\[build\] completed'" - [[ "$status" -eq 0 ]] + [[ $status -eq 0 ]] } @test "We should have a terraform state file in the remote state bucket" { @@ -190,47 +190,47 @@ EOF STATE_KEY="${GITHUB_RUN_ID:-test}/${APP_NAMESPACE}/${RESOURCE_NAME}" runit "aws s3api head-object --bucket ${BUCKET} --key ${STATE_KEY}" - [[ "$status" -eq 0 ]] + [[ $status -eq 0 ]] } @test "We should be able to delete the terraform state from bucket" { BUCKET="terranetes-controller-state-e2e-ci" runit "aws s3 rm s3://${BUCKET} --recursive" - [[ "$status" -eq 0 ]] + [[ $status -eq 0 ]] } @test "We should have a terraform state secret in the terraform-system namespace" { ID=$(kubectl -n ${APP_NAMESPACE} get configuration ${RESOURCE_NAME} -o json | jq -r '.metadata.uid') - [[ "$status" -eq 0 ]] + [[ $status -eq 0 ]] SECRET_NAME="tfstate-default-${ID}" runit "kubectl -n terraform-system get secret ${SECRET_NAME}" - [[ "$status" -eq 0 ]] + [[ $status -eq 0 ]] } @test "We should have a application secret in the configuration namespace" { runit "kubectl -n ${APP_NAMESPACE} get secret custom-secret" - [[ "$status" -eq 0 ]] + [[ $status -eq 0 ]] } @test "We should have the configuration secret in the application namespace" { runit "kubectl -n ${APP_NAMESPACE} get secret custom-secret -o json" "jq .data.NUMBER | grep -q -v null" - [[ "$status" -eq 0 ]] + [[ $status -eq 0 ]] } @test "We should be able to delete the configuration" { ID=$(kubectl -n ${APP_NAMESPACE} get configuration ${RESOURCE_NAME} -o json | jq -r '.metadata.uid') runit "kubectl -n ${APP_NAMESPACE} delete configuration ${RESOURCE_NAME}" - [[ "$status" -eq 0 ]] + [[ $status -eq 0 ]] runit "kubectl -n terraform-system get secret config-${ID} 2>&1" "grep -qi 'not found'" - [[ "$status" -eq 0 ]] + [[ $status -eq 0 ]] runit "kubectl -n terraform-system get secret tfstate-default-${ID} 2>&1" "grep -qi 'not found'" - [[ "$status" -eq 0 ]] + [[ $status -eq 0 ]] } @test "We should be able to delete the custom provider" { runit "kubectl delete provider provider-state" - [[ "$status" -eq 0 ]] + [[ $status -eq 0 ]] } diff --git a/test/e2e/integration/setup.bats b/test/e2e/integration/setup.bats index ded6d9e34..97f2fec65 100644 --- a/test/e2e/integration/setup.bats +++ b/test/e2e/integration/setup.bats @@ -22,21 +22,21 @@ setup() { } teardown() { - [[ -n "$BATS_TEST_COMPLETED" ]] || touch ${BATS_PARENT_TMPNAME}.skip + [[ -n $BATS_TEST_COMPLETED ]] || touch ${BATS_PARENT_TMPNAME}.skip } @test "We should be able to setup the helm repository" { runit "helm repo add appvia https://terranetes-controller.appvia.io" - [[ "$status" -eq 0 ]] + [[ $status -eq 0 ]] runit "helm repo update" - [[ "$status" -eq 0 ]] + [[ $status -eq 0 ]] } @test "We should be able to deploy the helm chart" { CHART="charts/terranetes-controller" if [[ ${USE_CHART} == "false" ]]; then - cat < ${BATS_TMPDIR}/my_values.yaml + cat << EOF > ${BATS_TMPDIR}/my_values.yaml replicaCount: 2 controller: enableNamespaceProtection: true @@ -50,7 +50,7 @@ EOF else CHART="appvia/terranetes-controller" - cat < ${BATS_TMPDIR}/my_values.yaml + cat << EOF > ${BATS_TMPDIR}/my_values.yaml controller: enableNamespaceProtection: true costs: @@ -59,36 +59,36 @@ EOF fi runit "helm upgrade --install terranetes-controller ${CHART} -n ${NAMESPACE} --create-namespace --values ${BATS_TMPDIR}/my_values.yaml" - [[ "$status" -eq 0 ]] + [[ $status -eq 0 ]] } @test "We should see the custom resource types" { runit "kubectl get crd configurations.terraform.appvia.io" - [[ "$status" -eq 0 ]] + [[ $status -eq 0 ]] runit "kubectl get crd policies.terraform.appvia.io" - [[ "$status" -eq 0 ]] + [[ $status -eq 0 ]] runit "kubectl get crd providers.terraform.appvia.io" - [[ "$status" -eq 0 ]] + [[ $status -eq 0 ]] runit "kubectl get crd contexts.terraform.appvia.io" - [[ "$status" -eq 0 ]] + [[ $status -eq 0 ]] runit "kubectl get crd plans.terraform.appvia.io" - [[ "$status" -eq 0 ]] + [[ $status -eq 0 ]] runit "kubectl get crd revisions.terraform.appvia.io" - [[ "$status" -eq 0 ]] + [[ $status -eq 0 ]] } @test "We should have the controller webhooks enabled" { runit "kubectl get validatingwebhookconfigurations validating-webhook-configuration" - [[ "$status" -eq 0 ]] + [[ $status -eq 0 ]] } @test "We should have the terranetes-controller helm chart deployed" { runit "helm ls -n ${NAMESPACE}" "grep -v deployed" - [[ "$status" -eq 0 ]] + [[ $status -eq 0 ]] } @test "We should be able to create a namespace for testing" { - cat < ${BATS_TMPDIR}/resource.yaml + cat << EOF > ${BATS_TMPDIR}/resource.yaml apiVersion: v1 kind: Namespace metadata: @@ -97,37 +97,37 @@ metadata: name: ${APP_NAMESPACE} EOF runit "kubectl apply -f ${BATS_TMPDIR}/resource.yaml" - [[ "$status" -eq 0 ]] + [[ $status -eq 0 ]] runit "kubectl -n ${APP_NAMESPACE} delete job --all --wait=false" - [[ "$status" -eq 0 ]] + [[ $status -eq 0 ]] runit "kubectl -n ${APP_NAMESPACE} delete po --all --wait=false" - [[ "$status" -eq 0 ]] + [[ $status -eq 0 ]] } @test "We should have a clean terraform namespace for testing" { runit "kubectl delete policies.terraform.appvia.io --all" - [[ "$status" -eq 0 ]] + [[ $status -eq 0 ]] runit "kubectl -n ${NAMESPACE} delete job --all" - [[ "$status" -eq 0 ]] + [[ $status -eq 0 ]] runit "kubectl -n ${NAMESPACE} delete po -l terraform.appvia.io/configuration" - [[ "$status" -eq 0 ]] + [[ $status -eq 0 ]] runit "kubectl -n ${APP_NAMESPACE} delete job --all --wait=false" - [[ "$status" -eq 0 ]] + [[ $status -eq 0 ]] runit "kubectl -n ${APP_NAMESPACE} delete po --all --wait=false" - [[ "$status" -eq 0 ]] + [[ $status -eq 0 ]] runit "kubectl -n ${APP_NAMESPACE} delete ev --all --wait=false" - [[ "$status" -eq 0 ]] + [[ $status -eq 0 ]] } @test "We should be able to provision a secret with infracost api token" { - [[ "${INFRACOST_API_KEY}" == "" ]] && skip "INFRACOST_API_KEY is not set" + [[ ${INFRACOST_API_KEY} == "" ]] && skip "INFRACOST_API_KEY is not set" if kubectl -n ${NAMESPACE} get secret infracost-api; then skip "infracost token already exists" fi runit "kubectl -n ${NAMESPACE} create secret generic infracost-api --from-literal=INFRACOST_API_KEY=${INFRACOST_API_KEY}" - [[ "$status" -eq 0 ]] + [[ $status -eq 0 ]] runit "kubectl -n ${NAMESPACE} get secret infracost-api" - [[ "$status" -eq 0 ]] + [[ $status -eq 0 ]] }