mirror of https://github.com/rancher/dashboard.git
459 lines
12 KiB
TypeScript
459 lines
12 KiB
TypeScript
import { LoginPagePo } from '@/cypress/e2e/po/pages/login-page.po';
|
|
import { CreateUserParams } from '@/cypress/globals';
|
|
|
|
// This file contains commands which makes API requests to the rancher API.
|
|
// It includes the `login` command to store the `token` to use
|
|
|
|
let token: any;
|
|
|
|
/**
|
|
* Login local authentication, including first login and bootstrap if not cached
|
|
*/
|
|
Cypress.Commands.add('login', (
|
|
username = Cypress.env('username'),
|
|
password = Cypress.env('password'),
|
|
cacheSession = true,
|
|
) => {
|
|
const login = () => {
|
|
cy.intercept('POST', '/v3-public/localProviders/local*').as('loginReq');
|
|
|
|
LoginPagePo.goTo(); // Needs to happen before the page element is created/located
|
|
const loginPage = new LoginPagePo();
|
|
|
|
loginPage
|
|
.checkIsCurrentPage();
|
|
|
|
loginPage.switchToLocal();
|
|
|
|
loginPage.canSubmit()
|
|
.should('eq', true);
|
|
|
|
loginPage.username()
|
|
.set(username);
|
|
|
|
loginPage.password()
|
|
.set(password);
|
|
|
|
loginPage.canSubmit()
|
|
.should('eq', true);
|
|
loginPage.submit();
|
|
|
|
cy.wait('@loginReq').its('request.body')
|
|
.should(
|
|
'deep.equal',
|
|
{
|
|
username,
|
|
password,
|
|
description: 'UI session',
|
|
responseType: 'cookie'
|
|
}
|
|
);
|
|
};
|
|
|
|
if (cacheSession) {
|
|
(cy as any).session([username, password], login);
|
|
cy.getCookie('CSRF').then((c) => {
|
|
token = c;
|
|
});
|
|
} else {
|
|
login();
|
|
}
|
|
});
|
|
|
|
/**
|
|
* Create user via api request
|
|
*/
|
|
Cypress.Commands.add('createUser', (params: CreateUserParams) => {
|
|
const {
|
|
username, globalRole, clusterRole, projectRole
|
|
} = params;
|
|
|
|
return cy.request({
|
|
method: 'POST',
|
|
url: `${ Cypress.env('api') }/v3/users`,
|
|
failOnStatusCode: false,
|
|
headers: {
|
|
'x-api-csrf': token.value,
|
|
Accept: 'application/json'
|
|
},
|
|
body: {
|
|
type: 'user',
|
|
enabled: true,
|
|
mustChangePassword: false,
|
|
username,
|
|
password: Cypress.env('password')
|
|
}
|
|
})
|
|
.then((resp) => {
|
|
if (resp.status === 422 && resp.body.message === 'Username is already in use.') {
|
|
cy.log('User already exists. Skipping user creation');
|
|
|
|
return '';
|
|
} else {
|
|
expect(resp.status).to.eq(201);
|
|
|
|
const userPrincipalId = resp.body.principalIds[0];
|
|
|
|
if (globalRole) {
|
|
return cy.setGlobalRoleBinding(resp.body.id, globalRole.role)
|
|
.then(() => {
|
|
if (clusterRole) {
|
|
const { clusterId, role } = clusterRole;
|
|
|
|
return cy.setClusterRoleBinding(clusterId, userPrincipalId, role);
|
|
}
|
|
})
|
|
.then(() => {
|
|
if (projectRole) {
|
|
const { clusterId, projectName, role } = projectRole;
|
|
|
|
return cy.setProjectRoleBinding(clusterId, userPrincipalId, projectName, role);
|
|
}
|
|
});
|
|
}
|
|
}
|
|
});
|
|
});
|
|
|
|
/**
|
|
* Set global role binding for user via api request
|
|
*/
|
|
Cypress.Commands.add('setGlobalRoleBinding', (userId, role) => {
|
|
return cy.request({
|
|
method: 'POST',
|
|
url: `${ Cypress.env('api') }/v3/globalrolebindings`,
|
|
headers: {
|
|
'x-api-csrf': token.value,
|
|
Accept: 'application/json'
|
|
},
|
|
body: {
|
|
type: 'globalRoleBinding',
|
|
globalRoleId: role,
|
|
userId
|
|
}
|
|
})
|
|
.then((resp) => {
|
|
expect(resp.status).to.eq(201);
|
|
});
|
|
});
|
|
|
|
/**
|
|
* Set cluster role binding for user via api request
|
|
*
|
|
*/
|
|
Cypress.Commands.add('setClusterRoleBinding', (clusterId, userPrincipalId, role) => {
|
|
return cy.request({
|
|
method: 'POST',
|
|
url: `${ Cypress.env('api') }/v3/clusterroletemplatebindings`,
|
|
headers: {
|
|
'x-api-csrf': token.value,
|
|
Accept: 'application/json'
|
|
},
|
|
body: {
|
|
type: 'clusterRoleTemplateBinding',
|
|
clusterId,
|
|
roleTemplateId: role,
|
|
userPrincipalId
|
|
}
|
|
})
|
|
.then((resp) => {
|
|
expect(resp.status).to.eq(201);
|
|
});
|
|
});
|
|
|
|
/**
|
|
* Set project role binding for user via api request
|
|
*
|
|
*/
|
|
Cypress.Commands.add('setProjectRoleBinding', (clusterId, userPrincipalId, projectName, role) => {
|
|
return cy.getProjectByName(clusterId, projectName)
|
|
.then((project: any) => cy.request({
|
|
method: 'POST',
|
|
url: `${ Cypress.env('api') }/v3/projectroletemplatebindings`,
|
|
headers: {
|
|
'x-api-csrf': token.value,
|
|
Accept: 'application/json'
|
|
},
|
|
body: {
|
|
type: 'projectroletemplatebinding',
|
|
roleTemplateId: role,
|
|
userPrincipalId,
|
|
projectId: project.id
|
|
}
|
|
}))
|
|
.then((resp) => {
|
|
expect(resp.status).to.eq(201);
|
|
});
|
|
});
|
|
|
|
/**
|
|
* Get the project with the given name
|
|
*/
|
|
Cypress.Commands.add('getProjectByName', (clusterId, projectName) => {
|
|
return cy.request({
|
|
method: 'GET',
|
|
url: `${ Cypress.env('api') }/v3/projects?name=${ projectName }&clusterId=${ clusterId }`,
|
|
headers: {
|
|
'x-api-csrf': token.value,
|
|
Accept: 'application/json'
|
|
},
|
|
})
|
|
.then((resp) => {
|
|
expect(resp.status).to.eq(200);
|
|
expect(resp.body?.data?.length).to.eq(1);
|
|
|
|
return resp.body.data[0];
|
|
});
|
|
});
|
|
|
|
/**
|
|
* create a project
|
|
*/
|
|
Cypress.Commands.add('createProject', (projName, clusterId, userId) => {
|
|
return cy.request({
|
|
method: 'POST',
|
|
url: `${ Cypress.env('api') }/v3/projects`,
|
|
headers: {
|
|
'x-api-csrf': token.value,
|
|
Accept: 'application/json'
|
|
},
|
|
body: {
|
|
type: 'project',
|
|
name: projName,
|
|
annotations: {},
|
|
labels: {},
|
|
clusterId,
|
|
creatorId: `${ clusterId }://${ userId }`,
|
|
containerDefaultResourceLimit: {},
|
|
resourceQuota: {},
|
|
namespaceDefaultResourceQuota: {}
|
|
}
|
|
})
|
|
.then((resp) => {
|
|
expect(resp.status).to.eq(201);
|
|
});
|
|
});
|
|
|
|
/**
|
|
* create a namespace
|
|
*/
|
|
Cypress.Commands.add('createNamespace', (nsName, projId) => {
|
|
return cy.request({
|
|
method: 'POST',
|
|
url: `${ Cypress.env('api') }/v1/namespaces`,
|
|
headers: {
|
|
'x-api-csrf': token.value,
|
|
Accept: 'application/json'
|
|
},
|
|
body: {
|
|
metadata: {
|
|
annotations: {
|
|
'field.cattle.io/containerDefaultResourceLimit': '{}',
|
|
'field.cattle.io/projectId': projId
|
|
},
|
|
labels: {
|
|
'field.cattle.io/projectId': projId.split(':')[1],
|
|
'pod-security.kubernetes.io/enforce': 'privileged',
|
|
'pod-security.kubernetes.io/enforce-version': 'latest'
|
|
},
|
|
name: nsName
|
|
},
|
|
disableOpenApiValidation: false
|
|
}
|
|
})
|
|
.then((resp) => {
|
|
expect(resp.status).to.eq(201);
|
|
});
|
|
});
|
|
|
|
/**
|
|
* Create pod
|
|
*/
|
|
Cypress.Commands.add('createPod', (nsName, podName, image) => {
|
|
return cy.request({
|
|
method: 'POST',
|
|
url: `${ Cypress.env('api') }/v1/pods`,
|
|
headers: {
|
|
'x-api-csrf': token.value,
|
|
Accept: 'application/json'
|
|
},
|
|
body: {
|
|
type: 'pod',
|
|
metadata: {
|
|
namespace: nsName, labels: { 'workload.user.cattle.io/workloadselector': `pod-${ nsName }-pod-${ podName }` }, name: `pod-${ podName }`, annotations: {}
|
|
},
|
|
spec: {
|
|
selector: { matchLabels: { 'workload.user.cattle.io/workloadselector': `pod-${ nsName }-pod-${ podName }` } },
|
|
containers: [{
|
|
imagePullPolicy: 'Always', name: 'container-0', _init: false, volumeMounts: [], env: [], envFrom: [], image: `${ image }`, __active: true
|
|
}],
|
|
initContainers: [],
|
|
imagePullSecrets: [],
|
|
volumes: [],
|
|
affinity: {}
|
|
}
|
|
}
|
|
})
|
|
.then((resp) => {
|
|
expect(resp.status).to.eq(201);
|
|
});
|
|
});
|
|
|
|
/**
|
|
* 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
|
|
*/
|
|
// eslint-disable-next-line no-undef
|
|
Cypress.Commands.add('userPreferences', (preferences: Partial<UserPreferences> = {}) => {
|
|
return cy.intercept('/v1/userpreferences*', (req) => {
|
|
req.reply({
|
|
statusCode: 201,
|
|
body: {
|
|
data: [{
|
|
type: 'userpreference',
|
|
data: {
|
|
'after-login-route': '\"home\"',
|
|
cluster: 'local',
|
|
'group-by': 'none',
|
|
'home-page-cards': '',
|
|
'last-namespace': 'default',
|
|
'last-visited': '',
|
|
'ns-by-cluster': '',
|
|
provisioner: '',
|
|
'read-whatsnew': '',
|
|
'seen-whatsnew': '2.x.x',
|
|
theme: '',
|
|
...preferences,
|
|
},
|
|
}]
|
|
},
|
|
});
|
|
});
|
|
});
|
|
|
|
Cypress.Commands.add('requestBase64Image', (url: string) => {
|
|
return cy.request({
|
|
url,
|
|
method: 'GET',
|
|
encoding: 'binary',
|
|
headers: { Accept: 'image/png; charset=UTF-8' },
|
|
})
|
|
.its('body')
|
|
.then((favicon) => {
|
|
const blob = Cypress.Blob.binaryStringToBlob(favicon);
|
|
|
|
return Cypress.Blob.blobToBase64String(blob);
|
|
});
|
|
});
|
|
|
|
/**
|
|
* Get a v3 / v1 resource
|
|
* url is constructed based if resourceId is supplied or not
|
|
*/
|
|
|
|
Cypress.Commands.add('getRancherResource', (prefix, resourceType, resourceId?, expectedStatusCode = 200) => {
|
|
let url = `${ Cypress.env('api') }/${ prefix }/${ resourceType }`;
|
|
|
|
if (resourceId) {
|
|
url += `/${ resourceId }`;
|
|
}
|
|
|
|
return cy.request({
|
|
method: 'GET',
|
|
url,
|
|
headers: {
|
|
'x-api-csrf': token.value,
|
|
Accept: 'application/json'
|
|
},
|
|
})
|
|
.then((resp) => {
|
|
if (expectedStatusCode) {
|
|
expect(resp.status).to.eq(expectedStatusCode);
|
|
}
|
|
|
|
return resp;
|
|
});
|
|
});
|
|
|
|
/**
|
|
* set a v3 / v1 resource
|
|
*/
|
|
Cypress.Commands.add('setRancherResource', (prefix, resourceType, resourceId, body) => {
|
|
return cy.request({
|
|
method: 'PUT',
|
|
url: `${ Cypress.env('api') }/${ prefix }/${ resourceType }/${ resourceId }`,
|
|
headers: {
|
|
'x-api-csrf': token.value,
|
|
Accept: 'application/json'
|
|
},
|
|
body
|
|
})
|
|
.then((resp) => {
|
|
expect(resp.status).to.eq(200);
|
|
});
|
|
});
|
|
|
|
/**
|
|
* delete a v3 / v1 resource
|
|
*/
|
|
Cypress.Commands.add('deleteRancherResource', (prefix, resourceType, resourceId, expectedStatusCode = 200) => {
|
|
return cy.request({
|
|
method: 'DELETE',
|
|
url: `${ Cypress.env('api') }/${ prefix }/${ resourceType }/${ resourceId }`,
|
|
headers: {
|
|
'x-api-csrf': token.value,
|
|
Accept: 'application/json'
|
|
}
|
|
})
|
|
.then((resp) => {
|
|
// Either 200, or 204 (No Content)
|
|
expect(resp.status).to.be.oneOf([200, 204]);
|
|
});
|
|
});
|
|
|
|
/**
|
|
* create a v3 / v1 resource
|
|
*/
|
|
Cypress.Commands.add('createRancherResource', (prefix, resourceType, body) => {
|
|
return cy.request({
|
|
method: 'POST',
|
|
url: `${ Cypress.env('api') }/${ prefix }/${ resourceType }`,
|
|
headers: {
|
|
'x-api-csrf': token.value,
|
|
Accept: 'application/json'
|
|
},
|
|
body
|
|
})
|
|
.then((resp) => {
|
|
// Expect 201, Created HTTP status code
|
|
expect(resp.status).to.eq(201);
|
|
});
|
|
});
|