Skip to content

Commit

Permalink
Fix tests, reorganize wizard slightly
Browse files Browse the repository at this point in the history
  • Loading branch information
smarterclayton committed Apr 12, 2013
1 parent 5f682ae commit b39461e
Show file tree
Hide file tree
Showing 12 changed files with 210 additions and 56 deletions.
2 changes: 1 addition & 1 deletion lib/rhc/command_runner.rb
Original file line number Diff line number Diff line change
Expand Up @@ -101,7 +101,7 @@ def run!
end

def provided_arguments
@args[0, @args.find_index { |arg| arg.start_with?('-') } || @args.length]
@args[0, @args.find_index { |arg| arg != '--' and arg.start_with?('-') } || @args.length]
end

def global_option(*args, &block)
Expand Down
33 changes: 5 additions & 28 deletions lib/rhc/commands.rb
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,11 @@ def parse_options_and_call_procs *args
opts
end

remaining = opts.parse! args
# Separate option lists with '--'
remaining = args.split('--').map{ |a| opts.parse!(a) }.inject([]) do |arr, sub|
arr << '--' unless arr.empty?
arr.concat(sub)
end

_, config_path = proxy_options.find{ |arg| arg[0] == :config }
clean, _ = proxy_options.find{ |arg| arg[0] == :clean }
Expand Down Expand Up @@ -300,34 +304,7 @@ def self.fill_arguments(cmd, options, args_metadata, options_metadata, args)
end

raise ArgumentError, "Too many arguments passed in: #{available.reverse.join(" ")}" unless available.empty?
=begin
# process args
arg_slots = [].fill(nil, 0, args_metadata.length)
fill_args = args.reverse
args_metadata.each_with_index do |arg_meta, i|
# check options
option = arg_meta[:option_symbol]
context_helper = arg_meta[:context_helper]
value = options.__hash__[option] if option
value = fill_args.pop if value.nil?
value = cmd.send(context_helper) if value.nil? and context_helper
if arg_meta[:arg_type] == :list
fill_args.push(value) unless value.nil?
value = fill_args.reverse
fill_args = []
elsif value.nil?
raise ArgumentError.new("Missing required argument '#{arg_meta[:name]}'.") if fill_args.empty?
end
arg_slots[i] = value
options.__hash__[option] = value if option
end
raise ArgumentError.new("Too many arguments passed in: #{fill_args.reverse.join(" ")}") unless fill_args.empty?

arg_slots
=end
slots
end

Expand Down
17 changes: 16 additions & 1 deletion lib/rhc/commands/app.rb
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ class App < Base
description "Creates and controls an OpenShift application. To see the list of all applications use the rhc domain show command. Note that delete is not reversible and will stop your application and then remove the application and repo from the remote server. No local changes are made."
syntax "<action>"
default_action :help
suppress_wizard

summary "Create an application"
description <<-DESC
Expand Down Expand Up @@ -54,6 +55,8 @@ class App < Base
def create(name, cartridges)
check_config!

check_name!(name)

cartridges = check_cartridges(cartridges, &require_one_web_cart)

options.default \
Expand Down Expand Up @@ -341,6 +344,15 @@ def check_sshkeys!
RHC::SSHWizard.new(rest_client, config, options).run
end

def check_name!(name)
return unless name.blank?

paragraph{ say "When creating an application, you must provide a name and a cartridge from the list below:" }
paragraph{ list_cartridges(standalone_cartridges) }

raise ArgumentError, "Please specify the name of the application and the web cartridge to install"
end

def check_config!
return if not interactive? or (!options.clean && config.has_local_config?) or (options.server && (options.rhlogin || options.token))
RHC::EmbeddedWizard.new(config, options).run
Expand All @@ -354,7 +366,10 @@ def check_domain!
raise RHC::Rest::DomainNotFoundException, "No domains found. Please create a domain with 'rhc domain create <namespace>' before creating applications." unless interactive?
RHC::DomainWizard.new(config, options, rest_client).run
end
rest_client.domains.first.tap{ |d| options.namespace = d.id if d }
domain = rest_client.domains.first
raise RHC::Rest::DomainNotFoundException, "No domains found. Please create a domain with 'rhc domain create <namespace>' before creating applications." unless domain
options.namespace = domain.id
domain
end
end

Expand Down
8 changes: 0 additions & 8 deletions lib/rhc/commands/base.rb
Original file line number Diff line number Diff line change
Expand Up @@ -132,8 +132,6 @@ def self.option(switches, description, options={})

def self.argument(name, description, switches=[], options={})
arg_type = options[:arg_type]
raise ArgumentError("Only the last argument descriptor for an action can be a list") if arg_type == :list and list_argument_defined?
list_argument_defined true if arg_type == :list

option_symbol = Commander::Runner.switch_to_sym(switches.last)
args_metadata << {:name => name,
Expand All @@ -151,12 +149,6 @@ def self.default_action(action)
end

private
def self.list_argument_defined(bool)
options[:list_argument_defined] = bool
end
def self.list_argument_defined?
options[:list_argument_defined]
end
def self.options_metadata
options[:options] ||= []
end
Expand Down
17 changes: 17 additions & 0 deletions lib/rhc/core_ext.rb
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,23 @@ def to_json(options=nil)
end
end

class Array
# From rails
def split(value = nil)
using_block = block_given?

inject([[]]) do |results, element|
if (using_block && yield(element)) || (value == element)
results << []
else
results.last << element
end

results
end
end
end

class File
def chunk(chunk_size=1024)
yield read(chunk_size) until eof?
Expand Down
8 changes: 4 additions & 4 deletions lib/rhc/rest/mock.rb
Original file line number Diff line number Diff line change
Expand Up @@ -115,7 +115,7 @@ def stub_add_authorization(params)
to_return(new_authorization(params))
end
def stub_no_keys
stub_api_request(:get, 'broker/rest/user/keys', mock_user_auth).to_return(no_keys)
stub_api_request(:get, 'broker/rest/user/keys', mock_user_auth).to_return(empty_keys)
end
def stub_mock_ssh_keys(name='test')
stub_api_request(:get, 'broker/rest/user/keys', mock_user_auth).
Expand Down Expand Up @@ -154,7 +154,7 @@ def stub_one_key(name)
})
end
def stub_no_domains
stub_api_request(:get, 'broker/rest/domains', mock_user_auth).to_return(no_domains)
stub_api_request(:get, 'broker/rest/domains', mock_user_auth).to_return(empty_domains)
end
def stub_one_domain(name)
stub_api_request(:get, 'broker/rest/domains', mock_user_auth).
Expand Down Expand Up @@ -216,10 +216,10 @@ def test_and_raise
EOM
end

def no_keys
def empty_keys
empty_response_list('keys')
end
def no_domains
def empty_domains
empty_response_list('domains')
end

Expand Down
6 changes: 3 additions & 3 deletions lib/rhc/wizard.rb
Original file line number Diff line number Diff line change
Expand Up @@ -472,7 +472,7 @@ def setup_test_stage
end

def all_test_methods
private_methods.select {|m| m.to_s.start_with? 'test_'}
(protected_methods + private_methods).select {|m| m.to_s.start_with? 'test_'}
end

###
Expand Down Expand Up @@ -518,7 +518,7 @@ def finalize_stage

def config_namespace(namespace)
# skip if string is empty
if namespace_optional? and (namespace.nil? or namespace.chomp.length == 0)
if namespace_optional? and (namespace.nil? or namespace.chomp.blank?)
paragraph{ info "You may create a namespace later through 'rhc domain create'" }
return true
end
Expand Down Expand Up @@ -596,7 +596,7 @@ def finalize_stage

class EmbeddedWizard < Wizard
def stages
super - APP_STAGES
super - APP_STAGES - KEY_STAGES - [:setup_test_stage]
end

def finalize_stage
Expand Down
16 changes: 15 additions & 1 deletion spec/rhc/command_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -122,6 +122,12 @@ def execute(testarg); 1; end
summary "Test command execute-list"
def execute_list(args); 1; end

argument :arg1, "Test arg", ['--test'], :optional => true
argument :arg2, "Test arg list", ['--test2'], :arg_type => :list, :optional => true
argument :arg3, "Test arg list", ['--test3'], :arg_type => :list, :optional => true
summary "Test command execute-vararg"
def execute_vararg(arg1, arg2, arg3); 1; end

RHC::Helpers.global_option '--test-context', 'Test', :context => :context_var
def execute_implicit
end
Expand All @@ -142,7 +148,7 @@ def context_var
Static
end

it("should register itself") { expect { subject }.to change(commands, :length).by(6) }
it("should register itself") { expect { subject }.to change(commands, :length).by(7) }
it("should have an object name of the class") { subject.object_name.should == 'static' }

context 'and when test is called' do
Expand Down Expand Up @@ -178,6 +184,14 @@ def context_var
it('should make the option available') { command_for('static-execute-list', '1', '2', '3').send(:options).tests.should == ['1','2','3'] }
end

context 'and when execute_vararg is called' do
it{ expects_running('static-execute-vararg').should call(:execute_vararg).on(instance).with(nil, nil, nil) }
it{ expects_running('static-execute-vararg', '1', '2', '3').should call(:execute_vararg).on(instance).with('1', ['2', '3'], []) }
it("handles a list separator"){ expects_running('static-execute-vararg', '1', '2', '--', '3').should call(:execute_vararg).on(instance).with('1', ['2'], ['3']) }
it{ command_for('static-execute-vararg', '1', '2', '--', '3').send(:options).test.should == '1' }
it{ command_for('static-execute-vararg', '1', '2', '--', '3').send(:options).test2.should == ['2'] }
it{ command_for('static-execute-vararg', '1', '2', '--', '3').send(:options).test3.should == ['3'] }
end
context 'and when execute is called with a contextual global option' do
it("calls the helper") { command_for('static', 'execute-implicit').send(:options).test_context.should == 'contextual' }
end
Expand Down
110 changes: 103 additions & 7 deletions spec/rhc/commands/app_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -6,10 +6,11 @@

describe RHC::Commands::App do
let!(:rest_client){ MockRestClient.new }
before(:each) do
let!(:config){ user_config }
before{ RHC::Config.stub(:home_dir).and_return('/home/mock_user') }
before do
FakeFS.activate!
FakeFS::FileSystem.clear
user_config
RHC::Helpers.send(:remove_const, :MAX_RETRIES) rescue nil
RHC::Helpers.const_set(:MAX_RETRIES, 3)
@instance = RHC::Commands::App.new
Expand Down Expand Up @@ -38,7 +39,7 @@
end

context 'app' do
let(:arguments) { ['app', '--noprompt', '--config', 'test.conf', '-l', '[email protected]', '-p', 'password'] }
let(:arguments) { ['app'] }
it { run_output.should match('Usage:') }
end
end
Expand All @@ -49,11 +50,44 @@
it("shows number of started"){ subject.send(:gear_group_state, ['started', 'idle']).should == '1/2 started' }
end

describe 'app create' do
before(:each) do
domain = rest_client.add_domain("mockdomain")
describe '#check_domain!' do
let(:rest_client){ stub('RestClient') }
let(:domain){ stub('Domain', :id => 'test') }
before{ subject.stub(:rest_client).and_return(rest_client) }
let(:interactive){ false }
before{ subject.stub(:interactive?).and_return(interactive) }

context "when no options are provided and there is one domain" do
before{ rest_client.should_receive(:domains).twice.and_return([domain]) }
it("should load the first domain"){ subject.send(:check_domain!).should == domain }
after{ subject.send(:options).namespace.should == domain.id }
end

context "when no options are provided and there are no domains" do
before{ rest_client.should_receive(:domains).and_return([]) }
it("should load the first domain"){ expect{ subject.send(:check_domain!) }.to raise_error(RHC::Rest::DomainNotFoundException) }
after{ subject.send(:options).namespace.should be_nil }
end

context "when valid namespace is provided" do
before{ subject.send(:options)[:namespace] = 'test' }
before{ rest_client.should_receive(:find_domain).with('test').and_return(domain) }
it("should load the requested domain"){ subject.send(:check_domain!).should == domain }
after{ subject.send(:options).namespace.should == 'test' }
end

context "when interactive and no domains" do
let(:interactive){ true }
before{ rest_client.should_receive(:domains).twice.and_return([]) }
before{ RHC::DomainWizard.should_receive(:new).and_return(stub(:run => true)) }
it("should raise if the wizard doesn't set the option"){ expect{ subject.send(:check_domain!) }.to raise_error(RHC::Rest::DomainNotFoundException) }
after{ subject.send(:options).namespace.should be_nil }
end
end

describe 'app create' do
before{ rest_client.add_domain("mockdomain") }

context "when we ask for help with the alias" do
before{ FakeFS.deactivate! }
context do
Expand All @@ -66,6 +100,68 @@
end
end

context "when run with no arguments" do
before{ FakeFS.deactivate! }
let(:arguments){ ['create-app'] }
it{ run_output.should match "Usage: rhc app-create <name>" }
it{ run_output.should match "When creating an application, you must provide a name and a cartridge from the list below:" }
it{ run_output.should match "mock_standalone_cart-1" }
it{ run_output.should match "Please specify the name of the application" }
end

context "when dealing with config" do
subject{ described_class.new(Commander::Command::Options.new(options)) }
let(:wizard){ s = stub('Wizard'); RHC::EmbeddedWizard.should_receive(:new).and_return(s); s }
let(:options){ nil }
let(:interactive){ true }
before{ subject.should_receive(:interactive?).at_least(1).times.and_return(interactive) }
before{ subject.stub(:check_sshkeys!) }

it("should run the wizard"){ expect{ subject.create('name', ['mock_standalone_cart-1']) }.to call(:run).on(wizard).and_stop }

context "when has config" do
let(:options){ {:server => 'test', :rhlogin => 'foo'} }
before{ subject.send(:config).should_receive(:has_local_config?).and_return(true) }
it("should not run the wizard"){ expect{ subject.create('name', ['mock_standalone_cart-1']) }.to not_call(:new).on(RHC::EmbeddedWizard) }
end

context "when has no config" do
before{ subject.send(:config).should_receive(:has_local_config?).and_return(false) }
it("should run the wizard"){ expect{ subject.create('name', ['mock_standalone_cart-1']) }.to call(:new).on(RHC::EmbeddedWizard).and_stop }
end

context "when not interactive" do
let(:interactive){ false }
it("should not run the wizard"){ expect{ subject.create('name', ['mock_standalone_cart-1']) }.to not_call(:new).on(RHC::EmbeddedWizard) }
end
end

context "when dealing with ssh keys" do
subject{ described_class.new(options) }
let(:wizard){ s = stub('Wizard'); RHC::SSHWizard.should_receive(:new).and_return(s); s }
let(:options){ Commander::Command::Options.new(:server => 'foo.com', :rhlogin => 'test') }
let(:interactive){ true }
before{ subject.should_receive(:interactive?).at_least(1).times.and_return(interactive) }
before{ subject.should_receive(:check_config!) }

it("should run the wizard"){ expect{ subject.create('name', ['mock_standalone_cart-1']) }.to call(:run).on(wizard).and_stop }

context "when not interactive" do
let(:interactive){ false }
it("should not run the wizard"){ expect{ subject.create('name', ['mock_standalone_cart-1']) }.to not_call(:new).on(RHC::SSHWizard) }
end
end

context "when in full interactive mode with no keys, domain, or config" do
let!(:config){ base_config }
before{ RHC::Config.any_instance.stub(:has_local_config?).and_return(false) }
before{ described_class.any_instance.stub(:interactive?).and_return(true) }
before{ rest_client.domains.clear }
let(:arguments) { ['app', 'create', 'app1', 'mock_standalone_cart-1'] }
# skips login stage and insecure check because of mock rest client, doesn't check keys
it { run_output(['mydomain', 'y', 'mykey']).should match(/This wizard.*Checking your namespace.*Your domain name 'mydomain' has been successfully created.*Creating application.*Your public SSH key.*Uploading key 'mykey' from.*Downloading the application.*Success/m) }
end

context 'when run without a cart' do
before{ FakeFS.deactivate! }
let(:arguments) { ['app', 'create', 'app1', '--noprompt', '--timeout', '10', '--config', 'test.conf', '-l', '[email protected]', '-p', 'password'] }
Expand Down Expand Up @@ -273,7 +369,7 @@
before(:each) do
@domain = rest_client.add_domain("mockdomain")
@instance.stub(:git_clone_application) { raise RHC::GitException }
@instance.should_not_receive(:check_sshkeys!)
@instance.stub(:check_sshkeys!)
end

context 'when run with error in git clone' do
Expand Down
Loading

0 comments on commit b39461e

Please sign in to comment.