wukong-deploy 0.0.2 → 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,6 @@
1
+ --readme README.md
2
+ --markup markdown
3
+ -
4
+ Gemfile
5
+ LICENSE.md
6
+ README.md
data/Gemfile CHANGED
@@ -5,4 +5,6 @@ gemspec
5
5
  group :development do
6
6
  gem 'rake', '~> 0.9'
7
7
  gem 'rspec', '~> 2'
8
+ gem 'yard'
9
+ gem 'redcarpet'
8
10
  end
@@ -0,0 +1,95 @@
1
+ # License for Wukong-Deploy
2
+
3
+ The wukong code is __Copyright (c) 2011, 2012 Infochimps, Inc__
4
+
5
+ This code is licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at
6
+
7
+ http://www.apache.org/licenses/LICENSE-2.0
8
+
9
+ Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an **AS IS** BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License.
10
+
11
+ __________________________________________________________________________
12
+
13
+ # Apache License
14
+
15
+
16
+ Apache License
17
+ Version 2.0, January 2004
18
+ http://www.apache.org/licenses/
19
+
20
+ _TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION_
21
+
22
+ ## 1. Definitions.
23
+
24
+ * **License** shall mean the terms and conditions for use, reproduction, and distribution as defined by Sections 1 through 9 of this document.
25
+
26
+ * **Licensor** shall mean the copyright owner or entity authorized by the copyright owner that is granting the License.
27
+
28
+ * **Legal Entity** shall mean the union of the acting entity and all other entities that control, are controlled by, or are under common control with that entity. For the purposes of this definition, "control" means (i) the power, direct or indirect, to cause the direction or management of such entity, whether by contract or otherwise, or (ii) ownership of fifty percent (50%) or more of the outstanding shares, or (iii) beneficial ownership of such entity.
29
+
30
+ * **You** (or **Your**) shall mean an individual or Legal Entity exercising permissions granted by this License.
31
+
32
+ * **Source** form shall mean the preferred form for making modifications, including but not limited to software source code, documentation source, and configuration files.
33
+
34
+ * **Object** form shall mean any form resulting from mechanical transformation or translation of a Source form, including but not limited to compiled object code, generated documentation, and conversions to other media types.
35
+
36
+ * **Work** shall mean the work of authorship, whether in Source or Object form, made available under the License, as indicated by a copyright notice that is included in or attached to the work (an example is provided in the Appendix below).
37
+
38
+ * **Derivative Works** shall mean any work, whether in Source or Object form, that is based on (or derived from) the Work and for which the editorial revisions, annotations, elaborations, or other modifications represent, as a whole, an original work of authorship. For the purposes of this License, Derivative Works shall not include works that remain separable from, or merely link (or bind by name) to the interfaces of, the Work and Derivative Works thereof.
39
+
40
+ * **Contribution** shall mean any work of authorship, including the original version of the Work and any modifications or additions to that Work or Derivative Works thereof, that is intentionally submitted to Licensor for inclusion in the Work by the copyright owner or by an individual or Legal Entity authorized to submit on behalf of the copyright owner. For the purposes of this definition, "submitted" means any form of electronic, verbal, or written communication sent to the Licensor or its representatives, including but not limited to communication on electronic mailing lists, source code control systems, and issue tracking systems that are managed by, or on behalf of, the Licensor for the purpose of discussing and improving the Work, but excluding communication that is conspicuously marked or otherwise designated in writing by the copyright owner as "Not a Contribution."
41
+
42
+ * **Contributor** shall mean Licensor and any individual or Legal Entity on behalf of whom a Contribution has been received by Licensor and subsequently incorporated within the Work.
43
+
44
+ ## 2. Grant of Copyright License.
45
+
46
+ Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable copyright license to reproduce, prepare Derivative Works of, publicly display, publicly perform, sublicense, and distribute the Work and such Derivative Works in Source or Object form.
47
+
48
+ ## 3. Grant of Patent License.
49
+
50
+ Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable (except as stated in this section) patent license to make, have made, use, offer to sell, sell, import, and otherwise transfer the Work, where such license applies only to those patent claims licensable by such Contributor that are necessarily infringed by their Contribution(s) alone or by combination of their Contribution(s) with the Work to which such Contribution(s) was submitted. If You institute patent litigation against any entity (including a cross-claim or counterclaim in a lawsuit) alleging that the Work or a Contribution incorporated within the Work constitutes direct or contributory patent infringement, then any patent licenses granted to You under this License for that Work shall terminate as of the date such litigation is filed.
51
+
52
+ ## 4. Redistribution.
53
+
54
+ You may reproduce and distribute copies of the Work or Derivative Works thereof in any medium, with or without modifications, and in Source or Object form, provided that You meet the following conditions:
55
+
56
+ - (a) You must give any other recipients of the Work or Derivative Works a copy of this License; and
57
+ - (b) You must cause any modified files to carry prominent notices stating that You changed the files; and
58
+ - (c) You must retain, in the Source form of any Derivative Works that You distribute, all copyright, patent, trademark, and attribution notices from the Source form of the Work, excluding those notices that do not pertain to any part of the Derivative Works; and
59
+ - (d) If the Work includes a "NOTICE" text file as part of its distribution, then any Derivative Works that You distribute must include a readable copy of the attribution notices contained within such NOTICE file, excluding those notices that do not pertain to any part of the Derivative Works, in at least one of the following places: within a NOTICE text file distributed as part of the Derivative Works; within the Source form or documentation, if provided along with the Derivative Works; or, within a display generated by the Derivative Works, if and wherever such third-party notices normally appear. The contents of the NOTICE file are for informational purposes only and do not modify the License. You may add Your own attribution notices within Derivative Works that You distribute, alongside or as an addendum to the NOTICE text from the Work, provided that such additional attribution notices cannot be construed as modifying the License.
60
+
61
+ You may add Your own copyright statement to Your modifications and may provide additional or different license terms and conditions for use, reproduction, or distribution of Your modifications, or for any such Derivative Works as a whole, provided Your use, reproduction, and distribution of the Work otherwise complies with the conditions stated in this License.
62
+
63
+ ## 5. Submission of Contributions.
64
+
65
+ Unless You explicitly state otherwise, any Contribution intentionally submitted for inclusion in the Work by You to the Licensor shall be under the terms and conditions of this License, without any additional terms or conditions. Notwithstanding the above, nothing herein shall supersede or modify the terms of any separate license agreement you may have executed with Licensor regarding such Contributions.
66
+
67
+ ## 6. Trademarks.
68
+
69
+ This License does not grant permission to use the trade names, trademarks, service marks, or product names of the Licensor, except as required for reasonable and customary use in describing the origin of the Work and reproducing the content of the NOTICE file.
70
+
71
+ ## 7. Disclaimer of Warranty.
72
+
73
+ Unless required by applicable law or agreed to in writing, Licensor provides the Work (and each Contributor provides its Contributions) on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied, including, without limitation, any warranties or conditions of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A PARTICULAR PURPOSE. You are solely responsible for determining the appropriateness of using or redistributing the Work and assume any risks associated with Your exercise of permissions under this License.
74
+
75
+ ## 8. Limitation of Liability.
76
+
77
+ In no event and under no legal theory, whether in tort (including negligence), contract, or otherwise, unless required by applicable law (such as deliberate and grossly negligent acts) or agreed to in writing, shall any Contributor be liable to You for damages, including any direct, indirect, special, incidental, or consequential damages of any character arising as a result of this License or out of the use or inability to use the Work (including but not limited to damages for loss of goodwill, work stoppage, computer failure or malfunction, or any and all other commercial damages or losses), even if such Contributor has been advised of the possibility of such damages.
78
+
79
+ ## 9. Accepting Warranty or Additional Liability.
80
+
81
+ While redistributing the Work or Derivative Works thereof, You may choose to offer, and charge a fee for, acceptance of support, warranty, indemnity, or other liability obligations and/or rights consistent with this License. However, in accepting such obligations, You may act only on Your own behalf and on Your sole responsibility, not on behalf of any other Contributor, and only if You agree to indemnify, defend, and hold each Contributor harmless for any liability incurred by, or claims asserted against, such Contributor by reason of your accepting any such warranty or additional liability.
82
+
83
+ _END OF TERMS AND CONDITIONS_
84
+
85
+ ## APPENDIX: How to apply the Apache License to your work.
86
+
87
+ To apply the Apache License to your work, attach the following boilerplate notice, with the fields enclosed by brackets `[]` replaced with your own identifying information. (Don't include the brackets!) The text should be enclosed in the appropriate comment syntax for the file format. We also recommend that a file or class name and description of purpose be included on the same "printed page" as the copyright notice for easier identification within third-party archives.
88
+
89
+ > Copyright [yyyy] [name of copyright owner]
90
+ >
91
+ > Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at
92
+ >
93
+ > http://www.apache.org/licenses/LICENSE-2.0
94
+ >
95
+ > Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License.
data/bin/wu ADDED
@@ -0,0 +1,35 @@
1
+ #!/usr/bin/env ruby
2
+ require 'shellwords'
3
+ now=Time.now.strftime("%Y-%m-%d %H:%M:%S")
4
+ if ARGV.empty?
5
+ $stderr.puts "ERROR #{now} [wu ] -- Must provide a Wukong command to run. Try the --help option."
6
+ else
7
+ if ARGV.size == 1 && ARGV.first == '--help'
8
+ $stderr.puts <<EOF
9
+ usage: wu COMMAND [OPTIONS] [ARG] ...
10
+
11
+ wu is a wrapper for easy use of Wukong's command-line tools. It takes
12
+ your arguments, constructs the name of the proper wu-tool to call, and
13
+ prepends a call to bundle exec.
14
+
15
+ $ wu local ...
16
+
17
+ is equivalent to
18
+
19
+ $ bundle exec wu-local ...
20
+
21
+ You can run any of the wu-tools like
22
+
23
+ wu-local
24
+ wu-hadoop
25
+ wu-deploy
26
+
27
+ EOF
28
+ else
29
+ if ARGV.first =~ /^-/
30
+ $stderr.puts "ERROR ${now} [wu ] -- First argument must be the name of a wu tool to run, got <${1}>"
31
+ else
32
+ Kernel.exec "bundle exec wu-#{Shellwords.join(ARGV)}"
33
+ end
34
+ end
35
+ end
@@ -1,7 +1,4 @@
1
1
  #!/usr/bin/env ruby
2
2
 
3
3
  require 'wukong-deploy'
4
- settings = Wukong::Deploy::Configuration
5
- require 'wukong/boot'
6
- Wukong.boot!(settings)
7
- Wukong::Deploy::Driver.run(settings, *settings.rest)
4
+ Wukong::Deploy::DeployRunner.run
@@ -2,25 +2,59 @@
2
2
  # build-in widgets.
3
3
  require 'wukong'
4
4
 
5
- # Require just enough of wukong-hadoop to give us changes at the
6
- # processor level. The rest is only required when running the
7
- # 'wu-hadoop' program. Also grab configuration since we'll need it.
8
- require 'wukong-hadoop/extensions'
9
- require 'wukong-hadoop/configuration'
10
-
11
- # Grab configuration from Wonderdog.
12
- require 'wonderdog'
5
+ require_relative 'wukong-deploy/deploy_pack'
6
+ require_relative 'wukong-deploy/deploy_runner'
7
+ require_relative 'wukong-deploy/rake_runner'
13
8
 
14
9
  module Wukong
15
10
  # Provides some helper methods for loading the assets within a
16
11
  # deploy pack at runtime and for Wukong plugins to ask questions
17
12
  # about the deploy pack they're running in.
18
13
  module Deploy
19
- end
20
- end
14
+ include Plugin
15
+
16
+ # Configure the given settings object for use with Wukong::Deploy
17
+ #
18
+ # @param [Configliere::Param] settings the settings to configure
19
+ # @param [String] program the name of the currently executing program
20
+ def self.configure settings, program
21
+ settings.define(:environment, :description => "The environment to run in", :default => 'development', :flag => 'e', :env_var => 'ICS_PLATFORM_ENV')
22
+
23
+ case program
24
+ when 'wu-deploy'
25
+ settings.define(:dry_run, :description => "Don't actually create or modify anything", :type => :boolean, :default => false)
26
+ settings.define(:skip, :description => "Skip existing files", :type => :boolean, :default => false)
27
+ settings.define(:force, :description => "Overwrite existing files", :type => :boolean, :default => false)
28
+ when 'wu-hadoop'
29
+ require_relative('wukong-deploy/extensions')
30
+ settings[:command_prefix] = 'bundle exec'
31
+ end
32
+ end
21
33
 
34
+ # Boot the deploy pack, reading all available +settings+ and
35
+ # rooting it at the given +path+.
36
+ #
37
+ # @param [Configliere::Param] settings
38
+ # @param [String] path
39
+ def self.boot settings, path
40
+ # # Require just enough of wukong-hadoop to give us changes at the
41
+ # # processor level. The rest is only required when running the
42
+ # # 'wu-hadoop' program. Also grab configuration since we'll need it.
43
+ # require 'wukong-hadoop/extensions'
22
44
 
23
- # Now load the rest of the deploy pack.
24
- require 'wukong-deploy/deploy_pack'
25
- require 'wukong-deploy/configuration'
26
- require 'wukong-deploy/driver'
45
+ # # Grab configuration from Wonderdog.
46
+ # require 'wonderdog'
47
+
48
+
49
+ @pre_deploy_settings = settings.dup
50
+ @settings = settings
51
+ @root = Pathname.new(path)
52
+ read_common_settings
53
+ read_environment_settings
54
+ read_deploy_settings
55
+ read_remote_settings
56
+ @booted = true
57
+ end
58
+
59
+ end
60
+ end
@@ -1,11 +1,15 @@
1
1
  require 'irb'
2
2
  module Wukong
3
3
  module Deploy
4
+
5
+ # A class to wrap a basic IRB session.
4
6
  class Console
5
7
 
8
+ # Initialize this Console.
6
9
  def initialize
7
10
  end
8
11
 
12
+ # Start this Console.
9
13
  def run!
10
14
  ARGV.clear
11
15
  IRB.start
@@ -1,27 +1,13 @@
1
1
  module Wukong
2
2
  module Deploy
3
-
4
- # Boot the deploy pack, reading all available +settings+ and
5
- # rooting it at the given +path+.
6
- #
7
- # @param [Configliere::Param] settings
8
- # @param [String] path
9
- def self.boot! settings, path
10
- @pre_deploy_settings = settings.dup
11
- @settings = settings
12
- @root = Pathname.new(path)
13
- read_common_settings
14
- read_environment_settings
15
- read_remote_settings
16
- end
17
-
3
+
18
4
  # Return the root directory of this deploy pack.
19
5
  #
20
6
  # @return [Pathname]
21
7
  def self.root
22
8
  @root
23
9
  end
24
-
10
+
25
11
  # Recursively require each Ruby file +dir+.
26
12
  #
27
13
  # @example Requiring all .rb files anywhere within /lib/my_lib
@@ -29,15 +15,8 @@ module Wukong
29
15
  # Wukong::Deploy.require_recursive("lib/my_lib")
30
16
  #
31
17
  # @param [String] glob
32
- def self.require_recursive glob
33
- Dir[root.join("#{glob}/**/*.rb")].each { |path| require(path) }
34
- end
35
-
36
- # Return the name of the executable program currently running.
37
- #
38
- # @return [String]
39
- def self.executable
40
- File.basename($0)
18
+ def self.require_recursive glob, ext='.rb'
19
+ Dir[root.join("#{glob}/**/*#{ext}")].each { |path| require(path) }
41
20
  end
42
21
 
43
22
  # Return the current environment the deploy pack is in.
@@ -54,6 +33,14 @@ module Wukong
54
33
  @settings
55
34
  end
56
35
 
36
+ # Has this deploy pack been completely booted, all settings read,
37
+ # &c.
38
+ #
39
+ # @return [true, false]
40
+ def self.booted?
41
+ @booted
42
+ end
43
+
57
44
  # Return the settings the deploy pack had *before* it booted
58
45
  # itself -- these are used to pass to other tools when invoking
59
46
  # them, since they will read the deploy pack settings themselves
@@ -105,40 +92,58 @@ module Wukong
105
92
  def self.app_dir
106
93
  root.join('app')
107
94
  end
108
-
109
- # The logger for this deploy pack.
110
- #
111
- # @return [Logger]
112
- def self.logger
113
- return @logger if @logger
114
- # FIXME -- want to use the Wukong logger here...
115
- require 'logger'
116
- @logger ||= defined?(Log) ? Log : Logger.new
117
- end
118
95
 
119
96
  private
120
97
 
121
98
  # Read settings common across all environments from
122
- # config/settings.yml.
99
+ # `config/settings.yml`.
100
+ #
101
+ # Will also read any YAML files in the `config/settings` directory
102
+ # -- order is *not* guaranteed.
123
103
  def self.read_common_settings
124
104
  read_settings_from_file(settings, config_dir.join("settings.yml"))
105
+ if File.directory?(config_dir.join('settings'))
106
+ Dir[config_dir.join('settings','*.yml')].each do |path|
107
+ read_settings_from_file(settings, path)
108
+ end
109
+ end
125
110
  end
126
111
 
127
112
  # Read settings unique to this deploy pack's current environment
128
- # from config/ENVIRONMENT.yml.
113
+ # from config/environments/ENVIRONMENT.yml.
114
+ #
115
+ # Will also read any YAML files in the
116
+ # `config/environments/ENVIRONMENT` directory -- order is *not*
117
+ # guaranteed.
129
118
  def self.read_environment_settings
130
119
  read_settings_from_file(settings, config_dir.join("environments", "#{environment}.yml"))
120
+ if File.directory?(config_dir.join('environments', environment))
121
+ Dir[config_dir.join('environments', environment, '*.yml')].each do |path|
122
+ read_settings_from_file(settings, path)
123
+ end
124
+ end
125
+ end
126
+
127
+ # Read settings created by a deployment tool from
128
+ # `config/deploy.yml` and
129
+ # `config/environments/deploy-ENVIRONMENT.yml.
130
+ def self.read_deploy_settings
131
+ # pass 'false' here so we don't log an annoying warning message
132
+ # when not in a deployed environment.
133
+ read_settings_from_file(settings, config_dir.join("deploy.yml"), false)
134
+ read_settings_from_file(settings, config_dir.join("environments", "deploy-#{environment}.yml"), false)
131
135
  end
132
136
 
133
137
  # Update +settings+ with the configuration at the given +path+.
134
138
  #
135
139
  # @param [Configliere::Param] settings
136
140
  # @param [String, Pathname] path
137
- def self.read_settings_from_file settings, path
141
+ # @param [true, false] warn whether to log a warning message if no config file is found
142
+ def self.read_settings_from_file settings, path, warn=true
138
143
  if File.exist?(path) && File.readable?(path) && File.file?(path)
139
144
  settings.read(path)
140
145
  else
141
- logger.warn("Cannot read settings file at #{path}.")
146
+ Wukong::Log.warn("Could not read settings from path: #{path}") if warn
142
147
  end
143
148
  end
144
149
 
@@ -0,0 +1,72 @@
1
+ module Wukong
2
+ module Deploy
3
+
4
+ # A Runner class that implements wu-deploy.
5
+ class DeployRunner < Wukong::Runner
6
+
7
+ include Logging
8
+
9
+ usage 'ACTION'
10
+
11
+ description <<-EOF.gsub(/^ {8}/,'')
12
+ wu-deploy is a tool for creating and interacting with deploy packs.
13
+
14
+ You can create a new deploy pack
15
+
16
+ $ wu-deploy new my_app
17
+
18
+ The `--force' and `--skip' options can be used to control how conflict
19
+ resolution works when creating files. The `--dry_run` option can be
20
+ used to see what happens without doing it.
21
+
22
+ If you are within the directory of a deploy pack, you can enter an IRB
23
+ console with the deploy pack's environment already loaded:
24
+
25
+ $ wu-deploy console
26
+ EOF
27
+
28
+ # The action, or first argument given.
29
+ #
30
+ # @return [String]
31
+ def action
32
+ args.first
33
+ end
34
+
35
+ # The directory, or second argument given.
36
+ #
37
+ # @return [String]
38
+ def directory
39
+ args[1]
40
+ end
41
+
42
+ # Validate that the requested action is known and that its
43
+ # arguments are valid.
44
+ #
45
+ # @return [true]
46
+ # @raise [Wukong::Error] if the action or its arguments are invalid
47
+ def validate
48
+ case action
49
+ when 'new'
50
+ raise Error.new("Must provide a path to the root of the deploy pack you want to create") if directory.nil? || directory.blank?
51
+ when 'console'
52
+ else
53
+ raise Error.new("Invalid action: <#{action}>.")
54
+ end
55
+ true
56
+ end
57
+
58
+ # Run the requested action.
59
+ def run
60
+ case action
61
+ when 'new'
62
+ require_relative('templater')
63
+ Templater.new(File.expand_path(directory, Dir.pwd), settings).run!
64
+ when 'console'
65
+ require_relative('console')
66
+ Wukong::Deploy::Console.new.run!
67
+ end
68
+ end
69
+
70
+ end
71
+ end
72
+ end
@@ -0,0 +1,2 @@
1
+ require_relative('extensions/hadoop_invocation_override')
2
+ Wukong::Hadoop::HadoopRunner.class_eval { include Wukong::Deploy::HadoopInvocationOverride }
@@ -0,0 +1,13 @@
1
+ module Wukong
2
+ module Deploy
3
+ module HadoopInvocationOverride
4
+ def params_to_pass
5
+ Deploy.pre_deploy_settings
6
+ end
7
+ end
8
+ end
9
+ end
10
+
11
+
12
+
13
+
@@ -0,0 +1,42 @@
1
+ module Wukong
2
+ module Deploy
3
+
4
+ # A Runner class for booting up the environment within a Rake
5
+ # task.
6
+ class RakeRunner < Wukong::Runner
7
+
8
+ include Logging
9
+
10
+ # Load tasks that come with Wukong-Deploy.
11
+ def load
12
+ super()
13
+ load_rspec_tasks
14
+ load_generic_deploy_pack_tasks
15
+ load_this_deploy_packs_tasks
16
+ end
17
+
18
+ # Run the requested action.
19
+ def run
20
+ end
21
+
22
+ private
23
+
24
+ # :nodoc:
25
+ def load_rspec_tasks
26
+ require 'rspec/core/rake_task'
27
+ RSpec::Core::RakeTask.new(:spec)
28
+ end
29
+
30
+ # :nodoc:
31
+ def load_generic_deploy_pack_tasks
32
+ require 'wukong-deploy/tasks'
33
+ end
34
+
35
+ # :nodoc:
36
+ def load_this_deploy_packs_tasks
37
+ Wukong::Deploy.require_recursive('lib/tasks')
38
+ end
39
+
40
+ end
41
+ end
42
+ end
@@ -1,11 +1,20 @@
1
1
  module Wukong
2
2
  module Deploy
3
+
4
+ # A class to represent a deploy pack repository as a collection of
5
+ # files on disk.
3
6
  class Repo
4
7
 
8
+ # The names of the top level directories in the deploy pack.
5
9
  TOP_LEVEL_DIR_NAMES = %w[app config data lib log script spec tmp]
6
-
10
+
11
+ # The root directory where this deploy pack repo is or will be
12
+ # located.
7
13
  attr_reader :root
8
14
 
15
+ # Initialize a new deploy pack repo at the given `root`.
16
+ #
17
+ # @param [String] root
9
18
  def initialize root
10
19
  @root = Pathname.new(root)
11
20
  end
@@ -16,6 +25,9 @@ module Wukong
16
25
  end
17
26
  end
18
27
 
28
+ # The directories to create within this repo.
29
+ #
30
+ # @return [Array<String>]
19
31
  def dirs_to_create
20
32
  [
21
33
  root,
@@ -42,6 +54,10 @@ module Wukong
42
54
  ]
43
55
  end
44
56
 
57
+ # The files to template within this repo, relative to the repo's
58
+ # #root.
59
+ #
60
+ # @return [Array<String>]
45
61
  def files_to_template
46
62
  %w[
47
63
  config/boot.rb
@@ -1,13 +1,8 @@
1
1
  require 'rake'
2
2
 
3
- namespace 'bundler' do
4
- desc "Remove local bundle repository"
5
- task :clean do
6
- Wukong::Deploy.logger.info "Removing local bundle at /.bundle and /bundle"
7
- sh "rm -rf .bundle bundle"
8
- Wukong::Deploy.logger.info "Make sure to run 'bundle install --standalone' to re-create the bundle"
9
- end
10
-
11
- end
3
+ require 'yard'
4
+ YARD::Rake::YardocTask.new(:doc)
5
+
6
+ require 'rspec/core/rake_task'
7
+ RSpec::Core::RakeTask.new(:spec)
12
8
 
13
-
@@ -8,24 +8,39 @@ require_relative('templater/conflict_resolution')
8
8
 
9
9
  module Wukong
10
10
  module Deploy
11
+
12
+ # Templates out a deploy pack repo in a given directory.
11
13
  class Templater
12
14
 
15
+ # The Wukong::Deploy::Repo being templated.
13
16
  attr_accessor :repo
17
+
18
+ # The Configliere::Param settings.
14
19
  attr_accessor :options
15
20
 
16
21
  include FileUtils
17
22
  include Messaging
18
23
  include ConflictResolution
19
24
 
25
+ # Initialize a new Templater creating a deploy pack repository
26
+ # at the given `root` using the given `options`.
27
+ #
28
+ # @param [String] root
29
+ # @param [Hash] options
20
30
  def initialize root, options={}
21
31
  self.repo = Repo.new(root)
22
32
  self.options = options
23
33
  end
24
34
 
35
+ # Is this a dry run in which no files are actually created or
36
+ # modified on disk?
37
+ #
38
+ # @return [true, nil]
25
39
  def dry_run?
26
- @options[:dry_run]
40
+ options[:dry_run]
27
41
  end
28
42
 
43
+ # Run this templater.
29
44
  def run!
30
45
  if dry_run?
31
46
  puts "Would perform the following actions in #{repo.root}"
@@ -37,26 +52,40 @@ module Wukong
37
52
  create_gitkeeps
38
53
  create_gitignore
39
54
  end
55
+
56
+ # The directory containing templates used to generate the
57
+ # corresponding files in the new deploy pack repository.
58
+ #
59
+ # @return [Pathname]
60
+ def templates_dir
61
+ @templates_dir ||= Pathname.new(File.expand_path('../../../templates', __FILE__))
62
+ end
40
63
 
64
+ private
65
+
66
+ # :nodoc:
41
67
  def create_dirs
42
68
  repo.dirs_to_create.each do |dir|
43
69
  create_directory(dir)
44
70
  end
45
71
  end
46
72
 
73
+ # :nodoc:
47
74
  def create_templates
48
75
  repo.files_to_template.each do |repo_path|
49
76
  create_template(templates_dir.join("#{repo_path}.erb"), repo.root.join(repo_path))
50
77
  end
51
78
  end
52
79
 
80
+ # :nodoc:
53
81
  def create_template input_path, output_path, binding={}
54
82
  input = File.read(input_path)
55
83
  erb = Erubis::Eruby.new(input)
56
84
  content = erb.result(binding)
57
85
  create_file(content, output_path)
58
86
  end
59
-
87
+
88
+ # :nodoc:
60
89
  def create_gitkeeps
61
90
  repo.dirs_to_create.each do |dir|
62
91
  if Dir[File.join(dir, '*')].empty?
@@ -65,20 +94,17 @@ module Wukong
65
94
  end
66
95
  end
67
96
 
97
+ # :nodoc:
68
98
  def create_gitignore
69
99
  create_template(templates_dir.join('gitignore'), repo.root.join('.gitignore'))
70
100
  end
71
101
 
72
- def templates_dir
73
- @templates_dir ||= Pathname.new(File.expand_path('../../../templates', __FILE__))
74
- end
75
-
76
- private
77
-
102
+ # :nodoc:
78
103
  def empty_file
79
104
  ""
80
105
  end
81
-
106
+
107
+ # :nodoc:
82
108
  def create_file content, path
83
109
  if File.exist?(path)
84
110
  handle_conflict(content, path)
@@ -88,12 +114,14 @@ module Wukong
88
114
  end
89
115
  end
90
116
 
117
+ # :nodoc:
91
118
  def create_directory(dir)
92
119
  message_create(dir)
93
120
  return if dry_run?
94
121
  mkdir_p(dir)
95
122
  end
96
123
 
124
+ # :nodoc:
97
125
  def write_file content, path
98
126
  return if dry_run?
99
127
  File.open(path, 'w') { |f| f.write(content) }
@@ -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.2'
5
+ VERSION = '0.1.0'
6
6
  end
7
7
  end
@@ -9,7 +9,7 @@ describe 'wu-deploy' do
9
9
  subject { command('wu-deploy') }
10
10
  it { should exit_with(:non_zero) }
11
11
  it "displays a help message" do
12
- should have_stderr(/usage: wu-deploy/)
12
+ should have_stderr(/invalid action/i)
13
13
  end
14
14
  end
15
15
 
@@ -17,24 +17,57 @@ source :rubygems
17
17
  # Here's a link to the [Bundler documentation](http://gembundler.com/)
18
18
  # for your convenience.
19
19
 
20
+ #
21
+ # = Framework
22
+ #
23
+ # The following libraries are part of the deploy pack framework. You
24
+ # shouldn't need to change these.
25
+ #
20
26
 
27
+ # The core library: processors, dataflows, testing, &c.
28
+ #
29
+ # Provides
30
+ #
31
+ # - wu-local
32
+ gem 'wukong', '3.0.0'
21
33
 
34
+ # Model Hadoop jobs locally and run them on a cluster.
35
+ #
36
+ # Provides
37
+ #
38
+ # - wu-hadoop
39
+ gem 'wukong-hadoop', '0.1.0'
22
40
 
41
+ # Lets Hadoop streaming work with Elasticsearch.
42
+ gem 'wonderdog', '0.1.0'
23
43
 
24
-
44
+ # Provides an interface into Wukong dataflows accessible from Storm.
25
45
  #
26
- # = Framework
46
+ # Provides
27
47
  #
28
- # The following libraries are part of the deploy pack framework. You
29
- # shouldn't need to change these.
48
+ # - wu-storm
49
+ gem 'wukong-storm', '0.1.0'
50
+
51
+ # Lets you load JSON blobs into data stores.
30
52
  #
53
+ # Provides
54
+ #
55
+ # - wu-load
56
+ # - wu-source
57
+ gem 'wukong-load', '0.1.0'
31
58
 
32
- gem 'wukong-deploy', :git => 'https://github.com/infochimps-labs/wukong-deploy'
33
- gem 'wukong', :git => 'https://github.com/infochimps-labs/wukong', :branch => '3.0.0'
34
- gem 'wukong-hadoop', :git => 'https://github.com/infochimps-labs/wukong-hadoop'
35
- gem 'wonderdog', :git => 'https://github.com/infochimps-labs/wonderdog'
36
- gem 'vayacondios-client', :git => 'https://github.com/infochimps-labs/vayacondios'
59
+ # Framework for gluing code together.
60
+ #
61
+ # Provides
62
+ #
63
+ # - wu-deploy
64
+ gem 'wukong-deploy', '0.1.0'
37
65
 
38
66
  group :development do
67
+ gem 'yard'
68
+ gem 'redcarpet'
69
+ end
70
+
71
+ group :test do
39
72
  gem 'rspec'
40
73
  end
@@ -1,4 +1,4 @@
1
- f# Welcome to the Infochimps Platform!
1
+ # Welcome to the Infochimps Platform!
2
2
 
3
3
  The [Infochimps Platform](http://www.infochimps.com) is an end-to-end,
4
4
  managed solution for building Big Data applications. It integrates
@@ -86,17 +86,11 @@ From within the root of your deploy pack run the following commands
86
86
 
87
87
  ```
88
88
  $ sudo gem install bundler
89
- $ bundle install --standalone
89
+ $ bundle install
90
90
  ```
91
91
 
92
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.
93
+ want to run `rbenv exec bundle install`.
100
94
 
101
95
  ### Configuration
102
96
 
@@ -1,10 +1,13 @@
1
- require_relative 'config/environment'
2
- require 'wukong-deploy/tasks'
3
- require 'rake'
1
+ # Require the environment
2
+ require_relative('config/environment')
3
+
4
+ # Require the Wukong rake helper which gives us the :environment task.
5
+ require 'wukong/rake_helper'
4
6
 
5
- require 'rspec/core/rake_task'
6
- RSpec::Core::RakeTask.new(:spec)
7
+ # Load all pre-defined tasks from the deploy pack library.
8
+ require 'wukong-deploy/tasks'
7
9
 
8
- Wukong::Deploy.require_recursive('lib/tasks')
10
+ # Load all tasks within this deploy pack.
11
+ Dir[File.join(File.expand_path('../lib/tasks', __FILE__), '*')].each { |path| require path }
9
12
 
10
13
  task :default => :spec
@@ -2,9 +2,10 @@
2
2
  #
3
3
  # Loads the Ruby language framework and activates Bundler.
4
4
  #
5
- # We use a standalone bundle installation becaues it makes it easier
6
- # to have non-Ruby code in underlying frameworks interact with the
7
- # deploy pack.
5
+ # We can use a system-wide bundle installation _or_ a standalone
6
+ # bundle installation. If a standalone installation exists (at
7
+ # /bundle/bundler/setup.rb), we will detect and use it. Otherwise, we
8
+ # fall back on the system-wide bundle installation.
8
9
  #
9
10
  # Make sure you install the bundle locally with the following command:
10
11
  #
@@ -12,10 +13,14 @@
12
13
  #
13
14
  # $ bundle install --standalone
14
15
 
15
- setup_path = File.expand_path("../../bundle/bundler/setup.rb", __FILE__)
16
- begin
17
- require setup_path
18
- rescue LoadError => e
19
- $stderr.puts("Failed to require \"#{setup_path}\". Try running\n\n bundle install --standalone\n\n")
20
- exit(1)
16
+ local_setup_path = File.expand_path("../../bundle/bundler/setup.rb", __FILE__)
17
+ if File.exist?(local_setup_path)
18
+ begin
19
+ require local_setup_path
20
+ rescue LoadError => e
21
+ $stderr.puts("Local Bundle installation at #{local_setup_path} is corrupted. Try running\n\n rm -rf bundle .bundle\n bundle install --standalone\n\n")
22
+ exit(1)
23
+ end
24
+ else
25
+ require 'bundler/setup'
21
26
  end
@@ -4,5 +4,3 @@
4
4
  # runtime environment of your application.
5
5
 
6
6
  require_relative("application")
7
-
8
- Wukong::Deploy.boot!(Wukong::Deploy::Configuration, File.expand_path("../../", __FILE__))
@@ -31,15 +31,13 @@ Gem::Specification.new do |gem|
31
31
  EOF
32
32
 
33
33
  gem.files = `git ls-files`.split("\n")
34
- gem.executables = ['wu-deploy']
34
+ gem.executables = ['wu-deploy','wu']
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.pre3')
39
- gem.add_dependency('wukong-hadoop', '>= 0.0.2')
40
- gem.add_dependency('wonderdog', '>= 0.0.2')
38
+ gem.add_dependency('wukong', '3.0.0')
39
+ gem.add_dependency('rake', '~> 0.9')
41
40
  gem.add_dependency('erubis')
42
41
  gem.add_dependency('diffy')
43
- gem.add_dependency('rake', '~> 0.9')
44
42
  end
45
43
 
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.2
4
+ version: 0.1.0
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-17 00:00:00.000000000 Z
14
+ date: 2013-02-22 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.pre3
23
+ version: 3.0.0
24
24
  type: :runtime
25
25
  prerelease: false
26
26
  version_requirements: !ruby/object:Gem::Requirement
@@ -28,39 +28,23 @@ dependencies:
28
28
  requirements:
29
29
  - - '='
30
30
  - !ruby/object:Gem::Version
31
- version: 3.0.0.pre3
31
+ version: 3.0.0
32
32
  - !ruby/object:Gem::Dependency
33
- name: wukong-hadoop
34
- requirement: !ruby/object:Gem::Requirement
35
- none: false
36
- requirements:
37
- - - ! '>='
38
- - !ruby/object:Gem::Version
39
- version: 0.0.2
40
- type: :runtime
41
- prerelease: false
42
- version_requirements: !ruby/object:Gem::Requirement
43
- none: false
44
- requirements:
45
- - - ! '>='
46
- - !ruby/object:Gem::Version
47
- version: 0.0.2
48
- - !ruby/object:Gem::Dependency
49
- name: wonderdog
33
+ name: rake
50
34
  requirement: !ruby/object:Gem::Requirement
51
35
  none: false
52
36
  requirements:
53
- - - ! '>='
37
+ - - ~>
54
38
  - !ruby/object:Gem::Version
55
- version: 0.0.2
39
+ version: '0.9'
56
40
  type: :runtime
57
41
  prerelease: false
58
42
  version_requirements: !ruby/object:Gem::Requirement
59
43
  none: false
60
44
  requirements:
61
- - - ! '>='
45
+ - - ~>
62
46
  - !ruby/object:Gem::Version
63
- version: 0.0.2
47
+ version: '0.9'
64
48
  - !ruby/object:Gem::Dependency
65
49
  name: erubis
66
50
  requirement: !ruby/object:Gem::Requirement
@@ -93,22 +77,6 @@ dependencies:
93
77
  - - ! '>='
94
78
  - !ruby/object:Gem::Version
95
79
  version: '0'
96
- - !ruby/object:Gem::Dependency
97
- name: rake
98
- requirement: !ruby/object:Gem::Requirement
99
- none: false
100
- requirements:
101
- - - ~>
102
- - !ruby/object:Gem::Version
103
- version: '0.9'
104
- type: :runtime
105
- prerelease: false
106
- version_requirements: !ruby/object:Gem::Requirement
107
- none: false
108
- requirements:
109
- - - ~>
110
- - !ruby/object:Gem::Version
111
- version: '0.9'
112
80
  description: ! " The Infochimps Platform is an end-to-end, managed solution for\n
113
81
  \ building Big Data applications. It integrates best-of-breed\n technologies like
114
82
  Hadoop, Storm, Kafka, MongoDB, ElasticSearch,\n HBase, &c. and provides simple
@@ -123,21 +91,27 @@ description: ! " The Infochimps Platform is an end-to-end, managed solution for
123
91
  email: coders@infochimps.com
124
92
  executables:
125
93
  - wu-deploy
94
+ - wu
126
95
  extensions: []
127
96
  extra_rdoc_files: []
128
97
  files:
129
98
  - .gitignore
130
99
  - .rspec
100
+ - .yardopts
131
101
  - Gemfile
102
+ - LICENSE.md
132
103
  - README.md
133
104
  - Rakefile
105
+ - bin/wu
134
106
  - bin/wu-deploy
135
107
  - examples/.gitkeep
136
108
  - lib/wukong-deploy.rb
137
- - lib/wukong-deploy/configuration.rb
138
109
  - lib/wukong-deploy/console.rb
139
110
  - lib/wukong-deploy/deploy_pack.rb
140
- - lib/wukong-deploy/driver.rb
111
+ - lib/wukong-deploy/deploy_runner.rb
112
+ - lib/wukong-deploy/extensions.rb
113
+ - lib/wukong-deploy/extensions/hadoop_invocation_override.rb
114
+ - lib/wukong-deploy/rake_runner.rb
141
115
  - lib/wukong-deploy/repo.rb
142
116
  - lib/wukong-deploy/tasks.rb
143
117
  - lib/wukong-deploy/templater.rb
@@ -1,47 +0,0 @@
1
- module Wukong
2
- module Deploy
3
-
4
- # Pass in +settings+ that need to be modified for deploy-specific
5
- # settings *before* they are resolved.
6
- #
7
- # @param [Configliere::Param] settings
8
- # @return [Configliere::Param] the newly configured settings
9
- def self.configure settings
10
- settings.define(:environment, :description => "The environment to run in", :default => 'development', :flag => 'e', :env_var => 'ICS_PLATFORM_ENV')
11
-
12
- case executable
13
- when 'wu-hadoop'
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
39
- end
40
- settings
41
- end
42
-
43
- # All configuration for Wukong::Deploy lives in this object.
44
- Configuration = configure(Configliere::Param.new) unless defined?(Configuration)
45
- end
46
-
47
- end
@@ -1,39 +0,0 @@
1
- module Wukong
2
- module Deploy
3
- class Driver
4
-
5
- attr_accessor :settings
6
- attr_accessor :args
7
-
8
- def self.run(settings, *args)
9
- begin
10
- new(settings,*args).run!
11
- rescue Wukong::Error => e
12
- $stderr.puts(e.message)
13
- exit(1)
14
- end
15
- end
16
-
17
- def run!
18
- case args.first
19
- when 'new'
20
- require_relative('templater')
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?
22
- Templater.new(File.expand_path(args[1], Dir.pwd), settings).run!
23
- when 'console'
24
- require_relative('console')
25
- Wukong::Deploy::Console.new.run!
26
- else
27
- settings.dump_help
28
- exit(2)
29
- end
30
- end
31
-
32
- def initialize settings, *args
33
- self.settings = settings
34
- self.args = args
35
- end
36
-
37
- end
38
- end
39
- end