Skip to content
GitLab
Menu
Projects
Groups
Snippets
Help
Projects
Groups
Snippets
Help
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Sign in
Toggle navigation
Menu
Open sidebar
小 白蛋
Nomad
Commits
da1e1797
Commit
da1e1797
authored
6 years ago
by
Michael Lange
Browse files
Options
Download
Email Patches
Plain Diff
Parse and Plan API and UI workflows
parent
302401d4
Changes
6
Hide whitespace changes
Inline
Side-by-side
Showing
6 changed files
ui/app/adapters/job.js
+20
-0
ui/app/adapters/job.js
ui/app/controllers/jobs/run.js
+36
-0
ui/app/controllers/jobs/run.js
ui/app/models/job.js
+46
-0
ui/app/models/job.js
ui/app/routes/jobs/run.js
+13
-0
ui/app/routes/jobs/run.js
ui/app/styles/components/codemirror.scss
+1
-1
ui/app/styles/components/codemirror.scss
ui/app/templates/jobs/run.hbs
+51
-24
ui/app/templates/jobs/run.hbs
with
167 additions
and
25 deletions
+167
-25
ui/app/adapters/job.js
+
20
-
0
View file @
da1e1797
...
...
@@ -59,6 +59,26 @@ export default Watchable.extend({
const
url
=
this
.
urlForFindRecord
(
job
.
get
(
'
id
'
),
'
job
'
);
return
this
.
ajax
(
url
,
'
DELETE
'
);
},
parse
(
spec
)
{
const
url
=
addToPath
(
this
.
urlForFindAll
(
'
job
'
),
'
/parse
'
);
return
this
.
ajax
(
url
,
'
POST
'
,
{
data
:
{
JobHCL
:
spec
,
Canonicalize
:
true
,
},
});
},
plan
(
job
)
{
const
url
=
addToPath
(
this
.
urlForFindRecord
(
job
.
get
(
'
id
'
),
'
job
'
),
'
/plan
'
);
return
this
.
ajax
(
url
,
'
POST
'
,
{
data
:
{
Job
:
job
.
get
(
'
_newDefinitionJSON
'
),
Diff
:
true
,
},
});
},
});
function
associateNamespace
(
url
,
namespace
)
{
...
...
This diff is collapsed.
Click to expand it.
ui/app/controllers/jobs/run.js
0 → 100644
+
36
-
0
View file @
da1e1797
import
Controller
from
'
@ember/controller
'
;
import
{
computed
}
from
'
@ember/object
'
;
import
{
task
}
from
'
ember-concurrency
'
;
export
default
Controller
.
extend
({
stage
:
computed
(
'
planOutput
'
,
function
()
{
return
this
.
get
(
'
planOutput
'
)
?
'
plan
'
:
'
editor
'
;
}),
plan
:
task
(
function
*
()
{
this
.
cancel
();
try
{
yield
this
.
get
(
'
model
'
).
parse
();
}
catch
(
err
)
{
this
.
set
(
'
parseError
'
,
err
);
}
try
{
const
planOutput
=
yield
this
.
get
(
'
model
'
).
plan
();
console
.
log
(
'
Heyo!
'
,
planOutput
);
this
.
set
(
'
planOutput
'
,
planOutput
);
}
catch
(
err
)
{
this
.
set
(
'
planError
'
,
err
);
console
.
log
(
'
Uhoh
'
,
err
);
}
}).
drop
(),
submit
:
task
(
function
*
()
{}),
cancel
()
{
this
.
set
(
'
planOutput
'
,
null
);
this
.
set
(
'
planError
'
,
null
);
this
.
set
(
'
parseError
'
,
null
);
},
});
This diff is collapsed.
Click to expand it.
ui/app/models/job.js
+
46
-
0
View file @
da1e1797
...
...
@@ -4,6 +4,8 @@ import Model from 'ember-data/model';
import
attr
from
'
ember-data/attr
'
;
import
{
belongsTo
,
hasMany
}
from
'
ember-data/relationships
'
;
import
{
fragmentArray
}
from
'
ember-data-model-fragments/attributes
'
;
import
RSVP
from
'
rsvp
'
;
import
{
assert
}
from
'
@ember/debug
'
;
const
JOB_TYPES
=
[
'
service
'
,
'
batch
'
,
'
system
'
];
...
...
@@ -191,6 +193,41 @@ export default Model.extend({
return
this
.
store
.
adapterFor
(
'
job
'
).
stop
(
this
);
},
plan
()
{
assert
(
'
A job must be parsed before planned
'
,
this
.
get
(
'
_newDefinitionJSON
'
));
return
this
.
store
.
adapterFor
(
'
job
'
).
plan
(
this
);
},
parse
()
{
const
definition
=
this
.
get
(
'
_newDefinition
'
);
let
promise
;
try
{
// If the definition is already JSON then it doesn't need to be parsed.
const
json
=
JSON
.
parse
(
definition
);
this
.
set
(
'
_newDefinitionJSON
'
,
definition
);
this
.
setIDByPayload
(
json
);
promise
=
RSVP
.
Resolve
(
definition
);
}
catch
(
err
)
{
// If the definition is invalid JSON, assume it is HCL. If it is invalid
// in anyway, the parse endpoint will throw an error.
promise
=
this
.
store
.
adapterFor
(
'
job
'
)
.
parse
(
this
.
get
(
'
_newDefinition
'
))
.
then
(
response
=>
{
this
.
set
(
'
_newDefinitionJSON
'
,
response
);
this
.
setIDByPayload
(
response
);
});
}
return
promise
;
},
setIDByPayload
(
payload
)
{
this
.
set
(
'
plainId
'
,
payload
.
Name
);
this
.
set
(
'
id
'
,
JSON
.
stringify
([
payload
.
Name
,
payload
.
Namespace
||
'
default
'
]));
},
statusClass
:
computed
(
'
status
'
,
function
()
{
const
classMap
=
{
pending
:
'
is-pending
'
,
...
...
@@ -206,4 +243,13 @@ export default Model.extend({
// Lazily decode the base64 encoded payload
return
window
.
atob
(
this
.
get
(
'
payload
'
)
||
''
);
}),
// An arbitrary HCL or JSON string that is used by the serializer to plan
// and run this job. Used for both new job models and saved job models.
_newDefinition
:
attr
(
'
string
'
),
// The new definition may be HCL, in which case the API will need to parse the
// spec first. In order to preserve both the original HCL and the parsed response
// that will be submitted to the create job endpoint, another prop is necessary.
_newDefinitionJSON
:
attr
(
'
string
'
),
});
This diff is collapsed.
Click to expand it.
ui/app/routes/jobs/run.js
+
13
-
0
View file @
da1e1797
...
...
@@ -3,6 +3,7 @@ import { inject as service } from '@ember/service';
export
default
Route
.
extend
({
store
:
service
(),
system
:
service
(),
breadcrumbs
:
[
{
...
...
@@ -10,4 +11,16 @@ export default Route.extend({
args
:
[
'
jobs.run
'
],
},
],
model
()
{
return
this
.
get
(
'
store
'
).
createRecord
(
'
job
'
,
{
namespace
:
this
.
get
(
'
system.activeNamespace
'
),
});
},
resetController
(
controller
,
isExiting
)
{
if
(
isExiting
)
{
controller
.
get
(
'
model
'
).
deleteRecord
();
}
},
});
This diff is collapsed.
Click to expand it.
ui/app/styles/components/codemirror.scss
+
1
-
1
View file @
da1e1797
...
...
@@ -43,7 +43,7 @@ $dark-bright: lighten($dark, 15%);
}
span
.cm-comment
{
color
:
$grey
-light
;
color
:
$grey
;
}
span
.cm-string
,
...
...
This diff is collapsed.
Click to expand it.
ui/app/templates/jobs/run.hbs
+
51
-
24
View file @
da1e1797
<section
class=
"section"
>
<div
class=
"notification is-info"
>
<div
class=
"columns"
>
<div
class=
"column"
>
<h3
class=
"title is-4"
>
Run a Job
</h3>
<p>
Paste or author HCL or JSON to submit to your cluster. A plan will be requested before the job is submitted.
</p>
{{#if
(
eq
stage
"editor"
)
}}
<div
class=
"notification is-info"
>
<div
class=
"columns"
>
<div
class=
"column"
>
<h3
class=
"title is-4"
>
Run a Job
</h3>
<p>
Paste or author HCL or JSON to submit to your cluster. A plan will be requested before the job is submitted.
</p>
</div>
<div
class=
"column is-centered is-minimum"
>
<button
class=
"button is-info"
>
Okay
</button>
</div>
</div>
<div
class=
"column is-centered is-minimum"
>
<button
class=
"button is-info"
>
Okay
</button>
</div>
<div
class=
"boxed-section"
>
<div
class=
"boxed-section-head"
>
Job Definition
</div>
<div
class=
"boxed-section-body is-full-bleed"
>
{{
ivy-codemirror
value
=
(
or
model
.
_newDefinition
jobSpec
)
valueUpdated
=
(
action
(
mut
model
.
_newDefinition
))
options
=
(
hash
mode
=
"javascript"
theme
=
"hashi"
tabSize
=
2
lineNumbers
=
true
)
}}
</div>
</div>
<div
class=
"content is-associative"
>
<button
class=
"button is-primary
{{
if
plan
.
isRunning
"is-loading"
}}
"
onclick=
{{
perform
plan
}}
>
Plan
</button>
</div>
{{/if}}
{{#if
(
eq
stage
"plan"
)
}}
<div
class=
"notification is-info"
>
<div
class=
"columns"
>
<div
class=
"column"
>
<h3
class=
"title is-4"
>
Job Plan
</h3>
<p>
This is the impact running this job will have on your cluster.
</p>
</div>
<div
class=
"column is-centered is-minimum"
>
<button
class=
"button is-info"
>
Okay
</button>
</div>
</div>
</div>
</div>
<div
class=
"boxed-section"
>
<div
class=
"boxed-section-head"
>
Job Definition
<div
class=
"boxed-section"
>
<div
class=
"boxed-section-head"
>
Job Plan
</div>
<div
class=
"boxed-section-body is-dark"
>
{{
job-diff
diff
=
planOutput
.
Diff
}}
</div>
</div>
<div
class=
"boxed-section-body is-full-bleed"
>
{{
ivy-codemirror
value
=
jobSpec
options
=
(
hash
mode
=
"javascript"
theme
=
"hashi"
tabSize
=
2
lineNumbers
=
true
)
}}
<div
class=
"content is-associative"
>
<button
class=
"button is-primary
{{
if
submit
.
isRunning
"is-loading"
}}
"
onclick=
{{
perform
submit
}}
>
Submit
</button>
<button
class=
"button is-light"
onclick=
{{
action
cancel
}}
>
Cancel
</button>
</div>
</div>
<div
class=
"content is-associative"
>
<button
class=
"button is-primary"
>
Plan
</button>
</div>
{{/if}}
</section>
This diff is collapsed.
Click to expand it.
Write
Preview
Supports
Markdown
0%
Try again
or
attach a new file
.
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment
Menu
Projects
Groups
Snippets
Help