minicron 0.3 → 0.4
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/README.md +42 -33
- data/bin/minicron +3 -0
- data/lib/minicron.rb +12 -3
- data/lib/minicron/alert.rb +9 -6
- data/lib/minicron/cli.rb +15 -6
- data/lib/minicron/cli/commands.rb +35 -12
- data/lib/minicron/constants.rb +1 -1
- data/lib/minicron/cron.rb +71 -30
- data/lib/minicron/hub/app.rb +6 -0
- data/lib/minicron/hub/assets/app/components/schedules.js +1 -1
- data/lib/minicron/hub/assets/app/controllers/hosts.js +6 -2
- data/lib/minicron/hub/assets/app/controllers/jobs.js +5 -2
- data/lib/minicron/hub/assets/app/controllers/schedules.js +15 -13
- data/lib/minicron/hub/assets/app/models/host.js +1 -0
- data/lib/minicron/hub/assets/app/models/job.js +1 -0
- data/lib/minicron/hub/controllers/api/executions.rb +0 -1
- data/lib/minicron/hub/controllers/api/hosts.rb +12 -13
- data/lib/minicron/hub/controllers/api/job_execution_outputs.rb +0 -1
- data/lib/minicron/hub/controllers/api/jobs.rb +5 -3
- data/lib/minicron/hub/controllers/api/schedule.rb +3 -1
- data/lib/minicron/hub/db/schema.rb +8 -6
- data/lib/minicron/hub/db/schema.sql +4 -2
- data/lib/minicron/hub/views/handlebars/hosts.erb +18 -0
- data/lib/minicron/hub/views/handlebars/jobs.erb +18 -0
- data/lib/minicron/monitor.rb +14 -12
- data/lib/minicron/transport.rb +0 -1
- data/lib/minicron/transport/client.rb +19 -11
- data/lib/minicron/transport/faye/client.rb +16 -2
- data/lib/minicron/transport/faye/extensions/job_handler.rb +10 -4
- data/lib/minicron/transport/faye/server.rb +5 -4
- data/lib/minicron/transport/server.rb +9 -4
- data/lib/minicron/transport/ssh.rb +5 -4
- data/spec/minicron/alert/pagerduty_spec.rb +1 -0
- data/spec/minicron/alert/sms_spec.rb +1 -0
- data/spec/minicron/cli_spec.rb +1 -0
- data/spec/minicron/transport/client_spec.rb +1 -0
- data/spec/minicron/transport/faye/client_spec.rb +1 -0
- data/spec/minicron/transport/server_spec.rb +1 -0
- data/spec/minicron/transport_spec.rb +1 -0
- data/spec/minicron_spec.rb +6 -0
- metadata +88 -88
data/lib/minicron/hub/app.rb
CHANGED
@@ -23,6 +23,10 @@ module Minicron::Hub
|
|
23
23
|
# Disable internal middleware for presenting errors
|
24
24
|
# as useful HTML pages
|
25
25
|
set :show_exceptions, false
|
26
|
+
|
27
|
+
# Used to enable asset compression, currently nothing else
|
28
|
+
# relies on this
|
29
|
+
set :environment, :production
|
26
30
|
end
|
27
31
|
|
28
32
|
# Configure how we server assets
|
@@ -32,6 +36,8 @@ module Minicron::Hub
|
|
32
36
|
serve '/fonts', :from => 'assets/fonts'
|
33
37
|
serve '/app', :from => 'assets/app'
|
34
38
|
|
39
|
+
js_compression :simple
|
40
|
+
|
35
41
|
# Set up the application css
|
36
42
|
css :app, '/css/all.css', [
|
37
43
|
'/css/bootswatch.min.css',
|
@@ -30,8 +30,10 @@
|
|
30
30
|
// TODO: make this use a bootstrap model as a component
|
31
31
|
var results = 'Test Results\n\n';
|
32
32
|
results += 'connect: ' + data.connect + '\n';
|
33
|
-
results += '
|
34
|
-
results += '
|
33
|
+
results += '/etc writeable: ' + data.etc.write + '\n';
|
34
|
+
results += '/etc executable: ' + data.etc.execute + '\n';
|
35
|
+
results += 'crontab readable: ' + data.crontab.read + '\n';
|
36
|
+
results += 'crontab writeable: ' + data.crontab.write;
|
35
37
|
|
36
38
|
window.alert(results);
|
37
39
|
} else {
|
@@ -73,6 +75,7 @@
|
|
73
75
|
host = this.store.createRecord('host', {
|
74
76
|
name: this.get('name'),
|
75
77
|
fqdn: this.get('fqdn'),
|
78
|
+
user: this.get('user'),
|
76
79
|
host: this.get('host'),
|
77
80
|
port: this.get('port'),
|
78
81
|
public_key: this.get('public_key')
|
@@ -101,6 +104,7 @@
|
|
101
104
|
id: this.get('id'),
|
102
105
|
name: this.get('name'),
|
103
106
|
fqdn: this.get('fqdn'),
|
107
|
+
user: this.get('user'),
|
104
108
|
host: this.get('host'),
|
105
109
|
port: this.get('port'),
|
106
110
|
public_key: this.get('public_key')
|
@@ -32,13 +32,15 @@
|
|
32
32
|
Minicron.JobsNewController = Ember.ObjectController.extend({
|
33
33
|
save_button: 'Save',
|
34
34
|
job_name: null,
|
35
|
+
job_user: null,
|
35
36
|
job_command: null,
|
36
37
|
actions: {
|
37
38
|
save: function() {
|
38
39
|
var self = this,
|
39
40
|
job = this.store.createRecord('job', {
|
40
41
|
name: this.get('job_name'),
|
41
|
-
|
42
|
+
user: this.get('job_user'),
|
43
|
+
command: this.get('job_command')
|
42
44
|
});
|
43
45
|
// Let the user know the job is being saved
|
44
46
|
this.set('save_button', 'Saving..');
|
@@ -86,7 +88,8 @@
|
|
86
88
|
var self = this,
|
87
89
|
job = this.store.push('job', {
|
88
90
|
id: this.get('id'),
|
89
|
-
name: this.get('name')
|
91
|
+
name: this.get('name'),
|
92
|
+
user: this.get('user')
|
90
93
|
});
|
91
94
|
|
92
95
|
job.save().then(function(job) {
|
@@ -5,18 +5,20 @@
|
|
5
5
|
var confirmation = "Are you sure want to delete this schedule? It will be removed from the host crontab also!\n";
|
6
6
|
var job_id = schedule.get('job.id');
|
7
7
|
|
8
|
-
|
8
|
+
if (window.confirm(confirmation)) {
|
9
|
+
schedule.deleteRecord();
|
9
10
|
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
11
|
+
schedule.save().then(function() {
|
12
|
+
// This is needed to reload all the relationships correctly after a delete
|
13
|
+
// TODO: do this in a nicer way
|
14
|
+
window.location.hash = '/jobs/' + job_id;
|
15
|
+
window.location.reload();
|
16
|
+
}, function(response) {
|
17
|
+
schedule.rollback();
|
18
|
+
console.log(response);
|
19
|
+
window.prompt('Error deleting schedule, reason:', response.responseJSON.error);
|
20
|
+
});
|
21
|
+
}
|
20
22
|
}
|
21
23
|
|
22
24
|
Minicron.SchedulesNewController = Ember.ObjectController.extend({
|
@@ -38,8 +40,8 @@
|
|
38
40
|
});
|
39
41
|
});
|
40
42
|
},
|
41
|
-
cancel: function(
|
42
|
-
this.transitionToRoute('job',
|
43
|
+
cancel: function(job_id) {
|
44
|
+
this.transitionToRoute('job', job_id);
|
43
45
|
}
|
44
46
|
}
|
45
47
|
});
|
@@ -2,7 +2,6 @@ require 'minicron/transport/ssh'
|
|
2
2
|
|
3
3
|
class Minicron::Hub::App
|
4
4
|
# Get all hosts that a job
|
5
|
-
# TODO: Add offset/limit
|
6
5
|
get '/api/hosts' do
|
7
6
|
content_type :json
|
8
7
|
hosts = Minicron::Hub::Host.all.includes(:jobs).order(:id => :asc)
|
@@ -26,10 +25,14 @@ class Minicron::Hub::App
|
|
26
25
|
# Default the value of the port
|
27
26
|
request_body['host']['port'] ||= 22
|
28
27
|
|
28
|
+
# Default the value of the user
|
29
|
+
request_body['host']['user'] ||= 'root'
|
30
|
+
|
29
31
|
# Try and save the new host
|
30
32
|
host = Minicron::Hub::Host.create(
|
31
33
|
:name => request_body['host']['name'],
|
32
34
|
:fqdn => request_body['host']['fqdn'],
|
35
|
+
:user => request_body['host']['user'],
|
33
36
|
:host => request_body['host']['host'],
|
34
37
|
:port => request_body['host']['port']
|
35
38
|
)
|
@@ -66,6 +69,7 @@ class Minicron::Hub::App
|
|
66
69
|
# Update its data
|
67
70
|
host.name = request_body['host']['name']
|
68
71
|
host.fqdn = request_body['host']['fqdn']
|
72
|
+
host.user = request_body['host']['user']
|
69
73
|
host.host = request_body['host']['host']
|
70
74
|
host.port = request_body['host']['port']
|
71
75
|
|
@@ -93,6 +97,7 @@ class Minicron::Hub::App
|
|
93
97
|
|
94
98
|
# Get an ssh instance and open a connection
|
95
99
|
ssh = Minicron::Transport::SSH.new(
|
100
|
+
:user => host.user,
|
96
101
|
:host => host.host,
|
97
102
|
:port => host.port,
|
98
103
|
:private_key => "~/.ssh/minicron_host_#{host.id}_rsa"
|
@@ -131,29 +136,23 @@ class Minicron::Hub::App
|
|
131
136
|
|
132
137
|
# Set up the ssh instance
|
133
138
|
ssh = Minicron::Transport::SSH.new(
|
139
|
+
:user => host.user,
|
134
140
|
:host => host.host,
|
135
141
|
:port => host.port,
|
136
142
|
:private_key => "~/.ssh/minicron_host_#{host.id}_rsa"
|
137
143
|
)
|
138
144
|
|
139
|
-
#
|
140
|
-
|
141
|
-
|
142
|
-
# Check if the crontab is readable
|
143
|
-
read = conn.exec!('test -r /etc/crontab && echo "y" || echo "n"').strip
|
145
|
+
# Get an instance of the cron class
|
146
|
+
cron = Minicron::Cron.new(ssh)
|
144
147
|
|
145
|
-
#
|
146
|
-
|
148
|
+
# Test the SSH connection
|
149
|
+
test = cron.test_host_permissions
|
147
150
|
|
148
151
|
# Tidy up
|
149
152
|
ssh.close
|
150
153
|
|
151
154
|
# Return the test results as JSON
|
152
|
-
|
153
|
-
:connect => true,
|
154
|
-
:read => read == 'y',
|
155
|
-
:write => write == 'y'
|
156
|
-
}.to_json
|
155
|
+
test.to_json
|
157
156
|
rescue Exception => e
|
158
157
|
status 422
|
159
158
|
{ :connect => false, :error => e.message }.to_json
|
@@ -2,7 +2,6 @@ require 'minicron/transport'
|
|
2
2
|
|
3
3
|
class Minicron::Hub::App
|
4
4
|
# Get all jobs
|
5
|
-
# TODO: Add offset/limit
|
6
5
|
get '/api/jobs' do
|
7
6
|
content_type :json
|
8
7
|
|
@@ -11,7 +10,7 @@ class Minicron::Hub::App
|
|
11
10
|
.where(:job_hash => params[:job_hash])
|
12
11
|
else
|
13
12
|
jobs = Minicron::Hub::Job.all.order(:created_at => :desc)
|
14
|
-
|
13
|
+
.includes(:host, :schedules, :executions => :job_execution_outputs)
|
15
14
|
end
|
16
15
|
|
17
16
|
Minicron::Hub::JobSerializer.new(jobs).serialize.to_json
|
@@ -39,6 +38,7 @@ class Minicron::Hub::App
|
|
39
38
|
job = Minicron::Hub::Job.create(
|
40
39
|
:job_hash => Minicron::Transport.get_job_hash(request_body['job']['command'], host.fqdn),
|
41
40
|
:name => request_body['job']['name'],
|
41
|
+
:user => request_body['job']['user'],
|
42
42
|
:command => request_body['job']['command'],
|
43
43
|
:host_id => host.id
|
44
44
|
)
|
@@ -65,8 +65,9 @@ class Minicron::Hub::App
|
|
65
65
|
job = Minicron::Hub::Job.includes(:host, :schedules, :executions => :job_execution_outputs)
|
66
66
|
.find(params[:id])
|
67
67
|
|
68
|
-
# Update the name
|
68
|
+
# Update the name and user
|
69
69
|
job.name = request_body['job']['name']
|
70
|
+
job.user = request_body['job']['user']
|
70
71
|
|
71
72
|
job.save!
|
72
73
|
|
@@ -92,6 +93,7 @@ class Minicron::Hub::App
|
|
92
93
|
|
93
94
|
# Get an ssh instance
|
94
95
|
ssh = Minicron::Transport::SSH.new(
|
96
|
+
:user => job.host.user,
|
95
97
|
:host => job.host.host,
|
96
98
|
:port => job.host.port,
|
97
99
|
:private_key => "~/.ssh/minicron_host_#{job.host.id}_rsa"
|
@@ -3,7 +3,6 @@ require 'minicron/cron'
|
|
3
3
|
|
4
4
|
class Minicron::Hub::App
|
5
5
|
# Get all schedules
|
6
|
-
# TODO: Add offset/limit
|
7
6
|
get '/api/schedules' do
|
8
7
|
content_type :json
|
9
8
|
|
@@ -65,6 +64,7 @@ class Minicron::Hub::App
|
|
65
64
|
|
66
65
|
# Get an ssh instance
|
67
66
|
ssh = Minicron::Transport::SSH.new(
|
67
|
+
:user => job.host.user,
|
68
68
|
:host => job.host.host,
|
69
69
|
:port => job.host.port,
|
70
70
|
:private_key => "~/.ssh/minicron_host_#{job.host.id}_rsa"
|
@@ -106,6 +106,7 @@ class Minicron::Hub::App
|
|
106
106
|
|
107
107
|
# Get an ssh instance
|
108
108
|
ssh = Minicron::Transport::SSH.new(
|
109
|
+
:user => schedule.job.host.user,
|
109
110
|
:host => schedule.job.host.host,
|
110
111
|
:port => schedule.job.host.port,
|
111
112
|
:private_key => "~/.ssh/minicron_host_#{schedule.job.host.id}_rsa"
|
@@ -158,6 +159,7 @@ class Minicron::Hub::App
|
|
158
159
|
|
159
160
|
# Get an ssh instance
|
160
161
|
ssh = Minicron::Transport::SSH.new(
|
162
|
+
:user => schedule.job.host.user,
|
161
163
|
:host => schedule.job.host.host,
|
162
164
|
:port => schedule.job.host.port,
|
163
165
|
:private_key => "~/.ssh/minicron_host_#{schedule.job.host.id}_rsa"
|
@@ -42,12 +42,13 @@ ActiveRecord::Schema.define(version: 0) do
|
|
42
42
|
|
43
43
|
create_table "hosts", force: true do |t|
|
44
44
|
t.string "name"
|
45
|
-
t.string "fqdn",
|
46
|
-
t.string "
|
47
|
-
t.
|
45
|
+
t.string "fqdn", default: "", null: false
|
46
|
+
t.string "user", limit: 32, default: "", null: false
|
47
|
+
t.string "host", default: "", null: false
|
48
|
+
t.integer "port", null: false
|
48
49
|
t.text "public_key"
|
49
|
-
t.datetime "created_at",
|
50
|
-
t.datetime "updated_at",
|
50
|
+
t.datetime "created_at", null: false
|
51
|
+
t.datetime "updated_at", null: false
|
51
52
|
end
|
52
53
|
|
53
54
|
add_index "hosts", ["fqdn"], name: "hostname", using: :btree
|
@@ -63,10 +64,11 @@ ActiveRecord::Schema.define(version: 0) do
|
|
63
64
|
add_index "job_execution_outputs", ["seq"], name: "seq", using: :btree
|
64
65
|
|
65
66
|
create_table "jobs", force: true do |t|
|
67
|
+
t.integer "host_id", null: false
|
66
68
|
t.string "job_hash", limit: 32, default: "", null: false
|
67
69
|
t.string "name"
|
70
|
+
t.string "user", limit: 32, null: false
|
68
71
|
t.text "command", null: false
|
69
|
-
t.integer "host_id", null: false
|
70
72
|
t.datetime "created_at", null: false
|
71
73
|
t.datetime "updated_at", null: false
|
72
74
|
end
|
@@ -7,7 +7,7 @@
|
|
7
7
|
#
|
8
8
|
# Host: 127.0.0.1 (MySQL 5.6.16)
|
9
9
|
# Database: minicron
|
10
|
-
# Generation Time: 2014-04-
|
10
|
+
# Generation Time: 2014-04-07 17:06:03 +0000
|
11
11
|
# ************************************************************
|
12
12
|
|
13
13
|
|
@@ -73,6 +73,7 @@ CREATE TABLE `hosts` (
|
|
73
73
|
`id` int(11) NOT NULL AUTO_INCREMENT,
|
74
74
|
`name` varchar(255) DEFAULT NULL,
|
75
75
|
`fqdn` varchar(255) NOT NULL DEFAULT '',
|
76
|
+
`user` varchar(32) NOT NULL DEFAULT '',
|
76
77
|
`host` varchar(255) NOT NULL DEFAULT '',
|
77
78
|
`port` int(11) NOT NULL,
|
78
79
|
`public_key` text,
|
@@ -109,10 +110,11 @@ DROP TABLE IF EXISTS `jobs`;
|
|
109
110
|
|
110
111
|
CREATE TABLE `jobs` (
|
111
112
|
`id` int(11) NOT NULL AUTO_INCREMENT,
|
113
|
+
`host_id` int(11) NOT NULL,
|
112
114
|
`job_hash` varchar(32) NOT NULL DEFAULT '',
|
113
115
|
`name` varchar(255) DEFAULT NULL,
|
116
|
+
`user` varchar(32) NOT NULL,
|
114
117
|
`command` text NOT NULL,
|
115
|
-
`host_id` int(11) NOT NULL,
|
116
118
|
`created_at` datetime NOT NULL,
|
117
119
|
`updated_at` datetime NOT NULL,
|
118
120
|
PRIMARY KEY (`id`),
|
@@ -55,6 +55,12 @@
|
|
55
55
|
<div class="form-control form-control-view">{{fqdn}}</div>
|
56
56
|
</div>
|
57
57
|
</div>
|
58
|
+
<div class="form-group">
|
59
|
+
<label class="col-sm-2 control-label">User</label>
|
60
|
+
<div class="col-sm-10">
|
61
|
+
<div class="form-control form-control-view">{{user}}</div>
|
62
|
+
</div>
|
63
|
+
</div>
|
58
64
|
<div class="form-group">
|
59
65
|
<label class="col-sm-2 control-label">Host</label>
|
60
66
|
<div class="col-sm-10">
|
@@ -141,6 +147,12 @@
|
|
141
147
|
{{input value=fqdn type="text" class="form-control" placeholder="The machine fully qualified domain name e.g 'server1.host.com'"}}
|
142
148
|
</div>
|
143
149
|
</div>
|
150
|
+
<div class="form-group">
|
151
|
+
<label class="col-sm-2 control-label">User</label>
|
152
|
+
<div class="col-sm-10">
|
153
|
+
{{input value=user type="text" class="form-control" placeholder="The user to connect to the host as"}}
|
154
|
+
</div>
|
155
|
+
</div>
|
144
156
|
<div class="form-group">
|
145
157
|
<label class="col-sm-2 control-label">Host</label>
|
146
158
|
<div class="col-sm-10">
|
@@ -183,6 +195,12 @@
|
|
183
195
|
{{input value=fqdn type="text" class="form-control" placeholder="The machine fully qualified domain name e.g 'server1.host.com'"}}
|
184
196
|
</div>
|
185
197
|
</div>
|
198
|
+
<div class="form-group">
|
199
|
+
<label class="col-sm-2 control-label">User</label>
|
200
|
+
<div class="col-sm-10">
|
201
|
+
{{input value=user type="text" class="form-control" placeholder="The user to connect to the host as"}}
|
202
|
+
</div>
|
203
|
+
</div>
|
186
204
|
<div class="form-group">
|
187
205
|
<label class="col-sm-2 control-label">Host</label>
|
188
206
|
<div class="col-sm-10">
|
@@ -48,6 +48,12 @@
|
|
48
48
|
<div class="form-control form-control-view">{{name}}</div>
|
49
49
|
</div>
|
50
50
|
</div>
|
51
|
+
<div class="form-group">
|
52
|
+
<label class="col-sm-2 control-label">User</label>
|
53
|
+
<div class="col-sm-10">
|
54
|
+
<div class="form-control form-control-view">{{user}}</div>
|
55
|
+
</div>
|
56
|
+
</div>
|
51
57
|
<div class="form-group">
|
52
58
|
<label class="col-sm-2 control-label">Command</label>
|
53
59
|
<div class="col-sm-10">
|
@@ -151,6 +157,12 @@
|
|
151
157
|
{{input value=job_name type="text" class="form-control" placeholder="A nickname for the job"}}
|
152
158
|
</div>
|
153
159
|
</div>
|
160
|
+
<div class="form-group">
|
161
|
+
<label class="col-sm-2 control-label">User</label>
|
162
|
+
<div class="col-sm-10">
|
163
|
+
{{input value=job_user type="text" class="form-control" placeholder="What user should the job be run as"}}
|
164
|
+
</div>
|
165
|
+
</div>
|
154
166
|
<div class="form-group">
|
155
167
|
<label class="col-sm-2 control-label">Command</label>
|
156
168
|
<div class="col-sm-10">
|
@@ -193,6 +205,12 @@
|
|
193
205
|
{{input value=name type="text" class="form-control" placeholder="A nickname for the job"}}
|
194
206
|
</div>
|
195
207
|
</div>
|
208
|
+
<div class="form-group">
|
209
|
+
<label class="col-sm-2 control-label">User</label>
|
210
|
+
<div class="col-sm-10">
|
211
|
+
{{input value=user type="text" class="form-control" placeholder="What user should the job be run as"}}
|
212
|
+
</div>
|
213
|
+
</div>
|
196
214
|
<div class="form-group">
|
197
215
|
<div class="col-sm-offset-2 col-sm-10">
|
198
216
|
<button type="submit" class="btn btn-success">Save</button>
|