kit 0.3.0 → 1.0.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,18 @@
1
+ *.gem
2
+ *.rbc
3
+ .bundle
4
+ .config
5
+ .yardoc
6
+ Gemfile.lock
7
+ InstalledFiles
8
+ _yardoc
9
+ coverage
10
+ doc/
11
+ lib/bundler/man
12
+ pkg
13
+ rdoc
14
+ spec/reports
15
+ test/tmp
16
+ test/version_tmp
17
+ tmp
18
+ test_kit/
data/.rspec ADDED
File without changes
@@ -0,0 +1,2 @@
1
+ --exclude spec/
2
+ --exclude test_kit/
@@ -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. This allows one to write methods available to all actions and methods available to specific actions (helps with DRY). See the skeleton kit for the updated structure.
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
@@ -0,0 +1,2 @@
1
+ source 'https://rubygems.org'
2
+ gemspec
@@ -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.
@@ -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 a framework for making simple management tools called kits. Each kit keeps track of a set of objects (the bits) and info about them. Actions of different types can be queued as tasks and run separately. Bits are put into groups so that code for each action type can be different for each group. The tasks are stored in a separate database, so the permissions for adding tasks and managing bit meta information can be set separately.
9
+ Kit is written using Active Record, so if you have worked with Rails, then Kit should feel familiar.
6
10
 
7
- == Using Kit
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
- k = Kit.new "/path_to/config.yml"
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
- where the config file is either the default config file included with the kit, or your own that may override some of the defaults. Now you can start adding bits and queuing and running tasks:
20
+ === Example use scenario
14
21
 
15
- bit = { :name => "foo", :group_name => "bar" }
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
- { :baz => { :bit => 1 } }.each do |action, options|
19
- k.add_task action, options
20
- end
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
- k.run_tasks
28
+ * Each vhost is a bit.
29
+ * Actions might look like
23
30
 
24
- For more information on what methods are available see the {YARD documentation}[https://rubygems.org/gems/kit] which is hosted at RubyGems.org. For more detailed information on how to use Kit, check out the wiki[https://github.com/razor-x/kit/wiki].
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
- === Gem Installation
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
- Download and install Kit with
68
+ $ mkdir my_kit && cd my_kit && git init && git pull git://github.com/razor-x/kits_skeleton.git
31
69
 
32
- gem install kit
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. The github web page is
39
- https://github.com/razor-x/kit. To clone the project run
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
- git clone git://github.com/razor-x/kit.git
106
+ You will also need to set up the test_kit to run specs. Do this with
42
107
 
43
- After cloning, you should run yard to generate documentation for the source.
108
+ $ rake develop:prepare
44
109
 
45
110
  == License
46
111
 
@@ -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
@@ -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 'yaml'
1
+ require 'active_record'
2
+ require 'sqlite3'
2
3
 
3
- # Primary class for Kit.
4
- class Kit
5
-
6
- require 'kit/bit'
7
-
8
- # Exceptions.
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
- # Bit related methods.
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
- return config
173
- end
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