mirror of
https://github.com/semaphoreui/semaphore.git
synced 2025-01-20 15:29:28 +01:00
sample Projects UI, cleanup vendor/
- Update dependencies - Remove lib/ - Dashboard
This commit is contained in:
parent
e212c88bd2
commit
121567fa03
@ -13,17 +13,4 @@ mongodb:
|
||||
volumes:
|
||||
- /tmp/mongodb:/data/db
|
||||
expose:
|
||||
- 27017
|
||||
|
||||
semaphore:
|
||||
image: castawaylabs/semaphore:latest
|
||||
environment:
|
||||
MONGODB_URL: mongodb://mongodb/semaphore
|
||||
REDIS_HOST: redis
|
||||
expose:
|
||||
- 80
|
||||
ports:
|
||||
- 8088:80
|
||||
links:
|
||||
- redis:redis
|
||||
- mongodb:mongodb
|
||||
- 27017
|
125
lib/app.js
125
lib/app.js
@ -1,125 +0,0 @@
|
||||
var config = require('./config'),
|
||||
express = require('express'),
|
||||
routes = require('./routes'),
|
||||
http = require('http'),
|
||||
path = require('path'),
|
||||
mongoose = require('mongoose'),
|
||||
util = require('./util'),
|
||||
session = require('express-session'),
|
||||
RedisStore = require('connect-redis')(session),
|
||||
passport = require('passport'),
|
||||
auth = require('./auth'),
|
||||
bugsnag = require('bugsnag'),
|
||||
socketPassport = require('passport.socketio'),
|
||||
bodyParser = require('body-parser'),
|
||||
logtrail = require('logtrail');
|
||||
|
||||
var app = exports.app = express();
|
||||
|
||||
logtrail.configure({
|
||||
timestamps: {
|
||||
enabled: false
|
||||
},
|
||||
stacktrace: true,
|
||||
basedir: __dirname
|
||||
});
|
||||
console.log = logtrail.log.bind(logtrail);
|
||||
|
||||
var releaseStage = config.production ? "production" : "development";
|
||||
|
||||
bugsnag.register(config.credentials.bugsnag_key, {
|
||||
notifyReleaseStages: ["production"],
|
||||
releaseStage: releaseStage
|
||||
});
|
||||
|
||||
mongoose.connect(config.credentials.db, config.credentials.db_options);
|
||||
|
||||
var sessionStore = new RedisStore({
|
||||
host: config.credentials.redis_host,
|
||||
port: config.credentials.redis_port,
|
||||
ttl: 604800000,
|
||||
pass: config.credentials.redis_key
|
||||
});
|
||||
|
||||
var db = mongoose.connection
|
||||
db.on('error', console.error.bind(console, 'Mongodb Connection Error:'));
|
||||
db.once('open', function callback () {
|
||||
if (!config.is_testing) console.log("Mongodb connection established")
|
||||
});
|
||||
|
||||
// all environments
|
||||
app.enable('trust proxy');
|
||||
app.set('port', config.port || 3000); // Port
|
||||
app.set('views', __dirname + '/views');
|
||||
app.set('view engine', 'jade'); // Templating engine
|
||||
app.set('app version', config.version); // App version
|
||||
app.set('x-powered-by', false);
|
||||
|
||||
app.set('view cache', config.production);
|
||||
|
||||
config.configure(app);
|
||||
|
||||
app.use(function(req, res, next) {
|
||||
res.set('x-frame-options', 'SAMEORIGIN');
|
||||
res.set('x-xss-protection', '1; mode=block');
|
||||
next();
|
||||
});
|
||||
|
||||
var publicFolder = path.join(__dirname, '..', 'public');
|
||||
app.use(require('less-middleware')(publicFolder));
|
||||
app.use(require('serve-static')(publicFolder));
|
||||
app.use(require('morgan')(config.production ? 'combined' : 'dev'));
|
||||
|
||||
app.use(bugsnag.requestHandler);
|
||||
app.use(bodyParser.urlencoded({
|
||||
extended: true
|
||||
}));
|
||||
app.use(bodyParser.json());
|
||||
app.use(require('cookie-parser')());
|
||||
app.use(session({
|
||||
secret: "#semaphore",
|
||||
name: 'semaphore',
|
||||
store: sessionStore,
|
||||
proxy: true,
|
||||
saveUninitialized: false,
|
||||
resave: false,
|
||||
cookie: {
|
||||
secure: config.credentials.is_ssl,
|
||||
maxAge: 604800000
|
||||
}
|
||||
}));
|
||||
|
||||
app.use(passport.initialize());
|
||||
app.use(passport.session());
|
||||
|
||||
// Custom middleware
|
||||
app.use(function(req, res, next) {
|
||||
res.locals.user = req.user;
|
||||
res.locals.loggedIn = res.locals.user != null;
|
||||
|
||||
next();
|
||||
});
|
||||
|
||||
// routes
|
||||
routes.router(app);
|
||||
|
||||
app.use(bugsnag.errorHandler);
|
||||
|
||||
var server = http.createServer(app)
|
||||
server.listen(app.get('port'), function(){
|
||||
console.log('Semaphore listening on port ' + app.get('port'));
|
||||
});
|
||||
exports.io = io = require('socket.io').listen(server)
|
||||
|
||||
config.init();
|
||||
|
||||
io.use(socketPassport.authorize({
|
||||
cookieParser: require('cookie-parser'),
|
||||
secret: "#semaphore",
|
||||
key: 'semaphore',
|
||||
store: sessionStore,
|
||||
passport: passport,
|
||||
fail: function(data, message, error, accept) {
|
||||
accept(false);
|
||||
}
|
||||
}))
|
13
lib/auth.js
13
lib/auth.js
@ -1,13 +0,0 @@
|
||||
var passport = require('passport')
|
||||
, models = require('./models')
|
||||
, bugsnag = require('bugsnag')
|
||||
|
||||
passport.serializeUser(function(user, done) {
|
||||
done(null, user._id);
|
||||
});
|
||||
|
||||
passport.deserializeUser(function(id, done) {
|
||||
models.User.findOne({
|
||||
_id: id
|
||||
}, done);
|
||||
})
|
@ -1,86 +0,0 @@
|
||||
var fs = require('fs'),
|
||||
env = process.env;
|
||||
|
||||
try {
|
||||
var credentials = require('./credentials.json');
|
||||
} catch (e) {
|
||||
if (!(process.env.MONGODB_URL && process.env.REDIS_HOST)) {
|
||||
console.log("\nNo credentials.json File or env variables!\n");
|
||||
process.exit(1);
|
||||
} else {
|
||||
credentials = require('./credentials.default.json');
|
||||
}
|
||||
}
|
||||
|
||||
exports.credentials = credentials;
|
||||
|
||||
['redis_port', 'redis_host', 'redis_key', 'bugsnag_key', 'port'].forEach(function (key) {
|
||||
if (env[key.toUpperCase()]) {
|
||||
exports.credentials[key] = env[key.toUpperCase()];
|
||||
}
|
||||
});
|
||||
|
||||
if (env.SMTP_USER) {
|
||||
exports.credentials.smtp.user = env.SMTP_USER;
|
||||
}
|
||||
if (env.SMTP_PASS) {
|
||||
exports.credentials.smtp.pass = env.SMTP_PASS;
|
||||
}
|
||||
if (env.MONGODB_URL) {
|
||||
exports.credentials.db = env.MONGODB_URL;
|
||||
}
|
||||
|
||||
exports.version = require('../package.json').version;
|
||||
exports.hash = 'dirty';
|
||||
exports.production = process.env.NODE_ENV == "production";
|
||||
exports.port = process.env.PORT || credentials.port;
|
||||
exports.path = __dirname;
|
||||
|
||||
if (process.platform.match(/^win/) == null) {
|
||||
try {
|
||||
var spawn_process = require('child_process').spawn
|
||||
var readHash = spawn_process('git', ['rev-parse', '--short', 'HEAD']);
|
||||
readHash.stdout.on('data', function (data) {
|
||||
exports.hash = data.toString().trim();
|
||||
require('./app').app.locals.versionHash = exports.hash;
|
||||
})
|
||||
} catch (e) {
|
||||
console.log("\n~= Unable to obtain git commit hash =~\n")
|
||||
}
|
||||
}
|
||||
|
||||
exports.configure = function (app) {
|
||||
app.locals.pretty = exports.production // Pretty HTML outside production mode
|
||||
app.locals.version = exports.version;
|
||||
app.locals.versionHash = exports.hash;
|
||||
app.locals.production = exports.production;
|
||||
app.locals.use_analytics = credentials.use_analytics;
|
||||
}
|
||||
|
||||
exports.init = function () {
|
||||
var models = require('./models');
|
||||
|
||||
models.User.findOne({
|
||||
}).exec(function (err, user) {
|
||||
if (!user) {
|
||||
console.log("Creating Admin user admin@semaphore.local!");
|
||||
|
||||
var admin = new models.User({
|
||||
email: 'admin@semaphore.local',
|
||||
username: 'semaphore',
|
||||
name: 'Administrator'
|
||||
});
|
||||
models.User.hashPassword('CastawayLabs', function (hash) {
|
||||
admin.password = hash;
|
||||
|
||||
admin.save();
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
models.Task.remove({
|
||||
status: 'Running'
|
||||
}, function (err) {
|
||||
if (err) throw err;
|
||||
});
|
||||
}
|
@ -1,21 +0,0 @@
|
||||
{
|
||||
"redis_port": 6379,
|
||||
"redis_host": "127.0.0.1",
|
||||
"redis_key": "",
|
||||
"use_analytics": false,
|
||||
"is_ssl": false,
|
||||
"bugsnag_key": "",
|
||||
"smtp": {
|
||||
"user": "",
|
||||
"pass": ""
|
||||
},
|
||||
"db": "mongodb://127.0.0.1/semaphore",
|
||||
"db_options": {
|
||||
"auto_reconnect": true,
|
||||
"native_parser": true,
|
||||
"server": {
|
||||
"auto_reconnect": true
|
||||
}
|
||||
},
|
||||
"port": 80
|
||||
}
|
@ -1,23 +0,0 @@
|
||||
var mongoose = require('mongoose')
|
||||
var ObjectId = mongoose.Schema.ObjectId;
|
||||
|
||||
var schema = mongoose.Schema({
|
||||
created: {
|
||||
type: Date,
|
||||
default: Date.now
|
||||
},
|
||||
credential_type: {
|
||||
type: String,
|
||||
enum: ['ssh', 'vault', 'git']
|
||||
},
|
||||
name: String,
|
||||
password: String,
|
||||
private_key: String,
|
||||
public_key: String
|
||||
});
|
||||
|
||||
schema.index({
|
||||
name: 1
|
||||
});
|
||||
|
||||
module.exports = mongoose.model('Credential', schema);
|
@ -1,26 +0,0 @@
|
||||
var mongoose = require('mongoose')
|
||||
var ObjectId = mongoose.Schema.ObjectId;
|
||||
|
||||
var schema = mongoose.Schema({
|
||||
created: {
|
||||
type: Date,
|
||||
default: Date.now
|
||||
},
|
||||
name: String,
|
||||
hostname: String,
|
||||
group: {
|
||||
type: ObjectId,
|
||||
ref: 'HostGroup'
|
||||
},
|
||||
playbook: {
|
||||
type: ObjectId,
|
||||
ref: 'Playbook'
|
||||
}
|
||||
});
|
||||
|
||||
schema.index({
|
||||
name: 1,
|
||||
hostname: 1
|
||||
});
|
||||
|
||||
module.exports = mongoose.model('Host', schema);
|
@ -1,20 +0,0 @@
|
||||
var mongoose = require('mongoose')
|
||||
var ObjectId = mongoose.Schema.ObjectId;
|
||||
|
||||
var schema = mongoose.Schema({
|
||||
created: {
|
||||
type: Date,
|
||||
default: Date.now
|
||||
},
|
||||
name: String,
|
||||
playbook: {
|
||||
type: ObjectId,
|
||||
ref: 'Playbook'
|
||||
}
|
||||
});
|
||||
|
||||
schema.index({
|
||||
name: 1
|
||||
});
|
||||
|
||||
module.exports = mongoose.model('HostGroup', schema);
|
@ -1,25 +0,0 @@
|
||||
var mongoose = require('mongoose')
|
||||
var ObjectId = mongoose.Schema.ObjectId;
|
||||
|
||||
var schema = mongoose.Schema({
|
||||
created: {
|
||||
type: Date,
|
||||
default: Date.now
|
||||
},
|
||||
credential_type: {
|
||||
type: String,
|
||||
enum: ['ssh', 'vault', 'git']
|
||||
},
|
||||
name: String,
|
||||
// vault password
|
||||
password: String,
|
||||
// private keys for ssh/git
|
||||
private_key: String,
|
||||
public_key: String
|
||||
});
|
||||
|
||||
schema.index({
|
||||
name: 1
|
||||
});
|
||||
|
||||
module.exports = mongoose.model('Identity', schema);
|
@ -1,22 +0,0 @@
|
||||
var mongoose = require('mongoose')
|
||||
var ObjectId = mongoose.Schema.ObjectId;
|
||||
|
||||
var schema = mongoose.Schema({
|
||||
created: {
|
||||
type: Date,
|
||||
default: Date.now
|
||||
},
|
||||
playbook: {
|
||||
type: ObjectId,
|
||||
ref: 'Playbook'
|
||||
},
|
||||
name: String,
|
||||
play_file: String, //x.yml
|
||||
use_vault: Boolean
|
||||
});
|
||||
|
||||
schema.index({
|
||||
name: 1
|
||||
});
|
||||
|
||||
module.exports = mongoose.model('Job', schema);
|
@ -1,22 +0,0 @@
|
||||
var mongoose = require('mongoose')
|
||||
var ObjectId = mongoose.Schema.ObjectId;
|
||||
|
||||
var schema = mongoose.Schema({
|
||||
created: {
|
||||
type: Date,
|
||||
default: Date.now
|
||||
},
|
||||
name: String,
|
||||
location: String, // Git URL
|
||||
vault_password: String,
|
||||
identity: {
|
||||
type: ObjectId,
|
||||
ref: 'Identity'
|
||||
}
|
||||
});
|
||||
|
||||
schema.index({
|
||||
name: 1
|
||||
});
|
||||
|
||||
module.exports = mongoose.model('Playbook', schema);
|
@ -1,28 +0,0 @@
|
||||
var mongoose = require('mongoose')
|
||||
var ObjectId = mongoose.Schema.ObjectId;
|
||||
|
||||
var schema = mongoose.Schema({
|
||||
created: {
|
||||
type: Date,
|
||||
default: Date.now
|
||||
},
|
||||
job: {
|
||||
type: ObjectId,
|
||||
ref: 'Job'
|
||||
},
|
||||
playbook: {
|
||||
type: ObjectId,
|
||||
ref: 'Playbook'
|
||||
},
|
||||
output: String,
|
||||
status: {
|
||||
type: String,
|
||||
enum: ['Completed', 'Failed', 'Running', 'Queued']
|
||||
}
|
||||
});
|
||||
|
||||
schema.index({
|
||||
status: 1
|
||||
});
|
||||
|
||||
module.exports = mongoose.model('Task', schema);
|
@ -1,34 +0,0 @@
|
||||
var bcrypt = require('bcrypt')
|
||||
|
||||
var mongoose = require('mongoose')
|
||||
var ObjectId = mongoose.Schema.ObjectId;
|
||||
|
||||
var schema = mongoose.Schema({
|
||||
created: {
|
||||
type: Date,
|
||||
default: Date.now
|
||||
},
|
||||
username: String,
|
||||
name: String,
|
||||
email: String,
|
||||
password: String
|
||||
});
|
||||
|
||||
schema.index({
|
||||
email: 1
|
||||
});
|
||||
|
||||
schema.statics.hashPassword = function(password, cb) {
|
||||
bcrypt.hash(password, 10, function(err, hash) {
|
||||
cb(hash);
|
||||
});
|
||||
}
|
||||
|
||||
schema.methods.comparePassword = function (password, cb) {
|
||||
bcrypt.compare(password, this.password, function(err, res) {
|
||||
// res is boolean
|
||||
cb(res);
|
||||
})
|
||||
}
|
||||
|
||||
module.exports = mongoose.model('User', schema);
|
@ -1,13 +0,0 @@
|
||||
var manifest = [
|
||||
'Host',
|
||||
'HostGroup',
|
||||
'Job',
|
||||
'Identity',
|
||||
'Playbook',
|
||||
'Task',
|
||||
'User'
|
||||
];
|
||||
|
||||
manifest.forEach(function (model) {
|
||||
module.exports[model] = require('./'+model);
|
||||
});
|
@ -1,171 +0,0 @@
|
||||
var passport = require('passport')
|
||||
, models = require('../models')
|
||||
, validator = require('validator')
|
||||
, util = require('../util')
|
||||
, config = require('../config')
|
||||
, async = require('async')
|
||||
, express = require('express')
|
||||
, mongoose = require('mongoose')
|
||||
|
||||
exports.unauthorized = function (app, template) {
|
||||
// Unrestricted -- non-authorized people can access!
|
||||
template([
|
||||
'login'
|
||||
], {
|
||||
prefix: 'auth'
|
||||
});
|
||||
|
||||
var auth = express.Router();
|
||||
|
||||
auth.post('/password', doLogin)
|
||||
.get('/loggedin', isLoggedIn)
|
||||
.get('/logout', doLogout)
|
||||
|
||||
app.use('/auth', auth);
|
||||
}
|
||||
|
||||
exports.router = function (app) {
|
||||
// Restricted -- only authorized people can access!
|
||||
app.post('/auth/register', doRegister)
|
||||
}
|
||||
|
||||
function isLoggedIn (req, res) {
|
||||
res.send({
|
||||
hasSession: req.user != null,
|
||||
isLoggedIn: res.locals.loggedIn
|
||||
});
|
||||
}
|
||||
|
||||
function doLogin (req, res) {
|
||||
var auth = req.body.auth;
|
||||
var isValid = true;
|
||||
|
||||
if (!validator.isLength(auth, 4)) {
|
||||
isValid = false;
|
||||
}
|
||||
|
||||
// validate password
|
||||
if (!validator.isLength(req.body.password, 6)) {
|
||||
isValid = false;
|
||||
}
|
||||
|
||||
if (!isValid) {
|
||||
return authCallback(false, null, req, res);
|
||||
}
|
||||
|
||||
var query = {
|
||||
email: auth.toLowerCase()
|
||||
};
|
||||
|
||||
models.User.findOne(query, function(err, user) {
|
||||
if (err) {
|
||||
throw err;
|
||||
}
|
||||
|
||||
if (user == null) {
|
||||
return authCallback(false, null, req, res);
|
||||
}
|
||||
|
||||
user.comparePassword(req.body.password, function (matches) {
|
||||
authCallback(matches, user, req, res);
|
||||
});
|
||||
})
|
||||
}
|
||||
|
||||
function authCallback (isValid, user, req, res) {
|
||||
if (!isValid) {
|
||||
res.send(400, {
|
||||
message: "Nope. Incorrect Credentials!"
|
||||
});
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
req.login(user, function(err) {
|
||||
if (err) throw err;
|
||||
|
||||
res.send(201)
|
||||
})
|
||||
}
|
||||
|
||||
function doRegister (req, res) {
|
||||
var errs = {
|
||||
name: false,
|
||||
email: false,
|
||||
password: false,
|
||||
username: false
|
||||
};
|
||||
|
||||
var userObject = req.body.user;
|
||||
if (!(userObject && typeof userObject === 'object')) {
|
||||
return res.send(400, {
|
||||
message: 'Invalid Request'
|
||||
});
|
||||
}
|
||||
|
||||
var email = userObject.email;
|
||||
if (email) {
|
||||
email = email.toLowerCase();
|
||||
}
|
||||
var password = userObject.password;
|
||||
var username = userObject.username;
|
||||
var name = userObject.name;
|
||||
|
||||
errs.email = !validator.isEmail(email);
|
||||
errs.username = !validator.isLength(username, 3, 15);
|
||||
errs.name = !validator.isLength(name, 4, 50);
|
||||
|
||||
if (!(username && username.match(/^[a-zA-Z0-9_-]{3,15}$/) && validator.isAscii(username))) {
|
||||
// Errornous username
|
||||
errs.username = true;
|
||||
}
|
||||
|
||||
// validate password
|
||||
errs.password = !validator.isLength(password, 8, 100);
|
||||
|
||||
if (!(errs.username == false && errs.password == false && errs.name == false && errs.email == false)) {
|
||||
res.send(400, {
|
||||
fields: errs,
|
||||
message: ''
|
||||
});
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
// Register
|
||||
var user = new models.User({
|
||||
email: email,
|
||||
username: username,
|
||||
name: name
|
||||
});
|
||||
|
||||
models.User.hashPassword(password, function (hash) {
|
||||
user.password = hash;
|
||||
|
||||
user.save();
|
||||
|
||||
// log in now
|
||||
req.login(user, function(err) {
|
||||
if (err) throw err;
|
||||
|
||||
res.send({
|
||||
message: "Registration Successful",
|
||||
user_id: user._id
|
||||
});
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
function doLogout (req, res) {
|
||||
req.logout();
|
||||
req.session.destroy();
|
||||
|
||||
res.format({
|
||||
json: function() {
|
||||
res.send(201)
|
||||
},
|
||||
html: function() {
|
||||
res.redirect('/')
|
||||
}
|
||||
})
|
||||
}
|
@ -1,116 +0,0 @@
|
||||
var models = require('../../models')
|
||||
var mongoose = require('mongoose')
|
||||
var express = require('express')
|
||||
|
||||
exports.unauthorized = function (app, template) {
|
||||
template([
|
||||
'view'
|
||||
], {
|
||||
prefix: 'job'
|
||||
});
|
||||
}
|
||||
|
||||
exports.httpRouter = function (app) {
|
||||
}
|
||||
|
||||
exports.router = function (app) {
|
||||
app.param('hostgroup_id', getHostGroup)
|
||||
app.param('host_id', getHost)
|
||||
|
||||
var job = express.Router();
|
||||
|
||||
job.get('/', viewHostGroup)
|
||||
.delete('/', removeHostGroup)
|
||||
|
||||
.get('/hosts', getHosts)
|
||||
.post('/hosts', addHost)
|
||||
|
||||
app.use('/playbook/:playbook_id/hostgroup/:hostgroup_id', job);
|
||||
|
||||
var host = express.Router();
|
||||
host.get('/', viewHost)
|
||||
.delete('/', removeHost)
|
||||
|
||||
app.use('/playbook/:playbook_id/hostgroup/:hostgroup_id/host/:host_id', host);
|
||||
}
|
||||
|
||||
/*
|
||||
* hostgroup -> hosts
|
||||
*/
|
||||
|
||||
function getHosts (req, res) {
|
||||
models.Host.find({
|
||||
group: req.hostgroup._id
|
||||
}).sort('-created').exec(function (err, hosts) {
|
||||
res.send(hosts)
|
||||
})
|
||||
}
|
||||
|
||||
function addHost (req, res) {
|
||||
var host = new models.Host({
|
||||
group: req.hostgroup._id,
|
||||
playbook: req.playbook._id,
|
||||
name: req.body.name,
|
||||
hostname: req.body.hostname
|
||||
});
|
||||
|
||||
host.save(function () {
|
||||
res.send(host);
|
||||
});
|
||||
}
|
||||
|
||||
/*
|
||||
* hostgroup (singular)
|
||||
*/
|
||||
|
||||
function getHostGroup (req, res, next, id) {
|
||||
models.HostGroup.findOne({
|
||||
_id: id
|
||||
}).exec(function (err, hostgroup) {
|
||||
if (err || !hostgroup) {
|
||||
return res.send(404);
|
||||
}
|
||||
|
||||
req.hostgroup = hostgroup;
|
||||
next();
|
||||
});
|
||||
}
|
||||
|
||||
function viewHostGroup (req, res) {
|
||||
res.send(req.hostgroup);
|
||||
}
|
||||
|
||||
function removeHostGroup (req, res) {
|
||||
req.hostgroup.remove(function (err) {
|
||||
res.send(201);
|
||||
})
|
||||
}
|
||||
|
||||
/*
|
||||
* hostgroup -> host (singular)
|
||||
*/
|
||||
|
||||
function getHost (req, res, next, id) {
|
||||
models.Host.findOne({
|
||||
_id: id
|
||||
}).exec(function (err, host) {
|
||||
console.log(host);
|
||||
if (err || !host) {
|
||||
return res.send(404);
|
||||
}
|
||||
|
||||
req.group_host = host;
|
||||
next();
|
||||
});
|
||||
}
|
||||
|
||||
function viewHost (req, res) {
|
||||
res.send(req.group_host);
|
||||
}
|
||||
|
||||
function removeHost (req, res) {
|
||||
console.log(req.group_host)
|
||||
req.group_host.remove(function (err) {
|
||||
res.send(201);
|
||||
})
|
||||
}
|
@ -1,44 +0,0 @@
|
||||
var models = require('../../models')
|
||||
var mongoose = require('mongoose')
|
||||
|
||||
var host = require('./host')
|
||||
|
||||
exports.unauthorized = function (app, template) {
|
||||
template([
|
||||
'hosts'
|
||||
], {
|
||||
prefix: 'host'
|
||||
});
|
||||
|
||||
host.unauthorized(app, template);
|
||||
}
|
||||
|
||||
exports.httpRouter = function (app) {
|
||||
host.httpRouter(app);
|
||||
}
|
||||
|
||||
exports.router = function (app) {
|
||||
app.get('/playbook/:playbook_id/hostgroups', get)
|
||||
.post('/playbook/:playbook_id/hostgroups', add)
|
||||
|
||||
host.router(app);
|
||||
}
|
||||
|
||||
function get (req, res) {
|
||||
models.HostGroup.find({
|
||||
playbook: req.playbook._id
|
||||
}).sort('-created').exec(function (err, hosts) {
|
||||
res.send(hosts)
|
||||
})
|
||||
}
|
||||
|
||||
function add (req, res) {
|
||||
var hostgroup = new models.HostGroup({
|
||||
playbook: req.playbook._id,
|
||||
name: req.body.name
|
||||
});
|
||||
|
||||
hostgroup.save(function () {
|
||||
res.send(hostgroup);
|
||||
});
|
||||
}
|
@ -1,52 +0,0 @@
|
||||
var models = require('../../models')
|
||||
var mongoose = require('mongoose')
|
||||
|
||||
var identity = require('./identity')
|
||||
|
||||
var validator = require('validator')
|
||||
|
||||
exports.unauthorized = function (app, template) {
|
||||
template([
|
||||
'add',
|
||||
'list'
|
||||
], {
|
||||
prefix: 'identity'
|
||||
});
|
||||
|
||||
identity.unauthorized(app, template);
|
||||
}
|
||||
|
||||
exports.httpRouter = function (app) {
|
||||
identity.httpRouter(app);
|
||||
}
|
||||
|
||||
exports.router = function (app) {
|
||||
app.get('/identities', get)
|
||||
.post('/identities', add)
|
||||
|
||||
identity.router(app);
|
||||
}
|
||||
|
||||
function get (req, res) {
|
||||
models.Identity.find({
|
||||
}).sort('-created').select('-public_key -private_key -password').exec(function (err, identities) {
|
||||
res.send(identities)
|
||||
})
|
||||
}
|
||||
|
||||
function add (req, res) {
|
||||
if (!validator.isLength(req.body.name, 1)) {
|
||||
return res.send(400);
|
||||
}
|
||||
|
||||
var identity = new models.Identity({
|
||||
name: req.body.name,
|
||||
password: req.body.password,
|
||||
private_key: req.body.private_key,
|
||||
public_key: req.body.public_key
|
||||
});
|
||||
|
||||
identity.save(function () {
|
||||
res.send(identity);
|
||||
});
|
||||
}
|
@ -1,56 +0,0 @@
|
||||
var models = require('../../models')
|
||||
var mongoose = require('mongoose')
|
||||
var express = require('express')
|
||||
|
||||
exports.unauthorized = function (app, template) {
|
||||
template([
|
||||
'view'
|
||||
], {
|
||||
prefix: 'identity'
|
||||
});
|
||||
}
|
||||
|
||||
exports.httpRouter = function (app) {
|
||||
}
|
||||
|
||||
exports.router = function (app) {
|
||||
var identity = express.Router();
|
||||
|
||||
identity.get('/', view)
|
||||
.put('/', save)
|
||||
.delete('/', remove)
|
||||
|
||||
app.param('identity_id', get)
|
||||
app.use('/identity/:identity_id', identity);
|
||||
}
|
||||
|
||||
function get (req, res, next, id) {
|
||||
models.Identity.findOne({
|
||||
_id: id
|
||||
}).select('-private_key -password').exec(function (err, identity) {
|
||||
if (err || !identity) {
|
||||
return res.send(404);
|
||||
}
|
||||
|
||||
req.identity = identity;
|
||||
next();
|
||||
});
|
||||
}
|
||||
|
||||
function view (req, res) {
|
||||
res.send(req.identity);
|
||||
}
|
||||
|
||||
function save (req, res) {
|
||||
req.identity.name = req.body.name;
|
||||
req.identity.password = req.body.password;
|
||||
|
||||
req.identity.save();
|
||||
res.send(201);
|
||||
}
|
||||
|
||||
function remove (req, res) {
|
||||
req.identity.remove(function (err) {
|
||||
res.send(201);
|
||||
})
|
||||
}
|
@ -1,66 +0,0 @@
|
||||
var util = require('../util')
|
||||
auth = require('./auth'),
|
||||
playbooks = require('./playbook/playbooks'),
|
||||
profile = require('./profile'),
|
||||
identities = require('./identity/identities'),
|
||||
jobs = require('./job/jobs'),
|
||||
hosts = require('./host/hosts'),
|
||||
tasks = require('./task/tasks'),
|
||||
users = require('./user/users')
|
||||
|
||||
exports.router = function(app) {
|
||||
var templates = require('../templates')(app);
|
||||
templates.route([
|
||||
auth,
|
||||
playbooks,
|
||||
identities,
|
||||
jobs,
|
||||
hosts,
|
||||
tasks,
|
||||
users
|
||||
]);
|
||||
|
||||
templates.add('homepage')
|
||||
templates.add('abstract')
|
||||
templates.setup();
|
||||
|
||||
app.get('/', layout);
|
||||
app.all('*', util.authorized);
|
||||
|
||||
// Handle HTTP reqs
|
||||
playbooks.httpRouter(app);
|
||||
identities.httpRouter(app);
|
||||
jobs.httpRouter(app);
|
||||
hosts.httpRouter(app);
|
||||
tasks.httpRouter(app);
|
||||
users.httpRouter(app);
|
||||
|
||||
// only json beyond this point
|
||||
app.get('*', function(req, res, next) {
|
||||
res.format({
|
||||
json: function() {
|
||||
next()
|
||||
},
|
||||
html: function() {
|
||||
layout(req, res);
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
auth.router(app);
|
||||
playbooks.router(app);
|
||||
profile.router(app);
|
||||
identities.router(app);
|
||||
jobs.router(app);
|
||||
hosts.router(app);
|
||||
tasks.router(app);
|
||||
users.router(app);
|
||||
}
|
||||
|
||||
function layout (req, res) {
|
||||
if (res.locals.loggedIn) {
|
||||
res.render('layout')
|
||||
} else {
|
||||
res.render('auth');
|
||||
}
|
||||
}
|
@ -1,47 +0,0 @@
|
||||
var models = require('../../models')
|
||||
var mongoose = require('mongoose')
|
||||
var express = require('express')
|
||||
|
||||
exports.unauthorized = function (app, template) {
|
||||
template([
|
||||
'view'
|
||||
], {
|
||||
prefix: 'job'
|
||||
});
|
||||
}
|
||||
|
||||
exports.httpRouter = function (app) {
|
||||
}
|
||||
|
||||
exports.router = function (app) {
|
||||
var job = express.Router();
|
||||
|
||||
job.get('/', view)
|
||||
.delete('/', remove)
|
||||
|
||||
app.param('job_id', get)
|
||||
app.use('/playbook/:playbook_id/job/:job_id', job);
|
||||
}
|
||||
|
||||
function get (req, res, next, id) {
|
||||
models.Job.findOne({
|
||||
_id: id
|
||||
}).exec(function (err, job) {
|
||||
if (err || !job) {
|
||||
return res.send(404);
|
||||
}
|
||||
|
||||
req.job = job;
|
||||
next();
|
||||
});
|
||||
}
|
||||
|
||||
function view (req, res) {
|
||||
res.send(req.job);
|
||||
}
|
||||
|
||||
function remove (req, res) {
|
||||
req.job.remove(function (err) {
|
||||
res.send(201);
|
||||
})
|
||||
}
|
@ -1,46 +0,0 @@
|
||||
var models = require('../../models')
|
||||
var mongoose = require('mongoose')
|
||||
|
||||
var job = require('./job')
|
||||
|
||||
exports.unauthorized = function (app, template) {
|
||||
template([
|
||||
'jobs'
|
||||
], {
|
||||
prefix: 'job'
|
||||
});
|
||||
|
||||
job.unauthorized(app, template);
|
||||
}
|
||||
|
||||
exports.httpRouter = function (app) {
|
||||
job.httpRouter(app);
|
||||
}
|
||||
|
||||
exports.router = function (app) {
|
||||
app.get('/playbook/:playbook_id/jobs', get)
|
||||
.post('/playbook/:playbook_id/jobs', add)
|
||||
|
||||
job.router(app);
|
||||
}
|
||||
|
||||
function get (req, res) {
|
||||
models.Job.find({
|
||||
playbook: req.playbook._id
|
||||
}).sort('-created').exec(function (err, jobs) {
|
||||
res.send(jobs)
|
||||
})
|
||||
}
|
||||
|
||||
function add (req, res) {
|
||||
var job = new models.Job({
|
||||
playbook: req.playbook._id,
|
||||
name: req.body.name,
|
||||
play_file: req.body.play_file,
|
||||
use_vault: req.body.use_vault
|
||||
})
|
||||
|
||||
job.save(function () {
|
||||
res.send(job);
|
||||
});
|
||||
}
|
@ -1,69 +0,0 @@
|
||||
var models = require('../../models')
|
||||
var mongoose = require('mongoose')
|
||||
var express = require('express')
|
||||
|
||||
exports.unauthorized = function (app, template) {
|
||||
template([
|
||||
'tasks',
|
||||
'jobs',
|
||||
'hosts',
|
||||
'view'
|
||||
], {
|
||||
prefix: 'playbook'
|
||||
});
|
||||
}
|
||||
|
||||
exports.httpRouter = function (app) {
|
||||
}
|
||||
|
||||
exports.router = function (app) {
|
||||
var playbook = express.Router();
|
||||
|
||||
playbook.get('/', view)
|
||||
.put('/', save)
|
||||
.delete('/', remove)
|
||||
|
||||
app.param('playbook_id', getPlaybook)
|
||||
app.use('/playbook/:playbook_id', playbook);
|
||||
}
|
||||
|
||||
function getPlaybook (req, res, next, id) {
|
||||
models.Playbook.findOne({
|
||||
_id: id
|
||||
}).select('-vault_password').exec(function (err, playbook) {
|
||||
if (err || !playbook) {
|
||||
return res.send(404);
|
||||
}
|
||||
|
||||
req.playbook = playbook;
|
||||
next();
|
||||
});
|
||||
}
|
||||
|
||||
function view (req, res) {
|
||||
res.send(req.playbook);
|
||||
}
|
||||
|
||||
function save (req, res) {
|
||||
req.playbook.name = req.body.name;
|
||||
req.playbook.location = req.body.location;
|
||||
|
||||
if (typeof req.body.vault_password == 'string' && req.body.vault_password.length > 0) {
|
||||
req.playbook.vault_password = req.body.vault_password;
|
||||
}
|
||||
|
||||
if (typeof req.body.identity == 'string' && req.body.identity.length > 0) {
|
||||
try {
|
||||
req.playbook.identity = mongoose.Types.ObjectId(req.body.identity);
|
||||
} catch (e) {}
|
||||
}
|
||||
|
||||
req.playbook.save();
|
||||
res.send(201);
|
||||
}
|
||||
|
||||
function remove (req, res) {
|
||||
req.playbook.remove(function (err) {
|
||||
res.send(201);
|
||||
})
|
||||
}
|
@ -1,51 +0,0 @@
|
||||
var models = require('../../models')
|
||||
var mongoose = require('mongoose')
|
||||
|
||||
var playbook = require('./playbook')
|
||||
|
||||
exports.unauthorized = function (app, template) {
|
||||
template([
|
||||
'add',
|
||||
'list'
|
||||
], {
|
||||
prefix: 'playbook'
|
||||
});
|
||||
|
||||
playbook.unauthorized(app, template);
|
||||
}
|
||||
|
||||
exports.httpRouter = function (app) {
|
||||
playbook.httpRouter(app);
|
||||
}
|
||||
|
||||
exports.router = function (app) {
|
||||
app.get('/playbooks', getPlaybooks)
|
||||
.post('/playbooks', addPlaybook)
|
||||
|
||||
playbook.router(app);
|
||||
}
|
||||
|
||||
function getPlaybooks (req, res) {
|
||||
models.Playbook.find({
|
||||
}).sort('-created').select('-vault_password').exec(function (err, playbooks) {
|
||||
res.send(playbooks)
|
||||
})
|
||||
}
|
||||
|
||||
function addPlaybook (req, res) {
|
||||
var playbook = new models.Playbook({
|
||||
name: req.body.name,
|
||||
location: req.body.location,
|
||||
vault_password: req.body.vault_password
|
||||
})
|
||||
|
||||
if (typeof req.body.identity == 'string' && req.body.identity.length > 0) {
|
||||
try {
|
||||
playbook.identity = mongoose.Types.ObjectId(req.body.identity);
|
||||
} catch (e) {}
|
||||
}
|
||||
|
||||
playbook.save(function () {
|
||||
res.send(playbook);
|
||||
});
|
||||
}
|
@ -1,13 +0,0 @@
|
||||
|
||||
exports.router = function (app, template) {
|
||||
app.get('/profile', getProfile)
|
||||
}
|
||||
|
||||
function getProfile (req, res) {
|
||||
res.send({
|
||||
_id: req.user._id,
|
||||
name: req.user.name,
|
||||
username: req.user.username,
|
||||
email: req.user.email
|
||||
})
|
||||
}
|
@ -1,63 +0,0 @@
|
||||
var models = require('../../models')
|
||||
var mongoose = require('mongoose')
|
||||
var express = require('express')
|
||||
|
||||
var jobRunner = require('../../runner');
|
||||
|
||||
exports.unauthorized = function (app, template) {
|
||||
template([
|
||||
'view'
|
||||
], {
|
||||
prefix: 'task'
|
||||
});
|
||||
}
|
||||
|
||||
exports.httpRouter = function (app) {
|
||||
}
|
||||
|
||||
exports.router = function (app) {
|
||||
var task = express.Router();
|
||||
|
||||
task.get('/', view)
|
||||
.delete('/', remove)
|
||||
|
||||
app.param('task_id', get)
|
||||
app.use('/playbook/:playbook_id/job/:job_id/task/:task_id', task);
|
||||
}
|
||||
|
||||
function get (req, res, next, id) {
|
||||
models.Task.findOne({
|
||||
_id: id
|
||||
}).exec(function (err, task) {
|
||||
if (err || !task) {
|
||||
return res.send(404);
|
||||
}
|
||||
|
||||
req.task = task;
|
||||
next();
|
||||
});
|
||||
}
|
||||
|
||||
function view (req, res) {
|
||||
res.send(req.task);
|
||||
}
|
||||
|
||||
function remove (req, res) {
|
||||
if (req.task.status == 'Running') {
|
||||
return res.send(400, 'Job is Running.');
|
||||
}
|
||||
|
||||
jobRunner.queue.pause();
|
||||
for (var i = 0; i < jobRunner.queue.tasks.length; i++) {
|
||||
if (jobRunner.queue.tasks[i].data._id.toString() == req.task._id.toString()) {
|
||||
// This is our task
|
||||
jobRunner.queue.tasks.splice(i, 1);
|
||||
break;
|
||||
}
|
||||
}
|
||||
jobRunner.queue.resume();
|
||||
|
||||
req.task.remove(function (err) {
|
||||
res.send(201);
|
||||
})
|
||||
}
|
@ -1,80 +0,0 @@
|
||||
var models = require('../../models')
|
||||
var mongoose = require('mongoose')
|
||||
|
||||
var task = require('./task')
|
||||
|
||||
var app = require('../../app')
|
||||
|
||||
var jobRunner = require('../../runner');
|
||||
|
||||
exports.unauthorized = function (app, template) {
|
||||
template([
|
||||
'tasks'
|
||||
], {
|
||||
prefix: 'task'
|
||||
});
|
||||
|
||||
task.unauthorized(app, template);
|
||||
}
|
||||
|
||||
exports.httpRouter = function (app) {
|
||||
task.httpRouter(app);
|
||||
}
|
||||
|
||||
exports.router = function (app) {
|
||||
app.get('/playbook/:playbook_id/tasks', getTasks)
|
||||
.get('/playbook/:playbook_id/job/:job_id/tasks', get)
|
||||
.post('/playbook/:playbook_id/job/:job_id/tasks', add)
|
||||
.post('/playbook/:playbook_id/job/:job_id/run', runJob)
|
||||
|
||||
task.router(app);
|
||||
}
|
||||
|
||||
function get (req, res) {
|
||||
models.Task.find({
|
||||
job: req.job._id
|
||||
}).populate('job').sort('-created').exec(function (err, tasks) {
|
||||
res.send(tasks)
|
||||
})
|
||||
}
|
||||
|
||||
function getTasks (req, res) {
|
||||
models.Task.find({
|
||||
playbook: req.playbook._id
|
||||
}).populate('job').sort('-created').exec(function (err, tasks) {
|
||||
res.send(tasks)
|
||||
})
|
||||
}
|
||||
|
||||
function add (req, res) {
|
||||
var task = new models.Task({
|
||||
job: req.job._id,
|
||||
status: 'Queued'
|
||||
})
|
||||
|
||||
task.save(function () {
|
||||
res.send(task);
|
||||
});
|
||||
}
|
||||
|
||||
function runJob (req, res) {
|
||||
var task = new models.Task({
|
||||
job: req.job._id,
|
||||
playbook: req.playbook._id,
|
||||
status: 'Queued'
|
||||
});
|
||||
|
||||
task.save(function (err) {
|
||||
task.populate('job', function () {
|
||||
app.io.emit('playbook.update', {
|
||||
task_id: task._id,
|
||||
playbook_id: req.playbook._id,
|
||||
task: task
|
||||
});
|
||||
|
||||
jobRunner.queue.push(task);
|
||||
})
|
||||
});
|
||||
|
||||
res.send(201)
|
||||
}
|
@ -1,60 +0,0 @@
|
||||
var models = require('../../models'),
|
||||
mongoose = require('mongoose'),
|
||||
express = require('express');
|
||||
|
||||
exports.unauthorized = function (app, template) {
|
||||
template([
|
||||
'view'
|
||||
], {
|
||||
prefix: 'user'
|
||||
});
|
||||
}
|
||||
|
||||
exports.httpRouter = function (app) {
|
||||
}
|
||||
|
||||
exports.router = function (app) {
|
||||
var user = express.Router();
|
||||
|
||||
user.get('/', view)
|
||||
.put('/', save)
|
||||
.delete('/', remove)
|
||||
|
||||
app.param('user_id', get)
|
||||
app.use('/user/:user_id', user);
|
||||
}
|
||||
|
||||
function get (req, res, next, id) {
|
||||
models.User.findOne({
|
||||
_id: id
|
||||
})
|
||||
.select('-password')
|
||||
.exec(function (err, user) {
|
||||
if (err || !user) {
|
||||
return res.send(404);
|
||||
}
|
||||
|
||||
req._user = user;
|
||||
next();
|
||||
});
|
||||
}
|
||||
|
||||
function view (req, res) {
|
||||
res.send(req._user);
|
||||
}
|
||||
|
||||
function save (req, res) {
|
||||
req._user.name = req.body.name;
|
||||
models.User.hashPassword(req.body.password, function (hash) {
|
||||
req._user.password = hash;
|
||||
});
|
||||
|
||||
req._user.save();
|
||||
res.send(201);
|
||||
}
|
||||
|
||||
function remove (req, res) {
|
||||
req._user.remove(function (err) {
|
||||
res.send(201);
|
||||
})
|
||||
}
|
@ -1,63 +0,0 @@
|
||||
var models = require('../../models'),
|
||||
mongoose = require('mongoose'),
|
||||
validator = require('validator'),
|
||||
user = require('./user');
|
||||
|
||||
exports.unauthorized = function (app, template) {
|
||||
template([
|
||||
'add',
|
||||
'list'
|
||||
], {
|
||||
prefix: 'user'
|
||||
});
|
||||
|
||||
user.unauthorized(app, template);
|
||||
}
|
||||
|
||||
exports.httpRouter = function (app) {
|
||||
user.httpRouter(app);
|
||||
}
|
||||
|
||||
exports.router = function (app) {
|
||||
app.get('/users', get)
|
||||
.post('/users', add)
|
||||
|
||||
user.router(app);
|
||||
}
|
||||
|
||||
function get (req, res) {
|
||||
models.User.find({})
|
||||
.sort('-created')
|
||||
.select('-password')
|
||||
.exec(function (err, users) {
|
||||
res.send(users);
|
||||
});
|
||||
}
|
||||
|
||||
function add (req, res) {
|
||||
var user = new models.User({
|
||||
name: req.body.name,
|
||||
email: req.body.email,
|
||||
username: req.body.username
|
||||
});
|
||||
|
||||
if (user.name.length == 0 || user.name.email == 0) {
|
||||
return res.send(400);
|
||||
}
|
||||
|
||||
models.User.findOne({
|
||||
email: user.email
|
||||
}, function (_, existingUser) {
|
||||
if (existingUser) {
|
||||
return res.send(400);
|
||||
}
|
||||
|
||||
models.User.hashPassword(req.body.password, function (hash) {
|
||||
user.password = hash;
|
||||
|
||||
user.save(function () {
|
||||
res.send(user);
|
||||
});
|
||||
});
|
||||
});
|
||||
}
|
242
lib/runner.js
242
lib/runner.js
@ -1,242 +0,0 @@
|
||||
var async = require('async'),
|
||||
fs = require('fs'),
|
||||
spawn = require('child_process').spawn;
|
||||
|
||||
var config = require('./config'),
|
||||
models = require('./models'),
|
||||
app = require('./app');
|
||||
|
||||
var home = process.env.HOME + '/';
|
||||
var user = process.env.USER;
|
||||
|
||||
exports.queue = async.queue(worker, 1);
|
||||
|
||||
function worker (task, callback) {
|
||||
// Task is to be model Task
|
||||
|
||||
// Download the git project
|
||||
// Set up hosts file
|
||||
// Set up vault pwd file
|
||||
// Set up private key
|
||||
// Execute ansible-playbook -i hosts --ask-vault-pass --private-key=~/.ssh/ansible_key task.yml
|
||||
|
||||
async.waterfall([
|
||||
function (done) {
|
||||
task.populate('job', function (err) {
|
||||
done(err, task);
|
||||
})
|
||||
},
|
||||
function (task, done) {
|
||||
models.Playbook.findOne({ _id: task.playbook }, function (err, playbook) {
|
||||
done(err, task, playbook)
|
||||
});
|
||||
},
|
||||
function (task, playbook, done) {
|
||||
// mark task as running and send an update via socketio
|
||||
task.status = 'Running';
|
||||
|
||||
app.io.emit('playbook.update', {
|
||||
task_id: task._id,
|
||||
playbook_id: playbook._id,
|
||||
task: task
|
||||
});
|
||||
|
||||
models.Task.update({
|
||||
_id: task._id
|
||||
}, {
|
||||
$set: {
|
||||
status: 'Running'
|
||||
}
|
||||
}, function (err) {
|
||||
done(err, task, playbook);
|
||||
});
|
||||
},
|
||||
function (task, playbook, done) {
|
||||
playbook.populate('identity', function (err) {
|
||||
done(err, task, playbook)
|
||||
});
|
||||
},
|
||||
installHostKeys,
|
||||
pullGit,
|
||||
setupHosts,
|
||||
setupVault,
|
||||
playTheBook
|
||||
], function (err) {
|
||||
if (err) {
|
||||
task.status = 'Failed';
|
||||
} else {
|
||||
task.status = 'Completed';
|
||||
}
|
||||
|
||||
var rmrf = spawn('rm', ['-rf', home + 'playbook_'+task.playbook])
|
||||
rmrf.on('close', function () {
|
||||
app.io.emit('playbook.update', {
|
||||
task_id: task._id,
|
||||
playbook_id: task.playbook,
|
||||
task: task
|
||||
});
|
||||
task.save();
|
||||
|
||||
callback(err);
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
function installHostKeys (task, playbook, done) {
|
||||
// Install the private key
|
||||
playbookOutputHandler.call(task, "Updating SSH Keys\n");
|
||||
|
||||
var location = home + '.ssh/id_rsa';
|
||||
fs.mkdir( home + '.ssh', 448, function() {
|
||||
async.parallel([
|
||||
function (done) {
|
||||
fs.writeFile(location, playbook.identity.private_key, {
|
||||
mode: 384 // base 8 = 0600
|
||||
}, done);
|
||||
},
|
||||
function (done) {
|
||||
fs.writeFile(location+'.pub', playbook.identity.public_key, {
|
||||
mode: 420 // base 8 = 0644
|
||||
}, done);
|
||||
},
|
||||
function (done) {
|
||||
var config = "Host *\n\
|
||||
StrictHostKeyChecking no\n\
|
||||
CheckHostIp no\n\
|
||||
PasswordAuthentication no\n\
|
||||
PreferredAuthentications publickey\n";
|
||||
|
||||
fs.writeFile(home + '.ssh/config', config, {
|
||||
mode: 420 // 0644
|
||||
}, done);
|
||||
}
|
||||
], function (err) {
|
||||
playbookOutputHandler.call(task, "SSH Keys Updated.\n");
|
||||
done(err, task, playbook)
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
function pullGit (task, playbook, done) {
|
||||
// Pull from git
|
||||
playbookOutputHandler.call(task, "\nDownloading Playbook.\n");
|
||||
|
||||
var install = spawn(config.path+"/scripts/pullGit.sh", [playbook.location, 'playbook_'+playbook._id], {
|
||||
cwd: home,
|
||||
env: {
|
||||
HOME: home,
|
||||
OLDPWD: home,
|
||||
PWD: home,
|
||||
LOGNAME: user,
|
||||
USER: user,
|
||||
TERM: 'xterm',
|
||||
SHELL: '/bin/bash',
|
||||
PATH: process.env.PATH+':/usr/local/sbin:/usr/local/bin:/sbin:/bin:/usr/sbin:/usr/bin:/root/bin',
|
||||
LANG: 'en_GB.UTF-8'
|
||||
}
|
||||
});
|
||||
install.stdout.on('data', playbookOutputHandler.bind(task));
|
||||
install.stderr.on('data', playbookOutputHandler.bind(task));
|
||||
|
||||
install.on('close', function(code) {
|
||||
playbookOutputHandler.call(task, "\n\nPlaybook Downloaded.\n");
|
||||
|
||||
done(null, task, playbook);
|
||||
});
|
||||
}
|
||||
|
||||
function setupHosts (task, playbook, done) {
|
||||
var hostfile = '';
|
||||
|
||||
models.HostGroup.find({
|
||||
playbook: playbook._id
|
||||
}, function (err, hostgroups) {
|
||||
async.each(hostgroups, function (group, cb) {
|
||||
models.Host.find({
|
||||
group: group._id
|
||||
}, function (err, hosts) {
|
||||
hostfile += "["+group.name+"]\n";
|
||||
|
||||
for (var i = 0; i < hosts.length; i++) {
|
||||
hostfile += hosts[i].hostname+"\n";
|
||||
}
|
||||
|
||||
cb();
|
||||
});
|
||||
}, function () {
|
||||
playbookOutputHandler.call(task, "\nSet up Ansible Hosts file with contents:\n"+hostfile+"\n");
|
||||
|
||||
fs.writeFile(home + 'playbook_'+playbook._id+'/semaphore_hosts', hostfile, function (err) {
|
||||
done(err, task, playbook);
|
||||
});
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
function setupVault (task, playbook, done) {
|
||||
fs.writeFile(home + 'playbook_'+playbook._id+'/semaphore_vault_pwd', playbook.vault_password, function (err) {
|
||||
done(err, task, playbook);
|
||||
})
|
||||
}
|
||||
|
||||
function playTheBook (task, playbook, done) {
|
||||
playbookOutputHandler.call(task, "\nStarting play "+task.job.play_file+".\n");
|
||||
|
||||
var args = ['-i', 'semaphore_hosts'];
|
||||
if (task.job.use_vault && playbook.vault_password && playbook.vault_password.length > 0) {
|
||||
args.push('--vault-password-file='+'semaphore_vault_pwd');
|
||||
}
|
||||
|
||||
// private key to login to server[s]
|
||||
args.push('--private-key=' + home + '.ssh/id_rsa');
|
||||
|
||||
// the playbook file
|
||||
args.push(task.job.play_file);
|
||||
|
||||
var playbook = spawn("ansible-playbook", args, {
|
||||
cwd: home + 'playbook_'+playbook._id,
|
||||
env: {
|
||||
HOME: home,
|
||||
OLDPWD: home,
|
||||
PWD: home + 'playbook_'+playbook._id,
|
||||
LOGNAME: user,
|
||||
USER: user,
|
||||
TERM: 'xterm',
|
||||
SHELL: '/bin/bash',
|
||||
PATH: process.env.PATH+':/usr/local/sbin:/usr/local/bin:/sbin:/bin:/usr/sbin:/usr/bin:/root/bin',
|
||||
LANG: 'en_GB.UTF-8',
|
||||
PYTHONPATH: process.env.PYTHONPATH,
|
||||
PYTHONUNBUFFERED: 1
|
||||
}
|
||||
});
|
||||
playbook.stdout.on('data', playbookOutputHandler.bind(task));
|
||||
playbook.stderr.on('data', playbookOutputHandler.bind(task));
|
||||
|
||||
playbook.on('close', function(code) {
|
||||
console.log('done.', code);
|
||||
|
||||
if (code !== 0) {
|
||||
// Task failed
|
||||
return done('Failed with code '+code);
|
||||
}
|
||||
|
||||
done();
|
||||
});
|
||||
}
|
||||
|
||||
function playbookOutputHandler (chunk) {
|
||||
chunk = chunk.toString('utf8');
|
||||
|
||||
if (!this.output) {
|
||||
this.output = "";
|
||||
}
|
||||
|
||||
this.output += chunk;
|
||||
app.io.emit('playbook.output', {
|
||||
task_id: this._id,
|
||||
playbook_id: this.playbook,
|
||||
output: chunk
|
||||
});
|
||||
|
||||
console.log(chunk);
|
||||
}
|
@ -1,10 +0,0 @@
|
||||
#!/bin/bash
|
||||
|
||||
printf "#\041/bin/bash\nssh -i \"$HOME/.ssh/id_rsa\" \$1 \$2\n" > $HOME/ssh_wrapper.sh
|
||||
chmod +x $HOME/ssh_wrapper.sh
|
||||
|
||||
cd $HOME
|
||||
GIT_SSH=$HOME/ssh_wrapper.sh git clone "$1" $2
|
||||
if [ $? -ne 0 ]; then
|
||||
exit 2
|
||||
fi
|
@ -1,67 +0,0 @@
|
||||
// By Matej Kramny <matej@matej.me>
|
||||
// Please leave this comment here.
|
||||
|
||||
module.exports = function(app) {
|
||||
var self = this;
|
||||
self.routes = [];
|
||||
self.app = app
|
||||
|
||||
self.route = function (controller) {
|
||||
if (!(controller instanceof Array)) {
|
||||
controller = [controller];
|
||||
}
|
||||
|
||||
for (c in controller) {
|
||||
controller[c].unauthorized(self.app, self.add.bind(self));
|
||||
}
|
||||
}
|
||||
|
||||
self.makeRoute = function(route, view) {
|
||||
return {
|
||||
route: route,
|
||||
view: view
|
||||
}
|
||||
}
|
||||
|
||||
self.add = function (routes, opts) {
|
||||
var args = arguments;
|
||||
|
||||
var prefix = opts ? opts.prefix : null;
|
||||
if (!prefix) prefix = '';
|
||||
else prefix += '/';
|
||||
|
||||
if (typeof routes === 'string') {
|
||||
self.routes.push(self.makeRoute(prefix+routes, prefix+routes));
|
||||
return;
|
||||
}
|
||||
if (Object.prototype.toString.call(routes) == '[object Object]') {
|
||||
self.routes.push(routes);
|
||||
return;
|
||||
}
|
||||
|
||||
for (var i = 0; i < routes.length; i++) {
|
||||
var r;
|
||||
if (typeof routes[i] == 'string') {
|
||||
r = self.makeRoute(prefix+routes[i], prefix+routes[i]);
|
||||
} else if (routes[i] instanceof Array) {
|
||||
r = self.makeRoute(prefix+routes[i][0], routes[i][1]);
|
||||
} else {
|
||||
r = routes[i]
|
||||
}
|
||||
|
||||
self.routes.push(r);
|
||||
}
|
||||
}
|
||||
|
||||
self.setup = function () {
|
||||
for (var i = 0; i < routes.length; i++) {
|
||||
app.get('/view/'+routes[i].route, self.getView.bind(routes[i]));
|
||||
}
|
||||
}
|
||||
|
||||
self.getView = function (req, res) {
|
||||
res.render(this.view);
|
||||
}
|
||||
|
||||
return self;
|
||||
}
|
16
lib/util.js
16
lib/util.js
@ -1,16 +0,0 @@
|
||||
exports.authorized = function (req, res, next) {
|
||||
if (res.locals.loggedIn) {
|
||||
next()
|
||||
} else {
|
||||
res.format({
|
||||
html: function() {
|
||||
res.render('auth');
|
||||
},
|
||||
json: function() {
|
||||
res.send(403, {
|
||||
message: "Unauthorized"
|
||||
})
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
@ -1,8 +1,7 @@
|
||||
[
|
||||
"/vendor/jquery.min",
|
||||
"/vendor/angular-1.2.29",
|
||||
"/vendor/angular-couch-potato/dist/angular-couch-potato",
|
||||
"/vendor/angular-ui-router/release/angular-ui-router.min",
|
||||
"/vendor/angular.min",
|
||||
"/vendor/angular-couch-potato",
|
||||
"/vendor/angular-ui-router.min",
|
||||
"/vendor/angular-ui.min",
|
||||
"/vendor/angular-loading-bar/loading-bar",
|
||||
"/vendor/moment/moment.min",
|
||||
|
File diff suppressed because it is too large
Load Diff
3
public/html/auth/logout.jade
Normal file
3
public/html/auth/logout.jade
Normal file
@ -0,0 +1,3 @@
|
||||
.jumbotron: .container
|
||||
h1 Hey there,
|
||||
p We're logging you out <i class="fa fa-fw fa-spin fa-spinner"></i>
|
11
public/html/dashboard.jade
Normal file
11
public/html/dashboard.jade
Normal file
@ -0,0 +1,11 @@
|
||||
.container-fluid
|
||||
.row
|
||||
.col-md-8
|
||||
ul
|
||||
li Scheduled job {x} was successfully executed. Took 30s
|
||||
.col-md-4
|
||||
.panel.panel-default
|
||||
.panel-heading Projects
|
||||
button.btn.btn-default.btn-xs.pull-right: i.fa.fa-fw.fa-plus
|
||||
ul.list-group
|
||||
li.list-group-item(ng-repeat="project in projects") {{ project.name }}
|
@ -1,16 +0,0 @@
|
||||
|
||||
h2 If you're just getting started
|
||||
|
||||
ol
|
||||
li Read about how Ansible Playbooks work, and try them out
|
||||
li Host your playbook on a git repository (e.g. github / gitlab)
|
||||
li Create a deploy key
|
||||
li Create an Identity (inside Semaphore). Add your Deploy Private and Public keys
|
||||
li Create a playbook, set the git url to your repository
|
||||
li Define hosts which you would like your playbook to use
|
||||
li Create a job that runs your playbook task file
|
||||
li Press Run
|
||||
|
||||
h3 Playbook Variables
|
||||
|
||||
p This is a bit advanced, but a good practice may be providing your variables through <code>group_vars/{host-group}.yml</code>. These can be encrypted using ansible-vault. The vault password can then be provided using a Semaphore Identity.
|
@ -10,24 +10,25 @@ html(lang="en" ng-app="semaphore")
|
||||
link(rel="stylesheet" href="/public/css/semaphore.css")
|
||||
|
||||
body
|
||||
.navbar.navbar-default(ng-if="loggedIn"): .container
|
||||
.navbar.navbar-default(ng-if="loggedIn"): .container-fluid
|
||||
.navbar-header
|
||||
a.navbar-brand(ui-sref="homepage") Semaphore
|
||||
a.navbar-brand(ui-sref="homepage") SEMAPHORE
|
||||
|
||||
nav.nav.navbar-nav
|
||||
li: a(ui-sref="playbooks") Playbooks
|
||||
li: a(ui-sref="identities.list") Identities
|
||||
li: a(ui-sref="users.list") Users
|
||||
ul.nav.navbar-nav.navbar-right(style="margin-right: 0;")
|
||||
li(uib-dropdown)
|
||||
a(uib-dropdown-toggle)
|
||||
i.fa.fa-fw.fa-user
|
||||
i.caret
|
||||
ul(uib-dropdown-menu)
|
||||
li: a(ui-sref="user") Profile
|
||||
li: a Settings
|
||||
li.divider
|
||||
li: a(ui-sref="auth.logout") Log out
|
||||
|
||||
nav.nav.navbar-nav.pull-right
|
||||
li: a(ui-sref="addPlaybook") Add Playbook
|
||||
|
||||
.container
|
||||
.col-lg-12
|
||||
ui-view(autoscroll="false")
|
||||
p.lead.text-center
|
||||
i.fa.fa-spin.fa-cog
|
||||
| Loading...
|
||||
ui-view(autoscroll="false")
|
||||
p.lead.text-center
|
||||
i.fa.fa-spin.fa-cog
|
||||
| Loading...
|
||||
|
||||
footer: a.github-corner(href="https://github.com/ansible-semaphore/semaphore" target="_blank" title="Ansible-Semaphore on GitHub")
|
||||
svg(width="80" height="80" viewbox="0 0 250 250")
|
||||
|
@ -7,6 +7,10 @@ app.config(['$httpProvider', function ($httpProvider) {
|
||||
return {
|
||||
request: function (request) {
|
||||
var url = request.url;
|
||||
if (url.indexOf('/tpl/') !== -1) {
|
||||
request.url = url = url.replace('/tpl/', '/public/html/');
|
||||
}
|
||||
|
||||
if (!(url.indexOf('/public') !== -1 || url.indexOf('://') !== -1)) {
|
||||
request.url = "/api" + request.url;
|
||||
request.headers['Cache-Control'] = 'no-cache';
|
||||
@ -51,7 +55,7 @@ app.run(['$rootScope', '$window', '$couchPotato', '$injector', '$state', '$http'
|
||||
$rootScope.user = user;
|
||||
$rootScope.loggedIn = true;
|
||||
}, function () {
|
||||
$state.go('login');
|
||||
$state.go('auth.login');
|
||||
});
|
||||
}
|
||||
|
||||
|
9
public/js/controllers/dashboard.js
Normal file
9
public/js/controllers/dashboard.js
Normal file
@ -0,0 +1,9 @@
|
||||
define(function () {
|
||||
app.registerController('DashboardCtrl', function ($scope, $http) {
|
||||
$scope.projects = [{
|
||||
name: 'Hey there'
|
||||
}, {
|
||||
name: 'Test project'
|
||||
}];
|
||||
})
|
||||
})
|
@ -1,11 +1,27 @@
|
||||
app.config(function ($stateProvider, $urlRouterProvider, $locationProvider, $couchPotatoProvider) {
|
||||
$stateProvider.state('login', {
|
||||
$stateProvider.state('auth', {
|
||||
url: '/auth',
|
||||
abstract: true,
|
||||
templateUrl: '/tpl/abstract.html'
|
||||
})
|
||||
.state('auth.login', {
|
||||
url: '/login',
|
||||
pageTitle: "Sign In",
|
||||
templateUrl: "/public/html/auth/login.html",
|
||||
templateUrl: '/tpl/auth/login.html',
|
||||
controller: "SignInCtrl",
|
||||
resolve: {
|
||||
dummy: $couchPotatoProvider.resolveDependencies(['controllers/auth/login'])
|
||||
$d: $couchPotatoProvider.resolveDependencies(['controllers/auth/login'])
|
||||
}
|
||||
})
|
||||
.state('auth.logout', {
|
||||
url: '/logout',
|
||||
public: true,
|
||||
templateUrl: '/tpl/auth/logout.html',
|
||||
controller: ['$http', '$rootScope', '$state', function ($http, $rootScope, $state) {
|
||||
$http.post('/auth/logout').success(function () {
|
||||
$rootScope.refreshUser();
|
||||
$state.go('auth.login');
|
||||
});
|
||||
}]
|
||||
});
|
||||
});
|
@ -7,19 +7,15 @@ app.config(function ($stateProvider, $urlRouterProvider, $locationProvider, $cou
|
||||
$urlRouterProvider.otherwise('/');
|
||||
|
||||
$stateProvider
|
||||
.state('homepage', {
|
||||
.state('dashboard', {
|
||||
url: '/',
|
||||
pageTitle: 'Homepage',
|
||||
templateUrl: "/public/html/homepage.html"
|
||||
})
|
||||
|
||||
.state('logout', {
|
||||
url: '/logout',
|
||||
pageTitle: 'Log Out',
|
||||
controller: function ($scope) {
|
||||
window.location = "/logout";
|
||||
pageTitle: 'Dashboard',
|
||||
templateUrl: '/tpl/dashboard.html',
|
||||
controller: 'DashboardCtrl',
|
||||
resolve: {
|
||||
$d: $couchPotatoProvider.resolveDependencies(['controllers/dashboard'])
|
||||
}
|
||||
})
|
||||
});
|
||||
});
|
||||
|
||||
app.run(function($rootScope, $state, $stateParams, $http) {
|
||||
|
@ -2,7 +2,6 @@ package auth
|
||||
|
||||
import (
|
||||
"database/sql"
|
||||
"fmt"
|
||||
"net/mail"
|
||||
"strings"
|
||||
"time"
|
||||
@ -38,7 +37,6 @@ func Login(c *gin.Context) {
|
||||
}
|
||||
|
||||
query, args, _ := q.ToSql()
|
||||
fmt.Println(query, args)
|
||||
|
||||
var user models.User
|
||||
if err := database.Mysql.SelectOne(&user, query, args...); err != nil {
|
||||
@ -65,3 +63,12 @@ func Login(c *gin.Context) {
|
||||
|
||||
c.AbortWithStatus(204)
|
||||
}
|
||||
|
||||
func Logout(c *gin.Context) {
|
||||
session := c.MustGet("session").(models.Session)
|
||||
if err := database.Redis.Del("session:" + session.ID).Err(); err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
c.AbortWithStatus(204)
|
||||
}
|
||||
|
@ -23,6 +23,7 @@ func Route(r *gin.Engine) {
|
||||
|
||||
func(api *gin.RouterGroup) {
|
||||
api.POST("/login", auth.Login)
|
||||
api.POST("/logout", auth.Logout)
|
||||
}(api.Group("/auth"))
|
||||
|
||||
api.Use(MustAuthenticate)
|
Loading…
Reference in New Issue
Block a user