Cluster management (#10161)

* actions on cluster tests

* initial iteration for cluster drivers tests

* node drivers tests

* rke templates tests

* cloud credentials tests and initial node templates tests

* completed node templates tests

* pod security admissions and policy templates

* MachineDeployments MachineSets and Machines tests

* repositories tests

* filter out tests with @jenkins tag
This commit is contained in:
yonasberhe23 2024-02-05 17:04:57 -08:00 committed by GitHub
parent af5731a0b8
commit b189f8efb0
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
72 changed files with 2824 additions and 80 deletions

View File

@ -74,7 +74,7 @@ jobs:
run: |
yarn e2e:prod
env:
GREP_TAGS: ${{ matrix.role.tag }}Setup+${{ matrix.features[0] }} ${{ matrix.role.tag }}Setup+${{ matrix.features[1] || matrix.features[0] }}
GREP_TAGS: ${{ matrix.role.tag }}Setup+${{ matrix.features[0] }} --@jenkins ${{ matrix.role.tag }}Setup+${{ matrix.features[1] || matrix.features[0] }} --@jenkins
TEST_USERNAME: admin
TEST_ONLY: setup
@ -84,7 +84,7 @@ jobs:
[ "$BUILD_DASHBOARD" != "false" ] || exit 0
env:
TEST_SKIP: setup
GREP_TAGS: ${{ matrix.role.tag }}+${{ matrix.features[0] }} ${{ matrix.role.tag }}+${{ matrix.features[1] || matrix.features[0] }}
GREP_TAGS: ${{ matrix.role.tag }}+${{ matrix.features[0] }} --@jenkins ${{ matrix.role.tag }}+${{ matrix.features[1] || matrix.features[0] }} --@jenkins
TEST_USERNAME: ${{ matrix.role.username }}
- name: Upload screenshots

View File

@ -80,7 +80,9 @@ export default defineConfig({
username,
password: process.env.CATTLE_BOOTSTRAP_PASSWORD || process.env.TEST_PASSWORD,
bootstrapPassword: process.env.CATTLE_BOOTSTRAP_PASSWORD,
grepTags: process.env.GREP_TAGS
grepTags: process.env.GREP_TAGS,
awsAccessKey: process.env.AWS_ACCESS_KEY_ID,
awsSecretKey: process.env.AWS_SECRET_ACCESS_KEY
},
e2e: {
fixturesFolder: 'cypress/e2e/blueprints',

View File

@ -0,0 +1,52 @@
apiVersion: cluster.x-k8s.io/v1beta1
kind: MachineDeployment
metadata:
creationTimestamp: '2023-12-07T18:14:50Z'
generation: 1
labels:
cluster.x-k8s.io/cluster-name: local
managedFields:
- apiVersion: cluster.x-k8s.io/v1beta1
fieldsType: FieldsV1
fieldsV1:
f:spec:
.: {}
f:clusterName: {}
f:selector: {}
f:template:
.: {}
f:metadata: {}
f:spec:
.: {}
f:clusterName: {}
manager: rancher
operation: Update
time: '2023-12-07T18:14:50Z'
name: e2e-machinedeployment-name-1701972886077
namespace: default
resourceVersion: '22851'
uid: f5bf052d-7bbf-483a-a20a-b2f6e48d1e15
spec:
clusterName: local
minReadySeconds: 0
progressDeadlineSeconds: 600
replicas: 1
revisionHistoryLimit: 1
selector:
matchLabels:
cluster.x-k8s.io/cluster-name: local
cluster.x-k8s.io/deployment-name: e2e-machinedeployment-name-1701972886077
strategy:
rollingUpdate:
maxSurge: 1
maxUnavailable: 0
type: RollingUpdate
template:
metadata:
labels:
cluster.x-k8s.io/cluster-name: local
cluster.x-k8s.io/deployment-name: e2e-machinedeployment-name-1701972886077
spec:
bootstrap: {}
clusterName: local
infrastructureRef: {}

View File

@ -0,0 +1,65 @@
apiVersion: cluster.x-k8s.io/v1beta1
kind: MachineDeployment
metadata:
name: e2etest
namespace: default
# annotations: key: string
# labels: key: string
spec:
selector:
matchLabels:# key: string
# matchExpressions:
# - key: string
# operator: string
# values:
# - string
template:
metadata:
labels:# key: string
# annotations: key: string
# generateName: string
# name: string
# namespace: string
# ownerReferences:
# - apiVersion: string
# blockOwnerDeletion: boolean
# controller: boolean
# kind: string
# name: string
# uid: string
spec:
# bootstrap:
# configRef:
# apiVersion: string
# fieldPath: string
# kind: string
# name: string
# namespace: string
# resourceVersion: string
# uid: string
# data: string
# dataSecretName: string
clusterName: local
# failureDomain: string
# infrastructureRef:
# apiVersion: string
# fieldPath: string
# kind: string
# name: string
# namespace: string
# resourceVersion: string
# uid: string
# nodeDrainTimeout: string
# providerID: string
# version: string
clusterName: local
# minReadySeconds: int
# paused: boolean
# progressDeadlineSeconds: int
# replicas: int
# revisionHistoryLimit: int
# strategy:
# type: string
# rollingUpdate:
# maxSurge: json
# maxUnavailable: json

View File

@ -0,0 +1,44 @@
apiVersion: cluster.x-k8s.io/v1beta1
kind: MachineSet
metadata:
creationTimestamp: '2023-12-06T23:41:44Z'
generation: 3
labels:
cluster.x-k8s.io/cluster-name: local
managedFields:
- apiVersion: cluster.x-k8s.io/v1beta1
fieldsType: FieldsV1
fieldsV1:
f:spec:
.: {}
f:clusterName: {}
f:replicas: {}
f:selector: {}
f:template:
.: {}
f:metadata: {}
f:spec:
.: {}
f:clusterName: {}
manager: rancher
operation: Update
time: '2023-12-06T23:46:28Z'
name: e2e-machine-name-1701906098950
namespace: default
resourceVersion: '647485'
uid: 98380f64-0706-4522-8dc2-b91a7f012dcf
spec:
clusterName: local
deletePolicy: Random
replicas: 1
selector:
matchLabels:
cluster.x-k8s.io/set-name: e2e-machine-name-1701906098950
template:
metadata:
labels:
cluster.x-k8s.io/set-name: e2e-machine-name-1701906098950
spec:
bootstrap: {}
clusterName: local
infrastructureRef: {}

View File

@ -0,0 +1,58 @@
apiVersion: cluster.x-k8s.io/v1beta1
kind: MachineSet
metadata:
name: e2etest
namespace: default
# annotations: key: string
# labels: key: string
spec:
selector:
matchLabels:# key: string
# matchExpressions:
# - key: string
# operator: string
# values:
# - string
template:
metadata:
labels:# key: string
# annotations: key: string
# generateName: string
# name: string
# namespace: string
# ownerReferences:
# - apiVersion: string
# blockOwnerDeletion: boolean
# controller: boolean
# kind: string
# name: string
# uid: string
spec:
bootstrap:
# configRef:
# apiVersion: string
# fieldPath: string
# kind: string
# name: string
# namespace: string
# resourceVersion: string
# uid: string
# data: string
dataSecretName: secretName
clusterName: local
# failureDomain: string
# infrastructureRef:
# apiVersion: string
# fieldPath: string
# kind: string
# name: string
# namespace: string
# resourceVersion: string
# uid: string
# nodeDrainTimeout: string
# providerID: string
# version: string
clusterName: local
# deletePolicy: string
# minReadySeconds: int
# replicas: int

View File

@ -0,0 +1,33 @@
apiVersion: cluster.x-k8s.io/v1beta1
kind: Machine
metadata:
creationTimestamp: '2023-12-06T22:21:54Z'
generation: 1
labels:
cluster.x-k8s.io/cluster-name: local
managedFields:
- apiVersion: cluster.x-k8s.io/v1beta1
fieldsType: FieldsV1
fieldsV1:
f:spec:
.: {}
f:bootstrap:
.: {}
f:dataSecretName: {}
f:clusterName: {}
f:infrastructureRef: {}
manager: rancher
operation: Update
time: '2023-12-06T22:21:54Z'
name: e2e-machine-name-1701901308645
namespace: default
resourceVersion: '609444'
uid: 7d61939a-b44a-4113-a7d1-9db2eda08811
spec:
bootstrap:
dataSecretName: secretname
clusterName: local
infrastructureRef:
namespace: default
resourceVersion: abc123
nodeDeletionTimeout: 10s

View File

@ -0,0 +1,32 @@
apiVersion: cluster.x-k8s.io/v1beta1
kind: Machine
metadata:
name: string
namespace: default
# annotations: key: string
# labels: key: string
spec:
bootstrap:
# configRef:
# apiVersion: string
# fieldPath: string
# kind: string
# name: string
# namespace: string
# resourceVersion: string
# uid: string
# data: string
dataSecretName: secretname
clusterName: local
# failureDomain: string
# infrastructureRef:
# apiVersion: string
# fieldPath: string
# kind: string
# name: string
# namespace: string
# resourceVersion: string
# uid: string
# nodeDrainTimeout: string
# providerID: string
# version: string

View File

@ -0,0 +1,37 @@
export const createPayloadData = {
id: 'e2e-pod-security-admission-1705617529465',
type: 'management.cattle.io.podsecurityadmissionconfigurationtemplate',
apiVersion: 'management.cattle.io/v3',
configuration: {
defaults: {
audit: 'baseline', 'audit-version': 'latest', enforce: 'privileged', 'enforce-version': 'latest', warn: 'restricted', 'warn-version': 'latest'
},
exemptions: {
usernames: ['admin', 'user'], runtimeClasses: ['myclass1', 'myclass2'], namespaces: ['ingress-nginx', 'kube-system']
}
},
kind: 'PodSecurityAdmissionConfigurationTemplate',
metadata: {
fields: ['e2e-pod-security-admission-1705617529465', '18s'], name: 'e2e-pod-security-admission-1705617529465', resourceVersion: '831667'
},
description: 'e2e-pod-security-admission-1705617529465-description'
};
export const updatePayloadData = {
id: 'e2e-pod-security-admission-1705628550961',
type: 'management.cattle.io.podsecurityadmissionconfigurationtemplate',
apiVersion: 'management.cattle.io/v3',
configuration: {
defaults: {
audit: 'baseline', 'audit-version': 'v1.25', enforce: 'privileged', 'enforce-version': 'v1.25', warn: 'restricted', 'warn-version': 'v1.25'
},
exemptions: {
usernames: ['admin1', 'user1'], runtimeClasses: ['myclass3', 'myclass4'], namespaces: ['cattle-system', 'cattle-epinio-system']
}
},
kind: 'PodSecurityAdmissionConfigurationTemplate',
metadata: {
fields: ['e2e-pod-security-admission-1705628550961', '7s'], name: 'e2e-pod-security-admission-1705628550961', resourceVersion: '938739'
},
description: 'e2e-pod-security-admission-1705628550961-description-edit'
};

View File

@ -8,4 +8,8 @@ export default class ResourceListMastheadPo extends ComponentPo {
title() {
return this.self().get('.title h1').invoke('text');
}
create() {
return this.self().find('[data-testid="masthead-create-yaml"]').click();
}
}

View File

@ -1,4 +1,5 @@
import ComponentPo from '@/cypress/e2e/po/components/component.po';
import AsyncButtonPo from '@/cypress/e2e/po/components/async-button.po';
export default class CruResourcePo extends ComponentPo {
selectSubType(groupIndex: number, itemIndex: number) {
@ -6,4 +7,20 @@ export default class CruResourcePo extends ComponentPo {
.eq(groupIndex).find('.item')
.eq(itemIndex);
}
selectSubTypeByIndex(index: number) {
return this.self().find('.subtypes-container > div')
.eq(index);
}
saveOrCreate(): AsyncButtonPo {
return new AsyncButtonPo('[data-testid="form-save"]', this.self());
}
saveAndWaitForRequests(method: string, url: string) {
cy.intercept(method, url).as('request');
this.saveOrCreate().click();
return cy.wait('@request', { timeout: 10000 });
}
}

View File

@ -1,5 +1,4 @@
import EmberComponentPo from '@/cypress/e2e/po/components/ember/ember-component.po';
export default class EmberAccordionPo extends EmberComponentPo {
private headerSelector: string;
private contentSelector: string;

View File

@ -0,0 +1,19 @@
import EmberComponentPo from '@/cypress/e2e/po/components/ember/ember-component.po';
export default class EmberCheckboxInputPo extends EmberComponentPo {
/**
* Click on the checkbox input button
* @returns
*/
set(): Cypress.Chainable {
return this.input().click({ force: true });
}
/**
* Return the checkbox input button from a given container
* @returns
*/
private input(): Cypress.Chainable {
return this.self().find('.ember-checkbox');
}
}

View File

@ -0,0 +1,29 @@
import EmberAccordionPo from '@/cypress/e2e/po/components/ember/ember-accordion.po';
import EmberComponentPo from '@/cypress/e2e/po/components/ember/ember-component.po';
import EmberInputPo from '@/cypress/e2e/po/components/ember/ember-input.po';
export default class EmberAddPodSecurityTemplatePo extends EmberComponentPo {
templateName(): EmberInputPo {
return new EmberInputPo('[data-testid="form-name-description__name"]');
}
templateDescription(): EmberInputPo {
return new EmberInputPo('.ember-text-area');
}
addDescription() {
this.self().find('div > a.btn', 'Add a Description').click();
}
accordion() {
return new EmberAccordionPo('.accordion-wrapper');
}
create() {
return this.self().find('button.btn').contains('Create').click();
}
save() {
return this.self().find('button.btn').contains('Save').click();
}
}

View File

@ -0,0 +1,16 @@
import EmberComponentPo from '@/cypress/e2e/po/components/ember/ember-component.po';
import EmberInputPo from '@/cypress/e2e/po/components/ember/ember-input.po';
export default class EmberFormRkeTemplatesPo extends EmberComponentPo {
templateDetails(index): EmberInputPo {
return new EmberInputPo(`.horizontal-form .row:nth-of-type(1) input:nth-child(${ index })`);
}
create() {
return this.self().contains('[data-testid="save-cancel-rke1"] button', 'Create').click();
}
save() {
return this.self().contains('[data-testid="save-cancel-rke1"] button', 'Save').click();
}
}

View File

@ -0,0 +1,20 @@
import EmberModalPo from '@/cypress/e2e/po/components/ember/ember-modal.po';
import EmberInputPo from '@/cypress/e2e/po/components/ember/ember-input.po';
export default class EmberModalClusterDriverPo extends EmberModalPo {
formInput(index: number) {
return new EmberInputPo(`.modal-open .inline-form:nth-of-type(${ index }) input`);
}
addDomainButton() {
this.self().find('button').contains('Add Domain').click();
}
create() {
return this.self().find('button').contains('Create').click();
}
save() {
return this.self().find('button').contains('Save').click();
}
}

View File

@ -0,0 +1,20 @@
import EmberModalPo from '@/cypress/e2e/po/components/ember/ember-modal.po';
import EmberInputPo from '@/cypress/e2e/po/components/ember/ember-input.po';
export default class EmberModalNodeDriverPo extends EmberModalPo {
formInput(index: number) {
return new EmberInputPo(`.modal-open .inline-form:nth-of-type(${ index }) input`);
}
addDomainButton() {
this.self().find('button').contains('Add Domain').click();
}
create() {
return this.self().find('button').contains('Create').click();
}
save() {
return this.self().find('button').contains('Save').click();
}
}

View File

@ -0,0 +1,33 @@
import EmberAccordionPo from '@/cypress/e2e/po/components/ember/ember-accordion.po';
import EmberModalPo from '@/cypress/e2e/po/components/ember/ember-modal.po';
import EmberInputPo from '@/cypress/e2e/po/components/ember/ember-input.po';
export default class EmberModalAddNodeTemplatePo extends EmberModalPo {
serviceProviderOptions(label: string) {
return this.self().contains('.nav-box-item', new RegExp(` ${ label } `));
}
nextButton(label: string) {
return this.self().contains('.btn', label, { timeout: 10000 });
}
accordion() {
return new EmberAccordionPo('');
}
checkOption(value: string) {
return this.self().find('.form-control').contains(value).click();
}
templateName(): EmberInputPo {
return new EmberInputPo('[data-testid="form-name-description__name"]');
}
create() {
return this.self().find('button').contains('Create').click();
}
save() {
return this.self().find('button').contains('Save').click();
}
}

View File

@ -4,4 +4,12 @@ export default class EmberModalPo extends EmberComponentPo {
constructor() {
super('.modal-open');
}
deactivate() {
return this.self().contains('.btn', 'Deactivate').click();
}
delete() {
return this.self().contains('.btn', 'Delete').click();
}
}

View File

@ -0,0 +1,25 @@
import EmberComponentPo from '@/cypress/e2e/po/components/ember/ember-component.po';
export default class EmberSelectPo extends EmberComponentPo {
getMenuItem(label: string, index = 0) {
return this.self().eq(index).contains(label);
}
selectMenuItemByLabel(label: string, index = 0) {
return this.self().eq(index).contains(label).click();
}
/**
* Select an <option> within a <select> using cy.select() command.
* @param index
* @param option
* @returns
*/
selectMenuItemByOption(option: string, index = 0) {
return this.self().eq(index).select(option);
}
checkOptionSelected(label: string, index = 0) {
return this.self().eq(index).should('contain.text', label);
}
}

View File

@ -0,0 +1,70 @@
import EmberComponentPo from '@/cypress/e2e/po/components/ember/ember-component.po';
import EmberSelectPo from '@/cypress/e2e/po/components/ember/ember-select.po';
export default class EmberSortableTablePo extends EmberComponentPo {
/**
* Get main row with name
* @param name
* @returns
*/
rowWithName(name: string) {
return this.self().contains('.main-row', new RegExp(` ${ name } `));
}
/**
* Open row action menu for main row with name
* @param name
* @returns
*/
rowActionMenuOpen(name: string) {
return this.rowWithName(name).find('.ember-basic-dropdown-trigger').click();
}
/**
* Get state of main row with name
* @param name
* @returns
*/
state(name: string) {
return this.rowWithName(name).find('.state');
}
/**
* Get group row with name
* @param name
* @returns
*/
groupRowWithName(name: string) {
return this.self().contains('.group-row', new RegExp(` ${ name } `));
}
/**
* Open row action menu for group row with name
* @param name
* @returns
*/
groupRowActionMenuOpen(name: string) {
return this.groupRowWithName(name).find('.ember-basic-dropdown-trigger').click();
}
/**
* Get row for a given group with group and main row name
* @param groupRowName
* @param mainRowName
* @returns
*/
rowWithinGroupByName(groupRowName: string, mainRowName: string) {
return this.self()
.contains('.group-row', new RegExp(` ${ groupRowName } `))
.siblings('tr.main-row')
.contains(mainRowName);
}
bulkActions(label: string) {
return cy.iFrame().contains('.bulk-actions', label);
}
actionMenu(): EmberSelectPo {
return new EmberSelectPo('.ember-basic-dropdown-content');
}
}

View File

@ -21,15 +21,20 @@ export default class LabeledInputPo extends ComponentPo {
/**
* Type value in the input
* @param value Value to be typed
* @param secret Pass in true to hide sensitive data from logs
* @returns
*/
set(value: string): Cypress.Chainable {
set(value: string, secret?: boolean): Cypress.Chainable {
this.input().should('be.visible');
this.input().focus();
this.input().clear();
if (secret) {
return this.input().type(value, { log: false });
} else {
return this.input().type(value);
}
}
clear() {
return this.input().clear();

View File

@ -1,8 +1,13 @@
import ComponentPo from '@/cypress/e2e/po/components/component.po';
import { CypressChainable } from '@/cypress/e2e/po/po.types';
import AsyncButtonPo from '@/cypress/e2e/po/components/async-button.po';
export default class ResourceYamlPo extends ComponentPo {
constructor(parent: CypressChainable) {
super(parent.find('.resource-yaml'));
}
saveOrCreate(): AsyncButtonPo {
return new AsyncButtonPo('[data-testid="action-button-async-button"]', this.self());
}
}

View File

@ -0,0 +1,22 @@
import PagePo from '@/cypress/e2e/po/pages/page.po';
import CruResourcePo from '@/cypress/e2e/po/components/cru-resource.po';
export default class BaseCloudCredentialsPo extends PagePo {
private static createPath(clusterId: string, id?: string ) {
const root = `/c/${ clusterId }/manager/cloudCredential`;
return id ? `${ root }/${ id }` : `${ root }/create`;
}
static goTo(path: string): Cypress.Chainable<Cypress.AUTWindow> {
throw new Error('invalid');
}
constructor(clusterId = 'local', id?: string) {
super(BaseCloudCredentialsPo.createPath(clusterId, id));
}
cloudServiceOptions(): CruResourcePo {
return new CruResourcePo('[data-testid="cru-form"]');
}
}

View File

@ -0,0 +1,53 @@
import PagePo from '@/cypress/e2e/po/pages/page.po';
import LabeledInputPo from '@/cypress/e2e/po/components/labeled-input.po';
import AsyncButtonPo from '@/cypress/e2e/po/components/async-button.po';
import LabeledSelectPo from '@/cypress/e2e/po/components/labeled-select.po';
import RadioGroupInputPo from '@/cypress/e2e/po/components/radio-group-input.po';
import NameNsDescription from '@/cypress/e2e/po/components/name-ns-description.po';
export default class ChartRepositoriesCreateEditPo extends PagePo {
private static createPath(clusterId: string, product: 'apps' | 'manager', repoName?: string ) {
const root = `/c/${ clusterId }/${ product }/catalog.cattle.io.clusterrepo`;
return repoName ? `${ root }/${ repoName }` : `${ root }/create`;
}
static goTo(path: string): Cypress.Chainable<Cypress.AUTWindow> {
throw new Error('invalid');
}
constructor(clusterId = 'local', product: 'apps' | 'manager', id?: string) {
super(ChartRepositoriesCreateEditPo.createPath(clusterId, product, id));
}
nameNsDescription() {
return new NameNsDescription(this.self());
}
gitRepoUrl(): LabeledInputPo {
return LabeledInputPo.byLabel(this.self(), 'Git Repo URL');
}
gitBranch(): LabeledInputPo {
return LabeledInputPo.byLabel(this.self(), 'Git Branch');
}
authentication(): LabeledSelectPo {
return new LabeledSelectPo('.vs__dropdown-toggle');
}
repoRadioBtn(): RadioGroupInputPo {
return new RadioGroupInputPo('[data-testid="clusterrepo-radio-input"]');
}
saveCreateForm(): AsyncButtonPo {
return new AsyncButtonPo('[data-testid="action-button-async-button"]', this.self());
}
saveAndWaitForRequests(method: string, url: string) {
cy.intercept(method, url).as('request');
this.saveCreateForm().click();
return cy.wait('@request', { timeout: 10000 });
}
}

View File

@ -0,0 +1,26 @@
import LabeledInputPo from '@/cypress/e2e/po/components/labeled-input.po';
import LabeledSelectPo from '@/cypress/e2e/po/components/labeled-select.po';
import BaseCloudCredentialsPo from '@/cypress/e2e/po/edit/base-cloud-credentials.po';
import NameNsDescription from '@/cypress/e2e/po/components/name-ns-description.po';
import ResourceDetailPo from '@/cypress/e2e/po/edit/resource-detail.po';
export default class AmazonCloudCredentialsCreateEditPo extends BaseCloudCredentialsPo {
nameNsDescription() {
return new NameNsDescription(this.self());
}
accessKey(): LabeledInputPo {
return LabeledInputPo.byLabel(this.self(), 'Access Key');
}
secretKey(): LabeledInputPo {
return LabeledInputPo.byLabel(this.self(), 'Secret Key');
}
defaultRegion(): LabeledSelectPo {
return new LabeledSelectPo('.vs__dropdown-toggle');
}
saveCreateForm(): ResourceDetailPo {
return new ResourceDetailPo(this.self());
}
}

View File

@ -0,0 +1,21 @@
import PagePo from '@/cypress/e2e/po/pages/page.po';
import ResourceDetailPo from '@/cypress/e2e/po/edit/resource-detail.po';
export default class MachineDeploymentsCreateEditPo extends PagePo {
private static createPath(clusterId: string, nsName?: string, machineSetName?: string ) {
const root = `/c/${ clusterId }/manager/cluster.x-k8s.io.machinedeployment`;
return nsName && machineSetName ? `${ root }/${ nsName }/${ machineSetName }` : `${ root }/create`;
}
static goTo(path: string): Cypress.Chainable<Cypress.AUTWindow> {
throw new Error('invalid');
}
constructor(clusterId = 'local', nsName?: string, machineSetName?: string) {
super(MachineDeploymentsCreateEditPo.createPath(clusterId, nsName, machineSetName));
}
saveCreateForm(): ResourceDetailPo {
return new ResourceDetailPo(this.self());
}
}

View File

@ -0,0 +1,21 @@
import PagePo from '@/cypress/e2e/po/pages/page.po';
import ResourceDetailPo from '@/cypress/e2e/po/edit/resource-detail.po';
export default class MachineSetsCreateEditPo extends PagePo {
private static createPath(clusterId: string, nsName?: string, machineSetName?: string ) {
const root = `/c/${ clusterId }/manager/cluster.x-k8s.io.machineset`;
return nsName && machineSetName ? `${ root }/${ nsName }/${ machineSetName }` : `${ root }/create`;
}
static goTo(path: string): Cypress.Chainable<Cypress.AUTWindow> {
throw new Error('invalid');
}
constructor(clusterId = 'local', nsName?: string, machineSetName?: string) {
super(MachineSetsCreateEditPo.createPath(clusterId, nsName, machineSetName));
}
saveCreateForm(): ResourceDetailPo {
return new ResourceDetailPo(this.self());
}
}

View File

@ -0,0 +1,22 @@
import PagePo from '@/cypress/e2e/po/pages/page.po';
import ResourceDetailPo from '@/cypress/e2e/po/edit/resource-detail.po';
export default class MachinesCreateEditPo extends PagePo {
private static createPath(clusterId: string, nsName?: string, machineName?: string ) {
const root = `/c/${ clusterId }/manager/cluster.x-k8s.io.machine`;
return nsName && machineName ? `${ root }/${ nsName }/${ machineName }` : `${ root }/create`;
}
static goTo(path: string): Cypress.Chainable<Cypress.AUTWindow> {
throw new Error('invalid');
}
constructor(clusterId = 'local', nsName?: string, machineName?: string) {
super(MachinesCreateEditPo.createPath(clusterId, nsName, machineName));
}
saveCreateForm(): ResourceDetailPo {
return new ResourceDetailPo(this.self());
}
}

View File

@ -0,0 +1,49 @@
import PagePo from '@/cypress/e2e/po/pages/page.po';
import NameNsDescription from '@/cypress/e2e/po/components/name-ns-description.po';
import LabeledSelectPo from '@/cypress/e2e/po/components/labeled-select.po';
import InputPo from '@/cypress/e2e/po/components/input.po';
import CheckboxInputPo from '@/cypress/e2e/po/components/checkbox-input.po';
export default class PodSecurityAdmissionsCreateEditPo extends PagePo {
private static createPath(clusterId: string, id?: string ) {
const root = `/c/${ clusterId }/manager/management.cattle.io.podsecurityadmissionconfigurationtemplate`;
return id ? `${ root }/${ id }` : `${ root }/create`;
}
static goTo(path: string): Cypress.Chainable<Cypress.AUTWindow> {
throw new Error('invalid');
}
constructor(clusterId = 'local', id?: string) {
super(PodSecurityAdmissionsCreateEditPo.createPath(clusterId, id));
}
nameNsDescription() {
return new NameNsDescription(this.self());
}
psaControlLevel(itemRow: number, optionIndex: number) {
const selectMode = new LabeledSelectPo(`[data-testid="pod-security-admission--psaControl-${ itemRow }-level"]`, this.self());
selectMode.toggle();
selectMode.clickOption(optionIndex);
}
psaControlVersion(itemRow: number, text: string) {
const setVersion = new InputPo(`[data-testid="pod-security-admission--psaControl-${ itemRow }-version"]`, this.self());
setVersion.set(text);
}
setExemptionsCheckbox(optionIndex: number) {
const setExemptionsCheckbox = new CheckboxInputPo(`[data-testid="pod-security-admission--psaExemptionsControl-${ optionIndex }-active"]`);
setExemptionsCheckbox.set();
}
setExemptionsInput(optionIndex: number, text: string) {
const setExemptionsInputbox = new InputPo(`[data-testid="pod-security-admission--psaExemptionsControl-${ optionIndex }-value"]`);
setExemptionsInputbox.set(text);
}
}

View File

@ -0,0 +1,50 @@
import PagePo from '@/cypress/e2e/po/pages/page.po';
import ClusterManagerCreatePagePo from '@/cypress/e2e/po/edit/provisioning.cattle.io.cluster/create/cluster-create.po';
import EmberInputPo from '@/cypress/e2e/po/components/ember/ember-input.po';
import ClusterManagerCreateRKE1PagePo from '@/cypress/e2e/po/edit/provisioning.cattle.io.cluster/create/cluster-create-rke1.po';
import EmberAccordionPo from '@/cypress/e2e/po/components/ember/ember-accordion.po';
import EmberFormMembersPo from '@/cypress/e2e/po/components/ember/ember-form-members.po';
import EmberCheckboxInputPo from '@/cypress/e2e/po/components/ember/ember-checkbox-input.po';
import EmberSelectPo from '@/cypress/e2e/po/components/ember/ember-select.po';
/**
* Create page for an RKE1 amazonec2 cluster
*/
export default class ClusterManagerCreateRke1Amazonec2PagePo extends ClusterManagerCreateRKE1PagePo {
static url = `${ ClusterManagerCreatePagePo.url }/create?type=amazonec2`
static goTo(): Cypress.Chainable<Cypress.AUTWindow> {
return PagePo.goTo(ClusterManagerCreateRke1Amazonec2PagePo.url);
}
goToAmazonec2ClusterCreation(): Cypress.Chainable<Cypress.AUTWindow> {
return PagePo.goTo(`${ ClusterManagerCreatePagePo.url }?type=amazonec2`);
}
clusterName(): EmberInputPo {
return new EmberInputPo('[data-testid="form-name-description__name"]');
}
memberRoles(): EmberAccordionPo {
return new EmberAccordionPo('cru-cluster__members');
}
memberRolesFormMembers(): EmberFormMembersPo {
return new EmberFormMembersPo('[data-testid="cru-cluster__members__form"]') ;
}
clusterTemplateCheckbox(): EmberCheckboxInputPo {
return new EmberCheckboxInputPo('.cluster-template-select');
}
nodeTemplateDropdown(): EmberSelectPo {
return new EmberSelectPo('.main-row .new-select > select');
}
rkeTemplateAndRevisionDropdown(): EmberSelectPo {
return new EmberSelectPo('.new-select > select');
}
selectedOption(): EmberSelectPo {
return new EmberSelectPo('.new-select > select option:selected');
}
}

View File

@ -4,6 +4,8 @@ import EmberInputPo from '@/cypress/e2e/po/components/ember/ember-input.po';
import ClusterManagerCreateRKE1PagePo from '@/cypress/e2e/po/edit/provisioning.cattle.io.cluster/create/cluster-create-rke1.po';
import EmberAccordionPo from '@/cypress/e2e/po/components/ember/ember-accordion.po';
import EmberFormMembersPo from '@/cypress/e2e/po/components/ember/ember-form-members.po';
import EmberCheckboxInputPo from '@/cypress/e2e/po/components/ember/ember-checkbox-input.po';
import EmberSelectPo from '@/cypress/e2e/po/components/ember/ember-select.po';
/**
* Create page for an RKE1 custom cluster
@ -32,6 +34,18 @@ export default class ClusterManagerCreateRke1CustomPagePo extends ClusterManager
return new EmberFormMembersPo('[data-testid="cru-cluster__members__form"]') ;
}
clusterTemplateCheckbox(): EmberCheckboxInputPo {
return new EmberCheckboxInputPo('.cluster-template-select');
}
rkeTemplateAndRevisionDropdown(): EmberSelectPo {
return new EmberSelectPo('.new-select > select');
}
selectedOption(): EmberSelectPo {
return new EmberSelectPo('.new-select > select option:selected');
}
// Roles Page
nodeCommand(): EmberAccordionPo {

View File

@ -1,10 +0,0 @@
import BaseResourceList from '@/cypress/e2e/po/lists/base-resource-list.po';
/**
* List component for catalog.cattle.io.clusterrepo resources
*/
export default class RepoListPo extends BaseResourceList {
actionMenu(repoName: string) {
return this.resourceTable().sortableTable().rowActionMenuOpen(repoName);
}
}

View File

@ -0,0 +1,22 @@
import BaseResourceList from '@/cypress/e2e/po/lists/base-resource-list.po';
/**
* List component for catalog.cattle.io.clusterrepo resources
*/
export default class ChartRepositoriesListPo extends BaseResourceList {
actionMenu(repoName: string) {
return this.resourceTable().sortableTable().rowActionMenuOpen(repoName);
}
openBulkActionDropdown() {
return this.resourceTable().sortableTable().bulkActionDropDownOpen();
}
bulkActionButton(name: string) {
return this.resourceTable().sortableTable().bulkActionDropDownButton(name);
}
details(name: string, index: number) {
return this.resourceTable().sortableTable().rowWithName(name).column(index);
}
}

View File

@ -0,0 +1,7 @@
import BaseResourceList from '@/cypress/e2e/po/lists/base-resource-list.po';
export default class CloudCredentialsListPo extends BaseResourceList {
details(name: string, index: number) {
return this.resourceTable().sortableTable().rowWithName(name).column(index);
}
}

View File

@ -0,0 +1,15 @@
import BaseResourceList from '@/cypress/e2e/po/lists/base-resource-list.po';
export default class MachineDeploymentsListPo extends BaseResourceList {
openBulkActionDropdown() {
return this.resourceTable().sortableTable().bulkActionDropDownOpen();
}
bulkActionButton(name: string) {
return this.resourceTable().sortableTable().bulkActionDropDownButton(name);
}
details(name: string, index: number) {
return this.resourceTable().sortableTable().rowWithName(name).column(index);
}
}

View File

@ -0,0 +1,15 @@
import BaseResourceList from '@/cypress/e2e/po/lists/base-resource-list.po';
export default class MachineSetsListPo extends BaseResourceList {
openBulkActionDropdown() {
return this.resourceTable().sortableTable().bulkActionDropDownOpen();
}
bulkActionButton(name: string) {
return this.resourceTable().sortableTable().bulkActionDropDownButton(name);
}
details(name: string, index: number) {
return this.resourceTable().sortableTable().rowWithName(name).column(index);
}
}

View File

@ -0,0 +1,7 @@
import BaseResourceList from '@/cypress/e2e/po/lists/base-resource-list.po';
export default class MachinesListPo extends BaseResourceList {
details(name: string, index: number) {
return this.resourceTable().sortableTable().rowWithName(name).column(index);
}
}

View File

@ -0,0 +1,7 @@
import BaseResourceList from '@/cypress/e2e/po/lists/base-resource-list.po';
export default class PodSecurityAdmissionListPo extends BaseResourceList {
details(name: string, index: number) {
return this.resourceTable().sortableTable().rowWithName(name).column(index);
}
}

View File

@ -4,6 +4,18 @@ import BaseResourceList from '@/cypress/e2e/po/lists/base-resource-list.po';
* List component for provisioning.cattle.io.cluster resources
*/
export default class ProvClusterListPo extends BaseResourceList {
openBulkActionDropdown() {
return this.resourceTable().sortableTable().bulkActionDropDownOpen();
}
bulkActionButton(name: string) {
return this.resourceTable().sortableTable().bulkActionDropDownButton(name);
}
downloadKubeConfig() {
return cy.getId('sortable-table-downloadKubeConfig');
}
state(clusterName: string) {
return this.resourceTable().sortableTable().rowWithName(clusterName).column(1);
}

View File

@ -0,0 +1,58 @@
import PagePo from '@/cypress/e2e/po/pages/page.po';
import ChartRepositoriesListPo from '@/cypress/e2e/po/lists/chart-repositories.po';
import ChartRepositoriesCreateEditPo from '@/cypress/e2e/po/edit/chart-repositories.po';
import ProductNavPo from '@/cypress/e2e/po/side-bars/product-side-nav.po';
import BurgerMenuPo from '@/cypress/e2e/po/side-bars/burger-side-menu.po';
/**
* List page for catalog.cattle.io.clusterrepo resources
*/
export default class ChartRepositoriesPagePo extends PagePo {
private static createPath(clusterId: string, product: 'apps' | 'manager') {
return `/c/${ clusterId }/${ product }/catalog.cattle.io.clusterrepo`;
}
static goTo(clusterId: string, product: 'apps' | 'manager'): Cypress.Chainable<Cypress.AUTWindow> {
return super.goTo(ChartRepositoriesPagePo.createPath(clusterId, product));
}
constructor(private clusterId = 'local', private product: 'apps' | 'manager') {
super(ChartRepositoriesPagePo.createPath(clusterId, product));
}
static navTo() {
const sideNav = new ProductNavPo();
BurgerMenuPo.burgerMenuNavToMenubyLabel('Cluster Management');
sideNav.groups().contains('Advanced').click();
sideNav.navToSideMenuEntryByLabel('Repositories');
}
createEditRepositories(repoName? : string): ChartRepositoriesCreateEditPo {
return new ChartRepositoriesCreateEditPo(this.clusterId, this.product, repoName);
}
list(): ChartRepositoriesListPo {
return new ChartRepositoriesListPo('[data-testid="app-cluster-repo-list"]');
}
/**
* Convenience method
*/
sortableTable() {
return this.list().resourceTable().sortableTable();
}
create() {
return this.list().masthead().actions().contains('Create')
.click();
}
waitForGoTo(endpoint: string) {
const interceptName = `validateGoTo${ Date.now() }`;
cy.intercept('GET', endpoint).as(interceptName);
this.goTo();
cy.wait(`@${ interceptName }`, { timeout: 15000 }).its('response.statusCode').should('eq', 200);
}
}

View File

@ -0,0 +1,39 @@
import PagePo from '@/cypress/e2e/po/pages/page.po';
import CloudCredentialsCreateEditPo from '@/cypress/e2e/po/edit/cloud-credentials-amazon.po';
import CloudCredentialsListPo from '@/cypress/e2e/po/lists/cloud-credentials-list.po';
import ProductNavPo from '@/cypress/e2e/po/side-bars/product-side-nav.po';
import BurgerMenuPo from '@/cypress/e2e/po/side-bars/burger-side-menu.po';
export default class CloudCredentialsPagePo extends PagePo {
private static createPath(clusterId: string) {
return `/c/${ clusterId }/manager/cloudCredential`;
}
static goTo(clusterId: string): Cypress.Chainable<Cypress.AUTWindow> {
return super.goTo(CloudCredentialsPagePo.createPath(clusterId));
}
constructor(private clusterId = 'local') {
super(CloudCredentialsPagePo.createPath(clusterId));
}
static navTo() {
const sideNav = new ProductNavPo();
BurgerMenuPo.burgerMenuNavToMenubyLabel('Cluster Management');
sideNav.navToSideMenuEntryByLabel('Cloud Credentials');
}
create() {
return this.list().masthead().actions().contains('Create')
.click();
}
createEditCloudCreds(id?: string): CloudCredentialsCreateEditPo {
return new CloudCredentialsCreateEditPo(this.clusterId, id);
}
list(): CloudCredentialsListPo {
return new CloudCredentialsListPo('[data-testid="cluster-list-container"]');
}
}

View File

@ -19,7 +19,6 @@ export default class ClusterManagerListPagePo extends PagePo {
}
static navTo() {
BurgerMenuPo.toggle();
BurgerMenuPo.burgerMenuNavToMenubyLabel('Cluster Management');
}

View File

@ -0,0 +1,44 @@
import PagePo from '@/cypress/e2e/po/pages/page.po';
import CodeMirrorPo from '@/cypress/e2e/po/components/code-mirror.po';
import MachineDeploymentsCreateEditPo from '@/cypress/e2e/po/edit/machine-deployments.po';
import MachineDeploymentsListPo from '@/cypress/e2e/po/lists/machine-deployments-list.po';
import ProductNavPo from '@/cypress/e2e/po/side-bars/product-side-nav.po';
import BurgerMenuPo from '@/cypress/e2e/po/side-bars/burger-side-menu.po';
export default class MachineDeploymentsPagePo extends PagePo {
private static createPath(clusterId: string) {
return `/c/${ clusterId }/manager/cluster.x-k8s.io.machinedeployment`;
}
static goTo(clusterId: string): Cypress.Chainable<Cypress.AUTWindow> {
return super.goTo(MachineDeploymentsPagePo.createPath(clusterId));
}
constructor(private clusterId = 'local') {
super(MachineDeploymentsPagePo.createPath(clusterId));
}
static navTo() {
const sideNav = new ProductNavPo();
BurgerMenuPo.burgerMenuNavToMenubyLabel('Cluster Management');
sideNav.groups().contains('Advanced').click();
sideNav.navToSideMenuEntryByLabel('MachineDeployments');
}
create() {
return this.list().masthead().actions().contains('Create from YAML')
.click();
}
createEditMachineDeployment(nsName?: string, machineSetName?: string): MachineDeploymentsCreateEditPo {
return new MachineDeploymentsCreateEditPo(this.clusterId, nsName, machineSetName);
}
list(): MachineDeploymentsListPo {
return new MachineDeploymentsListPo('[data-testid="cluster-list-container"]');
}
yamlEditor(): CodeMirrorPo {
return CodeMirrorPo.bySelector(this.self(), '[data-testid="yaml-editor-code-mirror"]');
}
}

View File

@ -0,0 +1,45 @@
import PagePo from '@/cypress/e2e/po/pages/page.po';
import CodeMirrorPo from '@/cypress/e2e/po/components/code-mirror.po';
import MachineSetsCreateEditPo from '@/cypress/e2e/po/edit/machine-sets.po';
import MachineSetsListPo from '@/cypress/e2e/po/lists/machine-set-list.po';
import ProductNavPo from '@/cypress/e2e/po/side-bars/product-side-nav.po';
import BurgerMenuPo from '@/cypress/e2e/po/side-bars/burger-side-menu.po';
export default class MachineSetsPagePo extends PagePo {
private static createPath(clusterId: string) {
return `/c/${ clusterId }/manager/cluster.x-k8s.io.machineset`;
}
static goTo(clusterId: string): Cypress.Chainable<Cypress.AUTWindow> {
return super.goTo(MachineSetsPagePo.createPath(clusterId));
}
constructor(private clusterId = 'local') {
super(MachineSetsPagePo.createPath(clusterId));
}
static navTo() {
const sideNav = new ProductNavPo();
BurgerMenuPo.burgerMenuNavToMenubyLabel('Cluster Management');
sideNav.groups().contains('Advanced').click();
sideNav.navToSideMenuEntryByLabel('MachineSets');
}
create() {
return this.list().masthead().actions().contains('Create from YAML')
.click();
}
createEditMachineSet(nsName?: string, machineSetName?: string): MachineSetsCreateEditPo {
return new MachineSetsCreateEditPo(this.clusterId, nsName, machineSetName);
}
list(): MachineSetsListPo {
return new MachineSetsListPo('[data-testid="cluster-list-container"]');
}
yamlEditor(): CodeMirrorPo {
return CodeMirrorPo.bySelector(this.self(), '[data-testid="yaml-editor-code-mirror"]');
}
}

View File

@ -0,0 +1,45 @@
import PagePo from '@/cypress/e2e/po/pages/page.po';
import MachinesCreateEditPo from '@/cypress/e2e/po/edit/machines.po';
import MachinesListPo from '@/cypress/e2e/po/lists/machines-list.po';
import CodeMirrorPo from '@/cypress/e2e/po/components/code-mirror.po';
import ProductNavPo from '@/cypress/e2e/po/side-bars/product-side-nav.po';
import BurgerMenuPo from '@/cypress/e2e/po/side-bars/burger-side-menu.po';
export default class MachinesPagePo extends PagePo {
private static createPath(clusterId: string) {
return `/c/${ clusterId }/manager/cluster.x-k8s.io.machine`;
}
static goTo(clusterId: string): Cypress.Chainable<Cypress.AUTWindow> {
return super.goTo(MachinesPagePo.createPath(clusterId));
}
constructor(private clusterId = 'local') {
super(MachinesPagePo.createPath(clusterId));
}
static navTo() {
const sideNav = new ProductNavPo();
BurgerMenuPo.burgerMenuNavToMenubyLabel('Cluster Management');
sideNav.groups().contains('Advanced').click();
sideNav.navToSideMenuEntryByLabel('Machines');
}
create() {
return this.list().masthead().actions().contains('Create from YAML')
.click();
}
createEditMachines(nsName?: string, machineName?: string): MachinesCreateEditPo {
return new MachinesCreateEditPo(this.clusterId, nsName, machineName);
}
list(): MachinesListPo {
return new MachinesListPo('[data-testid="cluster-list-container"]');
}
yamlEditor(): CodeMirrorPo {
return CodeMirrorPo.bySelector(this.self(), '[data-testid="yaml-editor-code-mirror"]');
}
}

View File

@ -0,0 +1,39 @@
import PagePo from '@/cypress/e2e/po/pages/page.po';
import EmberSortableTablePo from '@/cypress/e2e/po/components/ember/ember-sortable-table.po';
import EmberModalAddNodeTemplatePo from '@/cypress/e2e/po/components/ember/ember-modal-add-node-template.po';
import ProductNavPo from '@/cypress/e2e/po/side-bars/product-side-nav.po';
import BurgerMenuPo from '@/cypress/e2e/po/side-bars/burger-side-menu.po';
export default class NodeTemplatesPagePo extends PagePo {
private static createPath(clusterId: string) {
return `/c/${ clusterId }/manager/pages/node-templates`;
}
static goTo(clusterId: string): Cypress.Chainable<Cypress.AUTWindow> {
return super.goTo(NodeTemplatesPagePo.createPath(clusterId));
}
constructor(clusterId: string) {
super(NodeTemplatesPagePo.createPath(clusterId));
}
static navTo() {
const sideNav = new ProductNavPo();
BurgerMenuPo.burgerMenuNavToMenubyLabel('Cluster Management');
sideNav.groups().contains('RKE1 Configuration').click();
sideNav.navToSideMenuEntryByLabel('Node Templates');
}
addNodeTemplateModal(): EmberModalAddNodeTemplatePo {
return new EmberModalAddNodeTemplatePo();
}
list(): EmberSortableTablePo {
return new EmberSortableTablePo('.sortable-table');
}
addTemplate() {
return cy.iFrame().contains('.right-buttons .btn', 'Add Template');
}
}

View File

@ -0,0 +1,39 @@
import PagePo from '@/cypress/e2e/po/pages/page.po';
import PodSecurityAdmissionsCreateEditPo from '@/cypress/e2e/po/edit/pod-security-admissions.po';
import PodSecurityAdmissionListPo from '@/cypress/e2e/po/lists/pod-security-admissions-list.po';
import ProductNavPo from '@/cypress/e2e/po/side-bars/product-side-nav.po';
import BurgerMenuPo from '@/cypress/e2e/po/side-bars/burger-side-menu.po';
export default class PodSecurityAdmissionsPagePo extends PagePo {
private static createPath(clusterId: string) {
return `/c/${ clusterId }/manager/management.cattle.io.podsecurityadmissionconfigurationtemplate`;
}
static goTo(clusterId: string): Cypress.Chainable<Cypress.AUTWindow> {
return super.goTo(PodSecurityAdmissionsPagePo.createPath(clusterId));
}
constructor(private clusterId = 'local') {
super(PodSecurityAdmissionsPagePo.createPath(clusterId));
}
static navTo() {
const sideNav = new ProductNavPo();
BurgerMenuPo.burgerMenuNavToMenubyLabel('Cluster Management');
sideNav.groups().contains('Advanced').click();
sideNav.navToSideMenuEntryByLabel('Pod Security Admissions');
}
create() {
return this.list().masthead().actions().contains('Create')
.click();
}
createPodSecurityAdmissionForm(id? : string): PodSecurityAdmissionsCreateEditPo {
return new PodSecurityAdmissionsCreateEditPo(this.clusterId, id);
}
list(): PodSecurityAdmissionListPo {
return new PodSecurityAdmissionListPo('[data-testid="cluster-list-container"]');
}
}

View File

@ -0,0 +1,54 @@
import PagePo from '@/cypress/e2e/po/pages/page.po';
import EmberSortableTablePo from '@/cypress/e2e/po/components/ember/ember-sortable-table.po';
import EmberSelectPo from '@/cypress/e2e/po/components/ember/ember-select.po';
import EmberAddPodSecurityTemplatePo from '@/cypress/e2e/po/components/ember/ember-form-pod-security-template.po';
import ProductNavPo from '@/cypress/e2e/po/side-bars/product-side-nav.po';
import BurgerMenuPo from '@/cypress/e2e/po/side-bars/burger-side-menu.po';
export default class PodSecurityPoliciesTemplatesPagePo extends PagePo {
private static createPath(clusterId: string) {
return `/c/${ clusterId }/manager/pages/pod-security-policies`;
}
static goTo(clusterId: string): Cypress.Chainable<Cypress.AUTWindow> {
return super.goTo(PodSecurityPoliciesTemplatesPagePo.createPath(clusterId));
}
constructor(clusterId: string) {
super(PodSecurityPoliciesTemplatesPagePo.createPath(clusterId));
}
static navTo() {
const sideNav = new ProductNavPo();
BurgerMenuPo.burgerMenuNavToMenubyLabel('Cluster Management');
sideNav.groups().contains('Advanced').click();
sideNav.navToSideMenuEntryByLabel('Pod Security Policy Templates');
}
addPodSecurityTemplateForm(): EmberAddPodSecurityTemplatePo {
return new EmberAddPodSecurityTemplatePo('.container');
}
list(): EmberSortableTablePo {
return new EmberSortableTablePo('.sortable-table');
}
addPolicyTemplate() {
return cy.iFrame().contains('.right-buttons .btn', 'Add Policy Template');
}
bulkActions(label: string) {
return cy.iFrame().contains('.bulk-actions', label);
}
actionMenu(): EmberSelectPo {
return new EmberSelectPo('.ember-basic-dropdown-content');
}
// details view
templateDescription(label: string) {
return cy.iFrame().contains('.banner-message p', label);
}
}

View File

@ -0,0 +1,64 @@
import PagePo from '@/cypress/e2e/po/pages/page.po';
import EmberSortableTablePo from '@/cypress/e2e/po/components/ember/ember-sortable-table.po';
import EmberSelectPo from '@/cypress/e2e/po/components/ember/ember-select.po';
import EmberModalClusterDriverPo from '@/cypress/e2e/po/components/ember/ember-modal-add-edit-cluster-driver.po';
import EmberModalNodeDriverPo from '@/cypress/e2e/po/components/ember/ember-modal-add-edit-node-driver.po';
import BurgerMenuPo from '@/cypress/e2e/po/side-bars/burger-side-menu.po';
import ProductNavPo from '@/cypress/e2e/po/side-bars/product-side-nav.po';
export default class RkeDriversPagePo extends PagePo {
private static createPath(clusterId: string) {
return `/c/${ clusterId }/manager/pages/rke-drivers`;
}
static goTo(clusterId: string): Cypress.Chainable<Cypress.AUTWindow> {
return super.goTo(RkeDriversPagePo.createPath(clusterId));
}
constructor(clusterId: string) {
super(RkeDriversPagePo.createPath(clusterId));
}
static navTo() {
const sideNav = new ProductNavPo();
BurgerMenuPo.burgerMenuNavToMenubyLabel('Cluster Management');
sideNav.navToSideMenuEntryByLabel('Drivers');
}
list(): EmberSortableTablePo {
return new EmberSortableTablePo('table.grid.sortable-table');
}
refreshKubMetadata() {
return cy.iFrame().contains('.right-buttons .btn', 'Refresh Kubernetes Metadata');
}
addClusterDriver() {
return cy.iFrame().contains('.right-buttons .btn', 'Add Cluster Driver');
}
addNodeDriver() {
return cy.iFrame().contains('.right-buttons .btn', 'Add Node Driver');
}
createEditClusterDriver(): EmberModalClusterDriverPo {
return new EmberModalClusterDriverPo();
}
createEditNodeDriver(): EmberModalNodeDriverPo {
return new EmberModalNodeDriverPo();
}
/**
* Get tab by name
* @param tabName Cluster Drivers or Node Drivers
* @returns
*/
tabs(tabName: string) {
return cy.iFrame().contains('.tab-nav li', tabName);
}
actionMenu(): EmberSelectPo {
return new EmberSelectPo('.ember-basic-dropdown-content');
}
}

View File

@ -0,0 +1,48 @@
import PagePo from '@/cypress/e2e/po/pages/page.po';
import EmberSortableTablePo from '@/cypress/e2e/po/components/ember/ember-sortable-table.po';
import EmberSelectPo from '@/cypress/e2e/po/components/ember/ember-select.po';
import EmberFormRkeTemplatesPo from '@/cypress/e2e/po/components/ember/ember-form-rke-templates.po';
import ProductNavPo from '@/cypress/e2e/po/side-bars/product-side-nav.po';
import BurgerMenuPo from '@/cypress/e2e/po/side-bars/burger-side-menu.po';
export default class RkeTemplatesPagePo extends PagePo {
private static createPath(clusterId: string) {
return `/c/${ clusterId }/manager/pages/rke-templates`;
}
static goTo(clusterId: string): Cypress.Chainable<Cypress.AUTWindow> {
return super.goTo(RkeTemplatesPagePo.createPath(clusterId));
}
constructor(clusterId: string) {
super(RkeTemplatesPagePo.createPath(clusterId));
}
static navTo() {
const sideNav = new ProductNavPo();
BurgerMenuPo.burgerMenuNavToMenubyLabel('Cluster Management');
sideNav.groups().contains('RKE1 Configuration').click();
sideNav.navToSideMenuEntryByLabel('RKE Templates');
}
addTemplate() {
return cy.iFrame().contains('.right-buttons .btn', 'Add Template');
}
groupRow(): EmberSortableTablePo {
return new EmberSortableTablePo('table.sortable-table .group-row');
}
mainRow(): EmberSortableTablePo {
return new EmberSortableTablePo('table.sortable-table .main-row');
}
actionMenu(): EmberSelectPo {
return new EmberSelectPo('.ember-basic-dropdown-content');
}
form(): EmberFormRkeTemplatesPo {
return new EmberFormRkeTemplatesPo('form.horizontal-form');
}
}

View File

@ -4,9 +4,9 @@ import LabeledSelectPo from '@/cypress/e2e/po/components/labeled-select.po';
import TabbedPo from '@/cypress/e2e/po/components/tabbed.po';
import ActionMenuPo from '@/cypress/e2e/po/components/action-menu.po';
import NameNsDescriptionPo from '@/cypress/e2e/po/components/name-ns-description.po';
import ReposListPagePo from '@/cypress/e2e/po/pages/repositories.po';
import AppClusterRepoEditPo from '@/cypress/e2e/po/edit/catalog.cattle.io.clusterrepo.po';
import RepositoriesPagePo from '@/cypress/e2e/po/pages/chart-repositories.po';
import BannersPo from '@/cypress/e2e/po/components/banners.po';
import ChartRepositoriesCreateEditPo from '@/cypress/e2e/po/edit/chart-repositories.po';
export default class ExtensionsPagePo extends PagePo {
static url = '/c/local/uiplugins'
@ -90,25 +90,26 @@ export default class ExtensionsPagePo extends PagePo {
this.manageReposClick();
// create a new clusterrepo
const appRepoList = new ReposListPagePo('local', 'apps');
const appRepoList = new RepositoriesPagePo('local', 'apps');
appRepoList.waitForPage();
appRepoList.waitForGoTo('/v1/catalog.cattle.io.clusterrepos?exclude=metadata.managedFields');
appRepoList.create();
const appRepoCreate = new AppClusterRepoEditPo('local', 'create');
const appRepoCreate = new ChartRepositoriesCreateEditPo('local', 'apps');
appRepoCreate.waitForPage();
// fill the form
appRepoCreate.selectRadioOptionGitRepo(1);
appRepoCreate.repoRadioBtn().set(1);
appRepoCreate.nameNsDescription().name().self().scrollIntoView()
.should('be.visible');
appRepoCreate.nameNsDescription().name().set(name);
appRepoCreate.enterGitRepoName(repo);
appRepoCreate.enterGitBranchName(branch);
appRepoCreate.gitRepoUrl().set(repo);
appRepoCreate.gitBranch().set(branch);
// save it
return appRepoCreate.save();
return appRepoCreate.saveAndWaitForRequests('POST', '/v1/catalog.cattle.io.clusterrepos');
}
// ------------------ extension card ------------------

View File

@ -1,6 +1,6 @@
import PagePo from '@/cypress/e2e/po/pages/page.po';
import BurgerMenuPo from '@/cypress/e2e/po/side-bars/burger-side-menu.po';
import SimpleBoxPo from '~/cypress/e2e/po/components/simple-box.po';
import SimpleBoxPo from '@/cypress/e2e/po/components/simple-box.po';
const burgerMenu = new BurgerMenuPo();

View File

@ -1,43 +0,0 @@
import PagePo from '@/cypress/e2e/po/pages/page.po';
import RepoListPo from '@/cypress/e2e/po/lists/catalog.cattle.io.clusterrepo.po';
/**
* List page for catalog.cattle.io.clusterrepo resources
*/
export default class ReposListPagePo extends PagePo {
private static createPath(clusterId: string, product: 'apps' | 'manager') {
return `/c/${ clusterId }/${ product }/catalog.cattle.io.clusterrepo`;
}
static goTo(clusterId: string, product: 'apps' | 'manager'): Cypress.Chainable<Cypress.AUTWindow> {
return super.goTo(ReposListPagePo.createPath(clusterId, product));
}
constructor(clusterId: string, product: 'apps' | 'manager') {
super(ReposListPagePo.createPath(clusterId, product));
}
list(): RepoListPo {
return new RepoListPo('[data-testid="app-cluster-repo-list"]');
}
/**
* Convenience method
*/
sortableTable() {
return this.list().resourceTable().sortableTable();
}
create() {
return this.list().masthead().actions().eq(0)
.click();
}
waitForGoTo(endpoint: string) {
const interceptName = `validateGoTo${ Date.now() }`;
cy.intercept('GET', endpoint).as(interceptName);
this.goTo();
cy.wait(`@${ interceptName }`, { timeout: 15000 }).its('response.statusCode').should('eq', 200);
}
}

View File

@ -1,4 +1,4 @@
import ReposListPagePo from '@/cypress/e2e/po/pages/repositories.po';
import ReposListPagePo from '@/cypress/e2e/po/pages/chart-repositories.po';
import AppClusterRepoEditPo from '@/cypress/e2e/po/edit/catalog.cattle.io.clusterrepo.po';
describe('Apps/Repositories', { tags: ['@explorer', '@adminUser'] }, () => {

View File

@ -1,5 +1,5 @@
import ExtensionsPagePo from '@/cypress/e2e/po/pages/extensions.po';
import ReposListPagePo from '@/cypress/e2e/po/pages/repositories.po';
import RepositoriesPagePo from '@/cypress/e2e/po/pages/chart-repositories.po';
import PromptRemove from '@/cypress/e2e/po/prompts/promptRemove.po';
import BurgerMenuPo from '@/cypress/e2e/po/side-bars/burger-side-menu.po';
@ -44,7 +44,7 @@ describe('Extensions page', { tags: ['@extensions', '@adminUser'] }, () => {
extensionsPo.addReposModal().should('not.exist');
// go to repos list page
const appRepoList = new ReposListPagePo('local', 'apps');
const appRepoList = new RepositoriesPagePo('local', 'apps');
appRepoList.goTo();
appRepoList.waitForPage();
@ -96,7 +96,7 @@ describe('Extensions page', { tags: ['@extensions', '@adminUser'] }, () => {
}
});
const appRepoList = new ReposListPagePo('local', 'apps');
const appRepoList = new RepositoriesPagePo('local', 'apps');
// Ensure that the banner should be shown (by confirming that a required repo isn't there)
appRepoList.goTo();

View File

@ -1,6 +1,6 @@
import ExtensionsPagePo from '@/cypress/e2e/po/pages/extensions.po';
import { ChartsPage } from '@/cypress/e2e/po/pages/charts.po';
import ReposListPagePo from '@/cypress/e2e/po/pages/repositories.po';
import RepositoriesPagePo from '@/cypress/e2e/po/pages/chart-repositories.po';
import ProductNavPo from '@/cypress/e2e/po/side-bars/product-side-nav.po';
import KubewardenExtensionPo from '@/cypress/e2e/po/pages/extensions/kubewarden.po';
@ -54,7 +54,7 @@ describe('Kubewarden Extension', { tags: ['@extensions', '@adminUser'] }, () =>
chartsPage.waitForPage();
chartsPage.self().getId('charts-header-title').invoke('text').should('contain', 'Charts');
const appRepoList: ReposListPagePo = new ReposListPagePo('local', 'apps');
const appRepoList: RepositoriesPagePo = new RepositoriesPagePo('local', 'apps');
appRepoList.goTo();
appRepoList.waitForPage();

View File

@ -0,0 +1,116 @@
import PromptRemove from '@/cypress/e2e/po/prompts/promptRemove.po';
import CloudCredentialsPagePo from '@/cypress/e2e/po/pages/cluster-manager/cloud-credentials.po';
// will only run this in jenkins pipeline where cloud credentials are stored
describe('Cloud Credentials', { testIsolation: 'off', tags: ['@manager', '@jenkins', '@adminUser', '@standardUser'] }, () => {
const cloudCredentialsPage = new CloudCredentialsPagePo('_');
let cloudcredentialId = '';
before(() => {
cy.login();
cy.createE2EResourceName('cloudCredential').as('cloudCredentialName');
});
it('can see error when authentication fails', function() {
CloudCredentialsPagePo.navTo();
cloudCredentialsPage.waitForPage();
cloudCredentialsPage.create();
cloudCredentialsPage.createEditCloudCreds().waitForPage();
cloudCredentialsPage.createEditCloudCreds().cloudServiceOptions().selectSubTypeByIndex(0).click();
cloudCredentialsPage.createEditCloudCreds().nameNsDescription().name().set(this.cloudCredentialName);
cloudCredentialsPage.createEditCloudCreds().nameNsDescription().description().set(`${ this.cloudCredentialName }-description`);
cloudCredentialsPage.createEditCloudCreds().accessKey().set(Cypress.env('awsAccessKey'));
cloudCredentialsPage.createEditCloudCreds().secretKey().set(`${ Cypress.env('awsSecretKey') }abc`, true);
cloudCredentialsPage.createEditCloudCreds().defaultRegion().checkOptionSelected('us-west-2');
cloudCredentialsPage.createEditCloudCreds().saveCreateForm().cruResource().saveOrCreate()
.click();
cy.contains('Authentication test failed, please check your credentials').should('be.visible');
});
it('can create aws cloud credentials', function() {
CloudCredentialsPagePo.navTo();
cloudCredentialsPage.create();
cloudCredentialsPage.createEditCloudCreds().waitForPage();
cloudCredentialsPage.createEditCloudCreds().cloudServiceOptions().selectSubTypeByIndex(0).click();
cloudCredentialsPage.createEditCloudCreds().waitForPage('type=aws');
cloudCredentialsPage.createEditCloudCreds().nameNsDescription().name().set(this.cloudCredentialName);
cloudCredentialsPage.createEditCloudCreds().nameNsDescription().description().set(`${ this.cloudCredentialName }-description`);
cloudCredentialsPage.createEditCloudCreds().accessKey().set(Cypress.env('awsAccessKey'));
cloudCredentialsPage.createEditCloudCreds().secretKey().set(Cypress.env('awsSecretKey'), true);
cloudCredentialsPage.createEditCloudCreds().defaultRegion().checkOptionSelected('us-west-2');
cloudCredentialsPage.createEditCloudCreds().saveCreateForm().cruResource().saveAndWaitForRequests('POST', '/v3/cloudcredentials')
.then((req) => {
cloudcredentialId = req.response?.body.id;
});
cloudCredentialsPage.waitForPage();
// check list details
cloudCredentialsPage.list().details(this.cloudCredentialName, 2).should('be.visible');
});
it('can edit cloud credentials', function() {
CloudCredentialsPagePo.navTo();
cloudCredentialsPage.list().actionMenu(this.cloudCredentialName).getMenuItem('Edit Config').click();
cloudCredentialsPage.createEditCloudCreds(cloudcredentialId).waitForPage('mode=edit');
cloudCredentialsPage.createEditCloudCreds().nameNsDescription().description().set(`${ this.cloudCredentialName }-description-edit`);
cloudCredentialsPage.createEditCloudCreds().secretKey().set(Cypress.env('awsSecretKey'), true);
cloudCredentialsPage.createEditCloudCreds().saveCreateForm().cruResource().saveAndWaitForRequests('PUT', '/v3/cloudCredentials/**');
cloudCredentialsPage.waitForPage();
// check list details
cloudCredentialsPage.list().details(`${ this.cloudCredentialName }-description-edit`, 3).should('be.visible');
});
it('can clone cloud credentials', function() {
CloudCredentialsPagePo.navTo();
cloudCredentialsPage.list().actionMenu(`${ this.cloudCredentialName }-description-edit`).getMenuItem('Clone').click();
cloudCredentialsPage.createEditCloudCreds(cloudcredentialId).waitForPage('mode=clone');
cloudCredentialsPage.createEditCloudCreds().nameNsDescription().name().set(`${ this.cloudCredentialName }-clone`);
cloudCredentialsPage.createEditCloudCreds().accessKey().set(Cypress.env('awsAccessKey'));
cloudCredentialsPage.createEditCloudCreds().secretKey().set(Cypress.env('awsSecretKey'), true);
cloudCredentialsPage.createEditCloudCreds().defaultRegion().checkOptionSelected('us-west-2');
cloudCredentialsPage.createEditCloudCreds().saveCreateForm().cruResource().saveAndWaitForRequests('POST', '/v3/cloudcredentials');
cloudCredentialsPage.waitForPage();
// check list details
cloudCredentialsPage.list().details(`${ this.cloudCredentialName }-clone`, 1).should('be.visible');
cloudCredentialsPage.list().details(`${ this.cloudCredentialName }-description-edit`, 3).should('be.visible');
});
it('can delete cloud credentials', function() {
CloudCredentialsPagePo.navTo();
// delete clone cloud credential
cloudCredentialsPage.list().actionMenu(`${ this.cloudCredentialName }-clone`).getMenuItem('Delete').click();
const promptRemove = new PromptRemove();
cy.intercept('DELETE', '/v3/cloudCredentials/**').as('deleteCloudCred');
promptRemove.remove();
cy.wait('@deleteCloudCred');
cloudCredentialsPage.waitForPage();
// check list details
cy.contains(`${ this.cloudCredentialName }-clone`).should('not.exist');
});
it('can delete cloud credentials via bulk actions', function() {
CloudCredentialsPagePo.navTo();
// delete original cloud credential
cloudCredentialsPage.list().resourceTable().sortableTable().rowSelectCtlWithName(this.cloudCredentialName)
.set();
cloudCredentialsPage.list().resourceTable().sortableTable().deleteButton()
.click();
const promptRemove = new PromptRemove();
cy.intercept('DELETE', '/v3/cloudCredentials/**').as('deleteCloudCred');
promptRemove.remove();
cy.wait('@deleteCloudCred');
cloudCredentialsPage.waitForPage();
// check list details
cy.contains(this.cloudCredentialName).should('not.exist');
});
});

View File

@ -18,7 +18,7 @@ import ClusterManagerCreateRke1CustomPagePo from '@/cypress/e2e/po/edit/provisio
import Shell from '@/cypress/e2e/po/components/shell.po';
import BurgerMenuPo from '@/cypress/e2e/po/side-bars/burger-side-menu.po';
import { snapshot } from '@/cypress/e2e/blueprints/manager/cluster-snapshots';
import HomePagePo from '@/cypress/e2e/po/pages/home.po';
// At some point these will come from somewhere central, then we can make tools to remove resources from this or all runs
const runTimestamp = +new Date();
const runPrefix = `e2e-test-${ runTimestamp }`;
@ -394,6 +394,20 @@ describe('Cluster Manager', { testIsolation: 'off', tags: ['@manager', '@adminUs
});
});
it('can navigate to Cluster Management Page', () => {
HomePagePo.goTo();
const burgerMenu = new BurgerMenuPo();
BurgerMenuPo.toggle();
const clusterManagementNavItem = burgerMenu.links().contains(`Cluster Management`);
clusterManagementNavItem.should('exist');
clusterManagementNavItem.click();
const clusterList = new ClusterManagerListPagePo('_');
clusterList.waitForPage();
});
it(`can navigate to local cluster's explore product`, () => {
const clusterName = 'local';
const clusterDashboard = new ClusterDashboardPagePo(clusterName);
@ -404,6 +418,48 @@ describe('Cluster Manager', { testIsolation: 'off', tags: ['@manager', '@adminUs
clusterDashboard.waitForPage(undefined, 'cluster-events');
});
it('can download YAML via bulk actions', () => {
// Delete downloads directory. Need a fresh start to avoid conflicting file names
cy.deleteDownloadsFolder();
ClusterManagerListPagePo.navTo();
clusterList.list().resourceTable().sortableTable().rowElementWithName('local')
.click();
clusterList.list().openBulkActionDropdown();
clusterList.list().bulkActionButton('Download YAML').click();
const downloadedFilename = path.join(downloadsFolder, `local.yaml`);
cy.readFile(downloadedFilename).then((buffer) => {
const obj: any = jsyaml.load(buffer);
// Basic checks on the downloaded YAML
expect(obj.apiVersion).to.equal('provisioning.cattle.io/v1');
expect(obj.metadata.name).to.equal('local');
expect(obj.kind).to.equal('Cluster');
});
});
it('can download KubeConfig via bulk actions', () => {
// Delete downloads directory. Need a fresh start to avoid conflicting file names
cy.deleteDownloadsFolder();
ClusterManagerListPagePo.navTo();
clusterList.list().resourceTable().sortableTable().rowElementWithName('local')
.click();
clusterList.list().openBulkActionDropdown();
clusterList.list().bulkActionButton('Download KubeConfig').click();
const downloadedFilename = path.join(downloadsFolder, 'local.yaml');
cy.readFile(downloadedFilename).then((buffer) => {
const obj: any = jsyaml.load(buffer);
// Basic checks on the downloaded YAML
expect(obj.apiVersion).to.equal('v1');
expect(obj.clusters[0].name).to.equal('local');
expect(obj.kind).to.equal('Config');
});
});
it('can connect to kubectl shell', () => {
ClusterManagerListPagePo.navTo();
clusterList.list().actionMenu('local').getMenuItem('Kubectl Shell').click();

View File

@ -0,0 +1,151 @@
import RkeDriversPagePo from '@/cypress/e2e/po/pages/cluster-manager/rke-drivers.po';
import EmberModalPo from '@/cypress/e2e/po/components/ember/ember-modal.po';
describe('Drivers', { testIsolation: 'off', tags: ['@manager', '@adminUser'] }, () => {
const driversPage = new RkeDriversPagePo('_');
const emberModal = new EmberModalPo();
before(() => {
cy.login();
});
beforeEach(() => {
cy.viewport(1440, 900);
});
describe('Cluster Drivers', () => {
it('can refresh kubernetes metadata', () => {
RkeDriversPagePo.navTo();
driversPage.waitForPage();
cy.intercept('POST', '/v3/kontainerdrivers?action=refresh').as('refresh');
driversPage.refreshKubMetadata().click({ force: true });
cy.wait('@refresh').its('response.statusCode').should('eq', 200);
});
it('can create a cluster driver', () => {
// see https://github.com/rancher-plugins/kontainer-engine-driver-example/releases for lsit of example drivers
const downloadUrl = 'https://github.com/rancher-plugins/kontainer-engine-driver-example/releases/download/v0.2.3/kontainer-engine-driver-example-copy1-linux-amd64';
RkeDriversPagePo.navTo();
driversPage.addClusterDriver().click();
driversPage.createEditClusterDriver().formInput(2).set(downloadUrl);
cy.intercept('POST', '/v3/kontainerdriver').as('createDriver');
driversPage.createEditClusterDriver().create();
cy.wait('@createDriver').its('response.statusCode').should('eq', 201);
driversPage.list().state('Example').should('contain.text', 'Active');
});
it('can edit a cluster driver', () => {
// see https://github.com/rancher-plugins/kontainer-engine-driver-example/releases for list of example drivers
const downloadUrl = 'https://github.com/rancher-plugins/kontainer-engine-driver-example/releases/download/v0.2.3/kontainer-engine-driver-example-copy2-linux-amd64';
RkeDriversPagePo.navTo();
driversPage.list().rowActionMenuOpen(`Example`);
driversPage.actionMenu().selectMenuItemByLabel(`Edit`);
driversPage.createEditClusterDriver().formInput(2).set(downloadUrl);
cy.intercept('PUT', '/v3/kontainerDrivers/*').as('updateDriver');
driversPage.createEditClusterDriver().save();
cy.wait('@updateDriver').its('response.statusCode').should('eq', 200);
driversPage.list().state('Example').should('contain.text', 'Active');
});
it('can deactivate a cluster driver', () => {
RkeDriversPagePo.navTo();
driversPage.list().rowActionMenuOpen(`Example`);
driversPage.actionMenu().selectMenuItemByLabel(`Deactivate`);
cy.intercept('POST', '/v3/kontainerDrivers/*').as('deactivateDriver');
emberModal.deactivate();
cy.wait('@deactivateDriver').its('response.statusCode').should('eq', 200);
driversPage.list().state('Example').should('contain.text', 'Inactive');
});
it('can activate a cluster driver', () => {
RkeDriversPagePo.navTo();
driversPage.list().rowActionMenuOpen(`Example`);
cy.intercept('POST', '/v3/kontainerDrivers/*').as('activateDriver');
driversPage.actionMenu().selectMenuItemByLabel(`Activate`);
cy.wait('@activateDriver').its('response.statusCode').should('eq', 200);
driversPage.list().state('Example').should('contain.text', 'Active');
});
it('can delete a cluster driver', () => {
RkeDriversPagePo.navTo();
driversPage.list().rowActionMenuOpen(`Example`);
driversPage.actionMenu().selectMenuItemByLabel(`Delete`);
cy.intercept('DELETE', '/v3/kontainerDrivers/*').as('deleteDriver');
emberModal.delete();
cy.wait('@deleteDriver').its('response.statusCode').should('eq', 200);
driversPage.list().state('Example').should('not.exist');
});
});
// Note: This test fails due to https://github.com/rancher/dashboard/issues/10275
// skipping this tests until issue has been resolved
describe.skip('Node Drivers', () => {
it('can delete an existing node driver', () => {
RkeDriversPagePo.navTo();
cy.intercept('GET', '/v3/nodedrivers?limit=-1&sort=name').as('nodeDrivers');
driversPage.tabs('Node Drivers').should('be.visible').click();
cy.wait('@nodeDrivers');
driversPage.list().rowActionMenuOpen(`Cloud.ca`);
driversPage.actionMenu().selectMenuItemByLabel(`Delete`);
cy.intercept('DELETE', '/v3/nodeDrivers/*').as('deleteDriver');
emberModal.delete();
cy.wait('@deleteDriver').its('response.statusCode').should('eq', 200);
driversPage.list().state('Cloud.ca').should('not.exist');
});
it('can create a node driver', () => {
const downloadUrl = 'https://github.com/cloud-ca/docker-machine-driver-cloudca/files/2446837/docker-machine-driver-cloudca_v2.0.0_linux-amd64.zip';
const customUrl = 'https://objects-east.cloud.ca/v1/5ef827605f884961b94881e928e7a250/ui-driver-cloudca/v2.1.2/component.js';
const checksum = '2a55efd6d62d5f7fd27ce877d49596f4';
const domain = 'objects-east.cloud.ca';
RkeDriversPagePo.navTo();
driversPage.tabs('Node Drivers').should('be.visible').click();
driversPage.addNodeDriver().click();
driversPage.createEditNodeDriver().formInput(2).set(downloadUrl);
driversPage.createEditNodeDriver().formInput(3).set(customUrl);
driversPage.createEditNodeDriver().formInput(4).set(checksum);
driversPage.createEditNodeDriver().addDomainButton();
driversPage.createEditNodeDriver().formInput(5).set(domain);
cy.intercept('POST', '/v3/nodedriver').as('createNodeDriver');
driversPage.createEditClusterDriver().create();
cy.wait('@createNodeDriver').its('response.statusCode').should('eq', 201);
driversPage.list().state('Cloud.ca').should('contain.text', 'Active');
});
it('can edit a node driver', () => {
RkeDriversPagePo.navTo();
driversPage.tabs('Node Drivers').should('be.visible').click();
driversPage.list().rowActionMenuOpen(`Cloud.ca`);
driversPage.actionMenu().selectMenuItemByLabel(`Edit`);
cy.intercept('PUT', '/v3/nodeDrivers/*').as('updateDriver');
driversPage.createEditClusterDriver().save();
cy.wait('@updateDriver').its('response.statusCode').should('eq', 200);
driversPage.list().state('Cloud.ca').should('contain.text', 'Active');
});
it('can deactivate a node driver', () => {
RkeDriversPagePo.navTo();
driversPage.tabs('Node Drivers').should('be.visible').click();
driversPage.list().rowActionMenuOpen(`Cloud.ca`);
driversPage.actionMenu().selectMenuItemByLabel(`Deactivate`);
cy.intercept('POST', '/v3/nodeDrivers/**').as('deactivateDriver');
emberModal.deactivate();
cy.wait('@deactivateDriver').its('response.statusCode').should('eq', 200);
driversPage.list().state('Cloud.ca').should('contain.text', 'Inactive');
});
it('can activate a node driver', () => {
RkeDriversPagePo.navTo();
driversPage.tabs('Node Drivers').should('be.visible').click();
driversPage.list().rowActionMenuOpen(`Cloud.ca`);
cy.intercept('POST', '/v3/nodeDrivers/**').as('activateDriver');
driversPage.actionMenu().selectMenuItemByLabel(`Activate`);
cy.wait('@activateDriver').its('response.statusCode').should('eq', 200);
driversPage.list().state('Cloud.ca').should('contain.text', 'Active');
});
});
});

View File

@ -0,0 +1,158 @@
import PromptRemove from '@/cypress/e2e/po/prompts/promptRemove.po';
import MachineDeploymentsPagePo from '@/cypress/e2e/po/pages/cluster-manager/machine-deployments.po';
import * as path from 'path';
import * as jsyaml from 'js-yaml';
describe('MachineDeployments', { testIsolation: 'off', tags: ['@manager', '@adminUser'] }, () => {
const machineDeploymentsPage = new MachineDeploymentsPagePo('_');
const nsName = 'default';
let resourceVersion = '';
let creationTimestamp = '';
let time = '';
let uid = '';
const downloadsFolder = Cypress.config('downloadsFolder');
before(() => {
cy.login();
cy.createE2EResourceName('machinedeployments').as('machineDeploymentsName');
});
it('can create a MachineDeployments', function() {
MachineDeploymentsPagePo.navTo();
machineDeploymentsPage.waitForPage();
machineDeploymentsPage.create();
machineDeploymentsPage.createEditMachineDeployment().waitForPage('as=yaml');
cy.readFile('cypress/e2e/blueprints/cluster_management/machine-deployments.yml').then((machineDeploymentDoc) => {
// convert yaml into json to update name value
const json: any = jsyaml.load(machineDeploymentDoc);
json.metadata.name = this.machineDeploymentsName;
machineDeploymentsPage.yamlEditor().set(jsyaml.dump(json));
});
cy.intercept('POST', '/v1/cluster.x-k8s.io.machinedeployments').as('createMachineDeployment');
machineDeploymentsPage.createEditMachineDeployment().saveCreateForm().resourceYaml().saveOrCreate()
.click();
cy.wait('@createMachineDeployment').then((req) => {
resourceVersion = req.response?.body.metadata.resourceVersion;
creationTimestamp = req.response?.body.metadata.creationTimestamp;
time = req.response?.body.metadata.managedFields[0].time;
uid = req.response?.body.metadata.uid;
});
machineDeploymentsPage.waitForPage();
machineDeploymentsPage.list().details(this.machineDeploymentsName, 1).should('be.visible');
});
it('can edit a MachineDeployments', function() {
MachineDeploymentsPagePo.navTo();
machineDeploymentsPage.list().actionMenu(this.machineDeploymentsName).getMenuItem('Edit YAML').click();
machineDeploymentsPage.createEditMachineDeployment(nsName, this.machineDeploymentsName).waitForPage('mode=edit&as=yaml');
cy.readFile('cypress/e2e/blueprints/cluster_management/machine-deployments-edit.yml').then((machineSetDoc) => {
// convert yaml into json to update values
const json: any = jsyaml.load(machineSetDoc);
json.spec.template.spec.bootstrap.dataSecretName = 'secretName2';
json.metadata.creationTimestamp = creationTimestamp;
json.metadata.managedFields.time = time;
json.metadata.uid = uid;
json.metadata.name = this.machineDeploymentsName;
json.metadata.resourceVersion = resourceVersion;
machineDeploymentsPage.yamlEditor().set(jsyaml.dump(json));
});
cy.intercept('PUT', `/v1/cluster.x-k8s.io.machinedeployments/${ nsName }/${ this.machineDeploymentsName }`).as('updateMachineSet');
machineDeploymentsPage.createEditMachineDeployment().saveCreateForm().resourceYaml().saveOrCreate()
.click();
cy.wait('@updateMachineSet').its('response.statusCode').should('eq', 200);
machineDeploymentsPage.waitForPage();
// check details page
machineDeploymentsPage.list().details(this.machineDeploymentsName, 2).find('a').click();
cy.contains('secretName2').scrollIntoView().should('be.visible');
});
it('can clone a MachineDeployments', function() {
MachineDeploymentsPagePo.navTo();
machineDeploymentsPage.list().actionMenu(this.machineDeploymentsName).getMenuItem('Clone').click();
machineDeploymentsPage.createEditMachineDeployment(nsName, this.machineDeploymentsName).waitForPage('mode=clone&as=yaml');
cy.readFile('cypress/e2e/blueprints/cluster_management/machine-deployments.yml').then((machineSetDoc) => {
// convert yaml into json to update name value
const json: any = jsyaml.load(machineSetDoc);
json.metadata.name = `${ this.machineDeploymentsName }-clone`;
machineDeploymentsPage.yamlEditor().set(jsyaml.dump(json));
});
cy.intercept('POST', 'v1/cluster.x-k8s.io.machinedeployments').as('cloneMachineSet');
machineDeploymentsPage.createEditMachineDeployment().saveCreateForm().resourceYaml().saveOrCreate()
.click();
cy.wait('@cloneMachineSet').its('response.statusCode').should('eq', 201);
machineDeploymentsPage.waitForPage();
// check list details
machineDeploymentsPage.list().details(`${ this.machineDeploymentsName }-clone`, 2).should('be.visible');
});
it('can download YAML', function() {
MachineDeploymentsPagePo.navTo();
machineDeploymentsPage.list().actionMenu(this.machineDeploymentsName).getMenuItem('Download YAML').click();
const downloadedFilename = path.join(downloadsFolder, `${ this.machineDeploymentsName }.yaml`);
cy.readFile(downloadedFilename).then((buffer) => {
const obj: any = jsyaml.load(buffer);
// Basic checks on the downloaded YAML
expect(obj.apiVersion).to.equal('cluster.x-k8s.io/v1beta1');
expect(obj.metadata.name).to.equal(this.machineDeploymentsName);
expect(obj.kind).to.equal('MachineDeployment');
});
});
it('can delete a MachineDeployments', function() {
MachineDeploymentsPagePo.navTo();
// delete original cloned MachineSet
machineDeploymentsPage.list().actionMenu(`${ this.machineDeploymentsName }-clone`).getMenuItem('Delete').click();
const promptRemove = new PromptRemove();
cy.intercept('DELETE', `v1/cluster.x-k8s.io.machinedeployments/${ nsName }/${ this.machineDeploymentsName }-clone`).as('deleteMachineSet');
promptRemove.remove();
cy.wait('@deleteMachineSet');
machineDeploymentsPage.waitForPage();
// check list details
cy.contains(`${ this.machineDeploymentsName }-clone`).should('not.exist');
});
it('can delete MachineDeployments via bulk actions', function() {
MachineDeploymentsPagePo.navTo();
// delete original MachineSet
machineDeploymentsPage.list().resourceTable().sortableTable().rowSelectCtlWithName(`${ this.machineDeploymentsName }`)
.set();
machineDeploymentsPage.list().openBulkActionDropdown();
cy.intercept('DELETE', `v1/cluster.x-k8s.io.machinedeployments/${ nsName }/${ this.machineDeploymentsName }`).as('deleteMachineSet');
machineDeploymentsPage.list().bulkActionButton('Delete').click();
const promptRemove = new PromptRemove();
promptRemove.remove();
cy.wait('@deleteMachineSet');
machineDeploymentsPage.waitForPage();
// check list details
cy.contains(this.machineDeploymentsName).should('not.exist');
});
});

View File

@ -0,0 +1,155 @@
import PromptRemove from '@/cypress/e2e/po/prompts/promptRemove.po';
import MachineSetsPagePo from '@/cypress/e2e/po/pages/cluster-manager/machine-sets.po';
import * as path from 'path';
import * as jsyaml from 'js-yaml';
describe('MachineSets', { testIsolation: 'off', tags: ['@manager', '@adminUser'] }, () => {
const machineSetsPage = new MachineSetsPagePo('_');
const nsName = 'default';
let resourceVersion = '';
let creationTimestamp = '';
let time = '';
let uid = '';
const downloadsFolder = Cypress.config('downloadsFolder');
before(() => {
cy.login();
cy.createE2EResourceName('machinesets').as('machineSetName');
});
it('can create a MachineSet', function() {
MachineSetsPagePo.navTo();
machineSetsPage.waitForPage();
machineSetsPage.create();
machineSetsPage.createEditMachineSet().waitForPage('as=yaml');
cy.readFile('cypress/e2e/blueprints/cluster_management/machine-sets.yml').then((machineSetDoc) => {
// convert yaml into json to update name value
const json: any = jsyaml.load(machineSetDoc);
json.metadata.name = this.machineSetName;
machineSetsPage.yamlEditor().set(jsyaml.dump(json));
});
cy.intercept('POST', '/v1/cluster.x-k8s.io.machinesets').as('createMachineSet');
machineSetsPage.createEditMachineSet().saveCreateForm().resourceYaml().saveOrCreate()
.click();
cy.wait('@createMachineSet').then((req) => {
resourceVersion = req.response?.body.metadata.resourceVersion;
creationTimestamp = req.response?.body.metadata.creationTimestamp;
time = req.response?.body.metadata.managedFields[0].time;
uid = req.response?.body.metadata.uid;
});
machineSetsPage.waitForPage();
machineSetsPage.list().details(this.machineSetName, 1).should('be.visible');
});
it('can edit a MachineSet', function() {
MachineSetsPagePo.navTo();
machineSetsPage.list().actionMenu(this.machineSetName).getMenuItem('Edit YAML').click();
machineSetsPage.createEditMachineSet(nsName, this.machineSetName).waitForPage('mode=edit&as=yaml');
cy.readFile('cypress/e2e/blueprints/cluster_management/machine-sets-edit.yml').then((machineSetDoc) => {
// convert yaml into json to update values
const json: any = jsyaml.load(machineSetDoc);
json.spec.template.spec.bootstrap.dataSecretName = 'secretName2';
json.metadata.creationTimestamp = creationTimestamp;
json.metadata.managedFields.time = time;
json.metadata.uid = uid;
json.metadata.name = this.machineSetName;
json.metadata.resourceVersion = resourceVersion;
machineSetsPage.yamlEditor().set(jsyaml.dump(json));
});
cy.intercept('PUT', `/v1/cluster.x-k8s.io.machinesets/${ nsName }/${ this.machineSetName }`).as('updateMachineSet');
machineSetsPage.createEditMachineSet().saveCreateForm().resourceYaml().saveOrCreate()
.click();
cy.wait('@updateMachineSet').its('response.statusCode').should('eq', 200);
machineSetsPage.waitForPage();
// check details page
machineSetsPage.list().details(this.machineSetName, 2).find('a').click();
cy.contains('secretName2').should('be.visible');
});
it('can clone a MachineSet', function() {
MachineSetsPagePo.navTo();
machineSetsPage.list().actionMenu(this.machineSetName).getMenuItem('Clone').click();
machineSetsPage.createEditMachineSet(nsName, this.machineSetName).waitForPage('mode=clone&as=yaml');
cy.readFile('cypress/e2e/blueprints/cluster_management/machine-sets.yml').then((machineSetDoc) => {
// convert yaml into json to update name value
const json: any = jsyaml.load(machineSetDoc);
json.metadata.name = `${ this.machineDeploymentsName }-clone`;
machineSetsPage.yamlEditor().set(jsyaml.dump(json));
});
cy.intercept('POST', '/v1/cluster.x-k8s.io.machinesets').as('cloneMachineSet');
machineSetsPage.createEditMachineSet().saveCreateForm().resourceYaml().saveOrCreate()
.click();
cy.wait('@cloneMachineSet').its('response.statusCode').should('eq', 201);
machineSetsPage.waitForPage();
// check list details
machineSetsPage.list().details(`${ this.machineDeploymentsName }-clone`, 2).should('be.visible');
});
it('can download YAML', function() {
MachineSetsPagePo.navTo();
machineSetsPage.list().actionMenu(this.machineSetName).getMenuItem('Download YAML').click();
const downloadedFilename = path.join(downloadsFolder, `${ this.machineSetName }.yaml`);
cy.readFile(downloadedFilename).then((buffer) => {
const obj: any = jsyaml.load(buffer);
// Basic checks on the downloaded YAML
expect(obj.apiVersion).to.equal('cluster.x-k8s.io/v1beta1');
expect(obj.metadata.name).to.equal(this.machineSetName);
expect(obj.kind).to.equal('MachineSet');
});
});
it('can delete a MachineSet', function() {
MachineSetsPagePo.navTo();
// delete original cloned MachineSet
machineSetsPage.list().actionMenu(`${ this.machineDeploymentsName }-clone`).getMenuItem('Delete').click();
const promptRemove = new PromptRemove();
cy.intercept('DELETE', `v1/cluster.x-k8s.io.machinesets/${ nsName }/${ this.machineDeploymentsName }-clone`).as('deleteMachineSet');
promptRemove.remove();
cy.wait('@deleteMachineSet');
machineSetsPage.waitForPage();
// check list details
cy.contains(`${ this.machineDeploymentsName }-clone`).should('not.exist');
});
it('can delete MachineSet via bulk actions', function() {
MachineSetsPagePo.navTo();
// delete original MachineSet
machineSetsPage.list().resourceTable().sortableTable().rowSelectCtlWithName(this.machineSetName)
.set();
machineSetsPage.list().openBulkActionDropdown();
cy.intercept('DELETE', `v1/cluster.x-k8s.io.machinesets/${ nsName }/${ this.machineSetName }`).as('deleteMachineSet');
machineSetsPage.list().bulkActionButton('Delete').click();
const promptRemove = new PromptRemove();
promptRemove.remove();
cy.wait('@deleteMachineSet');
machineSetsPage.waitForPage();
// check list details
cy.contains(this.machineSetName).should('not.exist');
});
});

View File

@ -0,0 +1,113 @@
import PromptRemove from '@/cypress/e2e/po/prompts/promptRemove.po';
import MachinesPagePo from '@/cypress/e2e/po/pages/cluster-manager/machines.po';
import * as path from 'path';
import * as jsyaml from 'js-yaml';
describe('Machines', { testIsolation: 'off', tags: ['@manager', '@adminUser'] }, () => {
const machinesPage = new MachinesPagePo('_');
const nsName = 'default';
let resourceVersion = '';
let creationTimestamp = '';
let time = '';
let uid = '';
const downloadsFolder = Cypress.config('downloadsFolder');
before(() => {
cy.login();
cy.createE2EResourceName('machines').as('machineName');
});
it('can create a Machine', function() {
MachinesPagePo.navTo();
machinesPage.waitForPage();
machinesPage.create();
machinesPage.createEditMachines().waitForPage('as=yaml');
cy.readFile('cypress/e2e/blueprints/cluster_management/machines.yml').then((machineDoc) => {
// convert yaml into json to update name value
const json: any = jsyaml.load(machineDoc);
json.metadata.name = this.machineName;
json.metadata.namespace = nsName;
json.spec.bootstrap.clusterName = 'local';
json.spec.bootstrap.dataSecretName = 'secretName';
machinesPage.yamlEditor().set(jsyaml.dump(json));
});
cy.intercept('POST', '/v1/cluster.x-k8s.io.machines').as('createMachine');
machinesPage.createEditMachines().saveCreateForm().resourceYaml().saveOrCreate()
.click();
cy.wait('@createMachine').then((req) => {
resourceVersion = req.response?.body.metadata.resourceVersion;
creationTimestamp = req.response?.body.metadata.creationTimestamp;
time = req.response?.body.metadata.managedFields[0].time;
uid = req.response?.body.metadata.uid;
});
machinesPage.waitForPage();
machinesPage.list().details(this.machineName, 1).should('be.visible');
});
it('can edit a Machine', function() {
MachinesPagePo.navTo();
machinesPage.list().actionMenu(this.machineName).getMenuItem('Edit YAML').click();
machinesPage.createEditMachines(nsName, this.machineName).waitForPage('mode=edit&as=yaml');
cy.readFile('cypress/e2e/blueprints/cluster_management/machines-edit.yml').then((machineDoc) => {
// convert yaml into json to update values
const json: any = jsyaml.load(machineDoc);
json.spec.bootstrap.dataSecretName = 'secretName2';
json.metadata.creationTimestamp = creationTimestamp;
json.metadata.managedFields.time = time;
json.metadata.uid = uid;
json.metadata.name = this.machineName;
json.metadata.resourceVersion = resourceVersion;
machinesPage.yamlEditor().set(jsyaml.dump(json));
});
cy.intercept('PUT', `/v1/cluster.x-k8s.io.machines/${ nsName }/${ this.machineName }`).as('updateMachine');
machinesPage.createEditMachines().saveCreateForm().resourceYaml().saveOrCreate()
.click();
cy.wait('@updateMachine').its('response.statusCode').should('eq', 200);
machinesPage.waitForPage();
// check details page
machinesPage.list().details(this.machineName, 2).find('a').click();
cy.contains('secretName2').should('be.visible');
});
it('can download YAML', function() {
MachinesPagePo.navTo();
machinesPage.list().actionMenu(this.machineName).getMenuItem('Download YAML').click();
const downloadedFilename = path.join(downloadsFolder, `${ this.machineName }.yaml`);
cy.readFile(downloadedFilename).then((buffer) => {
const obj: any = jsyaml.load(buffer);
// Basic checks on the downloaded YAML
expect(obj.apiVersion).to.equal('cluster.x-k8s.io/v1beta1');
expect(obj.metadata.name).to.equal(this.machineName);
expect(obj.kind).to.equal('Machine');
});
});
it('can delete a Machine', function() {
MachinesPagePo.navTo();
machinesPage.list().actionMenu(this.machineName).getMenuItem('Delete').click();
const promptRemove = new PromptRemove();
cy.intercept('DELETE', `v1/cluster.x-k8s.io.machines/${ nsName }/${ this.machineName }`).as('deleteCloudCred');
promptRemove.remove();
cy.wait('@deleteCloudCred');
machinesPage.waitForPage();
// check list details
cy.contains(this.machineName).should('not.exist');
});
});

View File

@ -0,0 +1,145 @@
import ClusterManagerListPagePo from '@/cypress/e2e/po/pages/cluster-manager/cluster-manager-list.po';
import NodeTemplatesPagePo from '@/cypress/e2e/po/pages/cluster-manager/node-templates.po';
import ClusterManagerCreateRke1Amazonec2PagePo from '@/cypress/e2e/po/edit/provisioning.cattle.io.cluster/create/cluster-create-rke1-amazonec2.po';
import EmberModalPo from '@/cypress/e2e/po/components/ember/ember-modal.po';
// will only run this in jenkins pipeline where cloud credentials are stored
describe('Node Templates', { testIsolation: 'off', tags: ['@manager', '@jenkins', '@adminUser'] }, () => {
const nodeTemplatesPage = new NodeTemplatesPagePo('_');
const clusterList = new ClusterManagerListPagePo('local');
let cloudCredentialId = '';
before(() => {
cy.login();
cy.createE2EResourceName('nodeTemplates').as('nodeTemplateName');
cy.createE2EResourceName('cloudCredential').as('cloudCredentialName');
});
beforeEach(() => {
cy.viewport(1380, 720);
});
let removeCloudCred = false;
it('can create a node template for Amazon EC2 and should display on RKE1 cluster creation page', function() {
cy.createAwsCloudCredentials('fleet-default', this.cloudCredentialName, 'us-west-2', Cypress.env('awsAccessKey'), Cypress.env('awsSecretKey')).then((resp: Cypress.Response<any>) => {
cloudCredentialId = resp.body.id;
removeCloudCred = true;
});
NodeTemplatesPagePo.navTo();
nodeTemplatesPage.waitForPage();
nodeTemplatesPage.addTemplate().click();
nodeTemplatesPage.addNodeTemplateModal().serviceProviderOptions('Amazon EC2').should('have.class', 'active');
nodeTemplatesPage.addNodeTemplateModal().nextButton('Next: Authenticate & configure nodes').click();
nodeTemplatesPage.addNodeTemplateModal().accordion().content().find('.radio .acc-label')
.eq(0)
.click();
nodeTemplatesPage.addNodeTemplateModal().nextButton('Next: Select a Security Group').should('exist');
nodeTemplatesPage.addNodeTemplateModal().nextButton('Next: Select a Security Group').click();
nodeTemplatesPage.addNodeTemplateModal().accordion().content().contains('.radio label', 'Choose one or more existing groups')
.click();
nodeTemplatesPage.addNodeTemplateModal().serviceProviderOptions('Amazon EC2').should('have.class', 'active');
nodeTemplatesPage.addNodeTemplateModal().nextButton('Next: Set Instance options').click();
nodeTemplatesPage.addNodeTemplateModal().templateName().set(this.nodeTemplateName);
cy.intercept('POST', '/v3/nodetemplate').as('createTemplate');
nodeTemplatesPage.addNodeTemplateModal().create();
cy.wait('@createTemplate');
nodeTemplatesPage.waitForPage();
nodeTemplatesPage.list().rowWithName(this.nodeTemplateName).should('be.visible');
// check RKE template displays as an option on the RKE cluster create page
clusterList.goTo();
clusterList.checkIsCurrentPage();
clusterList.createCluster();
const createClusterRKE1Page = new ClusterManagerCreateRke1Amazonec2PagePo();
createClusterRKE1Page.waitForPage();
createClusterRKE1Page.rkeToggle().set('RKE1');
createClusterRKE1Page.selectCreate(0);
createClusterRKE1Page.nodeTemplateDropdown().selectMenuItemByOption(this.nodeTemplateName);
createClusterRKE1Page.selectedOption().checkOptionSelected(this.nodeTemplateName);
});
it('can edit a node template', function() {
NodeTemplatesPagePo.navTo();
nodeTemplatesPage.list().rowWithName(this.nodeTemplateName).should('be.visible');
nodeTemplatesPage.list().rowActionMenuOpen(this.nodeTemplateName);
nodeTemplatesPage.list().actionMenu().selectMenuItemByLabel('Edit');
nodeTemplatesPage.addNodeTemplateModal().nextButton('Next: Authenticate & configure nodes').click();
nodeTemplatesPage.addNodeTemplateModal().nextButton('Next: Select a Security Group').click();
nodeTemplatesPage.addNodeTemplateModal().nextButton('Next: Set Instance options').click();
nodeTemplatesPage.addNodeTemplateModal().templateName().set(`${ this.nodeTemplateName }-edit`);
cy.intercept('PUT', '/v3/nodeTemplates/**').as('editTemplate');
nodeTemplatesPage.addNodeTemplateModal().save();
cy.wait('@editTemplate');
nodeTemplatesPage.waitForPage();
nodeTemplatesPage.list().rowWithName(`${ this.nodeTemplateName }-edit`).should('be.visible');
});
it('can clone a node template', function() {
NodeTemplatesPagePo.navTo();
nodeTemplatesPage.list().rowWithName(`${ this.nodeTemplateName }-edit`).should('be.visible');
nodeTemplatesPage.list().rowActionMenuOpen(`${ this.nodeTemplateName }-edit`);
nodeTemplatesPage.list().actionMenu().selectMenuItemByLabel('Clone');
nodeTemplatesPage.addNodeTemplateModal().nextButton('Next: Authenticate & configure nodes').click();
nodeTemplatesPage.addNodeTemplateModal().nextButton('Next: Select a Security Group').click();
nodeTemplatesPage.addNodeTemplateModal().nextButton('Next: Set Instance options').click();
nodeTemplatesPage.addNodeTemplateModal().templateName().set(`${ this.nodeTemplateName }-clone`);
cy.intercept('POST', '/v3/nodetemplate').as('cloneTemplate');
nodeTemplatesPage.addNodeTemplateModal().save();
cy.wait('@cloneTemplate');
nodeTemplatesPage.waitForPage();
nodeTemplatesPage.list().rowWithName(`${ this.nodeTemplateName }-clone`).should('be.visible');
});
it('can delete a node template', function() {
NodeTemplatesPagePo.navTo();
// delete clone node template
nodeTemplatesPage.list().rowWithName(`${ this.nodeTemplateName }-clone`).should('be.visible');
nodeTemplatesPage.list().rowActionMenuOpen(`${ this.nodeTemplateName }-clone`);
nodeTemplatesPage.list().actionMenu().selectMenuItemByLabel('Delete');
const promptRemove = new EmberModalPo();
cy.intercept('DELETE', '/v3/nodeTemplates/**').as('deleteNodeTemplate');
promptRemove.delete();
cy.wait('@deleteNodeTemplate');
nodeTemplatesPage.waitForPage();
// check list details
cy.contains(`${ this.nodeTemplateName }-clone`).should('not.exist');
});
it('can delete a node template via bulk actions', function() {
NodeTemplatesPagePo.navTo();
// delete original node template
nodeTemplatesPage.list().rowWithName(`${ this.nodeTemplateName }-edit`).click();
nodeTemplatesPage.list().bulkActions('Delete').click();
const promptRemove = new EmberModalPo();
cy.intercept('DELETE', '/v3/nodeTemplates/**').as('deleteNodeTemplate');
promptRemove.delete();
cy.wait('@deleteNodeTemplate');
nodeTemplatesPage.waitForPage();
// check list details
cy.contains(`${ this.nodeTemplateName }-edit`).should('not.exist');
});
after('clean up', () => {
if (removeCloudCred) {
// delete cloud cred
cy.deleteRancherResource('v3', 'cloudCredentials', cloudCredentialId);
}
});
});

View File

@ -0,0 +1,142 @@
import PodSecurityAdmissionsPagePo from '@/cypress/e2e/po/pages/cluster-manager/pod-security-admissions.po';
import PromptRemove from '@/cypress/e2e/po/prompts/promptRemove.po';
import ResourceDetailPo from '@/cypress/e2e/po/edit/resource-detail.po';
import * as path from 'path';
import * as jsyaml from 'js-yaml';
import { createPayloadData, updatePayloadData } from '@/cypress/e2e/blueprints/cluster_management/pod-security-admissions-payload';
describe('Pod Security Admissions', { testIsolation: 'off', tags: ['@manager', '@adminUser'] }, () => {
const podSecurityAdmissionsPage = new PodSecurityAdmissionsPagePo('_');
const resourceDetails = new ResourceDetailPo('.main-layout');
const downloadsFolder = Cypress.config('downloadsFolder');
before(() => {
cy.login();
cy.createE2EResourceName('podsecurityadmissions').as('podSecurityAdmissionsName');
});
beforeEach(() => {
cy.viewport(1380, 720);
});
it('can create a policy security admission', function() {
PodSecurityAdmissionsPagePo.navTo();
podSecurityAdmissionsPage.waitForPage();
podSecurityAdmissionsPage.create();
podSecurityAdmissionsPage.createPodSecurityAdmissionForm().waitForPage();
podSecurityAdmissionsPage.createPodSecurityAdmissionForm().nameNsDescription().name().set(this.podSecurityAdmissionsName);
podSecurityAdmissionsPage.createPodSecurityAdmissionForm().nameNsDescription().description().set(`${ this.podSecurityAdmissionsName }-description`);
podSecurityAdmissionsPage.createPodSecurityAdmissionForm().psaControlLevel(0, 1);
podSecurityAdmissionsPage.createPodSecurityAdmissionForm().psaControlLevel(1, 2);
podSecurityAdmissionsPage.createPodSecurityAdmissionForm().psaControlLevel(2, 3);
podSecurityAdmissionsPage.createPodSecurityAdmissionForm().psaControlVersion(0, 'latest');
podSecurityAdmissionsPage.createPodSecurityAdmissionForm().psaControlVersion(1, 'latest');
podSecurityAdmissionsPage.createPodSecurityAdmissionForm().psaControlVersion(2, 'latest');
podSecurityAdmissionsPage.createPodSecurityAdmissionForm().setExemptionsCheckbox(0);
podSecurityAdmissionsPage.createPodSecurityAdmissionForm().setExemptionsInput(0, 'admin,user');
podSecurityAdmissionsPage.createPodSecurityAdmissionForm().setExemptionsCheckbox(1);
podSecurityAdmissionsPage.createPodSecurityAdmissionForm().setExemptionsInput(1, 'myclass1,myclass2');
podSecurityAdmissionsPage.createPodSecurityAdmissionForm().setExemptionsCheckbox(2);
podSecurityAdmissionsPage.createPodSecurityAdmissionForm().setExemptionsInput(2, 'ingress-nginx,kube-system');
resourceDetails.cruResource().saveAndWaitForRequests('POST', '/v1/management.cattle.io.podsecurityadmissionconfigurationtemplates').then(({ request, response }) => {
expect(response?.statusCode).to.eq(201);
expect(request?.body.configuration.defaults).to.deep.include(createPayloadData.configuration.defaults);
expect(response?.body.configuration.defaults).to.deep.include(createPayloadData.configuration.defaults);
expect(request?.body.configuration.exemptions).to.deep.include(createPayloadData.configuration.exemptions);
expect(response?.body.configuration.exemptions).to.deep.include(createPayloadData.configuration.exemptions);
});
podSecurityAdmissionsPage.waitForPage();
// check list details
podSecurityAdmissionsPage.list().details(this.podSecurityAdmissionsName, 1).should('be.visible');
});
it('can edit a policy security admission', function() {
PodSecurityAdmissionsPagePo.navTo();
podSecurityAdmissionsPage.list().actionMenu(this.podSecurityAdmissionsName).getMenuItem('Edit Config').click();
podSecurityAdmissionsPage.createPodSecurityAdmissionForm(this.podSecurityAdmissionsName).waitForPage('mode=edit');
podSecurityAdmissionsPage.createPodSecurityAdmissionForm().nameNsDescription().description().set(`${ this.podSecurityAdmissionsName }-description-edit`);
podSecurityAdmissionsPage.createPodSecurityAdmissionForm().psaControlLevel(0, 1);
podSecurityAdmissionsPage.createPodSecurityAdmissionForm().psaControlLevel(1, 2);
podSecurityAdmissionsPage.createPodSecurityAdmissionForm().psaControlLevel(2, 3);
podSecurityAdmissionsPage.createPodSecurityAdmissionForm().psaControlVersion(0, 'v1.25');
podSecurityAdmissionsPage.createPodSecurityAdmissionForm().psaControlVersion(1, 'v1.25');
podSecurityAdmissionsPage.createPodSecurityAdmissionForm().psaControlVersion(2, 'v1.25');
podSecurityAdmissionsPage.createPodSecurityAdmissionForm().setExemptionsInput(0, 'admin1,user1');
podSecurityAdmissionsPage.createPodSecurityAdmissionForm().setExemptionsInput(1, 'myclass3,myclass4');
podSecurityAdmissionsPage.createPodSecurityAdmissionForm().setExemptionsInput(2, 'cattle-system,cattle-epinio-system');
resourceDetails.cruResource().saveAndWaitForRequests('PUT', '/v1/management.cattle.io.podsecurityadmissionconfigurationtemplates/**').then(({ request, response }) => {
expect(response?.statusCode).to.eq(200);
expect(request?.body.configuration.defaults).to.deep.include(updatePayloadData.configuration.defaults);
expect(response?.body.configuration.defaults).to.deep.include(updatePayloadData.configuration.defaults);
expect(request?.body.configuration.exemptions).to.deep.include(updatePayloadData.configuration.exemptions);
expect(response?.body.configuration.exemptions).to.deep.include(updatePayloadData.configuration.exemptions);
});
podSecurityAdmissionsPage.waitForPage();
// check list details
podSecurityAdmissionsPage.list().details(`${ this.podSecurityAdmissionsName }-description-edit`, 1).should('be.visible');
});
it('can clone a policy security admission', function() {
PodSecurityAdmissionsPagePo.navTo();
podSecurityAdmissionsPage.list().actionMenu(this.podSecurityAdmissionsName).getMenuItem('Clone').click();
podSecurityAdmissionsPage.createPodSecurityAdmissionForm(this.podSecurityAdmissionsName).waitForPage('mode=clone');
podSecurityAdmissionsPage.createPodSecurityAdmissionForm().nameNsDescription().name().set(`${ this.podSecurityAdmissionsName }-clone`);
resourceDetails.cruResource().saveAndWaitForRequests('POST', '/v1/management.cattle.io.podsecurityadmissionconfigurationtemplates');
podSecurityAdmissionsPage.waitForPage();
// check list details
podSecurityAdmissionsPage.list().details(`${ this.podSecurityAdmissionsName }-clone`, 1).should('be.visible');
});
it('can download YAML for a policy security admission', function() {
PodSecurityAdmissionsPagePo.navTo();
podSecurityAdmissionsPage.list().actionMenu(this.podSecurityAdmissionsName).getMenuItem('Download YAML').click();
const downloadedFilename = path.join(downloadsFolder, `${ this.podSecurityAdmissionsName }.yaml`);
cy.readFile(downloadedFilename).then((buffer) => {
const obj: any = jsyaml.load(buffer);
// Basic checks on the downloaded YAML
expect(obj.apiVersion).to.equal('management.cattle.io/v3');
expect(obj.metadata.name).to.equal(this.podSecurityAdmissionsName);
expect(obj.kind).to.equal('PodSecurityAdmissionConfigurationTemplate');
});
});
it('can delete a policy security admission', function() {
PodSecurityAdmissionsPagePo.navTo();
podSecurityAdmissionsPage.list().actionMenu(`${ this.podSecurityAdmissionsName }-clone`).getMenuItem('Delete').click();
const promptRemove = new PromptRemove();
cy.intercept('DELETE', `/v1/management.cattle.io.podsecurityadmissionconfigurationtemplates/${ this.podSecurityAdmissionsName }-clone`).as('deletePolicyAdmission');
promptRemove.remove();
cy.wait('@deletePolicyAdmission');
podSecurityAdmissionsPage.waitForPage();
// check list details
cy.contains(`${ this.podSecurityAdmissionsName }-clone`).should('not.exist');
});
it('can delete a policy security admission via bulk actions', function() {
PodSecurityAdmissionsPagePo.navTo();
podSecurityAdmissionsPage.list().details(this.podSecurityAdmissionsName, 0).click();
podSecurityAdmissionsPage.list().resourceTable().sortableTable().deleteButton()
.click();
const promptRemove = new PromptRemove();
cy.intercept('DELETE', `/v1/management.cattle.io.podsecurityadmissionconfigurationtemplates/${ this.podSecurityAdmissionsName }`).as('deletePolicyAdmission');
promptRemove.remove();
cy.wait('@deletePolicyAdmission');
podSecurityAdmissionsPage.waitForPage();
// check list details
cy.contains(this.podSecurityAdmissionsName).should('not.exist');
});
});

View File

@ -0,0 +1,63 @@
import PodSecurityPoliciesTemplatesPagePo from '@/cypress/e2e/po/pages/cluster-manager/pod-security-policy-templates.po';
import EmberModalPo from '@/cypress/e2e/po/components/ember/ember-modal.po';
describe.skip('Pod Security Policy Templates', { testIsolation: 'off', tags: ['@manager', '@adminUser'] }, () => {
// Note: this test fails due to https://github.com/rancher/dashboard/issues/10187
// skipping these tests until issue is resolved
const podSecurityTemplatesPage = new PodSecurityPoliciesTemplatesPagePo('_');
before(() => {
cy.login();
cy.createE2EResourceName('podsecuritytemplate').as('podSecurityTemplateName');
});
beforeEach(() => {
cy.viewport(1380, 720);
});
it('can create a policy template', function() {
PodSecurityPoliciesTemplatesPagePo.navTo();
podSecurityTemplatesPage.waitForPage();
podSecurityTemplatesPage.addPolicyTemplate().click();
podSecurityTemplatesPage.addPodSecurityTemplateForm().templateName().set(this.podSecurityTemplateName);
cy.intercept('POST', '/v3/podsecuritypolicytemplate').as('createPolicyTemplate');
podSecurityTemplatesPage.addPodSecurityTemplateForm().create();
cy.wait('@createPolicyTemplate');
// check list details
podSecurityTemplatesPage.list().rowWithName(this.podSecurityTemplateName).should('be.visible');
});
it('can edit a policy template', function() {
PodSecurityPoliciesTemplatesPagePo.navTo();
podSecurityTemplatesPage.list().rowActionMenuOpen(this.podSecurityTemplateName);
podSecurityTemplatesPage.actionMenu().selectMenuItemByLabel('Edit');
// update template by adding a description
podSecurityTemplatesPage.addPodSecurityTemplateForm().addDescription();
podSecurityTemplatesPage.addPodSecurityTemplateForm().templateDescription().set(`${ this.podSecurityTemplateName }-description`);
cy.intercept('PUT', '/v3/podSecurityPolicyTemplates/**').as('updatePolicyTemplate');
podSecurityTemplatesPage.addPodSecurityTemplateForm().save();
cy.wait('@updatePolicyTemplate');
podSecurityTemplatesPage.list().rowWithName(this.podSecurityTemplateName).find('a').click();
podSecurityTemplatesPage.templateDescription(`${ this.podSecurityTemplateName }-description`).should('be.visible');
});
it('can delete a policy template', function() {
PodSecurityPoliciesTemplatesPagePo.navTo();
podSecurityTemplatesPage.list().rowActionMenuOpen(this.podSecurityTemplateName);
podSecurityTemplatesPage.actionMenu().selectMenuItemByLabel('Delete');
const promptRemove = new EmberModalPo();
cy.intercept('DELETE', '/v3/podSecurityPolicyTemplates/**').as('deletePolicyTemplate');
promptRemove.delete();
cy.wait('@deletePolicyTemplate');
podSecurityTemplatesPage.waitForPage();
// check list details
cy.contains(this.podSecurityTemplateName).should('not.exist');
});
});

View File

@ -0,0 +1,126 @@
import PromptRemove from '@/cypress/e2e/po/prompts/promptRemove.po';
import ChartRepositoriesPagePo from '@/cypress/e2e/po/pages/chart-repositories.po';
import * as path from 'path';
import * as jsyaml from 'js-yaml';
describe('Cluster Management Helm Repositories', { testIsolation: 'off', tags: ['@manager', '@adminUser'] }, () => {
const repositoriesPage = new ChartRepositoriesPagePo('_', 'manager');
const downloadsFolder = Cypress.config('downloadsFolder');
before(() => {
cy.login();
cy.createE2EResourceName('repo').as('repoName');
});
it('can create a repository', function() {
ChartRepositoriesPagePo.navTo();
repositoriesPage.waitForPage();
repositoriesPage.waitForGoTo('/v1/catalog.cattle.io.clusterrepos?exclude=metadata.managedFields');
repositoriesPage.create();
repositoriesPage.createEditRepositories().waitForPage();
repositoriesPage.createEditRepositories().nameNsDescription().name().set(this.repoName);
repositoriesPage.createEditRepositories().nameNsDescription().description().set(`${ this.repoName }-description`);
repositoriesPage.createEditRepositories().repoRadioBtn().set(1);
repositoriesPage.createEditRepositories().gitRepoUrl().set('https://git.rancher.io/charts');
repositoriesPage.createEditRepositories().gitBranch().set('release-v2.8');
repositoriesPage.createEditRepositories().saveAndWaitForRequests('POST', '/v1/catalog.cattle.io.clusterrepos');
repositoriesPage.waitForPage();
// check list details
repositoriesPage.list().details(this.repoName, 2).should('be.visible');
repositoriesPage.list().details(this.repoName, 1).contains('In Progress').should('be.visible');
repositoriesPage.list().details(this.repoName, 1).contains('Active').should('be.visible');
});
it('can refresh a repository', function() {
ChartRepositoriesPagePo.navTo();
cy.intercept('PUT', `/v1/catalog.cattle.io.clusterrepos/${ this.repoName }`).as('refreshRepo');
repositoriesPage.list().actionMenu(this.repoName).getMenuItem('Refresh').click();
cy.wait('@refreshRepo').its('response.statusCode').should('eq', 200);
// check list details
repositoriesPage.list().details(this.repoName, 1).contains('In Progress').should('be.visible');
repositoriesPage.list().details(this.repoName, 1).contains('Active').should('be.visible');
});
it('can edit a repository', function() {
ChartRepositoriesPagePo.navTo();
repositoriesPage.list().actionMenu(this.repoName).getMenuItem('Edit Config').click();
repositoriesPage.createEditRepositories(this.repoName).waitForPage('mode=edit');
repositoriesPage.createEditRepositories().nameNsDescription().description().set(`${ this.repoName }-desc-edit`);
repositoriesPage.createEditRepositories().saveAndWaitForRequests('PUT', `/v1/catalog.cattle.io.clusterrepos/${ this.repoName }`);
repositoriesPage.waitForPage();
// check details page
repositoriesPage.list().details(this.repoName, 2).click();
cy.contains(`${ this.repoName }-desc-edit`).should('be.visible');
});
it('can clone a repository', function() {
ChartRepositoriesPagePo.navTo();
repositoriesPage.list().actionMenu(this.repoName).getMenuItem('Clone').click();
repositoriesPage.createEditRepositories(this.repoName).waitForPage('mode=clone');
repositoriesPage.createEditRepositories().nameNsDescription().name().set(`${ this.repoName }-clone`);
repositoriesPage.createEditRepositories().nameNsDescription().description().set(`${ this.repoName }-desc-clone`);
repositoriesPage.createEditRepositories().saveAndWaitForRequests('POST', '/v1/catalog.cattle.io.clusterrepos');
repositoriesPage.waitForPage();
// check list details
repositoriesPage.list().details(`${ this.repoName }-clone`, 2).should('be.visible');
});
it('can download YAML', function() {
ChartRepositoriesPagePo.navTo();
repositoriesPage.list().actionMenu(this.repoName).getMenuItem('Download YAML').click();
const downloadedFilename = path.join(downloadsFolder, `${ this.repoName }.yaml`);
cy.readFile(downloadedFilename).then((buffer) => {
const obj: any = jsyaml.load(buffer);
// Basic checks on the downloaded YAML
expect(obj.apiVersion).to.equal('catalog.cattle.io/v1');
expect(obj.metadata.name).to.equal(this.repoName);
expect(obj.kind).to.equal('ClusterRepo');
});
});
it('can delete a repository', function() {
ChartRepositoriesPagePo.navTo();
// delete original cloned Repository
repositoriesPage.list().actionMenu(`${ this.repoName }-clone`).getMenuItem('Delete').click();
const promptRemove = new PromptRemove();
cy.intercept('DELETE', `v1/catalog.cattle.io.clusterrepos/${ this.repoName }-clone`).as('deleteRepository');
promptRemove.remove();
cy.wait('@deleteRepository');
repositoriesPage.waitForPage();
// check list details
cy.contains(`${ this.repoName }-clone`).should('not.exist');
});
it('can delete a repository via bulk actions', function() {
ChartRepositoriesPagePo.navTo();
// delete original Repository
repositoriesPage.list().resourceTable().sortableTable().rowSelectCtlWithName(this.repoName)
.set();
repositoriesPage.list().openBulkActionDropdown();
cy.intercept('DELETE', `v1/catalog.cattle.io.clusterrepos/${ this.repoName }`).as('deleteRepository');
repositoriesPage.list().bulkActionButton('Delete').click();
const promptRemove = new PromptRemove();
promptRemove.remove();
cy.wait('@deleteRepository');
repositoriesPage.waitForPage();
// check list details
cy.contains(this.repoName).should('not.exist');
});
});

View File

@ -0,0 +1,102 @@
import ClusterManagerListPagePo from '@/cypress/e2e/po/pages/cluster-manager/cluster-manager-list.po';
import ClusterManagerCreateRke1CustomPagePo from '@/cypress/e2e/po/edit/provisioning.cattle.io.cluster/create/cluster-create-rke1-custom.po';
import RkeTemplatesPagePo from '@/cypress/e2e/po/pages/cluster-manager/rke-templates.po';
import EmberModalPo from '@/cypress/e2e/po/components/ember/ember-modal.po';
describe('RKE Templates', { testIsolation: 'off', tags: ['@manager', '@adminUser'] }, () => {
const rkeTemplatesPage = new RkeTemplatesPagePo('_');
const clusterList = new ClusterManagerListPagePo('local');
const promptRemove = new EmberModalPo();
before(() => {
cy.login();
cy.createE2EResourceName('rkeTemplate').as('rkeTemplateName');
cy.createE2EResourceName('rkeRevision').as('rkeRevisionName');
});
beforeEach(() => {
cy.viewport(1380, 720);
});
it('can create RKE template and should display on RKE1 cluster creation page', function() {
RkeTemplatesPagePo.navTo();
rkeTemplatesPage.waitForPage();
rkeTemplatesPage.addTemplate().click();
rkeTemplatesPage.form().templateDetails(3).set(this.rkeTemplateName);
rkeTemplatesPage.form().templateDetails(2).set(this.rkeRevisionName);
cy.intercept('POST', '/v3/clustertemplate').as('createTemplate');
rkeTemplatesPage.form().create();
cy.wait('@createTemplate');
rkeTemplatesPage.waitForPage();
rkeTemplatesPage.groupRow().groupRowWithName(this.rkeTemplateName).should('be.visible');
rkeTemplatesPage.groupRow().rowWithinGroupByName(this.rkeTemplateName, this.rkeRevisionName).should('be.visible');
// check RKE template displays as an option on the RKE custom cluster create page
clusterList.goTo();
clusterList.checkIsCurrentPage();
clusterList.createCluster();
const createClusterRKE1Page = new ClusterManagerCreateRke1CustomPagePo();
createClusterRKE1Page.waitForPage();
createClusterRKE1Page.rkeToggle().set('RKE1');
createClusterRKE1Page.selectCustom(0);
createClusterRKE1Page.clusterTemplateCheckbox().set();
createClusterRKE1Page.rkeTemplateAndRevisionDropdown().selectMenuItemByOption(this.rkeTemplateName);
createClusterRKE1Page.selectedOption().checkOptionSelected(this.rkeTemplateName);
createClusterRKE1Page.selectedOption().checkOptionSelected(this.rkeRevisionName, 1);
});
it('can disable RKE template revision', function() {
RkeTemplatesPagePo.navTo();
rkeTemplatesPage.mainRow().rowActionMenuOpen(this.rkeRevisionName);
cy.intercept('POST', '/v3/clusterTemplateRevisions/*').as('disableTemplateRevision');
rkeTemplatesPage.actionMenu().selectMenuItemByLabel('Disable');
cy.wait('@disableTemplateRevision');
rkeTemplatesPage.mainRow().state(this.rkeRevisionName).contains('Active').should('not.exist');
rkeTemplatesPage.mainRow().state(this.rkeRevisionName).should('contain.text', 'Disabled');
});
it('can enable RKE template revision', function() {
RkeTemplatesPagePo.navTo();
rkeTemplatesPage.mainRow().rowActionMenuOpen(this.rkeRevisionName);
cy.intercept('POST', '/v3/clusterTemplateRevisions/*').as('enableTemplateRevision');
rkeTemplatesPage.actionMenu().selectMenuItemByLabel('Enable');
cy.wait('@enableTemplateRevision');
rkeTemplatesPage.mainRow().state(this.rkeRevisionName).contains('Disabled').should('not.exist');
rkeTemplatesPage.mainRow().state(this.rkeRevisionName).should('contain.text', 'Active');
});
it('can clone RKE template revision', function() {
RkeTemplatesPagePo.navTo();
rkeTemplatesPage.groupRow().groupRowWithName(this.rkeTemplateName).should('be.visible');
rkeTemplatesPage.mainRow().rowActionMenuOpen(this.rkeRevisionName);
rkeTemplatesPage.actionMenu().selectMenuItemByLabel('Clone Revision');
rkeTemplatesPage.form().templateDetails(2).set(`${ this.rkeRevisionName }-2`);
cy.intercept('PUT', '/v3/clusterTemplates/*').as('cloneTemplateRevision');
rkeTemplatesPage.form().save();
cy.wait('@cloneTemplateRevision');
rkeTemplatesPage.groupRow().rowWithinGroupByName(this.rkeTemplateName, `${ this.rkeRevisionName }-2`);
});
it('can delete RKE template revision', function() {
RkeTemplatesPagePo.navTo();
rkeTemplatesPage.mainRow().rowActionMenuOpen(`${ this.rkeRevisionName }-2`);
rkeTemplatesPage.actionMenu().selectMenuItemByLabel(`Delete`);
cy.intercept('DELETE', '/v3/clusterTemplateRevisions/*').as('deleteTemplateRevision');
promptRemove.delete();
cy.wait('@deleteTemplateRevision').its('response.statusCode').should('eq', 204);
rkeTemplatesPage.mainRow().rowWithName(`${ this.rkeRevisionName }-2`).should('not.exist');
});
it('can delete RKE template group', function() {
RkeTemplatesPagePo.navTo();
rkeTemplatesPage.groupRow().groupRowActionMenuOpen(this.rkeTemplateName);
rkeTemplatesPage.actionMenu().selectMenuItemByLabel(`Delete`);
cy.intercept('DELETE', '/v3/clusterTemplates/*').as('deleteTemplate');
promptRemove.delete();
cy.wait('@deleteTemplate').its('response.statusCode').should('eq', 204);
rkeTemplatesPage.groupRow().groupRowWithName(this.rkeTemplateName).should('not.exist');
});
});

View File

@ -1,13 +1,13 @@
import BannersPo from '@/cypress/e2e/po/components/banners.po';
import HomePagePo from '@/cypress/e2e/po/pages/home.po';
import PreferencesPagePo from '@/cypress/e2e/po/pages/preferences.po';
import ReposListPagePo from '@/cypress/e2e/po/pages/repositories.po';
import UserMenuPo from '@/cypress/e2e/po/side-bars/user-menu.po';
import RepositoriesPagePo from '@/cypress/e2e/po/pages/chart-repositories.po';
// import ClusterManagerListPagePo from '@/cypress/e2e/po/pages/cluster-manager/cluster-manager-list.po';
const userMenu = new UserMenuPo();
const prefPage = new PreferencesPagePo();
const repoListPage = new ReposListPagePo('_', 'manager');
const repoListPage = new RepositoriesPagePo('_', 'manager');
const repoList = repoListPage.list();
// const clusterManagerPage = new ClusterManagerListPagePo('_');
@ -360,9 +360,9 @@ describe('User can update their preferences', () => {
Validate http request's payload & response contain correct values per selection
*/
const buttonOptions = {
'Normal human': 'sublime',
Emacs: 'emacs',
Vim: 'vim',
'Normal human': 'sublime'
};
prefPage.goTo();

View File

@ -29,6 +29,7 @@ declare global {
login(username?: string, password?: string, cacheSession?: boolean): Chainable<Element>;
logout(): Chainable;
byLabel(label: string): Chainable<Element>;
createE2EResourceName(context: string): Chainable<Element>;
createUser(params: CreateUserParams): Chainable;
setGlobalRoleBinding(userId: string, role: string): Chainable;
@ -38,6 +39,7 @@ declare global {
createProject(projName: string, clusterId: string, userId: string): Chainable;
createNamespace(nsName: string, projId: string): Chainable;
createPod(nsName: string, podName: string, image: string): Chainable;
createAwsCloudCredentials(nsName: string, cloudCredName: string, defaultRegion: string, accessKey: string, secretKey: string): Chainable;
getRancherResource(prefix: 'v3' | 'v1', resourceType: string, resourceId?: string, expectedStatusCode?: number): Chainable;
setRancherResource(prefix: 'v3' | 'v1', resourceType: string, resourceId: string, body: string): Chainable;

View File

@ -59,3 +59,12 @@ Cypress.Commands.add('iFrame', () => {
.should('not.be.empty')
.then((body) => cy.wrap(body));
});
/**
* Create resource name
*/
const runTimestamp = +new Date();
Cypress.Commands.add('createE2EResourceName', (context) => {
return cy.wrap(`e2e-test-${ runTimestamp }-${ context }`);
});

View File

@ -299,6 +299,34 @@ Cypress.Commands.add('createPod', (nsName, podName, image) => {
});
});
/**
* create aws cloud credentials
*/
Cypress.Commands.add('createAwsCloudCredentials', (nsName, cloudCredName, defaultRegion, accessKey, secretKey) => {
return cy.request({
method: 'POST',
url: `${ Cypress.env('api') }/v3/cloudcredentials`,
headers: {
'x-api-csrf': token.value,
Accept: 'application/json'
},
body: {
type: 'provisioning.cattle.io/cloud-credential',
metadata: { generateName: 'cc-', namespace: `${ nsName }` },
_name: `${ cloudCredName }`,
annotations: { 'provisioning.cattle.io/driver': 'aws' },
amazonec2credentialConfig: {
defaultRegion: `${ defaultRegion }`, accessKey: `${ accessKey }`, secretKey: `${ secretKey }`
},
_type: 'provisioning.cattle.io/cloud-credential',
name: `${ cloudCredName }`
}
})
.then((resp) => {
expect(resp.status).to.eq(201);
});
});
/**
* Override user preferences to default values, allowing to pass custom preferences for a deterministic scenario
*/
@ -395,7 +423,7 @@ Cypress.Commands.add('setRancherResource', (prefix, resourceType, resourceId, bo
/**
* delete a v3 / v1 resource
*/
Cypress.Commands.add('deleteRancherResource', (prefix, resourceType, resourceId) => {
Cypress.Commands.add('deleteRancherResource', (prefix, resourceType, resourceId, expectedStatusCode = 200) => {
return cy.request({
method: 'DELETE',
url: `${ Cypress.env('api') }/${ prefix }/${ resourceType }/${ resourceId }`,