Skip to content

Commit

Permalink
Add logo, fix jobRow.finishedAt and test CronJobRow/JobRow elements
Browse files Browse the repository at this point in the history
  • Loading branch information
danroux committed May 6, 2024
1 parent 1af7e44 commit 324e0f4
Show file tree
Hide file tree
Showing 9 changed files with 245 additions and 57 deletions.
3 changes: 3 additions & 0 deletions .changelog/54.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
```release-note:enhancement
Add logo, fix jobRow.finishedAt and test CronJobRow/JobRow elements
```
5 changes: 3 additions & 2 deletions .github/workflows/k8s-test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,7 @@ jobs:
- name: Update config files with dev docker image tag
if:
run: |
pr_image_tag=pre-${{ inputs.image_tag }}
pr_image_tag=pre-${{ inputs.pull_request_number }}-v1.29.2
cp testdata/sk8l-values.yml testdata/sk8l-values.yml.bak
yq e -i ".sk8lUi.imageTag = \"$pr_image_tag\"" testdata/sk8l-values.yml
set +e
Expand All @@ -66,7 +66,8 @@ jobs:
- name: ui smoke tests
id: ui_smoke_tests
run: |
./ci/ui_smoke_tests.sh ghcr.io/danroux/sk8l-ui:ui-test-${{ inputs.image_tag }}
image_tag=ui-test-${{ inputs.pull_request_number }}-v1.29.2
./ci/ui_smoke_tests.sh ghcr.io/danroux/sk8l-ui:$image_tag
- name: ui smoke tests error output
if: ${{ failure() && steps.ui_smoke_tests.conclusion == 'failure' }}
run: |
Expand Down
202 changes: 174 additions & 28 deletions cypress/integration/sk8l.spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -19,8 +19,60 @@ describe('Home Test', () => {
cy.contains('Cronjob activity')
cy.contains('33%')
cy.contains('Latest completions')
})
});

describe('CronJobRow Details', () => {
it('displays details for a working cronjob correctly', () => {
cy.visit('https://sk8l-ui:8001/')
const cronJobName = 'process-videos';
cy.get(`#cronjob-${cronJobName}`).as('cronJobElement');

cy.get('@cronJobElement')
.should('exist');

cy.get('@cronJobElement')
.find('.cronjob-namespace')
.should('exist')
.contains('sk8l');

cy.get('@cronJobElement')
.find('.cronjob-completions')
.should('exist')
.contains('1');

cy.get('@cronJobElement')
.find('.cronjob-parallelism')
.should('exist')
.contains('1');

cy.get('@cronJobElement')
.find('.cronjob-creation-time')
.should('exist')
.contains(/\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}Z/)

cy.get('@cronJobElement')
.find('.cronjob-last-duration')
.should('exist')
.contains(/\d+ sec|(\d+ min, \d+ sec)/);

cy.get('@cronJobElement')
.find('.cronjob-successful-time')
.should('exist')
.contains(/\d+ (?:second|minute)(s)? ago/);

cy.get('@cronJobElement')
.find('.cronjob-completion-time')
.should('exist')
.contains(/\d+ (?:second|minute)(s)? ago/);

// cy.get('@cronJobElement')
// .find('.cronjob-failure-time')
// .should('exist');
});
});
});

describe('/cronjobs/:namespace', () => {
it('visits a cronjob', () => {
cy.visit('https://sk8l-ui:8001/cronjob/sk8l/download-report-files')
cy.contains('Overview')
Expand Down Expand Up @@ -55,33 +107,127 @@ describe('Home Test', () => {
cy.contains('Host:')
cy.contains('Pod Ips:')
})
});

describe('/jobs/:namespace', () => {
it("visits /jobs/:namespace ", () => {
cy.visit('https://sk8l-ui:8001/jobs/sk8l/')
cy.get('#jobs-timeline').should('exist')
cy.contains('Job activity')
cy.get('.job-row').should('have.length', 2)
cy.get('.completed-job').should('have.length.gt', 0)

cy.get('.completed-job')
.should('have.length.gt', 0)
.its('length')
.then((count) => {
expect(count).to.be.greaterThan(0)
cy.log(`Found ${count} elements with class '.completed-job'`)
})

cy.get('#job-cypress-job.job-row')
.find('strong.job-name')
describe('/jobs/:namespace', () => {
it("visits /jobs/:namespace ", () => {
cy.visit('https://sk8l-ui:8001/jobs/sk8l/')
cy.get('#jobs-timeline').should('exist')
cy.contains('Job activity')
cy.get('.job-row').should('have.length', 3)
cy.get('.completed-job').should('have.length.gt', 0)

cy.get('.completed-job')
.should('have.length.gt', 0)
.its('length')
.then((count) => {
expect(count).to.be.greaterThan(0)
cy.log(`Found ${count} elements with class '.completed-job'`)
})

cy.get('#job-cypress-job.job-row')
.find('strong.job-name')
.should('exist')
.and('have.text', 'cypress-job');

cy.get('#job-sk8l-demo-job.job-row').within(() => {
cy.get('strong.job-name')
.should('exist')
.and('have.text', 'cypress-job');

cy.get('#job-sk8l-demo-job.job-row').within(() => {
cy.get('strong.job-name')
.should('exist')
.and('have.text', 'sk8l-demo-job');
});
})
.and('have.text', 'sk8l-demo-job');
});
})
})

describe('JobRow Details', () => {
it('displays details for a working job correctly', () => {
cy.visit('https://sk8l-ui:8001/jobs/sk8l/')
cy.get('#job-sk8l-demo-job').as('jobElement');

cy.get('@jobElement')
.find('.job-uuid')
.should('exist');

cy.get('@jobElement')
.find('.job-row-footer')
.should('exist');

cy.get('@jobElement')
.find('.job-completions')
.should('exist');

cy.get('@jobElement')
.find('.job-parallelism')
.should('exist');

cy.get('@jobElement')
.find('.job-suspend')
.should('exist');

cy.get('@jobElement')
.find('.job-start-time')
.should('exist')
.contains(/\d+ (?:second|minute)(s)? ago/);

cy.get('@jobElement')
.find('.job-duration-time')
.should('exist')
.contains(/\d+ sec|(\d+ min, \d+ sec)/);

cy.get('@jobElement')
.find('.job-completion-time')
.should('exist')
.contains(/\d+ (?:second|minute)(s)? ago/);
});

it('displays details for a failing job correctly', () => {
cy.visit('https://sk8l-ui:8001/jobs/sk8l/')
cy.get('#job-sk8l-failing-demo-job').as('jobElement');

// ['job-uuid', 'job-failure-condition', 'job-row-footer', 'job-completions', 'job-parallelism',
// 'job-suspend', 'job-start-time', 'job-duration-time', 'job-failure-time', 'job-completion-time']
// .forEach(className => {
// cy.get('@jobElement')
// .find(`.${className}`)
// .should('exist');
// });

cy.get('@jobElement')
.find('.job-uuid')
.should('exist');

cy.get('@jobElement')
.find('.job-failure-condition')
.should('exist');

cy.get('@jobElement')
.find('.job-row-footer')
.should('exist');

cy.get('@jobElement')
.find('.job-completions')
.should('exist');

cy.get('@jobElement')
.find('.job-parallelism')
.should('exist');

cy.get('@jobElement')
.find('.job-suspend')
.should('exist');

cy.get('@jobElement')
.find('.job-start-time')
.should('exist')
.contains(/\d+ (?:second|minute)(s)? ago/);

cy.get('@jobElement')
.find('.job-duration-time')
.should('exist')
.contains(/\d+ sec|(\d+ min, \d+ sec)/);

cy.get('@jobElement')
.find('.job-failure-time')
.should('exist')
.contains(/\d+ (?:second|minute)(s)? ago/);
});
});
});
3 changes: 2 additions & 1 deletion index.html
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,8 @@
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta name="description" content="">
<meta name="author" content="">
<link href='https://fonts.googleapis.com/css?family=Open+Sans:300italic,400italic,600italic,700italic,800italic,400,300,600,700,800' rel='stylesheet' type='text/css'>
<link href='https://fonts.googleapis.com/css?family=Open+Sans:300italic,400italic,600italic,700italic,800italic,400,300,600,700,800'
rel='stylesheet' type='text/css'>
<script defer src="/assets/fontawesome/js/all.js"></script>

<link id="theme-style" rel="stylesheet" href="/assets/css/modal.vue.css">
Expand Down
18 changes: 9 additions & 9 deletions src/components/CronJobRow.vue
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@

<template>
<!-- eslint-disable -->
<li>
<li :id="`cronjob-${cronJob.name}`">
<div class="d-block">
<div class="d-flex flex-justify-between">
<div class="mb-0 col-9">
Expand All @@ -29,31 +29,31 @@
<div class="color-fg-muted f6">
<StatusProp :propText="status" />

<span class="mr-2">
<span class="mr-2 cronjob-namespace">
<Octicon name="north-star" /> {{ cronJob.namespace }}
</span>
<span class="mr-2">
<span class="mr-2 cronjob-completions">
<Octicon name="stack" />{{ cronJob.spec.jobTemplate.spec.completions || "1" }}
</span>
<span class="mr-2">
<span class="mr-2 cronjob-parallelism">
<Octicon name="versions" /> {{ cronJob.spec.jobTemplate.spec.parallelism || "1" }}
</span>
<span class="mr-2">
<span class="mr-2 cronjob-creation-time">
<Octicon name="sun" /> {{ cronJob.creationTimestamp }}
</span>
<template v-if="all.length > 0">
<span class="mr-2">
<span class="mr-2 cronjob-last-duration">
<Octicon name="stopwatch" /> {{ duration(cronJob.lastDuration) }}
</span>
<span class="mr-2" v-if="lastFailed && showLastFailure">
<span class="mr-2 cronjob-failure-time" v-if="lastFailed && showLastFailure">
<Octicon name="x-circle-fill" /> {{ lux1(lastFailureTime) }}
</span>

<template v-if="lastSucceeded">
<span class="mr-2">
<span class="mr-2 cronjob-successful-time">
<Octicon name="calendar" /> {{ lux1(cronJob.lastSuccessfulTime) }}
</span>
<span class="mr-2">
<span class="mr-2 cronjob-completion-time">
<Octicon name="goal" /> {{ luxs(Number(lastSucceeded.status.completionTime.seconds)) }}
</span>
</template>
Expand Down
3 changes: 2 additions & 1 deletion src/components/CronjobListHeader.vue
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,8 @@
<div class="container-xl pt-4 pt-lg-0 p-responsive clearfix">
<div class="d-flex flex-wrap flex-items-start flex-md-items-center my-3">
<div>
<img itemprop="image" class="avatar flex-shrink-0 mb-3 mr-3 mb-md-0 mr-md-4" src="https://www.npmjs.com/npm-avatar/eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJhdmF0YXJVUkwiOiJodHRwczovL3MuZ3JhdmF0YXIuY29tL2F2YXRhci8zNDAyNGQxNGM5OWZhNTEyODRkYzBjOGQ5MTYzYjAzOD9zaXplPTQ5NiZkZWZhdWx0PXJldHJvIn0.03zIr0EjnNyAiquvrP_54MEiP1K9BkSCiuzu7yWQj_8" alt="@primer" width="100" height="100">
<img itemprop="image" class="avatar flex-shrink-0 mb-3 mr-3 mb-md-0 mr-md-4"
src="https://sk8l.io/charts/logo.png" alt="sk8l.io" width="100" height="100">
</div>
<div class="flex-1">
<h1 class="h2 lh-condensed">
Expand Down
50 changes: 35 additions & 15 deletions src/components/JobRow.vue
Original file line number Diff line number Diff line change
Expand Up @@ -23,22 +23,38 @@
</span>
Container: {{ tl.containerName }}
</p>

<p class="color-fg-muted mb-0 wb-break-word" v-if="job.failureCondition">
<span class="job-failure-condition" >
{{ job.failureCondition.reason }} - {{ job.failureCondition.message }}
</span>
</p>
</div>
</div>
</div>
<div class="color-fg-muted f6 mt-2">
<div class="color-fg-muted f6 mt-2 job-row-footer">
<StatusProp :propText="status" />

<span class="mr-2"><Octicon name="stack" /> {{ job.spec.completions }}</span>
<span class="mr-2"><Octicon name="versions" /> {{ job.spec.parallelism }}</span>
<span class="mr-2"><Octicon name="strikethrough" /> {{ job.spec.suspend }}</span>
<span class="mr-2"><Octicon name="sparkle-fill" /> {{ luxs(job.status.startTime.seconds) }}</span>
<span class="mr-2"><Octicon name="stopwatch" /> {{ duration(job.durationInS) }}</span>
<span class="mr-2" v-if="job.failed">
<Octicon name="x-circle-fill" /> {{ lux1(lastFailureTime) }}
<span class="mr-2 job-completions">
<Octicon name="stack" /> {{ job.spec.completions }}
</span>
<span class="mr-2 job-parallelism">
<Octicon name="versions" /> {{ job.spec.parallelism }}
</span>
<span class="mr-2 job-suspend">
<Octicon name="strikethrough" /> {{ job.spec.suspend }}
</span>
<span class="mr-2" v-if="job.status.succeeded && job.status.completiontime">
<Octicon name="goal" /> Completed {{ luxs(job.status.completionTime.seconds) }}
<span class="mr-2 job-start-time">
<Octicon name="sparkle-fill" /> {{ luxs(job.status.startTime.seconds) }}
</span>
<span class="mr-2 job-duration-time">
<Octicon name="stopwatch" /> {{ duration(job.durationInS) }}
</span>
<span class="mr-2 job-failure-time" v-if="job.failed">
<Octicon name="x-circle-fill" /> {{ luxs(lastFailureTime) }}
</span>
<span class="mr-2 job-completion-time" v-if="job.status.succeeded && job.status.completionTime">
<Octicon name="goal" /> {{ luxs(job.status.completionTime.seconds) }}
</span>
</div>
</li>
Expand Down Expand Up @@ -104,13 +120,17 @@ export default {
}
},
lastFailureTime() {
if (this.job.failure_condition) {
return lastTransitionTime = this.job.lastFailed.failure_condition.lastTransitionTime;
// when it failed
if (this.job.failureCondition) {
if (this.job.failed) {
let lastTransitionTime = this.job.failureCondition.lastTransitionTime.seconds;
return lastTransitionTime;
}
}
const l = Number(this.job.terminationReasons.find((first) => first).terminationDetails.finishedAt.seconds);
const dt = DateTime.fromSeconds(l);
return dt;
// while is failing
const finishedAt = this.job.terminationReasons.find((first) => first).terminationDetails.finishedAt.seconds;
return finishedAt;
},
pods(vm) {
return PodsGenerator.pods(vm.job.pods);
Expand Down
2 changes: 1 addition & 1 deletion src/components/PodRow.vue
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@
<span v-if="tr.terminationDetails.message">
Message: {{ tr.terminationDetails.message }}<br/>
</span>
Container: {{ tr.terminationDetails.containerName }}
<span class="termination-reason-container">Container: {{ tr.containerName }}</span>
</p>
</div>
</div>
Expand Down
Loading

0 comments on commit 324e0f4

Please sign in to comment.