wukong-deploy 0.0.1 → 0.0.2

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/Gemfile CHANGED
@@ -1,3 +1,8 @@
1
- source :rubygems
1
+ source :rubygems
2
2
 
3
3
  gemspec
4
+
5
+ group :development do
6
+ gem 'rake', '~> 0.9'
7
+ gem 'rspec', '~> 2'
8
+ end
data/README.md CHANGED
@@ -38,6 +38,53 @@ The deploy pack is installed as a RubyGem:
38
38
  $ sudo gem install wukong-deploy
39
39
  ```
40
40
 
41
+ ## Usage
42
+
43
+ Wukong-Deploy provides a command-line tool `wu-deploy` which can be
44
+ used to create or interact with deploy packs.
45
+
46
+ ### Creating a New Deploy Pack
47
+
48
+ Create a new deploy pack:
49
+
50
+ ```
51
+ $ wu-deploy new my_app
52
+ Within /home/user/my_app:
53
+ create .
54
+ create app/models
55
+ create app/processors
56
+ ...
57
+ ```
58
+
59
+ This will create a directory `my_app` in the current directory.
60
+ Passing the `dry_run` option will print what should happen without
61
+ actually doing anything:
62
+
63
+ ```
64
+ $ wu-deploy new my_app --dry_run
65
+ Within /home/user/my_app:
66
+ create .
67
+ create app/models
68
+ create app/processors
69
+ ...
70
+ ```
71
+
72
+ You'll be prompted if there is a conflict. You can pass the `force`
73
+ option to always overwrite files and the `skip` option to never
74
+ overwrite files.
75
+
76
+ ### Working with an Existing Deploy Pack
77
+
78
+ If your current directory is within an existing deploy pack you can
79
+ start up an IRB console with the deploy pack's environment already
80
+ loaded:
81
+
82
+ ```
83
+ $ wu-deploy console
84
+ irb(main):001:0>
85
+ ```
86
+
87
+
41
88
  ## File Structure
42
89
 
43
90
  A deploy pack is a repository with the following
data/examples/.gitkeep ADDED
File without changes
@@ -12,6 +12,30 @@ module Wukong
12
12
  case executable
13
13
  when 'wu-hadoop'
14
14
  Wukong::Elasticsearch.configure(settings) if executable == 'wu-hadoop'
15
+ when 'wu-deploy'
16
+ settings.define(:dry_run, :description => "Don't actually create or modify anything", :type => :boolean, :default => false)
17
+ settings.define(:skip, :description => "Skip existing files", :type => :boolean, :default => false)
18
+ settings.define(:force, :description => "Overwrite existing files", :type => :boolean, :default => false)
19
+ def settings.usage
20
+ "usage: wu-deploy ACTION [ --param=val | --param | -p val | -p ] ..."
21
+ end
22
+ settings.use(:commandline)
23
+ settings.description = <<EOF
24
+ wu-deploy is a tool for creating and interacting with deploy packs.
25
+
26
+ You can create a new deploy pack
27
+
28
+ $ wu-deploy new my_app
29
+
30
+ The `--force' and `--skip' options can be used to control how conflict
31
+ resolution works when creating files. The `--dry_run` option can be
32
+ used to see what happens without doing it.
33
+
34
+ If you are within the directory of a deploy pack, you can enter an IRB
35
+ console with the deploy pack's environment already loaded:
36
+
37
+ $ wu-deploy console
38
+ EOF
15
39
  end
16
40
  settings
17
41
  end
@@ -1,5 +1,3 @@
1
-
2
-
3
1
  module Wukong
4
2
  module Deploy
5
3
  class Driver
@@ -21,7 +19,7 @@ module Wukong
21
19
  when 'new'
22
20
  require_relative('templater')
23
21
  raise Error.new("Must provide a path to the root of the deploy pack you want to create") if args[1].nil? || args[1].blank?
24
- Templater.new(File.expand_path(args[1], Dir.pwd)).create
22
+ Templater.new(File.expand_path(args[1], Dir.pwd), settings).run!
25
23
  when 'console'
26
24
  require_relative('console')
27
25
  Wukong::Deploy::Console.new.run!
@@ -3,6 +3,8 @@ require 'fileutils'
3
3
  require 'erubis'
4
4
 
5
5
  require_relative('repo')
6
+ require_relative('templater/messaging')
7
+ require_relative('templater/conflict_resolution')
6
8
 
7
9
  module Wukong
8
10
  module Deploy
@@ -11,22 +13,35 @@ module Wukong
11
13
  attr_accessor :repo
12
14
  attr_accessor :options
13
15
 
14
- include FileUtils::Verbose
16
+ include FileUtils
17
+ include Messaging
18
+ include ConflictResolution
15
19
 
16
20
  def initialize root, options={}
17
21
  self.repo = Repo.new(root)
18
22
  self.options = options
19
23
  end
20
24
 
21
- def create
25
+ def dry_run?
26
+ @options[:dry_run]
27
+ end
28
+
29
+ def run!
30
+ if dry_run?
31
+ puts "Would perform the following actions in #{repo.root}"
32
+ else
33
+ puts "Within #{repo.root}:"
34
+ end
22
35
  create_dirs
23
36
  create_templates
24
37
  create_gitkeeps
25
38
  create_gitignore
26
39
  end
27
-
40
+
28
41
  def create_dirs
29
- repo.dirs_to_create.each { |dir| mkdir_p(dir) }
42
+ repo.dirs_to_create.each do |dir|
43
+ create_directory(dir)
44
+ end
30
45
  end
31
46
 
32
47
  def create_templates
@@ -36,18 +51,16 @@ module Wukong
36
51
  end
37
52
 
38
53
  def create_template input_path, output_path, binding={}
39
- input = File.read(input_path)
40
- erb = Erubis::Eruby.new(input)
41
- output = erb.result(binding)
42
- action = File.exist?(output_path) ? 'modify' : 'create'
43
- puts "#{action} #{output_path}"
44
- File.open(output_path, 'w') { |f| f.puts(output) }
54
+ input = File.read(input_path)
55
+ erb = Erubis::Eruby.new(input)
56
+ content = erb.result(binding)
57
+ create_file(content, output_path)
45
58
  end
46
59
 
47
60
  def create_gitkeeps
48
61
  repo.dirs_to_create.each do |dir|
49
62
  if Dir[File.join(dir, '*')].empty?
50
- touch(File.join(dir, '.gitkeep'))
63
+ create_file(empty_file, File.join(dir, '.gitkeep'))
51
64
  end
52
65
  end
53
66
  end
@@ -59,7 +72,33 @@ module Wukong
59
72
  def templates_dir
60
73
  @templates_dir ||= Pathname.new(File.expand_path('../../../templates', __FILE__))
61
74
  end
75
+
76
+ private
77
+
78
+ def empty_file
79
+ ""
80
+ end
62
81
 
82
+ def create_file content, path
83
+ if File.exist?(path)
84
+ handle_conflict(content, path)
85
+ else
86
+ message_create(path)
87
+ write_file(content, path)
88
+ end
89
+ end
90
+
91
+ def create_directory(dir)
92
+ message_create(dir)
93
+ return if dry_run?
94
+ mkdir_p(dir)
95
+ end
96
+
97
+ def write_file content, path
98
+ return if dry_run?
99
+ File.open(path, 'w') { |f| f.write(content) }
100
+ end
101
+
63
102
  end
64
103
  end
65
104
  end
@@ -0,0 +1,57 @@
1
+ require_relative("differ")
2
+
3
+ module Wukong
4
+ module Deploy
5
+ module ConflictResolution
6
+
7
+ def handle_conflict(new_content, path)
8
+ existing_content = File.read(path)
9
+ case
10
+ when new_content == existing_content
11
+ message_same(path)
12
+ when always_replace?
13
+ message_replace(path)
14
+ write_file(new_content, path)
15
+ when never_replace?
16
+ message_skip(path)
17
+ else
18
+ message_conflict(path)
19
+ diff!(new_content, existing_content, path)
20
+ end
21
+ end
22
+
23
+ def always_replace?
24
+ @always_replace || options[:force]
25
+ end
26
+
27
+ def always_replace!
28
+ @always_replace = true
29
+ end
30
+
31
+ def never_replace?
32
+ @never_replace || options[:skip]
33
+ end
34
+
35
+ def never_replace!
36
+ @never_replace = true
37
+ end
38
+
39
+ private
40
+
41
+ # :nodoc:
42
+ def diff! new_content, existing_content, path
43
+ differ = Differ.new(new_content, existing_content)
44
+ differ.resolve!
45
+ always_replace! if differ.always_replace?
46
+ never_replace! if differ.never_replace?
47
+ if differ.replace?
48
+ message_replace(path)
49
+ write_file(new_content, path)
50
+ else
51
+ message_skip(path)
52
+ end
53
+ end
54
+
55
+ end
56
+ end
57
+ end
@@ -0,0 +1,90 @@
1
+ require 'diffy'
2
+
3
+ module Wukong
4
+ module Deploy
5
+ class Differ
6
+
7
+ attr_accessor :new_content
8
+ attr_accessor :existing_content
9
+
10
+ def initialize new_content, existing_content
11
+ self.new_content = new_content
12
+ self.existing_content = existing_content
13
+ end
14
+
15
+ def replace?
16
+ @replace
17
+ end
18
+
19
+ def always_replace?
20
+ @always_replace
21
+ end
22
+
23
+ def never_replace?
24
+ @never_replace
25
+ end
26
+
27
+ def resolve!
28
+ response = get_response
29
+ case response
30
+ when /^y/
31
+ @replace = true
32
+ when /^Y/
33
+ @replace = true
34
+ @always_replace = true
35
+ when /^n/
36
+ @replace = false
37
+ when /^N/
38
+ @replace = false
39
+ @never_replace = true
40
+ end
41
+ end
42
+
43
+ def diff
44
+ @diff = Diffy::Diff.new(new_content, existing_content, :allow_empty_diff => true, :diff => "-U 5", :include_diff_info => true)
45
+ end
46
+
47
+ def show_diff
48
+ puts ''
49
+ diff.each do |line|
50
+ puts " #{line}"
51
+ end
52
+ puts ''
53
+ end
54
+
55
+ def show_help
56
+ puts " Y - yes, overwrite this file and all other conflicts"
57
+ puts " y - yes, overwrite this file"
58
+ puts " N - no, skip this file and all other conflicts"
59
+ puts " n - no, skip this file"
60
+ puts " d - diff, show the differences between the existing file and the new file"
61
+ puts " q - quit, abort"
62
+ puts " h - help, show this help"
63
+ end
64
+
65
+ def get_response
66
+ STDOUT.write ' Overwrite? (enter "h" for help) [YNynqdh]: '
67
+ begin
68
+ response = STDIN.readline.chomp.strip
69
+ rescue EOFError, Interrupt => e
70
+ exit(1)
71
+ end
72
+ case
73
+ when response =~ /^(y|n|Y|N)/
74
+ response
75
+ when response =~ /^q/i
76
+ exit(1)
77
+ when response =~ /^d/i
78
+ show_diff
79
+ get_response
80
+ when response =~ /^h/i
81
+ show_help
82
+ get_response
83
+ else
84
+ get_response
85
+ end
86
+ end
87
+
88
+ end
89
+ end
90
+ end
@@ -0,0 +1,32 @@
1
+ module Wukong
2
+ module Deploy
3
+ module Messaging
4
+
5
+ def message action, *objects
6
+ puts [action.rjust(25), ' ', objects.map { |path| Pathname.new(path).relative_path_from(repo.root).to_s }.join(' ')].join
7
+ end
8
+
9
+ def message_create *objects
10
+ message "\e[32m\e[1mcreate\e[0m", *objects
11
+ end
12
+
13
+ def message_conflict *objects
14
+ message "\e[31m\e[1mconflict\e[0m", *objects
15
+ end
16
+
17
+ def message_replace *objects
18
+ message "\e[31m\e[1mreplace\e[0m", *objects
19
+ end
20
+
21
+ def message_same *objects
22
+ message "\e[34m\e[1msame\e[0m", *objects
23
+ end
24
+
25
+ def message_skip *objects
26
+ message "\e[35m\e[1mskip\e[0m", *objects
27
+ end
28
+ end
29
+ end
30
+ end
31
+
32
+
@@ -2,6 +2,6 @@ module Wukong
2
2
  module Deploy
3
3
 
4
4
  # The current version of this deploy pack framework.
5
- VERSION = '0.0.1'
5
+ VERSION = '0.0.2'
6
6
  end
7
7
  end
@@ -0,0 +1,10 @@
1
+ require 'rspec'
2
+ require 'wukong-deploy'
3
+ require 'wukong/spec_helpers'
4
+ require_relative './support/integration_helper'
5
+
6
+ RSpec.configure do |config|
7
+ config.mock_with :rspec
8
+ include Wukong::SpecHelpers
9
+ include Wukong::Deploy::IntegrationHelper
10
+ end
@@ -0,0 +1,38 @@
1
+ module Wukong
2
+ module Deploy
3
+ module IntegrationHelper
4
+
5
+ def root
6
+ @root ||= Pathname.new(File.expand_path('../../..', __FILE__))
7
+ end
8
+
9
+ def lib_dir *args
10
+ root.join('lib', *args)
11
+ end
12
+
13
+ def bin_dir *args
14
+ root.join('bin', *args)
15
+ end
16
+
17
+ def examples_dir *args
18
+ root.join('examples', *args)
19
+ end
20
+
21
+ def integration_env
22
+ {
23
+ "PATH" => [bin_dir.to_s, ENV["PATH"]].compact.join(':'),
24
+ "RUBYLIB" => [lib_dir.to_s, ENV["RUBYLIB"]].compact.join(':')
25
+ }
26
+ end
27
+
28
+ def integration_cwd
29
+ root.to_s
30
+ end
31
+
32
+ def example_script *args
33
+ examples_dir(*args)
34
+ end
35
+
36
+ end
37
+ end
38
+ end
@@ -0,0 +1,94 @@
1
+ require 'spec_helper'
2
+
3
+ describe 'wu-deploy' do
4
+
5
+ before {`rm -rf #{examples_dir('*')}` }
6
+ after {`rm -rf #{examples_dir('*')}` }
7
+
8
+ context "without arguments" do
9
+ subject { command('wu-deploy') }
10
+ it { should exit_with(:non_zero) }
11
+ it "displays a help message" do
12
+ should have_stderr(/usage: wu-deploy/)
13
+ end
14
+ end
15
+
16
+ context "creating a deploy pack" do
17
+
18
+ context "without a given path" do
19
+ subject { command('wu-deploy', 'new') }
20
+ it { should exit_with(:non_zero) }
21
+ it "prints an error message" do
22
+ should have_stderr(/path/)
23
+ end
24
+ end
25
+
26
+ context "with a given path" do
27
+ subject { command('wu-deploy', 'new', examples_dir("deploy_pack")) }
28
+ it { should exit_with(0) }
29
+ it "prints the files its creating" do
30
+ should have_stdout(/create.*config/, /create.*Gemfile/, /create.*\.gitignore/)
31
+ end
32
+ it "creates files on disk" do
33
+ subject.run!
34
+ Dir[examples_dir('deploy_pack', '*')].should_not be_empty
35
+ end
36
+ end
37
+
38
+ context "with the --dry_run flag" do
39
+ subject { command('wu-deploy', 'new', examples_dir("deploy_pack"), '--dry_run') }
40
+ it { should exit_with(0) }
41
+ it "prints the files its creating" do
42
+ should have_stdout(/create.*config/, /create.*Gemfile/, /create.*\.gitignore/)
43
+ end
44
+ it "doesn't create files on disk" do
45
+ subject.run!
46
+ Dir[examples_dir('deploy_pack', '*')].should be_empty
47
+ end
48
+ end
49
+
50
+ context "on top of an existing deploy pack" do
51
+ before { command('wu-deploy', 'new', examples_dir("deploy_pack")).run! }
52
+ subject { command('wu-deploy', 'new', examples_dir("deploy_pack")) }
53
+ it { should exit_with(0) }
54
+ it "prints the files its creating and which ones are the same" do
55
+ should have_stdout(/create.*config/, /same.*Gemfile/, /same.*\.gitignore/)
56
+ end
57
+ context "with conflicts" do
58
+ before do
59
+ File.open(examples_dir("deploy_pack", "Gemfile"), 'w') { |f| f.puts "new content" }
60
+ end
61
+ context "that are skipped by hand" do
62
+ subject { command('wu-deploy', 'new', examples_dir("deploy_pack")) < "n" }
63
+ it { should exit_with(0) }
64
+ it "prints the files it skipped" do
65
+ should have_stdout(/create.*config/, /skip.*Gemfile/, /same.*\.gitignore/)
66
+ end
67
+ end
68
+ context "that are automatically skipped" do
69
+ subject { command('wu-deploy', 'new', examples_dir("deploy_pack"), "--skip") }
70
+ it { should exit_with(0) }
71
+ it "prints the files it skipped" do
72
+ should have_stdout(/create.*config/, /skip.*Gemfile/, /same.*\.gitignore/)
73
+ end
74
+ end
75
+ context "that are replaced" do
76
+ subject { command('wu-deploy', 'new', examples_dir("deploy_pack")) < "y" }
77
+ it { should exit_with(0) }
78
+ it "prints the files it replaced" do
79
+ should have_stdout(/create.*config/, /replace.*Gemfile/, /same.*\.gitignore/)
80
+ end
81
+ end
82
+ context "that are automatically replaced" do
83
+ subject { command('wu-deploy', 'new', examples_dir("deploy_pack"), "--force") }
84
+ it { should exit_with(0) }
85
+ it "prints the files it replaced" do
86
+ should have_stdout(/create.*config/, /replace.*Gemfile/, /same.*\.gitignore/)
87
+ end
88
+ end
89
+
90
+ end
91
+ end
92
+ end
93
+ end
94
+
@@ -1 +1,214 @@
1
- Welcome to your new deploy pack.
1
+ f# Welcome to the Infochimps Platform!
2
+
3
+ The [Infochimps Platform](http://www.infochimps.com) is an end-to-end,
4
+ managed solution for building Big Data applications. It integrates
5
+ best-of-breed technologies like [Hadoop](http://hadoop.apache.org/),
6
+ [Storm](https://github.com/nathanmarz/storm),
7
+ [Kafka](http://incubator.apache.org/kafka/),
8
+ [MongoDB](http://www.mongodb.org/),
9
+ [ElasticSearch](http://www.elasticsearch.org/),
10
+ [HBase](http://hbase.apache.org/), &c. and provides simple interfaces
11
+ for accessing these powerful tools.
12
+
13
+ Computation, analytics, scripting, &c. are all handled by
14
+ [Wukong](http://github.com/infochimps-labs/wukong) within the
15
+ platform. Wukong is an abstract framework for defining computations
16
+ on data. Wukong processors and flows can run in many different
17
+ execution contexts including:
18
+
19
+ * locally on the command-line for testing or development purposes
20
+ * as a Hadoop mapper or reducer for batch analytics or ETL
21
+ * within Storm as part of a real-time data flow
22
+
23
+ The Infochimps Platform uses the concept of a deploy pack for
24
+ developers to develop all their processors, flows, and jobs within.
25
+ The deploy pack can be thought of as a container for all the necessary
26
+ Wukong code and plugins useful in the context of an Infochimps
27
+ Platform application. It includes the following libraries:
28
+
29
+ * <a href="http://github.com/infochimps-labs/wukong/tree/3.0.0">wukong</a>: The core framework for writing processors and chaining them together.
30
+ * <a href="http://github.com/infochimps-labs/wukong-hadoop">wukong-hadoop</a>: Run Wukong processors as mappers and reducers within the Hadoop framework. Model Hadoop jobs locally before you run them.
31
+ * <a href="http://github.com/infochimps-labs/wonderdog">wonderdog</a>: Connect Wukong processors running within Hadoop to Elasticsearch as either a source or sink for data.
32
+ * <a href="http://github.com/infochimps-labs/wukong-deploy">wukong-deploy</a>: Code for coordinating Wukong and its plugins in a deploy pack.
33
+
34
+ **This is your deploy pack!** You will build your data processing
35
+ pipelines and Hadoop jobs within this repo.
36
+
37
+ ## Setup
38
+
39
+ ### Dependencies
40
+
41
+ In order to install and run a deploy pack you need the following
42
+ dependencies:
43
+
44
+ #### Ruby 1.9.x
45
+
46
+ Wukong and the deploy pack framework will only run on Ruby 1.9. There
47
+ are a lot of [online
48
+ instructions](http://www.ruby-lang.org/en/downloads/) you can use to
49
+ get Ruby 1.9 (and RubyGems) installed and configured on your local
50
+ system.
51
+
52
+ If you use [rvm](https://rvm.io/) or
53
+ [rbenv](https://github.com/sstephenson/rbenv) to manage your Ruby
54
+ installations, make sure you install all gems appropriately and invoke
55
+ bundler appropriately in what follows.
56
+
57
+ #### Git
58
+
59
+ You'll need [Git](http://git-scm.com/) to push/pull your deploy pack
60
+ code to/from the Infochimps Platform.
61
+
62
+ ### Creating/Cloning the Deploy Pack
63
+
64
+ The first thing you need to do to get started is get a local copy of
65
+ this deploy on your computer. If you have already been giving a
66
+ deploy pack by Infochimps then you'll want to clone it:
67
+
68
+ ```
69
+ $ git clone <your-deploy-pack-git-url>
70
+ ```
71
+
72
+ If you are creating a deploy pack from scratch you'll want to use the
73
+ `wu-deploy` tool to create the scaffold of your deploy pack for you:
74
+
75
+ ```
76
+ $ sudo gem install wukong-deploy
77
+ $ wu-deploy new <my-app-name>
78
+ ```
79
+
80
+ Once you have the deploy pack on disk, you can install the
81
+ dependencies and
82
+
83
+ ### Installation
84
+
85
+ From within the root of your deploy pack run the following commands
86
+
87
+ ```
88
+ $ sudo gem install bundler
89
+ $ bundle install --standalone
90
+ ```
91
+
92
+ If you're using [rbenv](https://github.com/sstephenson/rbenv) you may
93
+ want to run `rbenv exec bundle install --standalone`.
94
+
95
+ Bundler will install all the necessary dependencies locally in a
96
+ directory called `bundle`. We use a `standalone` installation of your
97
+ application bundle because this makes it easier to connect code in the
98
+ deploy pack to frameworks like Hadoop, Storm, &c. when your code is
99
+ running within the Infochimps Platform.
100
+
101
+ ### Configuration
102
+
103
+ Your deploy pack doesn't need any configuration out of the box. As
104
+ you begin to extend it you may add functionality which benefits from
105
+ the ability to be configured.
106
+
107
+ Put any configuration you want shared across all environments into the
108
+ file `config/settings.yml`. Override this with environment-specific
109
+ configuration in the appropriate file within `config/environments`.
110
+
111
+ As an example, you may write a processor like this:
112
+
113
+ ```ruby
114
+ Wukong.procesor(:configurable_decorator) do
115
+ field :suffix, String, :default => '.'
116
+ def process record
117
+ yield [record, suffix].join
118
+ end
119
+ end
120
+ ```
121
+
122
+ This processor's `suffix` property can be set on the command-line:
123
+
124
+ ```
125
+ $ cat input
126
+ 1
127
+ 2
128
+ 3
129
+ $ cat input | wu-local configurable_decorator
130
+ 1.
131
+ 2.
132
+ 3.
133
+ $ cat input | wu-local configurable_decorator --suffix=','
134
+ 1,
135
+ 2,
136
+ 3,
137
+
138
+ You can also set the same property in a configuration file, scoped by
139
+ the name of the processor:
140
+
141
+ ```yaml
142
+ # in config/settings.yml
143
+ ---
144
+
145
+ configurable_decorator:
146
+ suffix: ,
147
+ ```
148
+
149
+ which lets you the `--suffix` flag on the command-line while still
150
+ overriding the default setting. You can also put such settings in
151
+ environment specific files within `config/environments`.
152
+
153
+ ## File Structure
154
+
155
+ A deploy pack is a repository with the following
156
+ [Rails](http://rubyonrails.org/)-like file structure:
157
+
158
+ ```
159
+ ├── app
160
+ │ ├── models
161
+ │ ├── processors
162
+ │ ├── flows
163
+ │ └── jobs
164
+ ├── config
165
+ │ ├── environment.rb
166
+ │ ├── application.rb
167
+ │ ├── initializers
168
+ │ ├── settings.yml
169
+ │ └── environments
170
+ │ ├── development.yml
171
+ │ ├── production.yml
172
+ │ └── test.yml
173
+ ├── data
174
+ ├── Gemfile
175
+ ├── Gemfile.lock
176
+ ├── lib
177
+ ├── log
178
+ ├── Rakefile
179
+ ├── spec
180
+ │ ├── spec_helper.rb
181
+ │ └── support
182
+ └── tmp
183
+ ```
184
+
185
+ Let's look at it piece by piece:
186
+
187
+ * <b>app</b>: The directory with all the action. It's where you define:
188
+ * <b>models</b>: Your domain models or "nouns", which define and wrap the different kinds of data elements in your application. They are built using whatever framework you like (defaults to [Gorillib](http://github.com/infochimps-labs/gorillib))
189
+ * <b>processors</b>: Your fundamental operations or "verbs", which are passed records and parse, filter, augment, normalize, or split them.
190
+ * <b>flows</b>: Chain together processors into streaming flows for ingestion, real-time processing, or [complex event processing](http://en.wikipedia.org/wiki/Complex_event_processing) (CEP)
191
+ * <b>jobs</b>: Pair processors together to create batch jobs to run in Hadoop
192
+ * <b>config</b>: Where you place all application configuration for all environments
193
+ * <b>environment.rb</b>: Defines the runtime environment for all code, requiring and configuring all Wukong framework code. You shouldn't have to edit this file directly.
194
+ * <b>application.rb</b>: Require and configure libraries specific to your application. Choose a model framework, pick what application code gets loaded by default (vs. auto-loaded).
195
+ * <b>initializers</b>: Holds any files you need to load before <b>application.rb</b> here. Useful for requiring and configuring external libraries.
196
+ * <b>settings.yml</b>: Defines application-wide settings.
197
+ * <b>environments</b>: Defines environment-specific settings in YAML files named after the environment. Overrides <b>config/settings.yml</b>.
198
+ * <b>data</b>: Holds sample data in flat files. You'll develop and test your application using this data.
199
+ * <b>Gemfile</b> and <b>Gemfile.lock</b>: Defines how libraries are resolved with [Bundler](http://gembundler.com/).
200
+ * <b>lib</b>: Holds any code you want to use in your application but that isn't "part of" your application (like vendored libraries, Rake tasks, &c.).
201
+ * <b>log</b>: A good place to stash logs.
202
+ * <b>Rakefile</b>: Defines [Rake](http://rake.rubyforge.org/) tasks for the development, test, and deploy of your application.
203
+ * <b>spec</b>: Holds all your [RSpec](http://rspec.info/) unit tests.
204
+ * <b>spec_helper.rb</b>: Loads libraries you'll use during testing, includes spec helper libraries from Wukong.
205
+ * <b>support</b>: Holds support code for your tests.
206
+ * <b>tmp</b>: A good place to stash temporary files.
207
+
208
+ ## Writing your first models, processors, flows, and jobs
209
+
210
+ Before you start developing, it might be helpful to read up on some of
211
+ the underlying documentation for Wukong and its plugins, specifically:
212
+
213
+ * on [Wukong](http://github.com/infochimps-labs/wukong/tree/3.0.0) so you understand the basic idea of a processor and how to glue processors together
214
+ * on [Wukong-Hadoop](http://github.com/infochimps-labs/wukong-hadoop) so you understand how to move between local and Hadoop modes for batch analytics
@@ -62,5 +62,3 @@ require 'gorillib/object/blank'
62
62
  Dir[File.expand_path('../../app/models/**/*.rb', __FILE__)].each { |path| require(path) }
63
63
  Dir[File.expand_path('../../app/processors/**/*.rb', __FILE__)].each { |path| require(path) }
64
64
  Dir[File.expand_path('../../app/flows/**/*.rb', __FILE__)].each { |path| require(path) }
65
- Dir[File.expand_path('../../app/jobs/**/*.rb', __FILE__)].each { |path| require(path) }
66
- Dir[File.expand_path('../../app/**/*.rb', __FILE__)].each { |path| require(path) }
@@ -35,13 +35,11 @@ Gem::Specification.new do |gem|
35
35
  gem.test_files = gem.files.grep(/^spec/)
36
36
  gem.require_paths = ['lib']
37
37
 
38
- gem.add_dependency('wukong', '3.0.0.pre2')
39
- gem.add_dependency('wukong-hadoop')
40
- gem.add_dependency('wonderdog')
38
+ gem.add_dependency('wukong', '3.0.0.pre3')
39
+ gem.add_dependency('wukong-hadoop', '>= 0.0.2')
40
+ gem.add_dependency('wonderdog', '>= 0.0.2')
41
41
  gem.add_dependency('erubis')
42
-
42
+ gem.add_dependency('diffy')
43
43
  gem.add_dependency('rake', '~> 0.9')
44
- gem.add_development_dependency 'rspec', '~> 2'
45
-
46
44
  end
47
45
 
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: wukong-deploy
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.1
4
+ version: 0.0.2
5
5
  prerelease:
6
6
  platform: ruby
7
7
  authors:
@@ -11,7 +11,7 @@ authors:
11
11
  autorequire:
12
12
  bindir: bin
13
13
  cert_chain: []
14
- date: 2012-12-01 00:00:00.000000000 Z
14
+ date: 2012-12-17 00:00:00.000000000 Z
15
15
  dependencies:
16
16
  - !ruby/object:Gem::Dependency
17
17
  name: wukong
@@ -20,7 +20,7 @@ dependencies:
20
20
  requirements:
21
21
  - - '='
22
22
  - !ruby/object:Gem::Version
23
- version: 3.0.0.pre2
23
+ version: 3.0.0.pre3
24
24
  type: :runtime
25
25
  prerelease: false
26
26
  version_requirements: !ruby/object:Gem::Requirement
@@ -28,7 +28,7 @@ dependencies:
28
28
  requirements:
29
29
  - - '='
30
30
  - !ruby/object:Gem::Version
31
- version: 3.0.0.pre2
31
+ version: 3.0.0.pre3
32
32
  - !ruby/object:Gem::Dependency
33
33
  name: wukong-hadoop
34
34
  requirement: !ruby/object:Gem::Requirement
@@ -36,7 +36,7 @@ dependencies:
36
36
  requirements:
37
37
  - - ! '>='
38
38
  - !ruby/object:Gem::Version
39
- version: '0'
39
+ version: 0.0.2
40
40
  type: :runtime
41
41
  prerelease: false
42
42
  version_requirements: !ruby/object:Gem::Requirement
@@ -44,7 +44,7 @@ dependencies:
44
44
  requirements:
45
45
  - - ! '>='
46
46
  - !ruby/object:Gem::Version
47
- version: '0'
47
+ version: 0.0.2
48
48
  - !ruby/object:Gem::Dependency
49
49
  name: wonderdog
50
50
  requirement: !ruby/object:Gem::Requirement
@@ -52,7 +52,7 @@ dependencies:
52
52
  requirements:
53
53
  - - ! '>='
54
54
  - !ruby/object:Gem::Version
55
- version: '0'
55
+ version: 0.0.2
56
56
  type: :runtime
57
57
  prerelease: false
58
58
  version_requirements: !ruby/object:Gem::Requirement
@@ -60,7 +60,7 @@ dependencies:
60
60
  requirements:
61
61
  - - ! '>='
62
62
  - !ruby/object:Gem::Version
63
- version: '0'
63
+ version: 0.0.2
64
64
  - !ruby/object:Gem::Dependency
65
65
  name: erubis
66
66
  requirement: !ruby/object:Gem::Requirement
@@ -78,37 +78,37 @@ dependencies:
78
78
  - !ruby/object:Gem::Version
79
79
  version: '0'
80
80
  - !ruby/object:Gem::Dependency
81
- name: rake
81
+ name: diffy
82
82
  requirement: !ruby/object:Gem::Requirement
83
83
  none: false
84
84
  requirements:
85
- - - ~>
85
+ - - ! '>='
86
86
  - !ruby/object:Gem::Version
87
- version: '0.9'
87
+ version: '0'
88
88
  type: :runtime
89
89
  prerelease: false
90
90
  version_requirements: !ruby/object:Gem::Requirement
91
91
  none: false
92
92
  requirements:
93
- - - ~>
93
+ - - ! '>='
94
94
  - !ruby/object:Gem::Version
95
- version: '0.9'
95
+ version: '0'
96
96
  - !ruby/object:Gem::Dependency
97
- name: rspec
97
+ name: rake
98
98
  requirement: !ruby/object:Gem::Requirement
99
99
  none: false
100
100
  requirements:
101
101
  - - ~>
102
102
  - !ruby/object:Gem::Version
103
- version: '2'
104
- type: :development
103
+ version: '0.9'
104
+ type: :runtime
105
105
  prerelease: false
106
106
  version_requirements: !ruby/object:Gem::Requirement
107
107
  none: false
108
108
  requirements:
109
109
  - - ~>
110
110
  - !ruby/object:Gem::Version
111
- version: '2'
111
+ version: '0.9'
112
112
  description: ! " The Infochimps Platform is an end-to-end, managed solution for\n
113
113
  \ building Big Data applications. It integrates best-of-breed\n technologies like
114
114
  Hadoop, Storm, Kafka, MongoDB, ElasticSearch,\n HBase, &c. and provides simple
@@ -132,6 +132,7 @@ files:
132
132
  - README.md
133
133
  - Rakefile
134
134
  - bin/wu-deploy
135
+ - examples/.gitkeep
135
136
  - lib/wukong-deploy.rb
136
137
  - lib/wukong-deploy/configuration.rb
137
138
  - lib/wukong-deploy/console.rb
@@ -140,7 +141,13 @@ files:
140
141
  - lib/wukong-deploy/repo.rb
141
142
  - lib/wukong-deploy/tasks.rb
142
143
  - lib/wukong-deploy/templater.rb
144
+ - lib/wukong-deploy/templater/conflict_resolution.rb
145
+ - lib/wukong-deploy/templater/differ.rb
146
+ - lib/wukong-deploy/templater/messaging.rb
143
147
  - lib/wukong-deploy/version.rb
148
+ - spec/spec_helper.rb
149
+ - spec/support/integration_helper.rb
150
+ - spec/wukong-deploy/wu_deploy_spec.rb
144
151
  - templates/Gemfile.erb
145
152
  - templates/README.md.erb
146
153
  - templates/Rakefile.erb
@@ -179,5 +186,8 @@ rubygems_version: 1.8.23
179
186
  signing_key:
180
187
  specification_version: 3
181
188
  summary: Defines the deploy pack framework used by the Infochimps Platform
182
- test_files: []
189
+ test_files:
190
+ - spec/spec_helper.rb
191
+ - spec/support/integration_helper.rb
192
+ - spec/wukong-deploy/wu_deploy_spec.rb
183
193
  has_rdoc: