From 58d8158116d164e9c7bde32a2ff5d1237b0bef4d Mon Sep 17 00:00:00 2001 From: Matej Kramny Date: Tue, 17 Mar 2015 01:21:16 +0100 Subject: [PATCH 1/4] Update site layout - Add Dockerfile - Add docker instructions to README.md - Reorganise js & jade files --- Dockerfile | 11 +++ README.md | 74 ++++++++++++++----- bower.json | 2 +- lib/routes/playbook/playbook.js | 3 + lib/views/layout.jade | 19 ++--- lib/views/{host => playbook}/hosts.jade | 2 +- lib/views/{job => playbook}/jobs.jade | 2 +- lib/views/playbook/list.jade | 2 +- lib/views/{task => playbook}/tasks.jade | 2 +- lib/views/playbook/view.jade | 30 ++++---- playbooks/playbook.yml | 1 - public/css/semaphore.less | 6 ++ .../controllers/{host => playbook}/hosts.js | 6 +- .../js/controllers/{job => playbook}/jobs.js | 4 +- .../controllers/{task => playbook}/tasks.js | 6 +- public/js/routes/playbooks.js | 48 ++++++------ ssh_vagrant.sh | 1 - 17 files changed, 137 insertions(+), 82 deletions(-) create mode 100644 Dockerfile rename lib/views/{host => playbook}/hosts.jade (95%) rename lib/views/{job => playbook}/jobs.jade (98%) rename lib/views/{task => playbook}/tasks.jade (95%) rename public/js/controllers/{host => playbook}/hosts.js (90%) rename public/js/controllers/{job => playbook}/jobs.js (88%) rename public/js/controllers/{task => playbook}/tasks.js (95%) delete mode 100755 ssh_vagrant.sh diff --git a/Dockerfile b/Dockerfile new file mode 100644 index 00000000..fd56058f --- /dev/null +++ b/Dockerfile @@ -0,0 +1,11 @@ +FROM iojs:onbuild + +ENV NODE_ENV production + +ADD . /srv/semaphore +WORKDIR /srv/semaphore + +RUN npm install +CMD ["node", "/srv/semaphore/bin/semaphore"] + +EXPOSE 80 \ No newline at end of file diff --git a/README.md b/README.md index 6eeeafa8..a90b818b 100644 --- a/README.md +++ b/README.md @@ -3,36 +3,63 @@ semaphore Open Source Alternative to Ansible Tower -![](public/img/screenshot.png) +![screenshot](public/img/screenshot.png) Features -------- The basics of Ansible Tower, but in addition: -- Fast, Simple interface that doesn’t get in the way -- Task output is streamed live via websocket -- Free. MIT Licensed. Do what you want. +- [x] Fast, Simple interface (not having to submit a million forms to get something simple done) +- [x] Task output is streamed live via websocket +- [x] Create inventories per playbook +- [x] Add rsa keys (to authenticate git repositories) +- [x] Run playbooks against specified hosts +- [ ] Multiple Users support -How to run: ------------ +Docker quickstart +----------------- -1. Install Vagrant -2. Run `vagrant up` -3. Open [localhost:3000](http://localhost:3000) +1. Get Docker +2. Run redis + +``` +docker run -d \ + --name=redisio \ + -v /var/lib/redisio:/var/lib/redis \ + -p 127.0.0.1:6379:6379 \ + castawaylabs/redis-docker +``` + +3. Run mongodb + +``` +docker run -d \ + --name=mongodb \ + -v /var/lib/mongodb:/var/lib/mongodb \ + -p 127.0.0.1:6379:6379 \ + castawaylabs/mongo-docker +``` + +4. Run semaphore + +``` +docker run -d \ + --name=semaphroe \ + --restart=always \ + --link redisio:redis \ + --link mongodb:mongo \ + -p 80:80 \ + castawaylabs/semaphore +``` Development steps: Install requirements: -- node.js >= 0.11.x -- an isolated environment (e.g. Docker / NodeGear) -- ansible (the tool) +- node.js / io.js +- an isolated environment (e.g. Docker / Vagrant) +- ansible - mongodb & redis -- Sudo access (this might change). To run jobs, this tool writes private keys to /root/.ssh and copies playbook directories to /root/. - -1. Copy `lib/credentials.default.json` to `lib/credentials.json` and customise, or export relevant environment variables -2. `bower install` -3. `node bin/semaphore` Initial Login ------------- @@ -58,9 +85,22 @@ Use these variables to override the config. | SMTP_PASS | Mandrill smtp password | | | MONGODB_URL | Mongodb URL | `mongodb://127.0.0.1/semaphore` | +Vision and goals +---------------- + +- Be able to specify environment information per playbook / per task +- Schedule jobs +- Email alerts +>>>>>>> 1199a52... Update site layout + Note to Ansible guys -------------------- > Thanks very much for making Ansible, and Ansible Tower. It is a great tool!. Your UI is pretty horrible though, and so we'd be happy if you could learn and use parts of this tool in your Tower. It would be amazing if this could be your `Community Edition` of Ansible Tower. + +License +------- + +MIT \ No newline at end of file diff --git a/bower.json b/bower.json index 3811e452..deaeb048 100644 --- a/bower.json +++ b/bower.json @@ -13,4 +13,4 @@ "angular-couch-potato": "~0.1.1", "angular-ui-router": "~0.2.10" } -} +} \ No newline at end of file diff --git a/lib/routes/playbook/playbook.js b/lib/routes/playbook/playbook.js index b263a251..d2882d53 100644 --- a/lib/routes/playbook/playbook.js +++ b/lib/routes/playbook/playbook.js @@ -4,6 +4,9 @@ var express = require('express') exports.unauthorized = function (app, template) { template([ + 'tasks', + 'jobs', + 'hosts', 'view' ], { prefix: 'playbook' diff --git a/lib/views/layout.jade b/lib/views/layout.jade index 950eadae..70694e22 100644 --- a/lib/views/layout.jade +++ b/lib/views/layout.jade @@ -27,19 +27,12 @@ html li: a(ui-sref="addPlaybook") Add Playbook .container-fluid - .row - .col-sm-3.col-lg-2 - ul.nav - h2.no-top-margin Playbooks - li(ng-repeat="playbook in playbooks") - a(ui-sref="playbook.view({ playbook_id: playbook._id })") {{ playbook.name }} - - .col-sm-9.col-lg-10 - block content - ui-view(autoscroll="false") - p.lead.text-center - i.fa.fa-spin.fa-cog - | Loading... + .col-lg-12 + block content + ui-view(autoscroll="false") + p.lead.text-center + i.fa.fa-spin.fa-cog + | Loading... block js script(src="/vendor/requirejs/require.js" data-main="/js/semaphore.js") diff --git a/lib/views/host/hosts.jade b/lib/views/playbook/hosts.jade similarity index 95% rename from lib/views/host/hosts.jade rename to lib/views/playbook/hosts.jade index 611b18bc..d789ecf3 100644 --- a/lib/views/host/hosts.jade +++ b/lib/views/playbook/hosts.jade @@ -1,4 +1,4 @@ -h2 Hosts +h1 Hosts button.btn.btn-default.pull-right(ng-click="add()") Add Group div(ng-repeat="hostgroup in hostgroups.hostgroups") diff --git a/lib/views/job/jobs.jade b/lib/views/playbook/jobs.jade similarity index 98% rename from lib/views/job/jobs.jade rename to lib/views/playbook/jobs.jade index b84205d8..e1ab5e4a 100644 --- a/lib/views/job/jobs.jade +++ b/lib/views/playbook/jobs.jade @@ -1,4 +1,4 @@ -h2 Jobs +h1 Jobs button.btn.btn-default.pull-right(ng-click="add()") Add Job table.table.table-hover diff --git a/lib/views/playbook/list.jade b/lib/views/playbook/list.jade index 97371269..c65b6bd7 100644 --- a/lib/views/playbook/list.jade +++ b/lib/views/playbook/list.jade @@ -5,6 +5,6 @@ h1 Playbooks table.table tr(ng-repeat="playbook in playbooks") - td: a(ui-sref="playbook.view({ playbook_id: playbook._id })") {{ playbook.name }} + td: a(ui-sref="playbook.tasks({ playbook_id: playbook._id })") {{ playbook.name }} blockquote Playbooks are ansible playbooks. Each playbook defines a git repository with the playbook code. Semaphore downloads the playbook and runs the task file. \ No newline at end of file diff --git a/lib/views/task/tasks.jade b/lib/views/playbook/tasks.jade similarity index 95% rename from lib/views/task/tasks.jade rename to lib/views/playbook/tasks.jade index 211a9a58..4ebadcd6 100644 --- a/lib/views/task/tasks.jade +++ b/lib/views/playbook/tasks.jade @@ -1,4 +1,4 @@ -h2 Tasks +h1 Tasks small(ng-if="status.length > 0" ng-bind="status") table.table.table-hover diff --git a/lib/views/playbook/view.jade b/lib/views/playbook/view.jade index 62376f5e..8e0230c6 100644 --- a/lib/views/playbook/view.jade +++ b/lib/views/playbook/view.jade @@ -1,16 +1,16 @@ -h1 {{ playbook.data.name }} - .btn-group.pull-right - button.btn.btn-success(ui-sref="playbook.edit({ playbook_id: playbook.data._id })") Edit - button.btn.btn-danger(ng-click="delete()") Delete +mixin menuItem(state, name) + li(ng-class="{ active: $state.includes('#{state}') }"): a(ui-sref=state+"({ playbook_id: playbook.data._id })")= name -hr - -ui-view(name="tasks") - -hr - -ui-view(name="jobs") - -hr - -ui-view(name="hosts") +.row + .col-sm-3.col-lg-2 + ul.nav + h2.no-top-margin {{ playbook.data.name }} + +menuItem("playbook.tasks", "Tasks") + +menuItem("playbook.jobs", "Jobs") + +menuItem("playbook.hosts", "Hosts") + br + ul.nav + li: a(ui-sref="playbook.edit({ playbook_id: playbook.data._id })") Edit + li: a(ng-click="delete()") Delete + .col-sm-9.col-lg-10 + ui-view \ No newline at end of file diff --git a/playbooks/playbook.yml b/playbooks/playbook.yml index 2bdbc6c1..2078ae02 100644 --- a/playbooks/playbook.yml +++ b/playbooks/playbook.yml @@ -22,7 +22,6 @@ - runit - npm: name={{ item }} global=yes with_items: - - grunt-cli - bower # source is copied using ansible. diff --git a/public/css/semaphore.less b/public/css/semaphore.less index 81f16977..d12699c8 100644 --- a/public/css/semaphore.less +++ b/public/css/semaphore.less @@ -28,4 +28,10 @@ h1, h2, h3, h4, h5, h6 { &.no-top-margin { margin-top: 0; } +} + +ul.nav { + & > li.active a { + background-color: #eee; + } } \ No newline at end of file diff --git a/public/js/controllers/host/hosts.js b/public/js/controllers/playbook/hosts.js similarity index 90% rename from public/js/controllers/host/hosts.js rename to public/js/controllers/playbook/hosts.js index 9a133771..1408f4f3 100644 --- a/public/js/controllers/host/hosts.js +++ b/public/js/controllers/playbook/hosts.js @@ -5,10 +5,10 @@ define([ 'factories/hostgroup', 'factories/host' ], function(app, $) { - app.registerController('HostsCtrl', ['$scope', '$state', 'hostgroups', 'Host', function($scope, $state, hostgroups, Host) { - + app.registerController('PlaybookHostsCtrl', ['$scope', '$state', 'hostgroups', 'Host', function($scope, $state, hostgroups, Host) { + $scope.hostgroups = hostgroups; - + hostgroups.get($scope.playbook, function () { }); diff --git a/public/js/controllers/job/jobs.js b/public/js/controllers/playbook/jobs.js similarity index 88% rename from public/js/controllers/job/jobs.js rename to public/js/controllers/playbook/jobs.js index 1d834c79..ff03fdb8 100644 --- a/public/js/controllers/job/jobs.js +++ b/public/js/controllers/playbook/jobs.js @@ -4,9 +4,9 @@ define([ 'services/jobs', 'factories/job' ], function(app, $) { - app.registerController('JobsCtrl', ['$scope', 'jobs', function($scope, jobs) { + app.registerController('PlaybookJobsCtrl', ['$scope', 'jobs', function($scope, jobs) { $scope.jobs = jobs; - + jobs.get($scope.playbook, function () { }); diff --git a/public/js/controllers/task/tasks.js b/public/js/controllers/playbook/tasks.js similarity index 95% rename from public/js/controllers/task/tasks.js rename to public/js/controllers/playbook/tasks.js index 22cf618e..74fe3fd4 100644 --- a/public/js/controllers/task/tasks.js +++ b/public/js/controllers/playbook/tasks.js @@ -7,9 +7,9 @@ define([ ], function(app, $, io) { var socket = io(); - app.registerController('TasksCtrl', ['$scope', 'tasks', 'Task', function($scope, tasks, Task) { + app.registerController('PlaybookTasksCtrl', ['$scope', 'tasks', 'Task', function($scope, tasks, Task) { $scope.tasks = tasks; - + tasks.get($scope.playbook, function () { }); @@ -40,7 +40,7 @@ define([ if (!task.data.output) { task.data.output = ""; } - + task.data.output += data.output; if (!$scope.$$phase) { diff --git a/public/js/routes/playbooks.js b/public/js/routes/playbooks.js index cebc89b9..6e2cbe03 100644 --- a/public/js/routes/playbooks.js +++ b/public/js/routes/playbooks.js @@ -30,10 +30,7 @@ define([ controller: 'PlaybookCtrl', templateUrl: '/view/playbook/view', resolve: { - dummy: $couchPotatoProvider.resolve(['controllers/playbook/playbook', - 'controllers/host/hosts', - 'controllers/job/jobs', - 'controllers/task/tasks']), + dummy: $couchPotatoProvider.resolve(['controllers/playbook/playbook']), playbook: function (Playbook, $stateParams, $q, $state) { var deferred = $q.defer(); @@ -51,24 +48,6 @@ define([ } }) - .state('playbook.view', { - url: '', - views: { - tasks: { - templateUrl: '/view/task/tasks', - controller: 'TasksCtrl' - }, - jobs: { - templateUrl: '/view/job/jobs', - controller: 'JobsCtrl' - }, - hosts: { - templateUrl: '/view/host/hosts', - controller: 'HostsCtrl' - } - } - }) - .state('playbook.edit', { url: '/edit', templateUrl: "/view/playbook/add", @@ -83,5 +62,30 @@ define([ } } }) + + .state('playbook.tasks', { + url: '/tasks', + templateUrl: "/view/playbook/tasks", + controller: 'PlaybookTasksCtrl', + resolve: { + dummy: $couchPotatoProvider.resolve(['controllers/playbook/tasks']) + } + }) + .state('playbook.jobs', { + url: '/jobs', + templateUrl: "/view/playbook/jobs", + controller: 'PlaybookJobsCtrl', + resolve: { + dummy: $couchPotatoProvider.resolve(['controllers/playbook/jobs']) + } + }) + .state('playbook.hosts', { + url: '/hosts', + templateUrl: "/view/playbook/hosts", + controller: 'PlaybookHostsCtrl', + resolve: { + dummy: $couchPotatoProvider.resolve(['controllers/playbook/hosts']) + } + }) }) }) \ No newline at end of file diff --git a/ssh_vagrant.sh b/ssh_vagrant.sh deleted file mode 100755 index a19efd1b..00000000 --- a/ssh_vagrant.sh +++ /dev/null @@ -1 +0,0 @@ -vagrant ssh -- -R 27017:localhost:27017 -R 6379:localhost:6379 -R 3000:localhost:3000 From 7d64a0e5ede126d75ef355638a5e1343ebdf8b90 Mon Sep 17 00:00:00 2001 From: Matej Kramny Date: Tue, 24 Mar 2015 17:45:44 +0000 Subject: [PATCH 2/4] Fix editing, bugs after adding a playbook --- lib/views/playbook/add.jade | 9 ++++++--- lib/views/playbook/tasks.jade | 10 +++++++--- lib/views/playbook/view.jade | 3 +-- public/js/controllers/playbook/add.js | 2 +- public/js/routes/playbooks.js | 6 ------ 5 files changed, 15 insertions(+), 15 deletions(-) diff --git a/lib/views/playbook/add.jade b/lib/views/playbook/add.jade index ce3f0a3a..cea93d80 100644 --- a/lib/views/playbook/add.jade +++ b/lib/views/playbook/add.jade @@ -1,7 +1,9 @@ -h1 Add Playbook +h1 + span(ng-if="!playbook.data._id") Add Playbook + span(ng-if="playbook.data._id.length > 0") Edit Playbook .row - .col-md-6 + div(ng-class="{ 'col-md-6': !playbook.data._id, 'col-md-12': playbook.data._id.length > 0 }") .panel.panel-default .panel-body form.form-horizontal(name="playbookForm") @@ -31,5 +33,6 @@ h1 Add Playbook button.btn.btn-success(ng-click="add()" ng-disabled="playbookForm.$invalid") span(ng-if="!playbook.data._id") Add span(ng-if="playbook.data._id.length > 0") Edit - .col-md-6 + a.btn.btn-danger(ng-if="playbook.data._id.length > 0" ng-click="delete()" style="margin-left: 10px;") Delete + .col-md-6(ng-if="!playbook.data._id") p.lead It is recommended you create an identity before creating playbooks. \ No newline at end of file diff --git a/lib/views/playbook/tasks.jade b/lib/views/playbook/tasks.jade index 4ebadcd6..65350dea 100644 --- a/lib/views/playbook/tasks.jade +++ b/lib/views/playbook/tasks.jade @@ -1,7 +1,7 @@ -h1 Tasks +h1(ng-if="tasks.tasks.length") Tasks small(ng-if="status.length > 0" ng-bind="status") -table.table.table-hover +table.table.table-hover(ng-if="tasks.tasks.length") thead tr th Job Name @@ -33,4 +33,8 @@ table.table.table-hover button(data-dismiss="modal").close: span × h4.modal-title Task Output .modal-body - pre: code {{ openTask.data.output }} \ No newline at end of file + pre: code {{ openTask.data.output }} + +h4.text-center.text-muted(ng-if="!tasks.tasks.length" style="margin-top: 15px;") It seems no  + a(ui-sref="playbook.jobs") jobs + |  have been run yet. \ No newline at end of file diff --git a/lib/views/playbook/view.jade b/lib/views/playbook/view.jade index 8e0230c6..e0825d96 100644 --- a/lib/views/playbook/view.jade +++ b/lib/views/playbook/view.jade @@ -10,7 +10,6 @@ mixin menuItem(state, name) +menuItem("playbook.hosts", "Hosts") br ul.nav - li: a(ui-sref="playbook.edit({ playbook_id: playbook.data._id })") Edit - li: a(ng-click="delete()") Delete + li: a(ui-sref="playbook.edit") Edit .col-sm-9.col-lg-10 ui-view \ No newline at end of file diff --git a/public/js/controllers/playbook/add.js b/public/js/controllers/playbook/add.js index f9d464fa..e3606c3e 100644 --- a/public/js/controllers/playbook/add.js +++ b/public/js/controllers/playbook/add.js @@ -18,7 +18,7 @@ define([ $scope.playbook.add() .success(function (data) { playbooks.getPlaybooks(function () { - $state.transitionTo('playbook.view', { + $state.transitionTo('playbook.tasks', { playbook_id: data._id }); }); diff --git a/public/js/routes/playbooks.js b/public/js/routes/playbooks.js index 6e2cbe03..54dde85f 100644 --- a/public/js/routes/playbooks.js +++ b/public/js/routes/playbooks.js @@ -54,12 +54,6 @@ define([ controller: 'EditPlaybookCtrl', resolve: { dummy: $couchPotatoProvider.resolve(['controllers/playbook/edit']) - }, - views: { - tasks: { - templateUrl: '/view/playbook/add', - controller: 'EditPlaybookCtrl' - } } }) From c638774f7adfbca99a40ce992b514a5e8d4f7185 Mon Sep 17 00:00:00 2001 From: Matej Kramny Date: Tue, 24 Mar 2015 21:08:43 +0000 Subject: [PATCH 3/4] Improve readme & Dockerfile --- Dockerfile | 2 ++ README.md | 64 +++++++++++++++++++++++++++++------------------------- 2 files changed, 37 insertions(+), 29 deletions(-) diff --git a/Dockerfile b/Dockerfile index fd56058f..86856438 100644 --- a/Dockerfile +++ b/Dockerfile @@ -5,6 +5,8 @@ ENV NODE_ENV production ADD . /srv/semaphore WORKDIR /srv/semaphore +RUN rm -f node_modules/ + RUN npm install CMD ["node", "/srv/semaphore/bin/semaphore"] diff --git a/README.md b/README.md index a90b818b..4baef2a3 100644 --- a/README.md +++ b/README.md @@ -1,12 +1,10 @@ -semaphore -========= +# semaphore Open Source Alternative to Ansible Tower ![screenshot](public/img/screenshot.png) -Features --------- +## Features The basics of Ansible Tower, but in addition: @@ -17,60 +15,67 @@ The basics of Ansible Tower, but in addition: - [x] Run playbooks against specified hosts - [ ] Multiple Users support -Docker quickstart ------------------ +## Docker quickstart -1. Get Docker -2. Run redis +### Run redis ``` docker run -d \ --name=redisio \ + --restart=always \ -v /var/lib/redisio:/var/lib/redis \ -p 127.0.0.1:6379:6379 \ castawaylabs/redis-docker ``` -3. Run mongodb +### Run mongodb ``` docker run -d \ --name=mongodb \ + --restart=always \ -v /var/lib/mongodb:/var/lib/mongodb \ - -p 127.0.0.1:6379:6379 \ - castawaylabs/mongo-docker + -p 127.0.0.1:27017:27017 \ + castawaylabs/mongodb-docker ``` -4. Run semaphore +### Run semaphore ``` docker run -d \ - --name=semaphroe \ + --name=semaphore \ --restart=always \ --link redisio:redis \ --link mongodb:mongo \ + -e MONGODB_URL="mongodb://mongo/semaphore" \ + -e REDIS_HOST="redis" \ -p 80:80 \ castawaylabs/semaphore ``` -Development steps: +## Development -Install requirements: -- node.js / io.js -- an isolated environment (e.g. Docker / Vagrant) -- ansible -- mongodb & redis +1. Install VirtualBox & Vagrant +2. Run `vagrant plugin install gatling-rsync-auto` +3. Run `vagrant up` to start the vagrant box +4. Run `vagrant gatling-rsync-auto` to synchronise changes from your local machine to vagrant -Initial Login -------------- +### Running semaphore inside vagrant + +1. `vagrant ssh`, `cd /opt/semaphore` +2. `npm install` +3. `bower install` +4. `npm install -g nodemon` +5. `nodemon bin/semaphore` + +## Initial Login ``` Email: 'admin@semaphore.local' Password: 'CastawayLabs' ``` -Environment Variables ---------------------- +## Environment Variables Use these variables to override the config. @@ -85,22 +90,23 @@ Use these variables to override the config. | SMTP_PASS | Mandrill smtp password | | | MONGODB_URL | Mongodb URL | `mongodb://127.0.0.1/semaphore` | -Vision and goals ----------------- +## Vision and goals for v1 - Be able to specify environment information per playbook / per task - Schedule jobs - Email alerts +<<<<<<< HEAD >>>>>>> 1199a52... Update site layout +======= +- Multiple user support +>>>>>>> 7282f8a... Improve readme & Dockerfile -Note to Ansible guys --------------------- +## Note to Ansible guys > Thanks very much for making Ansible, and Ansible Tower. It is a great tool!. Your UI is pretty horrible though, and so we'd be happy if you could learn and use parts of this tool in your Tower. It would be amazing if this could be your `Community Edition` of Ansible Tower. -License -------- +## License MIT \ No newline at end of file From 970f0d4f1018fc411417d0f09ed3081800d0aa87 Mon Sep 17 00:00:00 2001 From: Matej Kramny Date: Wed, 25 Mar 2015 11:06:26 +0000 Subject: [PATCH 4/4] Fix merge conflicts --- README.md | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/README.md b/README.md index 4baef2a3..87f15256 100644 --- a/README.md +++ b/README.md @@ -95,11 +95,7 @@ Use these variables to override the config. - Be able to specify environment information per playbook / per task - Schedule jobs - Email alerts -<<<<<<< HEAD ->>>>>>> 1199a52... Update site layout -======= - Multiple user support ->>>>>>> 7282f8a... Improve readme & Dockerfile ## Note to Ansible guys @@ -109,4 +105,4 @@ It would be amazing if this could be your `Community Edition` of Ansible Tower. ## License -MIT \ No newline at end of file +MIT