kit 0.3.0 → 1.0.0
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.
- data/.gitignore +18 -0
- data/.rspec +0 -0
- data/.yardopts +2 -0
- data/CHANGELOG.rdoc +10 -1
- data/Gemfile +2 -0
- data/LICENSE.txt +22 -0
- data/README.rdoc +84 -19
- data/Rakefile +21 -0
- data/kit.gemspec +27 -0
- data/lib/kit.rb +67 -170
- data/lib/kit/db_support.rb +71 -0
- data/lib/kit/models/bit.rb +34 -0
- data/lib/kit/models/group.rb +5 -0
- data/lib/kit/models/permission.rb +6 -0
- data/lib/kit/models/user.rb +6 -0
- data/lib/kit/rake/admin.rb +3 -0
- data/lib/kit/rake/admin/database.rb +28 -0
- data/lib/kit/rake/admin/make.rb +19 -0
- data/lib/kit/rake/admin/manage.rb +8 -0
- data/lib/kit/version.rb +4 -0
- data/spec/bit_spec.rb +57 -0
- data/spec/kit_db_support_spec.rb +110 -0
- data/spec/kit_spec.rb +56 -0
- metadata +108 -19
- data/LICENCE.txt +0 -21
- data/lib/kit/bit.rb +0 -173
- data/lib/kit/db_sqlite3.rb +0 -212
data/.gitignore
ADDED
data/.rspec
ADDED
File without changes
|
data/.yardopts
ADDED
data/CHANGELOG.rdoc
CHANGED
@@ -1,10 +1,19 @@
|
|
1
1
|
= Kit ChangeLog
|
2
2
|
|
3
|
+
== 1.0.0
|
4
|
+
|
5
|
+
=== Breaking changes
|
6
|
+
|
7
|
+
Kit has been completely rewritten using Active Record.
|
8
|
+
See the {README}[http://rubydoc.info/gems/kit/frames] and {wiki}[https://github.com/razor-x/kit/wiki] for new documentation.
|
9
|
+
|
3
10
|
== 0.3.0
|
4
11
|
|
5
12
|
=== Breaking changes
|
6
13
|
|
7
|
-
* Kits are now expected to have an actions.rb file and specific global action files in the actions directory.
|
14
|
+
* Kits are now expected to have an actions.rb file and specific global action files in the actions directory.
|
15
|
+
This allows one to write methods available to all actions and methods available to specific actions (helps with DRY).
|
16
|
+
See the skeleton kit for the updated structure.
|
8
17
|
|
9
18
|
=== Enhancements
|
10
19
|
|
data/Gemfile
ADDED
data/LICENSE.txt
ADDED
@@ -0,0 +1,22 @@
|
|
1
|
+
Copyright (c) 2012 Evan Boyd Sosenko
|
2
|
+
|
3
|
+
MIT License
|
4
|
+
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
6
|
+
a copy of this software and associated documentation files (the
|
7
|
+
"Software"), to deal in the Software without restriction, including
|
8
|
+
without limitation the rights to use, copy, modify, merge, publish,
|
9
|
+
distribute, sublicense, and/or sell copies of the Software, and to
|
10
|
+
permit persons to whom the Software is furnished to do so, subject to
|
11
|
+
the following conditions:
|
12
|
+
|
13
|
+
The above copyright notice and this permission notice shall be
|
14
|
+
included in all copies or substantial portions of the Software.
|
15
|
+
|
16
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
17
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
18
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
19
|
+
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
20
|
+
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
21
|
+
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
22
|
+
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/README.rdoc
CHANGED
@@ -1,46 +1,111 @@
|
|
1
1
|
= Kit
|
2
2
|
|
3
|
+
<b>A framework for making simple management tools called kits.</b>
|
4
|
+
|
5
|
+
<em>Write your shell scripts in beautiful Ruby, put them in a kit, and keep them DRY.</em>
|
6
|
+
|
3
7
|
== What is Kit?
|
4
8
|
|
5
|
-
Kit is
|
9
|
+
Kit is written using Active Record, so if you have worked with Rails, then Kit should feel familiar.
|
6
10
|
|
7
|
-
|
11
|
+
Each kit keeps track of a set of objects (the bits) and info about them.
|
12
|
+
Bits know how to preform actions you create for them,
|
13
|
+
and can be put into groups so each type of bit can have its own set of actions.
|
14
|
+
Users and permissions can be set to control access to bits and actions.
|
8
15
|
|
9
|
-
To use Kit, you fist need a kit. You can download a {pre-build kit}[https://github.com/razor-x/kit/wiki/Pre-built-kits] or {build your own kit}[https://github.com/razor-x/kit/wiki/Building-your-own-kit]. Once you have a kit, create a new kit object with
|
10
16
|
|
11
|
-
|
17
|
+
Kit supports a robust action queue though {Delayed_job}[https://github.com/tobi/delayed_job].
|
18
|
+
One process can be responsible for queuing tasks and another for running them.
|
12
19
|
|
13
|
-
|
20
|
+
=== Example use scenario
|
14
21
|
|
15
|
-
|
16
|
-
k.add_bit bit
|
22
|
+
What can you use kit for? Here is an example a web server admin might be familiar with.
|
17
23
|
|
18
|
-
|
19
|
-
|
20
|
-
|
24
|
+
Say you are running Apache with multiple virtual hosts (vhosts).
|
25
|
+
You are constantly adding new domain names, updating their configurations, etc.
|
26
|
+
Here is how a Kit could manage the vhosts.
|
21
27
|
|
22
|
-
|
28
|
+
* Each vhost is a bit.
|
29
|
+
* Actions might look like
|
23
30
|
|
24
|
-
|
31
|
+
vhost.create #=> set up directory structure
|
32
|
+
vhost.generate_apache_config #=> generate new apache config files from ERB template
|
33
|
+
vhost.online #=> make website accessible
|
34
|
+
vhost.offline #=> set a static 'site is down' page
|
35
|
+
vhost.destroy #=> remove all trace of the vhost
|
36
|
+
|
37
|
+
* By grouping the vhosts, each action can depend on the type of web application the vhost will be running.
|
38
|
+
* Kit can store metadata about the vhosts which you can use when defining actions.
|
25
39
|
|
26
40
|
== Installation
|
27
41
|
|
28
|
-
|
42
|
+
Add this line to your application's Gemfile:
|
43
|
+
|
44
|
+
gem 'kit'
|
45
|
+
|
46
|
+
And then execute:
|
47
|
+
|
48
|
+
$ bundle
|
49
|
+
|
50
|
+
Or install it yourself as:
|
51
|
+
|
52
|
+
$ gem install kit
|
53
|
+
|
54
|
+
== Getting started with kit
|
55
|
+
|
56
|
+
=== Documentation
|
57
|
+
|
58
|
+
* {Full source documentation}[rubydoc.info/gems/kit/frames] is hosted on the {gem page}[https://rubygems.org/gems/kit].
|
59
|
+
* A {comprehensive wiki}[https://github.com/razor-x/kit/wiki] is available on github.
|
60
|
+
|
61
|
+
=== Kit basics
|
62
|
+
|
63
|
+
To use Kit, you will need a kit. You can either
|
64
|
+
* Download a {community built kit}[https://github.com/razor-x/kit/wiki/Community-built-kits].
|
65
|
+
* {Build your own kit}[https://github.com/razor-x/kit/wiki/Building-your-own-kit].
|
66
|
+
If you skipped the above links and just want to get started, run
|
29
67
|
|
30
|
-
|
68
|
+
$ mkdir my_kit && cd my_kit && git init && git pull git://github.com/razor-x/kits_skeleton.git
|
31
69
|
|
32
|
-
|
70
|
+
Once you have a kit, navigate to the root directory and run
|
71
|
+
|
72
|
+
$ rake db:migrate
|
73
|
+
|
74
|
+
This will set up the database.
|
75
|
+
Create an action by adding a method to the +KitActionsDefault+ module located in +actions/default.rb+.
|
76
|
+
|
77
|
+
Open the kit
|
78
|
+
|
79
|
+
require 'kit'
|
80
|
+
Kit.open 'config.yml'
|
81
|
+
|
82
|
+
and make a new bit.
|
83
|
+
|
84
|
+
Kit::Bit.create :name => 'lilac'
|
85
|
+
|
86
|
+
Now you can call the action with
|
87
|
+
|
88
|
+
Kit::Bit.find_by_name('lilac').plant_seeds
|
89
|
+
|
90
|
+
If you got this far, refer to the documentation listed above for more examples of what kit can do.
|
33
91
|
|
34
92
|
== Development
|
35
93
|
|
36
94
|
=== Source Repository
|
37
95
|
|
38
|
-
Kit is currently hosted at github.
|
39
|
-
|
96
|
+
The {Kit source}[https://github.com/razor-x/kit] is currently hosted at github.
|
97
|
+
To clone the project run
|
98
|
+
|
99
|
+
$ git clone git://github.com/razor-x/kit.git
|
100
|
+
|
101
|
+
After cloning, you can run +yard+ to generate documentation for the source
|
102
|
+
|
103
|
+
$ cd kit
|
104
|
+
$ yard
|
40
105
|
|
41
|
-
|
106
|
+
You will also need to set up the test_kit to run specs. Do this with
|
42
107
|
|
43
|
-
|
108
|
+
$ rake develop:prepare
|
44
109
|
|
45
110
|
== License
|
46
111
|
|
data/Rakefile
ADDED
@@ -0,0 +1,21 @@
|
|
1
|
+
#!/usr/bin/env rake
|
2
|
+
require 'bundler/gem_tasks'
|
3
|
+
require 'git'
|
4
|
+
|
5
|
+
namespace 'develop' do
|
6
|
+
|
7
|
+
test_kit = File.expand_path '../test_kit', __FILE__
|
8
|
+
|
9
|
+
task :prepare do |t|
|
10
|
+
puts 'Test kit exists, no need to clone it.' if File.exists? test_kit
|
11
|
+
Git.clone 'git://github.com/razor-x/kits_skeleton.git', test_kit unless File.exists? test_kit
|
12
|
+
end
|
13
|
+
|
14
|
+
task :update => [ :prepare ] do |t|
|
15
|
+
Git.open(test_kit).pull
|
16
|
+
end
|
17
|
+
|
18
|
+
task :reset => [ :prepare, :update ] do |t|
|
19
|
+
Git.open(test_kit).reset_hard('master')
|
20
|
+
end
|
21
|
+
end
|
data/kit.gemspec
ADDED
@@ -0,0 +1,27 @@
|
|
1
|
+
# -*- encoding: utf-8 -*-
|
2
|
+
require File.expand_path( '../lib/kit/version', __FILE__)
|
3
|
+
|
4
|
+
Gem::Specification.new do |gem|
|
5
|
+
gem.authors = ['Evan Boyd Sosenko']
|
6
|
+
gem.email = ['razorx@evansosenko.com']
|
7
|
+
gem.description = %q{Extendable tool to manage site development and more.}
|
8
|
+
gem.summary = %q{Kit is a framework for making simple management tools called kits.}
|
9
|
+
gem.homepage = "http://evansosenko.com"
|
10
|
+
gem.license = 'MIT'
|
11
|
+
|
12
|
+
gem.files = `git ls-files`.split($\)
|
13
|
+
gem.executables = gem.files.grep(%r{^bin/}).map{ |f| File.basename(f) }
|
14
|
+
gem.test_files = gem.files.grep(%r{^(test|spec|features)/})
|
15
|
+
gem.name = 'kit'
|
16
|
+
gem.require_paths = ['lib']
|
17
|
+
gem.platform = Gem::Platform::RUBY
|
18
|
+
gem.version = Kit::VERSION
|
19
|
+
|
20
|
+
gem.add_dependency 'activerecord'
|
21
|
+
gem.add_dependency 'rake'
|
22
|
+
|
23
|
+
gem.add_development_dependency 'sqlite3'
|
24
|
+
gem.add_development_dependency 'rspec'
|
25
|
+
gem.add_development_dependency 'git'
|
26
|
+
|
27
|
+
end
|
data/lib/kit.rb
CHANGED
@@ -1,175 +1,72 @@
|
|
1
|
-
require '
|
1
|
+
require 'active_record'
|
2
|
+
require 'sqlite3'
|
2
3
|
|
3
|
-
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
# Raised when an action is specified that is not in the defined actions for the kit.
|
11
|
-
class NoAction < RuntimeError
|
12
|
-
end
|
13
|
-
|
14
|
-
# Loads the settings for the kit.
|
15
|
-
# @param [String, Hash] config path to kit config file or hash of kit settings
|
16
|
-
def initialize config
|
17
|
-
# Load the config and merge with the default config.
|
18
|
-
config = load_config_file config if File.exists? config
|
19
|
-
|
20
|
-
fail "No path to kit set" unless config[:kits_path]
|
21
|
-
|
22
|
-
@@kit_path = config[:kits_path]
|
23
|
-
defaults = YAML.load File.read @@kit_path + "/config.yml"
|
24
|
-
config = defaults.merge config
|
25
|
-
|
26
|
-
# Load backend for selected database type.
|
27
|
-
load 'kit/db_sqlite3.rb' if config[:db_backend] == :sqlite3
|
28
|
-
|
29
|
-
# Load class files for the kit
|
30
|
-
begin
|
31
|
-
load @@kit_path + "/bit.rb"
|
32
|
-
load @@kit_path + "/kit.rb"
|
33
|
-
load @@kit_path + "/actions.rb"
|
34
|
-
rescue LoadError
|
35
|
-
end
|
36
|
-
|
37
|
-
# Set the class variables.
|
38
|
-
@@info = config[:info]
|
39
|
-
@@unique = config[:unique]
|
40
|
-
@@actions = config[:actions]
|
41
|
-
@@status_types = [ :pending, :completed, :failed, :running ]
|
42
|
-
@@db = Backend.new config[:db_config]
|
43
|
-
|
44
|
-
# Run initialization specific to the kit.
|
45
|
-
begin
|
46
|
-
self.kit_initialize
|
47
|
-
rescue NoMethodError
|
48
|
-
end
|
49
|
-
end
|
50
|
-
|
51
|
-
# Kit related methods.
|
52
|
-
|
53
|
-
# @return [Hash] names of actions defined for this kit
|
54
|
-
def action_types
|
55
|
-
@@actions.keys
|
56
|
-
end
|
57
|
-
|
58
|
-
# @return [Array] names of task status types defined for this kit
|
59
|
-
def status_types
|
60
|
-
@@status_types
|
61
|
-
end
|
62
|
-
|
63
|
-
# Deletes the kit's databases.
|
64
|
-
def delete_dbs
|
65
|
-
@@db.delete
|
66
|
-
end
|
4
|
+
require 'kit/version'
|
5
|
+
require 'kit/db_support'
|
6
|
+
require 'kit/models/bit'
|
7
|
+
require 'kit/models/group'
|
8
|
+
require 'kit/models/user'
|
9
|
+
require 'kit/models/permission'
|
67
10
|
|
68
|
-
|
69
|
-
|
70
|
-
# Creates bit object if it is unique enough.
|
71
|
-
# @param [Hash] info requested initial properties of the bit
|
72
|
-
# @return [Bit, nil] the new bit or nil if too similar to a bit that already exists
|
73
|
-
def add_bit info
|
74
|
-
begin
|
75
|
-
Bit.new info
|
76
|
-
rescue Bit::DuplicateElement
|
77
|
-
nil
|
78
|
-
end
|
79
|
-
end
|
80
|
-
|
81
|
-
# Gets a bit that matches id or info.
|
82
|
-
# @param [Integer, Hash] bit id or hash of info unique enough to identify a bit
|
83
|
-
# @return [Bit, nil] the Bit or nil if no unique bit could be found
|
84
|
-
def get_bit info
|
85
|
-
begin
|
86
|
-
if info.is_a? Integer
|
87
|
-
Bit.new info
|
88
|
-
elsif info.is_a? Hash
|
89
|
-
ids = Bit::lookup_id info
|
90
|
-
raise Bit::DuplicateElement unless ids.length == 1
|
91
|
-
Bit.new ids.first
|
92
|
-
end
|
93
|
-
rescue Bit::NoElement, Bit::DuplicateElement
|
94
|
-
nil
|
95
|
-
end
|
96
|
-
end
|
97
|
-
|
98
|
-
# Task related methods.
|
99
|
-
|
100
|
-
# Gets all tasks with requested status for one action type.
|
101
|
-
# @param [Symbol] name of action type to get tasks for
|
102
|
-
# @param [Symbol] task status
|
103
|
-
# @return [Array] tasks for given action type with requested status
|
104
|
-
def get_tasks_by_status action, status
|
105
|
-
@@db.select_all_actions_by_status action, @@actions[action], status
|
106
|
-
end
|
107
|
-
|
108
|
-
# Adds a new task to the corresponding action table.
|
109
|
-
# @param [Symbol] action name of the action type
|
110
|
-
# @param [Hash] options options for the corresponding action type
|
111
|
-
def add_task action, options
|
112
|
-
begin
|
113
|
-
fail NoAction, "#{action}" unless @@actions.include? action
|
114
|
-
@@db.insert_action action, options
|
115
|
-
rescue NoAction => ex
|
116
|
-
puts "Could not add task, no such action: '#{ex.message}'."
|
117
|
-
end
|
118
|
-
end
|
119
|
-
|
120
|
-
# Runs all pending tasks.
|
121
|
-
def run_tasks
|
122
|
-
collect_tasks_by_bit.each do |bit, tasks|
|
123
|
-
b = get_bit bit
|
124
|
-
next if b.nil?
|
125
|
-
|
126
|
-
actions = tasks.group_by { |t| t[:action] } . keys
|
127
|
-
actions.each do |a|
|
128
|
-
load @@kit_path + "/actions/#{a}.rb"
|
129
|
-
load @@kit_path + "/actions/#{b.group_name}/#{a}.rb"
|
130
|
-
b.extend Actions
|
131
|
-
end
|
132
|
-
|
133
|
-
tasks.each do |t|
|
134
|
-
b.queue_task t
|
135
|
-
end
|
136
|
-
|
137
|
-
b.run_all
|
138
|
-
end
|
139
|
-
end
|
140
|
-
|
141
|
-
private
|
142
|
-
# Gets all pending tasks with requested status and groups them by bit.
|
143
|
-
# @return [Hash{Integer => Hash}] tasks grouped by bit id
|
144
|
-
def collect_tasks_by_bit
|
145
|
-
tasks = []
|
146
|
-
@@actions.each_key do |action|
|
147
|
-
tasks.push get_tasks_by_status action, :pending
|
148
|
-
end
|
149
|
-
tasks.flatten!
|
150
|
-
tasks.group_by { |t| t[:bit] }
|
151
|
-
end
|
152
|
-
|
153
|
-
# Converts a kit config file into a hash of kit settings.
|
154
|
-
# @param [String] file path to a kit config file in YAML format
|
155
|
-
# @return [Hash] kit settings
|
156
|
-
def load_config_file file
|
157
|
-
|
158
|
-
# Load the file using YAML.
|
159
|
-
config = YAML.load File.read file
|
160
|
-
@@config_path = File.absolute_path File.dirname file
|
161
|
-
|
162
|
-
# Determine the path to the kit.
|
163
|
-
config[:kits_path] = \
|
164
|
-
if config[:kits_path].nil?
|
165
|
-
@@config_path
|
166
|
-
elsif ! [ "/", "~" ].include? config[:kits_path][0]
|
167
|
-
File.absolute_path @@config_path + config[:kits_path]
|
168
|
-
else
|
169
|
-
config[:kits_path]
|
170
|
-
end
|
11
|
+
class Kit
|
171
12
|
|
172
|
-
|
173
|
-
|
13
|
+
# Load a kit with its configuration.
|
14
|
+
# @param [String, Hash] config_file path to kit config file in kit root directory
|
15
|
+
def initialize config_file
|
16
|
+
@config_file = File.absolute_path config_file
|
17
|
+
Dir["#{path}/models/*.rb"].each { |f| require f }
|
18
|
+
Dir["#{path}/actions/*.rb"].each { |f| require f }
|
19
|
+
end
|
20
|
+
|
21
|
+
# Load a kit with its configuration and connect to its database.
|
22
|
+
# @param config_file (see #initialize)
|
23
|
+
def self.open config_file
|
24
|
+
kit = self.new config_file
|
25
|
+
kit.db_connect
|
26
|
+
kit
|
27
|
+
end
|
28
|
+
|
29
|
+
# Determines and returns the kit's root directory.
|
30
|
+
# @return [String] path to kit's root directory
|
31
|
+
def path
|
32
|
+
@path ||= File.dirname @config_file
|
33
|
+
end
|
34
|
+
|
35
|
+
# Loads settings from the config file (only loads from file on first call).
|
36
|
+
# @return [Hash] kit settings
|
37
|
+
def config
|
38
|
+
@config ||= YAML.load File.read(@config_file)
|
39
|
+
end
|
40
|
+
|
41
|
+
# Dynamically define actions handled by KitDBSupport.
|
42
|
+
[:create, :destroy, :connect, :migrate, :migrate_to].each do |action|
|
43
|
+
define_method "db_#{action}".to_sym do |*args|
|
44
|
+
db_action action, *args
|
45
|
+
return self
|
46
|
+
end
|
47
|
+
end
|
48
|
+
|
49
|
+
# Some actions have bang versions.
|
50
|
+
[:create, :destroy].each do |action|
|
51
|
+
define_method "db_#{action}!".to_sym do |*args|
|
52
|
+
db_action action, *args
|
53
|
+
return self
|
54
|
+
end
|
55
|
+
end
|
56
|
+
|
57
|
+
private
|
58
|
+
|
59
|
+
# Passes db_* method calls to KitSupportDB.
|
60
|
+
def db_action action, *args
|
61
|
+
if [:migrate, :migrate_to].include? action
|
62
|
+
KitDBSupport.send action, path, *args
|
63
|
+
else
|
64
|
+
if config[:db][:adapter] == 'sqlite3'
|
65
|
+
db_path = config[:db][:database]
|
66
|
+
config[:db][:database] = "#{path}/#{db_path}" unless db_path =~ /^(\/|~)/
|
67
|
+
end
|
68
|
+
KitDBSupport.send action, config[:db], *args
|
69
|
+
end
|
70
|
+
end
|
174
71
|
|
175
72
|
end
|