Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add logo, fix jobRow.finishedAt and test jobRow elements #54

Merged
merged 1 commit into from
May 6, 2024
Merged
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
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
Loading