Permalink
Browse files

Rename command to clone:create, Add clone:sharing, clone:config, clon…

…e:features
  • Loading branch information...
1 parent 86fa209 commit 74e84c57a6529b4ed20ba6f2c303a903b25a1df1 @eckardt committed Jan 7, 2013
Showing with 326 additions and 162 deletions.
  1. +1 −1 README.md
  2. +1 −1 init.rb
  3. +0 −82 lib/clone/heroku/command/apps.rb
  4. +144 −0 lib/clone/heroku/command/clone.rb
  5. +157 −51 spec/clone_spec.rb
  6. +23 −27 spec/spec_helper.rb
View
@@ -26,7 +26,7 @@ You'll start with an existing app which has some custom config variables and col
Now, creating an exact copy of this app is easy
- $ heroku apps:clone
+ $ heroku clone:create
Creating dry-oasis-7199-clone-19b3... done, stack is cedar
http://dry-oasis-7199-clone-19b3.herokuapp.com/ | git@heroku.com:dry-oasis-7199-clone-19b3.git
Copying someone@company.com to dry-oasis-7199-clone-19b3 collaborators... done
View
@@ -1 +1 @@
-require 'clone/heroku/command/apps'
+require 'clone/heroku/command/clone'
@@ -1,82 +0,0 @@
-require 'heroku/command/base'
-require 'securerandom'
-
-class Heroku::Command::Apps < Heroku::Command::Base
-
- # apps:clone [NAME]
- #
- # Create a new app which is a clone of an existing app
- #
- # --addons ADDONS # a comma-delimited list of addons to install
- # -a, --app APP # the app which should be cloned
- # -b, --buildpack BUILDPACK # a buildpack url to use for this app
- # -n, --no-remote # don't create a git remote
- # -r, --remote REMOTE # the git remote to create, default "heroku"
- # -s, --stack STACK # the stack on which to create the app
- # -c, --no-collabs # don't copy over the collaborators
- # -v, --no-vars # don't copy over the config vars
- #
- #Examples:
- #
- # $ heroku apps:clone
- # Creating floating-dragon-42-clone-e153d5... done, stack is cedar
- # http://floating-dragon-42.heroku.com/ | git@heroku.com:floating-dragon-42.git
- #
- # $ heroku apps:clone -s bamboo
- # Creating floating-dragon-42-clone-e153d5... done, stack is bamboo-mri-1.9.2
- # http://floating-dragon-42.herokuapp.com/ | git@heroku.com:floating-dragon-42.git
- #
- # # specify a name
- # $ heroku apps:clone example
- # Creating example... done, stack is cedar
- # http://example.heroku.com/ | git@heroku.com:example.git
- #
- # # create a staging app
- # $ heroku apps:clone example-staging --remote staging
- #
- def clone
- target_app = shift_argument || "#{app}-clone-#{SecureRandom.hex(2)}"
- source_app = app
- options[:app] = target_app
-
- create
-
- unless options[:no_collabs].is_a? FalseClass
- copy_collaborators(source_app, target_app)
- end
-
- unless options[:no_vars].is_a? FalseClass
- copy_config_vars(source_app, target_app)
- end
- end
-
- private
-
- def copy_collaborators(app, target_name)
- collaborators = api.get_collaborators(app).body.map{|collab| collab['email']}
- target_collaborators = api.get_collaborators(target_name).body.map{|collab| collab['email']}
-
- (collaborators - target_collaborators).each do |email|
- action("Copying #{email} to #{target_name} collaborators") do
- api.post_collaborator(target_name, email)
- end
- end
- end
-
-
- def copy_config_vars(app, target_name)
- vars = api.get_config_vars(app).body
-
- action("Copying config vars from #{app} and restarting #{target_name}") do
- api.put_config_vars(target_name, vars)
-
- @status = begin
- if release = api.get_release(target_name, 'current').body
- release['name']
- end
- rescue Heroku::API::Errors::RequestFailed => e
- end
- end
- end
-
-end
@@ -0,0 +1,144 @@
+require 'heroku/command/base'
+require 'securerandom'
+
+class Heroku::Command::Clone < Heroku::Command::Base
+
+ # clone:create [NAME]
+ #
+ # Create a new app which is a clone of an existing app
+ #
+ # --addons ADDONS # a comma-delimited list of addons to install
+ # -a, --app APP # the app which should be cloned
+ # -b, --buildpack BUILDPACK # a buildpack url to use for this app
+ # -n, --no-remote # don't create a git remote
+ # -r, --remote REMOTE # the git remote to create, default "heroku"
+ # -s, --stack STACK # the stack on which to create the app
+ # -c, --no-collabs # don't copy over the collaborators
+ # -v, --no-vars # don't copy over the config vars
+ # -f, --no-features # don't copy over the labs features
+ #
+ #Examples:
+ #
+ # $ heroku clone:create
+ # Creating floating-dragon-42-clone-e153d5... done, stack is cedar
+ # http://floating-dragon-42.heroku.com/ | git@heroku.com:floating-dragon-42.git
+ #
+ # $ heroku clone:create -s bamboo
+ # Creating floating-dragon-42-clone-e153d5... done, stack is bamboo-mri-1.9.2
+ # http://floating-dragon-42.herokuapp.com/ | git@heroku.com:floating-dragon-42.git
+ #
+ # # specify a name
+ # $ heroku clone:create example
+ # Creating example... done, stack is cedar
+ # http://example.heroku.com/ | git@heroku.com:example.git
+ #
+ # # create a staging app
+ # $ heroku clone:create example-staging --remote staging
+ #
+ def create
+ apps_command.create
+
+ unless options[:no_collabs].is_a? FalseClass
+ sharing
+ end
+
+ unless options[:no_vars].is_a? FalseClass
+ config
+ end
+
+ unless options[:no_features].is_a? FalseClass
+ features
+ end
+ end
+
+ # clone:sharing NAME
+ #
+ # Copy the list of collaborators of one app to another app
+ #
+ # -a, --app APP # app whose collaborators should be copied
+ #
+ #Examples:
+ #
+ # $ heroku clone:sharing example-clone -a example
+ # Copying collaborator@example.com to example-clone collaborators
+ #
+ def sharing
+ collaborators = api.get_collaborators(app).body.map{|collab| collab['email']}
+ target_collaborators = api.get_collaborators(target_app).body.map{|collab| collab['email']}
+
+ (collaborators - target_collaborators).each do |email|
+ action("Copying #{email} to #{target_app} collaborators") do
+ api.post_collaborator(target_app, email)
+ end
+ end
+ end
+
+ # clone:config NAME
+ #
+ # Copy the config of one app to another app
+ #
+ # -a, --app APP # app whose config should be copied
+ #
+ #Examples:
+ #
+ # $ heroku clone:config example-clone -a example
+ # Copying config vars from example and restarting example-clone
+ #
+ def config
+ vars = api.get_config_vars(app).body
+
+ action("Copying config vars from #{app} and restarting #{target_app}") do
+ api.put_config_vars(target_app, vars)
+
+ @status = begin
+ if release = api.get_release(target_app, 'current').body
+ release['name']
+ end
+ rescue Heroku::API::Errors::RequestFailed => e
+ end
+ end
+ end
+
+ # clone:features NAME
+ #
+ # Copy the features of one app to another app
+ #
+ # -a, --app APP # app whose features should be copied
+ #
+ #Examples:
+ #
+ # $ heroku clone:features example-clone -a example
+ # Adding user_env_compile to example-clone
+ # Deleting sigterm-all from example-clone
+ #
+ def features
+ features = Hash[api.get_features(app).body.map{|feature| [feature['name'], feature['enabled']]}]
+ actual_features = Hash[api.get_features(target_app).body.map{|feature| [feature['name'], feature['enabled']]}]
+
+ features_to_enable = features.select{|feature, enabled| enabled && !actual_features[feature]}
+ features_to_disable = actual_features.select{|feature, enabled| enabled && !features[feature]}
+
+ action("Copying labs features from #{app} and restarting #{target_app}") do
+ features_to_enable.each do |feature|
+ puts "Adding #{feature} to #{target_app}"
+ api.post_feature(feature, target_app)
+ end
+
+ features_to_disable.each do |feature|
+ puts "Deleting #{feature} from #{target_app}"
+ api.delete_feature(feature, target_app)
+ end
+ end
+ end
+
+ private
+
+ def apps_command
+ @apps_command ||= Heroku::Command::Apps.new(@args, @options.merge(app: target_app))
+ end
+
+ def target_app
+ @target_app ||= shift_argument || "#{app}-clone-#{SecureRandom.hex(2)}"
+ end
+
+end
Oops, something went wrong.

0 comments on commit 74e84c5

Please sign in to comment.