minicron 0.3 → 0.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- 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>
|