Skip to content

quote the image name in image check failure errors to make it clear it is empty #17524

quote the image name in image check failure errors to make it clear it is empty

quote the image name in image check failure errors to make it clear it is empty #17524

Workflow file for this run

name: build-test
on:
pull_request:
# pull_request_target:
# # This workflow trigger may lead to malicious PR authors being able to obtain repository write permissions or stealing repository secrets.
# # Please read https://securitylab.github.com/research/github-actions-preventing-pwn-requests/
# types: [ opened, synchronize, reopened, labeled ]
concurrency:
group: ${{ github.head_ref }}
cancel-in-progress: true
jobs:
can-run-ci:
runs-on: ubuntu-20.04
# if the event is pull_request and:
# - it is not a fork OR
# - it has the label '@actions/safe-to-test'
#
# The 'pull_request_target' workflow trigger may lead to malicious PR authors being able to obtain repository write permissions or stealing repository secrets.
# Please read https://securitylab.github.com/research/github-actions-preventing-pwn-requests/
if: >
( github.event_name == 'pull_request' &&
( github.event.pull_request.head.repo.full_name == github.repository ||
contains(github.event.pull_request.labels.*.name, '@actions/safe-to-test' )
)
)
steps:
- name: ok
run: echo "yes"
# Use this to disable tests when iterating on a specific test to save time
enable-tests:
runs-on: ubuntu-20.04
steps:
- name: ok
# change 0 to a positive integer to prevent all tests from running
run: exit 0
generate-tag:
runs-on: ubuntu-20.04
outputs:
tag: ${{ steps.get_tag.outputs.GIT_TAG }}
steps:
- name: Checkout
uses: actions/checkout@v4
- name: Get tags
id: get_tag
uses: ./.github/actions/version-tag
deps-web:
runs-on: ubuntu-20.04
needs: [ can-run-ci ]
steps:
- name: Checkout
uses: actions/checkout@v4
with:
ref: ${{github.event.pull_request.head.ref}}
repository: ${{github.event.pull_request.head.repo.full_name}}
- name: Setup Node.js environment
uses: actions/setup-node@v4
with:
node-version: '18.x'
cache: yarn
cache-dependency-path: web/yarn.lock
- name: Cache node_modules
uses: actions/cache@v4
with:
path: ${{ github.workspace }}/web/node_modules
key: ${{ runner.os }}-${{ runner.arch }}-yarn-node_modules-${{ hashFiles('web/yarn.lock') }}
- name: Install web deps
run: make -C web deps
lint-web:
runs-on: ubuntu-20.04
needs: [ can-run-ci, deps-web ]
steps:
- name: Checkout
uses: actions/checkout@v4
with:
ref: ${{github.event.pull_request.head.ref}}
repository: ${{github.event.pull_request.head.repo.full_name}}
- name: Setup Node.js environment
uses: actions/setup-node@v4
with:
node-version: '18.x'
cache: yarn
cache-dependency-path: web/yarn.lock
- name: Cache node_modules
uses: actions/cache@v4
with:
path: ${{ github.workspace }}/web/node_modules
key: ${{ runner.os }}-${{ runner.arch }}-yarn-node_modules-${{ hashFiles('web/yarn.lock') }}
- name: Lint
run: make -C web lint
unit-test-web:
runs-on: ubuntu-20.04
needs: [ can-run-ci, deps-web ]
steps:
- name: Checkout
uses: actions/checkout@v4
with:
ref: ${{github.event.pull_request.head.ref}}
repository: ${{github.event.pull_request.head.repo.full_name}}
- name: Setup Node.js environment
uses: actions/setup-node@v4
with:
node-version: '18.x'
cache: yarn
cache-dependency-path: web/yarn.lock
- name: Cache node_modules
uses: actions/cache@v4
with:
path: ${{ github.workspace }}/web/node_modules
key: ${{ runner.os }}-${{ runner.arch }}-yarn-node_modules-${{ hashFiles('web/yarn.lock') }}
- name: Unit test
run: make -C web test-unit
build-web:
runs-on: ubuntu-20.04
needs: [ can-run-ci, deps-web, generate-tag ]
steps:
# This workflow trigger may lead to malicious PR authors being able to obtain repository write permissions or stealing repository secrets.
# Please read https://securitylab.github.com/research/github-actions-preventing-pwn-requests/
# this action checks out the remote branch and runs CI
- name: Checkout
uses: actions/checkout@v4
with:
ref: ${{github.event.pull_request.head.ref}}
repository: ${{github.event.pull_request.head.repo.full_name}}
- name: Setup Node.js environment
uses: actions/setup-node@v4
with:
node-version: '18.x'
cache: yarn
cache-dependency-path: web/yarn.lock
- name: Cache node_modules
uses: actions/cache@v4
with:
path: ${{ github.workspace }}/web/node_modules
key: ${{ runner.os }}-${{ runner.arch }}-yarn-node_modules-${{ hashFiles('web/yarn.lock') }}
- name: Build web
env:
GIT_TAG: ${{ needs.generate-tag.outputs.tag }}
run: mapfile -t envs < <(grep -v '#.*' < .image.env) && export "${envs[@]}" && make -C web build-kotsadm
- name: Upload web artifact
uses: actions/upload-artifact@v4
with:
name: web
path: ./web/dist
deps-kots:
runs-on: ubuntu-20.04
needs: [ can-run-ci ]
steps:
- uses: actions/checkout@v4
with:
ref: ${{github.event.pull_request.head.ref}}
repository: ${{github.event.pull_request.head.repo.full_name}}
- uses: actions/setup-go@v5
with:
go-version: '^1.20.0'
cache: true
- run: go mod download
vet-kots:
runs-on: ubuntu-20.04
needs: [ can-run-ci, deps-kots ]
steps:
- uses: actions/checkout@v4
with:
ref: ${{github.event.pull_request.head.ref}}
repository: ${{github.event.pull_request.head.repo.full_name}}
- uses: actions/setup-go@v5
with:
go-version: '^1.20.0'
cache: true
- name: vet
run: make vet
ci-test-kots:
runs-on: ubuntu-20.04
needs: [ can-run-ci, deps-kots ]
steps:
- uses: actions/checkout@v4
with:
ref: ${{github.event.pull_request.head.ref}}
repository: ${{github.event.pull_request.head.repo.full_name}}
- uses: actions/setup-go@v5
with:
go-version: '^1.20.0'
cache: true
- name: test
run: make ci-test
build-kots:
runs-on: ubuntu-20.04
needs: [ can-run-ci, build-web, deps-kots, generate-tag ]
steps:
- uses: actions/checkout@v4
with:
ref: ${{github.event.pull_request.head.ref}}
repository: ${{github.event.pull_request.head.repo.full_name}}
- uses: actions/setup-go@v5
with:
go-version: '^1.20.0'
cache: true
- name: Download web artifact
uses: actions/download-artifact@v4
with:
name: web
path: ./web/dist
- name: Build kots
env:
GIT_TAG: ${{ needs.generate-tag.outputs.tag }}
run: mapfile -t envs < <(grep -v '#.*' < .image.env) && export "${envs[@]}" && make kots
- uses: actions/upload-artifact@v4
with:
name: kots
path: ./bin/kots
build-kotsadm-melange-packages:
needs: [ can-run-ci, generate-tag ]
strategy:
fail-fast: true
matrix:
runner: [
{name: ubuntu-20.04, arch: amd64},
{name: arm64-runner-set, arch: arm64}
]
runs-on: ${{ matrix.runner.name }}
steps:
- uses: actions/checkout@v4
with:
ref: ${{github.event.pull_request.head.ref}}
repository: ${{github.event.pull_request.head.repo.full_name}}
- uses: ./.github/actions/build-custom-melange-package
with:
context: deploy
component: kotsadm
git-tag: ${{ needs.generate-tag.outputs.tag }}
arch: ${{ matrix.runner.arch }}
build-kotsadm:
runs-on: ubuntu-20.04
needs: [ can-run-ci, generate-tag, build-kotsadm-melange-packages ]
steps:
- uses: actions/checkout@v4
with:
ref: ${{github.event.pull_request.head.ref}}
repository: ${{github.event.pull_request.head.repo.full_name}}
- uses: ./.github/actions/build-custom-image-with-apko
with:
context: deploy
component: kotsadm
git-tag: ${{ needs.generate-tag.outputs.tag }}
image-name: ttl.sh/automated-${{ github.run_id }}/kotsadm:24h
build-kots-helm:
runs-on: ubuntu-20.04
needs: [ can-run-ci ]
steps:
- uses: actions/checkout@v4
with:
ref: main
repository: replicatedhq/kots-helm
- name: Build KOTS Helm chart
env:
GIT_COMMIT: ${{ github.sha }}
run: |
curl -O -L "https://raw.githubusercontent.com/replicatedhq/kots/${GIT_COMMIT}/.image.env"
mapfile -t envs < <(grep -v '#.*' < .image.env) && export "${envs[@]}"
export CHART_VERSION=0.0.${{ github.run_id }}-automated
export KOTS_VERSION=24h
export KOTS_TAG=24h
export KOTSADM_REGISTRY=ttl.sh/automated-${{ github.run_id }}
envsubst < Chart.yaml.tmpl > Chart.yaml
envsubst < values.yaml.tmpl > values.yaml
CHART_NAME=$(helm package . | rev | cut -d/ -f1 | rev)
export CHART_NAME
helm push "$CHART_NAME" oci://ttl.sh/automated-${{ github.run_id }}
build-e2e:
runs-on: ubuntu-20.04
needs: [ can-run-ci ]
steps:
- uses: actions/setup-go@v5
with:
go-version: '^1.20.0'
- uses: actions/checkout@v4
with:
ref: ${{github.event.pull_request.head.ref}}
repository: ${{github.event.pull_request.head.repo.full_name}}
- name: Cache Go modules
uses: actions/cache@v4
with:
path: |
~/.cache/go-build
~/go/pkg/mod
key: ${{ runner.os }}-go-e2e-${{ hashFiles('**/go.sum') }}
restore-keys: |
${{ runner.os }}-go-e2e-
- run: make -C e2e build deps
- run: docker save e2e-deps -o e2e/bin/e2e-deps.tar
- uses: actions/upload-artifact@v4
with:
name: e2e
path: e2e/bin/
build-kurl-proxy-melange-packages:
needs: [ can-run-ci, generate-tag ]
strategy:
fail-fast: true
matrix:
runner: [
{name: ubuntu-20.04, arch: amd64},
{name: arm64-runner-set, arch: arm64}
]
runs-on: ${{ matrix.runner.name }}
steps:
- uses: actions/checkout@v4
with:
ref: ${{github.event.pull_request.head.ref}}
repository: ${{github.event.pull_request.head.repo.full_name}}
- uses: ./.github/actions/build-custom-melange-package
with:
context: kurl_proxy/deploy
component: kurl-proxy
git-tag: ${{ needs.generate-tag.outputs.tag }}
arch: ${{ matrix.runner.arch }}
build-kurl-proxy:
runs-on: ubuntu-20.04
needs: [ can-run-ci, generate-tag, build-kurl-proxy-melange-packages ]
steps:
- uses: actions/checkout@v4
with:
ref: ${{github.event.pull_request.head.ref}}
repository: ${{github.event.pull_request.head.repo.full_name}}
- uses: ./.github/actions/build-custom-image-with-apko
with:
context: kurl_proxy/deploy
component: kurl-proxy
git-tag: ${{ needs.generate-tag.outputs.tag }}
image-name: ttl.sh/automated-${{ github.run_id }}/kurl-proxy:24h
build-migrations-melange-packages:
needs: [ can-run-ci, generate-tag ]
strategy:
fail-fast: true
matrix:
runner: [
{name: ubuntu-20.04, arch: amd64},
{name: arm64-runner-set, arch: arm64}
]
runs-on: ${{ matrix.runner.name }}
steps:
- uses: actions/checkout@v4
with:
ref: ${{github.event.pull_request.head.ref}}
repository: ${{github.event.pull_request.head.repo.full_name}}
- uses: ./.github/actions/build-custom-melange-package
with:
context: migrations/deploy
component: kotsadm-migrations
git-tag: ${{ needs.generate-tag.outputs.tag }}
arch: ${{ matrix.runner.arch }}
build-migrations:
runs-on: ubuntu-20.04
needs: [ can-run-ci, generate-tag, build-migrations-melange-packages ]
steps:
- uses: actions/checkout@v4
with:
ref: ${{github.event.pull_request.head.ref}}
repository: ${{github.event.pull_request.head.repo.full_name}}
- uses: ./.github/actions/build-custom-image-with-apko
with:
context: migrations/deploy
component: kotsadm-migrations
git-tag: ${{ needs.generate-tag.outputs.tag }}
image-name: ttl.sh/automated-${{ github.run_id }}/kotsadm-migrations:24h
push-minio:
runs-on: ubuntu-20.04
needs: [ can-run-ci ]
steps:
# This workflow trigger may lead to malicious PR authors being able to obtain repository write permissions or stealing repository secrets.
# Please read https://securitylab.github.com/research/github-actions-preventing-pwn-requests/
# this action creates a branch based on remote branch and runs the tests
- uses: actions/checkout@v4
with:
ref: ${{github.event.pull_request.head.ref}}
repository: ${{github.event.pull_request.head.repo.full_name}}
- name: load environment variables from .image.env
uses: falti/dotenv-action@v1
id: dotenv
with:
path: .image.env
- name: push minio
run: skopeo copy --all docker://kotsadm/minio:${{ steps.dotenv.outputs.MINIO_TAG }} docker://ttl.sh/automated-${{ github.run_id }}/minio:${{ steps.dotenv.outputs.MINIO_TAG }}
push-rqlite:
runs-on: ubuntu-20.04
needs: [ can-run-ci ]
steps:
# This workflow trigger may lead to malicious PR authors being able to obtain repository write permissions or stealing repository secrets.
# Please read https://securitylab.github.com/research/github-actions-preventing-pwn-requests/
# this action creates a branch based on remote branch and runs the tests
- uses: actions/checkout@v4
with:
ref: ${{github.event.pull_request.head.ref}}
repository: ${{github.event.pull_request.head.repo.full_name}}
- name: load environment variables from .image.env
uses: falti/dotenv-action@v1
id: dotenv
with:
path: .image.env
- name: push rqlite
run: skopeo copy --all docker://kotsadm/rqlite:${{ steps.dotenv.outputs.RQLITE_TAG }} docker://ttl.sh/automated-${{ github.run_id }}/rqlite:${{ steps.dotenv.outputs.RQLITE_TAG }}
push-dex:
runs-on: ubuntu-20.04
needs: [ can-run-ci ]
steps:
# This workflow trigger may lead to malicious PR authors being able to obtain repository write permissions or stealing repository secrets.
# Please read https://securitylab.github.com/research/github-actions-preventing-pwn-requests/
# this action creates a branch based on remote branch and runs the tests
- uses: actions/checkout@v4
with:
ref: ${{github.event.pull_request.head.ref}}
repository: ${{github.event.pull_request.head.repo.full_name}}
- name: load environment variables from .image.env
uses: falti/dotenv-action@v1
id: dotenv
with:
path: .image.env
- name: push dex
run: skopeo copy --all docker://kotsadm/dex:${{ steps.dotenv.outputs.DEX_TAG }} docker://ttl.sh/automated-${{ github.run_id }}/dex:${{ steps.dotenv.outputs.DEX_TAG }}
# only run validate-kurl-addon if changes to "deploy/kurl/kotsadm/template/**"
kurl-addon-changes-filter:
runs-on: ubuntu-20.04
needs: [ can-run-ci, enable-tests ]
outputs:
ok-to-test: ${{ steps.filter.outputs.kurl-addon }}
steps:
- uses: actions/checkout@v4
- uses: dorny/paths-filter@v3
id: filter
with:
filters: |
kurl-addon:
- 'deploy/kurl/kotsadm/template/**'
- 'deploy/kurl/kotsadm/testgrid-os-spec.yaml'
validate-kurl-addon:
runs-on: ubuntu-20.04
if: ${{ needs.kurl-addon-changes-filter.outputs.ok-to-test == 'true' }}
needs: [ can-run-ci, enable-tests, generate-tag, kurl-addon-changes-filter, build-kots, build-kotsadm, build-kurl-proxy, build-migrations, push-dex ]
steps:
- name: checkout
uses: actions/checkout@v4
- name: set outputs
id: vars
run: |
addon_version=${{ needs.generate-tag.outputs.tag }}
echo "addon_version=${addon_version#v}" >> "$GITHUB_OUTPUT"
- name: download kots binary
uses: actions/download-artifact@v4
with:
name: kots
path: bin/
- name: prepare kots binary executable
run: |
chmod +x bin/*
tar -C bin/ -czvf bin/kots.tar.gz kots
- name: generate kurl add-on
id: addon-generate
uses: ./.github/actions/kurl-addon-kots-generate
env:
AWS_ACCESS_KEY_ID: ${{ secrets.KURL_ADDONS_AWS_ACCESS_KEY_ID }}
AWS_SECRET_ACCESS_KEY: ${{ secrets.KURL_ADDONS_AWS_SECRET_ACCESS_KEY }}
AWS_DEFAULT_REGION: us-east-1
with:
addon_version: ${{ steps.vars.outputs.addon_version }}
kotsadm_image_registry: ttl.sh
kotsadm_image_namespace: automated-${{ github.run_id }}
kotsadm_image_tag: 24h
kotsadm_binary_override: bin/kots.tar.gz
- name: test kurl add-on
id: addon-test
uses: ./.github/actions/kurl-addon-kots-test
with:
addon_version: ${{ steps.vars.outputs.addon_version }}
addon_package_url: ${{ steps.addon-generate.outputs.addon_package_url }}
testgrid_api_token: ${{ secrets.TESTGRID_PROD_API_TOKEN }}
- name: comment testgrid url
uses: mshick/add-pr-comment@v2
with:
message: ${{ steps.addon-test.outputs.testgrid_run_message }}
repo-token: ${{ secrets.GITHUB_TOKEN }}
allow-repeats: false
cmx-versions:
runs-on: ubuntu-20.04
needs: [ enable-tests, can-run-ci ]
steps:
- uses: actions/checkout@v4
with:
fetch-depth: 0
- name: get CMX versions to test
id: cmx-versions-to-test
uses: ./.github/actions/cmx-versions
with:
replicated-api-token: ${{ secrets.C11Y_MATRIX_TOKEN }}
outputs:
versions-to-test: ${{ steps.cmx-versions-to-test.outputs.versions-to-test }}
validate-existing-online-install-minimal:
runs-on: ubuntu-20.04
needs: [ enable-tests, can-run-ci, build-kots, build-kotsadm, build-e2e, build-kurl-proxy, build-migrations, push-minio, push-rqlite ]
steps:
- name: Checkout
uses: actions/checkout@v4
- name: download e2e deps
uses: actions/download-artifact@v4
with:
name: e2e
path: e2e/bin/
- name: download kots binary
uses: actions/download-artifact@v4
with:
name: kots
path: bin/
- run: |
docker load -i e2e/bin/e2e-deps.tar
chmod +x e2e/bin/*
chmod +x bin/*
- uses: ./.github/actions/kots-e2e
with:
kots-namespace: 'qakotsregression'
test-id: '@regression'
k8s-distribution: k3s
k8s-version: v1.26
testim-branch: ${{ github.head_ref == 'main' && 'master' || github.head_ref }}
testim-access-token: '${{ secrets.TESTIM_ACCESS_TOKEN }}'
replicated-api-token: '${{ secrets.C11Y_MATRIX_TOKEN }}'
kots-dockerhub-username: '${{ secrets.E2E_DOCKERHUB_USERNAME }}'
kots-dockerhub-password: '${{ secrets.E2E_DOCKERHUB_PASSWORD }}'
validate-smoke-test:
runs-on: ubuntu-20.04
needs: [ enable-tests, can-run-ci, cmx-versions, build-kots, build-kotsadm, build-e2e, build-kurl-proxy, build-migrations, push-minio, push-rqlite ]
strategy:
fail-fast: false
matrix:
cluster: ${{ fromJson(needs.cmx-versions.outputs.versions-to-test) }}
continue-on-error: ${{ matrix.cluster.stage != 'stable' }}
steps:
- name: Checkout
uses: actions/checkout@v4
- name: download e2e deps
uses: actions/download-artifact@v4
with:
name: e2e
path: e2e/bin/
- run: docker load -i e2e/bin/e2e-deps.tar
- run: chmod +x e2e/bin/*
- name: download kots binary
uses: actions/download-artifact@v4
with:
name: kots
path: bin/
- run: chmod +x bin/*
- uses: ./.github/actions/kots-e2e
with:
test-id: '@smoke-test'
kots-namespace: 'smoke-test'
k8s-distribution: ${{ matrix.cluster.distribution }}
k8s-version: ${{ matrix.cluster.version }}
k8s-instance-type: ${{ matrix.cluster.instance_type }}
replicated-api-token: '${{ secrets.C11Y_MATRIX_TOKEN }}'
kots-dockerhub-username: '${{ secrets.E2E_DOCKERHUB_USERNAME }}'
kots-dockerhub-password: '${{ secrets.E2E_DOCKERHUB_PASSWORD }}'
validate-minimal-rbac:
runs-on: ubuntu-20.04
needs: [ enable-tests, can-run-ci, cmx-versions, build-kots, build-kotsadm, build-e2e, build-kurl-proxy, build-migrations, push-minio, push-rqlite ]
strategy:
fail-fast: false
matrix:
cluster: [
{distribution: kind, version: v1.28.0},
{distribution: openshift, version: 4.15.0-okd}
]
env:
APP_SLUG: minimal-rbac
steps:
- name: Checkout
uses: actions/checkout@v4
- name: Create Cluster
id: create-cluster
uses: replicatedhq/replicated-actions/create-cluster@v1
with:
api-token: ${{ secrets.C11Y_MATRIX_TOKEN }}
kubernetes-distribution: ${{ matrix.cluster.distribution }}
kubernetes-version: ${{ matrix.cluster.version }}
cluster-name: automated-kots-${{ github.run_id }}-${{ matrix.cluster.distribution }}-${{ matrix.cluster.version }}
timeout-minutes: '120'
ttl: 2h
export-kubeconfig: true
- name: download kots binary
uses: actions/download-artifact@v4
with:
name: kots
path: bin/
- run: chmod +x bin/kots
- name: create namespace and dockerhub secret
run: |
kubectl create ns "$APP_SLUG"
kubectl create secret docker-registry kotsadm-dockerhub --docker-server index.docker.io --docker-username "${{ secrets.E2E_DOCKERHUB_USERNAME }}" --docker-password "${{ secrets.E2E_DOCKERHUB_PASSWORD }}" --namespace "$APP_SLUG"
- name: run the test
run: |
set +e
echo ${{ secrets.MINIMAL_RBAC_LICENSE }} | base64 -d > license.yaml
./bin/kots \
install "$APP_SLUG/automated" \
--license-file license.yaml \
--no-port-forward \
--namespace "$APP_SLUG" \
--shared-password password \
--kotsadm-registry ttl.sh \
--kotsadm-namespace automated-${{ github.run_id }} \
--additional-labels testlabel1=testvalue1 \
--additional-labels test.label/two=test.value.two \
--additional-annotations testannotation1=testannotationvalue1 \
--additional-annotations test.annotation/two=testannotation.value.two \
--tolerations test.com/role:Equal:core:NoSchedule \
--tolerations test.com/productid:Exists::NoSchedule \
--kotsadm-tag 24h | tee output.txt
if ! grep -q "The Kubernetes RBAC policy that the Admin Console is running with does not have access to complete the Preflight Checks. It's recommended that you run these manually before proceeding." output.txt; then
echo "Expected to see an RBAC error for preflight checks, but did not"
exit 1
fi
if ! grep -q 'The app was not deployed.' output.txt; then
printf "Expected to see message about app not being deployed, but did not\n"
exit 1
fi
if grep FAIL output.txt | grep -q 'This application requires at least 100 nodes'; then
printf "Did not expect to see a failure about number of nodes, but did\n"
exit 1
fi
if ! kubectl get role -n "$APP_SLUG" | grep -q kotsadm; then
echo "kotsadm role not found in namespace $APP_SLUG"
kubectl get role -n "$APP_SLUG"
exit 1
fi
if ! kubectl get rolebinding -n "$APP_SLUG" | grep -q kotsadm; then
echo "kotsadm rolebinding not found in namespace $APP_SLUG"
kubectl get rolebinding -n "$APP_SLUG"
exit 1
fi
if kubectl get clusterrole | grep -q kotsadm; then
echo "found kotsadm clusterrole in minimal RBAC install"
kubectl get clusterrole
exit 1
fi
if kubectl get clusterrolebinding | grep -q kotsadm; then
echo "found kotsadm clusterrolebinding in minimal RBAC install"
kubectl get clusterrolebinding
exit 1
fi
echo "check that the kotsadm, minio and rqlite pods have the correct labels and annotations"
echo "label one"
if ! kubectl get pods -n "$APP_SLUG" -l app=kotsadm -o jsonpath='{.items[0].metadata.labels.testlabel1}' | grep -q testvalue1; then
echo "kotsadm pod does not have the correct testlabel1 label"
kubectl get pods -n "$APP_SLUG" -l app=kotsadm -o jsonpath='{.items[0].metadata.labels}'
exit 1
fi
if ! kubectl get pods -n "$APP_SLUG" -l app=kotsadm-minio -o jsonpath='{.items[0].metadata.labels.testlabel1}' | grep -q testvalue1; then
echo "kotsadm-minio pod does not have the correct testlabel1 label"
kubectl get pods -n "$APP_SLUG" -l app=kotsadm-minio -o jsonpath='{.items[0].metadata.labels}'
exit 1
fi
if ! kubectl get pods -n "$APP_SLUG" -l app=kotsadm-rqlite -o jsonpath='{.items[0].metadata.labels.testlabel1}' | grep -q testvalue1; then
echo "kotsadm-rqlite pod does not have the correct testlabel1 label"
kubectl get pods -n "$APP_SLUG" -l app=kotsadm-rqlite -o jsonpath='{.items[0].metadata.labels}'
exit 1
fi
echo "annotation one"
if ! kubectl get pods -n "$APP_SLUG" -l app=kotsadm -o jsonpath='{.items[0].metadata.annotations.testannotation1}' | grep -q testannotationvalue1; then
echo "kotsadm pod does not have the correct testannotation1 annotation"
kubectl get pods -n "$APP_SLUG" -l app=kotsadm -o jsonpath='{.items[0].metadata.annotations}'
exit 1
fi
if ! kubectl get pods -n "$APP_SLUG" -l app=kotsadm-minio -o jsonpath='{.items[0].metadata.annotations.testannotation1}' | grep -q testannotationvalue1; then
echo "kotsadm-minio pod does not have the correct testannotation1 annotation"
kubectl get pods -n "$APP_SLUG" -l app=kotsadm-minio -o jsonpath='{.items[0].metadata.annotations}'
exit 1
fi
if ! kubectl get pods -n "$APP_SLUG" -l app=kotsadm-rqlite -o jsonpath='{.items[0].metadata.annotations.testannotation1}' | grep -q testannotationvalue1; then
echo "kotsadm-rqlite pod does not have the correct testannotation1 annotation"
kubectl get pods -n "$APP_SLUG" -l app=kotsadm-rqlite -o jsonpath='{.items[0].metadata.annotations}'
exit 1
fi
echo "label two"
if ! kubectl get pod -n "$APP_SLUG" -l app=kotsadm -o jsonpath='{.items[0].metadata.labels.test\.label/two}' | grep -q 'test.value.two'; then
echo "kotsadm pod does not have the correct test.label/two label"
kubectl get pod -n "$APP_SLUG" -l app=kotsadm -o jsonpath='{.items[0].metadata.labels}'
exit 1
fi
if ! kubectl get pod -n "$APP_SLUG" -l app=kotsadm-minio -o jsonpath='{.items[0].metadata.labels.test\.label/two}' | grep -q 'test.value.two'; then
echo "kotsadm-minio pod does not have the correct test.label/two label"
kubectl get pod -n "$APP_SLUG" -l app=kotsadm-minio -o jsonpath='{.items[0].metadata.labels}'
exit 1
fi
if ! kubectl get pod -n "$APP_SLUG" -l app=kotsadm-rqlite -o jsonpath='{.items[0].metadata.labels.test\.label/two}' | grep -q 'test.value.two'; then
echo "kotsadm-rqlite pod does not have the correct test.label/two label"
kubectl get pod -n "$APP_SLUG" -l app=kotsadm-rqlite -o jsonpath='{.items[0].metadata.labels}'
exit 1
fi
echo "annotation two"
if ! kubectl get pod -n "$APP_SLUG" -l app=kotsadm -o jsonpath='{.items[0].metadata.annotations.test\.annotation/two}' | grep -q 'testannotation.value.two'; then
echo "kotsadm pod does not have the correct test.annotation/two annotation"
kubectl get pod -n "$APP_SLUG" -l app=kotsadm -o jsonpath='{.items[0].metadata.annotations}'
exit 1
fi
if ! kubectl get pod -n "$APP_SLUG" -l app=kotsadm-minio -o jsonpath='{.items[0].metadata.annotations.test\.annotation/two}' | grep -q 'testannotation.value.two'; then
echo "kotsadm-minio pod does not have the correct test.annotation/two annotation"
kubectl get pod -n "$APP_SLUG" -l app=kotsadm-minio -o jsonpath='{.items[0].metadata.annotations}'
exit 1
fi
if ! kubectl get pod -n "$APP_SLUG" -l app=kotsadm-rqlite -o jsonpath='{.items[0].metadata.annotations.test\.annotation/two}' | grep -q 'testannotation.value.two'; then
echo "kotsadm-rqlite pod does not have the correct test.annotation/two annotation"
kubectl get pod -n "$APP_SLUG" -l app=kotsadm-rqlite -o jsonpath='{.items[0].metadata.annotations}'
exit 1
fi
echo "additional pod labels and annotations are present"
echo "check that the kotsadm, minio and rqlite pods have the correct tolerations"
echo "Equal toleration"
if ! kubectl get pods -n "$APP_SLUG" -l app=kotsadm -o jsonpath='{.items[0].spec.tolerations[*]}' | grep 'Equal' | grep 'NoSchedule' | grep -q 'test.com/role'; then
echo "kotsadm pod does not have Equal toleration"
kubectl get pods -n "$APP_SLUG" -l app=kotsadm -o jsonpath='{.items[0].spec.tolerations[*]}'
exit 1
fi
if ! kubectl get pods -n "$APP_SLUG" -l app=kotsadm-minio -o jsonpath='{.items[0].spec.tolerations[*]}' | grep 'Equal' | grep 'NoSchedule' | grep -q 'test.com/role'; then
echo "kotsadm-minio pod does not have Equal toleration"
kubectl get pods -n "$APP_SLUG" -l app=kotsadm-minio -o jsonpath='{.items[0].spec.tolerations[*]}'
exit 1
fi
if ! kubectl get pods -n "$APP_SLUG" -l app=kotsadm-rqlite -o jsonpath='{.items[0].spec.tolerations[*]}' | grep 'Equal' | grep 'NoSchedule' | grep -q 'test.com/role'; then
echo "kotsadm-rqlite pod does not have Equal toleration"
kubectl get pods -n "$APP_SLUG" -l app=kotsadm-rqlite -o jsonpath='{.items[0].spec.tolerations[*]}'
exit 1
fi
echo "Equal tolerations are present"
echo "Exists toleration"
if ! kubectl get pods -n "$APP_SLUG" -l app=kotsadm -o jsonpath='{.items[0].spec.tolerations[*]}' | grep 'Exists' | grep 'NoSchedule' | grep -q 'test.com/productid'; then
echo "kotsadm pod does not have Exists toleration"
kubectl get pods -n "$APP_SLUG" -l app=kotsadm -o jsonpath='{.items[0].spec.tolerations[*]}'
exit 1
fi
if ! kubectl get pods -n "$APP_SLUG" -l app=kotsadm-minio -o jsonpath='{.items[0].spec.tolerations[*]}' | grep 'Exists' | grep 'NoSchedule' | grep -q 'test.com/productid'; then
echo "kotsadm-minio pod does not have Exists toleration"
kubectl get pods -n "$APP_SLUG" -l app=kotsadm-minio -o jsonpath='{.items[0].spec.tolerations[*]}'
exit 1
fi
if ! kubectl get pods -n "$APP_SLUG" -l app=kotsadm-rqlite -o jsonpath='{.items[0].spec.tolerations[*]}' | grep 'Exists' | grep 'NoSchedule' | grep -q 'test.com/productid'; then
echo "kotsadm-rqlite pod does not have Exists toleration"
kubectl get pods -n "$APP_SLUG" -l app=kotsadm-rqlite -o jsonpath='{.items[0].spec.tolerations[*]}'
exit 1
fi
echo "Exists tolerations are present"
echo "all tolerations are present"
- name: Generate support bundle on failure
if: failure()
uses: ./.github/actions/generate-support-bundle
with:
kots-namespace: "$APP_SLUG"
artifact-name: ${{ github.job }}-${{ matrix.cluster.distribution }}-${{ matrix.cluster.version }}-support-bundle
- name: Remove Cluster
id: remove-cluster
uses: replicatedhq/replicated-actions/remove-cluster@v1
if: ${{ always() && steps.create-cluster.outputs.cluster-id != '' }}
continue-on-error: true
with:
api-token: ${{ secrets.C11Y_MATRIX_TOKEN }}
cluster-id: ${{ steps.create-cluster.outputs.cluster-id }}
validate-backup-and-restore:
runs-on: ubuntu-20.04
needs: [ enable-tests, can-run-ci, cmx-versions, build-kots, build-kotsadm, build-e2e, build-kurl-proxy, build-migrations, push-minio, push-rqlite ]
strategy:
fail-fast: false
matrix:
cluster: ${{ fromJson(needs.cmx-versions.outputs.versions-to-test) }}
continue-on-error: ${{ matrix.cluster.stage != 'stable' }}
steps:
- name: Checkout
uses: actions/checkout@v4
- name: download e2e deps
uses: actions/download-artifact@v4
with:
name: e2e
path: e2e/bin/
- run: docker load -i e2e/bin/e2e-deps.tar
- run: chmod +x e2e/bin/*
- name: download kots binary
uses: actions/download-artifact@v4
with:
name: kots
path: bin/
- run: chmod +x bin/*
- uses: ./.github/actions/kots-e2e
with:
test-id: '@backup-and-restore'
kots-namespace: 'backup-and-restore'
k8s-distribution: ${{ matrix.cluster.distribution }}
k8s-version: ${{ matrix.cluster.version }}
k8s-instance-type: ${{ matrix.cluster.instance_type }}
replicated-api-token: '${{ secrets.C11Y_MATRIX_TOKEN }}'
kots-dockerhub-username: '${{ secrets.E2E_DOCKERHUB_USERNAME }}'
kots-dockerhub-password: '${{ secrets.E2E_DOCKERHUB_PASSWORD }}'
validate-no-required-config:
runs-on: ubuntu-20.04
needs: [ enable-tests, can-run-ci, build-kots, build-kotsadm, build-e2e, build-kurl-proxy, build-migrations, push-minio, push-rqlite ]
strategy:
fail-fast: false
matrix:
cluster: [
{distribution: kind, version: v1.28.0}
]
steps:
- name: Checkout
uses: actions/checkout@v4
- name: download e2e deps
uses: actions/download-artifact@v4
with:
name: e2e
path: e2e/bin/
- run: docker load -i e2e/bin/e2e-deps.tar
- run: chmod +x e2e/bin/*
- name: download kots binary
uses: actions/download-artifact@v4
with:
name: kots
path: bin/
- run: chmod +x bin/*
- uses: ./.github/actions/kots-e2e
with:
test-id: '@no-required-config'
kots-namespace: 'no-required-config'
k8s-distribution: ${{ matrix.cluster.distribution }}
k8s-version: ${{ matrix.cluster.version }}
replicated-api-token: '${{ secrets.C11Y_MATRIX_TOKEN }}'
kots-dockerhub-username: '${{ secrets.E2E_DOCKERHUB_USERNAME }}'
kots-dockerhub-password: '${{ secrets.E2E_DOCKERHUB_PASSWORD }}'
validate-strict-preflight-checks:
runs-on: ubuntu-20.04
needs: [ enable-tests, can-run-ci, build-kots, build-kotsadm, build-e2e, build-kurl-proxy, build-migrations, push-minio, push-rqlite ]
strategy:
fail-fast: false
matrix:
cluster: [
{distribution: kind, version: v1.28.0}
]
env:
APP_SLUG: strict-preflight-checks
steps:
- name: Checkout
uses: actions/checkout@v4
- name: Create Cluster
id: create-cluster
uses: replicatedhq/replicated-actions/create-cluster@v1
with:
api-token: ${{ secrets.C11Y_MATRIX_TOKEN }}
kubernetes-distribution: ${{ matrix.cluster.distribution }}
kubernetes-version: ${{ matrix.cluster.version }}
cluster-name: automated-kots-${{ github.run_id }}-${{ matrix.cluster.distribution }}-${{ matrix.cluster.version }}
timeout-minutes: '120'
ttl: 2h
export-kubeconfig: true
- name: download kots binary
uses: actions/download-artifact@v4
with:
name: kots
path: bin/
- run: chmod +x bin/kots
- name: create namespace and dockerhub secret
run: |
kubectl create ns "$APP_SLUG"
kubectl create secret docker-registry kotsadm-dockerhub --docker-server index.docker.io --docker-username "${{ secrets.E2E_DOCKERHUB_USERNAME }}" --docker-password "${{ secrets.E2E_DOCKERHUB_PASSWORD }}" --namespace "$APP_SLUG"
- name: run the test
run: |
set +e
echo ${{ secrets.STRICT_PREFLIGHT_CHECKS_LICENSE }} | base64 -d > license.yaml
./bin/kots \
install "$APP_SLUG/automated" \
--license-file license.yaml \
--no-port-forward \
--namespace "$APP_SLUG" \
--shared-password password \
--kotsadm-registry ttl.sh \
--kotsadm-namespace automated-${{ github.run_id }} \
--skip-preflights \
--kotsadm-tag 24h | tee output.txt
if ! grep -q 'The app was not deployed.' output.txt; then
printf "Expected to see message about app not being deployed, but did not\n"
exit 1
fi
if ! grep FAIL output.txt | grep -q 'The application requires a Kubernetes 2.0.0 or later.'; then
printf "Expected to see a failure about kubernetes version, but did not\n"
exit 1
fi
if ! kubectl logs deploy/kotsadm -n "$APP_SLUG" | grep -q "preflights will not be skipped, strict preflights are set to true"; then
echo "Failed to find a log line about strict preflights not being skipped in kotsadm logs"
echo "kotsadm logs:"
kubectl logs deploy/kotsadm -n "$APP_SLUG"
exit 1
fi
# disable the strict preflight check and app should deploy successfully
./bin/kots set config "$APP_SLUG" enable_failing_strict_analyzers="0" --namespace "$APP_SLUG" --deploy
COUNTER=1
while [ "$(./bin/kots get apps --namespace "$APP_SLUG" | awk 'NR>1{print $2}')" != "ready" ]; do
((COUNTER += 1))
if [ $COUNTER -gt 120 ]; then
echo "Timed out waiting for app to be ready"
./bin/kots get apps --namespace "$APP_SLUG"
echo "kotsadm logs:"
kubectl logs deploy/kotsadm --tail=100 -n "$APP_SLUG"
exit 1
fi
sleep 1
done
printf "App is installed successfully and is ready\n\n"
./bin/kots get apps --namespace "$APP_SLUG"
# enable the failing non-strict preflight check
./bin/kots set config "$APP_SLUG" enable_failing_non_strict_analyzers="1" --namespace "$APP_SLUG"
# download the config
./bin/kots get config --namespace "$APP_SLUG" > config.yaml
# remove the app
./bin/kots remove "$APP_SLUG" --namespace "$APP_SLUG" --undeploy
# install the app and skip preflights
./bin/kots \
install "$APP_SLUG/automated" \
--license-file license.yaml \
--config-values config.yaml \
--no-port-forward \
--namespace "$APP_SLUG" \
--shared-password password \
--kotsadm-registry ttl.sh \
--kotsadm-namespace automated-${{ github.run_id }} \
--skip-preflights \
--kotsadm-tag 24h
if ! kubectl logs deploy/kotsadm -n "$APP_SLUG" | grep -q "preflights will not be skipped, strict preflights are set to true"; then
echo "Failed to find a log line about strict preflights not being skipped in kotsadm logs"
echo "kotsadm logs:"
kubectl logs deploy/kotsadm -n "$APP_SLUG"
exit 1
fi
COUNTER=1
while [ "$(./bin/kots get apps --namespace "$APP_SLUG" | awk 'NR>1{print $2}')" != "ready" ]; do
((COUNTER += 1))
if [ $COUNTER -gt 120 ]; then
echo "Timed out waiting for app to be ready"
./bin/kots get apps --namespace "$APP_SLUG"
echo "kotsadm logs:"
kubectl logs deploy/kotsadm --tail=100 -n "$APP_SLUG"
exit 1
fi
sleep 1
done
printf "App is installed successfully and is ready\n\n"
./bin/kots get apps --namespace "$APP_SLUG"
- name: Generate support bundle on failure
if: failure()
uses: ./.github/actions/generate-support-bundle
with:
kots-namespace: "$APP_SLUG"
artifact-name: ${{ github.job }}-${{ matrix.cluster.distribution }}-${{ matrix.cluster.version }}-support-bundle
- name: Remove Cluster
id: remove-cluster
uses: replicatedhq/replicated-actions/remove-cluster@v1
if: ${{ always() && steps.create-cluster.outputs.cluster-id != '' }}
continue-on-error: true
with:
api-token: ${{ secrets.C11Y_MATRIX_TOKEN }}
cluster-id: ${{ steps.create-cluster.outputs.cluster-id }}
validate-config:
runs-on: ubuntu-20.04
needs: [ enable-tests, can-run-ci, build-kots, build-kotsadm, build-e2e, build-kurl-proxy, build-migrations, push-minio, push-rqlite ]
strategy:
fail-fast: false
matrix:
cluster: [
{distribution: kind, version: v1.28.0}
]
steps:
- name: Checkout
uses: actions/checkout@v4
- name: download e2e deps
uses: actions/download-artifact@v4
with:
name: e2e
path: e2e/bin/
- run: docker load -i e2e/bin/e2e-deps.tar
- run: chmod +x e2e/bin/*
- name: download kots binary
uses: actions/download-artifact@v4
with:
name: kots
path: bin/
- run: chmod +x bin/*
- uses: ./.github/actions/kots-e2e
with:
test-id: '@config-validation'
kots-namespace: 'config-validation'
k8s-distribution: ${{ matrix.cluster.distribution }}
k8s-version: ${{ matrix.cluster.version }}
replicated-api-token: '${{ secrets.C11Y_MATRIX_TOKEN }}'
kots-dockerhub-username: '${{ secrets.E2E_DOCKERHUB_USERNAME }}'
kots-dockerhub-password: '${{ secrets.E2E_DOCKERHUB_PASSWORD }}'
validate-version-history-pagination:
runs-on: ubuntu-20.04
needs: [ enable-tests, can-run-ci, build-kots, build-kotsadm, build-e2e, build-kurl-proxy, build-migrations, push-minio, push-rqlite ]
strategy:
fail-fast: false
matrix:
cluster: [
{distribution: k3s-local, version: v1.27.1-k3s1}
]
steps:
- name: Checkout
uses: actions/checkout@v4
- name: download e2e deps
uses: actions/download-artifact@v4
with:
name: e2e
path: e2e/bin/
- run: docker load -i e2e/bin/e2e-deps.tar
- run: chmod +x e2e/bin/*
- name: download kots binary
uses: actions/download-artifact@v4
with:
name: kots
path: bin/
- run: chmod +x bin/*
- uses: ./.github/actions/kots-e2e
with:
test-id: '@version-history-pagination'
kots-namespace: 'version-history-pagination'
k8s-distribution: ${{ matrix.cluster.distribution }}
k8s-version: ${{ matrix.cluster.version }}
testim-access-token: '${{ secrets.TESTIM_ACCESS_TOKEN }}'
testim-branch: ${{ github.head_ref == 'main' && 'master' || github.head_ref }}
kots-dockerhub-username: '${{ secrets.E2E_DOCKERHUB_USERNAME }}'
kots-dockerhub-password: '${{ secrets.E2E_DOCKERHUB_PASSWORD }}'
validate-change-license:
runs-on: ubuntu-20.04
needs: [ enable-tests, can-run-ci, build-kots, build-kotsadm, build-e2e, build-kurl-proxy, build-migrations, push-minio, push-rqlite ]
strategy:
fail-fast: false
matrix:
cluster: [
{distribution: kind, version: v1.28.0}
]
steps:
- name: Checkout
uses: actions/checkout@v4
- name: download e2e deps
uses: actions/download-artifact@v4
with:
name: e2e
path: e2e/bin/
- run: docker load -i e2e/bin/e2e-deps.tar
- run: chmod +x e2e/bin/*
- name: download kots binary
uses: actions/download-artifact@v4
with:
name: kots
path: bin/
- run: chmod +x bin/*
- uses: ./.github/actions/kots-e2e
with:
test-id: '@change-license'
kots-namespace: 'change-license'
k8s-distribution: ${{ matrix.cluster.distribution }}
k8s-version: ${{ matrix.cluster.version }}
replicated-api-token: '${{ secrets.C11Y_MATRIX_TOKEN }}'
kots-dockerhub-username: '${{ secrets.E2E_DOCKERHUB_USERNAME }}'
kots-dockerhub-password: '${{ secrets.E2E_DOCKERHUB_PASSWORD }}'
validate-change-channel:
runs-on: ubuntu-20.04
needs: [ enable-tests, can-run-ci, build-kots, build-kotsadm, build-e2e, build-kurl-proxy, build-migrations, push-minio, push-rqlite ]
strategy:
fail-fast: false
matrix:
cluster: [
{distribution: kind, version: v1.28.0}
]
steps:
- name: Checkout
uses: actions/checkout@v4
- name: download e2e deps
uses: actions/download-artifact@v4
with:
name: e2e
path: e2e/bin/
- run: docker load -i e2e/bin/e2e-deps.tar
- run: chmod +x e2e/bin/*
- name: download kots binary
uses: actions/download-artifact@v4
with:
name: kots
path: bin/
- run: chmod +x bin/*
- uses: ./.github/actions/kots-e2e
with:
test-id: '@change-channel'
kots-namespace: 'change-channel'
k8s-distribution: ${{ matrix.cluster.distribution }}
k8s-version: ${{ matrix.cluster.version }}
replicated-api-token: '${{ secrets.C11Y_MATRIX_TOKEN }}'
kots-dockerhub-username: '${{ secrets.E2E_DOCKERHUB_USERNAME }}'
kots-dockerhub-password: '${{ secrets.E2E_DOCKERHUB_PASSWORD }}'
validate-minimal-rbac-override:
runs-on: ubuntu-20.04
needs: [ enable-tests, can-run-ci, cmx-versions, build-kots, build-kotsadm, build-e2e, build-kurl-proxy, build-migrations, push-minio, push-rqlite ]
strategy:
fail-fast: false
matrix:
cluster: [
{distribution: kind, version: v1.28.0},
{distribution: openshift, version: 4.15.0-okd}
]
env:
APP_SLUG: minimal-rbac
APP_VERSION_LABEL: "0.0.1"
steps:
- name: Checkout
uses: actions/checkout@v4
- name: Create Cluster
id: create-cluster
uses: replicatedhq/replicated-actions/create-cluster@v1
with:
api-token: ${{ secrets.C11Y_MATRIX_TOKEN }}
kubernetes-distribution: ${{ matrix.cluster.distribution }}
kubernetes-version: ${{ matrix.cluster.version }}
cluster-name: automated-kots-${{ github.run_id }}-${{ matrix.cluster.distribution }}-${{ matrix.cluster.version }}
timeout-minutes: '120'
ttl: 2h
export-kubeconfig: true
- name: download kots binary
uses: actions/download-artifact@v4
with:
name: kots
path: bin/
- run: chmod +x bin/kots
- name: create namespace and dockerhub secret
run: |
kubectl create ns "$APP_SLUG"
kubectl create secret docker-registry kotsadm-dockerhub --docker-server index.docker.io --docker-username "${{ secrets.E2E_DOCKERHUB_USERNAME }}" --docker-password "${{ secrets.E2E_DOCKERHUB_PASSWORD }}" --namespace "$APP_SLUG"
- name: minimal rbac override on command line
run: |
set +e
echo ${{ secrets.MINIMAL_RBAC_LICENSE }} | base64 -d > license.yaml
./bin/kots \
install "$APP_SLUG/automated" \
--license-file license.yaml \
--app-version-label "$APP_VERSION_LABEL" \
--no-port-forward \
--namespace "$APP_SLUG" \
--shared-password password \
--kotsadm-registry ttl.sh \
--kotsadm-namespace automated-${{ github.run_id }} \
--kotsadm-tag 24h \
--use-minimal-rbac | tee output.txt
if ! grep -q "The Kubernetes RBAC policy that the Admin Console is running with does not have access to complete the Preflight Checks. It's recommended that you run these manually before proceeding." output.txt; then
echo "Expected to see an RBAC error for preflight checks, but did not"
exit 1
fi
if ! grep -q 'The app was not deployed.' output.txt; then
printf "Expected to see message about app not being deployed, but did not\n"
exit 1
fi
if grep FAIL output.txt | grep -q 'This application requires at least 100 nodes'; then
printf "Did not expect to see a failure about number of nodes, but did\n"
exit 1
fi
if ! kubectl get role -n "$APP_SLUG" | grep -q kotsadm; then
echo "kotsadm role not found in namespace $APP_SLUG"
kubectl get role -n "$APP_SLUG"
exit 1
fi
if ! kubectl get rolebinding -n "$APP_SLUG" | grep -q kotsadm; then
echo "kotsadm rolebinding not found in namespace $APP_SLUG"
kubectl get rolebinding -n "$APP_SLUG"
exit 1
fi
if kubectl get clusterrole | grep -q kotsadm; then
echo "found kotsadm clusterrole in minimal RBAC install"
kubectl get clusterrole
exit 1
fi
if kubectl get clusterrolebinding | grep -q kotsadm; then
echo "found kotsadm clusterrolebinding in minimal RBAC install"
kubectl get clusterrolebinding
exit 1
fi
- name: create namespace and dockerhub secret
run: |
kubectl delete ns "$APP_SLUG" --ignore-not-found
kubectl create ns "$APP_SLUG"
kubectl create secret docker-registry kotsadm-dockerhub --docker-server index.docker.io --docker-username "${{ secrets.E2E_DOCKERHUB_USERNAME }}" --docker-password "${{ secrets.E2E_DOCKERHUB_PASSWORD }}" --namespace "$APP_SLUG"
- name: no minimal rbac override on command line
run: |
set +e
echo ${{ secrets.MINIMAL_RBAC_LICENSE }} | base64 -d > license.yaml
./bin/kots \
install "$APP_SLUG/automated" \
--license-file license.yaml \
--app-version-label "$APP_VERSION_LABEL" \
--no-port-forward \
--namespace "$APP_SLUG" \
--shared-password password \
--kotsadm-registry ttl.sh \
--kotsadm-namespace automated-${{ github.run_id }} \
--kotsadm-tag 24h | tee output.txt
if grep -q "The Kubernetes RBAC policy that the Admin Console is running with does not have access to complete the Preflight Checks. It's recommended that you run these manually before proceeding." output.txt; then
echo "Did not expect to see an RBAC error for preflight checks, but did"
exit 1
fi
if ! grep -q 'The app was not deployed.' output.txt; then
printf "Expected to see message about app not being deployed, but did not\n"
exit 1
fi
if ! grep FAIL output.txt | grep -q 'This application requires at least 100 nodes'; then
printf "Expected to see a failure about number of nodes, but did not\n"
exit 1
fi
if kubectl get role -n "$APP_SLUG" | grep -q kotsadm; then
echo "kotsadm role found in cluster scoped install"
kubectl get role -n "$APP_SLUG"
exit 1
fi
if kubectl get rolebinding -n "$APP_SLUG" | grep -q kotsadm; then
echo "kotsadm rolebinding found in cluster scoped install"
kubectl get rolebinding -n "$APP_SLUG"
exit 1
fi
if ! kubectl get clusterrole | grep -q kotsadm; then
echo "No kotsadm clusterrole found in cluster scoped install"
kubectl get clusterrole
exit 1
fi
if ! kubectl get clusterrolebinding | grep -q kotsadm; then
echo "No kotsadm clusterrolebinding found in cluster scoped install"
kubectl get clusterrolebinding
exit 1
fi
- name: Generate support bundle on failure
if: failure()
uses: ./.github/actions/generate-support-bundle
with:
kots-namespace: "$APP_SLUG"
artifact-name: ${{ github.job }}-${{ matrix.cluster.distribution }}-${{ matrix.cluster.version }}-support-bundle
- name: Remove Cluster
id: remove-cluster
uses: replicatedhq/replicated-actions/remove-cluster@v1
if: ${{ always() && steps.create-cluster.outputs.cluster-id != '' }}
continue-on-error: true
with:
api-token: ${{ secrets.C11Y_MATRIX_TOKEN }}
cluster-id: ${{ steps.create-cluster.outputs.cluster-id }}
validate-multi-namespace:
runs-on: ubuntu-20.04
needs: [ enable-tests, can-run-ci, cmx-versions, build-kots, build-kotsadm, build-e2e, build-kurl-proxy, build-migrations, push-minio, push-rqlite ]
strategy:
fail-fast: false
matrix:
cluster: ${{ fromJson(needs.cmx-versions.outputs.versions-to-test) }}
continue-on-error: ${{ matrix.cluster.stage != 'stable' }}
env:
APP_SLUG: multi-namespace-yeti
steps:
- name: Checkout
uses: actions/checkout@v4
- uses: azure/setup-helm@v4
with:
token: ${{ secrets.GITHUB_TOKEN }}
- name: Create Cluster
id: create-cluster
uses: replicatedhq/replicated-actions/create-cluster@v1
with:
api-token: ${{ secrets.C11Y_MATRIX_TOKEN }}
kubernetes-distribution: ${{ matrix.cluster.distribution }}
kubernetes-version: ${{ matrix.cluster.version }}
cluster-name: automated-kots-${{ github.run_id }}-${{ matrix.cluster.distribution }}-${{ matrix.cluster.version }}
timeout-minutes: '120'
ttl: 2h
instance-type: ${{ matrix.cluster.instance_type }}
export-kubeconfig: true
- name: download kots binary
uses: actions/download-artifact@v4
with:
name: kots
path: bin/
- run: chmod +x bin/kots
- name: create namespace and dockerhub secret
run: |
kubectl create ns "$APP_SLUG"
kubectl create secret docker-registry kotsadm-dockerhub --docker-server index.docker.io --docker-username "${{ secrets.E2E_DOCKERHUB_USERNAME }}" --docker-password "${{ secrets.E2E_DOCKERHUB_PASSWORD }}" --namespace "$APP_SLUG"
- name: run the test
run: |
set +e
echo ${{ secrets.MULTI_NAMESPACE_LICENSE }} | base64 -d > license.yaml
./bin/kots \
install "$APP_SLUG/automated" \
--license-file license.yaml \
--no-port-forward \
--namespace "$APP_SLUG" \
--shared-password password \
--kotsadm-registry ttl.sh \
--kotsadm-namespace automated-${{ github.run_id }} \
--kotsadm-tag 24h \
--storage-class=${{ matrix.cluster.distribution == 'eks' && 'gp2' || '' }}
EXIT_CODE=$?
if [ $EXIT_CODE -ne 0 ]; then
echo "------pods:"
kubectl -n "$APP_SLUG" get pods
echo "------kotsadm logs"
kubectl logs -l app=kotsadm --tail=100 --namespace "$APP_SLUG"
exit $EXIT_CODE
fi
COUNTER=1
while [ "$(./bin/kots get apps --namespace "$APP_SLUG" | awk 'NR>1{print $2}')" != "ready" ]; do
((COUNTER += 1))
if [ $COUNTER -gt 180 ]; then
echo "Timed out waiting for app to be ready"
./bin/kots get apps --namespace "$APP_SLUG"
echo "kotsadm logs:"
kubectl logs -l app=kotsadm --tail=100 --namespace "$APP_SLUG"
exit 1
fi
sleep 1
done
# validate that helm charts installed using the native helm workflow were deployed via the helm CLI correctly
if ! helm ls -n postgres-test | awk 'NR>1{print $1}' | grep -q postgresql; then
printf "postgresql helm release not found in postgres-test namespace\n\n"
helm ls -n postgres-test
exit 1
fi
if ! helm ls -n "$APP_SLUG" | awk 'NR>1{print $1}' | grep -q private-chart; then
printf "private-chart helm release not found in %s namespace\n\n" "$APP_SLUG"
helm ls -n "$APP_SLUG"
exit 1
fi
- name: Generate support bundle on failure
if: failure()
uses: ./.github/actions/generate-support-bundle
with:
kots-namespace: "$APP_SLUG"
artifact-name: ${{ github.job }}-${{ matrix.cluster.distribution }}-${{ matrix.cluster.version }}-support-bundle
- name: Remove Cluster
id: remove-cluster
uses: replicatedhq/replicated-actions/remove-cluster@v1
if: ${{ always() && steps.create-cluster.outputs.cluster-id != '' }}
continue-on-error: true
with:
api-token: ${{ secrets.C11Y_MATRIX_TOKEN }}
cluster-id: ${{ steps.create-cluster.outputs.cluster-id }}
validate-kots-pull:
runs-on: ubuntu-20.04
needs: [ enable-tests, can-run-ci, cmx-versions, build-kots, build-kotsadm, build-e2e, build-kurl-proxy, build-migrations, push-minio, push-rqlite ]
strategy:
fail-fast: false
matrix:
cluster: ${{ fromJson(needs.cmx-versions.outputs.versions-to-test) }}
continue-on-error: ${{ matrix.cluster.stage != 'stable' }}
env:
APP_NAME: multi-namespace-yeti
APP_SLUG: multi-namespace
steps:
- name: Checkout
uses: actions/checkout@v4
- name: Create Cluster
id: create-cluster
uses: replicatedhq/replicated-actions/create-cluster@v1
with:
api-token: ${{ secrets.C11Y_MATRIX_TOKEN }}
kubernetes-distribution: ${{ matrix.cluster.distribution }}
kubernetes-version: ${{ matrix.cluster.version }}
cluster-name: automated-kots-${{ github.run_id }}-${{ matrix.cluster.distribution }}-${{ matrix.cluster.version }}
timeout-minutes: '120'
ttl: 2h
instance-type: ${{ matrix.cluster.instance_type }}
export-kubeconfig: true
- name: download kots binary
uses: actions/download-artifact@v4
with:
name: kots
path: bin/
- run: chmod +x bin/kots
- name: create namespace and dockerhub secret
run: |
kubectl create ns "$APP_NAME"
kubectl create secret docker-registry kotsadm-dockerhub --docker-server index.docker.io --docker-username "${{ secrets.E2E_DOCKERHUB_USERNAME }}" --docker-password "${{ secrets.E2E_DOCKERHUB_PASSWORD }}" --namespace "$APP_NAME"
- name: run kots pull
run: |
set +e
echo ${{ secrets.MULTI_NAMESPACE_LICENSE }} | base64 -d > license.yaml
./bin/kots pull "$APP_NAME/automated" \
--license-file license.yaml \
--shared-password password \
--namespace "$APP_NAME" \
--exclude-admin-console
kubectl create ns "$APP_NAME"
kubectl create ns nginx-test
kubectl create ns redis-test
kubectl create ns postgres-test
# HACK: without operator, additonal namespaces don't get image pull secrets
echo ${{ secrets.MULTI_NAMESPACE_REGISTRY_AUTH }} | base64 -d > replicated-registry-auth.json
kubectl -n nginx-test create secret generic multi-namespace-yeti-registry --type=kubernetes.io/dockerconfigjson --from-file=.dockerconfigjson=./replicated-registry-auth.json
kubectl -n redis-test create secret generic multi-namespace-yeti-registry --type=kubernetes.io/dockerconfigjson --from-file=.dockerconfigjson=./replicated-registry-auth.json
kubectl -n redis-test create secret generic multi-namespace-yeti-redis-registry --type=kubernetes.io/dockerconfigjson --from-file=.dockerconfigjson=./replicated-registry-auth.json
kubectl -n postgres-test create secret generic multi-namespace-yeti-registry --type=kubernetes.io/dockerconfigjson --from-file=.dockerconfigjson=./replicated-registry-auth.json
kubectl -n default create secret generic multi-namespace-yeti-registry --type=kubernetes.io/dockerconfigjson --from-file=.dockerconfigjson=./replicated-registry-auth.json
kustomize build "$PWD/$APP_SLUG/overlays/midstream" | kubectl apply -f -
kustomize build "$PWD/$APP_SLUG/overlays/midstream/charts/redis" | kubectl apply -f -
EXIT_CODE=$?
if [ $EXIT_CODE -ne 0 ]; then
echo "Failed to apply spec"
echo "------pods:"
kubectl get pods -A
echo "------kotsadm logs"
kubectl logs -l app=kotsadm --tail=100 --namespace "$APP_SLUG"
exit $EXIT_CODE
fi
echo "Waiting for pods to start"
COUNTER=1
while [ "$(kubectl get pods --no-headers | grep -v Running | grep -cv Completed)" -gt 0 ]; do
((COUNTER += 1))
if [ $COUNTER -gt 120 ]; then
echo "Timed out waiting for pods to start"
kubectl get pods -A
exit 1
fi
sleep 1
done
echo "All pods started"
- name: Generate support bundle on failure
if: failure()
uses: ./.github/actions/generate-support-bundle
with:
kots-namespace: "$APP_NAME"
artifact-name: ${{ github.job }}-${{ matrix.cluster.distribution }}-${{ matrix.cluster.version }}-support-bundle
- name: Remove Cluster
id: remove-cluster
uses: replicatedhq/replicated-actions/remove-cluster@v1
if: ${{ always() && steps.create-cluster.outputs.cluster-id != '' }}
continue-on-error: true
with:
api-token: ${{ secrets.C11Y_MATRIX_TOKEN }}
cluster-id: ${{ steps.create-cluster.outputs.cluster-id }}
validate-app-version-label:
runs-on: ubuntu-20.04
needs: [ enable-tests, can-run-ci, build-kots, build-kotsadm, build-kurl-proxy, build-migrations, push-minio, push-rqlite ]
strategy:
fail-fast: false
matrix:
cluster: [
{distribution: kind, version: v1.28.0}
]
env:
APP_SLUG: app-version-label
APP_VERSION_LABEL: v1.0.0
LATEST_APP_VERSION_LABEL: v1.0.1
steps:
- name: Checkout
uses: actions/checkout@v4
- name: Create Cluster
id: create-cluster
uses: replicatedhq/replicated-actions/create-cluster@v1
with:
api-token: ${{ secrets.C11Y_MATRIX_TOKEN }}
kubernetes-distribution: ${{ matrix.cluster.distribution }}
kubernetes-version: ${{ matrix.cluster.version }}
cluster-name: automated-kots-${{ github.run_id }}-${{ matrix.cluster.distribution }}-${{ matrix.cluster.version }}
timeout-minutes: '120'
ttl: 2h
export-kubeconfig: true
- name: download kots binary
uses: actions/download-artifact@v4
with:
name: kots
path: bin/
- run: chmod +x bin/kots
- name: create namespace and dockerhub secret
run: |
kubectl create ns "$APP_SLUG"
kubectl create secret docker-registry kotsadm-dockerhub --docker-server index.docker.io --docker-username "${{ secrets.E2E_DOCKERHUB_USERNAME }}" --docker-password "${{ secrets.E2E_DOCKERHUB_PASSWORD }}" --namespace "$APP_SLUG"
- name: test kots install with version label
run: |
set +e
echo ${{ secrets.APP_VERSION_LABEL_LICENSE }} | base64 -d > license.yaml
./bin/kots \
install "$APP_SLUG/automated" \
--license-file license.yaml \
--app-version-label "$APP_VERSION_LABEL" \
--no-port-forward \
--namespace "$APP_SLUG" \
--shared-password password \
--kotsadm-registry ttl.sh \
--kotsadm-namespace automated-${{ github.run_id }} \
--kotsadm-tag 24h
EXIT_CODE=$?
if [ $EXIT_CODE -ne 0 ]; then
echo "------pods:"
kubectl -n "$APP_SLUG" get pods
echo "------kotsadm logs"
kubectl logs -l app=kotsadm --tail=100 --namespace "$APP_SLUG"
exit $EXIT_CODE
fi
COUNTER=1
while [ "$(./bin/kots get apps --namespace "$APP_SLUG" | awk 'NR>1{print $3}')" != "$APP_VERSION_LABEL" ]; do
((COUNTER += 1))
if [ $COUNTER -gt 120 ]; then
echo "Timed out waiting for app to be installed with correct version label: $APP_VERSION_LABEL"
./bin/kots get apps --namespace "$APP_SLUG"
echo "kotsadm logs:"
kubectl logs -l app=kotsadm --tail=100 --namespace "$APP_SLUG"
exit 1
fi
sleep 1
done
printf "App is installed successfully with the correct version label: %s\n\n" "$APP_VERSION_LABEL"
./bin/kots get apps --namespace "$APP_SLUG"
# test setting DockerHub credentials
set +e
# TODO: deploy and check secrets are actually created and images are pulled
./bin/kots docker ensure-secret --dockerhub-username replicatedtests --dockerhub-password ${{ secrets.DOCKERHUB_RATELIMIT_PASSWORD }} -n "$APP_SLUG"
./bin/kots download -n "$APP_SLUG" --slug "$APP_SLUG"
if grep "${APP_SLUG}-kotsadm-dockerhub" -w "./${APP_SLUG}/overlays/midstream/secret.yaml"; then
echo "Found DockerHub secret in ${APP_SLUG} latest version"
else
echo "No DockerHub secret found in appication namespace"
exit 1
fi
- name: remove the app
run: |
set +e
./bin/kots remove "$APP_SLUG" --namespace "$APP_SLUG" --force
- name: test kots install without version label
run: |
set +e
echo ${{ secrets.APP_VERSION_LABEL_LICENSE }} | base64 -d > license.yaml
./bin/kots \
install "$APP_SLUG/automated" \
--license-file license.yaml \
--no-port-forward \
--namespace "$APP_SLUG" \
--shared-password password \
--kotsadm-registry ttl.sh \
--kotsadm-namespace automated-${{ github.run_id }} \
--kotsadm-tag 24h
EXIT_CODE=$?
if [ $EXIT_CODE -ne 0 ]; then
echo "------pods:"
kubectl -n "$APP_SLUG" get pods
echo "------kotsadm logs"
kubectl logs -l app=kotsadm --tail=100 --namespace "$APP_SLUG"
exit $EXIT_CODE
fi
COUNTER=1
while [ "$(./bin/kots get apps --namespace "$APP_SLUG" | awk 'NR>1{print $3}')" != "$LATEST_APP_VERSION_LABEL" ]; do
((COUNTER += 1))
if [ $COUNTER -gt 120 ]; then
echo "Timed out waiting for app to be installed with latest version label: $LATEST_APP_VERSION_LABEL"
./bin/kots get apps --namespace "$APP_SLUG"
echo "kotsadm logs:"
kubectl logs -l app=kotsadm --tail=100 --namespace "$APP_SLUG"
exit 1
fi
sleep 1
done
printf "App is installed successfully with the correct version label: %s\n\n" "$LATEST_APP_VERSION_LABEL"
./bin/kots get apps --namespace "$APP_SLUG"
- name: Generate support bundle on failure
if: failure()
uses: ./.github/actions/generate-support-bundle
with:
kots-namespace: "$APP_SLUG"
artifact-name: ${{ github.job }}-${{ matrix.cluster.distribution }}-${{ matrix.cluster.version }}-support-bundle
- name: Remove Cluster
id: remove-cluster
uses: replicatedhq/replicated-actions/remove-cluster@v1
if: ${{ always() && steps.create-cluster.outputs.cluster-id != '' }}
continue-on-error: true
with:
api-token: ${{ secrets.C11Y_MATRIX_TOKEN }}
cluster-id: ${{ steps.create-cluster.outputs.cluster-id }}
validate-helm-install-order:
runs-on: ubuntu-20.04
needs: [ enable-tests, can-run-ci, cmx-versions, build-kots, build-kotsadm, build-e2e, build-kurl-proxy, build-migrations, push-minio, push-rqlite ]
strategy:
fail-fast: false
matrix:
cluster: [
{distribution: kind, version: v1.28.0}
]
env:
APP_SLUG: helm-install-order
steps:
- name: Checkout
uses: actions/checkout@v4
- name: Create Cluster
id: create-cluster
uses: replicatedhq/replicated-actions/create-cluster@v1
with:
api-token: ${{ secrets.C11Y_MATRIX_TOKEN }}
kubernetes-distribution: ${{ matrix.cluster.distribution }}
kubernetes-version: ${{ matrix.cluster.version }}
cluster-name: automated-kots-${{ github.run_id }}-${{ matrix.cluster.distribution }}-${{ matrix.cluster.version }}
timeout-minutes: '120'
ttl: 2h
export-kubeconfig: true
- name: download kots binary
uses: actions/download-artifact@v4
with:
name: kots
path: bin/
- run: chmod +x bin/kots
- name: create namespace and dockerhub secret
run: |
kubectl create ns "$APP_SLUG"
kubectl create secret docker-registry kotsadm-dockerhub --docker-server index.docker.io --docker-username "${{ secrets.E2E_DOCKERHUB_USERNAME }}" --docker-password "${{ secrets.E2E_DOCKERHUB_PASSWORD }}" --namespace "$APP_SLUG"
- name: run the test
run: |
set +e
echo ${{ secrets.HELM_INSTALL_ORDER_LICENSE }} | base64 -d > license.yaml
./bin/kots \
install "$APP_SLUG/automated" \
--license-file license.yaml \
--no-port-forward \
--namespace "$APP_SLUG" \
--shared-password password \
--kotsadm-registry ttl.sh \
--kotsadm-namespace automated-${{ github.run_id }} \
--skip-preflights \
--kotsadm-tag 24h
EXIT_CODE=$?
if [ $EXIT_CODE -ne 0 ]; then
echo "------pods:"
kubectl -n "$APP_SLUG" get pods
echo "------kotsadm logs"
kubectl logs -l app=kotsadm --tail=100 --namespace "$APP_SLUG"
exit $EXIT_CODE
fi
COUNTER=1
while [ "$(./bin/kots get apps --namespace "$APP_SLUG" | awk 'NR>1{print $2}')" != "ready" ]; do
((COUNTER += 1))
if [ $COUNTER -gt 120 ]; then
echo "Timed out waiting for app to be ready"
./bin/kots get apps --namespace "$APP_SLUG"
echo "kotsadm logs:"
kubectl logs -l app=kotsadm --tail=100 --namespace "$APP_SLUG"
exit 1
fi
sleep 1
done
printf "App is installed successfully and is ready\n\n"
./bin/kots get apps --namespace "$APP_SLUG"
- name: Generate support bundle on failure
if: failure()
uses: ./.github/actions/generate-support-bundle
with:
kots-namespace: "$APP_SLUG"
artifact-name: ${{ github.job }}-${{ matrix.cluster.distribution }}-${{ matrix.cluster.version }}-support-bundle
- name: Remove Cluster
id: remove-cluster
uses: replicatedhq/replicated-actions/remove-cluster@v1
if: ${{ always() && steps.create-cluster.outputs.cluster-id != '' }}
continue-on-error: true
with:
api-token: ${{ secrets.C11Y_MATRIX_TOKEN }}
cluster-id: ${{ steps.create-cluster.outputs.cluster-id }}
validate-no-redeploy-on-restart:
runs-on: ubuntu-20.04
needs: [ enable-tests, can-run-ci, build-kots, build-kotsadm, build-kurl-proxy, build-migrations, push-minio, push-rqlite ]
strategy:
fail-fast: false
matrix:
cluster: [
{distribution: kind, version: v1.28.0}
]
env:
APP_SLUG: no-redeploy-on-restart
steps:
- name: Checkout
uses: actions/checkout@v4
- name: Create Cluster
id: create-cluster
uses: replicatedhq/replicated-actions/create-cluster@v1
with:
api-token: ${{ secrets.C11Y_MATRIX_TOKEN }}
kubernetes-distribution: ${{ matrix.cluster.distribution }}
kubernetes-version: ${{ matrix.cluster.version }}
cluster-name: automated-kots-${{ github.run_id }}-${{ matrix.cluster.distribution }}-${{ matrix.cluster.version }}
timeout-minutes: '120'
ttl: 2h
export-kubeconfig: true
- name: download kots binary
uses: actions/download-artifact@v4
with:
name: kots
path: bin/
- run: chmod +x bin/kots
- name: create namespace and dockerhub secret
run: |
kubectl create ns "$APP_SLUG"
kubectl create secret docker-registry kotsadm-dockerhub --docker-server index.docker.io --docker-username "${{ secrets.E2E_DOCKERHUB_USERNAME }}" --docker-password "${{ secrets.E2E_DOCKERHUB_PASSWORD }}" --namespace "$APP_SLUG"
- name: run the test
run: |
set +e
echo ${{ secrets.NO_REDEPLOY_ON_RESTART_LICENSE }} | base64 -d > license.yaml
./bin/kots \
install "$APP_SLUG/automated" \
--license-file license.yaml \
--no-port-forward \
--namespace "$APP_SLUG" \
--shared-password password \
--kotsadm-registry ttl.sh \
--kotsadm-namespace automated-${{ github.run_id }} \
--skip-preflights \
--kotsadm-tag 24h
EXIT_CODE=$?
if [ $EXIT_CODE -ne 0 ]; then
echo "------pods:"
kubectl -n "$APP_SLUG" get pods
echo "------kotsadm logs"
kubectl logs -l app=kotsadm --tail=100 --namespace "$APP_SLUG"
exit $EXIT_CODE
fi
# wait for application job to be created
COUNTER=1
while [ "$(kubectl get jobs -l app=example,component=job -n "$APP_SLUG" --ignore-not-found | awk 'NR>1' | wc -l)" == "0" ]; do
((COUNTER += 1))
if [ $COUNTER -gt 60 ]; then
echo "Timed out waiting for job to be created"
exit 1
fi
sleep 1
done
# delete the application job and restart the admin console
kubectl delete jobs -n "$APP_SLUG" --all
kubectl delete pods -l app=kotsadm -n "$APP_SLUG"
# wait for old kotsadm pod to terminate
COUNTER=1
while [ "$(kubectl get pods -l app=kotsadm -n "$APP_SLUG" | awk 'NR>1' | wc -l)" != "1" ]; do
((COUNTER += 1))
if [ $COUNTER -gt 60 ]; then
echo "More than 1 kotsadm pod found"
exit 1
fi
sleep 1
done
# wait for new kotsadm pod to become ready
kubectl wait --for=condition=ready pod -l app=kotsadm -n "$APP_SLUG" --timeout=60s
# delay in case the app takes a bit to be deployed
sleep 20
# validate that the application wasn't re-deployed and the job wasn't re-created
if [ "$(kubectl get jobs -l app=example,component=job -n "$APP_SLUG" --ignore-not-found | awk 'NR>1' | wc -l)" != "0" ]; then
echo "App should not be re-deployed after restart"
exit 1
fi
printf "Success. App was not re-deployed after restart\n\n"
- name: Generate support bundle on failure
if: failure()
uses: ./.github/actions/generate-support-bundle
with:
kots-namespace: "$APP_SLUG"
artifact-name: ${{ github.job }}-${{ matrix.cluster.distribution }}-${{ matrix.cluster.version }}-support-bundle
- name: Remove Cluster
id: remove-cluster
uses: replicatedhq/replicated-actions/remove-cluster@v1
if: ${{ always() && steps.create-cluster.outputs.cluster-id != '' }}
continue-on-error: true
with:
api-token: ${{ secrets.C11Y_MATRIX_TOKEN }}
cluster-id: ${{ steps.create-cluster.outputs.cluster-id }}
validate-kubernetes-installer-preflight:
runs-on: ubuntu-20.04
needs: [ enable-tests, can-run-ci, build-kots, build-kotsadm, build-kurl-proxy, build-migrations, push-minio, push-rqlite ]
strategy:
fail-fast: false
matrix:
cluster: [
{distribution: kind, version: v1.28.0}
]
env:
APP_SLUG: kubernetes-installer-preflight
steps:
- uses: actions/checkout@v4
- name: Create Cluster
id: create-cluster
uses: replicatedhq/replicated-actions/create-cluster@v1
with:
api-token: ${{ secrets.C11Y_MATRIX_TOKEN }}
kubernetes-distribution: ${{ matrix.cluster.distribution }}
kubernetes-version: ${{ matrix.cluster.version }}
cluster-name: automated-kots-${{ github.run_id }}-${{ matrix.cluster.distribution }}-${{ matrix.cluster.version }}
timeout-minutes: '120'
ttl: 2h
export-kubeconfig: true
- name: download kots binary
uses: actions/download-artifact@v4
with:
name: kots
path: bin/
- run: chmod +x bin/kots
- name: create namespace and dockerhub secret
run: |
kubectl create ns "$APP_SLUG"
kubectl create secret docker-registry kotsadm-dockerhub --docker-server index.docker.io --docker-username "${{ secrets.E2E_DOCKERHUB_USERNAME }}" --docker-password "${{ secrets.E2E_DOCKERHUB_PASSWORD }}" --namespace "$APP_SLUG"
- name: run the test
run: |
set +e
echo ${{ secrets.KUBERNETES_INSTALLER_PREFLIGHT_LICENSE }} | base64 -d > license.yaml
# Fake kurl installation using the crd and installer spec from the application manifests:
# Pull application manifests
./bin/kots pull "$APP_SLUG/automated" --license-file license.yaml --shared-password password
# Apply installer crd
kubectl apply -f "$APP_SLUG/upstream/installer-crd.yaml"
# Wait for crd to be created
kubectl wait --for condition=established --timeout=60s crd/installers.cluster.kurl.sh
# Seems that the above does not always guarantee the crd exists? So just in case...
sleep 10
# Apply installer
kubectl apply -f "$APP_SLUG/upstream/installer.yaml"
# Create kurl-config configmap in kube-system
kubectl create cm kurl-config -n kube-system --from-literal=installer_id=7cc8094
./bin/kots \
install "$APP_SLUG/automated" \
--license-file license.yaml \
--no-port-forward \
--namespace "$APP_SLUG" \
--shared-password password \
--kotsadm-registry ttl.sh \
--kotsadm-namespace automated-${{ github.run_id }} \
--kotsadm-tag 24h
EXIT_CODE=$?
if [ $EXIT_CODE -ne 0 ]; then
echo "------pods:"
kubectl -n "$APP_SLUG" get pods
echo "------kotsadm logs"
kubectl logs -l app=kotsadm --tail=100 --namespace "$APP_SLUG"
exit $EXIT_CODE
fi
COUNTER=1
while [ "$(./bin/kots get apps --namespace "$APP_SLUG" | awk 'NR>1{print $2}')" != "ready" ]; do
((COUNTER += 1))
if [ $COUNTER -gt 120 ]; then
echo "Timed out waiting for app to be ready"
./bin/kots get apps --namespace "$APP_SLUG"
echo "kotsadm logs:"
kubectl logs -l app=kotsadm --tail=100 --namespace "$APP_SLUG"
exit 1
fi
sleep 1
done
# try get apps without namespace (using kubeconfig)
# validate that output is the same as above
mkdir -p /tmp/.kube
sudo cp "$KUBECONFIG" /tmp/.kube/config
sudo chmod -R 777 /tmp/.kube
export KUBECONFIG=/tmp/.kube/config
kubectl config set-context --current --namespace="$APP_SLUG"
if [ "$(./bin/kots get apps | awk 'NR>1{print $2}')" != "ready" ]; then
echo "kots get apps output is not the same as above"
exit 1
fi
printf "App is installed successfully and is ready\n\n"
./bin/kots get apps --namespace "$APP_SLUG"
- name: Generate support bundle on failure
if: failure()
uses: ./.github/actions/generate-support-bundle
with:
kots-namespace: "$APP_SLUG"
artifact-name: ${{ github.job }}-${{ matrix.cluster.distribution }}-${{ matrix.cluster.version }}-support-bundle
- name: Remove Cluster
id: remove-cluster
uses: replicatedhq/replicated-actions/remove-cluster@v1
if: ${{ always() && steps.create-cluster.outputs.cluster-id != '' }}
continue-on-error: true
with:
api-token: ${{ secrets.C11Y_MATRIX_TOKEN }}
cluster-id: ${{ steps.create-cluster.outputs.cluster-id }}
validate-kots-push-images-anonymous:
runs-on: ubuntu-20.04
needs: [ enable-tests, can-run-ci, build-kots, build-kotsadm, build-kurl-proxy, build-migrations, push-minio, push-rqlite ]
steps:
- name: Checkout
uses: actions/checkout@v4
- name: download kots binary
uses: actions/download-artifact@v4
with:
name: kots
path: bin/
- run: chmod +x bin/kots
- name: run kots admin-console push-images
run: |
set +e
./bin/kots admin-console push-images ./e2e/artifacts/small.airgap ttl.sh/automated-${{ github.run_id }}
validate-kots-admin-console-generate-manifests:
runs-on: ubuntu-20.04
needs: [ enable-tests, can-run-ci, build-kots, build-kotsadm, build-kurl-proxy, build-migrations, push-minio, push-rqlite ]
strategy:
fail-fast: false
matrix:
cluster: [
{distribution: kind, version: v1.28.0}
]
env:
APP_SLUG: minimal-rbac
BASE_KOTS_VERSION: v1.72.0
NAMESPACE: generate-manifests
steps:
- name: Checkout
uses: actions/checkout@v4
- name: download kots binary
uses: actions/download-artifact@v4
with:
name: kots
path: bin/
- run: chmod +x bin/kots
- name: run kots admin-console generate-manifests without k8s context
run: |
set +e
./bin/kots admin-console generate-manifests -n "$NAMESPACE" --shared-password password
- name: validate that ./admin-console exists and is not empty
run: |
set +e
if [ ! -d ./admin-console ]; then
echo "admin-console directory does not exist"
exit 1
fi
if [ -z "$(ls -A ./admin-console)" ]; then
echo "admin-console directory is empty"
exit 1
fi
- name: remove admin-console directory
run: rm -rf ./admin-console
- name: Create Cluster
id: create-cluster
uses: replicatedhq/replicated-actions/create-cluster@v1
with:
api-token: ${{ secrets.C11Y_MATRIX_TOKEN }}
kubernetes-distribution: ${{ matrix.cluster.distribution }}
kubernetes-version: ${{ matrix.cluster.version }}
cluster-name: automated-kots-${{ github.run_id }}-${{ matrix.cluster.distribution }}-${{ matrix.cluster.version }}
timeout-minutes: '120'
ttl: 2h
export-kubeconfig: true
- name: download base kots version
run: |
curl -LO "https://github.com/replicatedhq/kots/releases/download/$BASE_KOTS_VERSION/kots_linux_amd64.tar.gz" \
&& tar zxvf kots_linux_amd64.tar.gz \
&& mv kots "kots-$BASE_KOTS_VERSION"
- name: create namespace
run: |
set +e
kubectl create namespace "$NAMESPACE"
- name: run kots admin-console generate-manifests using base kots version with k8s context
run: |
set +e
"./kots-$BASE_KOTS_VERSION" admin-console generate-manifests -n "$NAMESPACE" --shared-password password
- name: apply the generated manifests
run: |
set +e
kubectl apply -f ./admin-console -n "$NAMESPACE"
- name: wait for the kotsadm-minio-0 pod to be created
run: |
set +e
COUNTER=1
while ! kubectl get pods -n "$NAMESPACE" | grep -q kotsadm-minio-0; do
((COUNTER += 1))
if [ $COUNTER -gt 30 ]; then
echo "timed out waiting for kotsadm-minio-0 pod to be created"
exit 1
fi
sleep 1
done
- name: wait for kotsadm-minio-0 pod to be ready
run: |
set +e
kubectl wait --for=condition=ready --timeout=180s pod/kotsadm-minio-0 -n "$NAMESPACE"
- name: wait for the kotsadm deployment to be ready
run: |
set +e
kubectl wait --for=condition=available --timeout=300s deployment/kotsadm -n "$NAMESPACE"
- name: run kots admin-console generate-manifests using new kots version with k8s context
run: |
set +e
./bin/kots admin-console generate-manifests -n "$NAMESPACE" \
--shared-password password \
--kotsadm-registry ttl.sh \
--kotsadm-namespace automated-${{ github.run_id }} \
--kotsadm-tag 24h
- name: validate that ./admin-console/minio-statefulset.yaml has initContainers since a migration is needed
run: |
set +e
if ! grep -qE 'initContainers' ./admin-console/minio-statefulset.yaml; then
echo "admin-console/minio-statefulset.yaml does not have initContainers"
exit 1
fi
- name: apply the generated manifests
run: |
set +e
kubectl apply -f ./admin-console -n "$NAMESPACE"
- name: wait for kotsadm-minio-0 pod to be ready
run: |
set +e
sleep 10
kubectl wait --for=condition=ready --timeout=180s pod/kotsadm-minio-0 -n "$NAMESPACE"
- name: wait for the kotsadm deployment to be ready
run: |
set +e
kubectl wait --for=condition=available --timeout=300s deployment/kotsadm -n "$NAMESPACE"
- name: run kots admin-console generate-manifests using new kots version with k8s context
run: |
set +e
./bin/kots admin-console generate-manifests -n "$NAMESPACE" \
--shared-password password \
--kotsadm-registry ttl.sh \
--kotsadm-namespace automated-${{ github.run_id }} \
--kotsadm-tag 24h
- name: validate that ./admin-console/minio-statefulset.yaml does not have initContainers since a migration is not needed
run: |
set +e
if grep -qE 'initContainers' ./admin-console/minio-statefulset.yaml; then
echo "admin-console/minio-statefulset.yaml has initContainers"
exit 1
fi
- name: apply the generated manifests
run: |
set +e
kubectl apply -f ./admin-console -n "$NAMESPACE"
- name: wait for kotsadm-minio-0 pod to be ready
run: |
set +e
sleep 10
kubectl wait --for=condition=ready --timeout=180s pod/kotsadm-minio-0 -n "$NAMESPACE"
- name: wait for the kotsadm deployment to be ready
run: |
set +e
kubectl wait --for=condition=available --timeout=300s deployment/kotsadm -n "$NAMESPACE"
- name: print pods and logs on failure
if: failure()
run: |
echo "------pods:"
kubectl -n "$NAMESPACE" get pods
echo "------kotsadm logs"
kubectl logs -l app=kotsadm --tail=100 --namespace "$NAMESPACE"
echo "------kotsadm-minio logs"
kubectl logs -l app=kotsadm-minio --tail=100 --namespace "$NAMESPACE"
- name: Generate support bundle on failure
if: failure()
uses: ./.github/actions/generate-support-bundle
with:
kots-namespace: automated-${{ github.run_id }}
artifact-name: ${{ github.job }}-${{ matrix.cluster.distribution }}-${{ matrix.cluster.version }}-support-bundle
- name: Remove Cluster
id: remove-cluster
uses: replicatedhq/replicated-actions/remove-cluster@v1
if: ${{ always() && steps.create-cluster.outputs.cluster-id != '' }}
continue-on-error: true
with:
api-token: ${{ secrets.C11Y_MATRIX_TOKEN }}
cluster-id: ${{ steps.create-cluster.outputs.cluster-id }}
validate-min-kots-version:
runs-on: ubuntu-20.04
needs: [ enable-tests, can-run-ci, build-e2e, build-kots, build-kotsadm, build-kurl-proxy, build-migrations, push-minio, push-rqlite, generate-tag ]
env:
APP_SLUG: min-kots-version
strategy:
fail-fast: false
matrix:
cluster: [
{distribution: kind, version: v1.28.0}
]
steps:
- name: Checkout
uses: actions/checkout@v4
- name: download e2e deps
uses: actions/download-artifact@v4
with:
name: e2e
path: e2e/bin/
- name: download kots binary
uses: actions/download-artifact@v4
with:
name: kots
path: bin/
- run: |
docker load -i e2e/bin/e2e-deps.tar
chmod +x e2e/bin/*
chmod +x bin/*
cp ./bin/kots /usr/local/bin/kubectl-kots
sudo apt-get update -y && sudo apt-get install jq -y
- uses: ./.github/actions/kots-e2e
id: kots-e2e
with:
test-id: '@min-kots-version'
kots-namespace: 'min-kots-version'
k8s-distribution: ${{ matrix.cluster.distribution }}
k8s-version: ${{ matrix.cluster.version }}
testim-access-token: '${{ secrets.TESTIM_ACCESS_TOKEN }}'
testim-branch: ${{ github.head_ref == 'main' && 'master' || github.head_ref }}
kotsadm-image-registry: ttl.sh
replicated-api-token: '${{ secrets.C11Y_MATRIX_TOKEN }}'
kots-dockerhub-username: '${{ secrets.E2E_DOCKERHUB_USERNAME }}'
kots-dockerhub-password: '${{ secrets.E2E_DOCKERHUB_PASSWORD }}'
k8s-cluster-skip-teardown: true
- name: validate that kots install fails early
run: |
set +e
result=$(kubectl kots install "$APP_SLUG/automated" --no-port-forward --namespace "$APP_SLUG" --shared-password password 2>&1 >/dev/null)
echo "$result"
if [[ "$result" == *"requires"* ]] && [[ "$result" == *"10000.0.0"* ]]; then
exit 0
else
exit 1
fi
- name: Remove Cluster
id: remove-cluster
uses: replicatedhq/replicated-actions/remove-cluster@v1
if: ${{ always() && steps.kots-e2e.outputs.cluster-id != '' }}
continue-on-error: true
with:
api-token: ${{ secrets.C11Y_MATRIX_TOKEN }}
cluster-id: ${{ steps.kots-e2e.outputs.cluster-id }}
validate-target-kots-version:
runs-on: ubuntu-20.04
needs: [ enable-tests, can-run-ci, build-e2e, build-kots, build-kotsadm, build-kurl-proxy, build-migrations, push-minio, push-rqlite, generate-tag ]
strategy:
fail-fast: false
matrix:
cluster: [
{distribution: kind, version: v1.28.0}
]
steps:
- name: Checkout
uses: actions/checkout@v4
- name: download e2e deps
uses: actions/download-artifact@v4
with:
name: e2e
path: e2e/bin/
- name: download kots binary
uses: actions/download-artifact@v4
with:
name: kots
path: bin/
- run: |
docker load -i e2e/bin/e2e-deps.tar
chmod +x e2e/bin/*
chmod +x bin/*
cp ./bin/kots /usr/local/bin/kubectl-kots
sudo apt-get update -y && sudo apt-get install jq -y
- uses: ./.github/actions/kots-e2e
id: kots-e2e
with:
test-id: '@target-kots-version'
kots-namespace: 'target-kots-version'
k8s-distribution: ${{ matrix.cluster.distribution }}
k8s-version: ${{ matrix.cluster.version }}
testim-access-token: '${{ secrets.TESTIM_ACCESS_TOKEN }}'
testim-branch: ${{ github.head_ref == 'main' && 'master' || github.head_ref }}
replicated-api-token: '${{ secrets.C11Y_MATRIX_TOKEN }}'
kots-dockerhub-username: '${{ secrets.E2E_DOCKERHUB_USERNAME }}'
kots-dockerhub-password: '${{ secrets.E2E_DOCKERHUB_PASSWORD }}'
k8s-cluster-skip-teardown: true
- name: validate that kots install fails early
run: |
set +e
result=$(kubectl kots install target-kots-version/automated --no-port-forward --namespace target-kots-version --shared-password password 2>&1 >/dev/null)
echo "$result"
if [[ "$result" == *"requires"* ]] && [[ "$result" == *"1.0.0"* ]]; then
exit 0
else
exit 1
fi
- name: Remove Cluster
id: remove-cluster
uses: replicatedhq/replicated-actions/remove-cluster@v1
if: ${{ always() && steps.kots-e2e.outputs.cluster-id != '' }}
continue-on-error: true
with:
api-token: ${{ secrets.C11Y_MATRIX_TOKEN }}
cluster-id: ${{ steps.kots-e2e.outputs.cluster-id }}
validate-range-kots-version:
runs-on: ubuntu-20.04
needs: [ enable-tests, can-run-ci, build-e2e, build-kots, build-kotsadm, build-kurl-proxy, build-migrations, push-minio, push-rqlite, generate-tag ]
strategy:
fail-fast: false
matrix:
cluster: [
{distribution: kind, version: v1.28.0}
]
steps:
- name: Checkout
uses: actions/checkout@v4
- name: download e2e deps
uses: actions/download-artifact@v4
with:
name: e2e
path: e2e/bin/
- name: download kots binary
uses: actions/download-artifact@v4
with:
name: kots
path: bin/
- run: |
docker load -i e2e/bin/e2e-deps.tar
chmod +x e2e/bin/*
chmod +x bin/*
cp ./bin/kots /usr/local/bin/kubectl-kots
sudo apt-get update -y && sudo apt-get install jq -y
- uses: ./.github/actions/kots-e2e
id: kots-e2e
with:
test-id: '@range-kots-version'
kots-namespace: 'range-kots-version'
k8s-distribution: ${{ matrix.cluster.distribution }}
k8s-version: ${{ matrix.cluster.version }}
testim-access-token: '${{ secrets.TESTIM_ACCESS_TOKEN }}'
testim-branch: ${{ github.head_ref == 'main' && 'master' || github.head_ref }}
replicated-api-token: '${{ secrets.C11Y_MATRIX_TOKEN }}'
kots-dockerhub-username: '${{ secrets.E2E_DOCKERHUB_USERNAME }}'
kots-dockerhub-password: '${{ secrets.E2E_DOCKERHUB_PASSWORD }}'
k8s-cluster-skip-teardown: true
- name: validate that kots install fails early
run: |
set +e
result=$(kubectl kots install range-kots-version/automated --no-port-forward --namespace range-kots-version --shared-password password 2>&1 >/dev/null)
echo "$result"
if [[ "$result" == *"requires"* ]] && [[ "$result" == *"11000.0.0"* ]]; then
exit 0
else
exit 1
fi
- name: Remove Cluster
id: remove-cluster
uses: replicatedhq/replicated-actions/remove-cluster@v1
if: ${{ always() && steps.kots-e2e.outputs.cluster-id != '' }}
continue-on-error: true
with:
api-token: ${{ secrets.C11Y_MATRIX_TOKEN }}
cluster-id: ${{ steps.kots-e2e.outputs.cluster-id }}
validate-kots-upgrade:
runs-on: ubuntu-20.04
needs: [ enable-tests, can-run-ci, cmx-versions, build-kots, build-kotsadm, build-e2e, build-kurl-proxy, build-migrations, push-minio, push-rqlite ]
strategy:
fail-fast: false
matrix:
cluster: ${{ fromJson(needs.cmx-versions.outputs.versions-to-test) }}
exclude:
- cluster:
instance_type: m7g.large # old kots versions do not support arm64
continue-on-error: ${{ matrix.cluster.stage != 'stable' }}
env:
APP_SLUG: postgres-to-rqlite
BASE_KOTS_VERSION: v1.57.0
steps:
- name: Checkout
uses: actions/checkout@v4
- name: Create Cluster
id: create-cluster
uses: replicatedhq/replicated-actions/create-cluster@v1
with:
api-token: ${{ secrets.C11Y_MATRIX_TOKEN }}
kubernetes-distribution: ${{ matrix.cluster.distribution }}
kubernetes-version: ${{ matrix.cluster.version }}
cluster-name: automated-kots-${{ github.run_id }}-${{ matrix.cluster.distribution }}-${{ matrix.cluster.version }}
timeout-minutes: '120'
ttl: 2h
instance-type: ${{ matrix.cluster.instance_type }}
export-kubeconfig: true
- name: download base kots version
run: |
curl -LO "https://github.com/replicatedhq/kots/releases/download/$BASE_KOTS_VERSION/kots_linux_amd64.tar.gz" \
&& tar zxvf kots_linux_amd64.tar.gz \
&& mv kots "kots-$BASE_KOTS_VERSION"
- name: download kots binary
uses: actions/download-artifact@v4
with:
name: kots
path: bin/
- run: chmod +x bin/kots
- name: create namespace and dockerhub secret
run: |
kubectl create ns "$APP_SLUG"
kubectl create secret docker-registry kotsadm-dockerhub --docker-server index.docker.io --docker-username "${{ secrets.E2E_DOCKERHUB_USERNAME }}" --docker-password "${{ secrets.E2E_DOCKERHUB_PASSWORD }}" --namespace "$APP_SLUG"
- name: run the test
run: |
set +e
echo ${{ secrets.POSTGRES_TO_RQLITE_LICENSE }} | base64 -d > license.yaml
# install using the base KOTS version
"./kots-$BASE_KOTS_VERSION" \
install "$APP_SLUG/automated" \
--license-file license.yaml \
--port-forward=false \
--namespace "$APP_SLUG" \
--shared-password password
EXIT_CODE=$?
if [ $EXIT_CODE -ne 0 ]; then
echo "------pods:"
kubectl -n "$APP_SLUG" get pods
echo "------kotsadm logs"
kubectl logs -l app=kotsadm --tail=100 --namespace "$APP_SLUG"
exit $EXIT_CODE
fi
COUNTER=1
while [ "$("./kots-$BASE_KOTS_VERSION" get apps --namespace "$APP_SLUG" | awk 'NR>1{print $2}')" != "ready" ]; do
((COUNTER += 1))
if [ $COUNTER -gt 120 ]; then
echo "Timed out waiting for app to be ready"
"./kots-$BASE_KOTS_VERSION" get apps --namespace "$APP_SLUG"
echo "kotsadm logs:"
kubectl logs -l app=kotsadm --tail=100 --namespace "$APP_SLUG"
exit 1
fi
sleep 1
done
# upgrade using the new KOTS version
./bin/kots admin-console upgrade \
--namespace "$APP_SLUG" \
--kotsadm-registry ttl.sh \
--kotsadm-namespace automated-${{ github.run_id }} \
--kotsadm-tag 24h
# verify that the postgres to rqlite migration was successful
if ! kubectl logs -l app=kotsadm --namespace "$APP_SLUG" | grep -q "Migrated from Postgres to rqlite successfully"; then
echo "Failed to find a successful migration log line"
echo "kotsadm logs:"
kubectl logs -l app=kotsadm --all-containers --namespace "$APP_SLUG"
exit 1
fi
# verify that the minio migration happened
if [ -z "$(kubectl get statefulset kotsadm-minio -n "$APP_SLUG" -o jsonpath='{.spec.template.spec.initContainers}')" ]; then
echo "Failed to find initContainers in the kotsadm-minio statefulset"
echo "kotsadm-minio statefulset:"
kubectl get statefulset kotsadm-minio -n "$APP_SLUG" -o yaml
exit 1
fi
# make sure app is still installed and ready
if [ "$(./bin/kots get apps --namespace "$APP_SLUG" | awk 'NR>1{print $2}')" != "ready" ]; then
echo "App is not ready after the upgrade"
echo "kotsadm logs:"
kubectl logs -l app=kotsadm --tail=100 --namespace "$APP_SLUG"
exit 1
fi
printf "App is still installed and is ready after the migration\n\n"
./bin/kots get apps --namespace "$APP_SLUG"
- name: Generate support bundle on failure
if: failure()
uses: ./.github/actions/generate-support-bundle
with:
kots-namespace: "$APP_SLUG"
artifact-name: ${{ github.job }}-${{ matrix.cluster.distribution }}-${{ matrix.cluster.version }}-support-bundle
- name: Remove Cluster
id: remove-cluster
uses: replicatedhq/replicated-actions/remove-cluster@v1
if: ${{ always() && steps.create-cluster.outputs.cluster-id != '' }}
continue-on-error: true
with:
api-token: ${{ secrets.C11Y_MATRIX_TOKEN }}
cluster-id: ${{ steps.create-cluster.outputs.cluster-id }}
validate-kots-helm-release-secret-migration:
runs-on: ubuntu-20.04
needs: [ enable-tests, can-run-ci, build-kots, build-kotsadm, build-kurl-proxy, build-migrations, push-minio, push-rqlite ]
strategy:
fail-fast: false
matrix:
cluster: [
{distribution: kind, version: v1.28.0}
]
env:
APP_SLUG: helm-release-secret-migration
RELEASE_NAME: helm-release-chart
RELEASE_NAMESPACE: helm-release
BASE_KOTS_VERSION: v1.94.0
steps:
- name: Checkout
uses: actions/checkout@v4
- name: Create Cluster
id: create-cluster
uses: replicatedhq/replicated-actions/create-cluster@v1
with:
api-token: ${{ secrets.C11Y_MATRIX_TOKEN }}
kubernetes-distribution: ${{ matrix.cluster.distribution }}
kubernetes-version: ${{ matrix.cluster.version }}
cluster-name: automated-kots-${{ github.run_id }}-${{ matrix.cluster.distribution }}-${{ matrix.cluster.version }}
timeout-minutes: '120'
ttl: 2h
export-kubeconfig: true
- name: download base kots version
run: |
curl -LO "https://github.com/replicatedhq/kots/releases/download/$BASE_KOTS_VERSION/kots_linux_amd64.tar.gz" \
&& tar zxvf kots_linux_amd64.tar.gz \
&& mv kots "kots-$BASE_KOTS_VERSION"
- name: download kots binary
uses: actions/download-artifact@v4
with:
name: kots
path: bin/
- run: chmod +x bin/kots
- name: create namespace and dockerhub secret
run: |
kubectl create ns "$APP_SLUG"
kubectl create secret docker-registry kotsadm-dockerhub --docker-server index.docker.io --docker-username "${{ secrets.E2E_DOCKERHUB_USERNAME }}" --docker-password "${{ secrets.E2E_DOCKERHUB_PASSWORD }}" --namespace "$APP_SLUG"
- name: run the test
run: |
set +e
echo ${{ secrets.HELM_RELEASE_SECRET_MIGRATION_LICENSE }} | base64 -d > license.yaml
# install using the base KOTS version
"./kots-$BASE_KOTS_VERSION" \
install "$APP_SLUG/automated" \
--license-file license.yaml \
--no-port-forward=true \
--namespace "$APP_SLUG" \
--shared-password password
EXIT_CODE=$?
if [ $EXIT_CODE -ne 0 ]; then
echo "------pods:"
kubectl -n "$APP_SLUG" get pods
echo "------kotsadm logs"
kubectl logs -l app=kotsadm --tail=100 --namespace "$APP_SLUG"
exit $EXIT_CODE
fi
COUNTER=1
while [ "$("./kots-$BASE_KOTS_VERSION" get apps --namespace "$APP_SLUG" | awk 'NR>1{print $2}')" != "ready" ]; do
((COUNTER += 1))
if [ $COUNTER -gt 120 ]; then
echo "Timed out waiting for app to be ready"
"./kots-$BASE_KOTS_VERSION" get apps --namespace "$APP_SLUG"
echo "kotsadm logs:"
kubectl logs -l app=kotsadm --tail=100 --namespace "$APP_SLUG"
exit 1
fi
sleep 1
done
# verify that the helm release secret is created in the kotsadm namespace
releaseSecretName=$(kubectl get secret -n "$APP_SLUG" -l owner=helm,name="$RELEASE_NAME" -o jsonpath='{.items[*].metadata.name}')
if [ -z "$releaseSecretName" ]; then
echo "Failed to find the helm release secret in the $APP_SLUG namespace"
echo "kotsadm logs:"
kubectl logs -l app=kotsadm --tail=100 --namespace "$APP_SLUG"
exit 1
fi
# if there are more than one helm release secrets, fail
if [ "$(echo "$releaseSecretName" | wc -l)" -gt 1 ]; then
echo "Found more than one helm release secret in the $APP_SLUG namespace"
echo "kotsadm logs:"
kubectl logs -l app=kotsadm --tail=100 --namespace "$APP_SLUG"
exit 1
fi
# upgrade using the new KOTS version
./bin/kots admin-console upgrade \
--namespace "$APP_SLUG" \
--kotsadm-registry ttl.sh \
--kotsadm-namespace automated-${{ github.run_id }} \
--kotsadm-tag 24h
# make a config change and redeploy the app
./bin/kots set config "$APP_SLUG" create_new_sequence=true --deploy --namespace "$APP_SLUG"
# make sure app is still installed and ready
if [ "$(./bin/kots get apps --namespace "$APP_SLUG" | awk 'NR>1{print $2}')" != "ready" ]; then
echo "App is not ready after the upgrade"
echo "kotsadm logs:"
kubectl logs -l app=kotsadm --tail=100 --namespace "$APP_SLUG"
exit 1
fi
COUNTER=1
while [ "$(helm ls -n "$RELEASE_NAMESPACE" | grep "$RELEASE_NAME" | awk 'NR>0{print $3}')" != "2" ]; do
((COUNTER += 1))
if [ $COUNTER -gt 120 ]; then
echo "Timed out waiting for $RELEASE_NAME to be upgraded to revision 2"
helm ls -n "$RELEASE_NAMESPACE"
exit 1
fi
sleep 1
done
# verify that the helm release secret is created in the helm relase namespace
COUNT=1
releaseSecret=""
while [ -z "$releaseSecret" ]; do
((COUNT += 1))
if [ $COUNT -gt 10 ]; then
echo "Timed out waiting for the helm release secret to be migrated"
echo "kotsadm logs:"
kubectl logs -l app=kotsadm --tail=100 --namespace "$APP_SLUG"
exit 1
fi
sleep 1
releaseSecret=$(kubectl get secret "$releaseSecretName" -n "$RELEASE_NAMESPACE")
done
# verify that the release secret in app namepspace is deleted
oldReleaseSecret=$(kubectl get secret "$releaseSecretName" -n "$APP_SLUG")
if [ -n "$oldReleaseSecret" ]; then
echo "Found the helm release secret in the $APP_SLUG namespace"
echo "$oldReleaseSecret"
echo "kotsadm logs:"
kubectl logs -l app=kotsadm --tail=100 --namespace "$APP_SLUG"
exit 1
fi
# verify that there are two helm release secrets in the helm release namespace
releaseSecretNames=$(kubectl get secret -n "$RELEASE_NAMESPACE" -l owner=helm,name="$RELEASE_NAME" -o jsonpath='{.items[*].metadata.name}')
releaseSecretNamesCount=$(echo "$releaseSecretNames" | wc -w)
if [ "$releaseSecretNamesCount" -ne 2 ]; then
echo "Found $releaseSecretNamesCount helm release secrets in the $RELEASE_NAMESPACE namespace(Want: 2)"
kubectl get secret -n "$RELEASE_NAMESPACE" -l owner=helm,name="$RELEASE_NAME"
echo "kotsadm logs:"
kubectl logs -l app=kotsadm --tail=100 --namespace "$APP_SLUG"
exit 1
fi
printf "Helm release secret migration test passed\n\n"
./bin/kots get apps --namespace "$APP_SLUG"
- name: Generate support bundle on failure
if: failure()
uses: ./.github/actions/generate-support-bundle
with:
kots-namespace: "$APP_SLUG"
artifact-name: ${{ github.job }}-${{ matrix.cluster.distribution }}-${{ matrix.cluster.version }}-support-bundle
- name: Remove Cluster
id: remove-cluster
uses: replicatedhq/replicated-actions/remove-cluster@v1
if: ${{ always() && steps.create-cluster.outputs.cluster-id != '' }}
continue-on-error: true
with:
api-token: ${{ secrets.C11Y_MATRIX_TOKEN }}
cluster-id: ${{ steps.create-cluster.outputs.cluster-id }}
validate-multi-app-backup-and-restore:
runs-on: ubuntu-20.04
needs: [ enable-tests, can-run-ci, build-kots, build-kotsadm, build-e2e, build-kurl-proxy, build-migrations, push-minio, push-rqlite ]
strategy:
fail-fast: false
matrix:
cluster: [
{distribution: kind, version: v1.28.0}
]
steps:
- name: Checkout
uses: actions/checkout@v4
- name: download e2e deps
uses: actions/download-artifact@v4
with:
name: e2e
path: e2e/bin/
- run: docker load -i e2e/bin/e2e-deps.tar
- run: chmod +x e2e/bin/*
- name: download kots binary
uses: actions/download-artifact@v4
with:
name: kots
path: bin/
- run: chmod +x bin/*
- uses: ./.github/actions/kots-e2e
with:
test-id: '@multi-app-backup-and-restore'
kots-namespace: 'multi-app-backup-and-restore'
k8s-distribution: ${{ matrix.cluster.distribution }}
k8s-version: ${{ matrix.cluster.version }}
replicated-api-token: '${{ secrets.C11Y_MATRIX_TOKEN }}'
kots-dockerhub-username: '${{ secrets.E2E_DOCKERHUB_USERNAME }}'
kots-dockerhub-password: '${{ secrets.E2E_DOCKERHUB_PASSWORD }}'
validate-multi-app-install:
runs-on: ubuntu-20.04
needs: [ enable-tests, can-run-ci, build-kots, build-kotsadm, build-e2e, build-kurl-proxy, build-migrations, push-minio, push-rqlite ]
strategy:
fail-fast: false
matrix:
cluster: [
{distribution: kind, version: v1.28.0}
]
steps:
- name: Checkout
uses: actions/checkout@v4
- name: download e2e deps
uses: actions/download-artifact@v4
with:
name: e2e
path: e2e/bin/
- run: docker load -i e2e/bin/e2e-deps.tar
- run: chmod +x e2e/bin/*
- name: download kots binary
uses: actions/download-artifact@v4
with:
name: kots
path: bin/
- run: chmod +x bin/*
- uses: ./.github/actions/kots-e2e
with:
test-id: '@multi-app-install'
kots-namespace: 'multi-app-install'
k8s-distribution: ${{ matrix.cluster.distribution }}
k8s-version: ${{ matrix.cluster.version }}
replicated-api-token: '${{ secrets.C11Y_MATRIX_TOKEN }}'
kots-dockerhub-username: '${{ secrets.E2E_DOCKERHUB_USERNAME }}'
kots-dockerhub-password: '${{ secrets.E2E_DOCKERHUB_PASSWORD }}'
validate-airgap-smoke-test:
runs-on: ubuntu-20.04
needs: [ enable-tests, can-run-ci, build-kots, build-kotsadm, build-e2e, build-kurl-proxy, build-migrations, push-minio, push-rqlite ]
strategy:
fail-fast: false
matrix:
cluster: [
{distribution: kind, version: v1.28.0}
]
steps:
- name: Checkout
uses: actions/checkout@v4
- name: download e2e deps
uses: actions/download-artifact@v4
with:
name: e2e
path: e2e/bin/
- run: docker load -i e2e/bin/e2e-deps.tar
- run: chmod +x e2e/bin/*
- name: download kots binary
uses: actions/download-artifact@v4
with:
name: kots
path: bin/
- run: chmod +x bin/*
- uses: ./.github/actions/kots-e2e
with:
test-id: '@airgap-smoke-test'
kots-namespace: 'airgap-smoke-test'
k8s-distribution: ${{ matrix.cluster.distribution }}
k8s-version: ${{ matrix.cluster.version }}
testim-access-token: '${{ secrets.TESTIM_ACCESS_TOKEN }}'
testim-branch: ${{ github.head_ref == 'main' && 'master' || github.head_ref }}
kots-airgap: true
replicated-api-token: '${{ secrets.C11Y_MATRIX_TOKEN }}'
kots-dockerhub-username: '${{ secrets.E2E_DOCKERHUB_USERNAME }}'
kots-dockerhub-password: '${{ secrets.E2E_DOCKERHUB_PASSWORD }}'
validate-remove-app:
runs-on: ubuntu-20.04
needs: [ enable-tests, can-run-ci, build-kots, build-kotsadm, build-kurl-proxy, build-migrations, push-minio, push-rqlite ]
strategy:
fail-fast: false
matrix:
cluster: [
{distribution: kind, version: v1.28.0, instance_type: r1.medium}
]
env:
APP_SLUG: remove-app
steps:
- name: Checkout
uses: actions/checkout@v4
- name: Create Cluster
id: create-cluster
uses: replicatedhq/replicated-actions/create-cluster@v1
with:
api-token: ${{ secrets.C11Y_MATRIX_TOKEN }}
kubernetes-distribution: ${{ matrix.cluster.distribution }}
kubernetes-version: ${{ matrix.cluster.version }}
cluster-name: automated-kots-${{ github.run_id }}-${{ matrix.cluster.distribution }}-${{ matrix.cluster.version }}
timeout-minutes: '120'
ttl: 2h
instance-type: ${{ matrix.cluster.instance_type }}
export-kubeconfig: true
- name: download kots binary
uses: actions/download-artifact@v4
with:
name: kots
path: bin/
- run: chmod +x bin/kots
- name: create namespace and dockerhub secret
run: |
kubectl create ns "$APP_SLUG"
kubectl create secret docker-registry kotsadm-dockerhub --docker-server index.docker.io --docker-username "${{ secrets.E2E_DOCKERHUB_USERNAME }}" --docker-password "${{ secrets.E2E_DOCKERHUB_PASSWORD }}" --namespace "$APP_SLUG"
- name: run the test
run: |
set +e
echo ${{ secrets.REMOVE_APP_LICENSE }} | base64 -d > license.yaml
HELM_APP_NAMESPACES=(postgres-test redis-test "$APP_SLUG")
APP_NAMESPACES=(postgres-test redis-test nginx-test rabbitmq-system "$APP_SLUG")
./bin/kots \
install "$APP_SLUG/automated" \
--license-file license.yaml \
--no-port-forward \
--namespace "$APP_SLUG" \
--shared-password password \
--kotsadm-registry ttl.sh \
--kotsadm-namespace automated-${{ github.run_id }} \
--kotsadm-tag 24h
COUNTER=1
while [ "$(./bin/kots get apps --namespace "$APP_SLUG" | awk 'NR>1{print $2}')" != "ready" ]; do
((COUNTER += 1))
if [ $COUNTER -gt 120 ]; then
echo "Timed out waiting for app to be ready"
./bin/kots get apps --namespace "$APP_SLUG"
echo "kotsadm logs:"
kubectl logs -l app=kotsadm --tail=100 --namespace "$APP_SLUG"
exit 1
fi
sleep 1
done
# test that --undeploy deletes application resources from the cluster
./bin/kots remove "$APP_SLUG" --namespace "$APP_SLUG" --undeploy
if [ "$(./bin/kots get apps --namespace "$APP_SLUG" --output=json | tr -d '\n')" != "[]" ]; then
printf "App reference was not removed\n\n"
exit 1
fi
if [ "$(kubectl get all,secrets,configmap,pvc -A -l "kots.io/app-slug=$APP_SLUG" --ignore-not-found | wc -l | tr -d '\n')" != "0" ]; then
printf "Application resources are still found in the cluster\n\n"
kubectl get all,secrets,configmap,pvc -A -l "kots.io/app-slug=$APP_SLUG"
exit 1
fi
if [ "$(kubectl get crd rabbitmqclusters.rabbitmq.com --ignore-not-found | wc -l | tr -d '\n')" != "0" ]; then
printf "rabbitmqclusters.rabbitmq.com CRD was not removed\n\n"
kubectl get crd rabbitmqclusters.rabbitmq.com
exit 1
fi
for ns in "${HELM_APP_NAMESPACES[@]}"; do
if [ "$(kubectl get secret -n "$ns" --field-selector type=helm.sh/release.v1 --ignore-not-found | wc -l | tr -d '\n')" != "0" ]; then
printf "Application Helm release secrets are still found in the namepspace %s\n\n" "$ns"
kubectl get secret -n "$ns" --field-selector type=helm.sh/release.v1
exit 1
fi
done
# re-install and test that running the remove command without --undeploy does _not_ delete any resources from the cluster
./bin/kots \
install "$APP_SLUG/automated" \
--license-file license.yaml \
--no-port-forward \
--namespace "$APP_SLUG" \
--shared-password password \
--kotsadm-registry ttl.sh \
--kotsadm-namespace automated-${{ github.run_id }} \
--kotsadm-tag 24h
COUNTER=1
while [ "$(./bin/kots get apps --namespace "$APP_SLUG" | awk 'NR>1{print $2}')" != "ready" ]; do
((COUNTER += 1))
if [ $COUNTER -gt 120 ]; then
echo "Timed out waiting for app to be ready"
./bin/kots get apps --namespace "$APP_SLUG"
echo "kotsadm logs:"
kubectl logs -l app=kotsadm --tail=100 --namespace "$APP_SLUG"
exit 1
fi
sleep 1
done
./bin/kots remove "$APP_SLUG" --namespace "$APP_SLUG" --force
if [ "$(./bin/kots get apps --namespace "$APP_SLUG" --output=json | tr -d '\n')" != "[]" ]; then
printf "App reference was not removed\n\n"
exit 1
fi
for ns in "${APP_NAMESPACES[@]}"; do
if [ "$(kubectl get all,secrets,configmap,pvc -n "$ns" -l "kots.io/app-slug=$APP_SLUG" --ignore-not-found | wc -l | tr -d '\n')" == "0" ]; then
printf "%s namespace does not contain any resources\n\n" "$ns"
kubectl get all,secrets,configmap,pvc -n "$ns"
exit 1
fi
done
if [ "$(kubectl get crd rabbitmqclusters.rabbitmq.com --ignore-not-found | wc -l | tr -d '\n')" == "0" ]; then
printf "rabbitmqclusters.rabbitmq.com CRD was not found\n\n"
kubectl get crd rabbitmqclusters.rabbitmq.com
exit 1
fi
if [ "$(kubectl get rabbitmqclusters.rabbitmq.com -n rabbitmq-system --ignore-not-found | wc -l | tr -d '\n')" == "0" ]; then
printf "rabbitmq-system namespace does not contain rabbitmqclusters\n\n"
kubectl get rabbitmqclusters.rabbitmq.com -n rabbitmq-system
exit 1
fi
for ns in "${HELM_APP_NAMESPACES[@]}"; do
if [ "$(kubectl get secret -n "$ns" --field-selector type=helm.sh/release.v1 --ignore-not-found | wc -l | tr -d '\n')" == "0" ]; then
printf "Application Helm release secrets are not found in namepspace %s\n\n" "$ns"
kubectl get secret -n "$ns" --field-selector type=helm.sh/release.v1
exit 1
fi
done
- name: Generate support bundle on failure
if: failure()
uses: ./.github/actions/generate-support-bundle
with:
kots-namespace: "$APP_SLUG"
artifact-name: ${{ github.job }}-${{ matrix.cluster.distribution }}-${{ matrix.cluster.version }}-support-bundle
- name: Remove Cluster
id: remove-cluster
uses: replicatedhq/replicated-actions/remove-cluster@v1
if: ${{ always() && steps.create-cluster.outputs.cluster-id != '' }}
continue-on-error: true
with:
api-token: ${{ secrets.C11Y_MATRIX_TOKEN }}
cluster-id: ${{ steps.create-cluster.outputs.cluster-id }}
validate-registry-check:
runs-on: ubuntu-20.04
needs: [ enable-tests, can-run-ci, build-kots, build-kotsadm, build-kurl-proxy, build-migrations, push-minio, push-rqlite ]
strategy:
fail-fast: false
matrix:
cluster: [
{distribution: kind, version: v1.28.0}
]
steps:
- name: Checkout
uses: actions/checkout@v4
- name: Create Cluster
id: create-cluster
uses: replicatedhq/replicated-actions/create-cluster@v1
with:
api-token: ${{ secrets.C11Y_MATRIX_TOKEN }}
kubernetes-distribution: ${{ matrix.cluster.distribution }}
kubernetes-version: ${{ matrix.cluster.version }}
cluster-name: automated-kots-${{ github.run_id }}-${{ matrix.cluster.distribution }}-${{ matrix.cluster.version }}
timeout-minutes: '120'
ttl: 2h
export-kubeconfig: true
- name: download kots binary
uses: actions/download-artifact@v4
with:
name: kots
path: bin/
- run: chmod +x bin/kots
- name: run the test
run: |
set +e
./bin/kots admin-console push-images \
not-an-app.airgap localhost:1234/not-a-namespace \
--registry-username not-a-username \
--registry-password not-a-password > output.txt 2>&1
if ! grep -q 'Failed to test access' output.txt; then
printf "Expected registry validation to fail before pushing images, but did not.\n\n"
cat output.txt
exit 1
fi
rm output.txt
./bin/kots install not-an-app \
--airgap-bundle not-an-app.airgap \
--kotsadm-registry localhost:1234/not-a-namespace \
--registry-username not-a-username \
--registry-password not-a-password > output.txt 2>&1
if ! grep -q 'Failed to test access' output.txt; then
printf "Expected registry validation to fail before installation, but did not.\n\n"
cat output.txt
exit 1
fi
rm output.txt
./bin/kots upstream upgrade not-an-app \
--airgap-bundle not-an-app.airgap \
--kotsadm-registry localhost:1234/not-a-namespace \
--registry-username not-a-username \
--registry-password not-a-password \
--namespace not-a-namespace > output.txt 2>&1
if ! grep -q 'Failed to test access' output.txt; then
printf "Expected registry validation to fail before upgrading, but did not.\n\n"
cat output.txt
exit 1
fi
- name: Generate support bundle on failure
if: failure()
uses: ./.github/actions/generate-support-bundle
with:
kots-namespace: "$APP_SLUG"
artifact-name: ${{ github.job }}-${{ matrix.cluster.distribution }}-${{ matrix.cluster.version }}-support-bundle
- name: Remove Cluster
id: remove-cluster
uses: replicatedhq/replicated-actions/remove-cluster@v1
if: ${{ always() && steps.create-cluster.outputs.cluster-id != '' }}
continue-on-error: true
with:
api-token: ${{ secrets.C11Y_MATRIX_TOKEN }}
cluster-id: ${{ steps.create-cluster.outputs.cluster-id }}
validate-native-helm-v2:
runs-on: ubuntu-20.04
needs: [ enable-tests, can-run-ci, build-kots, build-kotsadm, build-kurl-proxy, build-migrations, push-minio, push-rqlite ]
strategy:
fail-fast: false
matrix:
cluster: [
{distribution: kind, version: v1.28.0}
]
env:
APP_SLUG: native-helm-v2
INITIAL_VERSION: '0.1.1'
UPGRADE_VERSION: '0.2.1'
steps:
- name: Checkout
uses: actions/checkout@v4
- uses: azure/setup-helm@v4
with:
token: ${{ secrets.GITHUB_TOKEN }}
- name: Create Cluster
id: create-cluster
uses: replicatedhq/replicated-actions/create-cluster@v1
with:
api-token: ${{ secrets.C11Y_MATRIX_TOKEN }}
kubernetes-distribution: ${{ matrix.cluster.distribution }}
kubernetes-version: ${{ matrix.cluster.version }}
cluster-name: automated-kots-${{ github.run_id }}-${{ matrix.cluster.distribution }}-${{ matrix.cluster.version }}
timeout-minutes: '120'
ttl: 2h
export-kubeconfig: true
- name: download kots binary
uses: actions/download-artifact@v4
with:
name: kots
path: bin/
- run: chmod +x bin/kots
- name: create namespace and dockerhub secret
run: |
kubectl create ns "$APP_SLUG"
kubectl create secret docker-registry kotsadm-dockerhub --docker-server index.docker.io --docker-username "${{ secrets.E2E_DOCKERHUB_USERNAME }}" --docker-password "${{ secrets.E2E_DOCKERHUB_PASSWORD }}" --namespace "$APP_SLUG"
- name: run the test
run: |
set +e
echo ${{ secrets.NATIVE_HELM_V2_LICENSE }} | base64 -d > license.yaml
./bin/kots \
install "$APP_SLUG/automated" \
--license-file license.yaml \
--app-version-label "$INITIAL_VERSION" \
--no-port-forward \
--namespace "$APP_SLUG" \
--shared-password password \
--kotsadm-registry ttl.sh \
--kotsadm-namespace automated-${{ github.run_id }} \
--kotsadm-tag 24h
EXIT_CODE=$?
if [ $EXIT_CODE -ne 0 ]; then
echo "------pods:"
kubectl -n "$APP_SLUG" get pods
echo "------kotsadm logs"
kubectl logs -l app=kotsadm --tail=100 --namespace "$APP_SLUG"
exit $EXIT_CODE
fi
COUNTER=1
while [ "$(./bin/kots get apps --namespace "$APP_SLUG" | awk 'NR>1{print $3}')" != "$INITIAL_VERSION" ]; do
((COUNTER += 1))
if [ $COUNTER -gt 120 ]; then
echo "Timed out waiting for app to be ready"
./bin/kots get apps --namespace "$APP_SLUG"
echo "kotsadm logs:"
kubectl logs -l app=kotsadm --tail=100 --namespace "$APP_SLUG"
exit 1
fi
sleep 1
done
COUNTER=1
while [ "$(./bin/kots get apps --namespace "$APP_SLUG" | awk 'NR>1{print $2}')" != "ready" ]; do
((COUNTER += 1))
if [ $COUNTER -gt 120 ]; then
echo "Timed out waiting for app to be ready"
./bin/kots get apps --namespace "$APP_SLUG"
echo "kotsadm logs:"
kubectl logs -l app=kotsadm --tail=100 --namespace "$APP_SLUG"
exit 1
fi
sleep 1
done
# validate that helm charts installed using both native helm workflow were deployed via the helm CLI correctly
if ! helm ls -n "$APP_SLUG" | awk 'NR>1{print $1}' | grep -q my-chart-release; then
printf "my-chart-release helm release not found in %s namespace\n\n" "$APP_SLUG"
helm ls -n "$APP_SLUG"
exit 1
fi
if ! helm ls -n "$APP_SLUG" | awk 'NR>1{print $1}' | grep -q my-other-chart-release; then
printf "my-other-chart-release helm release not found in %s namespace\n\n" "$APP_SLUG"
helm ls -n "$APP_SLUG"
exit 1
fi
# validate that `helm get values` works for the v1beta2 chart
if ! helm get values my-chart-release -n "$APP_SLUG" | grep -q my-value; then
printf "my-value not found in helm values for my-chart-release in %s namespace\n\n" "$APP_SLUG"
helm get values my-chart-release -n "$APP_SLUG"
exit 1
fi
# upgrade the app version
./bin/kots upstream upgrade "$APP_SLUG" -n "$APP_SLUG" --deploy
# wait for my-chart-release to be uninstalled and my-other-chart-release to be upgraded to revision 2
COUNTER=1
while [ "$(helm ls -n "$APP_SLUG" | awk 'NR>1{print $1}' | grep my-chart-release)" != "" ]; do
((COUNTER += 1))
if [ $COUNTER -gt 120 ]; then
echo "Timed out waiting for my-chart-release to be uninstalled"
helm ls -n "$APP_SLUG"
exit 1
fi
sleep 1
done
COUNTER=1
while [ "$(helm ls -n "$APP_SLUG" | grep my-other-chart-release | awk 'NR>0{print $3}')" != "2" ]; do
((COUNTER += 1))
if [ $COUNTER -gt 120 ]; then
echo "Timed out waiting for my-other-chart-release to be upgraded to revision 2"
helm ls -n "$APP_SLUG"
exit 1
fi
sleep 1
done
# validate that `helm get values` works for the upgraded v1beta2 chart
if ! helm get values my-other-chart-release -n "$APP_SLUG" | grep -q my-value; then
printf "my-value not found in helm values for my-chart-release in %s namespace\n\n" "$APP_SLUG"
helm get values my-chart-release -n "$APP_SLUG"
exit 1
fi
# wait for the app to be ready again
COUNTER=1
while [ "$(./bin/kots get apps --namespace "$APP_SLUG" | awk 'NR>1{print $3}')" != "$UPGRADE_VERSION" ]; do
((COUNTER += 1))
if [ $COUNTER -gt 120 ]; then
echo "Timed out waiting for app to be ready"
./bin/kots get apps --namespace "$APP_SLUG"
echo "kotsadm logs:"
kubectl logs -l app=kotsadm --tail=100 --namespace "$APP_SLUG"
exit 1
fi
sleep 1
done
COUNTER=1
while [ "$(./bin/kots get apps --namespace "$APP_SLUG" | awk 'NR>1{print $2}')" != "ready" ]; do
((COUNTER += 1))
if [ $COUNTER -gt 120 ]; then
echo "Timed out waiting for app to be ready"
./bin/kots get apps --namespace "$APP_SLUG"
echo "kotsadm logs:"
kubectl logs -l app=kotsadm --tail=100 --namespace "$APP_SLUG"
exit 1
fi
sleep 1
done
# validate that the conditional chart is installed
COUNTER=1
while [ "$(helm ls -n "$APP_SLUG" | awk 'NR>1{print $1}' | grep my-conditional-chart-release)" == "" ]; do
((COUNTER += 1))
if [ $COUNTER -gt 120 ]; then
echo "Timed out waiting for my-conditional-chart-release to be installed"
helm ls -n "$APP_SLUG"
exit 1
fi
sleep 1
done
# toggle the config option to exclude the conditional chart
./bin/kots set config "$APP_SLUG" install_conditional_chart=0 --deploy --namespace "$APP_SLUG"
# wait for my-conditional-chart-release to be uninstalled
COUNTER=1
while [ "$(helm ls -n "$APP_SLUG" | awk 'NR>1{print $1}' | grep my-conditional-chart-release)" != "" ]; do
((COUNTER += 1))
if [ $COUNTER -gt 120 ]; then
echo "Timed out waiting for my-conditional-chart-release to be uninstalled"
helm ls -n "$APP_SLUG"
exit 1
fi
sleep 1
done
- name: Generate support bundle on failure
if: failure()
uses: ./.github/actions/generate-support-bundle
with:
kots-namespace: "$APP_SLUG"
artifact-name: ${{ github.job }}-${{ matrix.cluster.distribution }}-${{ matrix.cluster.version }}-support-bundle
- name: Remove Cluster
id: remove-cluster
uses: replicatedhq/replicated-actions/remove-cluster@v1
if: ${{ always() && steps.create-cluster.outputs.cluster-id != '' }}
continue-on-error: true
with:
api-token: ${{ secrets.C11Y_MATRIX_TOKEN }}
cluster-id: ${{ steps.create-cluster.outputs.cluster-id }}
validate-deployment-orchestration:
runs-on: ubuntu-20.04
needs: [ enable-tests, can-run-ci, build-kots, build-kotsadm, build-kurl-proxy, build-migrations, push-minio, push-rqlite ]
strategy:
fail-fast: false
matrix:
cluster: [
{distribution: kind, version: v1.28.0}
]
env:
APP_SLUG: deployment-orchestration
steps:
- name: Checkout
uses: actions/checkout@v4
- uses: azure/setup-helm@v4
with:
token: ${{ secrets.GITHUB_TOKEN }}
- name: Create Cluster
id: create-cluster
uses: replicatedhq/replicated-actions/create-cluster@v1
with:
api-token: ${{ secrets.C11Y_MATRIX_TOKEN }}
kubernetes-distribution: ${{ matrix.cluster.distribution }}
kubernetes-version: ${{ matrix.cluster.version }}
cluster-name: automated-kots-${{ github.run_id }}-${{ matrix.cluster.distribution }}-${{ matrix.cluster.version }}
timeout-minutes: '120'
ttl: 2h
export-kubeconfig: true
- name: download kots binary
uses: actions/download-artifact@v4
with:
name: kots
path: bin/
- run: chmod +x bin/kots
- name: create namespace and dockerhub secret
run: |
kubectl create ns "$APP_SLUG"
kubectl create secret docker-registry kotsadm-dockerhub --docker-server index.docker.io --docker-username "${{ secrets.E2E_DOCKERHUB_USERNAME }}" --docker-password "${{ secrets.E2E_DOCKERHUB_PASSWORD }}" --namespace "$APP_SLUG"
- name: run the test
run: |
set +e
echo ${{ secrets.DEPLOYMENT_ORCHESTRATION_LICENSE }} | base64 -d > license.yaml
./bin/kots \
install "$APP_SLUG/automated" \
--license-file license.yaml \
--no-port-forward \
--namespace "$APP_SLUG" \
--shared-password password \
--kotsadm-registry ttl.sh \
--kotsadm-namespace automated-${{ github.run_id }} \
--kotsadm-tag 24h
EXIT_CODE=$?
if [ $EXIT_CODE -ne 0 ]; then
echo "------pods:"
kubectl -n "$APP_SLUG" get pods
echo "------kotsadm logs"
kubectl logs -l app=kotsadm --tail=100 --namespace "$APP_SLUG"
exit $EXIT_CODE
fi
function wait_for_log {
local counter=1
local timeout=30
local log_pattern="$1"
while ! kubectl logs deploy/kotsadm -c kotsadm -n "$APP_SLUG" | grep -i "$log_pattern"; do
((counter += 1))
if [ $counter -gt $timeout ]; then
echo "Timed out waiting for log $log_pattern"
exit 1
fi
sleep 1
done
}
wait_for_log "applying phase -9999"
wait_for_log "applying phase -3"
wait_for_log "waiting for resource apiextensions.k8s.io/v1/CustomResourceDefinition/myresources.example.com in namespace $APP_SLUG to be ready"
wait_for_log "applying phase -2"
# validate that phase -1 has not deployed yet since we're waiting on the CR status fields
if kubectl logs deploy/kotsadm -c kotsadm -n "$APP_SLUG" | grep -i "applying phase -1"; then
printf "phase -1 was deployed before phase -2 completed"
kubectl logs deploy/kotsadm -c kotsadm -n "$APP_SLUG"
exit 1
fi
wait_for_log "waiting for resource example.com/v1beta1/MyResource/my-resource in namespace $APP_SLUG to have property .status.tasks.extract=true"
# set .status.tasks.extract=true
kubectl patch myresources.example.com my-resource -n "$APP_SLUG" -p '{"status": {"tasks": {"extract": true}}}' --type=merge
wait_for_log "waiting for resource example.com/v1beta1/MyResource/my-resource in namespace $APP_SLUG to have property .status.tasks.transform=true"
# set .status.tasks.transform=true
kubectl patch myresources.example.com my-resource -n "$APP_SLUG" -p '{"status": {"tasks": {"transform": true}}}' --type=merge
wait_for_log "waiting for resource example.com/v1beta1/MyResource/my-resource in namespace $APP_SLUG to have property .status.tasks.load=true"
# set .status.tasks.load=true
kubectl patch myresources.example.com my-resource -n "$APP_SLUG" -p '{"status": {"tasks": {"load": true}}}' --type=merge
# now validate that the remaining phases are deployed (-1, 0, and 1)
wait_for_log "applying phase -1"
wait_for_log "waiting for resource apps/v1/Deployment/nginx-1 in namespace $APP_SLUG to be ready"
wait_for_log "applying phase 0"
wait_for_log "waiting for resource apps/v1/Deployment/nginx-2 in namespace $APP_SLUG to be ready"
wait_for_log "applying phase 1"
wait_for_log "waiting for resource /v1/Service/nginx-2 in namespace $APP_SLUG to be ready"
# wait for the app to be ready
COUNTER=1
while [ "$(./bin/kots get apps --namespace "$APP_SLUG" | awk 'NR>1{print $2}')" != "ready" ]; do
((COUNTER += 1))
if [ $COUNTER -gt 120 ]; then
echo "Timed out waiting for app to be ready"
./bin/kots get apps --namespace "$APP_SLUG"
echo "kotsadm logs:"
kubectl logs -l app=kotsadm --tail=100 --namespace "$APP_SLUG"
exit 1
fi
sleep 1
done
# remove the app
./bin/kots remove "$APP_SLUG" -n "$APP_SLUG" --undeploy
wait_for_log "deleting resources in phase -1"
wait_for_log "deleting resources in phase 0"
wait_for_log "deleting resources in phase 1"
wait_for_log "deleting resources in phase 2"
wait_for_log "deleting resources in phase 3"
# validate that the app reference was removed
if [ "$(./bin/kots get apps --namespace "$APP_SLUG" --output=json | tr -d '\n')" != "[]" ]; then
printf "App reference was not removed\n\n"
exit 1
fi
- name: Generate support bundle on failure
if: failure()
uses: ./.github/actions/generate-support-bundle
with:
kots-namespace: "$APP_SLUG"
artifact-name: ${{ github.job }}-${{ matrix.cluster.distribution }}-${{ matrix.cluster.version }}-support-bundle
- name: Remove Cluster
id: remove-cluster
uses: replicatedhq/replicated-actions/remove-cluster@v1
if: ${{ always() && steps.create-cluster.outputs.cluster-id != '' }}
continue-on-error: true
with:
api-token: ${{ secrets.C11Y_MATRIX_TOKEN }}
cluster-id: ${{ steps.create-cluster.outputs.cluster-id }}
validate-replicated-sdk:
runs-on: ubuntu-20.04
needs: [ enable-tests, can-run-ci, build-kots, build-kotsadm, build-kurl-proxy, build-migrations, push-minio, push-rqlite ]
strategy:
fail-fast: false
matrix:
cluster: [
{distribution: kind, version: v1.28.0},
{distribution: openshift, version: 4.15.0-okd}
]
env:
KOTS_NAMESPACE: replicated-sdk
steps:
- name: Checkout
uses: actions/checkout@v4
- name: Create Cluster
id: create-cluster
uses: replicatedhq/replicated-actions/create-cluster@v1
with:
api-token: ${{ secrets.C11Y_MATRIX_TOKEN }}
kubernetes-distribution: ${{ matrix.cluster.distribution }}
kubernetes-version: ${{ matrix.cluster.version }}
cluster-name: automated-kots-${{ github.run_id }}-${{ matrix.cluster.distribution }}-${{ matrix.cluster.version }}
timeout-minutes: '120'
ttl: 2h
export-kubeconfig: true
- name: download kots binary
uses: actions/download-artifact@v4
with:
name: kots
path: bin/
- run: chmod +x bin/kots
- name: create namespace and dockerhub secret
run: |
kubectl create ns "$KOTS_NAMESPACE"
kubectl create secret docker-registry kotsadm-dockerhub --docker-server index.docker.io --docker-username "${{ secrets.E2E_DOCKERHUB_USERNAME }}" --docker-password "${{ secrets.E2E_DOCKERHUB_PASSWORD }}" --namespace "$KOTS_NAMESPACE"
- name: run upgrade-to-replicated-sdk test
id: upgrade-to-replicated-sdk
env:
APP_SLUG: upgrade-to-replicated-sdk
run: |
set +e
echo ${{ secrets.UPGRADE_TO_REPLICATED_SDK_LICENSE }} | base64 -d > license.yaml
LICENSE_ID="$(grep -oP 'licenseID:\s*\K\w+' license.yaml)"
echo "license-id=$LICENSE_ID" >> "$GITHUB_OUTPUT"
./bin/kots \
install "$APP_SLUG/automated" \
--license-file license.yaml \
--no-port-forward \
--namespace "$KOTS_NAMESPACE" \
--shared-password password \
--app-version-label v1.0.0 \
--kotsadm-registry ttl.sh \
--kotsadm-namespace automated-${{ github.run_id }} \
--kotsadm-tag 24h
EXIT_CODE=$?
if [ $EXIT_CODE -ne 0 ]; then
echo "------pods:"
kubectl -n "$KOTS_NAMESPACE" get pods
echo "------kotsadm logs"
kubectl logs -l app=kotsadm --tail=100 --namespace "$KOTS_NAMESPACE"
exit $EXIT_CODE
fi
# wait for the app to be ready
COUNTER=1
while [ "$(./bin/kots get apps --namespace "$KOTS_NAMESPACE" | awk 'NR>1{print $2}')" != "ready" ]; do
((COUNTER += 1))
if [ $COUNTER -gt 120 ]; then
echo "Timed out waiting for app to be ready"
./bin/kots get apps --namespace "$KOTS_NAMESPACE"
echo "kotsadm logs:"
kubectl logs -l app=kotsadm --tail=100 --namespace "$KOTS_NAMESPACE"
exit 1
fi
sleep 1
done
# upgrade the app to the new version
./bin/kots upstream upgrade "$APP_SLUG" -n "$KOTS_NAMESPACE" --deploy
sleep 5
# wait for the app to be ready again
COUNTER=1
while [ "$(./bin/kots get apps --namespace "$KOTS_NAMESPACE" | awk 'NR>1{print $2}')" != "ready" ]; do
((COUNTER += 1))
if [ $COUNTER -gt 120 ]; then
echo "Timed out waiting for app to be ready"
./bin/kots get apps --namespace "$KOTS_NAMESPACE"
echo "kotsadm logs:"
kubectl logs -l app=kotsadm --tail=100 --namespace "$KOTS_NAMESPACE"
exit 1
fi
sleep 1
done
# get the version of the replicated-sdk that is running and set it as an output
REPLICATED_SDK_VERSION=$(kubectl get deploy replicated -n "$KOTS_NAMESPACE" -o jsonpath='{.spec.template.spec.containers[0].image}' | grep -oE '[^:]+$')
echo "replicated-sdk-version=$REPLICATED_SDK_VERSION" >> "$GITHUB_OUTPUT"
- run: rm -rf ./replicated-sdk
- name: Checkout replicated-sdk
uses: actions/checkout@v4
with:
repository: replicatedhq/replicated-sdk
path: replicated-sdk
ref: ${{ steps.upgrade-to-replicated-sdk.outputs.replicated-sdk-version }}
- name: Validate endpoints
uses: ./replicated-sdk/.github/actions/validate-endpoints
with:
license-id: ${{ steps.upgrade-to-replicated-sdk.outputs.license-id }}
license-fields: '[{"name":"expires_at","value": ""}]'
integration-enabled: true
namespace: "$KOTS_NAMESPACE"
- name: remove upgrade-to-replicated-sdk app
env:
APP_SLUG: upgrade-to-replicated-sdk
run: |
# remove the app
./bin/kots remove "$APP_SLUG" -n "$KOTS_NAMESPACE" --undeploy
# validate that the app reference was removed
if [ "$(./bin/kots get apps --namespace "$KOTS_NAMESPACE" --output=json | tr -d '\n')" != "[]" ]; then
printf "App reference was not removed\n\n"
exit 1
fi
- name: run replicated-sdk-subchart-native-helm-v1 test
id: replicated-sdk-subchart-native-helm-v1
env:
APP_SLUG: replicated-sdk-subchart-native-helm-v1
run: |
set +e
echo ${{ secrets.REPLICATED_SDK_SUBCHART_NATIVE_HELM_V1 }} | base64 -d > license.yaml
LICENSE_ID="$(grep -oP 'licenseID:\s*\K\w+' license.yaml)"
echo "license-id=$LICENSE_ID" >> "$GITHUB_OUTPUT"
./bin/kots \
install "$APP_SLUG/automated" \
--license-file license.yaml \
--no-port-forward \
--namespace "$KOTS_NAMESPACE" \
--shared-password password \
--kotsadm-registry ttl.sh \
--kotsadm-namespace automated-${{ github.run_id }} \
--kotsadm-tag 24h
EXIT_CODE=$?
if [ $EXIT_CODE -ne 0 ]; then
echo "------pods:"
kubectl -n "$KOTS_NAMESPACE" get pods
echo "------kotsadm logs"
kubectl logs -l app=kotsadm --tail=100 --namespace "$KOTS_NAMESPACE"
exit $EXIT_CODE
fi
# wait for the app to be ready
COUNTER=1
while [ "$(./bin/kots get apps --namespace "$KOTS_NAMESPACE" | awk 'NR>1{print $2}')" != "ready" ]; do
((COUNTER += 1))
if [ $COUNTER -gt 120 ]; then
echo "Timed out waiting for app to be ready"
./bin/kots get apps --namespace "$KOTS_NAMESPACE"
echo "kotsadm logs:"
kubectl logs -l app=kotsadm --tail=100 --namespace "$KOTS_NAMESPACE"
exit 1
fi
sleep 1
done
# get the version of the replicated-sdk that is running and set it as an output
REPLICATED_SDK_VERSION=$(kubectl get deploy replicated -n "$KOTS_NAMESPACE" -o jsonpath='{.spec.template.spec.containers[0].image}' | grep -oE '[^:]+$')
echo "replicated-sdk-version=$REPLICATED_SDK_VERSION" >> "$GITHUB_OUTPUT"
- run: rm -rf ./replicated-sdk
- name: Checkout replicated-sdk
uses: actions/checkout@v4
with:
repository: replicatedhq/replicated-sdk
path: replicated-sdk
ref: ${{ steps.replicated-sdk-subchart-native-helm-v1.outputs.replicated-sdk-version }}
- name: Validate endpoints
uses: ./replicated-sdk/.github/actions/validate-endpoints
with:
license-id: ${{ steps.replicated-sdk-subchart-native-helm-v1.outputs.license-id }}
license-fields: '[{"name":"expires_at","value": ""}]'
integration-enabled: true
namespace: "$KOTS_NAMESPACE"
- name: remove replicated-sdk-subchart-native-helm-v1 app
env:
APP_SLUG: replicated-sdk-subchart-native-helm-v1
run: |
# remove the app
./bin/kots remove "$APP_SLUG" -n "$KOTS_NAMESPACE" --undeploy
# validate that the app reference was removed
if [ "$(./bin/kots get apps --namespace "$KOTS_NAMESPACE" --output=json | tr -d '\n')" != "[]" ]; then
printf "App reference was not removed\n\n"
exit 1
fi
- name: run replicated-sdk-subchart-replicated-helm test
id: replicated-sdk-subchart-replicated-helm
env:
APP_SLUG: replicated-sdk-subchart-replicated-helm
run: |
set +e
echo ${{ secrets.REPLICATED_SDK_SUBCHART_REPLICATED_HELM }} | base64 -d > license.yaml
LICENSE_ID="$(grep -oP 'licenseID:\s*\K\w+' license.yaml)"
echo "license-id=$LICENSE_ID" >> "$GITHUB_OUTPUT"
./bin/kots \
install "$APP_SLUG/automated" \
--license-file license.yaml \
--no-port-forward \
--namespace "$KOTS_NAMESPACE" \
--shared-password password \
--kotsadm-registry ttl.sh \
--kotsadm-namespace automated-${{ github.run_id }} \
--kotsadm-tag 24h
EXIT_CODE=$?
if [ $EXIT_CODE -ne 0 ]; then
echo "------pods:"
kubectl -n "$KOTS_NAMESPACE" get pods
echo "------kotsadm logs"
kubectl logs -l app=kotsadm --tail=100 --namespace "$KOTS_NAMESPACE"
exit $EXIT_CODE
fi
# wait for the app to be ready
COUNTER=1
while [ "$(./bin/kots get apps --namespace "$KOTS_NAMESPACE" | awk 'NR>1{print $2}')" != "ready" ]; do
((COUNTER += 1))
if [ $COUNTER -gt 120 ]; then
echo "Timed out waiting for app to be ready"
./bin/kots get apps --namespace "$KOTS_NAMESPACE"
echo "kotsadm logs:"
kubectl logs -l app=kotsadm --tail=100 --namespace "$KOTS_NAMESPACE"
exit 1
fi
sleep 1
done
# get the version of the replicated-sdk that is running and set it as an output
REPLICATED_SDK_VERSION=$(kubectl get deploy replicated -n "$KOTS_NAMESPACE" -o jsonpath='{.spec.template.spec.containers[0].image}' | grep -oE '[^:]+$')
echo "replicated-sdk-version=$REPLICATED_SDK_VERSION" >> "$GITHUB_OUTPUT"
- run: rm -rf ./replicated-sdk
- name: Checkout replicated-sdk
uses: actions/checkout@v4
with:
repository: replicatedhq/replicated-sdk
path: replicated-sdk
ref: ${{ steps.replicated-sdk-subchart-replicated-helm.outputs.replicated-sdk-version }}
- name: Validate endpoints
uses: ./replicated-sdk/.github/actions/validate-endpoints
with:
license-id: ${{ steps.replicated-sdk-subchart-replicated-helm.outputs.license-id }}
license-fields: '[{"name":"expires_at","value": ""}]'
integration-enabled: true
namespace: "$KOTS_NAMESPACE"
deployed-via-kubectl: true
- name: remove replicated-sdk-subchart-replicated-helm app
env:
APP_SLUG: replicated-sdk-subchart-replicated-helm
run: |
# remove the app
./bin/kots remove "$APP_SLUG" -n "$KOTS_NAMESPACE" --undeploy
# validate that the app reference was removed
if [ "$(./bin/kots get apps --namespace "$KOTS_NAMESPACE" --output=json | tr -d '\n')" != "[]" ]; then
printf "App reference was not removed\n\n"
exit 1
fi
- name: Generate support bundle on failure
if: failure()
uses: ./.github/actions/generate-support-bundle
with:
kots-namespace: "$APP_SLUG"
artifact-name: ${{ github.job }}-${{ matrix.cluster.distribution }}-${{ matrix.cluster.version }}-support-bundle
- name: Remove Cluster
id: remove-cluster
uses: replicatedhq/replicated-actions/remove-cluster@v1
if: ${{ always() && steps.create-cluster.outputs.cluster-id != '' }}
continue-on-error: true
with:
api-token: ${{ secrets.C11Y_MATRIX_TOKEN }}
cluster-id: ${{ steps.create-cluster.outputs.cluster-id }}
validate-support-bundle:
runs-on: ubuntu-20.04
needs: [ enable-tests, can-run-ci, build-kots, build-kotsadm, build-e2e, build-kurl-proxy, build-migrations, push-minio, push-rqlite ]
strategy:
fail-fast: false
matrix:
cluster: [
{distribution: kind, version: v1.28.0},
{distribution: openshift, version: 4.15.0-okd}
]
steps:
- name: Checkout
uses: actions/checkout@v4
- name: download e2e deps
uses: actions/download-artifact@v4
with:
name: e2e
path: e2e/bin/
- run: docker load -i e2e/bin/e2e-deps.tar
- run: chmod +x e2e/bin/*
- name: download kots binary
uses: actions/download-artifact@v4
with:
name: kots
path: bin/
- run: chmod +x bin/*
- uses: ./.github/actions/kots-e2e
with:
test-id: '@support-bundle'
kots-namespace: 'support-bundle'
k8s-distribution: ${{ matrix.cluster.distribution }}
k8s-version: ${{ matrix.cluster.version }}
testim-access-token: '${{ secrets.TESTIM_ACCESS_TOKEN }}'
testim-branch: ${{ github.head_ref == 'main' && 'master' || github.head_ref }}
replicated-api-token: '${{ secrets.C11Y_MATRIX_TOKEN }}'
kots-dockerhub-username: '${{ secrets.E2E_DOCKERHUB_USERNAME }}'
kots-dockerhub-password: '${{ secrets.E2E_DOCKERHUB_PASSWORD }}'
validate-gitops:
runs-on: ubuntu-20.04
needs: [ enable-tests, can-run-ci, build-kots, build-kotsadm, build-e2e, build-kurl-proxy, build-migrations, push-minio, push-rqlite ]
strategy:
fail-fast: false
matrix:
cluster: [
{distribution: kind, version: v1.28.0}
]
steps:
- name: Checkout
uses: actions/checkout@v4
- name: download e2e deps
uses: actions/download-artifact@v4
with:
name: e2e
path: e2e/bin/
- run: docker load -i e2e/bin/e2e-deps.tar
- run: chmod +x e2e/bin/*
- name: download kots binary
uses: actions/download-artifact@v4
with:
name: kots
path: bin/
- run: chmod +x bin/*
- uses: ./.github/actions/kots-e2e
with:
test-id: '@gitops'
kots-namespace: 'gitops'
k8s-distribution: ${{ matrix.cluster.distribution }}
k8s-version: ${{ matrix.cluster.version }}
testim-access-token: '${{ secrets.TESTIM_ACCESS_TOKEN }}'
testim-branch: ${{ github.head_ref == 'main' && 'master' || github.head_ref }}
replicated-api-token: '${{ secrets.C11Y_MATRIX_TOKEN }}'
kots-dockerhub-username: '${{ secrets.E2E_DOCKERHUB_USERNAME }}'
kots-dockerhub-password: '${{ secrets.E2E_DOCKERHUB_PASSWORD }}'
validate-get-set-config:
runs-on: ubuntu-20.04
needs: [ enable-tests, can-run-ci, build-kots, build-kotsadm, build-kurl-proxy, build-migrations, push-minio, push-rqlite ]
strategy:
fail-fast: false
matrix:
cluster: [
{distribution: kind, version: v1.28.0}
]
env:
APP_SLUG: get-set-config
steps:
- name: Checkout
uses: actions/checkout@v4
- name: Create Cluster
id: create-cluster
uses: replicatedhq/replicated-actions/create-cluster@v1
with:
api-token: ${{ secrets.C11Y_MATRIX_TOKEN }}
kubernetes-distribution: ${{ matrix.cluster.distribution }}
kubernetes-version: ${{ matrix.cluster.version }}
cluster-name: automated-kots-${{ github.run_id }}-${{ matrix.cluster.distribution }}-${{ matrix.cluster.version }}
timeout-minutes: '120'
ttl: 2h
export-kubeconfig: true
- name: download kots binary
uses: actions/download-artifact@v4
with:
name: kots
path: bin/
- run: chmod +x bin/kots
- name: create namespace and dockerhub secret
run: |
kubectl create ns "$APP_SLUG"
kubectl create secret docker-registry kotsadm-dockerhub --docker-server index.docker.io --docker-username "${{ secrets.E2E_DOCKERHUB_USERNAME }}" --docker-password "${{ secrets.E2E_DOCKERHUB_PASSWORD }}" --namespace "$APP_SLUG"
- name: install yq
run: |
sudo wget https://github.com/mikefarah/yq/releases/latest/download/yq_linux_amd64 -O /usr/bin/yq
sudo chmod +x /usr/bin/yq
- name: run the test
run: |
set -e
echo ${{ secrets.GET_SET_CONFIG_LICENSE }} | base64 -d > license.yaml
./bin/kots \
install "$APP_SLUG/automated" \
--license-file license.yaml \
--no-port-forward \
--namespace "$APP_SLUG" \
--shared-password password \
--kotsadm-registry ttl.sh \
--kotsadm-namespace automated-${{ github.run_id }} \
--kotsadm-tag 24h
function validate_configmap {
local key="$1"
local expected_value="$2"
if [ "$(kubectl get configmap config-values -n "$APP_SLUG" -o jsonpath="{.data.$key}")" != "$expected_value" ]; then
printf "expected %s value in configmap to be %s. got:\n\n" "$key" "$expected_value"
kubectl get configmap config-values -n "$APP_SLUG" -oyaml
exit 1
fi
}
function validate_configvalues {
local config_values="$1"
local key="$2"
local expected_default="$3"
local expected_value="$4"
if [ "$(echo "$config_values" | yq -r ".spec.values.$key.default")" != "$expected_default" ]; then
printf "expected %s default in configvalues to be %s. got:\n\n" "$key" "$expected_default"
echo "$config_values"
exit 1
fi
if [ "$(echo "$config_values" | yq -r ".spec.values.$key.value")" != "$expected_value" ]; then
printf "expected %s value in configvalues to be %s. got:\n\n" "$key" "$expected_value"
echo "$config_values"
exit 1
fi
}
# give time for initial configmap to be created/deployed
sleep 5
validate_configmap "username" ""
validate_configmap "email" ""
validate_configmap "password" ""
validate_configmap "sequence" "0"
./bin/kots set config "$APP_SLUG" --key=password --value=example-password --namespace "$APP_SLUG" # don't deploy
sleep 5
validate_configmap "username" ""
validate_configmap "password" ""
validate_configmap "email" ""
validate_configmap "sequence" "0"
./bin/kots set config "$APP_SLUG" --key=username --value=example-username --namespace "$APP_SLUG" --deploy
sleep 5
validate_configmap "username" "example-username"
validate_configmap "password" "example-password"
validate_configmap "email" ""
validate_configmap "sequence" "2"
./bin/kots set config "$APP_SLUG" --key=email --value=example-email --namespace "$APP_SLUG" # don't deploy
sleep 5
validate_configmap "username" "example-username"
validate_configmap "password" "example-password"
validate_configmap "email" ""
validate_configmap "sequence" "2"
# validate getting config values (returned sequence is +1 for some reason :shrug:)
config_values=$(./bin/kots get config "$APP_SLUG" --namespace "$APP_SLUG" --decrypt --sequence=0)
validate_configvalues "$config_values" "username" "null" "null"
validate_configvalues "$config_values" "password" "null" "null"
validate_configvalues "$config_values" "email" "null" "null"
validate_configvalues "$config_values" "sequence" "1" "null"
config_values=$(./bin/kots get config "$APP_SLUG" --namespace "$APP_SLUG" --decrypt --sequence=1)
validate_configvalues "$config_values" "username" "null" "null"
validate_configvalues "$config_values" "password" "null" "example-password"
validate_configvalues "$config_values" "email" "null" "null"
validate_configvalues "$config_values" "sequence" "2" "null"
config_values=$(./bin/kots get config "$APP_SLUG" --namespace "$APP_SLUG" --decrypt --sequence=2)
validate_configvalues "$config_values" "username" "null" "example-username"
validate_configvalues "$config_values" "password" "null" "example-password"
validate_configvalues "$config_values" "email" "null" "null"
validate_configvalues "$config_values" "sequence" "3" "null"
config_values=$(./bin/kots get config "$APP_SLUG" --namespace "$APP_SLUG" --decrypt --sequence=3)
validate_configvalues "$config_values" "username" "null" "example-username"
validate_configvalues "$config_values" "password" "null" "example-password"
validate_configvalues "$config_values" "email" "null" "example-email"
validate_configvalues "$config_values" "sequence" "4" "null"
config_values=$(./bin/kots get config "$APP_SLUG" --namespace "$APP_SLUG" --decrypt) # latest sequence
validate_configvalues "$config_values" "username" "null" "example-username"
validate_configvalues "$config_values" "password" "null" "example-password"
validate_configvalues "$config_values" "email" "null" "example-email"
validate_configvalues "$config_values" "sequence" "4" "null"
config_values=$(./bin/kots get config "$APP_SLUG" --namespace "$APP_SLUG" --decrypt --current) # currently deployed sequence
validate_configvalues "$config_values" "username" "null" "example-username"
validate_configvalues "$config_values" "password" "null" "example-password"
validate_configvalues "$config_values" "email" "null" "null"
validate_configvalues "$config_values" "sequence" "3" "null"
# validate updating currently deployed config
./bin/kots set config "$APP_SLUG" --key=password --value=updated-password --namespace "$APP_SLUG" --current --deploy
sleep 5
validate_configmap "username" "example-username"
validate_configmap "password" "updated-password"
validate_configmap "email" ""
validate_configmap "sequence" "4"
# validate updating specific sequence
./bin/kots set config "$APP_SLUG" --key=username --value=updated-username --namespace "$APP_SLUG" --sequence=0 --deploy
sleep 5
validate_configmap "username" "updated-username"
validate_configmap "password" ""
validate_configmap "email" ""
validate_configmap "sequence" "5"
# should not be able to use --current and --sequence together
if ./bin/kots get config "$APP_SLUG" --namespace "$APP_SLUG" --decrypt --sequence=0 --current; then
echo "expected error when using --current and --sequence together in get config"
exit 1
fi
if ./bin/kots set config "$APP_SLUG" --key=username --value=updated-username --namespace "$APP_SLUG" --sequence=0 --current --deploy; then
echo "expected error when using --current and --sequence together in set config"
exit 1
fi
# ---- validate archives ---- #
function validate_configmap_in_archive {
local expected_value="$1"
if ! grep -q "$expected_value" get-set-config/base/configmap.yaml; then
echo "expected base/configmap.yaml to contain $expected_value:"
cat get-set-config/base/configmap.yaml
exit 1
fi
}
# make latest different from current
./bin/kots set config "$APP_SLUG" --key=username --value=latest-username --namespace "$APP_SLUG"
# validate the archive for sequence 0
./bin/kots download --namespace "$APP_SLUG" --slug "$APP_SLUG" --sequence=0 --decrypt-password-values --overwrite
validate_configmap_in_archive "username: ''"
validate_configmap_in_archive "password: ''"
validate_configmap_in_archive "email: ''"
validate_configmap_in_archive "sequence: '0'"
# validate the archive for sequence 2
./bin/kots download --namespace "$APP_SLUG" --slug "$APP_SLUG" --sequence=2 --decrypt-password-values --overwrite
validate_configmap_in_archive "username: 'example-username'"
validate_configmap_in_archive "password: 'example-password'"
validate_configmap_in_archive "email: ''"
validate_configmap_in_archive "sequence: '2'"
# validate the archive for the currently deployed version
./bin/kots download --namespace "$APP_SLUG" --slug "$APP_SLUG" --current --decrypt-password-values --overwrite
validate_configmap_in_archive "username: 'updated-username'"
validate_configmap_in_archive "password: ''"
validate_configmap_in_archive "email: ''"
validate_configmap_in_archive "sequence: '5'"
# validate the archive for the latest version
./bin/kots download --namespace "$APP_SLUG" --slug "$APP_SLUG" --decrypt-password-values --overwrite
validate_configmap_in_archive "username: 'latest-username'"
validate_configmap_in_archive "password: ''"
validate_configmap_in_archive "email: ''"
validate_configmap_in_archive "sequence: '6'"
- name: Generate support bundle on failure
if: failure()
uses: ./.github/actions/generate-support-bundle
with:
kots-namespace: "$APP_SLUG"
artifact-name: ${{ github.job }}-${{ matrix.cluster.distribution }}-${{ matrix.cluster.version }}-support-bundle
- name: Remove Cluster
id: remove-cluster
uses: replicatedhq/replicated-actions/remove-cluster@v1
if: ${{ always() && steps.create-cluster.outputs.cluster-id != '' }}
continue-on-error: true
with:
api-token: ${{ secrets.C11Y_MATRIX_TOKEN }}
cluster-id: ${{ steps.create-cluster.outputs.cluster-id }}
validate-custom-cas:
runs-on: ubuntu-20.04
needs: [ enable-tests, can-run-ci, build-kots, build-kotsadm, build-kurl-proxy, build-migrations, push-minio, push-rqlite ]
strategy:
fail-fast: false
matrix:
cluster: [
{distribution: kind, version: v1.28.0}
]
env:
APP_SLUG: get-set-config
steps:
- name: Checkout
uses: actions/checkout@v4
- name: Create Cluster
id: create-cluster
uses: replicatedhq/replicated-actions/create-cluster@v1
with:
api-token: ${{ secrets.C11Y_MATRIX_TOKEN }}
kubernetes-distribution: ${{ matrix.cluster.distribution }}
kubernetes-version: ${{ matrix.cluster.version }}
cluster-name: automated-kots-${{ github.run_id }}-${{ matrix.cluster.distribution }}-${{ matrix.cluster.version }}
timeout-minutes: '120'
ttl: 2h
export-kubeconfig: true
- name: download kots binary
uses: actions/download-artifact@v4
with:
name: kots
path: bin/
- run: chmod +x bin/kots
- name: create namespace and dockerhub secret
run: |
kubectl create ns "$APP_SLUG"
kubectl create secret docker-registry kotsadm-dockerhub --docker-server index.docker.io --docker-username "${{ secrets.E2E_DOCKERHUB_USERNAME }}" --docker-password "${{ secrets.E2E_DOCKERHUB_PASSWORD }}" --namespace "$APP_SLUG"
- name: install yq
run: |
sudo wget https://github.com/mikefarah/yq/releases/latest/download/yq_linux_amd64 -O /usr/bin/yq
sudo chmod +x /usr/bin/yq
- name: run the test
run: |
set -e
echo ${{ secrets.GET_SET_CONFIG_LICENSE }} | base64 -d > license.yaml
echo "test value" > ./ca.crt
kubectl create configmap -n "$APP_SLUG" custom-cas --from-file=ca.crt=./ca.crt
./bin/kots \
install "$APP_SLUG/automated" \
--license-file license.yaml \
--no-port-forward \
--namespace "$APP_SLUG" \
--shared-password password \
--kotsadm-registry ttl.sh \
--kotsadm-namespace automated-${{ github.run_id }} \
--private-ca-configmap custom-cas \
--kotsadm-tag 24h
echo "exec into the deployment and check for the file and its contents"
if ! kubectl exec -n "$APP_SLUG" deployment/kotsadm -- cat /certs/ca.crt | grep "test value"; then
echo "expected /certs/ca.crt to contain 'test value'"
kubectl exec -n "$APP_SLUG" deployment/kotsadm -- cat /certs/ca.crt
exit 1
fi
echo "check that the deployment has an environment variable pointing to the file"
if ! kubectl exec -n "$APP_SLUG" deployment/kotsadm -- env | grep "SSL_CERT_DIR" | grep "/certs"; then
echo "expected env output to contain SSL_CERT_DIR=/certs"
kubectl exec -n "$APP_SLUG" deployment/kotsadm -- env
exit 1
fi
echo "check that the deployment has an environment variable with the configmap name"
if ! kubectl exec -n "$APP_SLUG" deployment/kotsadm -- env | grep "SSL_CERT_CONFIGMAP" | grep "custom-cas"; then
echo "expected env output to contain SSL_CERT_CONFIGMAP=custom-cas"
kubectl exec -n "$APP_SLUG" deployment/kotsadm -- env
exit 1
fi
./bin/kots admin-console generate-manifests -n "$APP_SLUG" --shared-password password --private-ca-configmap generated-custom-cas
ls ./admin-console
if ! grep SSL_CERT_CONFIGMAP < ./admin-console/kotsadm-deployment.yaml; then
echo "expected generated kotsadm-deployment.yaml to contain SSL_CERT_CONFIGMAP"
cat ./admin-console/kotsadm-deployment.yaml
exit 1
fi
if ! grep generated-custom-cas < ./admin-console/kotsadm-deployment.yaml; then
echo "expected generated kotsadm-deployment.yaml to contain generated-custom-cas"
cat ./admin-console/kotsadm-deployment.yaml
exit 1
fi
- name: Generate support bundle on failure
if: failure()
uses: ./.github/actions/generate-support-bundle
with:
kots-namespace: "$APP_SLUG"
artifact-name: ${{ github.job }}-${{ matrix.cluster.distribution }}-${{ matrix.cluster.version }}-support-bundle
- name: Remove Cluster
id: remove-cluster
uses: replicatedhq/replicated-actions/remove-cluster@v1
if: ${{ always() && steps.create-cluster.outputs.cluster-id != '' }}
continue-on-error: true
with:
api-token: ${{ secrets.C11Y_MATRIX_TOKEN }}
cluster-id: ${{ steps.create-cluster.outputs.cluster-id }}
validate-pr-tests:
runs-on: ubuntu-20.04
needs:
# static and unit tests
- lint-web
- unit-test-web
- vet-kots
- ci-test-kots
# testim tests
- validate-existing-online-install-minimal
- validate-version-history-pagination
- validate-min-kots-version
- validate-target-kots-version
- validate-range-kots-version
- validate-airgap-smoke-test
- validate-support-bundle
- validate-gitops
# playwright tests
- validate-smoke-test
- validate-backup-and-restore
- validate-no-required-config
- validate-config
- validate-change-channel
- validate-multi-app-backup-and-restore
- validate-multi-app-install
- validate-change-license
# non-testim tests
- validate-minimal-rbac
- validate-minimal-rbac-override
- validate-multi-namespace
- validate-kots-pull
- validate-app-version-label
- validate-helm-install-order
- validate-no-redeploy-on-restart
- validate-kubernetes-installer-preflight
- validate-kots-upgrade
- validate-remove-app
- validate-registry-check
- validate-kots-helm-release-secret-migration
- validate-native-helm-v2
- validate-deployment-orchestration
- validate-replicated-sdk
- validate-strict-preflight-checks
- validate-get-set-config
- validate-custom-cas
# cli-only tests
- validate-kots-push-images-anonymous
steps:
- run: echo "All PR tests passed"
# this job will validate that the kurl add-on validation did not fail and that all pr-tests succeed
# it is used for the github branch protection rule
validate-success:
runs-on: ubuntu-20.04
needs:
- validate-kurl-addon
- validate-pr-tests
if: always()
steps:
# https://docs.github.com/en/actions/learn-github-actions/contexts#needs-context
# if the validate-kurl-addon job failed or was cancelled, this job will fail. it's ok if this job was skipped
- name: fail if validate-kurl-addon job failed
if: needs.validate-kurl-addon.result == 'failure' || needs.validate-kurl-addon.result == 'cancelled'
run: exit 1
# if the validate-pr-tests job was not successful, this job will fail
- name: fail if validate-pr-tests job was not successful
if: needs.validate-pr-tests.result != 'success'
run: exit 1
# if the validate-pr-tests job was successful, this job will succeed
- name: succeed if validate-pr-tests job succeeded
if: needs.validate-pr-tests.result == 'success'
run: echo "Validation succeeded"