Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
42 changes: 42 additions & 0 deletions cypress/apps/kvm.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
apiVersion: kubevirt.io/v1
kind: VirtualMachine
metadata:
name: test-vm-yaml
spec:
running: true
template:
spec:
domain:
cpu:
cores: 2
devices:
disks:
- disk:
bus: virtio
name: containerdisk
- disk:
bus: virtio
name: cloudinitdisk
interfaces:
- masquerade: {}
name: default
ports:
- port: 22
rng: {}
memory:
guest: 1024M
resources: {}
networks:
- name: default
pod: {}
volumes:
- name: containerdisk
containerDisk:
image: quay.io/containerdisks/fedora:40
- name: cloudinitdisk
cloudInitNoCloud:
userData: |
#cloud-config
ssh_pwauth: true
password: fedora
chpasswd: { expire: False }
33 changes: 20 additions & 13 deletions cypress/e2e/device.cy.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,9 @@
import { devicesPage, LOG_PRIORITIES } from '../views/devicesPage'

const DEVICE_NAME = 'test-device'
const DEVICE_NAME_EDITED = 'test-device-edited'
const DEVICE_NAME_EDITED_2 = 'test-device-edited2'

describe('Device Management', () => {
// One login + visit per spec file; later tests reuse the same tab (testIsolation: false).
before(() => {
Expand Down Expand Up @@ -44,37 +48,39 @@ describe('Device Management', () => {
})
})

describe('Approve device, edit device, view device events', () => {
describe('Approve device', () => {
it('Should approve a device enrollment request', () => {
devicesPage.approveDevice()
devicesPage.approveDevice(DEVICE_NAME)
})

/* it('Should open a terminal on a device', () => {
devicesPage.openTerminal()
}) */
})

describe('Edit device, view device events', () => {
it('Should edit a device', () => {
devicesPage.editDevice(`${Cypress.env('image')}`)
devicesPage.editDevice(`${Cypress.env('image')}`, DEVICE_NAME, DEVICE_NAME_EDITED)
})

it('Should edit a device image - fake url', () => {
devicesPage.editDevice(`quay.io/redhat/rhde:9.2`, 'test-device-edited', 'test-device-edited2')
devicesPage.editDevice(`quay.io/redhat/rhde:9.2`, DEVICE_NAME_EDITED, DEVICE_NAME_EDITED_2)
})

it('Should make sure device is out-of-date', () => {
devicesPage.checkDeviceOutOfDate()
devicesPage.checkDeviceOutOfDate(DEVICE_NAME_EDITED_2)
})

it('Should view device events', () => {
devicesPage.deviceEvents()
devicesPage.deviceEvents(DEVICE_NAME_EDITED_2)
})
})

describe('View device logs, filter by priority, search, download', () => {
const logMarker = (priority) => `CYPRESS_LOG_TEST_${priority.toUpperCase()}`

it('Should retrieve agent logs with default filters', () => {
devicesPage.openDeviceLogs()
devicesPage.openDeviceLogs(DEVICE_NAME_EDITED_2)
devicesPage.retrieveLogsAndVerify()
})

Expand All @@ -90,15 +96,15 @@ describe('Device Management', () => {
})

it('Should show error for non-existing file path', () => {
devicesPage.openDeviceLogs()
devicesPage.openDeviceLogs(DEVICE_NAME_EDITED_2)
devicesPage.selectLogCategory('File path')
cy.get('input[name="logFilePath"]', { timeout: 15000 }).clear().type('nonexistent-file-xyz.log')
cy.contains('button', 'Retrieve logs').should('not.be.disabled').click()
cy.get('.pf-m-danger, [class*="danger"]', { timeout: 30000 }).should('be.visible')
})

it('Should show error for directory file path', () => {
devicesPage.openDeviceLogs()
devicesPage.openDeviceLogs(DEVICE_NAME_EDITED_2)
devicesPage.selectLogCategory('File path')
cy.get('input[name="logFilePath"]', { timeout: 15000 }).clear().type('audit')
cy.contains('button', 'Retrieve logs').should('not.be.disabled').click()
Expand All @@ -107,13 +113,14 @@ describe('Device Management', () => {

it('Should inject logger messages at each syslog priority', () => {
cy.task('flightctlConsoleCommand', {
deviceAlias: DEVICE_NAME_EDITED_2,
commands: LOG_PRIORITIES.map(p => `logger -p user.${p.key} "${logMarker(p.key)}"`)
})
})

LOG_PRIORITIES.forEach(({ key, level }, index) => {
it(`Should show ${key} message and all higher priorities`, () => {
devicesPage.openDeviceLogs()
devicesPage.openDeviceLogs(DEVICE_NAME_EDITED_2)
devicesPage.selectLogCategory('System')
devicesPage.selectLogTimeRange('Last 1 hour')
devicesPage.selectLogLevel(level)
Expand All @@ -126,7 +133,7 @@ describe('Device Management', () => {
})

it('Should enable live logs and receive new entries', () => {
devicesPage.openDeviceLogs()
devicesPage.openDeviceLogs(DEVICE_NAME_EDITED_2)
devicesPage.selectLogCategory('Agent')
devicesPage.selectLogTimeRange('Current boot')
devicesPage.retrieveLogsAndVerify()
Expand All @@ -144,7 +151,7 @@ describe('Device Management', () => {
})

it('Should find and highlight search results', () => {
devicesPage.openDeviceLogs()
devicesPage.openDeviceLogs(DEVICE_NAME_EDITED_2)
devicesPage.retrieveLogsAndVerify()
devicesPage.searchLogsFor('flightctl')
})
Expand All @@ -161,7 +168,7 @@ describe('Device Management', () => {

describe('Decommission device', () => {
it('Should decommission a device', () => {
devicesPage.decommissionDevice()
devicesPage.decommissionDevice(DEVICE_NAME_EDITED_2)
})
})

Expand Down
29 changes: 29 additions & 0 deletions cypress/e2e/deviceApps.cy.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
import { devicesPage } from '../views/devicesPage'

const DEVICE_APPS = 'test-apps'

describe('Device applications (KVM)', () => {
before(() => {
cy.ensureLoggedIn()
})

it('Should approve the apps device enrollment request', () => {
devicesPage.approveDevice(DEVICE_APPS)
})

it('Should add Form and YAML KVM apps via edit-device wizard and reach Running', { timeout: 720000 }, () => {
devicesPage.addApplications(DEVICE_APPS, [
{ mode: 'form', name: 'test-vm', hostPort: '2222', guestPort: '22' },
{ mode: 'yaml', name: 'test-vm-yaml', yaml: 'apps/kvm.yaml', hostPort: '2223', guestPort: '22' },
])
devicesPage.waitForVmAppRunning(DEVICE_APPS, 'test-vm')
devicesPage.waitForVmAppRunning(DEVICE_APPS, 'test-vm-yaml')
})

it('Should open test-vm serial console and login as fedora', { timeout: 360000 }, () => {
devicesPage.openVmAppConsole(DEVICE_APPS, 'test-vm')
devicesPage.loginVmSerialConsole('fedora', 'fedora')
devicesPage.selectVmConsole('test-vm-yaml')
devicesPage.loginVmSerialConsole('fedora', 'fedora')
})
})
19 changes: 13 additions & 6 deletions cypress/plugins/flightctlConsoleTasks.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
*
* Usage in tests:
* cy.task('flightctlConsoleCommand', {
* deviceAlias: 'test-device-edited2',
* commands: ['logger -p user.info "test message"', 'whoami']
* })
*/
Expand Down Expand Up @@ -55,12 +56,17 @@ function getFlightctlBin() {
return 'flightctl'
}

function getDeviceName(bin) {
function getDeviceName(bin, alias) {
try {
const output = execSync(`${bin} get devices -o json`, { encoding: 'utf-8', timeout: 15000 })
const devices = JSON.parse(output)
if (devices.items && devices.items.length > 0) {
return devices.items[0].metadata.name
const items = devices.items || []
if (alias) {
const match = items.find((d) => d.metadata?.labels?.alias === alias)
if (match) return match.metadata.name
}
if (items.length > 0) {
return items[0].metadata.name
}
} catch (e) { /* fall through */ }
return null
Expand Down Expand Up @@ -262,11 +268,12 @@ function registerFlightctlConsoleTasks(on) {
return { seeded: true }
},

flightctlConsoleCommand({ commands }) {
flightctlConsoleCommand({ commands, deviceAlias }) {
const bin = getFlightctlBin()
const deviceName = getDeviceName(bin)
const deviceName = getDeviceName(bin, deviceAlias)
if (!deviceName) {
return [{ cmd: 'get devices', stdout: '', error: `No enrolled device found (using ${bin})` }]
const hint = deviceAlias ? ` alias=${deviceAlias}` : ''
return [{ cmd: 'get devices', stdout: '', error: `No enrolled device found${hint} (using ${bin})` }]
}

const results = []
Expand Down
Loading