ztk 0.3.1 → 1.0.0.rc.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/.travis.yml CHANGED
@@ -4,10 +4,12 @@ rvm:
4
4
  - 1.9.2
5
5
  - 1.9.3
6
6
 
7
- branches:
8
- only:
9
- - master
7
+ before_install:
8
+ - sudo apt-get -qq update
9
+
10
+ bundler_args: --binstubs
11
+
12
+ script: "rake spec"
10
13
 
11
14
  notifications:
12
- irc:
13
- - "irc.freenode.org#jovelabs"
15
+ irc: "irc.freenode.net#jovelabs"
data/.yardopts ADDED
@@ -0,0 +1,2 @@
1
+ --markup-provider=redcarpet
2
+ --markup=markdown
data/README.md CHANGED
@@ -2,7 +2,7 @@
2
2
 
3
3
  # ZTK
4
4
 
5
- Zachary's Tool Kit is a general purpose utility gem, featuring a collection of classes meant to simplify development of complex systems in Ruby.
5
+ Zachary's (DevOp) Tool Kit is a general purpose utility gem, featuring a collection of classes meant to simplify development of complex systems in Ruby.
6
6
 
7
7
  # RESOURCES
8
8
 
@@ -16,7 +16,7 @@ Issues:
16
16
 
17
17
  Documentation:
18
18
 
19
- * http://rubydoc.info/gems/ztk
19
+ * http://jovelabs.github.com/ztk/
20
20
 
21
21
  Wiki:
22
22
 
@@ -24,7 +24,7 @@ Wiki:
24
24
 
25
25
  # LICENSE
26
26
 
27
- ZTK - Zachary's Tool Kit
27
+ ZTK - Zachary's (DevOp) Tool Kit
28
28
 
29
29
  * Author: Zachary Patten <zachary@jovelabs.net>
30
30
  * Copyright: Copyright (c) Jove Labs
data/Rakefile CHANGED
@@ -41,3 +41,42 @@ task :coverage do
41
41
  end
42
42
 
43
43
  ################################################################################
44
+
45
+ require 'yard'
46
+ require 'yard/rake/yardoc_task'
47
+
48
+ GEM_NAME = File.basename(Dir.pwd)
49
+ DOC_PATH = File.expand_path(File.join("..", "/", "#{GEM_NAME}.doc"))
50
+
51
+ namespace :doc do
52
+ YARD::Rake::YardocTask.new(:pages) do |t|
53
+
54
+ # t.files = ['lib/**/*.rb']
55
+ t.options = ['--verbose', '-o', DOC_PATH]
56
+ end
57
+
58
+ namespace :pages do
59
+
60
+ desc 'Generate and publish YARD Documentation to GitHub pages'
61
+ task :publish => ['doc:pages'] do
62
+ describe = %x(git describe).chomp
63
+ stats = %x(bundle exec yard stats).chomp
64
+
65
+ commit_message = Array.new
66
+ commit_message << "Generated YARD Documentation for #{GEM_NAME.upcase} #{describe}\n\n"
67
+ commit_message << stats
68
+
69
+ Dir.chdir(DOC_PATH) do
70
+ puts(%x{git add -Av})
71
+ puts(%x{git commit -m"#{commit_message.join}"})
72
+ puts(%x{git push origin gh-pages})
73
+ end
74
+ end
75
+
76
+ end
77
+
78
+ end
79
+ desc 'Alias to doc:yard'
80
+ task 'doc' => 'doc:yard'
81
+
82
+ ################################################################################
@@ -17,7 +17,6 @@
17
17
  # limitatIOns under the License.
18
18
  #
19
19
  ################################################################################
20
-
21
20
  require "base64"
22
21
 
23
22
  module ZTK
@@ -63,10 +62,7 @@ module ZTK
63
62
  # Result Set
64
63
  attr_accessor :pid, :result
65
64
 
66
- # @param [Hash] config Configuration options hash.
67
- # @option config [Integer] :max_forks Maximum number of forks to use.
68
- # @option config [Proc] :before_fork (nil) Proc to call before forking.
69
- # @option config [Proc] :after_fork (nil) Proc to call after forking.
65
+ # @param [Hash] configuration Configuration options hash.
70
66
  def initialize(configuration={})
71
67
  super({
72
68
  }.merge(configuration))
@@ -80,7 +76,7 @@ module ZTK
80
76
  #
81
77
  # @yield Block should execute tasks to be performed in background.
82
78
  # @yieldreturn [Object] Block can return any object to be marshalled back to
83
- # the parent processes result set.
79
+ # the parent processes.
84
80
  # @return [Integer] Returns the pid of the child process forked.
85
81
  def process(&block)
86
82
  !block_given? and log_and_raise(BackgroundError, "You must supply a block to the process method!")
@@ -121,6 +117,10 @@ module ZTK
121
117
  # If a process successfully finished, it's return value from the *process*
122
118
  # block is stored into the result set.
123
119
  #
120
+ # It's advisable to use something like the *at_exit* hook to ensure you don't
121
+ # leave orphaned processes. For example, in the *at_exit* hook you could
122
+ # call *wait* to block until the child process finishes up.
123
+ #
124
124
  # @return [Array<pid, status, data>] An array containing the pid,
125
125
  # status and data returned from the process block. If wait2() fails nil
126
126
  # is returned.
@@ -140,6 +140,14 @@ module ZTK
140
140
  nil
141
141
  end
142
142
 
143
+ def alive?
144
+ (Process.getpgid(@pid).is_a?(Integer) rescue false)
145
+ end
146
+
147
+ def dead?
148
+ !alive?
149
+ end
150
+
143
151
  end
144
152
 
145
153
  end
data/lib/ztk/base.rb CHANGED
@@ -17,7 +17,6 @@
17
17
  # limitations under the License.
18
18
  #
19
19
  ################################################################################
20
-
21
20
  require "ostruct"
22
21
 
23
22
  module ZTK
@@ -37,7 +36,7 @@ module ZTK
37
36
 
38
37
  class << self
39
38
 
40
- # @param [Hash] config Configuration options hash.
39
+ # @param [Hash] configuration Configuration options hash.
41
40
  # @option config [IO] :stdout Instance of IO to be used for STDOUT.
42
41
  # @option config [IO] :stderr Instance of IO to be used for STDERR.
43
42
  # @option config [IO] :stdin Instance of IO to be used for STDIN.
@@ -81,6 +80,14 @@ module ZTK
81
80
  config
82
81
  end
83
82
 
83
+ # Logs an exception and then raises it.
84
+ #
85
+ # @param [Logger] logger An instance of a class based off the Ruby
86
+ # *Logger* class.
87
+ # @param [Exception] exception The exception class to raise.
88
+ # @param [String] message The message to display with the exception.
89
+ # @param [Integer] shift (1) How many places to shift the caller stack in
90
+ # the log statement.
84
91
  def log_and_raise(logger, exception, message, shift=1)
85
92
  if logger.is_a?(ZTK::Logger)
86
93
  logger.shift(:fatal, shift) { "EXCEPTION: #{exception.inspect} - #{message.inspect}" }
@@ -117,8 +124,16 @@ module ZTK
117
124
  end
118
125
  end
119
126
 
120
- def log_and_raise(exception, message)
121
- Base.log_and_raise(config.logger, exception, message, 2)
127
+ # Logs an exception and then raises it.
128
+ #
129
+ # @see Base.log_and_raise
130
+ #
131
+ # @param [Exception] exception The exception class to raise.
132
+ # @param [String] message The message to display with the exception.
133
+ # @param [Integer] shift (2) How many places to shift the caller stack in
134
+ # the log statement.
135
+ def log_and_raise(exception, message, shift=2)
136
+ Base.log_and_raise(config.logger, exception, message, shift)
122
137
  end
123
138
 
124
139
  # Direct logging method.
@@ -130,7 +145,7 @@ module ZTK
130
145
  # The value returned in the block is passed down to the logger specified in
131
146
  # the classes configuration.
132
147
  #
133
- # @param [Symbol] method_name This should be any one of [:debug, :info, :warn, :error, :fatal].
148
+ # @param [Symbol] log_level This should be any one of [:debug, :info, :warn, :error, :fatal].
134
149
  # @yield No value is passed to the block.
135
150
  # @yieldreturn [String] The message to log.
136
151
  def direct_log(log_level, &blocK)
data/lib/ztk/benchmark.rb CHANGED
@@ -26,13 +26,45 @@ module ZTK
26
26
  # @author Zachary Patten <zachary@jovelabs.net>
27
27
  class BenchmarkError < Error; end
28
28
 
29
- # Benchmark Class
29
+ # ZTK Benchmark Class
30
+ #
31
+ # This class contains a benchmarking tool which doubles to supply indications
32
+ # of activity to the console user during long running tasks.
33
+ #
34
+ # It can be run strictly for benchmarking (the default) or if supplied with
35
+ # the appropriate options it will display output to the user while
36
+ # benchmarking the supplied block.
30
37
  #
31
38
  # @author Zachary Patten <zachary@jovelabs.net>
32
39
  class Benchmark
33
40
 
34
41
  class << self
35
42
 
43
+ # Benchmark the supplied block.
44
+ #
45
+ # If *message* and *mark* options are used, then the *message* text will
46
+ # be displayed to the user. The the supplied *block* is yielded inside
47
+ # a *ZTK::Spinner.spin* call. This will provide the spinning cursor while
48
+ # the block executes. It is advisable to not have output sent to the
49
+ # console during this period.
50
+ #
51
+ # Once the block finishes executing, the *mark* text is displayed with
52
+ # the benchmark supplied to it as a sprintf option. One could use "%0.4f"
53
+ # in a *String* for example to get the benchmark time embedded in it
54
+ #
55
+ # @see Kernel#sprintf
56
+ #
57
+ # @param [Hash] options Configuration options hash.
58
+ # @option options [String] :message The *String* to be displayed to the
59
+ # user before the block is yielded.
60
+ # @option options [String] :mark The *String* to be displayed to the user
61
+ # after the block is yielded. This *String* should have an *sprintf*
62
+ # floating point macro in it if the benchmark is desired to be embedded
63
+ # in the given *String*.
64
+ #
65
+ # @yield Block should execute the tasks to be benchmarked.
66
+ # @yieldreturn [Object] The return value of the block is ignored.
67
+ # @return [Float] The benchmark time.
36
68
  def bench(options={}, &block)
37
69
  options = Base.build_config(options)
38
70
  options.logger.debug { "options=#{options.send(:table).inspect}" }
data/lib/ztk/command.rb CHANGED
@@ -17,7 +17,6 @@
17
17
  # limitations under the License.
18
18
  #
19
19
  ################################################################################
20
-
21
20
  require "ostruct"
22
21
  require "timeout"
23
22
 
@@ -50,11 +49,6 @@ module ZTK
50
49
  config.logger.debug { "config=#{config.send(:table).inspect}" }
51
50
  end
52
51
 
53
- def inspect
54
- @hostname ||= %x(hostname -f).chomp
55
- "#{ENV['USER']}@#{@hostname}"
56
- end
57
-
58
52
  # Executes a local command.
59
53
  #
60
54
  # @param [String] command The command to execute.
@@ -69,20 +63,17 @@ module ZTK
69
63
  # cmd = ZTK::Command.new
70
64
  # puts cmd.exec("hostname -f").inspect
71
65
  def exec(command, options={})
72
-
73
- def log_header(tag)
74
- count = 8
75
- sep = ("=" * count)
76
- header = [sep, "[ #{tag} ]", sep, "[ #{self.inspect} ]", sep, "[ #{tag} ]", sep].join
77
- "#{header}\n"
78
- end
79
-
80
66
  options = OpenStruct.new({ :exit_code => 0, :silence => false }.merge(options))
81
67
 
82
68
  config.logger.debug { "config=#{config.send(:table).inspect}" }
83
69
  config.logger.debug { "options=#{options.send(:table).inspect}" }
84
70
  config.logger.info { "command(#{command.inspect})" }
85
71
 
72
+ if config.replace_current_process
73
+ config.logger.fatal { "REPLACING CURRENT PROCESS - GOODBYE!" }
74
+ Kernel.exec(command)
75
+ end
76
+
86
77
  output = ""
87
78
  exit_code = -1
88
79
  stdout_header = false
@@ -169,14 +160,33 @@ module ZTK
169
160
  OpenStruct.new(:output => output, :exit_code => exit_code)
170
161
  end
171
162
 
163
+ # Not Supported
164
+ # @raise [CommandError] Not Supported
172
165
  def upload(*args)
173
166
  log_and_raise(CommandError, "Not Supported")
174
167
  end
175
168
 
169
+ # Not Supported
170
+ # @raise [CommandError] Not Supported
176
171
  def download(*args)
177
172
  log_and_raise(CommandError, "Not Supported")
178
173
  end
179
174
 
175
+
176
+ private
177
+
178
+ def tag
179
+ @hostname ||= %x(hostname -f).chomp
180
+ "#{ENV['USER']}@#{@hostname}"
181
+ end
182
+
183
+ def log_header(what)
184
+ count = 8
185
+ sep = ("=" * count)
186
+ header = [sep, "[ #{what} ]", sep, "[ #{tag} ]", sep, "[ #{what} ]", sep].join
187
+ "#{header}\n"
188
+ end
189
+
180
190
  end
181
191
 
182
192
  end
data/lib/ztk/config.rb CHANGED
@@ -17,7 +17,6 @@
17
17
  # limitations under the License.
18
18
  #
19
19
  ################################################################################
20
-
21
20
  require 'ostruct'
22
21
 
23
22
  module ZTK
@@ -0,0 +1,76 @@
1
+ ################################################################################
2
+ #
3
+ # Author: Zachary Patten <zachary@jovelabs.net>
4
+ # Copyright: Copyright (c) Jove Labs
5
+ # License: Apache License, Version 2.0
6
+ #
7
+ # Licensed under the Apache License, Version 2.0 (the "License");
8
+ # you may not use this file except in compliance with the License.
9
+ # You may obtain a copy of the License at
10
+ #
11
+ # http://www.apache.org/licenses/LICENSE-2.0
12
+ #
13
+ # Unless required by applicable law or agreed to in writing, software
14
+ # distributed under the License is distributed on an "AS IS" BASIS,
15
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16
+ # See the License for the specific language governing permissions and
17
+ # limitations under the License.
18
+ #
19
+ ################################################################################
20
+
21
+ # @author Zachary Patten <zachary@jovelabs.net>
22
+ module ZTK::DSL
23
+
24
+ class Base
25
+ include(ZTK::DSL::Core)
26
+
27
+ def self.inherited(base)
28
+ puts("inherited(#{base})")
29
+ base.send(:extend, ZTK::DSL::Base::ClassMethods)
30
+ base.instance_eval do
31
+ attribute :id
32
+ end
33
+ end
34
+
35
+ def self.included(base)
36
+ puts("included(#{base})")
37
+ end
38
+
39
+ def self.extended(base)
40
+ puts("extended(#{base})")
41
+ end
42
+
43
+ def initialize(&block)
44
+ self.id = self.class.id
45
+ self.class.dataset << self
46
+ block_given? and ((block.arity < 1) ? instance_eval(&block) : block.call(self))
47
+
48
+ primary_key_count = self.class.dataset.count do |d|
49
+ puts("d.id == #{d.id.inspect} / self.id == #{self.id.inspect}")
50
+ d.id == self.id
51
+ end
52
+ puts("primary_key_count == #{primary_key_count}")
53
+ raise StandardError, "Primary key '#{self.id}' already exists!" if (primary_key_count > 1)
54
+ end
55
+
56
+ def inspect
57
+ details = Array.new
58
+ details << "attributes=#{attributes.inspect}" if attributes.count > 0
59
+ details << "has_many_references=#{@has_many_references.count}" if @has_many_references
60
+ details << "belongs_to_references=#{@belongs_to_references.count}" if @belongs_to_references
61
+ "#<#{self.class.to_s} id=#{self.id.inspect} #{details.join(', ')}>"
62
+ end
63
+
64
+ module ClassMethods
65
+
66
+ def inspect
67
+ details = Array.new
68
+ details << "count=#{self.all.count}" if self.all.count > 0
69
+ "#<#{self.class.to_s}:#{self.id} #{details.join(', ')}>"
70
+ end
71
+
72
+ end
73
+
74
+ end
75
+
76
+ end
@@ -0,0 +1,49 @@
1
+ ################################################################################
2
+ #
3
+ # Author: Zachary Patten <zachary@jovelabs.net>
4
+ # Copyright: Copyright (c) Jove Labs
5
+ # License: Apache License, Version 2.0
6
+ #
7
+ # Licensed under the Apache License, Version 2.0 (the "License");
8
+ # you may not use this file except in compliance with the License.
9
+ # You may obtain a copy of the License at
10
+ #
11
+ # http://www.apache.org/licenses/LICENSE-2.0
12
+ #
13
+ # Unless required by applicable law or agreed to in writing, software
14
+ # distributed under the License is distributed on an "AS IS" BASIS,
15
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16
+ # See the License for the specific language governing permissions and
17
+ # limitations under the License.
18
+ #
19
+ ################################################################################
20
+
21
+ module ZTK::DSL::Core::Actions
22
+ module Find
23
+
24
+ def self.included(base)
25
+ base.class_eval do
26
+ base.send(:extend, ZTK::DSL::Core::Actions::Find::ClassMethods)
27
+ end
28
+ end
29
+
30
+ module ClassMethods
31
+
32
+ def all
33
+ dataset
34
+ end
35
+
36
+ def find(*args)
37
+ logger.debug { "*args(#{args.inspect})" }
38
+ ids = [args].flatten
39
+ all.select{ |data| ids.include?(data.id) }
40
+ end
41
+
42
+ def count
43
+ all.count
44
+ end
45
+
46
+ end
47
+
48
+ end
49
+ end
@@ -0,0 +1,47 @@
1
+ ################################################################################
2
+ #
3
+ # Author: Zachary Patten <zachary@jovelabs.net>
4
+ # Copyright: Copyright (c) Jove Labs
5
+ # License: Apache License, Version 2.0
6
+ #
7
+ # Licensed under the Apache License, Version 2.0 (the "License");
8
+ # you may not use this file except in compliance with the License.
9
+ # You may obtain a copy of the License at
10
+ #
11
+ # http://www.apache.org/licenses/LICENSE-2.0
12
+ #
13
+ # Unless required by applicable law or agreed to in writing, software
14
+ # distributed under the License is distributed on an "AS IS" BASIS,
15
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16
+ # See the License for the specific language governing permissions and
17
+ # limitations under the License.
18
+ #
19
+ ################################################################################
20
+
21
+ module ZTK::DSL::Core::Actions
22
+ module Timestamps
23
+
24
+ def self.included(base)
25
+ base.class_eval do
26
+ base.send(:extend, ZTK::DSL::Core::Actions::Timestamps::ClassMethods)
27
+ end
28
+ base.instance_eval do
29
+ attribute :created_at
30
+ attribute :updated_at
31
+ end
32
+ end
33
+
34
+ module ClassMethods
35
+
36
+ def updated_at_timestamp
37
+ self.updated_at = Time.now
38
+ end
39
+
40
+ def created_at_timestamp
41
+ self.created_at ||= Time.now
42
+ end
43
+
44
+ end
45
+
46
+ end
47
+ end
@@ -0,0 +1,34 @@
1
+ ################################################################################
2
+ #
3
+ # Author: Zachary Patten <zachary@jovelabs.net>
4
+ # Copyright: Copyright (c) Jove Labs
5
+ # License: Apache License, Version 2.0
6
+ #
7
+ # Licensed under the Apache License, Version 2.0 (the "License");
8
+ # you may not use this file except in compliance with the License.
9
+ # You may obtain a copy of the License at
10
+ #
11
+ # http://www.apache.org/licenses/LICENSE-2.0
12
+ #
13
+ # Unless required by applicable law or agreed to in writing, software
14
+ # distributed under the License is distributed on an "AS IS" BASIS,
15
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16
+ # See the License for the specific language governing permissions and
17
+ # limitations under the License.
18
+ #
19
+ ################################################################################
20
+
21
+ module ZTK::DSL::Core
22
+ module Actions
23
+ autoload :Find, "ztk/dsl/core/actions/find"
24
+ autoload :Timestamps, "ztk/dsl/core/actions/timestamps"
25
+
26
+ def self.included(base)
27
+ base.class_eval do
28
+ base.send(:include, ZTK::DSL::Core::Actions::Find)
29
+ base.send(:include, ZTK::DSL::Core::Actions::Timestamps)
30
+ end
31
+ end
32
+
33
+ end
34
+ end
@@ -0,0 +1,53 @@
1
+ ################################################################################
2
+ #
3
+ # Author: Zachary Patten <zachary@jovelabs.net>
4
+ # Copyright: Copyright (c) Jove Labs
5
+ # License: Apache License, Version 2.0
6
+ #
7
+ # Licensed under the Apache License, Version 2.0 (the "License");
8
+ # you may not use this file except in compliance with the License.
9
+ # You may obtain a copy of the License at
10
+ #
11
+ # http://www.apache.org/licenses/LICENSE-2.0
12
+ #
13
+ # Unless required by applicable law or agreed to in writing, software
14
+ # distributed under the License is distributed on an "AS IS" BASIS,
15
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16
+ # See the License for the specific language governing permissions and
17
+ # limitations under the License.
18
+ #
19
+ ################################################################################
20
+
21
+ module ZTK::DSL::Core
22
+ module Attributes
23
+
24
+ def self.included(base)
25
+ base.class_eval do
26
+ base.send(:extend, ZTK::DSL::Core::Attributes::ClassMethods)
27
+ end
28
+ end
29
+
30
+ def attributes
31
+ @attributes ||= {}
32
+ end
33
+
34
+ module ClassMethods
35
+
36
+ def attribute(key, options={})
37
+ send(:define_method, key) do |*args|
38
+ if args.count == 0
39
+ attributes[key]
40
+ else
41
+ send("#{key}=", *args)
42
+ end
43
+ end
44
+
45
+ send(:define_method, "#{key}=") do |value|
46
+ attributes[key] = value
47
+ end
48
+ end
49
+
50
+ end
51
+
52
+ end
53
+ end
@@ -0,0 +1,66 @@
1
+ ################################################################################
2
+ #
3
+ # Author: Zachary Patten <zachary@jovelabs.net>
4
+ # Copyright: Copyright (c) Jove Labs
5
+ # License: Apache License, Version 2.0
6
+ #
7
+ # Licensed under the Apache License, Version 2.0 (the "License");
8
+ # you may not use this file except in compliance with the License.
9
+ # You may obtain a copy of the License at
10
+ #
11
+ # http://www.apache.org/licenses/LICENSE-2.0
12
+ #
13
+ # Unless required by applicable law or agreed to in writing, software
14
+ # distributed under the License is distributed on an "AS IS" BASIS,
15
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16
+ # See the License for the specific language governing permissions and
17
+ # limitations under the License.
18
+ #
19
+ ################################################################################
20
+
21
+ module ZTK::DSL::Core
22
+ module Dataset
23
+
24
+ def self.included(base)
25
+ base.class_eval do
26
+ base.send(:extend, ZTK::DSL::Core::Dataset::ClassMethods)
27
+ end
28
+ end
29
+
30
+ module ClassMethods
31
+
32
+ def dataset
33
+ klass = self.to_s.underscore.to_sym
34
+ @@dataset ||= {}
35
+ if @@dataset.key?(klass)
36
+ @@dataset[klass]
37
+ else
38
+ @@dataset[klass] ||= []
39
+ end
40
+ end
41
+
42
+ def purge
43
+ @@dataset = nil
44
+ end
45
+
46
+ def id
47
+ @@id ||= 0
48
+ (@@id += 1)
49
+ end
50
+
51
+ # def foreign_keys(target)
52
+ # puts("==> foreign_keys(#{target.inspect})")
53
+
54
+ # target = singularize(underscore(target).to_sym)
55
+ # source = singularize(underscore(self).to_sym)
56
+
57
+ # splat = [source, target].sort
58
+
59
+ # key = [ splat[0], "references", splat[1] ].join(":")
60
+ # puts("key=#{key}")
61
+ # end
62
+
63
+ end
64
+
65
+ end
66
+ end