diff --git a/lib/engineyard-serverside-adapter/action.rb b/lib/engineyard-serverside-adapter/action.rb index e51a869..8d1acfc 100644 --- a/lib/engineyard-serverside-adapter/action.rb +++ b/lib/engineyard-serverside-adapter/action.rb @@ -1,5 +1,7 @@ require 'escape' require 'pathname' +require 'engineyard-serverside-adapter/option' +require 'engineyard-serverside-adapter/arguments' module EY module Serverside @@ -8,11 +10,9 @@ class Action def initialize(options = {}, &block) @gem_bin_path = Pathname.new(options[:gem_bin_path] || "") - arguments = options[:arguments] || Arguments.new - block.call arguments if block - @serverside_version = arguments.serverside_version - - extract_state_from_arguments(arguments) + @arguments = options[:arguments] || Arguments.new + block.call @arguments if block + @serverside_version = @arguments[:serverside_version] validate! end @@ -22,24 +22,22 @@ def call(&block) end def verbose - @state[:verbose] + @arguments[:verbose] end class << self attr_accessor :options - def option(name, type, extra={:required => false}) - self.options ||= {} - options[name] = extra.merge({:type => type}) + def option(*args) + self.options ||= [] + options << Option.new(*args) end end private - def extract_state_from_arguments(arguments) - @state = self.class.options.inject({}) do |acc, (option_name, option_attrs)| - acc.merge(option_name => arguments.send(option_name)) - end + def applicable_options + @applicable_options ||= self.class.options.select { |option| option.on_version?(engineyard_serverside_version) } end def check_and_install_command @@ -77,18 +75,16 @@ def gem_path def action_command cmd = Command.new(@gem_bin_path, engineyard_serverside_version, *task) - @state.each do |option_name, value| - option_type = self.class.options[option_name][:type] - switch = "--" + option_name.to_s.gsub(/_/, '-') - cmd.send("#{option_type}_argument", switch, value) + applicable_options.each do |option| + cmd.send("#{option.type}_argument", option.to_switch, @arguments[option.name]) end cmd end def validate! - self.class.options.each do |option_name, option_attrs| - if option_attrs[:required] && !@state[option_name] - raise ArgumentError, "Required field '#{option_name}' not provided." + applicable_options.each do |option| + if option.required? && !@arguments[option.name] + raise ArgumentError, "Required field '#{option.name}' not provided." end end end diff --git a/lib/engineyard-serverside-adapter/arguments.rb b/lib/engineyard-serverside-adapter/arguments.rb index 0464720..1f53ef7 100644 --- a/lib/engineyard-serverside-adapter/arguments.rb +++ b/lib/engineyard-serverside-adapter/arguments.rb @@ -6,17 +6,44 @@ class Arguments def self.nonempty_writer(*names) names.each do |name| define_method(:"#{name}=") do |value| - if value.to_s.empty? + if value.nil? || value.to_s.empty? raise ArgumentError, "Value for '#{name}' must be non-empty." end - instance_variable_set("@#{name}", value) + self[name] = value + end + end + end + + def self.writer(*names) + names.each do |name| + define_method(:"#{name}=") do |value| + self[name] = value end end end - attr_reader :app, :environment_name, :account_name, :config, :framework_env, :instances, :migrate, :ref, :repo, :serverside_version, :stack, :verbose nonempty_writer :app, :environment_name, :account_name, :framework_env, :ref, :repo, :serverside_version, :stack - attr_writer :config, :migrate, :verbose + writer :config, :migrate, :verbose + + def initialize(data={}) + @data = data + end + + def dup + self.class.new(@data.dup) + end + + def []=(key, val) + @data[key.to_sym] = val + end + + def [](key) + @data[key.to_sym] + end + + def key?(key) + @data.key?(key.to_sym) + end def instances=(instances) unless instances.respond_to?(:each) @@ -33,11 +60,15 @@ def instances=(instances) end end - @instances = instances + self[:instances] = instances end def serverside_version=(value) - @serverside_version = Gem::Version.new(value).to_s + self[:serverside_version] = Gem::Version.create(value).to_s + end + + def method_missing(meth, *) + key?(meth) ? self[meth] : super end end diff --git a/lib/engineyard-serverside-adapter/deploy.rb b/lib/engineyard-serverside-adapter/deploy.rb index 3729e9b..81fdf1c 100644 --- a/lib/engineyard-serverside-adapter/deploy.rb +++ b/lib/engineyard-serverside-adapter/deploy.rb @@ -4,8 +4,8 @@ class Adapter class Deploy < Action option :app, :string, :required => true - option :account_name, :string, :required => true - option :environment_name, :string, :required => true + option :account_name, :string, :required => true, :version => '>=2.0.0' + option :environment_name, :string, :required => true, :version => '>=2.0.0' option :stack, :string, :required => true option :instances, :instances, :required => true option :config, :json diff --git a/lib/engineyard-serverside-adapter/disable_maintenance.rb b/lib/engineyard-serverside-adapter/disable_maintenance.rb index 37a306d..88f53bb 100644 --- a/lib/engineyard-serverside-adapter/disable_maintenance.rb +++ b/lib/engineyard-serverside-adapter/disable_maintenance.rb @@ -4,8 +4,8 @@ class Adapter class DisableMaintenance < Action option :app, :string, :required => true - option :account_name, :string, :required => true - option :environment_name, :string, :required => true + option :account_name, :string, :required => true, :version => '>=2.0.0' + option :environment_name, :string, :required => true, :version => '>=2.0.0' option :instances, :instances, :required => true option :verbose, :boolean diff --git a/lib/engineyard-serverside-adapter/enable_maintenance.rb b/lib/engineyard-serverside-adapter/enable_maintenance.rb index 6dc4ff3..45a30bf 100644 --- a/lib/engineyard-serverside-adapter/enable_maintenance.rb +++ b/lib/engineyard-serverside-adapter/enable_maintenance.rb @@ -4,8 +4,8 @@ class Adapter class EnableMaintenance < Action option :app, :string, :required => true - option :account_name, :string, :required => true - option :environment_name, :string, :required => true + option :account_name, :string, :required => true, :version => '>=2.0.0' + option :environment_name, :string, :required => true, :version => '>=2.0.0' option :instances, :instances, :required => true option :verbose, :boolean diff --git a/lib/engineyard-serverside-adapter/integrate.rb b/lib/engineyard-serverside-adapter/integrate.rb index a1459b9..11e49cd 100644 --- a/lib/engineyard-serverside-adapter/integrate.rb +++ b/lib/engineyard-serverside-adapter/integrate.rb @@ -4,8 +4,8 @@ class Adapter class Integrate < Action option :app, :string, :required => true - option :account_name, :string, :required => true - option :environment_name, :string, :required => true + option :account_name, :string, :required => true, :version => '>=2.0.0' + option :environment_name, :string, :required => true, :version => '>=2.0.0' option :stack, :string, :required => true option :instances, :instances, :required => true option :framework_env, :string, :required => true diff --git a/lib/engineyard-serverside-adapter/option.rb b/lib/engineyard-serverside-adapter/option.rb new file mode 100644 index 0000000..e376722 --- /dev/null +++ b/lib/engineyard-serverside-adapter/option.rb @@ -0,0 +1,28 @@ +module EY + module Serverside + class Adapter + class Option + attr_reader :name, :type + + def initialize(name, type, options={:required => false}) + @name, @type = name, type + @version_requirement = Gem::Requirement.create(options[:version]) if options[:version] + @options = options + end + + def to_switch + "--#{@name}".gsub(/_/, '-') + end + + def on_version?(version) + !@version_requirement or @version_requirement.satisfied_by?(Gem::Version.create(version)) + end + + def required? + @options[:required] + end + + end + end + end +end diff --git a/lib/engineyard-serverside-adapter/restart.rb b/lib/engineyard-serverside-adapter/restart.rb index fa21d4f..500bf14 100644 --- a/lib/engineyard-serverside-adapter/restart.rb +++ b/lib/engineyard-serverside-adapter/restart.rb @@ -4,8 +4,8 @@ class Adapter class Restart < Action option :app, :string, :required => true - option :account_name, :string, :required => true - option :environment_name, :string, :required => true + option :account_name, :string, :required => true, :version => '>=2.0.0' + option :environment_name, :string, :required => true, :version => '>=2.0.0' option :instances, :instances, :required => true option :stack, :string, :required => true option :verbose, :boolean diff --git a/lib/engineyard-serverside-adapter/rollback.rb b/lib/engineyard-serverside-adapter/rollback.rb index 2a66923..8573d3b 100644 --- a/lib/engineyard-serverside-adapter/rollback.rb +++ b/lib/engineyard-serverside-adapter/rollback.rb @@ -4,8 +4,8 @@ class Adapter class Rollback < Action option :app, :string, :required => true - option :account_name, :string, :required => true - option :environment_name, :string, :required => true + option :account_name, :string, :required => true, :version => '>=2.0.0' + option :environment_name, :string, :required => true, :version => '>=2.0.0' option :config, :json option :framework_env, :string, :required => true option :instances, :instances, :required => true diff --git a/spec/adapter_spec.rb b/spec/adapter_spec.rb index d69e191..4146254 100644 --- a/spec/adapter_spec.rb +++ b/spec/adapter_spec.rb @@ -37,7 +37,7 @@ end @adapter.send(@method) do |args| - args.app.should == 'app-from-adapter-new' + args[:app].should == 'app-from-adapter-new' end end @@ -86,6 +86,8 @@ commands = all_commands(action) commands.first.should == "(gem list engineyard-serverside | grep 'engineyard-serverside ' | egrep -q '1\\.6\\.4[,)]') || (sudo sh -c 'cd `mktemp -d` && gem install engineyard-serverside --no-rdoc --no-ri -v 1.6.4')" commands.last.should =~ /engineyard-serverside _1\.6\.4_/ + commands.last.should_not =~ /--environment-name/ # 2.0.0 and above only + commands.last.should_not =~ /--account-name/ # 2.0.0 and above only end end end diff --git a/spec/deploy_spec.rb b/spec/deploy_spec.rb index 3afb65c..7eb8e82 100644 --- a/spec/deploy_spec.rb +++ b/spec/deploy_spec.rb @@ -24,6 +24,9 @@ it_should_require :repo it_should_require :stack + it_should_ignore_requirement_for_version :environment_name, '1.6.4' + it_should_ignore_requirement_for_version :account_name, '1.6.4' + it_should_behave_like "it treats config as optional" it_should_behave_like "it treats migrate as optional" diff --git a/spec/disable_maintenance_spec.rb b/spec/disable_maintenance_spec.rb index f8d8b04..9d54647 100644 --- a/spec/disable_maintenance_spec.rb +++ b/spec/disable_maintenance_spec.rb @@ -15,6 +15,9 @@ it_should_require :account_name it_should_require :instances + it_should_ignore_requirement_for_version :environment_name, '1.6.4' + it_should_ignore_requirement_for_version :account_name, '1.6.4' + context "with valid arguments" do let(:command) do adapter = described_class.new do |arguments| diff --git a/spec/enable_maintenance_spec.rb b/spec/enable_maintenance_spec.rb index f4d1577..e73f53a 100644 --- a/spec/enable_maintenance_spec.rb +++ b/spec/enable_maintenance_spec.rb @@ -15,6 +15,9 @@ it_should_require :account_name it_should_require :instances + it_should_ignore_requirement_for_version :environment_name, '1.6.4' + it_should_ignore_requirement_for_version :account_name, '1.6.4' + context "with valid arguments" do let(:command) do diff --git a/spec/integrate_spec.rb b/spec/integrate_spec.rb index 1e5d4b3..691da6a 100644 --- a/spec/integrate_spec.rb +++ b/spec/integrate_spec.rb @@ -19,6 +19,9 @@ it_should_require :instances it_should_require :framework_env + it_should_ignore_requirement_for_version :environment_name, '1.6.4' + it_should_ignore_requirement_for_version :account_name, '1.6.4' + context "with valid arguments" do let(:command) do adapter = described_class.new do |arguments| diff --git a/spec/restart_spec.rb b/spec/restart_spec.rb index 37435bd..d0a83be 100644 --- a/spec/restart_spec.rb +++ b/spec/restart_spec.rb @@ -17,6 +17,9 @@ it_should_require :instances it_should_require :stack + it_should_ignore_requirement_for_version :environment_name, '1.6.4' + it_should_ignore_requirement_for_version :account_name, '1.6.4' + context "with valid arguments" do let(:command) do adapter = described_class.new do |arguments| diff --git a/spec/rollback_spec.rb b/spec/rollback_spec.rb index 910e1c6..be722ef 100644 --- a/spec/rollback_spec.rb +++ b/spec/rollback_spec.rb @@ -19,6 +19,9 @@ it_should_require :instances it_should_require :stack + it_should_ignore_requirement_for_version :environment_name, '1.6.4' + it_should_ignore_requirement_for_version :account_name, '1.6.4' + context "with valid arguments" do let(:command) do adapter = described_class.new do |arguments| diff --git a/spec/spec_helper.rb b/spec/spec_helper.rb index c110c60..c1abb3b 100644 --- a/spec/spec_helper.rb +++ b/spec/spec_helper.rb @@ -59,6 +59,24 @@ def it_should_require(field) end end end + + def it_should_ignore_requirement_for_version(field, version) + context "field #{field} on version #{version}" do + it "is does not require #{field}" do + arguments = arguments_without(field) + arguments.serverside_version = version + lambda { described_class.new(:arguments => arguments) }.should_not raise_error + end + + it "it does not include #{field} in the command, even if it is set" do + arguments = valid_arguments + arguments.serverside_version = version + action = described_class.new(:arguments => arguments) + commands = all_commands(action) + commands.last.should_not include(EY::Serverside::Adapter::Option.new(field, :string).to_switch) + end + end + end end RSpec.configure do |config|