Repository: aurora Updated Branches: refs/heads/master 4f52f754f -> c6388774b
Add cron configuration to Job Page Reviewed at https://reviews.apache.org/r/63125/ Project: http://git-wip-us.apache.org/repos/asf/aurora/repo Commit: http://git-wip-us.apache.org/repos/asf/aurora/commit/c6388774 Tree: http://git-wip-us.apache.org/repos/asf/aurora/tree/c6388774 Diff: http://git-wip-us.apache.org/repos/asf/aurora/diff/c6388774 Branch: refs/heads/master Commit: c6388774ba2eef7bed18668c8c735d6134d22e80 Parents: 4f52f75 Author: David McLaughlin <[email protected]> Authored: Wed Oct 18 16:16:21 2017 -0700 Committer: David McLaughlin <[email protected]> Committed: Wed Oct 18 16:16:21 2017 -0700 ---------------------------------------------------------------------- ui/.eslintrc | 1 + ui/src/main/js/components/JobConfig.js | 18 ++- ui/src/main/js/components/TaskConfigSummary.js | 110 +++++++++++++++---- .../js/components/__tests__/JobConfig-test.js | 11 +- ui/src/main/js/pages/Job.js | 23 +++- ui/src/main/js/pages/__tests__/Job-test.js | 3 +- ui/src/main/js/utils/Thrift.js | 1 + ui/src/main/sass/components/_job-page.scss | 4 + ui/test-setup.js | 6 + 9 files changed, 144 insertions(+), 33 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/aurora/blob/c6388774/ui/.eslintrc ---------------------------------------------------------------------- diff --git a/ui/.eslintrc b/ui/.eslintrc index f7ac075..5cdc4e6 100644 --- a/ui/.eslintrc +++ b/ui/.eslintrc @@ -11,6 +11,7 @@ "globals": { "ACTIVE_STATES": true, "ACTIVE_JOB_UPDATE_STATES": true, + "CronCollisionPolicy": true, "JobKey": true, "JobUpdateAction": true, "JobUpdateKey": true, http://git-wip-us.apache.org/repos/asf/aurora/blob/c6388774/ui/src/main/js/components/JobConfig.js ---------------------------------------------------------------------- diff --git a/ui/src/main/js/components/JobConfig.js b/ui/src/main/js/components/JobConfig.js index 275f46a..0bce57c 100644 --- a/ui/src/main/js/components/JobConfig.js +++ b/ui/src/main/js/components/JobConfig.js @@ -2,15 +2,27 @@ import React from 'react'; import ConfigDiff from 'components/ConfigDiff'; import Loading from 'components/Loading'; -import TaskConfigSummary from 'components/TaskConfigSummary'; +import TaskConfigSummary, { CronConfigSummary } from 'components/TaskConfigSummary'; import { isNully, sort } from 'utils/Common'; -export default function JobConfig({ groups }) { - if (isNully(groups)) { +export function CronJobConfig({ cronJob }) { + return (<div className='job-configuration'> + <div className='job-configuration-summaries'> + <CronConfigSummary cronJob={cronJob} /> + </div> + </div>); +} + +export default function JobConfig({ cronJob, groups }) { + if (isNully(groups) && isNully(cronJob)) { return <Loading />; } + if (!isNully(cronJob)) { + return <CronJobConfig cronJob={cronJob} />; + } + const sorted = sort(groups, (g) => g.instances[0].first); return (<div className='job-configuration'> <div className='job-configuration-summaries'> http://git-wip-us.apache.org/repos/asf/aurora/blob/c6388774/ui/src/main/js/components/TaskConfigSummary.js ---------------------------------------------------------------------- diff --git a/ui/src/main/js/components/TaskConfigSummary.js b/ui/src/main/js/components/TaskConfigSummary.js index 5c00d1e..2a325d9 100644 --- a/ui/src/main/js/components/TaskConfigSummary.js +++ b/ui/src/main/js/components/TaskConfigSummary.js @@ -1,40 +1,107 @@ +import moment from 'moment'; import React from 'react'; +import { RelativeTime } from 'components/Time'; + import { constraintToString, getResource, getResources, instanceRangeToString } from 'utils/Task'; +import { COLLISION_POLICY } from 'utils/Thrift'; -export default function TaskConfigSummary({ config, instances }) { - return (<table className='table table-bordered task-config-summary'> +// ESLint doesn't like React's new adjacent elements, so we need to disable it here +/* eslint-disable */ +function Resources({ config }) { + return [<tr> + <th rowSpan='4'>Resources</th> + <td>cpus</td> + <td>{getResource(config.resources, 'numCpus').numCpus}</td> + </tr>, + <tr> + <td>ram</td> + <td>{getResource(config.resources, 'ramMb').ramMb}</td> + </tr>, + <tr> + <td>disk</td> + <td>{getResource(config.resources, 'diskMb').diskMb}</td> + </tr>, + <tr> + <td>ports</td> + <td>{getResources(config.resources, 'namedPort').map((r) => r.namedPort).join(', ')}</td> + </tr>]; +} +/* eslint-enable */ + +function Constraints({ config }) { + return (<tr> + <th>Constraints</th> + <td colSpan='2'> + {config.constraints.map((t) => (<span className='task-constraint' key={t.name}> + {t.name}: {constraintToString(t.constraint)} + </span>))} + </td> + </tr>); +} + +function Metadata({ config }) { + return (<tr> + <th>Metadata</th> + <td colSpan='2'> + {config.metadata.map((m, i) => <span key={`${m.key}-${i}`}>{m.key}: {m.value}</span>)} + </td> + </tr>); +} + +export function CronConfigSummary({ cronJob }) { + const config = cronJob.job.taskConfig; + return (<table className='table table-bordered task-config-summary cron-config-summary'> <tbody> <tr> <th colSpan='100%'> - Configuration for instance {instanceRangeToString(instances)} + Cron Job Configuration </th> </tr> <tr> - <th rowSpan='4'>Resources</th> - <td>cpus</td> - <td>{getResource(config.resources, 'numCpus').numCpus}</td> + <th>Cron Schedule</th> + <td colSpan='2'>{cronJob.job.cronSchedule}</td> </tr> <tr> - <td>ram</td> - <td>{getResource(config.resources, 'ramMb').ramMb}</td> + <th>Collision Policy</th> + <td colSpan='2'>{COLLISION_POLICY[cronJob.job.cronCollisionPolicy]}</td> </tr> <tr> - <td>disk</td> - <td>{getResource(config.resources, 'diskMb').diskMb}</td> + <th>Next Cron Run</th> + <td colSpan='2'> + {moment(cronJob.nextCronRunMs).format('MMMM Do YYYY, h:mm:ss a')} UTC ( + <RelativeTime ts={cronJob.nextCronRunMs} />) + </td> </tr> <tr> - <td>ports</td> - <td>{getResources(config.resources, 'namedPort').map((r) => r.namedPort).join(', ')}</td> + <th># Instances</th> + <td colSpan='2'>{cronJob.job.instanceCount}</td> </tr> + <Resources config={config} /> + <Constraints config={config} /> <tr> - <th>Constraints</th> - <td colSpan='2'> - {config.constraints.map((t) => (<span className='task-constraint' key={t.name}> - {t.name}: {constraintToString(t.constraint)} - </span>))} - </td> + <th>Tier</th> + <td colSpan='2'>{config.tier}</td> + </tr> + <Metadata config={config} /> + <tr> + <th>Contact</th> + <td colSpan='2'>{config.contactEmail}</td> + </tr> + </tbody> + </table>); +} + +export default function TaskConfigSummary({ config, instances }) { + return (<table className='table table-bordered task-config-summary'> + <tbody> + <tr> + <th colSpan='100%'> + Configuration for instance {instanceRangeToString(instances)} + </th> </tr> + <Resources config={config} /> + <Constraints config={config} /> <tr> <th>Tier</th> <td colSpan='2'>{config.tier}</td> @@ -43,12 +110,7 @@ export default function TaskConfigSummary({ config, instances }) { <th>Service</th> <td colSpan='2'>{config.isService ? 'true' : 'false'}</td> </tr> - <tr> - <th>Metadata</th> - <td colSpan='2'> - {config.metadata.map((m, i) => <span key={`${m.key}-${i}`}>{m.key}: {m.value}</span>)} - </td> - </tr> + <Metadata config={config} /> <tr> <th>Contact</th> <td colSpan='2'>{config.contactEmail}</td> http://git-wip-us.apache.org/repos/asf/aurora/blob/c6388774/ui/src/main/js/components/__tests__/JobConfig-test.js ---------------------------------------------------------------------- diff --git a/ui/src/main/js/components/__tests__/JobConfig-test.js b/ui/src/main/js/components/__tests__/JobConfig-test.js index 59541d9..cd1b7a0 100644 --- a/ui/src/main/js/components/__tests__/JobConfig-test.js +++ b/ui/src/main/js/components/__tests__/JobConfig-test.js @@ -2,10 +2,11 @@ import React from 'react'; import { shallow } from 'enzyme'; import ConfigDiff from '../ConfigDiff'; -import JobConfig from '../JobConfig'; +import JobConfig, { CronJobConfig } from '../JobConfig'; import Loading from '../Loading'; import TaskConfigSummary from '../TaskConfigSummary'; +import { JobSummaryBuilder } from 'test-utils/JobBuilders'; import { TaskConfigBuilder, createConfigGroup } from 'test-utils/TaskBuilders'; describe('JobConfig', () => { @@ -20,8 +21,14 @@ describe('JobConfig', () => { expect(el.contains(<ConfigDiff groups={[group0, group1, group2]} />)).toBe(true); }); - it('Should render Loading when no groups are supplied', () => { + it('Should render Loading when no groups or cronJob are supplied', () => { const el = shallow(<JobConfig />); expect(el.contains(<Loading />)).toBe(true); }); + + it('Should render CronJobConfig when cronJob is supplied', () => { + const cron = JobSummaryBuilder.build(); + const el = shallow(<JobConfig cronJob={cron} />); + expect(el.contains(<CronJobConfig cronJob={cron} />)).toBe(true); + }); }); http://git-wip-us.apache.org/repos/asf/aurora/blob/c6388774/ui/src/main/js/pages/Job.js ---------------------------------------------------------------------- diff --git a/ui/src/main/js/pages/Job.js b/ui/src/main/js/pages/Job.js index 6a9bd7e..070f1e4 100644 --- a/ui/src/main/js/pages/Job.js +++ b/ui/src/main/js/pages/Job.js @@ -27,7 +27,8 @@ export default class Job extends React.Component { configGroups: props.configGroups, tasks: props.tasks, updates: props.updates, - pendingReasons: props.pendingReasons + pendingReasons: props.pendingReasons, + cronJob: props.cronJob }; } @@ -58,6 +59,20 @@ export default class Job extends React.Component { configGroups: response.result.configSummaryResult.summary.groups }); }); + api.getJobSummary(role, (response) => { + const cronJob = response.result.jobSummaryResult.summaries.find((j) => { + return j.job.key.environment === that.props.match.params.environment && + j.job.key.name === that.props.match.params.name && + !isNully(j.job.cronSchedule); + }); + + if (cronJob) { + that.setState({ + cluster: response.serverInfo.clusterName, + cronJob + }); + } + }); const updateQuery = new JobUpdateQuery(); updateQuery.jobKey = key; @@ -123,7 +138,9 @@ export default class Job extends React.Component { jobStatusTab() { const activeTasks = sort(this.state.tasks.filter(isActive), (t) => t.assignedTask.instanceId); - const numberConfigs = isNully(this.state.configGroups) ? '' : this.state.configGroups.length; + const numberConfigs = isNully(this.state.cronJob) + ? isNully(this.state.configGroups) ? '' : this.state.configGroups.length + : 1; return { id: JOB_STATUS_TAB, name: 'Job Status', @@ -143,7 +160,7 @@ export default class Job extends React.Component { icon: 'info-sign', id: TASK_CONFIG_TAB, name: `Configuration (${numberConfigs})`, - content: <JobConfig groups={this.state.configGroups} /> + content: <JobConfig cronJob={this.state.cronJob} groups={this.state.configGroups} /> }]} /> </PanelGroup>) }; http://git-wip-us.apache.org/repos/asf/aurora/blob/c6388774/ui/src/main/js/pages/__tests__/Job-test.js ---------------------------------------------------------------------- diff --git a/ui/src/main/js/pages/__tests__/Job-test.js b/ui/src/main/js/pages/__tests__/Job-test.js index 09dd54e..03ef20d 100644 --- a/ui/src/main/js/pages/__tests__/Job-test.js +++ b/ui/src/main/js/pages/__tests__/Job-test.js @@ -23,7 +23,8 @@ function apiSpy() { getTasksWithoutConfigs: jest.fn(), getPendingReason: jest.fn(), getConfigSummary: jest.fn(), - getJobUpdateDetails: jest.fn() + getJobUpdateDetails: jest.fn(), + getJobSummary: jest.fn() }; } http://git-wip-us.apache.org/repos/asf/aurora/blob/c6388774/ui/src/main/js/utils/Thrift.js ---------------------------------------------------------------------- diff --git a/ui/src/main/js/utils/Thrift.js b/ui/src/main/js/utils/Thrift.js index 4336bd1..a097037 100644 --- a/ui/src/main/js/utils/Thrift.js +++ b/ui/src/main/js/utils/Thrift.js @@ -3,6 +3,7 @@ import { invert } from 'utils/Common'; export const SCHEDULE_STATUS = invert(ScheduleStatus); export const UPDATE_STATUS = invert(JobUpdateStatus); export const UPDATE_ACTION = invert(JobUpdateAction); +export const COLLISION_POLICY = invert(CronCollisionPolicy); export const OKAY_SCHEDULE_STATUS = [ ScheduleStatus.RUNNING, http://git-wip-us.apache.org/repos/asf/aurora/blob/c6388774/ui/src/main/sass/components/_job-page.scss ---------------------------------------------------------------------- diff --git a/ui/src/main/sass/components/_job-page.scss b/ui/src/main/sass/components/_job-page.scss index cd03832..91b731f 100644 --- a/ui/src/main/sass/components/_job-page.scss +++ b/ui/src/main/sass/components/_job-page.scss @@ -68,6 +68,10 @@ } } + .cron-config-summary { + width: 500px !important; + } + tr:first-child { background-color: $grid_color; } http://git-wip-us.apache.org/repos/asf/aurora/blob/c6388774/ui/test-setup.js ---------------------------------------------------------------------- diff --git a/ui/test-setup.js b/ui/test-setup.js index a86a89a..5b739de 100644 --- a/ui/test-setup.js +++ b/ui/test-setup.js @@ -64,3 +64,9 @@ global.JobUpdateAction = { 'INSTANCE_UPDATE_FAILED' : 5, 'INSTANCE_ROLLBACK_FAILED' : 6 }; + +global.CronCollisionPolicy = { + 'KILL_EXISTING': 0, + 'CANCEL_NEW': 1, + 'RUN_OVERLAP': 2 +};
