Permalink
Browse files

Add create-view, update-view, and fetch-view-config commands.

  • Loading branch information...
1 parent c34af84 commit bc9240ee7ed053afc40b38c5123e1e17ed94eff0 @cliffano committed Feb 18, 2014
Showing with 189 additions and 3 deletions.
  1. +1 −1 CHANGELOG.md
  2. +12 −0 README.md
  3. +31 −2 conf/commands.json
  4. +4 −0 lib/cli.js
  5. +45 −0 lib/cli/view.js
  6. +5 −0 lib/jenkins.js
  7. +55 −0 lib/jenkins/util.js
  8. +36 −0 lib/jenkins/view.js
View
@@ -1,5 +1,5 @@
### 0.2.4-pre
-*
+* Add create-view, update-view, and fetch-view-config commands
### 0.2.3
* Add enable and disable commands
View
@@ -91,6 +91,18 @@ Fetch the config.xml of an existing job:
nestor config <job>
+Create a new view with a specified config.xml:
+
+ nestor create-view <view> <path/to/config.xml>
+
+Update an existing view with a specified config.xml:
+
+ nestor update-view <view> <path/to/config.xml>
+
+Fetch the config.xml of an existing view:
+
+ nestor fetch-view-config <view>
+
View queued jobs:
nestor queue
View
@@ -75,7 +75,7 @@
]
},
"create": {
- "desc": "Create a new job with a specified config.xml",
+ "desc": "Create a new job with specified config.xml",
"args": [
{ "name": "job", "rules": [ "notEmpty" ] },
{ "name": "config", "rules": [ "notEmpty" ] }
@@ -85,7 +85,7 @@
]
},
"update": {
- "desc": "Update an existing job with a specified config.xml",
+ "desc": "Update an existing job with specified config.xml",
"args": [
{ "name": "job", "rules": [ "notEmpty" ] },
{ "name": "config", "rules": [ "notEmpty" ] }
@@ -122,6 +122,35 @@
"nestor config <job>"
]
},
+ "create-view": {
+ "desc": "Create a new view with specified config.xml",
+ "args": [
+ { "name": "view", "rules": [ "notEmpty" ] },
+ { "name": "config", "rules": [ "notEmpty" ] }
+ ],
+ "examples": [
+ "nestor create-view <view> <path/to/config.xml>"
+ ]
+ },
+ "update-view": {
+ "desc": "Update an existing view with specified config.xml",
+ "args": [
+ { "name": "view", "rules": [ "notEmpty" ] },
+ { "name": "config", "rules": [ "notEmpty" ] }
+ ],
+ "examples": [
+ "nestor update <job> <path/to/config.xml>"
+ ]
+ },
+ "fetch-view-config": {
+ "desc": "Fetch the config.xml of an existing view",
+ "args": [
+ { "name": "view", "rules": [ "notEmpty" ] }
+ ],
+ "examples": [
+ "nestor fetch-view-config <view>"
+ ]
+ },
"queue": {
"desc": "View queued jobs"
},
View
@@ -15,6 +15,7 @@ var _ = require('lodash'),
NinjaBlocks = require('./notifiers/ninjablocks'),
text = require('bagoftext'),
_url = require('url');
+var view = require('./cli/view');
function __exec(args, cb) {
// use url flag or JENKINS_URL environment variable if provided
@@ -334,6 +335,9 @@ function exec() {
copy: { action: _copy },
'delete': { action: _delete },
config: { action: _config },
+ 'create-view': { action: view.create(__exec) },
+ 'update-view': { action: view.update(__exec) },
+ 'fetch-view-config': { action: view.fetchConfig(__exec) },
queue: { action: _queue },
ver: { action: _version },
irc: { action: _irc },
View
@@ -0,0 +1,45 @@
+var cli = require('bagofcli');
+var fs = require('fs');
+var text = require('bagoftext');
+
+function create(cb) {
+ return function (name, configFile, args) {
+ function resultCb(result) {
+ console.log(text.__('View %s was created successfully'), name);
+ }
+ function jenkinsCb(jenkins) {
+ var config = fs.readFileSync(configFile).toString();
+ jenkins.createView(name, config, cli.exitCb(null, resultCb));
+ }
+ cb(args, jenkinsCb);
+ };
+}
+
+function update(cb) {
+ return function (name, configFile, args) {
+ function resultCb(result) {
+ console.log(text.__('View %s was updated successfully'), name);
+ }
+ function jenkinsCb(jenkins) {
+ var config = fs.readFileSync(configFile).toString();
+ jenkins.updateView(name, config, cli.exitCb(null, resultCb));
+ }
+ cb(args, jenkinsCb);
+ };
+}
+
+function fetchConfig(cb) {
+ return function (name, configFile, args) {
+ function resultCb(result) {
+ console.log(result);
+ }
+ function jenkinsCb(jenkins) {
+ jenkins.fetchViewConfig(name, cli.exitCb(null, resultCb));
+ }
+ cb(args, jenkinsCb);
+ };
+}
+
+exports.create = create;
+exports.update = update;
+exports.fetchConfig = fetchConfig;
View
@@ -11,6 +11,7 @@ var _ = require('lodash'),
request = require('request'),
text = require('bagoftext'),
xml2js = require('xml2js');
+var view = require('./jenkins/view');
text.initLocales(__dirname);
@@ -564,6 +565,10 @@ Jenkins.prototype.config = function (jobName, cb) {
req.request('get', this.url + '/job/' + jobName + '/config.xml', this.opts, cb);
};
+Jenkins.prototype.createView = view.create;
+Jenkins.prototype.updateView = view.update;
+Jenkins.prototype.fetchViewConfig = view.fetchConfig;
+
/**
* Retrieve jobs in the queue waiting for available executor or
* for a previously running build of the same job to finish.
View
@@ -0,0 +1,55 @@
+var text = require('bagoftext');
+
+/**
+ * Handle success simply by passing result's (response) body through to callback.
+ *
+ * @param {Object} result: result of the sent request
+ * @param {Function} cb: standard cb(err, result) callback
+ */
+function passThroughSuccess(result, cb) {
+ cb(null, result.body);
+}
+
+/**
+ * Parse HTML error page from Jenkins, pass the error message to the callback.
+ * This error is usually the response body of error 400.
+ *
+ * @param {Object} result: result of the sent request
+ * @param {Function} cb: standard cb(err, result) callback
+ */
+function htmlError(result, cb) {
+ var message = result.body
+ .match(/<h1>Error<\/h1>.+<\/p>/).toString()
+ .replace(/<h1>Error<\/h1>/, '')
+ .replace(/<\/?p>/g, '');
+ cb(new Error(message));
+}
+
+/**
+ * Create a 'job not found' error handler function.
+ *
+ * @param {String} name: the job name
+ * @return a handler function
+ */
+function jobNotFoundError(name) {
+ return function (result, cb) {
+ cb(new Error(text.__('Job %s does not exist', name)));
+ };
+}
+
+/**
+ * Create a 'view not found' error handler function.
+ *
+ * @param {String} name: the view name
+ * @return a handler function
+ */
+function viewNotFoundError(name) {
+ return function (result, cb) {
+ cb(new Error(text.__('View %s does not exist', name)));
+ };
+}
+
+exports.passThroughSuccess = passThroughSuccess;
+exports.htmlError = htmlError;
+exports.jobNotFoundError = jobNotFoundError;
+exports.viewNotFoundError = viewNotFoundError;
View
@@ -0,0 +1,36 @@
+var req = require('bagofrequest');
+var util = require('./util');
+
+function create(name, config, cb) {
+
+ this.opts.queryStrings = { name: name };
+ this.opts.headers = { 'content-type': 'application/xml' };
+ this.opts.body = config;
+
+ this.opts.handlers[200] = util.passThroughSuccess;
+ this.opts.handlers[400] = util.htmlError;
+
+ req.request('post', this.url + '/createView', this.opts, cb);
+}
+
+function update(name, config, cb) {
+
+ this.opts.body = config;
+
+ this.opts.handlers[200] = util.passThroughSuccess;
+ this.opts.handlers[404] = util.viewNotFoundError(name);
+
+ req.request('post', this.url + '/view/' + name + '/config.xml', this.opts, cb);
+}
+
+function fetchConfig(name, cb) {
+
+ this.opts.handlers[200] = util.passThroughSuccess;
+ this.opts.handlers[404] = util.viewNotFoundError(name);
+
+ req.request('get', this.url + '/view/' + name + '/config.xml', this.opts, cb);
+}
+
+exports.create = create;
+exports.update = update;
+exports.fetchConfig = fetchConfig;

0 comments on commit bc9240e

Please sign in to comment.