taketo 0.0.2 → 0.0.3
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/README.md +48 -3
- data/VERSION +1 -1
- data/bin/taketo +5 -3
- data/features/commands.feature +2 -2
- data/features/connect_to_server.feature +46 -1
- data/lib/taketo/constructs/base_construct.rb +24 -0
- data/lib/taketo/constructs/command.rb +3 -7
- data/lib/taketo/constructs/config.rb +7 -1
- data/lib/taketo/constructs/environment.rb +8 -3
- data/lib/taketo/constructs/project.rb +8 -3
- data/lib/taketo/constructs/server.rb +11 -14
- data/lib/taketo/destination_resolver.rb +118 -0
- data/lib/taketo/dsl.rb +9 -8
- data/lib/taketo/support/named_nodes_collection.rb +11 -2
- data/spec/integration/dsl_integration_spec.rb +7 -0
- data/spec/lib/taketo/constructs/base_construct_spec.rb +45 -0
- data/spec/lib/taketo/constructs/config_spec.rb +13 -0
- data/spec/lib/taketo/constructs/environment_spec.rb +7 -0
- data/spec/lib/taketo/constructs/project_spec.rb +7 -0
- data/spec/lib/taketo/constructs/server_spec.rb +4 -16
- data/spec/lib/taketo/constructs_factory_spec.rb +1 -1
- data/spec/lib/taketo/destination_resolver_spec.rb +170 -0
- data/spec/lib/taketo/dsl_spec.rb +39 -27
- data/spec/lib/taketo/support/eval_delegator_spec.rb +7 -1
- data/spec/lib/taketo/support/named_nodes_collection_spec.rb +7 -0
- data/spec/support/helpers/dsl_spec_helper.rb +1 -1
- metadata +6 -4
- data/lib/taketo/taketo_argv_parser.rb +0 -48
- data/spec/lib/taketo/taketo_argv_parser_spec.rb +0 -92
    
        data/README.md
    CHANGED
    
    | @@ -4,7 +4,15 @@ Take Me To | |
| 4 4 | 
             
            [](http://travis-ci.org/v-yarotsky/taketo)
         | 
| 5 5 | 
             
            [](https://codeclimate.com/github/v-yarotsky/taketo)
         | 
| 6 6 |  | 
| 7 | 
            -
            A tiny helper utility to make access to servers  | 
| 7 | 
            +
            A tiny helper utility to make access to servers easier for different projects and environments.
         | 
| 8 | 
            +
             | 
| 9 | 
            +
            Important note:
         | 
| 10 | 
            +
            ---------------
         | 
| 11 | 
            +
             | 
| 12 | 
            +
            The project is currently actively developed, thus it may contain bugs;
         | 
| 13 | 
            +
            backward compatibility is not guaranteed.
         | 
| 14 | 
            +
             | 
| 15 | 
            +
            Suggestions and contributions are highly appreciated :)
         | 
| 8 16 |  | 
| 9 17 | 
             
            Usage:
         | 
| 10 18 | 
             
            ------
         | 
| @@ -28,9 +36,42 @@ puts a config into ```~/.taketo.rc.rb```: | |
| 28 36 | 
             
              end
         | 
| 29 37 | 
             
            ```
         | 
| 30 38 |  | 
| 31 | 
            -
            Then execute ```taketo my_project | 
| 32 | 
            -
            or just ```taketo my_project | 
| 39 | 
            +
            Then execute ```taketo my_project:staging:server -c console``` to execute the "rails c" with corresponding environment variables set on desired server
         | 
| 40 | 
            +
            or just ```taketo my_project:staging:server``` to open bash
         | 
| 41 | 
            +
             | 
| 42 | 
            +
            Destination resolving works intelligently. Given the following config:
         | 
| 43 | 
            +
             | 
| 44 | 
            +
            ```ruby
         | 
| 45 | 
            +
              default_destination "my_project2:staging:s2"
         | 
| 33 46 |  | 
| 47 | 
            +
              project :my_project do
         | 
| 48 | 
            +
                environment :staging do
         | 
| 49 | 
            +
                  server :s1 do
         | 
| 50 | 
            +
                    host "1.2.3.4"
         | 
| 51 | 
            +
                  end
         | 
| 52 | 
            +
                end
         | 
| 53 | 
            +
                environment :production do
         | 
| 54 | 
            +
                  server :ps1 do
         | 
| 55 | 
            +
                    host "3.4.5.6"
         | 
| 56 | 
            +
                  end
         | 
| 57 | 
            +
                end
         | 
| 58 | 
            +
              end
         | 
| 59 | 
            +
              
         | 
| 60 | 
            +
              project :my_project2 do
         | 
| 61 | 
            +
                environment :staging do
         | 
| 62 | 
            +
                  server :s2 do
         | 
| 63 | 
            +
                    host "2.3.4.5"
         | 
| 64 | 
            +
                  end
         | 
| 65 | 
            +
                end
         | 
| 66 | 
            +
              end
         | 
| 67 | 
            +
            ```
         | 
| 68 | 
            +
             | 
| 69 | 
            +
            ```taketo my_project:staging``` will ssh to s1 with host = 1.2.3.4  
         | 
| 70 | 
            +
            ```taketo my_project2``` will ssh to s2 with host = 2.3.4.5   
         | 
| 71 | 
            +
             | 
| 72 | 
            +
            Note that default destination can be specified via ```default_destination``` config option
         | 
| 73 | 
            +
             | 
| 74 | 
            +
              
         | 
| 34 75 | 
             
            To-Do:
         | 
| 35 76 | 
             
            ------
         | 
| 36 77 |  | 
| @@ -40,6 +81,10 @@ To-Do: | |
| 40 81 | 
             
            The Changelog:
         | 
| 41 82 | 
             
            --------------
         | 
| 42 83 |  | 
| 84 | 
            +
            ### v0.0.3 (22.07.2012) ###
         | 
| 85 | 
            +
            * Add default_destination config option
         | 
| 86 | 
            +
            * Add intelligent destination resolving
         | 
| 87 | 
            +
             | 
| 43 88 | 
             
            ### v0.0.2 (21.07.2012) ###
         | 
| 44 89 | 
             
            * Add ability to define environment variables
         | 
| 45 90 | 
             
            * Add support for server commands
         | 
    
        data/VERSION
    CHANGED
    
    | @@ -1 +1 @@ | |
| 1 | 
            -
            0.0. | 
| 1 | 
            +
            0.0.3
         | 
    
        data/bin/taketo
    CHANGED
    
    | @@ -6,7 +6,7 @@ begin | |
| 6 6 | 
             
              require 'taketo'
         | 
| 7 7 | 
             
              require 'taketo/constructs_factory'
         | 
| 8 8 | 
             
              require 'taketo/commands'
         | 
| 9 | 
            -
              require 'taketo/ | 
| 9 | 
            +
              require 'taketo/destination_resolver'
         | 
| 10 10 | 
             
              require 'optparse'
         | 
| 11 11 | 
             
            rescue LoadError => e #development
         | 
| 12 12 | 
             
              raise if $loaded
         | 
| @@ -62,7 +62,7 @@ end | |
| 62 62 |  | 
| 63 63 | 
             
            def remote_command(server, options)
         | 
| 64 64 | 
             
              command_name = options[:command] or return default_command(options)
         | 
| 65 | 
            -
              server. | 
| 65 | 
            +
              server.find(:command, command_name.to_sym) { default_command(options) }
         | 
| 66 66 | 
             
            end
         | 
| 67 67 |  | 
| 68 68 | 
             
            def default_command(options)
         | 
| @@ -75,7 +75,8 @@ begin | |
| 75 75 | 
             
              options = parse_options
         | 
| 76 76 | 
             
              config  = parse_config(options[:config])
         | 
| 77 77 |  | 
| 78 | 
            -
               | 
| 78 | 
            +
              destination_path = ARGV.shift.to_s
         | 
| 79 | 
            +
              server = DestinationResolver.new(config, destination_path).resolve
         | 
| 79 80 |  | 
| 80 81 | 
             
              server_command = remote_command(server, options)
         | 
| 81 82 | 
             
              command_to_execute = Commands::SSHCommand.new(server).render(server_command)
         | 
| @@ -91,3 +92,4 @@ rescue Exception => e | |
| 91 92 | 
             
              STDERR.puts "An error occurred: #{e.message}"
         | 
| 92 93 | 
             
              raise if options && options[:debug]
         | 
| 93 94 | 
             
            end
         | 
| 95 | 
            +
             | 
    
        data/features/commands.feature
    CHANGED
    
    | @@ -16,7 +16,7 @@ Feature: | |
| 16 16 | 
             
                    end
         | 
| 17 17 | 
             
                  end
         | 
| 18 18 | 
             
                  """
         | 
| 19 | 
            -
             | 
| 19 | 
            +
                And I successfully run `taketo --config=/tmp/taketo_test_cfg.rb --dry-run --command "TERM=xterm-256color bash"`
         | 
| 20 20 | 
             
                Then the output should contain
         | 
| 21 21 | 
             
                  """
         | 
| 22 22 | 
             
                  ssh -t 1.2.3.4 "cd /var/apps/slots; RAILS_ENV=staging TERM=xterm-256color bash"
         | 
| @@ -37,7 +37,7 @@ Feature: | |
| 37 37 | 
             
                    end
         | 
| 38 38 | 
             
                  end
         | 
| 39 39 | 
             
                  """
         | 
| 40 | 
            -
             | 
| 40 | 
            +
                And I successfully run `taketo --config=/tmp/taketo_test_cfg.rb --dry-run --command console slots:staging:s1`
         | 
| 41 41 | 
             
                Then the output should contain
         | 
| 42 42 | 
             
                  """
         | 
| 43 43 | 
             
                  ssh -t 1.2.3.4 "cd /var/apps/slots; RAILS_ENV=staging rails c"
         | 
| @@ -14,11 +14,15 @@ Feature: | |
| 14 14 | 
             
                        user "deployer"
         | 
| 15 15 | 
             
                        location "/var/apps/slots"
         | 
| 16 16 | 
             
                      end
         | 
| 17 | 
            +
             | 
| 18 | 
            +
                      server :s2 do
         | 
| 19 | 
            +
                        host "2.3.4.5"
         | 
| 20 | 
            +
                      end
         | 
| 17 21 | 
             
                    end
         | 
| 18 22 | 
             
                  end
         | 
| 19 23 |  | 
| 20 24 | 
             
                  """
         | 
| 21 | 
            -
                And I successfully run `taketo --config=/tmp/taketo_test_cfg.rb --dry-run slots | 
| 25 | 
            +
                And I successfully run `taketo --config=/tmp/taketo_test_cfg.rb --dry-run slots:staging:s1`
         | 
| 22 26 | 
             
                Then the output should contain
         | 
| 23 27 | 
             
                  """
         | 
| 24 28 | 
             
                  ssh -t deployer@1.2.3.4 "cd /var/apps/slots; RAILS_ENV=staging bash"
         | 
| @@ -65,3 +69,44 @@ Feature: | |
| 65 69 | 
             
                  FOO=the\ value
         | 
| 66 70 | 
             
                  """
         | 
| 67 71 |  | 
| 72 | 
            +
              Scenario: Reopen config scopes
         | 
| 73 | 
            +
                When I have the following config in "/tmp/taketo_test_cfg.rb"
         | 
| 74 | 
            +
                  """
         | 
| 75 | 
            +
                  project :slots do
         | 
| 76 | 
            +
                    environment :staging do
         | 
| 77 | 
            +
                      server :s1 do
         | 
| 78 | 
            +
                        host "1.2.3.4"
         | 
| 79 | 
            +
                      end
         | 
| 80 | 
            +
                    end
         | 
| 81 | 
            +
                  end
         | 
| 82 | 
            +
             | 
| 83 | 
            +
                  project :slots do
         | 
| 84 | 
            +
                    environment :staging do
         | 
| 85 | 
            +
                      server :s1 do
         | 
| 86 | 
            +
                        env :FOO => "bar"
         | 
| 87 | 
            +
                      end
         | 
| 88 | 
            +
                    end
         | 
| 89 | 
            +
                  end
         | 
| 90 | 
            +
                  """
         | 
| 91 | 
            +
                And I successfully run `taketo --config=/tmp/taketo_test_cfg.rb slots:staging:s1 --dry-run`
         | 
| 92 | 
            +
                Then the output should match /ssh -t 1\.2\.3\.4 "(RAILS_ENV=staging FOO=bar|FOO=bar RAILS_ENV=staging) bash"/
         | 
| 93 | 
            +
             | 
| 94 | 
            +
              Scenario: Default destination
         | 
| 95 | 
            +
                When I have the following config in "/tmp/taketo_test_cfg.rb"
         | 
| 96 | 
            +
                  """
         | 
| 97 | 
            +
                  default_destination "slots:staging:s2"
         | 
| 98 | 
            +
                  project :slots do
         | 
| 99 | 
            +
                    environment :staging do
         | 
| 100 | 
            +
                      server :s1 do
         | 
| 101 | 
            +
                      end
         | 
| 102 | 
            +
                      server :s2 do
         | 
| 103 | 
            +
                        host "2.3.4.5"
         | 
| 104 | 
            +
                      end
         | 
| 105 | 
            +
                    end
         | 
| 106 | 
            +
                  end
         | 
| 107 | 
            +
                  """
         | 
| 108 | 
            +
                And I successfully run `taketo --config=/tmp/taketo_test_cfg.rb --dry-run`
         | 
| 109 | 
            +
                Then the output should contain
         | 
| 110 | 
            +
                  """
         | 
| 111 | 
            +
                  ssh -t 2.3.4.5 "RAILS_ENV=staging bash"
         | 
| 112 | 
            +
                  """
         | 
| @@ -0,0 +1,24 @@ | |
| 1 | 
            +
            require 'taketo/support'
         | 
| 2 | 
            +
             | 
| 3 | 
            +
            module Taketo
         | 
| 4 | 
            +
              module Constructs
         | 
| 5 | 
            +
                class BaseConstruct
         | 
| 6 | 
            +
                  attr_reader :name
         | 
| 7 | 
            +
             | 
| 8 | 
            +
                  def initialize(name)
         | 
| 9 | 
            +
                    @name = name
         | 
| 10 | 
            +
                  end
         | 
| 11 | 
            +
             | 
| 12 | 
            +
                  def find(scope, name)
         | 
| 13 | 
            +
                    send("find_#{scope}", name) or
         | 
| 14 | 
            +
                      if block_given?
         | 
| 15 | 
            +
                        yield
         | 
| 16 | 
            +
                      else
         | 
| 17 | 
            +
                        raise KeyError, "#{scope.to_s.capitalize} #{name} not found for #{self.class.name} #{name}"
         | 
| 18 | 
            +
                      end
         | 
| 19 | 
            +
                  end
         | 
| 20 | 
            +
                end
         | 
| 21 | 
            +
              end
         | 
| 22 | 
            +
            end
         | 
| 23 | 
            +
             | 
| 24 | 
            +
             | 
| @@ -1,19 +1,15 @@ | |
| 1 | 
            +
            require 'taketo/constructs/base_construct'
         | 
| 1 2 | 
             
            require 'shellwords'
         | 
| 2 3 |  | 
| 3 4 | 
             
            module Taketo
         | 
| 4 5 | 
             
              module Constructs
         | 
| 5 | 
            -
                class Command
         | 
| 6 | 
            +
                class Command < BaseConstruct
         | 
| 6 7 | 
             
                  include Shellwords
         | 
| 7 8 |  | 
| 8 | 
            -
                  attr_reader :name
         | 
| 9 9 | 
             
                  attr_accessor :command
         | 
| 10 10 |  | 
| 11 | 
            -
                  def initialize(name)
         | 
| 12 | 
            -
                    @name = name
         | 
| 13 | 
            -
                  end
         | 
| 14 | 
            -
             | 
| 15 11 | 
             
                  def render(server)
         | 
| 16 | 
            -
                    %Q[#{location(server)} #{environment_variables(server)} #{command}].squeeze(" ")
         | 
| 12 | 
            +
                    %Q[#{location(server)} #{environment_variables(server)} #{command}].strip.squeeze(" ")
         | 
| 17 13 | 
             
                  end
         | 
| 18 14 |  | 
| 19 15 | 
             
                  private
         | 
| @@ -1,9 +1,11 @@ | |
| 1 | 
            +
            require 'taketo/constructs/base_construct'
         | 
| 1 2 | 
             
            require 'taketo/support'
         | 
| 2 3 |  | 
| 3 4 | 
             
            module Taketo
         | 
| 4 5 | 
             
              module Constructs
         | 
| 5 | 
            -
                class Config
         | 
| 6 | 
            +
                class Config < BaseConstruct
         | 
| 6 7 | 
             
                  attr_reader :projects
         | 
| 8 | 
            +
                  attr_accessor :default_destination
         | 
| 7 9 |  | 
| 8 10 | 
             
                  def initialize
         | 
| 9 11 | 
             
                    @projects = Taketo::Support::NamedNodesCollection.new
         | 
| @@ -12,6 +14,10 @@ module Taketo | |
| 12 14 | 
             
                  def append_project(project)
         | 
| 13 15 | 
             
                    @projects << project
         | 
| 14 16 | 
             
                  end
         | 
| 17 | 
            +
             | 
| 18 | 
            +
                  def find_project(name)
         | 
| 19 | 
            +
                    @projects.find_by_name(name)
         | 
| 20 | 
            +
                  end
         | 
| 15 21 | 
             
                end
         | 
| 16 22 | 
             
              end
         | 
| 17 23 | 
             
            end
         | 
| @@ -1,12 +1,13 @@ | |
| 1 | 
            +
            require 'taketo/constructs/base_construct'
         | 
| 1 2 | 
             
            require 'taketo/support'
         | 
| 2 3 |  | 
| 3 4 | 
             
            module Taketo
         | 
| 4 5 | 
             
              module Constructs
         | 
| 5 | 
            -
                class Environment
         | 
| 6 | 
            -
                  attr_reader : | 
| 6 | 
            +
                class Environment < BaseConstruct
         | 
| 7 | 
            +
                  attr_reader :servers
         | 
| 7 8 |  | 
| 8 9 | 
             
                  def initialize(name)
         | 
| 9 | 
            -
                     | 
| 10 | 
            +
                    super
         | 
| 10 11 | 
             
                    @servers = Taketo::Support::NamedNodesCollection.new
         | 
| 11 12 | 
             
                  end
         | 
| 12 13 |  | 
| @@ -14,6 +15,10 @@ module Taketo | |
| 14 15 | 
             
                    server.environment = self
         | 
| 15 16 | 
             
                    @servers << server
         | 
| 16 17 | 
             
                  end
         | 
| 18 | 
            +
             | 
| 19 | 
            +
                  def find_server(name)
         | 
| 20 | 
            +
                    @servers.find_by_name(name)
         | 
| 21 | 
            +
                  end
         | 
| 17 22 | 
             
                end
         | 
| 18 23 | 
             
              end
         | 
| 19 24 | 
             
            end
         | 
| @@ -1,18 +1,23 @@ | |
| 1 | 
            +
            require 'taketo/constructs/base_construct'
         | 
| 1 2 | 
             
            require 'taketo/support'
         | 
| 2 3 |  | 
| 3 4 | 
             
            module Taketo
         | 
| 4 5 | 
             
              module Constructs
         | 
| 5 | 
            -
                class Project
         | 
| 6 | 
            -
                  attr_reader : | 
| 6 | 
            +
                class Project < BaseConstruct
         | 
| 7 | 
            +
                  attr_reader :environments
         | 
| 7 8 |  | 
| 8 9 | 
             
                  def initialize(name)
         | 
| 9 | 
            -
                     | 
| 10 | 
            +
                    super
         | 
| 10 11 | 
             
                    @environments = Taketo::Support::NamedNodesCollection.new
         | 
| 11 12 | 
             
                  end
         | 
| 12 13 |  | 
| 13 14 | 
             
                  def append_environment(environment)
         | 
| 14 15 | 
             
                    @environments << environment
         | 
| 15 16 | 
             
                  end
         | 
| 17 | 
            +
             | 
| 18 | 
            +
                  def find_environment(name)
         | 
| 19 | 
            +
                    @environments.find_by_name(name)
         | 
| 20 | 
            +
                  end
         | 
| 16 21 | 
             
                end
         | 
| 17 22 | 
             
              end
         | 
| 18 23 | 
             
            end
         | 
| @@ -1,15 +1,18 @@ | |
| 1 | 
            +
            require 'taketo/constructs/base_construct'
         | 
| 2 | 
            +
            require 'taketo/support'
         | 
| 3 | 
            +
             | 
| 1 4 | 
             
            module Taketo
         | 
| 2 5 | 
             
              module Constructs
         | 
| 3 | 
            -
                class Server
         | 
| 6 | 
            +
                class Server < BaseConstruct
         | 
| 4 7 | 
             
                  class CommandNotFoundError < StandardError; end
         | 
| 5 8 |  | 
| 6 | 
            -
                  attr_reader : | 
| 9 | 
            +
                  attr_reader :environment_variables, :commands
         | 
| 7 10 | 
             
                  attr_accessor :host, :port, :username, :default_location, :environment
         | 
| 8 11 |  | 
| 9 12 | 
             
                  def initialize(name)
         | 
| 10 | 
            -
                     | 
| 13 | 
            +
                    super
         | 
| 11 14 | 
             
                    @environment_variables = {}
         | 
| 12 | 
            -
                    @commands =  | 
| 15 | 
            +
                    @commands = Taketo::Support::NamedNodesCollection.new
         | 
| 13 16 | 
             
                  end
         | 
| 14 17 |  | 
| 15 18 | 
             
                  def env(env_variables)
         | 
| @@ -20,20 +23,14 @@ module Taketo | |
| 20 23 | 
             
                    @commands << command
         | 
| 21 24 | 
             
                  end
         | 
| 22 25 |  | 
| 26 | 
            +
                  def find_command(name)
         | 
| 27 | 
            +
                    @commands.find_by_name(name)
         | 
| 28 | 
            +
                  end
         | 
| 29 | 
            +
             | 
| 23 30 | 
             
                  def environment=(environment)
         | 
| 24 31 | 
             
                    env(:RAILS_ENV => environment.name.to_s)
         | 
| 25 32 | 
             
                    @environment = environment
         | 
| 26 33 | 
             
                  end
         | 
| 27 | 
            -
             | 
| 28 | 
            -
                  def command_by_name(command_name)
         | 
| 29 | 
            -
                    @commands.detect { |c| c.name == command_name } or 
         | 
| 30 | 
            -
                      if block_given?
         | 
| 31 | 
            -
                        yield
         | 
| 32 | 
            -
                      else
         | 
| 33 | 
            -
                        raise CommandNotFoundError, "Command #{command_name} not found for server #{name}"
         | 
| 34 | 
            -
                      end
         | 
| 35 | 
            -
                  end
         | 
| 36 | 
            -
             | 
| 37 34 | 
             
                end
         | 
| 38 35 | 
             
              end
         | 
| 39 36 | 
             
            end
         | 
| @@ -0,0 +1,118 @@ | |
| 1 | 
            +
            module Taketo
         | 
| 2 | 
            +
              class ConfigError < StandardError; end
         | 
| 3 | 
            +
              class AmbiguousDestinationError < StandardError; end
         | 
| 4 | 
            +
              class NonExistentDestinationError < StandardError; end
         | 
| 5 | 
            +
             | 
| 6 | 
            +
              class DestinationResolver
         | 
| 7 | 
            +
                def initialize(config, path)
         | 
| 8 | 
            +
                  @config = config
         | 
| 9 | 
            +
                  set_destination(path)
         | 
| 10 | 
            +
                end
         | 
| 11 | 
            +
             | 
| 12 | 
            +
                def resolve
         | 
| 13 | 
            +
                  case @path.size
         | 
| 14 | 
            +
                  when 3 then resolve_by_three_segments
         | 
| 15 | 
            +
                  when 2 then resolve_by_two_segments
         | 
| 16 | 
            +
                  when 1 then resolve_by_one_segment
         | 
| 17 | 
            +
                  when 0 then resolve_with_no_segments
         | 
| 18 | 
            +
                  end
         | 
| 19 | 
            +
                end
         | 
| 20 | 
            +
             | 
| 21 | 
            +
                private
         | 
| 22 | 
            +
             | 
| 23 | 
            +
                def set_destination(path)
         | 
| 24 | 
            +
                  @path_str = path
         | 
| 25 | 
            +
                  @path = String(path).split(":").map(&:to_sym)
         | 
| 26 | 
            +
                end
         | 
| 27 | 
            +
             | 
| 28 | 
            +
                def resolve_by_three_segments
         | 
| 29 | 
            +
                  get_server(*@path)
         | 
| 30 | 
            +
                end
         | 
| 31 | 
            +
             | 
| 32 | 
            +
                def resolve_by_two_segments
         | 
| 33 | 
            +
                  project, environment = get_project_and_environment(*@path)
         | 
| 34 | 
            +
                  get_only_server_for_project_and_environment(project, environment)
         | 
| 35 | 
            +
                end
         | 
| 36 | 
            +
             | 
| 37 | 
            +
                def resolve_by_one_segment
         | 
| 38 | 
            +
                  project = get_project(*@path)
         | 
| 39 | 
            +
                  get_only_server_for_project(project)
         | 
| 40 | 
            +
                end
         | 
| 41 | 
            +
             | 
| 42 | 
            +
                def resolve_with_no_segments
         | 
| 43 | 
            +
                  unless @config.default_destination.nil?
         | 
| 44 | 
            +
                    set_destination(@config.default_destination.to_s)
         | 
| 45 | 
            +
                    return resolve
         | 
| 46 | 
            +
                  end
         | 
| 47 | 
            +
                  get_only_server
         | 
| 48 | 
            +
                end
         | 
| 49 | 
            +
             | 
| 50 | 
            +
                def get_server(project_name, environment_name, server_name)
         | 
| 51 | 
            +
                  handling_failure("There is no such project, environment or server for destination: #@path_str") do
         | 
| 52 | 
            +
                    project, environment = get_project_and_environment(project_name, environment_name)
         | 
| 53 | 
            +
                    environment.servers[server_name]
         | 
| 54 | 
            +
                  end
         | 
| 55 | 
            +
                end
         | 
| 56 | 
            +
             | 
| 57 | 
            +
                def get_project_and_environment(project_name, environment_name)
         | 
| 58 | 
            +
                  handling_failure("There is no such project - environment pair: #@path_str") do
         | 
| 59 | 
            +
                    project = get_project(project_name)
         | 
| 60 | 
            +
                    environment = project.environments[environment_name]
         | 
| 61 | 
            +
                    [project, environment]
         | 
| 62 | 
            +
                  end
         | 
| 63 | 
            +
                end
         | 
| 64 | 
            +
             | 
| 65 | 
            +
                def get_only_server_for_project_and_environment(project, environment)
         | 
| 66 | 
            +
                  if environment.servers.one?
         | 
| 67 | 
            +
                    return environment.servers.first
         | 
| 68 | 
            +
                  else
         | 
| 69 | 
            +
                    raise_server_ambiguous!(project, environment)
         | 
| 70 | 
            +
                  end
         | 
| 71 | 
            +
                end
         | 
| 72 | 
            +
             | 
| 73 | 
            +
                def get_project(project_name)
         | 
| 74 | 
            +
                  handling_failure("There is no such project: #@path_str") do
         | 
| 75 | 
            +
                    @config.projects[project_name]
         | 
| 76 | 
            +
                  end
         | 
| 77 | 
            +
                end
         | 
| 78 | 
            +
             | 
| 79 | 
            +
                def get_only_server_for_project(project)
         | 
| 80 | 
            +
                  if project.environments.one?
         | 
| 81 | 
            +
                    environment = project.environments.first
         | 
| 82 | 
            +
                    get_only_server_for_project_and_environment(project, environment)
         | 
| 83 | 
            +
                  else
         | 
| 84 | 
            +
                    raise_environment_ambiguous!(project)
         | 
| 85 | 
            +
                  end
         | 
| 86 | 
            +
                end
         | 
| 87 | 
            +
             | 
| 88 | 
            +
                def get_only_server
         | 
| 89 | 
            +
                  if @config.projects.one?
         | 
| 90 | 
            +
                    project = @config.projects.first
         | 
| 91 | 
            +
                    get_only_server_for_project(project)
         | 
| 92 | 
            +
                  else
         | 
| 93 | 
            +
                    raise_project_ambiguous!
         | 
| 94 | 
            +
                  end
         | 
| 95 | 
            +
                end
         | 
| 96 | 
            +
             | 
| 97 | 
            +
                def raise_project_ambiguous!
         | 
| 98 | 
            +
                  raise AmbiguousDestinationError, "There are multiple projects #{@config.projects.map(&:name).join(", ")}"
         | 
| 99 | 
            +
                end
         | 
| 100 | 
            +
             | 
| 101 | 
            +
                def raise_environment_ambiguous!(project)
         | 
| 102 | 
            +
                  raise AmbiguousDestinationError, "There are multiple environments for project #{project.name}: " \
         | 
| 103 | 
            +
                    "#{project.environments.map(&:name).join(", ")}"
         | 
| 104 | 
            +
                end
         | 
| 105 | 
            +
             | 
| 106 | 
            +
                def raise_server_ambiguous!(project, environment)
         | 
| 107 | 
            +
                  raise AmbiguousDestinationError, "There are multiple servers for project #{project.name} " \
         | 
| 108 | 
            +
                    "in environment #{environment.name}: #{environment.servers.map(&:name).join(", ")}"
         | 
| 109 | 
            +
                end
         | 
| 110 | 
            +
             | 
| 111 | 
            +
                def handling_failure(message)
         | 
| 112 | 
            +
                  yield
         | 
| 113 | 
            +
                rescue KeyError, NonExistentDestinationError
         | 
| 114 | 
            +
                  raise NonExistentDestinationError, message
         | 
| 115 | 
            +
                end
         | 
| 116 | 
            +
              end
         | 
| 117 | 
            +
            end
         | 
| 118 | 
            +
             | 
    
        data/lib/taketo/dsl.rb
    CHANGED
    
    | @@ -11,7 +11,7 @@ module Taketo | |
| 11 11 | 
             
                        raise ScopeError,
         | 
| 12 12 | 
             
                          "#{scope} can't be defined in #{current_scope} scope"
         | 
| 13 13 | 
             
                      end
         | 
| 14 | 
            -
                      scope_object = @factory.create(scope, name)
         | 
| 14 | 
            +
                      scope_object = current_scope_object.find(scope, name) { @factory.create(scope, name) }
         | 
| 15 15 | 
             
                      in_scope(scope, scope_object) do
         | 
| 16 16 | 
             
                        block.call
         | 
| 17 17 | 
             
                      end
         | 
| @@ -55,12 +55,13 @@ module Taketo | |
| 55 55 | 
             
                define_scope :server, :environment
         | 
| 56 56 | 
             
                define_scope :command, :server
         | 
| 57 57 |  | 
| 58 | 
            -
                define_attribute(: | 
| 59 | 
            -
                define_attribute(: | 
| 60 | 
            -
                define_attribute(: | 
| 61 | 
            -
                define_attribute(: | 
| 62 | 
            -
                define_attribute(: | 
| 63 | 
            -
                define_attribute(: | 
| 58 | 
            +
                define_attribute(:default_destination, :config) { |destination| current_scope_object.default_destination = destination }
         | 
| 59 | 
            +
                define_attribute(:host, :server)                { |hostname|    current_scope_object.host = hostname                   }
         | 
| 60 | 
            +
                define_attribute(:port, :server)                { |port_number| current_scope_object.port = port_number                }
         | 
| 61 | 
            +
                define_attribute(:user, :server)                { |username|    current_scope_object.username = username               }
         | 
| 62 | 
            +
                define_attribute(:location, :server)            { |path|        current_scope_object.default_location = path           }
         | 
| 63 | 
            +
                define_attribute(:env, :server)                 { |env|         current_scope_object.env(env)                          }
         | 
| 64 | 
            +
                define_attribute(:execute, :command)            { |command|     current_scope_object.command = command                 }
         | 
| 64 65 |  | 
| 65 66 | 
             
                private
         | 
| 66 67 |  | 
| @@ -78,7 +79,7 @@ module Taketo | |
| 78 79 |  | 
| 79 80 | 
             
                def in_scope(scope, new_scope_object)
         | 
| 80 81 | 
             
                  parent_scope_object, @current_scope_object = @current_scope_object, new_scope_object
         | 
| 81 | 
            -
                  @scope | 
| 82 | 
            +
                  @scope.push(scope)
         | 
| 82 83 | 
             
                  yield
         | 
| 83 84 | 
             
                  parent_scope_object.send("append_#{scope}", current_scope_object)
         | 
| 84 85 | 
             
                  @scope.pop
         | 
| @@ -7,19 +7,28 @@ module Taketo | |
| 7 7 | 
             
                  include Enumerable
         | 
| 8 8 | 
             
                  extend Forwardable
         | 
| 9 9 |  | 
| 10 | 
            -
                  def_delegators :@nodes, :each,  | 
| 10 | 
            +
                  def_delegators :@nodes, :each, :length, :size, :empty?
         | 
| 11 11 |  | 
| 12 12 | 
             
                  def initialize(nodes = [])
         | 
| 13 13 | 
             
                    @nodes = nodes
         | 
| 14 14 | 
             
                  end
         | 
| 15 15 |  | 
| 16 | 
            +
                  def push(node)
         | 
| 17 | 
            +
                    @nodes << node unless find_by_name(node.name)
         | 
| 18 | 
            +
                  end
         | 
| 19 | 
            +
                  alias :<< :push
         | 
| 20 | 
            +
             | 
| 16 21 | 
             
                  def [](index)
         | 
| 17 22 | 
             
                    if index.is_a?(Symbol)
         | 
| 18 | 
            -
                      node =  | 
| 23 | 
            +
                      node = find_by_name(index) or raise KeyError, "Element with name #{index} not found"
         | 
| 19 24 | 
             
                      return node
         | 
| 20 25 | 
             
                    end
         | 
| 21 26 | 
             
                    @nodes[index] or raise KeyError, "Element ##{index} not found"
         | 
| 22 27 | 
             
                  end
         | 
| 28 | 
            +
             | 
| 29 | 
            +
                  def find_by_name(name)
         | 
| 30 | 
            +
                    @nodes.detect { |n| n.name == name }
         | 
| 31 | 
            +
                  end
         | 
| 23 32 | 
             
                end
         | 
| 24 33 | 
             
              end
         | 
| 25 34 | 
             
            end
         | 
| @@ -11,6 +11,10 @@ describe "Taketo DSL" do | |
| 11 11 | 
             
                        host "127.0.0.2"
         | 
| 12 12 | 
             
                        user "deployer"
         | 
| 13 13 | 
             
                        location "/var/app"
         | 
| 14 | 
            +
                        env :FOO => "bar"
         | 
| 15 | 
            +
                        command :console do
         | 
| 16 | 
            +
                          execute "rails c"
         | 
| 17 | 
            +
                        end
         | 
| 14 18 | 
             
                      end
         | 
| 15 19 | 
             
                    end
         | 
| 16 20 |  | 
| @@ -40,6 +44,9 @@ describe "Taketo DSL" do | |
| 40 44 | 
             
                staging_server.host.should == "127.0.0.2"
         | 
| 41 45 | 
             
                staging_server.username.should == "deployer"
         | 
| 42 46 | 
             
                staging_server.default_location.should == "/var/app"
         | 
| 47 | 
            +
                staging_server.environment_variables.should == { :RAILS_ENV => "staging", :FOO => "bar" }
         | 
| 48 | 
            +
                staging_server.commands.length.should == 1
         | 
| 49 | 
            +
                staging_server.commands[:console].command.should == "rails c"
         | 
| 43 50 |  | 
| 44 51 | 
             
                production = project.environments[:production]
         | 
| 45 52 | 
             
                production.servers.length.should == 2
         | 
| @@ -0,0 +1,45 @@ | |
| 1 | 
            +
            require File.expand_path('../../../../spec_helper', __FILE__)
         | 
| 2 | 
            +
            require 'taketo/constructs/base_construct'
         | 
| 3 | 
            +
             | 
| 4 | 
            +
            include Taketo
         | 
| 5 | 
            +
             | 
| 6 | 
            +
            describe "BaseConstruct" do
         | 
| 7 | 
            +
              class TestConstruct < Constructs::BaseConstruct
         | 
| 8 | 
            +
                attr_reader :foos
         | 
| 9 | 
            +
             | 
| 10 | 
            +
                def initialize(name, foos)
         | 
| 11 | 
            +
                  super(name)
         | 
| 12 | 
            +
                  @foos = foos
         | 
| 13 | 
            +
                end
         | 
| 14 | 
            +
             | 
| 15 | 
            +
                def find_foo(name)
         | 
| 16 | 
            +
                  @foos[name]
         | 
| 17 | 
            +
                end
         | 
| 18 | 
            +
              end
         | 
| 19 | 
            +
             | 
| 20 | 
            +
              let(:foos) { mock(:NamedNodesCollection) }
         | 
| 21 | 
            +
              let(:construct) { TestConstruct.new(:construct, foos) }
         | 
| 22 | 
            +
             | 
| 23 | 
            +
              describe "#find" do
         | 
| 24 | 
            +
                context "if there is such node" do
         | 
| 25 | 
            +
                  it "should return node object with corresponding name" do
         | 
| 26 | 
            +
                    foos.should_receive(:[]).with(:bar).and_return(:qux)
         | 
| 27 | 
            +
                    construct.find(:foo, :bar).should == :qux
         | 
| 28 | 
            +
                  end
         | 
| 29 | 
            +
                end
         | 
| 30 | 
            +
             | 
| 31 | 
            +
                context "if there is no such command" do
         | 
| 32 | 
            +
                  before(:each) { foos.should_receive(:[]).and_return(nil) }
         | 
| 33 | 
            +
             | 
| 34 | 
            +
                  it "should yield if block given" do
         | 
| 35 | 
            +
                    expect { |b| construct.find(:foo, :bar, &b) }.to yield_control
         | 
| 36 | 
            +
                  end
         | 
| 37 | 
            +
             | 
| 38 | 
            +
                  it "should raise KeyError if no block given" do
         | 
| 39 | 
            +
                    expect { construct.find(:foo, :bar) }.to raise_error(KeyError)
         | 
| 40 | 
            +
                  end
         | 
| 41 | 
            +
                end
         | 
| 42 | 
            +
              end
         | 
| 43 | 
            +
            end
         | 
| 44 | 
            +
             | 
| 45 | 
            +
             | 
| @@ -13,5 +13,18 @@ describe "Config" do | |
| 13 13 | 
             
                  config.projects.should include(project)
         | 
| 14 14 | 
             
                end
         | 
| 15 15 | 
             
              end
         | 
| 16 | 
            +
             | 
| 17 | 
            +
              describe "#find_project" do
         | 
| 18 | 
            +
                it "should find project by name" do
         | 
| 19 | 
            +
                  config.projects.should_receive(:find_by_name).with(:foo).and_return(:bar)
         | 
| 20 | 
            +
                  config.find_project(:foo).should == :bar
         | 
| 21 | 
            +
                end
         | 
| 22 | 
            +
              end
         | 
| 23 | 
            +
             | 
| 24 | 
            +
              it "should set default_destination" do
         | 
| 25 | 
            +
                config.default_destination.should be_nil
         | 
| 26 | 
            +
                config.default_destination = "foo:bar:baz"
         | 
| 27 | 
            +
                config.default_destination.should == "foo:bar:baz"
         | 
| 28 | 
            +
              end
         | 
| 16 29 | 
             
            end
         | 
| 17 30 |  | 
| @@ -23,6 +23,13 @@ describe "Environment" do | |
| 23 23 | 
             
                  environment.append_server(server)
         | 
| 24 24 | 
             
                end
         | 
| 25 25 | 
             
              end
         | 
| 26 | 
            +
             | 
| 27 | 
            +
              describe "#find_server" do
         | 
| 28 | 
            +
                it "should find server by name" do
         | 
| 29 | 
            +
                  environment.servers.should_receive(:find_by_name).with(:foo).and_return(:bar)
         | 
| 30 | 
            +
                  environment.find_server(:foo).should == :bar
         | 
| 31 | 
            +
                end
         | 
| 32 | 
            +
              end
         | 
| 26 33 | 
             
            end
         | 
| 27 34 |  | 
| 28 35 |  | 
| @@ -17,5 +17,12 @@ describe "Project" do | |
| 17 17 | 
             
                  project.environments.should include(environment)
         | 
| 18 18 | 
             
                end
         | 
| 19 19 | 
             
              end
         | 
| 20 | 
            +
             | 
| 21 | 
            +
              describe "#find_environment" do
         | 
| 22 | 
            +
                it "should find environment by name" do
         | 
| 23 | 
            +
                  project.environments.should_receive(:find_by_name).with(:foo).and_return(:bar)
         | 
| 24 | 
            +
                  project.find_environment(:foo).should == :bar
         | 
| 25 | 
            +
                end
         | 
| 26 | 
            +
              end
         | 
| 20 27 | 
             
            end
         | 
| 21 28 |  | 
| @@ -60,22 +60,10 @@ describe "Server" do | |
| 60 60 | 
             
                  end
         | 
| 61 61 | 
             
                end
         | 
| 62 62 |  | 
| 63 | 
            -
                describe "# | 
| 64 | 
            -
                   | 
| 65 | 
            -
                     | 
| 66 | 
            -
             | 
| 67 | 
            -
                      server.command_by_name(:foo).should == command
         | 
| 68 | 
            -
                    end
         | 
| 69 | 
            -
                  end
         | 
| 70 | 
            -
             | 
| 71 | 
            -
                  context "if there is no such command" do
         | 
| 72 | 
            -
                    it "should yield if block given" do
         | 
| 73 | 
            -
                      expect { |b| server.command_by_name(:bar, &b) }.to yield_control
         | 
| 74 | 
            -
                    end
         | 
| 75 | 
            -
             | 
| 76 | 
            -
                    it "should raise CommandNotFoundError if no block given" do
         | 
| 77 | 
            -
                      expect { server.command_by_name(:bar) }.to raise_error(Taketo::Constructs::Server::CommandNotFoundError)
         | 
| 78 | 
            -
                    end
         | 
| 63 | 
            +
                describe "#find_command" do
         | 
| 64 | 
            +
                  it "should find command by name" do
         | 
| 65 | 
            +
                    server.commands.should_receive(:find_by_name).with(:foo).and_return(:bar)
         | 
| 66 | 
            +
                    server.find_command(:foo).should == :bar
         | 
| 79 67 | 
             
                  end
         | 
| 80 68 | 
             
                end
         | 
| 81 69 | 
             
              end
         | 
| @@ -6,7 +6,7 @@ include Taketo | |
| 6 6 | 
             
            describe "ConstructsFactory" do
         | 
| 7 7 | 
             
              let(:factory) { Taketo::ConstructsFactory.new }
         | 
| 8 8 |  | 
| 9 | 
            -
              specify "#create should delegate to  | 
| 9 | 
            +
              specify "#create should delegate to appropriate method according to the type" do
         | 
| 10 10 | 
             
                factory.should_receive(:create_config)
         | 
| 11 11 | 
             
                factory.create(:config)
         | 
| 12 12 |  | 
| @@ -0,0 +1,170 @@ | |
| 1 | 
            +
            require File.expand_path('../../../spec_helper', __FILE__)
         | 
| 2 | 
            +
            require 'taketo/destination_resolver'
         | 
| 3 | 
            +
            require 'taketo/support/named_nodes_collection'
         | 
| 4 | 
            +
             | 
| 5 | 
            +
            include Taketo
         | 
| 6 | 
            +
             | 
| 7 | 
            +
            describe "DestinationResolver" do
         | 
| 8 | 
            +
              let(:server1) { stub(:Server, :name => :s1) }
         | 
| 9 | 
            +
              let(:server2) { stub(:Server, :name => :s2) }
         | 
| 10 | 
            +
              let(:server3) { stub(:Server, :name => :s3) }
         | 
| 11 | 
            +
              let(:server4) { stub(:Server, :name => :s4) }
         | 
| 12 | 
            +
              let(:config) do
         | 
| 13 | 
            +
                stub(:Config, :projects => list(
         | 
| 14 | 
            +
                  stub(:name => :foo, :environments => list(
         | 
| 15 | 
            +
                    stub(:name => :bar, :servers => list(server1))
         | 
| 16 | 
            +
                  )),
         | 
| 17 | 
            +
                  stub(:name => :baz, :environments => list(
         | 
| 18 | 
            +
                    stub(:name => :qux, :servers => list(server2))
         | 
| 19 | 
            +
                  )),
         | 
| 20 | 
            +
                  stub(:name => :quux, :environments => list(
         | 
| 21 | 
            +
                    stub(:name => :corge, :servers => list(server3, server4))
         | 
| 22 | 
            +
                  )),
         | 
| 23 | 
            +
                  stub(:name => :grault, :environments => list(
         | 
| 24 | 
            +
                    stub(:name => :garply, :servers => list(anything, anything)),
         | 
| 25 | 
            +
                    stub(:name => :waldo, :servers => list(anything))
         | 
| 26 | 
            +
                  ))
         | 
| 27 | 
            +
                ))
         | 
| 28 | 
            +
              end
         | 
| 29 | 
            +
             | 
| 30 | 
            +
              context "when project, environment and server specified" do
         | 
| 31 | 
            +
                it "should return server if it exists" do
         | 
| 32 | 
            +
                  resolver(config, "foo:bar:s1").resolve.should == server1
         | 
| 33 | 
            +
                end
         | 
| 34 | 
            +
             | 
| 35 | 
            +
                it "should raise error if server does not exist" do
         | 
| 36 | 
            +
                  config = stub(:Config, :projects => list())
         | 
| 37 | 
            +
                  expect { resolver(config, "foo:bar:noserver").resolve }.to raise_error(NonExistentDestinationError, /no such/i)
         | 
| 38 | 
            +
                end
         | 
| 39 | 
            +
              end
         | 
| 40 | 
            +
             | 
| 41 | 
            +
              context "when there are 2 segments in path" do
         | 
| 42 | 
            +
                context "when there is matching project - environment pair" do
         | 
| 43 | 
            +
                  it "should return server if only one specified" do
         | 
| 44 | 
            +
                    resolver(config, "foo:bar").resolve.should == server1
         | 
| 45 | 
            +
                    resolver(config, "baz:qux").resolve.should == server2
         | 
| 46 | 
            +
                  end
         | 
| 47 | 
            +
             | 
| 48 | 
            +
                  it "should raise error if there are multiple servers" do
         | 
| 49 | 
            +
                    expect { resolver(config, "quux:corge").resolve }.to raise_error(AmbiguousDestinationError, /servers/i)
         | 
| 50 | 
            +
                  end
         | 
| 51 | 
            +
                end
         | 
| 52 | 
            +
             | 
| 53 | 
            +
                context "when there is no matching project - environment pair" do
         | 
| 54 | 
            +
                  it "should raise error if no such project - environment pair exist" do
         | 
| 55 | 
            +
                    expect { resolver(config, "chunky:bacon").resolve }.to raise_error(NonExistentDestinationError, /project.*environment/i)
         | 
| 56 | 
            +
                  end
         | 
| 57 | 
            +
                end
         | 
| 58 | 
            +
              end
         | 
| 59 | 
            +
             | 
| 60 | 
            +
              context "when there is only one segment in the path" do
         | 
| 61 | 
            +
                context "when project with given name exists" do
         | 
| 62 | 
            +
                  context "when there's one environment" do
         | 
| 63 | 
            +
                    context "when there's one server" do
         | 
| 64 | 
            +
                      it "should return the server" do
         | 
| 65 | 
            +
                        resolver(config, "foo").resolve.should == server1
         | 
| 66 | 
            +
                      end
         | 
| 67 | 
            +
                    end
         | 
| 68 | 
            +
             | 
| 69 | 
            +
                    context "when there are multiple servers" do
         | 
| 70 | 
            +
                      it "should raise error" do
         | 
| 71 | 
            +
                        expect { resolver(config, "quux").resolve }.to raise_error(AmbiguousDestinationError, /servers/i)
         | 
| 72 | 
            +
                      end
         | 
| 73 | 
            +
                    end
         | 
| 74 | 
            +
                  end
         | 
| 75 | 
            +
             | 
| 76 | 
            +
                  context "when there are multiple environments" do
         | 
| 77 | 
            +
                    it "should raise error" do
         | 
| 78 | 
            +
                      expect { resolver(config, "grault").resolve }.to raise_error(AmbiguousDestinationError, /environments/i)
         | 
| 79 | 
            +
                    end
         | 
| 80 | 
            +
                  end
         | 
| 81 | 
            +
                end
         | 
| 82 | 
            +
             | 
| 83 | 
            +
                context "when there is no such project" do
         | 
| 84 | 
            +
                  it "should raise error" do
         | 
| 85 | 
            +
                    expect { resolver(config, "chunky").resolve }.to raise_error(NonExistentDestinationError, /project/i)
         | 
| 86 | 
            +
                  end
         | 
| 87 | 
            +
                end
         | 
| 88 | 
            +
              end
         | 
| 89 | 
            +
             | 
| 90 | 
            +
              context "when passed path is empty" do
         | 
| 91 | 
            +
                context "when there is no default destination set" do
         | 
| 92 | 
            +
                  context "when there's one project" do
         | 
| 93 | 
            +
                    context "when there's one environment" do
         | 
| 94 | 
            +
                      context "when there's one server" do
         | 
| 95 | 
            +
                        it "should execute command without asking project/environment/server" do
         | 
| 96 | 
            +
                          config = stub(:Config, :default_destination => nil, :projects => list(
         | 
| 97 | 
            +
                            stub(:name => :foo, :environments => list(
         | 
| 98 | 
            +
                              stub(:name => :bar, :servers => list(
         | 
| 99 | 
            +
                                server1
         | 
| 100 | 
            +
                              ))
         | 
| 101 | 
            +
                            ))
         | 
| 102 | 
            +
                          ))
         | 
| 103 | 
            +
             | 
| 104 | 
            +
                          resolver(config, "").resolve.should == server1
         | 
| 105 | 
            +
                        end
         | 
| 106 | 
            +
                      end
         | 
| 107 | 
            +
             | 
| 108 | 
            +
                      context "when there are multiple servers" do
         | 
| 109 | 
            +
                        let(:server1) { stub(:Server, :name => :s1) }
         | 
| 110 | 
            +
                        let(:server2) { stub(:Server, :name => :s2) }
         | 
| 111 | 
            +
             | 
| 112 | 
            +
                        it "should ask for server" do
         | 
| 113 | 
            +
                          config = stub(:Config, :default_destination => nil, :projects => list(
         | 
| 114 | 
            +
                            stub(:name => :foo, :environments => list(
         | 
| 115 | 
            +
                              stub(:name => :bar, :servers => list(
         | 
| 116 | 
            +
                                server1, server2
         | 
| 117 | 
            +
                              ))
         | 
| 118 | 
            +
                            ))
         | 
| 119 | 
            +
                          ))
         | 
| 120 | 
            +
             | 
| 121 | 
            +
                          expect { resolver(config, "").resolve }.to raise_error AmbiguousDestinationError, /server/i
         | 
| 122 | 
            +
                        end
         | 
| 123 | 
            +
                      end
         | 
| 124 | 
            +
                    end
         | 
| 125 | 
            +
             | 
| 126 | 
            +
                    context "when there are multiple environments" do
         | 
| 127 | 
            +
                      it "should ask for environment" do
         | 
| 128 | 
            +
                        config = stub(:Config, :default_destination => nil, :projects => list(
         | 
| 129 | 
            +
                          stub(:name => :foo, :environments => list(
         | 
| 130 | 
            +
                            stub(:name => :bar, :servers => [anything]),
         | 
| 131 | 
            +
                            stub(:name => :baz, :servers => [anything])
         | 
| 132 | 
            +
                          ))
         | 
| 133 | 
            +
                        ))
         | 
| 134 | 
            +
             | 
| 135 | 
            +
                        expect { resolver(config, "").resolve }.to raise_error AmbiguousDestinationError, /environment/i
         | 
| 136 | 
            +
                      end
         | 
| 137 | 
            +
                    end
         | 
| 138 | 
            +
                  end
         | 
| 139 | 
            +
             | 
| 140 | 
            +
                  context "when there are multiple projects" do
         | 
| 141 | 
            +
                    it "should ask for project" do
         | 
| 142 | 
            +
                      config = stub(:Config, :default_destination => nil, :projects => list(
         | 
| 143 | 
            +
                        stub(:name => :foo, :environments => [anything]),
         | 
| 144 | 
            +
                        stub(:name => :bar, :environments => [anything])
         | 
| 145 | 
            +
                      ))
         | 
| 146 | 
            +
             | 
| 147 | 
            +
                      expect { resolver(config, "").resolve }.to raise_error AmbiguousDestinationError, /projects/i
         | 
| 148 | 
            +
                    end
         | 
| 149 | 
            +
                  end
         | 
| 150 | 
            +
                end
         | 
| 151 | 
            +
             | 
| 152 | 
            +
                context "when there is default destination" do
         | 
| 153 | 
            +
                  it "should resolve by default destination" do
         | 
| 154 | 
            +
                    config.stub(:default_destination => "foo:bar:s1")
         | 
| 155 | 
            +
                    resolver(config, "").resolve.should == server1
         | 
| 156 | 
            +
                  end
         | 
| 157 | 
            +
                end
         | 
| 158 | 
            +
              end
         | 
| 159 | 
            +
             | 
| 160 | 
            +
             | 
| 161 | 
            +
              def resolver(*args)
         | 
| 162 | 
            +
                DestinationResolver.new(*args)
         | 
| 163 | 
            +
              end
         | 
| 164 | 
            +
             | 
| 165 | 
            +
              def list(*items)
         | 
| 166 | 
            +
                Taketo::Support::NamedNodesCollection.new(items)
         | 
| 167 | 
            +
              end
         | 
| 168 | 
            +
             | 
| 169 | 
            +
            end
         | 
| 170 | 
            +
             | 
    
        data/spec/lib/taketo/dsl_spec.rb
    CHANGED
    
    | @@ -18,28 +18,36 @@ describe "DSL" do | |
| 18 18 | 
             
                  it { should_not be_appropriate_construct(scope_name, :foo).under(inappropriate_scope) }
         | 
| 19 19 | 
             
                end
         | 
| 20 20 |  | 
| 21 | 
            -
                it "should create a #{scope_name} and set it as current scope object" do
         | 
| 22 | 
            -
                  dsl(parent_scope, factory.create(parent_scope_name)) do |c|
         | 
| 23 | 
            -
                     | 
| 24 | 
            -
             | 
| 25 | 
            -
             | 
| 26 | 
            -
                     | 
| 27 | 
            -
             | 
| 28 | 
            -
             | 
| 29 | 
            -
             | 
| 30 | 
            -
             | 
| 31 | 
            -
             | 
| 32 | 
            -
             | 
| 33 | 
            -
             | 
| 34 | 
            -
                   | 
| 35 | 
            -
             | 
| 36 | 
            -
             | 
| 37 | 
            -
             | 
| 38 | 
            -
             | 
| 39 | 
            -
                    c.current_scope_object. | 
| 40 | 
            -
             | 
| 41 | 
            -
             | 
| 42 | 
            -
             | 
| 21 | 
            +
                it "should create a #{scope_name} and set it as current scope object" do # it "should create project and set it as current scope object"
         | 
| 22 | 
            +
                  dsl(parent_scope, factory.create(parent_scope_name)) do |c|            #   dsl([:config], factory.create(:config)) do |c|
         | 
| 23 | 
            +
                    c.current_scope_object.should_receive(:find).with(scope_name, :bar). #     c.current_scope_object.should_receive(:find).with(:project, :bar).
         | 
| 24 | 
            +
                      and_yield.and_return(:bacon)                                       #       and_yield.and_return(:bacon)
         | 
| 25 | 
            +
                    factory.should_receive(:create).with(scope_name, :bar)               #     factory.should_receive(:create).with(:project, :bar)
         | 
| 26 | 
            +
                    c.send(scope_name, :bar) do                                          #     c.project(:bar) do
         | 
| 27 | 
            +
                      c.current_scope_object.should_not be_nil                           #       c.current_scope_object.should_not be_nil
         | 
| 28 | 
            +
                      c.current_scope_object.should == :bacon                            #       c.current_scope_object.should == factory.project
         | 
| 29 | 
            +
                    end                                                                  #     end
         | 
| 30 | 
            +
                  end                                                                    #   end
         | 
| 31 | 
            +
                end                                                                      # end
         | 
| 32 | 
            +
             | 
| 33 | 
            +
                it "should not leak #{scope_name} as current scope object" do              # it "should not leak project as current scope object"
         | 
| 34 | 
            +
                  dsl(parent_scope, factory.create(parent_scope_name)) do |c|              #   dsl([:config], factory.create(:config)) do |c|
         | 
| 35 | 
            +
                    c.current_scope_object.stub(:find => factory.create(scope_name, :bar)) #     c.current_scope.stub(:find => factory.create(:project, :bar)) 
         | 
| 36 | 
            +
                    c.send(scope_name, :bar) do                                            #     c.project(:bar) do
         | 
| 37 | 
            +
                      c.current_scope_object.should == factory.send(scope_name)            #       c.current_scope_object.should == factory.project
         | 
| 38 | 
            +
                    end                                                                    #     end
         | 
| 39 | 
            +
                    c.current_scope_object.should_not == factory.send(scope_name)          #     c.current_scope_object.should_not == factory.project
         | 
| 40 | 
            +
                  end                                                                      #   end
         | 
| 41 | 
            +
                end                                                                        # end
         | 
| 42 | 
            +
             | 
| 43 | 
            +
                it "should add a #{scope_name} to the #{parent_scope_name}'s #{scope_name}s collection" do # it "should add a project to the config's projects collection" do
         | 
| 44 | 
            +
                  dsl(parent_scope, factory.create(parent_scope_name)) do |c|                              #   dsl([:config], factory.create(:config)) do |c|
         | 
| 45 | 
            +
                    c.current_scope_object.stub(:find => factory.create(scope_name, :bar))                 #     c.current_scope_object.stub(:find => factory.create(:project, :bar))
         | 
| 46 | 
            +
                    c.current_scope_object.should_receive("append_#{scope_name}").                         #     c.current_scope_object.should_receive(:append_project).
         | 
| 47 | 
            +
                      with(factory.send(scope_name))                                                       #       with(factory.project)
         | 
| 48 | 
            +
                    c.send(scope_name, :bar) {}                                                            #     c.project(:bar) {}
         | 
| 49 | 
            +
                  end                                                                                      #   end
         | 
| 50 | 
            +
                end                                                                                        # end
         | 
| 43 51 | 
             
              end
         | 
| 44 52 |  | 
| 45 53 | 
             
              shared_examples "an attribute" do |attribute_name, parent_scope_name, parent_scope_method, example_value|
         | 
| @@ -51,14 +59,18 @@ describe "DSL" do | |
| 51 59 | 
             
                  it { should_not be_appropriate_construct(attribute_name, example_value).under(inaproppriate_scope) }
         | 
| 52 60 | 
             
                end
         | 
| 53 61 |  | 
| 54 | 
            -
                it "should call #{parent_scope_method} on current #{parent_scope_name}" do
         | 
| 55 | 
            -
                  dsl(parent_scope, factory.create(parent_scope_name, :foo)) do |c|
         | 
| 56 | 
            -
                    factory.send(parent_scope_name).should_receive(parent_scope_method).with(example_value)
         | 
| 57 | 
            -
                    c.send(attribute_name, example_value)
         | 
| 58 | 
            -
                  end
         | 
| 62 | 
            +
                it "should call #{parent_scope_method} on current #{parent_scope_name}" do                  # it "should call default_location= on current server" do
         | 
| 63 | 
            +
                  dsl(parent_scope, factory.create(parent_scope_name, :foo)) do |c|                         #   dsl([:config, :project, :environment, :server], factory.create(:server, :foo)) do |c|
         | 
| 64 | 
            +
                    factory.send(parent_scope_name).should_receive(parent_scope_method).with(example_value) #     factory.server.should_receive(:default_location=).with('/var/app/')
         | 
| 65 | 
            +
                    c.send(attribute_name, example_value)                                                   #   c.location "/var/app"
         | 
| 66 | 
            +
                  end                                                                                       # end
         | 
| 59 67 | 
             
                end
         | 
| 60 68 | 
             
              end
         | 
| 61 69 |  | 
| 70 | 
            +
              describe "#default_destination" do
         | 
| 71 | 
            +
                it_behaves_like "an attribute", :default_destination, :config, :default_destination=, "foo:bar:baz"
         | 
| 72 | 
            +
              end
         | 
| 73 | 
            +
             | 
| 62 74 | 
             
              describe "#project" do
         | 
| 63 75 | 
             
                it_behaves_like "a scope", :project, :config
         | 
| 64 76 |  | 
| @@ -26,7 +26,13 @@ describe Taketo::Support::EvalDelegator do | |
| 26 26 | 
             
                  end.not_to raise_error
         | 
| 27 27 | 
             
                end
         | 
| 28 28 |  | 
| 29 | 
            -
                it "should  | 
| 29 | 
            +
                it "should raise if external context does not respond" do
         | 
| 30 | 
            +
                  expect do
         | 
| 31 | 
            +
                    EvalDelegatorContext.new.evaluate { qux }
         | 
| 32 | 
            +
                  end.to raise_error(NameError)
         | 
| 33 | 
            +
                end
         | 
| 34 | 
            +
             | 
| 35 | 
            +
                it "should pass local variabnes through the scopes" do
         | 
| 30 36 | 
             
                  baz = :foo
         | 
| 31 37 | 
             
                  expect do
         | 
| 32 38 | 
             
                    EvalDelegatorContext.new.evaluate { baz }
         | 
| @@ -24,6 +24,13 @@ describe "NamedNodesCollection" do | |
| 24 24 | 
             
                expect { collection[3] }.to raise_error KeyError, /#3/i
         | 
| 25 25 | 
             
                expect { collection[:quux] }.to raise_error KeyError, /name/i
         | 
| 26 26 | 
             
              end
         | 
| 27 | 
            +
             | 
| 28 | 
            +
              it "should not add if node with same name exists" do
         | 
| 29 | 
            +
                collection << node1
         | 
| 30 | 
            +
                collection.push node1
         | 
| 31 | 
            +
                collection.length.should == 1
         | 
| 32 | 
            +
                collection.first.should == node1
         | 
| 33 | 
            +
              end
         | 
| 27 34 | 
             
            end
         | 
| 28 35 |  | 
| 29 36 |  | 
    
        metadata
    CHANGED
    
    | @@ -1,7 +1,7 @@ | |
| 1 1 | 
             
            --- !ruby/object:Gem::Specification
         | 
| 2 2 | 
             
            name: taketo
         | 
| 3 3 | 
             
            version: !ruby/object:Gem::Version
         | 
| 4 | 
            -
              version: 0.0. | 
| 4 | 
            +
              version: 0.0.3
         | 
| 5 5 | 
             
              prerelease: 
         | 
| 6 6 | 
             
            platform: ruby
         | 
| 7 7 | 
             
            authors:
         | 
| @@ -9,7 +9,7 @@ authors: | |
| 9 9 | 
             
            autorequire: 
         | 
| 10 10 | 
             
            bindir: bin
         | 
| 11 11 | 
             
            cert_chain: []
         | 
| 12 | 
            -
            date: 2012-07- | 
| 12 | 
            +
            date: 2012-07-22 00:00:00.000000000 Z
         | 
| 13 13 | 
             
            dependencies:
         | 
| 14 14 | 
             
            - !ruby/object:Gem::Dependency
         | 
| 15 15 | 
             
              name: rspec
         | 
| @@ -86,6 +86,7 @@ files: | |
| 86 86 | 
             
            - lib/taketo/commands/ssh_command.rb
         | 
| 87 87 | 
             
            - lib/taketo/commands.rb
         | 
| 88 88 | 
             
            - lib/taketo/config_validator.rb
         | 
| 89 | 
            +
            - lib/taketo/constructs/base_construct.rb
         | 
| 89 90 | 
             
            - lib/taketo/constructs/command.rb
         | 
| 90 91 | 
             
            - lib/taketo/constructs/config.rb
         | 
| 91 92 | 
             
            - lib/taketo/constructs/environment.rb
         | 
| @@ -93,26 +94,27 @@ files: | |
| 93 94 | 
             
            - lib/taketo/constructs/server.rb
         | 
| 94 95 | 
             
            - lib/taketo/constructs.rb
         | 
| 95 96 | 
             
            - lib/taketo/constructs_factory.rb
         | 
| 97 | 
            +
            - lib/taketo/destination_resolver.rb
         | 
| 96 98 | 
             
            - lib/taketo/dsl.rb
         | 
| 97 99 | 
             
            - lib/taketo/support/eval_delegator.rb
         | 
| 98 100 | 
             
            - lib/taketo/support/key_error.rb
         | 
| 99 101 | 
             
            - lib/taketo/support/named_nodes_collection.rb
         | 
| 100 102 | 
             
            - lib/taketo/support.rb
         | 
| 101 | 
            -
            - lib/taketo/taketo_argv_parser.rb
         | 
| 102 103 | 
             
            - lib/taketo.rb
         | 
| 103 104 | 
             
            - spec/integration/dsl_integration_spec.rb
         | 
| 104 105 | 
             
            - spec/lib/taketo/commands/ssh_command_spec.rb
         | 
| 105 106 | 
             
            - spec/lib/taketo/config_validator_spec.rb
         | 
| 107 | 
            +
            - spec/lib/taketo/constructs/base_construct_spec.rb
         | 
| 106 108 | 
             
            - spec/lib/taketo/constructs/command_spec.rb
         | 
| 107 109 | 
             
            - spec/lib/taketo/constructs/config_spec.rb
         | 
| 108 110 | 
             
            - spec/lib/taketo/constructs/environment_spec.rb
         | 
| 109 111 | 
             
            - spec/lib/taketo/constructs/project_spec.rb
         | 
| 110 112 | 
             
            - spec/lib/taketo/constructs/server_spec.rb
         | 
| 111 113 | 
             
            - spec/lib/taketo/constructs_factory_spec.rb
         | 
| 114 | 
            +
            - spec/lib/taketo/destination_resolver_spec.rb
         | 
| 112 115 | 
             
            - spec/lib/taketo/dsl_spec.rb
         | 
| 113 116 | 
             
            - spec/lib/taketo/support/eval_delegator_spec.rb
         | 
| 114 117 | 
             
            - spec/lib/taketo/support/named_nodes_collection_spec.rb
         | 
| 115 | 
            -
            - spec/lib/taketo/taketo_argv_parser_spec.rb
         | 
| 116 118 | 
             
            - spec/spec_helper.rb
         | 
| 117 119 | 
             
            - spec/support/helpers/dsl_spec_helper.rb
         | 
| 118 120 | 
             
            - spec/support/matchers/be_appropriate_construct_matcher.rb
         | 
| @@ -1,48 +0,0 @@ | |
| 1 | 
            -
            module Taketo
         | 
| 2 | 
            -
              class ConfigError < StandardError; end
         | 
| 3 | 
            -
             | 
| 4 | 
            -
              class TaketoArgvParser
         | 
| 5 | 
            -
                def initialize(config, argv)
         | 
| 6 | 
            -
                  @config = config
         | 
| 7 | 
            -
                  @argv   = argv
         | 
| 8 | 
            -
                end
         | 
| 9 | 
            -
             | 
| 10 | 
            -
                def parse
         | 
| 11 | 
            -
                  if all_specified?
         | 
| 12 | 
            -
                    project_name, environment_name, server_name = @argv.shift(3).map(&:to_sym)
         | 
| 13 | 
            -
             | 
| 14 | 
            -
                    begin
         | 
| 15 | 
            -
                      return @config.projects[project_name].environments[environment_name].servers[server_name]
         | 
| 16 | 
            -
                    rescue KeyError
         | 
| 17 | 
            -
                      raise ArgumentError,
         | 
| 18 | 
            -
                        "Server #{server_name} in environment #{environment_name} for project #{project_name} does not exist"
         | 
| 19 | 
            -
                    end
         | 
| 20 | 
            -
                  end
         | 
| 21 | 
            -
             | 
| 22 | 
            -
                  if @config.projects.one?
         | 
| 23 | 
            -
                    project = @config.projects.first
         | 
| 24 | 
            -
                    if project.environments.one?
         | 
| 25 | 
            -
                      environment = project.environments.first
         | 
| 26 | 
            -
                      if environment.servers.one?
         | 
| 27 | 
            -
                        return environment.servers.first
         | 
| 28 | 
            -
                      elsif environment.servers.length > 1
         | 
| 29 | 
            -
                        if server_name = @argv.shift
         | 
| 30 | 
            -
                          return environment.servers[server_name.to_sym]
         | 
| 31 | 
            -
                        else
         | 
| 32 | 
            -
                          raise ArgumentError, "There are multiple servers for project #{project.name} " \
         | 
| 33 | 
            -
                            "in environment #{environment.name}: #{environment.servers.map(&:name).join(", ")}"
         | 
| 34 | 
            -
                        end
         | 
| 35 | 
            -
                      end
         | 
| 36 | 
            -
                    end
         | 
| 37 | 
            -
                  end
         | 
| 38 | 
            -
                end
         | 
| 39 | 
            -
             | 
| 40 | 
            -
                private
         | 
| 41 | 
            -
             | 
| 42 | 
            -
                def all_specified?
         | 
| 43 | 
            -
                  @argv.size >= 3
         | 
| 44 | 
            -
                end
         | 
| 45 | 
            -
             | 
| 46 | 
            -
              end
         | 
| 47 | 
            -
            end
         | 
| 48 | 
            -
             | 
| @@ -1,92 +0,0 @@ | |
| 1 | 
            -
            require File.expand_path('../../../spec_helper', __FILE__)
         | 
| 2 | 
            -
            require 'taketo/taketo_argv_parser'
         | 
| 3 | 
            -
            require 'taketo/support/named_nodes_collection'
         | 
| 4 | 
            -
             | 
| 5 | 
            -
            include Taketo
         | 
| 6 | 
            -
             | 
| 7 | 
            -
            describe "TaketoArgvParser" do
         | 
| 8 | 
            -
              context "when project, environment and server specified" do
         | 
| 9 | 
            -
                let(:server) { stub(:Server, :name => :baz) }
         | 
| 10 | 
            -
             | 
| 11 | 
            -
                it "should return server if it exists" do
         | 
| 12 | 
            -
                  config = stub(:Config, :projects => list(
         | 
| 13 | 
            -
                    stub(:name => :foo, :environments => list(
         | 
| 14 | 
            -
                      stub(:name => :bar, :servers => list(
         | 
| 15 | 
            -
                        server
         | 
| 16 | 
            -
                      ))
         | 
| 17 | 
            -
                    ))
         | 
| 18 | 
            -
                  ))
         | 
| 19 | 
            -
             | 
| 20 | 
            -
                  parser(config, %w(foo bar baz)).parse.should == server
         | 
| 21 | 
            -
                end
         | 
| 22 | 
            -
             | 
| 23 | 
            -
                it "should raise error if server does not exist" do
         | 
| 24 | 
            -
                  config = stub(:Config, :projects => list())
         | 
| 25 | 
            -
                  expect do
         | 
| 26 | 
            -
                    parser(config, %w(foo bar baz)).parse
         | 
| 27 | 
            -
                  end.to raise_error ArgumentError, /exist/i
         | 
| 28 | 
            -
                end
         | 
| 29 | 
            -
              end
         | 
| 30 | 
            -
             | 
| 31 | 
            -
              context "when there are two arguments" do
         | 
| 32 | 
            -
              end
         | 
| 33 | 
            -
             | 
| 34 | 
            -
              context "when there are no args" do
         | 
| 35 | 
            -
                context "when there's one project" do
         | 
| 36 | 
            -
                  context "when there's one environment" do
         | 
| 37 | 
            -
                    context "when there's one server" do
         | 
| 38 | 
            -
                      let(:server) { stub(:Server) }
         | 
| 39 | 
            -
             | 
| 40 | 
            -
                      it "should execute command without asking project/environment/server" do
         | 
| 41 | 
            -
                        config = stub(:Config, :projects => list(
         | 
| 42 | 
            -
                          stub(:name => :foo, :environments => list(
         | 
| 43 | 
            -
                            stub(:name => :bar, :servers => list(
         | 
| 44 | 
            -
                              server
         | 
| 45 | 
            -
                            ))
         | 
| 46 | 
            -
                          ))
         | 
| 47 | 
            -
                        ))
         | 
| 48 | 
            -
             | 
| 49 | 
            -
                        parser(config, []).parse.should == server
         | 
| 50 | 
            -
                      end
         | 
| 51 | 
            -
                    end
         | 
| 52 | 
            -
             | 
| 53 | 
            -
                    context "when there are multiple servers" do
         | 
| 54 | 
            -
                      let(:server1) { stub(:Server, :name => :s1) }
         | 
| 55 | 
            -
                      let(:server2) { stub(:Server, :name => :s2) }
         | 
| 56 | 
            -
             | 
| 57 | 
            -
                      it "should ask for server if it's not specified" do
         | 
| 58 | 
            -
                        config = stub(:Config, :projects => list(
         | 
| 59 | 
            -
                          stub(:name => :foo, :environments => list(
         | 
| 60 | 
            -
                            stub(:name => :bar, :servers => list(
         | 
| 61 | 
            -
                              server1, server2
         | 
| 62 | 
            -
                            ))
         | 
| 63 | 
            -
                          ))
         | 
| 64 | 
            -
                        ))
         | 
| 65 | 
            -
             | 
| 66 | 
            -
                        expect do
         | 
| 67 | 
            -
                          parser(config, []).parse
         | 
| 68 | 
            -
                        end.to raise_error ArgumentError, /server/i
         | 
| 69 | 
            -
             | 
| 70 | 
            -
                        parser(config, ["s1"]).parse.should == server1
         | 
| 71 | 
            -
                      end
         | 
| 72 | 
            -
                    end
         | 
| 73 | 
            -
                  end
         | 
| 74 | 
            -
             | 
| 75 | 
            -
                  context "when there are multiple environments" do
         | 
| 76 | 
            -
                    context "when environment not specified" do
         | 
| 77 | 
            -
                      it "should ask for environment"
         | 
| 78 | 
            -
                    end
         | 
| 79 | 
            -
                  end
         | 
| 80 | 
            -
                end
         | 
| 81 | 
            -
              end
         | 
| 82 | 
            -
             | 
| 83 | 
            -
              def parser(*args)
         | 
| 84 | 
            -
                TaketoArgvParser.new(*args)
         | 
| 85 | 
            -
              end
         | 
| 86 | 
            -
             | 
| 87 | 
            -
              def list(*items)
         | 
| 88 | 
            -
                Taketo::Support::NamedNodesCollection.new(items)
         | 
| 89 | 
            -
              end
         | 
| 90 | 
            -
             | 
| 91 | 
            -
            end
         | 
| 92 | 
            -
             |