Splitting Operator UI Tests for faster execution (#2366)

This commit is contained in:
Cesar Celis Hernandez
2022-10-07 16:42:44 -04:00
committed by GitHub
parent 48b467a683
commit 43db7729c4
6 changed files with 1804 additions and 26 deletions

View File

@@ -1348,8 +1348,8 @@ jobs:
run: |
make cleanup-permissions
all-operator-tests:
name: Operator UI Tests
all-operator-tests-1:
name: Operator UI Tests Part 1
needs:
- lint-job
- no-warnings-and-make-assets
@@ -1440,7 +1440,383 @@ jobs:
- name: Run TestCafe Tests
uses: DevExpress/testcafe-action@latest
with:
args: '"chrome:headless" portal-ui/tests/operator/ --skip-js-errors -c 3'
args: '"chrome:headless" portal-ui/tests/operator/login --skip-js-errors -c 3'
all-operator-tests-2:
name: Operator UI Tests Part 2
needs:
- lint-job
- no-warnings-and-make-assets
- reuse-golang-dependencies
- vulnerable-dependencies-checks
- semgrep-static-code-analysis
runs-on: ${{ matrix.os }}
strategy:
matrix:
go-version: [ 1.18.x ]
os: [ ubuntu-latest ]
steps:
- name: Set up Go ${{ matrix.go-version }} on ${{ matrix.os }}
uses: actions/setup-go@v2
with:
go-version: ${{ matrix.go-version }}
id: go
- name: Check out code into the Go module directory
uses: actions/checkout@v2
# To build operator image, we need to clone the repository first
- name: clone https://github.com/minio/operator
uses: actions/checkout@master
with:
# Repository name with owner. For example, actions/checkout
# Default: ${{ github.repository }}
repository: minio/operator
# Relative path under $GITHUB_WORKSPACE to place the repository
# To have two repositories under the same test
path: 'operator_repository'
- name: Read .nvmrc
id: node_version
run: echo ::set-output name=NVMRC::$(cat .nvmrc)
- uses: actions/setup-node@v2
with:
node-version: ${{ env.NVMRC }}
- uses: actions/cache@v2
name: Go Mod Cache
with:
path: |
~/.cache/go-build
~/go/pkg/mod
key: ${{ runner.os }}-go-${{ github.run_id }}
- name: Get yarn cache directory path
id: yarn-cache-dir-path
run: echo "::set-output name=dir::$(yarn cache dir)"
- uses: actions/cache@v2
id: yarn-cache
name: Yarn Cache
with:
path: |
${{ steps.yarn-cache-dir-path.outputs.dir }}
./portal-ui/node_modules/
key: ${{ runner.os }}-yarn-${{ hashFiles('./portal-ui/yarn.lock') }}
restore-keys: |
${{ runner.os }}-yarn-
- uses: actions/cache@v2
id: assets-cache
name: Assets Cache
with:
path: |
./portal-ui/build/
key: ${{ runner.os }}-assets-${{ github.run_id }}
restore-keys: |
${{ runner.os }}-assets-
- name: Build Console on ${{ matrix.os }}
env:
GO111MODULE: on
GOOS: linux
run: |
make console
# Runs a set of commands using the runners shell
- name: Start Kind for Operator UI
run: |
"${GITHUB_WORKSPACE}/portal-ui/tests/scripts/operator.sh"
- name: Run TestCafe Tests
uses: DevExpress/testcafe-action@latest
with:
args: '"chrome:headless" portal-ui/tests/operator/tenant/test-1 --skip-js-errors -c 3'
all-operator-tests-3:
name: Operator UI Tests Part 3
needs:
- lint-job
- no-warnings-and-make-assets
- reuse-golang-dependencies
- vulnerable-dependencies-checks
- semgrep-static-code-analysis
runs-on: ${{ matrix.os }}
strategy:
matrix:
go-version: [ 1.18.x ]
os: [ ubuntu-latest ]
steps:
- name: Set up Go ${{ matrix.go-version }} on ${{ matrix.os }}
uses: actions/setup-go@v2
with:
go-version: ${{ matrix.go-version }}
id: go
- name: Check out code into the Go module directory
uses: actions/checkout@v2
# To build operator image, we need to clone the repository first
- name: clone https://github.com/minio/operator
uses: actions/checkout@master
with:
# Repository name with owner. For example, actions/checkout
# Default: ${{ github.repository }}
repository: minio/operator
# Relative path under $GITHUB_WORKSPACE to place the repository
# To have two repositories under the same test
path: 'operator_repository'
- name: Read .nvmrc
id: node_version
run: echo ::set-output name=NVMRC::$(cat .nvmrc)
- uses: actions/setup-node@v2
with:
node-version: ${{ env.NVMRC }}
- uses: actions/cache@v2
name: Go Mod Cache
with:
path: |
~/.cache/go-build
~/go/pkg/mod
key: ${{ runner.os }}-go-${{ github.run_id }}
- name: Get yarn cache directory path
id: yarn-cache-dir-path
run: echo "::set-output name=dir::$(yarn cache dir)"
- uses: actions/cache@v2
id: yarn-cache
name: Yarn Cache
with:
path: |
${{ steps.yarn-cache-dir-path.outputs.dir }}
./portal-ui/node_modules/
key: ${{ runner.os }}-yarn-${{ hashFiles('./portal-ui/yarn.lock') }}
restore-keys: |
${{ runner.os }}-yarn-
- uses: actions/cache@v2
id: assets-cache
name: Assets Cache
with:
path: |
./portal-ui/build/
key: ${{ runner.os }}-assets-${{ github.run_id }}
restore-keys: |
${{ runner.os }}-assets-
- name: Build Console on ${{ matrix.os }}
env:
GO111MODULE: on
GOOS: linux
run: |
make console
# Runs a set of commands using the runners shell
- name: Start Kind for Operator UI
run: |
"${GITHUB_WORKSPACE}/portal-ui/tests/scripts/operator.sh"
- name: Run TestCafe Tests
uses: DevExpress/testcafe-action@latest
with:
args: '"chrome:headless" portal-ui/tests/operator/tenant/test-2 --skip-js-errors -c 3'
all-operator-tests-4:
name: Operator UI Tests Part 4
needs:
- lint-job
- no-warnings-and-make-assets
- reuse-golang-dependencies
- vulnerable-dependencies-checks
- semgrep-static-code-analysis
runs-on: ${{ matrix.os }}
strategy:
matrix:
go-version: [ 1.18.x ]
os: [ ubuntu-latest ]
steps:
- name: Set up Go ${{ matrix.go-version }} on ${{ matrix.os }}
uses: actions/setup-go@v2
with:
go-version: ${{ matrix.go-version }}
id: go
- name: Check out code into the Go module directory
uses: actions/checkout@v2
# To build operator image, we need to clone the repository first
- name: clone https://github.com/minio/operator
uses: actions/checkout@master
with:
# Repository name with owner. For example, actions/checkout
# Default: ${{ github.repository }}
repository: minio/operator
# Relative path under $GITHUB_WORKSPACE to place the repository
# To have two repositories under the same test
path: 'operator_repository'
- name: Read .nvmrc
id: node_version
run: echo ::set-output name=NVMRC::$(cat .nvmrc)
- uses: actions/setup-node@v2
with:
node-version: ${{ env.NVMRC }}
- uses: actions/cache@v2
name: Go Mod Cache
with:
path: |
~/.cache/go-build
~/go/pkg/mod
key: ${{ runner.os }}-go-${{ github.run_id }}
- name: Get yarn cache directory path
id: yarn-cache-dir-path
run: echo "::set-output name=dir::$(yarn cache dir)"
- uses: actions/cache@v2
id: yarn-cache
name: Yarn Cache
with:
path: |
${{ steps.yarn-cache-dir-path.outputs.dir }}
./portal-ui/node_modules/
key: ${{ runner.os }}-yarn-${{ hashFiles('./portal-ui/yarn.lock') }}
restore-keys: |
${{ runner.os }}-yarn-
- uses: actions/cache@v2
id: assets-cache
name: Assets Cache
with:
path: |
./portal-ui/build/
key: ${{ runner.os }}-assets-${{ github.run_id }}
restore-keys: |
${{ runner.os }}-assets-
- name: Build Console on ${{ matrix.os }}
env:
GO111MODULE: on
GOOS: linux
run: |
make console
# Runs a set of commands using the runners shell
- name: Start Kind for Operator UI
run: |
"${GITHUB_WORKSPACE}/portal-ui/tests/scripts/operator.sh"
- name: Run TestCafe Tests
uses: DevExpress/testcafe-action@latest
with:
args: '"chrome:headless" portal-ui/tests/operator/tenant/test-3 --skip-js-errors -c 3'
all-operator-tests-5:
name: Operator UI Tests Part 5
needs:
- lint-job
- no-warnings-and-make-assets
- reuse-golang-dependencies
- vulnerable-dependencies-checks
- semgrep-static-code-analysis
runs-on: ${{ matrix.os }}
strategy:
matrix:
go-version: [ 1.18.x ]
os: [ ubuntu-latest ]
steps:
- name: Set up Go ${{ matrix.go-version }} on ${{ matrix.os }}
uses: actions/setup-go@v2
with:
go-version: ${{ matrix.go-version }}
id: go
- name: Check out code into the Go module directory
uses: actions/checkout@v2
# To build operator image, we need to clone the repository first
- name: clone https://github.com/minio/operator
uses: actions/checkout@master
with:
# Repository name with owner. For example, actions/checkout
# Default: ${{ github.repository }}
repository: minio/operator
# Relative path under $GITHUB_WORKSPACE to place the repository
# To have two repositories under the same test
path: 'operator_repository'
- name: Read .nvmrc
id: node_version
run: echo ::set-output name=NVMRC::$(cat .nvmrc)
- uses: actions/setup-node@v2
with:
node-version: ${{ env.NVMRC }}
- uses: actions/cache@v2
name: Go Mod Cache
with:
path: |
~/.cache/go-build
~/go/pkg/mod
key: ${{ runner.os }}-go-${{ github.run_id }}
- name: Get yarn cache directory path
id: yarn-cache-dir-path
run: echo "::set-output name=dir::$(yarn cache dir)"
- uses: actions/cache@v2
id: yarn-cache
name: Yarn Cache
with:
path: |
${{ steps.yarn-cache-dir-path.outputs.dir }}
./portal-ui/node_modules/
key: ${{ runner.os }}-yarn-${{ hashFiles('./portal-ui/yarn.lock') }}
restore-keys: |
${{ runner.os }}-yarn-
- uses: actions/cache@v2
id: assets-cache
name: Assets Cache
with:
path: |
./portal-ui/build/
key: ${{ runner.os }}-assets-${{ github.run_id }}
restore-keys: |
${{ runner.os }}-assets-
- name: Build Console on ${{ matrix.os }}
env:
GO111MODULE: on
GOOS: linux
run: |
make console
# Runs a set of commands using the runners shell
- name: Start Kind for Operator UI
run: |
"${GITHUB_WORKSPACE}/portal-ui/tests/scripts/operator.sh"
- name: Run TestCafe Tests
uses: DevExpress/testcafe-action@latest
with:
args: '"chrome:headless" portal-ui/tests/operator/tenant/test-4 --skip-js-errors -c 3'
compile-job:
name: Compiles on Go ${{ matrix.go-version }} and ${{ matrix.os }}

View File

@@ -14,9 +14,9 @@
// You should have received a copy of the GNU Affero General Public License
// along with this program. If not, see <http://www.gnu.org/licenses/>.
import * as roles from "../utils/roles";
import * as elements from "../utils/elements";
import { diagnosticsElement, supportElement } from "../utils/elements-menu";
import * as roles from "../../utils/roles";
import * as elements from "../../utils/elements";
import { diagnosticsElement, supportElement } from "../../utils/elements-menu";
fixture("For user with default permissions").page("http://localhost:9090");

View File

@@ -28,10 +28,11 @@ import {
goToMonitoringSection,
goToLoggingSection,
goToLoggingDBSection,
} from "./utils";
} from "../../utils";
fixture("For user with default permissions").page("http://localhost:9090");
// Test 1
test("Create Tenant and List Tenants", async (t) => {
const tenantName = `tenant-${Math.floor(Math.random() * 10000)}`;
await loginToOperator();
@@ -39,6 +40,7 @@ test("Create Tenant and List Tenants", async (t) => {
await deleteTenant(tenantName);
});
// Test 2
test("Create Tenant Without Audit Log", async (t) => {
const tenantName = `tenant-${Math.floor(Math.random() * 10000)}`;
await loginToOperator();
@@ -46,6 +48,7 @@ test("Create Tenant Without Audit Log", async (t) => {
await deleteTenant(tenantName);
});
// Test 3
test("Test describe section for PODs in new tenant", async (t) => {
const tenantName = "storage-lite";
await loginToOperator();
@@ -76,6 +79,7 @@ const checkPodDescribeHasSections = async () => {
.ok();
};
// Test 4
test("Test describe section for PVCs in new tenant", async (t) => {
const tenantName = `storage-lite`;
await loginToOperator();
@@ -487,27 +491,9 @@ const checkLoggingDBFieldsAcceptValues = async (tenantName: string) => {
.ok();
};
// Test 5
test("Test Prometheus monitoring can be disabled and enabled", async (t) => {
const tenantName = `storage-lite`;
await loginToOperator();
await checkMonitoringToggle(tenantName);
});
test("Test Prometheus config fields can be edited and submitted", async (t) => {
const tenantName = `storage-lite`;
await loginToOperator();
await checkMonitoringFieldsAcceptValues(tenantName);
});
test("Test Audit Logging can be disabled and enabled", async (t) => {
const tenantName = `storage-lite`;
await loginToOperator();
await checkLoggingToggle(tenantName);
});
test("Test Audit Log config fields can be edited and submitted", async (t) => {
const tenantName = `storage-lite`;
await loginToOperator();
await checkLoggingFieldsAcceptValues(tenantName);
await checkLoggingDBFieldsAcceptValues(tenantName);
});

View File

@@ -0,0 +1,469 @@
// This file is part of MinIO Console Server
// Copyright (c) 2022 MinIO, Inc.
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU Affero General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU Affero General Public License for more details.
//
// You should have received a copy of the GNU Affero General Public License
// along with this program. If not, see <http://www.gnu.org/licenses/>.
import { t, Selector } from "testcafe";
import {
loginToOperator,
createTenant,
createTenantWithoutAuditLog,
deleteTenant,
redirectToTenantsList,
goToPodInTenant,
goToPodSection,
goToPvcInTenant,
goToPvcSection,
goToMonitoringSection,
goToLoggingSection,
goToLoggingDBSection,
} from "../../utils";
fixture("For user with default permissions").page("http://localhost:9090");
const testPODDescribe = async (tenantName: string) => {
await goToPodInTenant(tenantName);
await goToPodSection(1);
await checkPodDescribeHasSections();
};
const checkPodDescribeHasSections = async () => {
await t
.expect(Selector("#pod-describe-summary").exists)
.ok()
.expect(Selector("#pod-describe-annotations").exists)
.ok()
.expect(Selector("#pod-describe-labels").exists)
.ok()
.expect(Selector("#pod-describe-conditions").exists)
.ok()
.expect(Selector("#pod-describe-tolerations").exists)
.ok()
.expect(Selector("#pod-describe-volumes").exists)
.ok()
.expect(Selector("#pod-describe-containers").exists)
.ok();
};
const testPvcDescribe = async (tenantName: string) => {
await goToPvcInTenant(tenantName);
await goToPvcSection(1);
await checkPvcDescribeHasSections();
};
const checkPvcDescribeHasSections = async () => {
await t
.expect(Selector("#pvc-describe-summary").exists)
.ok()
.expect(Selector("#pvc-describe-annotations").exists)
.ok()
.expect(Selector("#pvc-describe-labels").exists)
.ok();
};
export const checkMonitoringToggle = async (tenantName: string) => {
await goToMonitoringSection(tenantName);
await t
.click("#tenant-monitoring")
.click("#confirm-ok")
.wait(1000)
.expect(Selector("#image").exists)
.notOk()
.click("#yaml_button")
.expect(Selector("#code_wrapper").exists)
.ok();
await t
.expect(
(await Selector("#code_wrapper").textContent).includes("prometheus:")
)
.notOk();
await t
.click(Selector(`a[href$="/monitoring"]`))
.click("#tenant-monitoring")
.click("#confirm-ok")
.wait(5000)
.expect(Selector("#prometheus_image").exists)
.ok()
.click("#yaml_button")
.expect(Selector("#code_wrapper").exists)
.ok();
await t
.expect(
(await Selector("#code_wrapper").textContent).includes("prometheus:")
)
.ok();
};
export const checkMonitoringFieldsAcceptValues = async (tenantName: string) => {
await goToMonitoringSection(tenantName);
await t
.typeText("#prometheus_image", "quay.io/prometheus/prometheus:latest", {
replace: true,
})
.typeText("#sidecarImage", "library/alpine:latest", { replace: true })
.typeText("#initImage", "library/busybox:1.33.1", { replace: true })
.typeText("#diskCapacityGB", "1", { replace: true })
.typeText("#cpuRequest", "1", { replace: true })
.typeText("#memRequest", "1", { replace: true })
.typeText("#serviceAccountName", "monitoringTestServiceAccountName", {
replace: true,
})
.typeText("#storageClassName", "monitoringTestStorageClassName", {
replace: true,
})
.typeText("#securityContext_runAsUser", "1212", { replace: true })
.typeText("#securityContext_runAsGroup", "3434", { replace: true })
.typeText("#securityContext_fsGroup", "5656", { replace: true })
.expect(Selector("#securityContext_runAsNonRoot").checked)
.ok()
.click("#securityContext_runAsNonRoot")
.expect(Selector("#securityContext_runAsNonRoot").checked)
.notOk()
.typeText("#key-Labels-0", "monitoringLabelKey0Test", { replace: true })
.typeText("#val-Labels-0", "monitoringLabelVal0Test", { replace: true })
.click("#add-Labels-0")
.typeText("#key-Annotations-0", "monitoringAnnotationsKey0Test", {
replace: true,
})
.typeText("#val-Annotations-0", "monitoringAnnotationsVal0Test", {
replace: true,
})
.click("#add-Annotations-0")
.typeText("#key-NodeSelector-0", "monitoringNodeSelectorKey0Test", {
replace: true,
})
.typeText("#val-NodeSelector-0", "monitoringNodeSelectorVal0Test", {
replace: true,
})
.click("#add-NodeSelector-0")
.expect(Selector("#key-Labels-1").exists)
.ok()
.expect(Selector("#key-Annotations-1").exists)
.ok()
.expect(Selector("#key-NodeSelector-1").exists)
.ok()
.click("#submit_button")
.click("#yaml_button")
.expect(Selector("#code_wrapper").exists)
.ok();
await t
.expect(
(
await Selector("#code_wrapper").textContent
).includes("image: quay.io/prometheus/prometheus:latest")
)
.ok()
.expect(
(
await Selector("#code_wrapper").textContent
).includes("initimage: library/busybox:1.33.1")
)
.ok()
.expect(
(
await Selector("#code_wrapper").textContent
).includes("diskCapacityGB: 1")
)
.ok()
.expect((await Selector("#code_wrapper").textContent).includes('cpu: "1"'))
.ok()
.expect(
(await Selector("#code_wrapper").textContent).includes("memory: 1Gi")
)
.ok()
.expect(
(
await Selector("#code_wrapper").textContent
).includes("serviceAccountName: monitoringTestServiceAccountName")
)
.ok()
.expect(
(
await Selector("#code_wrapper").textContent
).includes("sidecarimage: library/alpine:latest")
)
.ok()
.expect(
(
await Selector("#code_wrapper").textContent
).includes("storageClassName: monitoringTestStorageClassName")
)
.ok()
.expect(
(await Selector("#code_wrapper").textContent).includes("fsGroup: 5656")
)
.ok()
.expect(
(await Selector("#code_wrapper").textContent).includes("runAsGroup: 3434")
)
.ok()
.expect(
(await Selector("#code_wrapper").textContent).includes("runAsUser: 1212")
)
.ok()
.expect(
(
await Selector("#code_wrapper").textContent
).includes("monitoringAnnotationsKey0Test: monitoringAnnotationsVal0Test")
)
.ok()
.expect(
(
await Selector("#code_wrapper").textContent
).includes(
"monitoringNodeSelectorKey0Test: monitoringNodeSelectorVal0Test"
)
)
.ok()
.expect(
(
await Selector("#code_wrapper").textContent
).includes("monitoringLabelKey0Test: monitoringLabelVal0Test")
)
.ok();
};
const checkLoggingToggle = async (tenantName: string) => {
await goToLoggingSection(tenantName);
await t
.click("#tenant_logging")
.click("#confirm-ok")
.wait(3000)
.expect(Selector("#image").exists)
.notOk()
.click("#yaml_button")
.expect(Selector("#code_wrapper").exists)
.ok();
await t
.expect((await Selector("#code_wrapper").textContent).includes("log:"))
.notOk();
await t
.click(Selector(`a[href$="/logging"]`))
.click("#tenant_logging")
.click("#confirm-ok")
.wait(3000)
.expect(Selector("#image").exists)
.ok()
.click("#yaml_button")
.expect(Selector("#code_wrapper").exists)
.ok();
await t
.expect((await Selector("#code_wrapper").textContent).includes("log:"))
.ok();
};
const checkLoggingFieldsAcceptValues = async (tenantName: string) => {
await goToLoggingSection(tenantName);
await t
.wait(3000)
.typeText("#image", "minio/operator:v4.4.22", { replace: true })
.typeText("#diskCapacityGB", "3", { replace: true })
.typeText("#cpuRequest", "3", { replace: true })
.typeText("#memRequest", "3", { replace: true })
.typeText("#serviceAccountName", "loggingTestServiceAccountName", {
replace: true,
})
.typeText("#securityContext_runAsUser", "1111", { replace: true })
.typeText("#securityContext_runAsGroup", "2222", { replace: true })
.typeText("#securityContext_fsGroup", "3333", { replace: true })
.expect(Selector("#securityContext_runAsNonRoot").checked)
.notOk()
.click("#securityContext_runAsNonRoot")
.expect(Selector("#securityContext_runAsNonRoot").checked)
.ok()
.typeText("#key-Labels-0", "loggingLabelKey0Test", { replace: true })
.typeText("#val-Labels-0", "loggingLabelVal0Test", { replace: true })
.click("#add-Labels-0")
.typeText("#key-Annotations-0", "loggingAnnotationsKey0Test", {
replace: true,
})
.typeText("#val-Annotations-0", "loggingAnnotationsVal0Test", {
replace: true,
})
.click("#add-Annotations-0")
.typeText("#key-NodeSelector-0", "loggingNodeSelectorKey0Test", {
replace: true,
})
.typeText("#val-NodeSelector-0", "loggingNodeSelectorVal0Test", {
replace: true,
})
.click("#add-NodeSelector-0")
.expect(Selector("#key-Labels-1").exists)
.ok()
.expect(Selector("#key-Annotations-1").exists)
.ok()
.expect(Selector("#key-NodeSelector-1").exists)
.ok()
.click("#submit_button")
.click("#yaml_button")
.expect(Selector("#code_wrapper").exists)
.ok();
await t
.expect(
(
await Selector("#code_wrapper").textContent
).includes("image: minio/operator:v4.4.22")
)
.ok()
.expect(
(
await Selector("#code_wrapper").textContent
).includes("diskCapacityGB: 3")
)
.ok()
.expect((await Selector("#code_wrapper").textContent).includes('cpu: "3"'))
.ok()
.expect(
(await Selector("#code_wrapper").textContent).includes('memory: "3"')
)
.ok()
.expect(
(
await Selector("#code_wrapper").textContent
).includes("serviceAccountName: loggingTestServiceAccountName")
)
.ok()
.expect(
(await Selector("#code_wrapper").textContent).includes("fsGroup: 3333")
)
.ok()
.expect(
(await Selector("#code_wrapper").textContent).includes("runAsGroup: 2222")
)
.ok()
.expect(
(await Selector("#code_wrapper").textContent).includes("runAsUser: 1111")
)
.ok()
.expect(
(
await Selector("#code_wrapper").textContent
).includes("AnnotationsKey0Test: loggingAnnotationsVal0Test")
)
.ok()
.expect(
(
await Selector("#code_wrapper").textContent
).includes("NodeSelectorKey0Test: loggingNodeSelectorVal0Test")
)
.ok()
.expect(
(
await Selector("#code_wrapper").textContent
).includes("loggingLabelKey0Test: loggingLabelVal0Test")
)
.ok();
};
const checkLoggingDBFieldsAcceptValues = async (tenantName: string) => {
await goToLoggingDBSection(tenantName);
await t
.typeText("#dbImage", "library/postgres:13", { replace: true })
.typeText("#dbInitImage", "library/busybox:1.33.1", { replace: true })
.typeText("#dbCPURequest", "4", { replace: true })
.typeText("#dbMemRequest", "4", { replace: true })
.typeText("#securityContext_runAsUser", "4444", { replace: true })
.typeText("#securityContext_runAsGroup", "5555", { replace: true })
.typeText("#securityContext_fsGroup", "6666", { replace: true })
.expect(Selector("#securityContext_runAsNonRoot").checked)
.notOk()
.click("#securityContext_runAsNonRoot")
.expect(Selector("#securityContext_runAsNonRoot").checked)
.ok()
.typeText("#key-dbLabels-0", "loggingdbLabelKey0Test", { replace: true })
.typeText("#val-dbLabels-0", "loggingdbLabelVal0Test", { replace: true })
.click("#add-dbLabels-0")
.typeText("#key-dbAnnotations-0", "loggingdbAnnotationsKey0Test", {
replace: true,
})
.typeText("#val-dbAnnotations-0", "loggingdbAnnotationsVal0Test", {
replace: true,
})
.click("#add-dbAnnotations-0")
.typeText("#key-DBNodeSelector-0", "loggingdbNodeSelectorKey0Test", {
replace: true,
})
.typeText("#val-DBNodeSelector-0", "loggingdbNodeSelectorVal0Test", {
replace: true,
})
.click("#add-DBNodeSelector-0")
.expect(Selector("#key-dbLabels-1").exists)
.ok()
.expect(Selector("#key-dbAnnotations-1").exists)
.ok()
.expect(Selector("#key-DBNodeSelector-1").exists)
.ok()
.click("#remove-dbLabels-1")
.click("#remove-dbAnnotations-1")
.click("#remove-DBNodeSelector-1")
.expect(Selector("#key-dbLabels-1").exists)
.notOk()
.expect(Selector("#key-dbAnnotations-1").exists)
.notOk()
.expect(Selector("#key-DBNodeSelector-1").exists)
.notOk()
.click("#submit_button")
.click("#yaml_button")
.expect(Selector("#code_wrapper").exists)
.ok();
await t
.expect(
(
await Selector("#code_wrapper").textContent
).includes("image: library/postgres:13")
)
.ok()
.expect((await Selector("#code_wrapper").textContent).includes('cpu: "4"'))
.ok()
.expect(
(await Selector("#code_wrapper").textContent).includes('memory: "4"')
)
.ok()
.expect(
(await Selector("#code_wrapper").textContent).includes("fsGroup: 6666")
)
.ok()
.expect(
(await Selector("#code_wrapper").textContent).includes("runAsGroup: 5555")
)
.ok()
.expect(
(await Selector("#code_wrapper").textContent).includes("runAsUser: 4444")
)
.ok()
.expect(
(
await Selector("#code_wrapper").textContent
).includes("loggingdbAnnotationsKey0Test: loggingdbAnnotationsVal0Test")
)
.ok()
.expect(
(
await Selector("#code_wrapper").textContent
).includes("loggingdbNodeSelectorKey0Test: loggingdbNodeSelectorVal0Test")
)
.ok()
.expect(
(
await Selector("#code_wrapper").textContent
).includes("loggingdbLabelKey0Test: loggingdbLabelVal0Test")
)
.ok();
};
// Test 1
test("Test Prometheus config fields can be edited and submitted", async (t) => {
const tenantName = `storage-lite`;
await loginToOperator();
await checkMonitoringFieldsAcceptValues(tenantName);
});

View File

@@ -0,0 +1,473 @@
// This file is part of MinIO Console Server
// Copyright (c) 2022 MinIO, Inc.
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU Affero General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU Affero General Public License for more details.
//
// You should have received a copy of the GNU Affero General Public License
// along with this program. If not, see <http://www.gnu.org/licenses/>.
import { t, Selector } from "testcafe";
import {
loginToOperator,
createTenant,
createTenantWithoutAuditLog,
deleteTenant,
redirectToTenantsList,
goToPodInTenant,
goToPodSection,
goToPvcInTenant,
goToPvcSection,
goToMonitoringSection,
goToLoggingSection,
goToLoggingDBSection,
} from "../../utils";
fixture("For user with default permissions").page("http://localhost:9090");
const testPODDescribe = async (tenantName: string) => {
await goToPodInTenant(tenantName);
await goToPodSection(1);
await checkPodDescribeHasSections();
};
const checkPodDescribeHasSections = async () => {
await t
.expect(Selector("#pod-describe-summary").exists)
.ok()
.expect(Selector("#pod-describe-annotations").exists)
.ok()
.expect(Selector("#pod-describe-labels").exists)
.ok()
.expect(Selector("#pod-describe-conditions").exists)
.ok()
.expect(Selector("#pod-describe-tolerations").exists)
.ok()
.expect(Selector("#pod-describe-volumes").exists)
.ok()
.expect(Selector("#pod-describe-containers").exists)
.ok();
};
const testPvcDescribe = async (tenantName: string) => {
await goToPvcInTenant(tenantName);
await goToPvcSection(1);
await checkPvcDescribeHasSections();
};
const checkPvcDescribeHasSections = async () => {
await t
.expect(Selector("#pvc-describe-summary").exists)
.ok()
.expect(Selector("#pvc-describe-annotations").exists)
.ok()
.expect(Selector("#pvc-describe-labels").exists)
.ok();
};
export const checkMonitoringToggle = async (tenantName: string) => {
await goToMonitoringSection(tenantName);
await t
.click("#tenant-monitoring")
.click("#confirm-ok")
.wait(1000)
.expect(Selector("#image").exists)
.notOk()
.click("#yaml_button")
.expect(Selector("#code_wrapper").exists)
.ok();
await t
.expect(
(await Selector("#code_wrapper").textContent).includes("prometheus:")
)
.notOk();
await t
.click(Selector(`a[href$="/monitoring"]`))
.click("#tenant-monitoring")
.click("#confirm-ok")
.wait(5000)
.expect(Selector("#prometheus_image").exists)
.ok()
.click("#yaml_button")
.expect(Selector("#code_wrapper").exists)
.ok();
await t
.expect(
(await Selector("#code_wrapper").textContent).includes("prometheus:")
)
.ok();
};
export const checkMonitoringFieldsAcceptValues = async (tenantName: string) => {
await goToMonitoringSection(tenantName);
await t
.typeText("#prometheus_image", "quay.io/prometheus/prometheus:latest", {
replace: true,
})
.typeText("#sidecarImage", "library/alpine:latest", { replace: true })
.typeText("#initImage", "library/busybox:1.33.1", { replace: true })
.typeText("#diskCapacityGB", "1", { replace: true })
.typeText("#cpuRequest", "1", { replace: true })
.typeText("#memRequest", "1", { replace: true })
.typeText("#serviceAccountName", "monitoringTestServiceAccountName", {
replace: true,
})
.typeText("#storageClassName", "monitoringTestStorageClassName", {
replace: true,
})
.typeText("#securityContext_runAsUser", "1212", { replace: true })
.typeText("#securityContext_runAsGroup", "3434", { replace: true })
.typeText("#securityContext_fsGroup", "5656", { replace: true })
.expect(Selector("#securityContext_runAsNonRoot").checked)
.ok()
.click("#securityContext_runAsNonRoot")
.expect(Selector("#securityContext_runAsNonRoot").checked)
.notOk()
.typeText("#key-Labels-0", "monitoringLabelKey0Test", { replace: true })
.typeText("#val-Labels-0", "monitoringLabelVal0Test", { replace: true })
.click("#add-Labels-0")
.typeText("#key-Annotations-0", "monitoringAnnotationsKey0Test", {
replace: true,
})
.typeText("#val-Annotations-0", "monitoringAnnotationsVal0Test", {
replace: true,
})
.click("#add-Annotations-0")
.typeText("#key-NodeSelector-0", "monitoringNodeSelectorKey0Test", {
replace: true,
})
.typeText("#val-NodeSelector-0", "monitoringNodeSelectorVal0Test", {
replace: true,
})
.click("#add-NodeSelector-0")
.expect(Selector("#key-Labels-1").exists)
.ok()
.expect(Selector("#key-Annotations-1").exists)
.ok()
.expect(Selector("#key-NodeSelector-1").exists)
.ok()
.click("#submit_button")
.click("#yaml_button")
.expect(Selector("#code_wrapper").exists)
.ok();
await t
.expect(
(
await Selector("#code_wrapper").textContent
).includes("image: quay.io/prometheus/prometheus:latest")
)
.ok()
.expect(
(
await Selector("#code_wrapper").textContent
).includes("initimage: library/busybox:1.33.1")
)
.ok()
.expect(
(
await Selector("#code_wrapper").textContent
).includes("diskCapacityGB: 1")
)
.ok()
.expect((await Selector("#code_wrapper").textContent).includes('cpu: "1"'))
.ok()
.expect(
(await Selector("#code_wrapper").textContent).includes("memory: 1Gi")
)
.ok()
.expect(
(
await Selector("#code_wrapper").textContent
).includes("serviceAccountName: monitoringTestServiceAccountName")
)
.ok()
.expect(
(
await Selector("#code_wrapper").textContent
).includes("sidecarimage: library/alpine:latest")
)
.ok()
.expect(
(
await Selector("#code_wrapper").textContent
).includes("storageClassName: monitoringTestStorageClassName")
)
.ok()
.expect(
(await Selector("#code_wrapper").textContent).includes("fsGroup: 5656")
)
.ok()
.expect(
(await Selector("#code_wrapper").textContent).includes("runAsGroup: 3434")
)
.ok()
.expect(
(await Selector("#code_wrapper").textContent).includes("runAsUser: 1212")
)
.ok()
.expect(
(
await Selector("#code_wrapper").textContent
).includes("monitoringAnnotationsKey0Test: monitoringAnnotationsVal0Test")
)
.ok()
.expect(
(
await Selector("#code_wrapper").textContent
).includes(
"monitoringNodeSelectorKey0Test: monitoringNodeSelectorVal0Test"
)
)
.ok()
.expect(
(
await Selector("#code_wrapper").textContent
).includes("monitoringLabelKey0Test: monitoringLabelVal0Test")
)
.ok();
};
const checkLoggingToggle = async (tenantName: string) => {
await goToLoggingSection(tenantName);
await t
.click("#tenant_logging")
.click("#confirm-ok")
.wait(3000)
.expect(Selector("#image").exists)
.notOk()
.click("#yaml_button")
.expect(Selector("#code_wrapper").exists)
.ok();
await t
.expect((await Selector("#code_wrapper").textContent).includes("log:"))
.notOk();
await t
.click(Selector(`a[href$="/logging"]`))
.click("#tenant_logging")
.click("#confirm-ok")
.wait(3000)
.expect(Selector("#image").exists)
.ok()
.click("#yaml_button")
.expect(Selector("#code_wrapper").exists)
.ok();
await t
.expect((await Selector("#code_wrapper").textContent).includes("log:"))
.ok();
};
const checkLoggingFieldsAcceptValues = async (tenantName: string) => {
await goToLoggingSection(tenantName);
await t
.wait(3000)
.typeText("#image", "minio/operator:v4.4.22", { replace: true })
.typeText("#diskCapacityGB", "3", { replace: true })
.typeText("#cpuRequest", "3", { replace: true })
.typeText("#memRequest", "3", { replace: true })
.typeText("#serviceAccountName", "loggingTestServiceAccountName", {
replace: true,
})
.typeText("#securityContext_runAsUser", "1111", { replace: true })
.typeText("#securityContext_runAsGroup", "2222", { replace: true })
.typeText("#securityContext_fsGroup", "3333", { replace: true })
.expect(Selector("#securityContext_runAsNonRoot").exists)
.ok();
await t.wait(3000);
await t
.expect(Selector("#securityContext_runAsNonRoot").checked)
.notOk()
.click("#securityContext_runAsNonRoot")
.expect(Selector("#securityContext_runAsNonRoot").checked)
.ok()
.typeText("#key-Labels-0", "loggingLabelKey0Test", { replace: true })
.typeText("#val-Labels-0", "loggingLabelVal0Test", { replace: true })
.click("#add-Labels-0")
.typeText("#key-Annotations-0", "loggingAnnotationsKey0Test", {
replace: true,
})
.typeText("#val-Annotations-0", "loggingAnnotationsVal0Test", {
replace: true,
})
.click("#add-Annotations-0")
.typeText("#key-NodeSelector-0", "loggingNodeSelectorKey0Test", {
replace: true,
})
.typeText("#val-NodeSelector-0", "loggingNodeSelectorVal0Test", {
replace: true,
})
.click("#add-NodeSelector-0")
.expect(Selector("#key-Labels-1").exists)
.ok()
.expect(Selector("#key-Annotations-1").exists)
.ok()
.expect(Selector("#key-NodeSelector-1").exists)
.ok()
.click("#submit_button")
.click("#yaml_button")
.expect(Selector("#code_wrapper").exists)
.ok();
await t
.expect(
(
await Selector("#code_wrapper").textContent
).includes("image: minio/operator:v4.4.22")
)
.ok()
.expect(
(
await Selector("#code_wrapper").textContent
).includes("diskCapacityGB: 3")
)
.ok()
.expect((await Selector("#code_wrapper").textContent).includes('cpu: "3"'))
.ok()
.expect(
(await Selector("#code_wrapper").textContent).includes('memory: "3"')
)
.ok()
.expect(
(
await Selector("#code_wrapper").textContent
).includes("serviceAccountName: loggingTestServiceAccountName")
)
.ok()
.expect(
(await Selector("#code_wrapper").textContent).includes("fsGroup: 3333")
)
.ok()
.expect(
(await Selector("#code_wrapper").textContent).includes("runAsGroup: 2222")
)
.ok()
.expect(
(await Selector("#code_wrapper").textContent).includes("runAsUser: 1111")
)
.ok()
.expect(
(
await Selector("#code_wrapper").textContent
).includes("AnnotationsKey0Test: loggingAnnotationsVal0Test")
)
.ok()
.expect(
(
await Selector("#code_wrapper").textContent
).includes("NodeSelectorKey0Test: loggingNodeSelectorVal0Test")
)
.ok()
.expect(
(
await Selector("#code_wrapper").textContent
).includes("loggingLabelKey0Test: loggingLabelVal0Test")
)
.ok();
};
const checkLoggingDBFieldsAcceptValues = async (tenantName: string) => {
await goToLoggingDBSection(tenantName);
await t
.typeText("#dbImage", "library/postgres:13", { replace: true })
.typeText("#dbInitImage", "library/busybox:1.33.1", { replace: true })
.typeText("#dbCPURequest", "4", { replace: true })
.typeText("#dbMemRequest", "4", { replace: true })
.typeText("#securityContext_runAsUser", "4444", { replace: true })
.typeText("#securityContext_runAsGroup", "5555", { replace: true })
.typeText("#securityContext_fsGroup", "6666", { replace: true })
.expect(Selector("#securityContext_runAsNonRoot").checked)
.notOk()
.click("#securityContext_runAsNonRoot")
.expect(Selector("#securityContext_runAsNonRoot").checked)
.ok()
.typeText("#key-dbLabels-0", "loggingdbLabelKey0Test", { replace: true })
.typeText("#val-dbLabels-0", "loggingdbLabelVal0Test", { replace: true })
.click("#add-dbLabels-0")
.typeText("#key-dbAnnotations-0", "loggingdbAnnotationsKey0Test", {
replace: true,
})
.typeText("#val-dbAnnotations-0", "loggingdbAnnotationsVal0Test", {
replace: true,
})
.click("#add-dbAnnotations-0")
.typeText("#key-DBNodeSelector-0", "loggingdbNodeSelectorKey0Test", {
replace: true,
})
.typeText("#val-DBNodeSelector-0", "loggingdbNodeSelectorVal0Test", {
replace: true,
})
.click("#add-DBNodeSelector-0")
.expect(Selector("#key-dbLabels-1").exists)
.ok()
.expect(Selector("#key-dbAnnotations-1").exists)
.ok()
.expect(Selector("#key-DBNodeSelector-1").exists)
.ok()
.click("#remove-dbLabels-1")
.click("#remove-dbAnnotations-1")
.click("#remove-DBNodeSelector-1")
.expect(Selector("#key-dbLabels-1").exists)
.notOk()
.expect(Selector("#key-dbAnnotations-1").exists)
.notOk()
.expect(Selector("#key-DBNodeSelector-1").exists)
.notOk()
.click("#submit_button")
.click("#yaml_button")
.expect(Selector("#code_wrapper").exists)
.ok();
await t
.expect(
(
await Selector("#code_wrapper").textContent
).includes("image: library/postgres:13")
)
.ok()
.expect((await Selector("#code_wrapper").textContent).includes('cpu: "4"'))
.ok()
.expect(
(await Selector("#code_wrapper").textContent).includes('memory: "4"')
)
.ok()
.expect(
(await Selector("#code_wrapper").textContent).includes("fsGroup: 6666")
)
.ok()
.expect(
(await Selector("#code_wrapper").textContent).includes("runAsGroup: 5555")
)
.ok()
.expect(
(await Selector("#code_wrapper").textContent).includes("runAsUser: 4444")
)
.ok()
.expect(
(
await Selector("#code_wrapper").textContent
).includes("loggingdbAnnotationsKey0Test: loggingdbAnnotationsVal0Test")
)
.ok()
.expect(
(
await Selector("#code_wrapper").textContent
).includes("loggingdbNodeSelectorKey0Test: loggingdbNodeSelectorVal0Test")
)
.ok()
.expect(
(
await Selector("#code_wrapper").textContent
).includes("loggingdbLabelKey0Test: loggingdbLabelVal0Test")
)
.ok();
};
// Test 1
test("Test Audit Logging can be disabled and enabled", async (t) => {
const tenantName = `storage-lite`;
await loginToOperator();
await checkLoggingToggle(tenantName);
});

View File

@@ -0,0 +1,474 @@
// This file is part of MinIO Console Server
// Copyright (c) 2022 MinIO, Inc.
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU Affero General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU Affero General Public License for more details.
//
// You should have received a copy of the GNU Affero General Public License
// along with this program. If not, see <http://www.gnu.org/licenses/>.
import { t, Selector } from "testcafe";
import {
loginToOperator,
createTenant,
createTenantWithoutAuditLog,
deleteTenant,
redirectToTenantsList,
goToPodInTenant,
goToPodSection,
goToPvcInTenant,
goToPvcSection,
goToMonitoringSection,
goToLoggingSection,
goToLoggingDBSection,
} from "../../utils";
fixture("For user with default permissions").page("http://localhost:9090");
const testPODDescribe = async (tenantName: string) => {
await goToPodInTenant(tenantName);
await goToPodSection(1);
await checkPodDescribeHasSections();
};
const checkPodDescribeHasSections = async () => {
await t
.expect(Selector("#pod-describe-summary").exists)
.ok()
.expect(Selector("#pod-describe-annotations").exists)
.ok()
.expect(Selector("#pod-describe-labels").exists)
.ok()
.expect(Selector("#pod-describe-conditions").exists)
.ok()
.expect(Selector("#pod-describe-tolerations").exists)
.ok()
.expect(Selector("#pod-describe-volumes").exists)
.ok()
.expect(Selector("#pod-describe-containers").exists)
.ok();
};
const testPvcDescribe = async (tenantName: string) => {
await goToPvcInTenant(tenantName);
await goToPvcSection(1);
await checkPvcDescribeHasSections();
};
const checkPvcDescribeHasSections = async () => {
await t
.expect(Selector("#pvc-describe-summary").exists)
.ok()
.expect(Selector("#pvc-describe-annotations").exists)
.ok()
.expect(Selector("#pvc-describe-labels").exists)
.ok();
};
export const checkMonitoringToggle = async (tenantName: string) => {
await goToMonitoringSection(tenantName);
await t
.click("#tenant-monitoring")
.click("#confirm-ok")
.wait(1000)
.expect(Selector("#image").exists)
.notOk()
.click("#yaml_button")
.expect(Selector("#code_wrapper").exists)
.ok();
await t
.expect(
(await Selector("#code_wrapper").textContent).includes("prometheus:")
)
.notOk();
await t
.click(Selector(`a[href$="/monitoring"]`))
.click("#tenant-monitoring")
.click("#confirm-ok")
.wait(5000)
.expect(Selector("#prometheus_image").exists)
.ok()
.click("#yaml_button")
.expect(Selector("#code_wrapper").exists)
.ok();
await t
.expect(
(await Selector("#code_wrapper").textContent).includes("prometheus:")
)
.ok();
};
export const checkMonitoringFieldsAcceptValues = async (tenantName: string) => {
await goToMonitoringSection(tenantName);
await t
.typeText("#prometheus_image", "quay.io/prometheus/prometheus:latest", {
replace: true,
})
.typeText("#sidecarImage", "library/alpine:latest", { replace: true })
.typeText("#initImage", "library/busybox:1.33.1", { replace: true })
.typeText("#diskCapacityGB", "1", { replace: true })
.typeText("#cpuRequest", "1", { replace: true })
.typeText("#memRequest", "1", { replace: true })
.typeText("#serviceAccountName", "monitoringTestServiceAccountName", {
replace: true,
})
.typeText("#storageClassName", "monitoringTestStorageClassName", {
replace: true,
})
.typeText("#securityContext_runAsUser", "1212", { replace: true })
.typeText("#securityContext_runAsGroup", "3434", { replace: true })
.typeText("#securityContext_fsGroup", "5656", { replace: true })
.expect(Selector("#securityContext_runAsNonRoot").checked)
.ok()
.click("#securityContext_runAsNonRoot")
.expect(Selector("#securityContext_runAsNonRoot").checked)
.notOk()
.typeText("#key-Labels-0", "monitoringLabelKey0Test", { replace: true })
.typeText("#val-Labels-0", "monitoringLabelVal0Test", { replace: true })
.click("#add-Labels-0")
.typeText("#key-Annotations-0", "monitoringAnnotationsKey0Test", {
replace: true,
})
.typeText("#val-Annotations-0", "monitoringAnnotationsVal0Test", {
replace: true,
})
.click("#add-Annotations-0")
.typeText("#key-NodeSelector-0", "monitoringNodeSelectorKey0Test", {
replace: true,
})
.typeText("#val-NodeSelector-0", "monitoringNodeSelectorVal0Test", {
replace: true,
})
.click("#add-NodeSelector-0")
.expect(Selector("#key-Labels-1").exists)
.ok()
.expect(Selector("#key-Annotations-1").exists)
.ok()
.expect(Selector("#key-NodeSelector-1").exists)
.ok()
.click("#submit_button")
.click("#yaml_button")
.expect(Selector("#code_wrapper").exists)
.ok();
await t
.expect(
(
await Selector("#code_wrapper").textContent
).includes("image: quay.io/prometheus/prometheus:latest")
)
.ok()
.expect(
(
await Selector("#code_wrapper").textContent
).includes("initimage: library/busybox:1.33.1")
)
.ok()
.expect(
(
await Selector("#code_wrapper").textContent
).includes("diskCapacityGB: 1")
)
.ok()
.expect((await Selector("#code_wrapper").textContent).includes('cpu: "1"'))
.ok()
.expect(
(await Selector("#code_wrapper").textContent).includes("memory: 1Gi")
)
.ok()
.expect(
(
await Selector("#code_wrapper").textContent
).includes("serviceAccountName: monitoringTestServiceAccountName")
)
.ok()
.expect(
(
await Selector("#code_wrapper").textContent
).includes("sidecarimage: library/alpine:latest")
)
.ok()
.expect(
(
await Selector("#code_wrapper").textContent
).includes("storageClassName: monitoringTestStorageClassName")
)
.ok()
.expect(
(await Selector("#code_wrapper").textContent).includes("fsGroup: 5656")
)
.ok()
.expect(
(await Selector("#code_wrapper").textContent).includes("runAsGroup: 3434")
)
.ok()
.expect(
(await Selector("#code_wrapper").textContent).includes("runAsUser: 1212")
)
.ok()
.expect(
(
await Selector("#code_wrapper").textContent
).includes("monitoringAnnotationsKey0Test: monitoringAnnotationsVal0Test")
)
.ok()
.expect(
(
await Selector("#code_wrapper").textContent
).includes(
"monitoringNodeSelectorKey0Test: monitoringNodeSelectorVal0Test"
)
)
.ok()
.expect(
(
await Selector("#code_wrapper").textContent
).includes("monitoringLabelKey0Test: monitoringLabelVal0Test")
)
.ok();
};
const checkLoggingToggle = async (tenantName: string) => {
await goToLoggingSection(tenantName);
await t
.click("#tenant_logging")
.click("#confirm-ok")
.wait(3000)
.expect(Selector("#image").exists)
.notOk()
.click("#yaml_button")
.expect(Selector("#code_wrapper").exists)
.ok();
await t
.expect((await Selector("#code_wrapper").textContent).includes("log:"))
.notOk();
await t
.click(Selector(`a[href$="/logging"]`))
.click("#tenant_logging")
.click("#confirm-ok")
.wait(3000)
.expect(Selector("#image").exists)
.ok()
.click("#yaml_button")
.expect(Selector("#code_wrapper").exists)
.ok();
await t
.expect((await Selector("#code_wrapper").textContent).includes("log:"))
.ok();
};
const checkLoggingFieldsAcceptValues = async (tenantName: string) => {
await goToLoggingSection(tenantName);
await t
.wait(3000)
.typeText("#image", "minio/operator:v4.4.22", { replace: true })
.typeText("#diskCapacityGB", "3", { replace: true })
.typeText("#cpuRequest", "3", { replace: true })
.typeText("#memRequest", "3", { replace: true })
.typeText("#serviceAccountName", "loggingTestServiceAccountName", {
replace: true,
})
.typeText("#securityContext_runAsUser", "1111", { replace: true })
.typeText("#securityContext_runAsGroup", "2222", { replace: true })
.typeText("#securityContext_fsGroup", "3333", { replace: true })
.expect(Selector("#securityContext_runAsNonRoot").exists)
.ok();
await t.wait(3000);
await t
.expect(Selector("#securityContext_runAsNonRoot").checked)
.ok()
.click("#securityContext_runAsNonRoot")
.expect(Selector("#securityContext_runAsNonRoot").checked)
.notOk()
.typeText("#key-Labels-0", "loggingLabelKey0Test", { replace: true })
.typeText("#val-Labels-0", "loggingLabelVal0Test", { replace: true })
.click("#add-Labels-0")
.typeText("#key-Annotations-0", "loggingAnnotationsKey0Test", {
replace: true,
})
.typeText("#val-Annotations-0", "loggingAnnotationsVal0Test", {
replace: true,
})
.click("#add-Annotations-0")
.typeText("#key-NodeSelector-0", "loggingNodeSelectorKey0Test", {
replace: true,
})
.typeText("#val-NodeSelector-0", "loggingNodeSelectorVal0Test", {
replace: true,
})
.click("#add-NodeSelector-0")
.expect(Selector("#key-Labels-1").exists)
.ok()
.expect(Selector("#key-Annotations-1").exists)
.ok()
.expect(Selector("#key-NodeSelector-1").exists)
.ok()
.click("#submit_button")
.click("#yaml_button")
.expect(Selector("#code_wrapper").exists)
.ok();
await t
.expect(
(
await Selector("#code_wrapper").textContent
).includes("image: minio/operator:v4.4.22")
)
.ok()
.expect(
(
await Selector("#code_wrapper").textContent
).includes("diskCapacityGB: 3")
)
.ok()
.expect((await Selector("#code_wrapper").textContent).includes('cpu: "3"'))
.ok()
.expect(
(await Selector("#code_wrapper").textContent).includes('memory: "3"')
)
.ok()
.expect(
(
await Selector("#code_wrapper").textContent
).includes("serviceAccountName: loggingTestServiceAccountName")
)
.ok()
.expect(
(await Selector("#code_wrapper").textContent).includes("fsGroup: 3333")
)
.ok()
.expect(
(await Selector("#code_wrapper").textContent).includes("runAsGroup: 2222")
)
.ok()
.expect(
(await Selector("#code_wrapper").textContent).includes("runAsUser: 1111")
)
.ok()
.expect(
(
await Selector("#code_wrapper").textContent
).includes("AnnotationsKey0Test: loggingAnnotationsVal0Test")
)
.ok()
.expect(
(
await Selector("#code_wrapper").textContent
).includes("NodeSelectorKey0Test: loggingNodeSelectorVal0Test")
)
.ok()
.expect(
(
await Selector("#code_wrapper").textContent
).includes("loggingLabelKey0Test: loggingLabelVal0Test")
)
.ok();
};
const checkLoggingDBFieldsAcceptValues = async (tenantName: string) => {
await goToLoggingDBSection(tenantName);
await t
.typeText("#dbImage", "library/postgres:13", { replace: true })
.typeText("#dbInitImage", "library/busybox:1.33.1", { replace: true })
.typeText("#dbCPURequest", "4", { replace: true })
.typeText("#dbMemRequest", "4", { replace: true })
.typeText("#securityContext_runAsUser", "4444", { replace: true })
.typeText("#securityContext_runAsGroup", "5555", { replace: true })
.typeText("#securityContext_fsGroup", "6666", { replace: true })
.expect(Selector("#securityContext_runAsNonRoot").checked)
.ok()
.click("#securityContext_runAsNonRoot")
.expect(Selector("#securityContext_runAsNonRoot").checked)
.notOk()
.typeText("#key-dbLabels-0", "loggingdbLabelKey0Test", { replace: true })
.typeText("#val-dbLabels-0", "loggingdbLabelVal0Test", { replace: true })
.click("#add-dbLabels-0")
.typeText("#key-dbAnnotations-0", "loggingdbAnnotationsKey0Test", {
replace: true,
})
.typeText("#val-dbAnnotations-0", "loggingdbAnnotationsVal0Test", {
replace: true,
})
.click("#add-dbAnnotations-0")
.typeText("#key-DBNodeSelector-0", "loggingdbNodeSelectorKey0Test", {
replace: true,
})
.typeText("#val-DBNodeSelector-0", "loggingdbNodeSelectorVal0Test", {
replace: true,
})
.click("#add-DBNodeSelector-0")
.expect(Selector("#key-dbLabels-1").exists)
.ok()
.expect(Selector("#key-dbAnnotations-1").exists)
.ok()
.expect(Selector("#key-DBNodeSelector-1").exists)
.ok()
.click("#remove-dbLabels-1")
.click("#remove-dbAnnotations-1")
.click("#remove-DBNodeSelector-1")
.expect(Selector("#key-dbLabels-1").exists)
.notOk()
.expect(Selector("#key-dbAnnotations-1").exists)
.notOk()
.expect(Selector("#key-DBNodeSelector-1").exists)
.notOk()
.click("#submit_button")
.click("#yaml_button")
.expect(Selector("#code_wrapper").exists)
.ok();
await t
.expect(
(
await Selector("#code_wrapper").textContent
).includes("image: library/postgres:13")
)
.ok()
.expect((await Selector("#code_wrapper").textContent).includes('cpu: "4"'))
.ok()
.expect(
(await Selector("#code_wrapper").textContent).includes('memory: "4"')
)
.ok()
.expect(
(await Selector("#code_wrapper").textContent).includes("fsGroup: 6666")
)
.ok()
.expect(
(await Selector("#code_wrapper").textContent).includes("runAsGroup: 5555")
)
.ok()
.expect(
(await Selector("#code_wrapper").textContent).includes("runAsUser: 4444")
)
.ok()
.expect(
(
await Selector("#code_wrapper").textContent
).includes("loggingdbAnnotationsKey0Test: loggingdbAnnotationsVal0Test")
)
.ok()
.expect(
(
await Selector("#code_wrapper").textContent
).includes("loggingdbNodeSelectorKey0Test: loggingdbNodeSelectorVal0Test")
)
.ok()
.expect(
(
await Selector("#code_wrapper").textContent
).includes("loggingdbLabelKey0Test: loggingdbLabelVal0Test")
)
.ok();
};
// Test 1
test("Test Audit Log config fields can be edited and submitted", async (t) => {
const tenantName = `storage-lite`;
await loginToOperator();
await checkLoggingFieldsAcceptValues(tenantName);
await checkLoggingDBFieldsAcceptValues(tenantName);
});