bosh_cli 0.19.6 → 1.0.rc1
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/bin/bosh +3 -0
 - data/lib/cli.rb +15 -5
 - data/lib/cli/{commands/base.rb → base_command.rb} +38 -44
 - data/lib/cli/command_discovery.rb +40 -0
 - data/lib/cli/command_handler.rb +135 -0
 - data/lib/cli/commands/biff.rb +16 -12
 - data/lib/cli/commands/blob_management.rb +10 -3
 - data/lib/cli/commands/cloudcheck.rb +13 -11
 - data/lib/cli/commands/complete.rb +29 -0
 - data/lib/cli/commands/deployment.rb +137 -28
 - data/lib/cli/commands/help.rb +96 -0
 - data/lib/cli/commands/job.rb +4 -1
 - data/lib/cli/commands/job_management.rb +36 -23
 - data/lib/cli/commands/job_rename.rb +11 -12
 - data/lib/cli/commands/log_management.rb +28 -32
 - data/lib/cli/commands/maintenance.rb +6 -1
 - data/lib/cli/commands/misc.rb +129 -87
 - data/lib/cli/commands/package.rb +6 -65
 - data/lib/cli/commands/property_management.rb +20 -8
 - data/lib/cli/commands/release.rb +211 -206
 - data/lib/cli/commands/ssh.rb +178 -188
 - data/lib/cli/commands/stemcell.rb +114 -51
 - data/lib/cli/commands/task.rb +74 -56
 - data/lib/cli/commands/user.rb +6 -3
 - data/lib/cli/commands/vms.rb +17 -15
 - data/lib/cli/config.rb +27 -1
 - data/lib/cli/core_ext.rb +27 -1
 - data/lib/cli/deployment_helper.rb +47 -0
 - data/lib/cli/director.rb +18 -9
 - data/lib/cli/errors.rb +6 -0
 - data/lib/cli/job_builder.rb +75 -23
 - data/lib/cli/job_property_collection.rb +87 -0
 - data/lib/cli/job_property_validator.rb +130 -0
 - data/lib/cli/package_builder.rb +32 -5
 - data/lib/cli/release.rb +2 -0
 - data/lib/cli/release_builder.rb +9 -13
 - data/lib/cli/release_compiler.rb +5 -34
 - data/lib/cli/release_tarball.rb +4 -19
 - data/lib/cli/runner.rb +118 -694
 - data/lib/cli/version.rb +1 -1
 - data/spec/assets/config/swift-hp/config/final.yml +6 -0
 - data/spec/assets/config/swift-hp/config/private.yml +7 -0
 - data/spec/assets/config/swift-rackspace/config/final.yml +6 -0
 - data/spec/assets/config/swift-rackspace/config/private.yml +6 -0
 - data/spec/spec_helper.rb +0 -5
 - data/spec/unit/base_command_spec.rb +32 -37
 - data/spec/unit/biff_spec.rb +11 -10
 - data/spec/unit/cli_commands_spec.rb +96 -88
 - data/spec/unit/core_ext_spec.rb +1 -1
 - data/spec/unit/deployment_manifest_spec.rb +36 -0
 - data/spec/unit/director_spec.rb +17 -3
 - data/spec/unit/job_builder_spec.rb +2 -2
 - data/spec/unit/job_property_collection_spec.rb +111 -0
 - data/spec/unit/job_property_validator_spec.rb +7 -0
 - data/spec/unit/job_rename_spec.rb +7 -6
 - data/spec/unit/package_builder_spec.rb +2 -2
 - data/spec/unit/release_builder_spec.rb +33 -0
 - data/spec/unit/release_spec.rb +54 -0
 - data/spec/unit/release_tarball_spec.rb +2 -7
 - data/spec/unit/runner_spec.rb +1 -151
 - data/spec/unit/ssh_spec.rb +15 -9
 - metadata +41 -12
 - data/lib/cli/command_definition.rb +0 -52
 - data/lib/cli/templates/help_message.erb +0 -80
 
    
        data/lib/cli/release.rb
    CHANGED
    
    | 
         @@ -64,6 +64,8 @@ module Bosh::Cli 
     | 
|
| 
       64 
64 
     | 
    
         
             
                  has_legacy_secret? ||
         
     | 
| 
       65 
65 
     | 
    
         
             
                    has_blobstore_secrets?(bs, "atmos", "secret") ||
         
     | 
| 
       66 
66 
     | 
    
         
             
                    has_blobstore_secrets?(bs, "simple", "user", "password") ||
         
     | 
| 
      
 67 
     | 
    
         
            +
                    has_blobstore_secrets?(bs, "swift", "rackspace") ||
         
     | 
| 
      
 68 
     | 
    
         
            +
                    has_blobstore_secrets?(bs, "swift", "hp") ||
         
     | 
| 
       67 
69 
     | 
    
         
             
                    has_blobstore_secrets?(bs, "s3", "access_key_id", "secret_access_key")
         
     | 
| 
       68 
70 
     | 
    
         
             
                end
         
     | 
| 
       69 
71 
     | 
    
         | 
    
        data/lib/cli/release_builder.rb
    CHANGED
    
    | 
         @@ -7,7 +7,7 @@ module Bosh::Cli 
     | 
|
| 
       7 
7 
     | 
    
         | 
| 
       8 
8 
     | 
    
         
             
                DEFAULT_RELEASE_NAME = "bosh_release"
         
     | 
| 
       9 
9 
     | 
    
         | 
| 
       10 
     | 
    
         
            -
                attr_reader :release, :packages, :jobs, :version
         
     | 
| 
      
 10 
     | 
    
         
            +
                attr_reader :release, :packages, :jobs, :version, :build_dir
         
     | 
| 
       11 
11 
     | 
    
         | 
| 
       12 
12 
     | 
    
         
             
                # @param [Bosh::Cli::Release] release Current release
         
     | 
| 
       13 
13 
     | 
    
         
             
                # @param [Array<Bosh::Cli::PackageBuilder>] packages Built packages
         
     | 
| 
         @@ -23,7 +23,12 @@ module Bosh::Cli 
     | 
|
| 
       23 
23 
     | 
    
         
             
                  @dev_index = VersionsIndex.new(dev_releases_dir, release_name)
         
     | 
| 
       24 
24 
     | 
    
         
             
                  @index = @final ? @final_index : @dev_index
         
     | 
| 
       25 
25 
     | 
    
         | 
| 
       26 
     | 
    
         
            -
                   
     | 
| 
      
 26 
     | 
    
         
            +
                  @build_dir = Dir.mktmpdir
         
     | 
| 
      
 27 
     | 
    
         
            +
             
     | 
| 
      
 28 
     | 
    
         
            +
                  in_build_dir do
         
     | 
| 
      
 29 
     | 
    
         
            +
                    FileUtils.mkdir("packages")
         
     | 
| 
      
 30 
     | 
    
         
            +
                    FileUtils.mkdir("jobs")
         
     | 
| 
      
 31 
     | 
    
         
            +
                  end
         
     | 
| 
       27 
32 
     | 
    
         
             
                end
         
     | 
| 
       28 
33 
     | 
    
         | 
| 
       29 
34 
     | 
    
         
             
                # @return [String] Release name
         
     | 
| 
         @@ -107,6 +112,7 @@ module Bosh::Cli 
     | 
|
| 
       107 
112 
     | 
    
         
             
                      "name" => package.name,
         
     | 
| 
       108 
113 
     | 
    
         
             
                      "version" => package.version,
         
     | 
| 
       109 
114 
     | 
    
         
             
                      "sha1" => package.checksum,
         
     | 
| 
      
 115 
     | 
    
         
            +
                      "fingerprint" => package.fingerprint,
         
     | 
| 
       110 
116 
     | 
    
         
             
                      "dependencies" => package.dependencies
         
     | 
| 
       111 
117 
     | 
    
         
             
                    }
         
     | 
| 
       112 
118 
     | 
    
         
             
                  end
         
     | 
| 
         @@ -115,6 +121,7 @@ module Bosh::Cli 
     | 
|
| 
       115 
121 
     | 
    
         
             
                    {
         
     | 
| 
       116 
122 
     | 
    
         
             
                      "name" => job.name,
         
     | 
| 
       117 
123 
     | 
    
         
             
                      "version" => job.version,
         
     | 
| 
      
 124 
     | 
    
         
            +
                      "fingerprint" => job.fingerprint,
         
     | 
| 
       118 
125 
     | 
    
         
             
                      "sha1" => job.checksum,
         
     | 
| 
       119 
126 
     | 
    
         
             
                    }
         
     | 
| 
       120 
127 
     | 
    
         
             
                  end
         
     | 
| 
         @@ -229,17 +236,6 @@ module Bosh::Cli 
     | 
|
| 
       229 
236 
     | 
    
         
             
                  end
         
     | 
| 
       230 
237 
     | 
    
         
             
                end
         
     | 
| 
       231 
238 
     | 
    
         | 
| 
       232 
     | 
    
         
            -
                def build_dir
         
     | 
| 
       233 
     | 
    
         
            -
                  @build_dir ||= Dir.mktmpdir
         
     | 
| 
       234 
     | 
    
         
            -
                end
         
     | 
| 
       235 
     | 
    
         
            -
             
     | 
| 
       236 
     | 
    
         
            -
                def create_release_build_dir
         
     | 
| 
       237 
     | 
    
         
            -
                  in_build_dir do
         
     | 
| 
       238 
     | 
    
         
            -
                    FileUtils.mkdir("packages")
         
     | 
| 
       239 
     | 
    
         
            -
                    FileUtils.mkdir("jobs")
         
     | 
| 
       240 
     | 
    
         
            -
                  end
         
     | 
| 
       241 
     | 
    
         
            -
                end
         
     | 
| 
       242 
     | 
    
         
            -
             
     | 
| 
       243 
239 
     | 
    
         
             
                def in_build_dir(&block)
         
     | 
| 
       244 
240 
     | 
    
         
             
                  Dir.chdir(build_dir) { yield }
         
     | 
| 
       245 
241 
     | 
    
         
             
                end
         
     | 
    
        data/lib/cli/release_compiler.rb
    CHANGED
    
    | 
         @@ -12,11 +12,10 @@ module Bosh::Cli 
     | 
|
| 
       12 
12 
     | 
    
         | 
| 
       13 
13 
     | 
    
         
             
                # @param [String] manifest_file Release manifest path
         
     | 
| 
       14 
14 
     | 
    
         
             
                # @param [Bosh::Blobstore::Client] blobstore Blobstore client
         
     | 
| 
       15 
     | 
    
         
            -
                # @param [Hash] remote_release Remote release info from director
         
     | 
| 
       16 
15 
     | 
    
         
             
                # @param [Array] package_matches List of package checksums that director
         
     | 
| 
       17 
16 
     | 
    
         
             
                #   can match
         
     | 
| 
       18 
17 
     | 
    
         
             
                # @param [String] release_dir Release directory
         
     | 
| 
       19 
     | 
    
         
            -
                def initialize(manifest_file, blobstore, 
     | 
| 
      
 18 
     | 
    
         
            +
                def initialize(manifest_file, blobstore,
         
     | 
| 
       20 
19 
     | 
    
         
             
                               package_matches = [], release_dir = nil)
         
     | 
| 
       21 
20 
     | 
    
         | 
| 
       22 
21 
     | 
    
         
             
                  @blobstore = blobstore
         
     | 
| 
         @@ -30,28 +29,11 @@ module Bosh::Cli 
     | 
|
| 
       30 
29 
     | 
    
         | 
| 
       31 
30 
     | 
    
         
             
                  @package_matches = Set.new(package_matches)
         
     | 
| 
       32 
31 
     | 
    
         | 
| 
       33 
     | 
    
         
            -
                  at_exit { FileUtils.rm_rf(@build_dir) }
         
     | 
| 
       34 
     | 
    
         
            -
             
     | 
| 
       35 
32 
     | 
    
         
             
                  FileUtils.mkdir_p(@jobs_dir)
         
     | 
| 
       36 
33 
     | 
    
         
             
                  FileUtils.mkdir_p(@packages_dir)
         
     | 
| 
       37 
34 
     | 
    
         | 
| 
       38 
35 
     | 
    
         
             
                  @manifest = load_yaml_file(manifest_file)
         
     | 
| 
       39 
36 
     | 
    
         | 
| 
       40 
     | 
    
         
            -
                  if remote_release
         
     | 
| 
       41 
     | 
    
         
            -
                    # TODO: instead of OpenStruct conversion we should probably
         
     | 
| 
       42 
     | 
    
         
            -
                    # introduce proper abstractions for things below
         
     | 
| 
       43 
     | 
    
         
            -
                    @remote_packages = remote_release["packages"].map do |pkg|
         
     | 
| 
       44 
     | 
    
         
            -
                      OpenStruct.new(pkg)
         
     | 
| 
       45 
     | 
    
         
            -
                    end
         
     | 
| 
       46 
     | 
    
         
            -
             
     | 
| 
       47 
     | 
    
         
            -
                    @remote_jobs = remote_release["jobs"].map do |job|
         
     | 
| 
       48 
     | 
    
         
            -
                      OpenStruct.new(job)
         
     | 
| 
       49 
     | 
    
         
            -
                    end
         
     | 
| 
       50 
     | 
    
         
            -
                  else
         
     | 
| 
       51 
     | 
    
         
            -
                    @remote_packages = []
         
     | 
| 
       52 
     | 
    
         
            -
                    @remote_jobs = []
         
     | 
| 
       53 
     | 
    
         
            -
                  end
         
     | 
| 
       54 
     | 
    
         
            -
             
     | 
| 
       55 
37 
     | 
    
         
             
                  @name = @manifest["name"]
         
     | 
| 
       56 
38 
     | 
    
         
             
                  @version = @manifest["version"]
         
     | 
| 
       57 
39 
     | 
    
         
             
                  @packages = @manifest["packages"].map { |pkg| OpenStruct.new(pkg) }
         
     | 
| 
         @@ -185,28 +167,17 @@ module Bosh::Cli 
     | 
|
| 
       185 
167 
     | 
    
         
             
                # @return [Boolean]
         
     | 
| 
       186 
168 
     | 
    
         
             
                def remote_package_exists?(local_package)
         
     | 
| 
       187 
169 
     | 
    
         
             
                  # If checksum is known to director we can always match it
         
     | 
| 
       188 
     | 
    
         
            -
                   
     | 
| 
       189 
     | 
    
         
            -
             
     | 
| 
       190 
     | 
    
         
            -
             
     | 
| 
      
 170 
     | 
    
         
            +
                  @package_matches.include?(local_package.sha1) ||
         
     | 
| 
      
 171 
     | 
    
         
            +
                    (local_package.fingerprint &&
         
     | 
| 
      
 172 
     | 
    
         
            +
                     @package_matches.include?(local_package.fingerprint))
         
     | 
| 
       191 
173 
     | 
    
         
             
                end
         
     | 
| 
       192 
174 
     | 
    
         | 
| 
       193 
175 
     | 
    
         
             
                # Checks if local job is already known remotely
         
     | 
| 
       194 
176 
     | 
    
         
             
                # @param [#name, #version] local_job
         
     | 
| 
       195 
177 
     | 
    
         
             
                # @return [Boolean]
         
     | 
| 
       196 
178 
     | 
    
         
             
                def remote_job_exists?(local_job)
         
     | 
| 
       197 
     | 
    
         
            -
                   
     | 
| 
       198 
     | 
    
         
            -
                end
         
     | 
| 
       199 
     | 
    
         
            -
             
     | 
| 
       200 
     | 
    
         
            -
                # @param [Enumerable] remote_objects Remote object collection
         
     | 
| 
       201 
     | 
    
         
            -
                # @param [#name, #version] local_object
         
     | 
| 
       202 
     | 
    
         
            -
                # @return [Boolean]
         
     | 
| 
       203 
     | 
    
         
            -
                def remote_object_exists?(remote_objects, local_object)
         
     | 
| 
       204 
     | 
    
         
            -
                  remote_objects.any? do |remote_object|
         
     | 
| 
       205 
     | 
    
         
            -
                    remote_object.name == local_object.name &&
         
     | 
| 
       206 
     | 
    
         
            -
                      remote_object.version.to_s == local_object.version.to_s
         
     | 
| 
       207 
     | 
    
         
            -
                  end
         
     | 
| 
      
 179 
     | 
    
         
            +
                  false
         
     | 
| 
       208 
180 
     | 
    
         
             
                end
         
     | 
| 
       209 
     | 
    
         
            -
             
     | 
| 
       210 
181 
     | 
    
         
             
              end
         
     | 
| 
       211 
182 
     | 
    
         | 
| 
       212 
183 
     | 
    
         
             
            end
         
     | 
    
        data/lib/cli/release_tarball.rb
    CHANGED
    
    | 
         @@ -32,25 +32,17 @@ module Bosh::Cli 
     | 
|
| 
       32 
32 
     | 
    
         | 
| 
       33 
33 
     | 
    
         
             
                # Repacks tarball according to the structure of remote release
         
     | 
| 
       34 
34 
     | 
    
         
             
                # Return path to repackaged tarball or nil if repack has failed
         
     | 
| 
       35 
     | 
    
         
            -
                def repack( 
     | 
| 
      
 35 
     | 
    
         
            +
                def repack(package_matches = [])
         
     | 
| 
       36 
36 
     | 
    
         
             
                  return nil unless valid?
         
     | 
| 
       37 
37 
     | 
    
         
             
                  unpack
         
     | 
| 
       38 
38 
     | 
    
         | 
| 
       39 
39 
     | 
    
         
             
                  tmpdir = Dir.mktmpdir
         
     | 
| 
       40 
40 
     | 
    
         
             
                  repacked_path = File.join(tmpdir, "release-repack.tgz")
         
     | 
| 
       41 
41 
     | 
    
         | 
| 
       42 
     | 
    
         
            -
                  at_exit { FileUtils.rm_rf(tmpdir) }
         
     | 
| 
       43 
     | 
    
         
            -
             
     | 
| 
       44 
42 
     | 
    
         
             
                  manifest = load_yaml_file(File.join(@unpack_dir, "release.MF"))
         
     | 
| 
       45 
43 
     | 
    
         | 
| 
       46 
     | 
    
         
            -
                  # Remote release could be not-existent, then package matches are supposed
         
     | 
| 
       47 
     | 
    
         
            -
                  # to satisfy everything
         
     | 
| 
       48 
     | 
    
         
            -
                  remote_release ||= {"jobs" => [], "packages" => []}
         
     | 
| 
       49 
     | 
    
         
            -
             
     | 
| 
       50 
44 
     | 
    
         
             
                  local_packages = manifest["packages"]
         
     | 
| 
       51 
45 
     | 
    
         
             
                  local_jobs = manifest["jobs"]
         
     | 
| 
       52 
     | 
    
         
            -
                  remote_packages = remote_release["packages"]
         
     | 
| 
       53 
     | 
    
         
            -
                  remote_jobs = remote_release["jobs"]
         
     | 
| 
       54 
46 
     | 
    
         | 
| 
       55 
47 
     | 
    
         
             
                  @skipped = 0
         
     | 
| 
       56 
48 
     | 
    
         | 
| 
         @@ -61,8 +53,8 @@ module Bosh::Cli 
     | 
|
| 
       61 
53 
     | 
    
         
             
                    local_packages.each do |package|
         
     | 
| 
       62 
54 
     | 
    
         
             
                      say("#{package["name"]} (#{package["version"]})".ljust(30), " ")
         
     | 
| 
       63 
55 
     | 
    
         
             
                      if package_matches.include?(package["sha1"]) ||
         
     | 
| 
       64 
     | 
    
         
            -
             
     | 
| 
       65 
     | 
    
         
            -
                          package[" 
     | 
| 
      
 56 
     | 
    
         
            +
                         (package["fingerprint"] &&
         
     | 
| 
      
 57 
     | 
    
         
            +
                          package_matches.include?(package["fingerprint"]))
         
     | 
| 
       66 
58 
     | 
    
         
             
                        say("SKIP".green)
         
     | 
| 
       67 
59 
     | 
    
         
             
                        @skipped += 1
         
     | 
| 
       68 
60 
     | 
    
         
             
                        FileUtils.rm_rf(File.join("packages", "#{package["name"]}.tgz"))
         
     | 
| 
         @@ -73,14 +65,7 @@ module Bosh::Cli 
     | 
|
| 
       73 
65 
     | 
    
         | 
| 
       74 
66 
     | 
    
         
             
                    local_jobs.each do |job|
         
     | 
| 
       75 
67 
     | 
    
         
             
                      say("#{job["name"]} (#{job["version"]})".ljust(30), " ")
         
     | 
| 
       76 
     | 
    
         
            -
                       
     | 
| 
       77 
     | 
    
         
            -
                          job["version"].to_s == rj["version"].to_s }
         
     | 
| 
       78 
     | 
    
         
            -
                        say("SKIP".green)
         
     | 
| 
       79 
     | 
    
         
            -
                        @skipped += 1
         
     | 
| 
       80 
     | 
    
         
            -
                        FileUtils.rm_rf(File.join("jobs", "#{job["name"]}.tgz"))
         
     | 
| 
       81 
     | 
    
         
            -
                      else
         
     | 
| 
       82 
     | 
    
         
            -
                        say("UPLOAD".red)
         
     | 
| 
       83 
     | 
    
         
            -
                      end
         
     | 
| 
      
 68 
     | 
    
         
            +
                      say("UPLOAD".red)
         
     | 
| 
       84 
69 
     | 
    
         
             
                    end
         
     | 
| 
       85 
70 
     | 
    
         | 
| 
       86 
71 
     | 
    
         
             
                    return nil if @skipped == 0
         
     | 
    
        data/lib/cli/runner.rb
    CHANGED
    
    | 
         @@ -6,667 +6,186 @@ module Bosh::Cli 
     | 
|
| 
       6 
6 
     | 
    
         
             
              end
         
     | 
| 
       7 
7 
     | 
    
         | 
| 
       8 
8 
     | 
    
         
             
              class Runner
         
     | 
| 
       9 
     | 
    
         
            -
                COMMANDS = { }
         
     | 
| 
       10 
     | 
    
         
            -
                ALL_KEYWORDS = []
         
     | 
| 
       11 
9 
     | 
    
         | 
| 
       12 
     | 
    
         
            -
                 
     | 
| 
       13 
     | 
    
         
            -
                attr_reader :namespace
         
     | 
| 
       14 
     | 
    
         
            -
                attr_reader :action
         
     | 
| 
      
 10 
     | 
    
         
            +
                # @return [Array]
         
     | 
| 
       15 
11 
     | 
    
         
             
                attr_reader :args
         
     | 
| 
       16 
     | 
    
         
            -
                attr_reader :options
         
     | 
| 
       17 
12 
     | 
    
         | 
| 
       18 
     | 
    
         
            -
                #  
     | 
| 
       19 
     | 
    
         
            -
                 
     | 
| 
       20 
     | 
    
         
            -
                # @return [Bosh::Cli::Command::<type>] Instance of the command instance.
         
     | 
| 
       21 
     | 
    
         
            -
                attr_accessor :runner
         
     | 
| 
      
 13 
     | 
    
         
            +
                # @return [Hash]
         
     | 
| 
      
 14 
     | 
    
         
            +
                attr_reader :options
         
     | 
| 
       22 
15 
     | 
    
         | 
| 
      
 16 
     | 
    
         
            +
                # @param [Array] args
         
     | 
| 
       23 
17 
     | 
    
         
             
                def self.run(args)
         
     | 
| 
       24 
18 
     | 
    
         
             
                  new(args).run
         
     | 
| 
       25 
19 
     | 
    
         
             
                end
         
     | 
| 
       26 
20 
     | 
    
         | 
| 
       27 
     | 
    
         
            -
                 
     | 
| 
      
 21 
     | 
    
         
            +
                # @param [Array] args
         
     | 
| 
      
 22 
     | 
    
         
            +
                def initialize(args, options = {})
         
     | 
| 
       28 
23 
     | 
    
         
             
                  @args = args
         
     | 
| 
       29 
     | 
    
         
            -
                  @options =  
     | 
| 
       30 
     | 
    
         
            -
                    :director_checks => true,
         
     | 
| 
       31 
     | 
    
         
            -
                    :colorize => true,
         
     | 
| 
       32 
     | 
    
         
            -
                  }
         
     | 
| 
       33 
     | 
    
         
            -
                end
         
     | 
| 
      
 24 
     | 
    
         
            +
                  @options = options.dup
         
     | 
| 
       34 
25 
     | 
    
         | 
| 
       35 
     | 
    
         
            -
             
     | 
| 
       36 
     | 
    
         
            -
                   
     | 
| 
       37 
     | 
    
         
            -
                  parse_options!
         
     | 
| 
       38 
     | 
    
         
            -
                  Config.output ||= STDOUT unless @options[:quiet]
         
     | 
| 
       39 
     | 
    
         
            -
                  Config.interactive = !@options[:non_interactive]
         
     | 
| 
       40 
     | 
    
         
            -
                  Config.colorize = @options.delete(:colorize)
         
     | 
| 
       41 
     | 
    
         
            -
                  Config.cache = Bosh::Cli::Cache.new(@options[:cache_dir] ||
         
     | 
| 
       42 
     | 
    
         
            -
                                                        Bosh::Cli::DEFAULT_CACHE_DIR)
         
     | 
| 
      
 26 
     | 
    
         
            +
                  banner = "Usage: bosh [<options>] <command> [<args>]"
         
     | 
| 
      
 27 
     | 
    
         
            +
                  @option_parser = OptionParser.new(banner)
         
     | 
| 
       43 
28 
     | 
    
         | 
| 
       44 
     | 
    
         
            -
                   
     | 
| 
       45 
     | 
    
         
            -
                   
     | 
| 
       46 
     | 
    
         
            -
                  add_shortcuts
         
     | 
| 
      
 29 
     | 
    
         
            +
                  Config.colorize = true
         
     | 
| 
      
 30 
     | 
    
         
            +
                  Config.output ||= STDOUT
         
     | 
| 
       47 
31 
     | 
    
         
             
                end
         
     | 
| 
       48 
32 
     | 
    
         | 
| 
      
 33 
     | 
    
         
            +
                # Find and run CLI command
         
     | 
| 
      
 34 
     | 
    
         
            +
                # @return [void]
         
     | 
| 
       49 
35 
     | 
    
         
             
                def run
         
     | 
| 
       50 
     | 
    
         
            -
                   
     | 
| 
       51 
     | 
    
         
            -
                  dispatch unless @namespace && @action
         
     | 
| 
       52 
     | 
    
         
            -
             
     | 
| 
       53 
     | 
    
         
            -
                  if @namespace && @action
         
     | 
| 
       54 
     | 
    
         
            -
                    ns_class_name = @namespace.to_s.gsub(/(?:_|^)(.)/) { $1.upcase }
         
     | 
| 
       55 
     | 
    
         
            -
                    klass = eval("Bosh::Cli::Command::#{ns_class_name}")
         
     | 
| 
       56 
     | 
    
         
            -
                    runner = klass.new(@options)
         
     | 
| 
       57 
     | 
    
         
            -
                    runner.usage = @usage
         
     | 
| 
      
 36 
     | 
    
         
            +
                  parse_global_options
         
     | 
| 
       58 
37 
     | 
    
         | 
| 
       59 
     | 
    
         
            -
             
     | 
| 
       60 
     | 
    
         
            -
             
     | 
| 
      
 38 
     | 
    
         
            +
                  Config.interactive = !@options[:non_interactive]
         
     | 
| 
      
 39 
     | 
    
         
            +
                  Config.cache = Bosh::Cli::Cache.new(@options[:cache_dir])
         
     | 
| 
       61 
40 
     | 
    
         | 
| 
       62 
     | 
    
         
            -
             
     | 
| 
       63 
     | 
    
         
            -
             
     | 
| 
       64 
     | 
    
         
            -
             
     | 
| 
       65 
     | 
    
         
            -
                    if action_arity >= 0 && n_required_args < @args.size
         
     | 
| 
       66 
     | 
    
         
            -
                      err("Too many arguments, correct usage is: bosh #{@usage}")
         
     | 
| 
       67 
     | 
    
         
            -
                    end
         
     | 
| 
      
 41 
     | 
    
         
            +
                  build_parse_tree
         
     | 
| 
      
 42 
     | 
    
         
            +
                  load_plugins
         
     | 
| 
      
 43 
     | 
    
         
            +
                  add_shortcuts
         
     | 
| 
       68 
44 
     | 
    
         | 
| 
       69 
     | 
    
         
            -
             
     | 
| 
       70 
     | 
    
         
            -
                     
     | 
| 
       71 
     | 
    
         
            -
                  elsif @args.empty? || @args == %w(help)
         
     | 
| 
       72 
     | 
    
         
            -
                    say(help_message)
         
     | 
| 
       73 
     | 
    
         
            -
                    say(plugin_help_message) if @plugins
         
     | 
| 
       74 
     | 
    
         
            -
                  elsif @args[0] == "complete"
         
     | 
| 
       75 
     | 
    
         
            -
                    unless ENV.has_key?('COMP_LINE')
         
     | 
| 
       76 
     | 
    
         
            -
                      $stderr.puts "COMP_LINE must be set when calling bosh complete"
         
     | 
| 
       77 
     | 
    
         
            -
                      exit(1)
         
     | 
| 
       78 
     | 
    
         
            -
                    end
         
     | 
| 
       79 
     | 
    
         
            -
                    line = ENV['COMP_LINE'].gsub(/^\S*bosh\s*/, '')
         
     | 
| 
       80 
     | 
    
         
            -
                    puts complete(line).join("\n")
         
     | 
| 
      
 45 
     | 
    
         
            +
                  if @args.empty?
         
     | 
| 
      
 46 
     | 
    
         
            +
                    say(usage)
         
     | 
| 
       81 
47 
     | 
    
         
             
                    exit(0)
         
     | 
| 
       82 
     | 
    
         
            -
                   
     | 
| 
       83 
     | 
    
         
            -
                    cmd_args = @args[1..-1]
         
     | 
| 
       84 
     | 
    
         
            -
                    suggestions = command_suggestions(cmd_args).map do |cmd|
         
     | 
| 
       85 
     | 
    
         
            -
                      command_usage(cmd, 0)
         
     | 
| 
       86 
     | 
    
         
            -
                    end
         
     | 
| 
       87 
     | 
    
         
            -
                    if suggestions.empty?
         
     | 
| 
       88 
     | 
    
         
            -
                      unknown_command(cmd_args.join(" "))
         
     | 
| 
       89 
     | 
    
         
            -
                    else
         
     | 
| 
       90 
     | 
    
         
            -
                      say(suggestions.uniq.join("\n"))
         
     | 
| 
       91 
     | 
    
         
            -
                    end
         
     | 
| 
       92 
     | 
    
         
            -
                  else
         
     | 
| 
       93 
     | 
    
         
            -
                    unknown_command(@args.join(" "))
         
     | 
| 
      
 48 
     | 
    
         
            +
                  end
         
     | 
| 
       94 
49 
     | 
    
         | 
| 
       95 
     | 
    
         
            -
             
     | 
| 
       96 
     | 
    
         
            -
             
     | 
| 
       97 
     | 
    
         
            -
                     
     | 
| 
      
 50 
     | 
    
         
            +
                  command = search_parse_tree(@parse_tree)
         
     | 
| 
      
 51 
     | 
    
         
            +
                  if command.nil? && Config.interactive
         
     | 
| 
      
 52 
     | 
    
         
            +
                    command = try_alias
         
     | 
| 
      
 53 
     | 
    
         
            +
                  end
         
     | 
| 
      
 54 
     | 
    
         
            +
             
     | 
| 
      
 55 
     | 
    
         
            +
                  if command.nil?
         
     | 
| 
      
 56 
     | 
    
         
            +
                    err("Unknown command: #{@args.join(" ")}")
         
     | 
| 
      
 57 
     | 
    
         
            +
                  end
         
     | 
| 
       98 
58 
     | 
    
         | 
| 
       99 
     | 
    
         
            -
             
     | 
| 
       100 
     | 
    
         
            -
             
     | 
| 
       101 
     | 
    
         
            -
             
     | 
| 
      
 59 
     | 
    
         
            +
                  command.runner = self
         
     | 
| 
      
 60 
     | 
    
         
            +
                  begin
         
     | 
| 
      
 61 
     | 
    
         
            +
                    exit_code = command.run(@args, @options)
         
     | 
| 
      
 62 
     | 
    
         
            +
                    exit(exit_code)
         
     | 
| 
      
 63 
     | 
    
         
            +
                  rescue OptionParser::ParseError => e
         
     | 
| 
      
 64 
     | 
    
         
            +
                    say(e.message.red)
         
     | 
| 
      
 65 
     | 
    
         
            +
                    say("Usage: bosh #{command.usage_with_params.columnize(60, 7)}")
         
     | 
| 
      
 66 
     | 
    
         
            +
                    if command.has_options?
         
     | 
| 
      
 67 
     | 
    
         
            +
                      say(command.options_summary.indent(7))
         
     | 
| 
       102 
68 
     | 
    
         
             
                    end
         
     | 
| 
       103 
     | 
    
         
            -
                    exit(1)
         
     | 
| 
       104 
69 
     | 
    
         
             
                  end
         
     | 
| 
       105 
70 
     | 
    
         | 
| 
       106 
     | 
    
         
            -
                rescue OptionParser:: 
     | 
| 
       107 
     | 
    
         
            -
                  say(e.message.red + "\n" + basic_usage)
         
     | 
| 
       108 
     | 
    
         
            -
                  exit(1)
         
     | 
| 
       109 
     | 
    
         
            -
                rescue Bosh::Cli::GracefulExit => e
         
     | 
| 
       110 
     | 
    
         
            -
                  # Redirected bosh commands end up
         
     | 
| 
       111 
     | 
    
         
            -
                  # generating this exception (kind of goto)
         
     | 
| 
       112 
     | 
    
         
            -
                rescue Bosh::Cli::CliExit, Bosh::Cli::DirectorError => e
         
     | 
| 
      
 71 
     | 
    
         
            +
                rescue OptionParser::ParseError => e
         
     | 
| 
       113 
72 
     | 
    
         
             
                  say(e.message.red)
         
     | 
| 
       114 
     | 
    
         
            -
                   
     | 
| 
      
 73 
     | 
    
         
            +
                  say(@option_parser.to_s)
         
     | 
| 
      
 74 
     | 
    
         
            +
                  exit(1)
         
     | 
| 
       115 
75 
     | 
    
         
             
                rescue Bosh::Cli::CliError => e
         
     | 
| 
       116 
     | 
    
         
            -
                  say( 
     | 
| 
      
 76 
     | 
    
         
            +
                  say(e.message.red)
         
     | 
| 
       117 
77 
     | 
    
         
             
                  exit(e.exit_code)
         
     | 
| 
       118 
     | 
    
         
            -
                rescue => e
         
     | 
| 
       119 
     | 
    
         
            -
                  if @options[:debug]
         
     | 
| 
       120 
     | 
    
         
            -
                    raise e
         
     | 
| 
       121 
     | 
    
         
            -
                  else
         
     | 
| 
       122 
     | 
    
         
            -
                    save_exception(e)
         
     | 
| 
       123 
     | 
    
         
            -
                    exit(1)
         
     | 
| 
       124 
     | 
    
         
            -
                  end
         
     | 
| 
       125 
78 
     | 
    
         
             
                end
         
     | 
| 
       126 
79 
     | 
    
         | 
| 
       127 
     | 
    
         
            -
                #  
     | 
| 
       128 
     | 
    
         
            -
                 
     | 
| 
      
 80 
     | 
    
         
            +
                # Finds command completions in the parse tree
         
     | 
| 
      
 81 
     | 
    
         
            +
                # @param [Array] words Completion prefix
         
     | 
| 
      
 82 
     | 
    
         
            +
                # @param [Bosh::Cli::ParseTreeNode] node Current parse tree node
         
     | 
| 
      
 83 
     | 
    
         
            +
                def find_completions(words, node = @parse_tree, index = 0)
         
     | 
| 
       129 
84 
     | 
    
         
             
                  word = words[index]
         
     | 
| 
       130 
85 
     | 
    
         | 
| 
       131 
86 
     | 
    
         
             
                  # exact match and not on the last word
         
     | 
| 
       132 
87 
     | 
    
         
             
                  if node[word] && words.length != index
         
     | 
| 
       133 
     | 
    
         
            -
                     
     | 
| 
      
 88 
     | 
    
         
            +
                    find_completions(words, node[word], index + 1)
         
     | 
| 
       134 
89 
     | 
    
         | 
| 
       135 
     | 
    
         
            -
             
     | 
| 
      
 90 
     | 
    
         
            +
                    # exact match at the last word
         
     | 
| 
       136 
91 
     | 
    
         
             
                  elsif node[word]
         
     | 
| 
       137 
92 
     | 
    
         
             
                    node[word].values
         
     | 
| 
       138 
93 
     | 
    
         | 
| 
       139 
     | 
    
         
            -
             
     | 
| 
      
 94 
     | 
    
         
            +
                    # find all partial matches
         
     | 
| 
       140 
95 
     | 
    
         
             
                  else
         
     | 
| 
       141 
96 
     | 
    
         
             
                    node.keys.grep(/^#{word}/)
         
     | 
| 
       142 
97 
     | 
    
         
             
                  end
         
     | 
| 
       143 
98 
     | 
    
         
             
                end
         
     | 
| 
       144 
99 
     | 
    
         | 
| 
       145 
     | 
    
         
            -
                 
     | 
| 
       146 
     | 
    
         
            -
             
     | 
| 
       147 
     | 
    
         
            -
             
     | 
| 
       148 
     | 
    
         
            -
             
     | 
| 
       149 
     | 
    
         
            -
             
     | 
| 
       150 
     | 
    
         
            -
             
     | 
| 
       151 
     | 
    
         
            -
                  parse_tree_completion(@parse_tree, words, 0)
         
     | 
| 
       152 
     | 
    
         
            -
                end
         
     | 
| 
       153 
     | 
    
         
            -
             
     | 
| 
       154 
     | 
    
         
            -
                def command(name, &block)
         
     | 
| 
       155 
     | 
    
         
            -
                  cmd_def = CommandDefinition.new
         
     | 
| 
       156 
     | 
    
         
            -
                  cmd_def.instance_eval(&block)
         
     | 
| 
       157 
     | 
    
         
            -
                  COMMANDS[name] = cmd_def
         
     | 
| 
       158 
     | 
    
         
            -
                  ALL_KEYWORDS.push(*cmd_def.keywords)
         
     | 
| 
       159 
     | 
    
         
            -
                end
         
     | 
| 
       160 
     | 
    
         
            -
             
     | 
| 
       161 
     | 
    
         
            -
                def find_command(name)
         
     | 
| 
       162 
     | 
    
         
            -
                  COMMANDS[name] || raise("Unknown command definition: #{name}")
         
     | 
| 
       163 
     | 
    
         
            -
                end
         
     | 
| 
       164 
     | 
    
         
            -
             
     | 
| 
       165 
     | 
    
         
            -
                def dispatch(command = nil)
         
     | 
| 
       166 
     | 
    
         
            -
                  command ||= search_parse_tree(@parse_tree)
         
     | 
| 
       167 
     | 
    
         
            -
                  command = try_alias if command.nil? && Config.interactive
         
     | 
| 
       168 
     | 
    
         
            -
                  return if command.nil?
         
     | 
| 
       169 
     | 
    
         
            -
                  @usage = command.usage
         
     | 
| 
       170 
     | 
    
         
            -
             
     | 
| 
       171 
     | 
    
         
            -
                  case command.route
         
     | 
| 
       172 
     | 
    
         
            -
                    when Array
         
     | 
| 
       173 
     | 
    
         
            -
                      @namespace, @action = command.route
         
     | 
| 
       174 
     | 
    
         
            -
                    when Proc
         
     | 
| 
       175 
     | 
    
         
            -
                      @namespace, @action = command.route.call(@args)
         
     | 
| 
       176 
     | 
    
         
            -
                    else
         
     | 
| 
       177 
     | 
    
         
            -
                      raise "Command definition is invalid, " +
         
     | 
| 
       178 
     | 
    
         
            -
                                "route should be an Array or Proc"
         
     | 
| 
       179 
     | 
    
         
            -
                  end
         
     | 
| 
       180 
     | 
    
         
            -
                end
         
     | 
| 
       181 
     | 
    
         
            -
             
     | 
| 
       182 
     | 
    
         
            -
                def define_commands
         
     | 
| 
       183 
     | 
    
         
            -
                  command :version do
         
     | 
| 
       184 
     | 
    
         
            -
                    usage "version"
         
     | 
| 
       185 
     | 
    
         
            -
                    desc  "Show version"
         
     | 
| 
       186 
     | 
    
         
            -
                    route :misc, :version
         
     | 
| 
       187 
     | 
    
         
            -
                  end
         
     | 
| 
       188 
     | 
    
         
            -
             
     | 
| 
       189 
     | 
    
         
            -
                  command :alias do
         
     | 
| 
       190 
     | 
    
         
            -
                    usage "alias <name> <command>"
         
     | 
| 
       191 
     | 
    
         
            -
                    desc  "Create an alias <name> for command <command>"
         
     | 
| 
       192 
     | 
    
         
            -
                    route :misc, :set_alias
         
     | 
| 
       193 
     | 
    
         
            -
                  end
         
     | 
| 
       194 
     | 
    
         
            -
             
     | 
| 
       195 
     | 
    
         
            -
                  command :list_aliases do
         
     | 
| 
       196 
     | 
    
         
            -
                    usage "aliases"
         
     | 
| 
       197 
     | 
    
         
            -
                    desc  "Show the list of available command aliases"
         
     | 
| 
       198 
     | 
    
         
            -
                    route :misc, :list_aliases
         
     | 
| 
       199 
     | 
    
         
            -
                  end
         
     | 
| 
       200 
     | 
    
         
            -
             
     | 
| 
       201 
     | 
    
         
            -
                  command :target do
         
     | 
| 
       202 
     | 
    
         
            -
                    usage "target [<name>] [<alias>]"
         
     | 
| 
       203 
     | 
    
         
            -
                    desc  "Choose director to talk to (optionally creating an alias). " +
         
     | 
| 
       204 
     | 
    
         
            -
                              "If no arguments given, show currently targeted director"
         
     | 
| 
       205 
     | 
    
         
            -
                    route do |args|
         
     | 
| 
       206 
     | 
    
         
            -
                      (args.size > 0) ? [:misc, :set_target] : [:misc, :show_target]
         
     | 
| 
       207 
     | 
    
         
            -
                    end
         
     | 
| 
       208 
     | 
    
         
            -
                  end
         
     | 
| 
       209 
     | 
    
         
            -
             
     | 
| 
       210 
     | 
    
         
            -
                  command :list_targets do
         
     | 
| 
       211 
     | 
    
         
            -
                    usage "targets"
         
     | 
| 
       212 
     | 
    
         
            -
                    desc  "Show the list of available targets"
         
     | 
| 
       213 
     | 
    
         
            -
                    route :misc, :list_targets
         
     | 
| 
       214 
     | 
    
         
            -
                  end
         
     | 
| 
       215 
     | 
    
         
            -
             
     | 
| 
       216 
     | 
    
         
            -
                  command :deployment do
         
     | 
| 
       217 
     | 
    
         
            -
                    usage "deployment [<name>]"
         
     | 
| 
       218 
     | 
    
         
            -
                    desc  "Choose deployment to work with " +
         
     | 
| 
       219 
     | 
    
         
            -
                              "(it also updates current target)"
         
     | 
| 
       220 
     | 
    
         
            -
                    route do |args|
         
     | 
| 
       221 
     | 
    
         
            -
                      if args.size > 0
         
     | 
| 
       222 
     | 
    
         
            -
                        [:deployment, :set_current]
         
     | 
| 
       223 
     | 
    
         
            -
                      else
         
     | 
| 
       224 
     | 
    
         
            -
                        [:deployment, :show_current]
         
     | 
| 
       225 
     | 
    
         
            -
                      end
         
     | 
| 
       226 
     | 
    
         
            -
                    end
         
     | 
| 
       227 
     | 
    
         
            -
                  end
         
     | 
| 
       228 
     | 
    
         
            -
             
     | 
| 
       229 
     | 
    
         
            -
                  command :deploy do
         
     | 
| 
       230 
     | 
    
         
            -
                    usage  "deploy"
         
     | 
| 
       231 
     | 
    
         
            -
                    desc   "Deploy according to the currently selected " +
         
     | 
| 
       232 
     | 
    
         
            -
                               "deployment manifest"
         
     | 
| 
       233 
     | 
    
         
            -
                    option "--recreate", "recreate all VMs in deployment"
         
     | 
| 
       234 
     | 
    
         
            -
                    route  :deployment, :perform
         
     | 
| 
       235 
     | 
    
         
            -
                  end
         
     | 
| 
       236 
     | 
    
         
            -
             
     | 
| 
       237 
     | 
    
         
            -
                  command :edit_deployment do
         
     | 
| 
       238 
     | 
    
         
            -
                    usage  "edit deployment"
         
     | 
| 
       239 
     | 
    
         
            -
                    desc   "Edit current deployment manifest"
         
     | 
| 
       240 
     | 
    
         
            -
                    route  :deployment, :edit
         
     | 
| 
       241 
     | 
    
         
            -
                  end
         
     | 
| 
       242 
     | 
    
         
            -
             
     | 
| 
       243 
     | 
    
         
            -
                  command :ssh do
         
     | 
| 
       244 
     | 
    
         
            -
                    usage "ssh <job> [index] [<options>] [command]"
         
     | 
| 
       245 
     | 
    
         
            -
                    desc  "Given a job, execute the given command or " +
         
     | 
| 
       246 
     | 
    
         
            -
                          "start an interactive session"
         
     | 
| 
       247 
     | 
    
         
            -
                    option "--public_key <file>"
         
     | 
| 
       248 
     | 
    
         
            -
                    option "--gateway_host <host>"
         
     | 
| 
       249 
     | 
    
         
            -
                    option "--gateway_user <user>"
         
     | 
| 
       250 
     | 
    
         
            -
                    option "--default_password", "Use default ssh password. Not recommended."
         
     | 
| 
       251 
     | 
    
         
            -
                    route :ssh, :shell
         
     | 
| 
       252 
     | 
    
         
            -
                  end
         
     | 
| 
       253 
     | 
    
         
            -
             
     | 
| 
       254 
     | 
    
         
            -
                  command :ssh_cleanup do
         
     | 
| 
       255 
     | 
    
         
            -
                    usage "ssh_cleanup <job> [index]"
         
     | 
| 
       256 
     | 
    
         
            -
                    desc  "Cleanup SSH artifacts"
         
     | 
| 
       257 
     | 
    
         
            -
                    route :ssh, :cleanup
         
     | 
| 
       258 
     | 
    
         
            -
                  end
         
     | 
| 
       259 
     | 
    
         
            -
             
     | 
| 
       260 
     | 
    
         
            -
                  command :scp do
         
     | 
| 
       261 
     | 
    
         
            -
                    usage "scp <job> [index] (--upload|--download) [options]" +
         
     | 
| 
       262 
     | 
    
         
            -
                      "/path/to/source /path/to/destination"
         
     | 
| 
       263 
     | 
    
         
            -
                    desc  "upload/download the source file to the given job. " +
         
     | 
| 
       264 
     | 
    
         
            -
                      "Note: for dowload /path/to/destination is a directory"
         
     | 
| 
       265 
     | 
    
         
            -
                    option "--public_key <file>"
         
     | 
| 
       266 
     | 
    
         
            -
                    option "--gateway_host <host>"
         
     | 
| 
       267 
     | 
    
         
            -
                    option "--gateway_user <user>"
         
     | 
| 
       268 
     | 
    
         
            -
                    route :ssh, :scp
         
     | 
| 
       269 
     | 
    
         
            -
                  end
         
     | 
| 
       270 
     | 
    
         
            -
             
     | 
| 
       271 
     | 
    
         
            -
                  command :scp do
         
     | 
| 
       272 
     | 
    
         
            -
                    usage "scp <job> <--upload | --download> [options] " +
         
     | 
| 
       273 
     | 
    
         
            -
                              "/path/to/source /path/to/destination"
         
     | 
| 
       274 
     | 
    
         
            -
                    desc  "upload/download the source file to the given job. " +
         
     | 
| 
       275 
     | 
    
         
            -
                              "Note: for download /path/to/destination is a directory"
         
     | 
| 
       276 
     | 
    
         
            -
                    option "--index <job_index>"
         
     | 
| 
       277 
     | 
    
         
            -
                    option "--public_key <file>"
         
     | 
| 
       278 
     | 
    
         
            -
                    option "--gateway_host <host>"
         
     | 
| 
       279 
     | 
    
         
            -
                    option "--gateway_user <user>"
         
     | 
| 
       280 
     | 
    
         
            -
                    route :ssh, :scp
         
     | 
| 
       281 
     | 
    
         
            -
                  end
         
     | 
| 
       282 
     | 
    
         
            -
             
     | 
| 
       283 
     | 
    
         
            -
                  command :status do
         
     | 
| 
       284 
     | 
    
         
            -
                    usage "status"
         
     | 
| 
       285 
     | 
    
         
            -
                    desc  "Show current status (current target, " +
         
     | 
| 
       286 
     | 
    
         
            -
                              "user, deployment info etc.)"
         
     | 
| 
       287 
     | 
    
         
            -
                    route :misc, :status
         
     | 
| 
       288 
     | 
    
         
            -
                  end
         
     | 
| 
       289 
     | 
    
         
            -
             
     | 
| 
       290 
     | 
    
         
            -
                  command :login do
         
     | 
| 
       291 
     | 
    
         
            -
                    usage "login [<name>] [<password>]"
         
     | 
| 
       292 
     | 
    
         
            -
                    desc  "Provide credentials for the subsequent interactions " +
         
     | 
| 
       293 
     | 
    
         
            -
                              "with targeted director"
         
     | 
| 
       294 
     | 
    
         
            -
                    route :misc, :login
         
     | 
| 
       295 
     | 
    
         
            -
                  end
         
     | 
| 
       296 
     | 
    
         
            -
             
     | 
| 
       297 
     | 
    
         
            -
                  command :logout do
         
     | 
| 
       298 
     | 
    
         
            -
                    usage "logout"
         
     | 
| 
       299 
     | 
    
         
            -
                    desc  "Forget saved credentials for targeted director"
         
     | 
| 
       300 
     | 
    
         
            -
                    route :misc, :logout
         
     | 
| 
       301 
     | 
    
         
            -
                  end
         
     | 
| 
       302 
     | 
    
         
            -
             
     | 
| 
       303 
     | 
    
         
            -
                  command :purge do
         
     | 
| 
       304 
     | 
    
         
            -
                    usage "purge"
         
     | 
| 
       305 
     | 
    
         
            -
                    desc  "Purge local manifest cache"
         
     | 
| 
       306 
     | 
    
         
            -
                    route :misc, :purge_cache
         
     | 
| 
       307 
     | 
    
         
            -
                  end
         
     | 
| 
       308 
     | 
    
         
            -
             
     | 
| 
       309 
     | 
    
         
            -
                  command :create_release do
         
     | 
| 
       310 
     | 
    
         
            -
                    usage  "create release"
         
     | 
| 
       311 
     | 
    
         
            -
                    desc   "Create release (assumes current directory " +
         
     | 
| 
       312 
     | 
    
         
            -
                               "to be a release repository)"
         
     | 
| 
       313 
     | 
    
         
            -
                    route  :release, :create
         
     | 
| 
       314 
     | 
    
         
            -
                    option "--force", "bypass git dirty state check"
         
     | 
| 
       315 
     | 
    
         
            -
                    option "--final", "create production-ready release " +
         
     | 
| 
       316 
     | 
    
         
            -
                        "(stores artefacts in blobstore, bumps final version)"
         
     | 
| 
       317 
     | 
    
         
            -
                    option "--with-tarball", "create full release tarball" +
         
     | 
| 
       318 
     | 
    
         
            -
                        "(by default only manifest is created)"
         
     | 
| 
       319 
     | 
    
         
            -
                    option "--dry-run", "stop before writing release " +
         
     | 
| 
       320 
     | 
    
         
            -
                        "manifest (for diagnostics)"
         
     | 
| 
       321 
     | 
    
         
            -
                  end
         
     | 
| 
       322 
     | 
    
         
            -
             
     | 
| 
       323 
     | 
    
         
            -
                  command :create_user do
         
     | 
| 
       324 
     | 
    
         
            -
                    usage "create user [<name>] [<password>]"
         
     | 
| 
       325 
     | 
    
         
            -
                    desc  "Create user"
         
     | 
| 
       326 
     | 
    
         
            -
                    route :user, :create
         
     | 
| 
       327 
     | 
    
         
            -
                  end
         
     | 
| 
       328 
     | 
    
         
            -
             
     | 
| 
       329 
     | 
    
         
            -
                  command :create_package do
         
     | 
| 
       330 
     | 
    
         
            -
                    usage "create package <name>|<path>"
         
     | 
| 
       331 
     | 
    
         
            -
                    desc  "Build a single package"
         
     | 
| 
       332 
     | 
    
         
            -
                    route :package, :create
         
     | 
| 
       333 
     | 
    
         
            -
                  end
         
     | 
| 
       334 
     | 
    
         
            -
             
     | 
| 
       335 
     | 
    
         
            -
                  command :start_job do
         
     | 
| 
       336 
     | 
    
         
            -
                    usage  "start <job> [<index>]"
         
     | 
| 
       337 
     | 
    
         
            -
                    desc   "Start job/instance"
         
     | 
| 
       338 
     | 
    
         
            -
                    route  :job_management, :start_job
         
     | 
| 
       339 
     | 
    
         
            -
             
     | 
| 
       340 
     | 
    
         
            -
                    power_option "--force"
         
     | 
| 
       341 
     | 
    
         
            -
                  end
         
     | 
| 
       342 
     | 
    
         
            -
             
     | 
| 
       343 
     | 
    
         
            -
                  command :stop_job do
         
     | 
| 
       344 
     | 
    
         
            -
                    usage  "stop <job> [<index>]"
         
     | 
| 
       345 
     | 
    
         
            -
                    desc   "Stop job/instance"
         
     | 
| 
       346 
     | 
    
         
            -
                    route  :job_management, :stop_job
         
     | 
| 
       347 
     | 
    
         
            -
                    option "--soft", "stop process only"
         
     | 
| 
       348 
     | 
    
         
            -
                    option "--hard", "power off VM"
         
     | 
| 
       349 
     | 
    
         
            -
             
     | 
| 
       350 
     | 
    
         
            -
                    power_option "--force"
         
     | 
| 
       351 
     | 
    
         
            -
                  end
         
     | 
| 
       352 
     | 
    
         
            -
             
     | 
| 
       353 
     | 
    
         
            -
                  command :restart_job do
         
     | 
| 
       354 
     | 
    
         
            -
                    usage  "restart <job> [<index>]"
         
     | 
| 
       355 
     | 
    
         
            -
                    desc   "Restart job/instance (soft stop + start)"
         
     | 
| 
       356 
     | 
    
         
            -
                    route  :job_management, :restart_job
         
     | 
| 
       357 
     | 
    
         
            -
             
     | 
| 
       358 
     | 
    
         
            -
                    power_option "--force"
         
     | 
| 
       359 
     | 
    
         
            -
                  end
         
     | 
| 
       360 
     | 
    
         
            -
             
     | 
| 
       361 
     | 
    
         
            -
                  command :recreate_job do
         
     | 
| 
       362 
     | 
    
         
            -
                    usage "recreate <job> [<index>]"
         
     | 
| 
       363 
     | 
    
         
            -
                    desc  "Recreate job/instance (hard stop + start)"
         
     | 
| 
       364 
     | 
    
         
            -
                    route :job_management, :recreate_job
         
     | 
| 
       365 
     | 
    
         
            -
             
     | 
| 
       366 
     | 
    
         
            -
                    power_option "--force"
         
     | 
| 
       367 
     | 
    
         
            -
                  end
         
     | 
| 
       368 
     | 
    
         
            -
             
     | 
| 
       369 
     | 
    
         
            -
                  command :rename_job do
         
     | 
| 
       370 
     | 
    
         
            -
                    usage "rename <old_job_name> <new_job_name>"
         
     | 
| 
       371 
     | 
    
         
            -
                    desc  "renames a job. NOTE, your deployment manifest must also be " +
         
     | 
| 
       372 
     | 
    
         
            -
                          "updated to reflect the new job name."
         
     | 
| 
       373 
     | 
    
         
            -
                    power_option "--force"
         
     | 
| 
       374 
     | 
    
         
            -
             
     | 
| 
       375 
     | 
    
         
            -
                    route :job_rename, :rename
         
     | 
| 
       376 
     | 
    
         
            -
                  end
         
     | 
| 
       377 
     | 
    
         
            -
             
     | 
| 
       378 
     | 
    
         
            -
                  command :fetch_logs do
         
     | 
| 
       379 
     | 
    
         
            -
                    usage  "logs <job> <index>"
         
     | 
| 
       380 
     | 
    
         
            -
                    desc   "Fetch job (default) or agent (if option provided) logs"
         
     | 
| 
       381 
     | 
    
         
            -
                    route  :log_management, :fetch_logs
         
     | 
| 
       382 
     | 
    
         
            -
                    option "--agent", "fetch agent logs"
         
     | 
| 
       383 
     | 
    
         
            -
                    option "--only <filter1>[...]", "only fetch logs that satisfy " +
         
     | 
| 
       384 
     | 
    
         
            -
                        "given filters (defined in job spec)"
         
     | 
| 
       385 
     | 
    
         
            -
                    option "--all", "fetch all files in the job or agent log directory"
         
     | 
| 
       386 
     | 
    
         
            -
                  end
         
     | 
| 
       387 
     | 
    
         
            -
             
     | 
| 
       388 
     | 
    
         
            -
                  command :set_property do
         
     | 
| 
       389 
     | 
    
         
            -
                    usage "set property <name> <value>"
         
     | 
| 
       390 
     | 
    
         
            -
                    desc  "Set deployment property"
         
     | 
| 
       391 
     | 
    
         
            -
                    route :property_management, :set
         
     | 
| 
       392 
     | 
    
         
            -
                  end
         
     | 
| 
       393 
     | 
    
         
            -
             
     | 
| 
       394 
     | 
    
         
            -
                  command :get_property do
         
     | 
| 
       395 
     | 
    
         
            -
                    usage "get property <name>"
         
     | 
| 
       396 
     | 
    
         
            -
                    desc  "Get deployment property"
         
     | 
| 
       397 
     | 
    
         
            -
                    route :property_management, :get
         
     | 
| 
       398 
     | 
    
         
            -
                  end
         
     | 
| 
       399 
     | 
    
         
            -
             
     | 
| 
       400 
     | 
    
         
            -
                  command :unset_property do
         
     | 
| 
       401 
     | 
    
         
            -
                    usage "unset property <name>"
         
     | 
| 
       402 
     | 
    
         
            -
                    desc  "Unset deployment property"
         
     | 
| 
       403 
     | 
    
         
            -
                    route :property_management, :unset
         
     | 
| 
       404 
     | 
    
         
            -
                  end
         
     | 
| 
       405 
     | 
    
         
            -
             
     | 
| 
       406 
     | 
    
         
            -
                  command :list_properties do
         
     | 
| 
       407 
     | 
    
         
            -
                    usage  "properties"
         
     | 
| 
       408 
     | 
    
         
            -
                    desc   "List current deployment properties"
         
     | 
| 
       409 
     | 
    
         
            -
                    route  :property_management, :list
         
     | 
| 
       410 
     | 
    
         
            -
                    option "--terse", "easy to parse output"
         
     | 
| 
       411 
     | 
    
         
            -
                  end
         
     | 
| 
       412 
     | 
    
         
            -
             
     | 
| 
       413 
     | 
    
         
            -
                  command :init_release do
         
     | 
| 
       414 
     | 
    
         
            -
                    usage "init release [<path>]"
         
     | 
| 
       415 
     | 
    
         
            -
                    desc  "Initialize release directory"
         
     | 
| 
       416 
     | 
    
         
            -
                    route :release, :init
         
     | 
| 
       417 
     | 
    
         
            -
                    option "--git", "initialize git repository"
         
     | 
| 
       418 
     | 
    
         
            -
                  end
         
     | 
| 
       419 
     | 
    
         
            -
             
     | 
| 
       420 
     | 
    
         
            -
                  command :generate_package do
         
     | 
| 
       421 
     | 
    
         
            -
                    usage "generate package <name>"
         
     | 
| 
       422 
     | 
    
         
            -
                    desc  "Generate package template"
         
     | 
| 
       423 
     | 
    
         
            -
                    route :package, :generate
         
     | 
| 
       424 
     | 
    
         
            -
                  end
         
     | 
| 
       425 
     | 
    
         
            -
             
     | 
| 
       426 
     | 
    
         
            -
                  command :generate_job do
         
     | 
| 
       427 
     | 
    
         
            -
                    usage "generate job <name>"
         
     | 
| 
       428 
     | 
    
         
            -
                    desc  "Generate job template"
         
     | 
| 
       429 
     | 
    
         
            -
                    route :job, :generate
         
     | 
| 
       430 
     | 
    
         
            -
                  end
         
     | 
| 
       431 
     | 
    
         
            -
             
     | 
| 
       432 
     | 
    
         
            -
                  command :upload_stemcell do
         
     | 
| 
       433 
     | 
    
         
            -
                    usage "upload stemcell <path>"
         
     | 
| 
       434 
     | 
    
         
            -
                    desc  "Upload the stemcell"
         
     | 
| 
       435 
     | 
    
         
            -
                    route :stemcell, :upload
         
     | 
| 
       436 
     | 
    
         
            -
                  end
         
     | 
| 
       437 
     | 
    
         
            -
             
     | 
| 
       438 
     | 
    
         
            -
                  command :upload_release do
         
     | 
| 
       439 
     | 
    
         
            -
                    usage "upload release [<path>]"
         
     | 
| 
       440 
     | 
    
         
            -
                    desc  "Upload release (<path> can point to tarball or manifest, " +
         
     | 
| 
       441 
     | 
    
         
            -
                              "defaults to the most recently created release)"
         
     | 
| 
       442 
     | 
    
         
            -
                    route :release, :upload
         
     | 
| 
       443 
     | 
    
         
            -
                  end
         
     | 
| 
       444 
     | 
    
         
            -
             
     | 
| 
       445 
     | 
    
         
            -
                  command :verify_stemcell do
         
     | 
| 
       446 
     | 
    
         
            -
                    usage "verify stemcell <path>"
         
     | 
| 
       447 
     | 
    
         
            -
                    desc  "Verify stemcell"
         
     | 
| 
       448 
     | 
    
         
            -
                    route :stemcell, :verify
         
     | 
| 
       449 
     | 
    
         
            -
                  end
         
     | 
| 
       450 
     | 
    
         
            -
             
     | 
| 
       451 
     | 
    
         
            -
                  command :verify_release do
         
     | 
| 
       452 
     | 
    
         
            -
                    usage "verify release <path>"
         
     | 
| 
       453 
     | 
    
         
            -
                    desc  "Verify release"
         
     | 
| 
       454 
     | 
    
         
            -
                    route :release, :verify
         
     | 
| 
       455 
     | 
    
         
            -
                  end
         
     | 
| 
       456 
     | 
    
         
            -
             
     | 
| 
       457 
     | 
    
         
            -
                  command :delete_deployment do
         
     | 
| 
       458 
     | 
    
         
            -
                    usage "delete deployment <name>"
         
     | 
| 
       459 
     | 
    
         
            -
                    desc  "Delete deployment"
         
     | 
| 
       460 
     | 
    
         
            -
                    route :deployment, :delete
         
     | 
| 
       461 
     | 
    
         
            -
                    option "--force", "ignore all errors while deleting parts " +
         
     | 
| 
       462 
     | 
    
         
            -
                        "of the deployment"
         
     | 
| 
       463 
     | 
    
         
            -
                  end
         
     | 
| 
       464 
     | 
    
         
            -
             
     | 
| 
       465 
     | 
    
         
            -
                  command :delete_stemcell do
         
     | 
| 
       466 
     | 
    
         
            -
                    usage "delete stemcell <name> <version>"
         
     | 
| 
       467 
     | 
    
         
            -
                    desc  "Delete the stemcell"
         
     | 
| 
       468 
     | 
    
         
            -
                    route :stemcell, :delete
         
     | 
| 
       469 
     | 
    
         
            -
                  end
         
     | 
| 
       470 
     | 
    
         
            -
             
     | 
| 
       471 
     | 
    
         
            -
                  command :delete_release do
         
     | 
| 
       472 
     | 
    
         
            -
                    usage  "delete release <name> [<version>]"
         
     | 
| 
       473 
     | 
    
         
            -
                    desc   "Delete release (or a particular release version)"
         
     | 
| 
       474 
     | 
    
         
            -
                    route  :release, :delete
         
     | 
| 
       475 
     | 
    
         
            -
                    option "--force", "ignore errors during deletion"
         
     | 
| 
       476 
     | 
    
         
            -
                  end
         
     | 
| 
       477 
     | 
    
         
            -
             
     | 
| 
       478 
     | 
    
         
            -
                  command :reset_release do
         
     | 
| 
       479 
     | 
    
         
            -
                    usage "reset release"
         
     | 
| 
       480 
     | 
    
         
            -
                    desc  "Reset release development environment " +
         
     | 
| 
       481 
     | 
    
         
            -
                              "(deletes all dev artifacts)"
         
     | 
| 
       482 
     | 
    
         
            -
                    route :release, :reset
         
     | 
| 
       483 
     | 
    
         
            -
                  end
         
     | 
| 
       484 
     | 
    
         
            -
             
     | 
| 
       485 
     | 
    
         
            -
                  command :cancel_task do
         
     | 
| 
       486 
     | 
    
         
            -
                    usage "cancel task <id>"
         
     | 
| 
       487 
     | 
    
         
            -
                    desc  "Cancel task once it reaches the next cancel checkpoint"
         
     | 
| 
       488 
     | 
    
         
            -
                    route :task, :cancel
         
     | 
| 
       489 
     | 
    
         
            -
                  end
         
     | 
| 
       490 
     | 
    
         
            -
             
     | 
| 
       491 
     | 
    
         
            -
                  command :track_task do
         
     | 
| 
       492 
     | 
    
         
            -
                    usage  "task [<task_id>|last]"
         
     | 
| 
       493 
     | 
    
         
            -
                    desc   "Show task status and start tracking its output"
         
     | 
| 
       494 
     | 
    
         
            -
                    route  :task, :track
         
     | 
| 
       495 
     | 
    
         
            -
                    option "--no-cache", "don't cache output locally"
         
     | 
| 
       496 
     | 
    
         
            -
                    option "--event|--soap|--debug", "different log types to track"
         
     | 
| 
       497 
     | 
    
         
            -
                    option "--raw", "don't beautify log"
         
     | 
| 
       498 
     | 
    
         
            -
                  end
         
     | 
| 
       499 
     | 
    
         
            -
             
     | 
| 
       500 
     | 
    
         
            -
                  command :list_stemcells do
         
     | 
| 
       501 
     | 
    
         
            -
                    usage "stemcells"
         
     | 
| 
       502 
     | 
    
         
            -
                    desc  "Show the list of available stemcells"
         
     | 
| 
       503 
     | 
    
         
            -
                    route :stemcell, :list
         
     | 
| 
       504 
     | 
    
         
            -
                  end
         
     | 
| 
       505 
     | 
    
         
            -
             
     | 
| 
       506 
     | 
    
         
            -
                  command :list_public_stemcells do
         
     | 
| 
       507 
     | 
    
         
            -
                    usage "public stemcells"
         
     | 
| 
       508 
     | 
    
         
            -
                    desc  "Show the list of publicly available stemcells for download."
         
     | 
| 
       509 
     | 
    
         
            -
                    route :stemcell, :list_public
         
     | 
| 
       510 
     | 
    
         
            -
                    option "--full", "show the full download url"
         
     | 
| 
      
 100 
     | 
    
         
            +
                def parse_global_options
         
     | 
| 
      
 101 
     | 
    
         
            +
                  # -v is reserved for verbose but having 'bosh -v' is handy,
         
     | 
| 
      
 102 
     | 
    
         
            +
                  # hence the little hack
         
     | 
| 
      
 103 
     | 
    
         
            +
                  if @args.size == 1 && (@args[0] == "-v" || @args[0] == "--version")
         
     | 
| 
      
 104 
     | 
    
         
            +
                    @args = %w(version)
         
     | 
| 
      
 105 
     | 
    
         
            +
                    return
         
     | 
| 
       511 
106 
     | 
    
         
             
                  end
         
     | 
| 
       512 
107 
     | 
    
         | 
| 
       513 
     | 
    
         
            -
                   
     | 
| 
       514 
     | 
    
         
            -
             
     | 
| 
       515 
     | 
    
         
            -
                     
     | 
| 
       516 
     | 
    
         
            -
                    route :stemcell, :download_public
         
     | 
| 
      
 108 
     | 
    
         
            +
                  opts = @option_parser
         
     | 
| 
      
 109 
     | 
    
         
            +
                  opts.on("-c", "--config FILE", "Override configuration file") do |file|
         
     | 
| 
      
 110 
     | 
    
         
            +
                    @options[:config] = file
         
     | 
| 
       517 
111 
     | 
    
         
             
                  end
         
     | 
| 
       518 
     | 
    
         
            -
             
     | 
| 
       519 
     | 
    
         
            -
             
     | 
| 
       520 
     | 
    
         
            -
                    usage "releases"
         
     | 
| 
       521 
     | 
    
         
            -
                    desc  "Show the list of available releases"
         
     | 
| 
       522 
     | 
    
         
            -
                    route :release, :list
         
     | 
| 
      
 112 
     | 
    
         
            +
                  opts.on("-C", "--cache-dir DIR", "Override cache directory") do |dir|
         
     | 
| 
      
 113 
     | 
    
         
            +
                    @options[:cache_dir] = dir
         
     | 
| 
       523 
114 
     | 
    
         
             
                  end
         
     | 
| 
       524 
     | 
    
         
            -
             
     | 
| 
       525 
     | 
    
         
            -
             
     | 
| 
       526 
     | 
    
         
            -
                    usage "deployments"
         
     | 
| 
       527 
     | 
    
         
            -
                    desc  "Show the list of available deployments"
         
     | 
| 
       528 
     | 
    
         
            -
                    route :deployment, :list
         
     | 
| 
      
 115 
     | 
    
         
            +
                  opts.on("--[no-]color", "Toggle colorized output") do |v|
         
     | 
| 
      
 116 
     | 
    
         
            +
                    Config.colorize = v
         
     | 
| 
       529 
117 
     | 
    
         
             
                  end
         
     | 
| 
       530 
118 
     | 
    
         | 
| 
       531 
     | 
    
         
            -
                   
     | 
| 
       532 
     | 
    
         
            -
                     
     | 
| 
       533 
     | 
    
         
            -
                    desc  "Diffs your current BOSH deployment configuration against " +
         
     | 
| 
       534 
     | 
    
         
            -
                          "the specified BOSH deployment configuration template so that " +
         
     | 
| 
       535 
     | 
    
         
            -
                          "you can keep your deployment configuration file up to date.  " +
         
     | 
| 
       536 
     | 
    
         
            -
                          "A dev template can be found in deployments repos."
         
     | 
| 
       537 
     | 
    
         
            -
                    route :biff, :biff
         
     | 
| 
      
 119 
     | 
    
         
            +
                  opts.on("-v", "--verbose", "Show additional output") do
         
     | 
| 
      
 120 
     | 
    
         
            +
                    @options[:verbose] = true
         
     | 
| 
       538 
121 
     | 
    
         
             
                  end
         
     | 
| 
       539 
     | 
    
         
            -
             
     | 
| 
       540 
     | 
    
         
            -
             
     | 
| 
       541 
     | 
    
         
            -
                    usage "tasks"
         
     | 
| 
       542 
     | 
    
         
            -
                    desc  "Show the list of running tasks"
         
     | 
| 
       543 
     | 
    
         
            -
                    route :task, :list_running
         
     | 
| 
      
 122 
     | 
    
         
            +
                  opts.on("-q", "--quiet", "Suppress all output") do
         
     | 
| 
      
 123 
     | 
    
         
            +
                    Config.output = nil
         
     | 
| 
       544 
124 
     | 
    
         
             
                  end
         
     | 
| 
       545 
     | 
    
         
            -
             
     | 
| 
       546 
     | 
    
         
            -
             
     | 
| 
       547 
     | 
    
         
            -
                     
     | 
| 
       548 
     | 
    
         
            -
                    desc  "Show <number> recent tasks"
         
     | 
| 
       549 
     | 
    
         
            -
                    route :task, :list_recent
         
     | 
| 
      
 125 
     | 
    
         
            +
                  opts.on("-n", "--non-interactive", "Don't ask for user input") do
         
     | 
| 
      
 126 
     | 
    
         
            +
                    @options[:non_interactive] = true
         
     | 
| 
      
 127 
     | 
    
         
            +
                    Config.colorize = false
         
     | 
| 
       550 
128 
     | 
    
         
             
                  end
         
     | 
| 
       551 
     | 
    
         
            -
             
     | 
| 
       552 
     | 
    
         
            -
             
     | 
| 
       553 
     | 
    
         
            -
                    usage "vms [<deployment>]"
         
     | 
| 
       554 
     | 
    
         
            -
                    desc  "List all VMs that supposed to be in a deployment"
         
     | 
| 
       555 
     | 
    
         
            -
                    route :vms, :list
         
     | 
| 
      
 129 
     | 
    
         
            +
                  opts.on("-t", "--target URL", "Override target") do |target|
         
     | 
| 
      
 130 
     | 
    
         
            +
                    @options[:target] = target
         
     | 
| 
       556 
131 
     | 
    
         
             
                  end
         
     | 
| 
       557 
     | 
    
         
            -
             
     | 
| 
       558 
     | 
    
         
            -
             
     | 
| 
       559 
     | 
    
         
            -
                    usage "cleanup"
         
     | 
| 
       560 
     | 
    
         
            -
                    desc  "Remove all but several recent stemcells and releases " +
         
     | 
| 
       561 
     | 
    
         
            -
                              "from current director " +
         
     | 
| 
       562 
     | 
    
         
            -
                              "(stemcells and releases currently in use are NOT deleted)"
         
     | 
| 
       563 
     | 
    
         
            -
                    route :maintenance, :cleanup
         
     | 
| 
      
 132 
     | 
    
         
            +
                  opts.on("-u", "--user USER", "Override username") do |user|
         
     | 
| 
      
 133 
     | 
    
         
            +
                    @options[:username] = user
         
     | 
| 
       564 
134 
     | 
    
         
             
                  end
         
     | 
| 
       565 
     | 
    
         
            -
             
     | 
| 
       566 
     | 
    
         
            -
             
     | 
| 
       567 
     | 
    
         
            -
                    usage  "cloudcheck [<deployment>]"
         
     | 
| 
       568 
     | 
    
         
            -
                    desc   "Cloud consistency check and interactive repair"
         
     | 
| 
       569 
     | 
    
         
            -
                    option "--auto", "resolve problems automatically " +
         
     | 
| 
       570 
     | 
    
         
            -
                        "(not recommended for production)"
         
     | 
| 
       571 
     | 
    
         
            -
                    option "--report", "generate report only, " +
         
     | 
| 
       572 
     | 
    
         
            -
                        "don't attempt to resolve problems"
         
     | 
| 
       573 
     | 
    
         
            -
                    route  :cloud_check, :perform
         
     | 
| 
      
 135 
     | 
    
         
            +
                  opts.on("-p", "--password PASSWORD", "Override password") do |pass|
         
     | 
| 
      
 136 
     | 
    
         
            +
                    @options[:password] = pass
         
     | 
| 
       574 
137 
     | 
    
         
             
                  end
         
     | 
| 
       575 
     | 
    
         
            -
             
     | 
| 
       576 
     | 
    
         
            -
             
     | 
| 
       577 
     | 
    
         
            -
                    usage  "add blob <local_path> [<blob_dir>]"
         
     | 
| 
       578 
     | 
    
         
            -
                    desc   "Add a local file as BOSH blob"
         
     | 
| 
       579 
     | 
    
         
            -
                    route  :blob_management, :add
         
     | 
| 
      
 138 
     | 
    
         
            +
                  opts.on("-d", "--deployment FILE", "Override deployment") do |file|
         
     | 
| 
      
 139 
     | 
    
         
            +
                    @options[:deployment] = file
         
     | 
| 
       580 
140 
     | 
    
         
             
                  end
         
     | 
| 
       581 
141 
     | 
    
         | 
| 
       582 
     | 
    
         
            -
                   
     | 
| 
       583 
     | 
    
         
            -
             
     | 
| 
       584 
     | 
    
         
            -
                    desc   "Upload new and updated blobs to the blobstore"
         
     | 
| 
       585 
     | 
    
         
            -
                    route  :blob_management, :upload
         
     | 
| 
       586 
     | 
    
         
            -
                  end
         
     | 
| 
      
 142 
     | 
    
         
            +
                  @args = @option_parser.order!(@args)
         
     | 
| 
      
 143 
     | 
    
         
            +
                end
         
     | 
| 
       587 
144 
     | 
    
         | 
| 
       588 
     | 
    
         
            -
             
     | 
| 
       589 
     | 
    
         
            -
             
     | 
| 
       590 
     | 
    
         
            -
             
     | 
| 
       591 
     | 
    
         
            -
             
     | 
| 
       592 
     | 
    
         
            -
                  end
         
     | 
| 
      
 145 
     | 
    
         
            +
                # Discover and load CLI plugins from all available gems
         
     | 
| 
      
 146 
     | 
    
         
            +
                # @return [void]
         
     | 
| 
      
 147 
     | 
    
         
            +
                def load_plugins
         
     | 
| 
      
 148 
     | 
    
         
            +
                  plugins_glob = "bosh/cli/commands/*.rb"
         
     | 
| 
       593 
149 
     | 
    
         | 
| 
       594 
     | 
    
         
            -
                   
     | 
| 
       595 
     | 
    
         
            -
                     
     | 
| 
       596 
     | 
    
         
            -
             
     | 
| 
       597 
     | 
    
         
            -
             
     | 
| 
      
 150 
     | 
    
         
            +
                  unless Gem.respond_to?(:find_files)
         
     | 
| 
      
 151 
     | 
    
         
            +
                    say("Cannot load plugins, ".yellow +
         
     | 
| 
      
 152 
     | 
    
         
            +
                        "please run `gem update --system' to ".yellow +
         
     | 
| 
      
 153 
     | 
    
         
            +
                        "update your RubyGems".yellow)
         
     | 
| 
      
 154 
     | 
    
         
            +
                    return
         
     | 
| 
       598 
155 
     | 
    
         
             
                  end
         
     | 
| 
       599 
156 
     | 
    
         | 
| 
       600 
     | 
    
         
            -
                   
     | 
| 
       601 
     | 
    
         
            -
                    plugins_glob  
     | 
| 
       602 
     | 
    
         
            -
             
     | 
| 
       603 
     | 
    
         
            -
                     
     | 
| 
       604 
     | 
    
         
            -
             
     | 
| 
       605 
     | 
    
         
            -
                          "please run `gem update --system' to ".yellow +
         
     | 
| 
       606 
     | 
    
         
            -
                          "update your RubyGems".yellow)
         
     | 
| 
       607 
     | 
    
         
            -
                      return
         
     | 
| 
       608 
     | 
    
         
            -
                    end
         
     | 
| 
       609 
     | 
    
         
            -
             
     | 
| 
       610 
     | 
    
         
            -
                    plugins = begin
         
     | 
| 
       611 
     | 
    
         
            -
                      Gem.find_files(plugins_glob, true)
         
     | 
| 
       612 
     | 
    
         
            -
                    rescue ArgumentError
         
     | 
| 
       613 
     | 
    
         
            -
                      # Handling rubygems compatibility issue
         
     | 
| 
       614 
     | 
    
         
            -
                      Gem.find_files(plugins_glob)
         
     | 
| 
       615 
     | 
    
         
            -
                    end
         
     | 
| 
       616 
     | 
    
         
            -
             
     | 
| 
       617 
     | 
    
         
            -
                    plugins.each do |file|
         
     | 
| 
       618 
     | 
    
         
            -
                      class_name = File.basename(file, ".rb").capitalize
         
     | 
| 
       619 
     | 
    
         
            -
             
     | 
| 
       620 
     | 
    
         
            -
                      next if Bosh::Cli::Command.const_defined?(class_name)
         
     | 
| 
       621 
     | 
    
         
            -
             
     | 
| 
       622 
     | 
    
         
            -
                      load file
         
     | 
| 
       623 
     | 
    
         
            -
             
     | 
| 
       624 
     | 
    
         
            -
                      plugin = Bosh::Cli::Command.const_get(class_name)
         
     | 
| 
       625 
     | 
    
         
            -
             
     | 
| 
       626 
     | 
    
         
            -
                      plugin.commands.each do |name, block|
         
     | 
| 
       627 
     | 
    
         
            -
                        command(name, &block)
         
     | 
| 
       628 
     | 
    
         
            -
                      end
         
     | 
| 
       629 
     | 
    
         
            -
             
     | 
| 
       630 
     | 
    
         
            -
                      @plugins ||= {}
         
     | 
| 
       631 
     | 
    
         
            -
                      @plugins[class_name] = plugin
         
     | 
| 
       632 
     | 
    
         
            -
                    end
         
     | 
| 
      
 157 
     | 
    
         
            +
                  plugins = begin
         
     | 
| 
      
 158 
     | 
    
         
            +
                    Gem.find_files(plugins_glob, true)
         
     | 
| 
      
 159 
     | 
    
         
            +
                  rescue ArgumentError
         
     | 
| 
      
 160 
     | 
    
         
            +
                    # Handling rubygems compatibility issue
         
     | 
| 
      
 161 
     | 
    
         
            +
                    Gem.find_files(plugins_glob)
         
     | 
| 
       633 
162 
     | 
    
         
             
                  end
         
     | 
| 
       634 
163 
     | 
    
         | 
| 
       635 
     | 
    
         
            -
             
     | 
| 
       636 
     | 
    
         
            -
             
     | 
| 
       637 
     | 
    
         
            -
             
     | 
| 
       638 
     | 
    
         
            -
             
     | 
| 
       639 
     | 
    
         
            -
                     
     | 
| 
       640 
     | 
    
         
            -
             
     | 
| 
       641 
     | 
    
         
            -
                     
     | 
| 
       642 
     | 
    
         
            -
             
     | 
| 
       643 
     | 
    
         
            -
                    opts.on("-q", "--quiet") { @options[:quiet] = true }
         
     | 
| 
       644 
     | 
    
         
            -
                    opts.on("-s", "--skip-director-checks") do
         
     | 
| 
       645 
     | 
    
         
            -
                      @options[:director_checks] = false
         
     | 
| 
      
 164 
     | 
    
         
            +
                  plugins.each do |plugin|
         
     | 
| 
      
 165 
     | 
    
         
            +
                    n_commands = Config.commands.size
         
     | 
| 
      
 166 
     | 
    
         
            +
                    gem_dir = Pathname.new(Gem.dir)
         
     | 
| 
      
 167 
     | 
    
         
            +
                    plugin_name = Pathname.new(plugin).relative_path_from(gem_dir)
         
     | 
| 
      
 168 
     | 
    
         
            +
                    begin
         
     | 
| 
      
 169 
     | 
    
         
            +
                      require plugin
         
     | 
| 
      
 170 
     | 
    
         
            +
                    rescue Exception => e
         
     | 
| 
      
 171 
     | 
    
         
            +
                      say("Failed to load plugin #{plugin_name}: #{e.message}".red)
         
     | 
| 
       646 
172 
     | 
    
         
             
                    end
         
     | 
| 
       647 
     | 
    
         
            -
                     
     | 
| 
       648 
     | 
    
         
            -
                       
     | 
| 
       649 
     | 
    
         
            -
             
     | 
| 
      
 173 
     | 
    
         
            +
                    if Config.commands.size == n_commands
         
     | 
| 
      
 174 
     | 
    
         
            +
                      say(("File #{plugin_name} has been loaded as plugin but it didn't " +
         
     | 
| 
      
 175 
     | 
    
         
            +
                          "contain any commands.\nMake sure this plugin is updated to be " +
         
     | 
| 
      
 176 
     | 
    
         
            +
                          "compatible with BOSH CLI 1.0.").columnize(80).yellow)
         
     | 
| 
       650 
177 
     | 
    
         
             
                    end
         
     | 
| 
       651 
     | 
    
         
            -
                    opts.on("-d", "--debug") { @options[:debug] = true }
         
     | 
| 
       652 
     | 
    
         
            -
                    opts.on("--target URL") { |target| @options[:target] = target }
         
     | 
| 
       653 
     | 
    
         
            -
                    opts.on("--user USER") { |user| @options[:username] = user }
         
     | 
| 
       654 
     | 
    
         
            -
                    opts.on("--password PASSWORD") { |pass| @options[:password] = pass }
         
     | 
| 
       655 
     | 
    
         
            -
                    opts.on("--deployment FILE") { |file| @options[:deployment] = file }
         
     | 
| 
       656 
     | 
    
         
            -
                    opts.on("-v", "--version") { dispatch(find_command(:version)) }
         
     | 
| 
       657 
178 
     | 
    
         
             
                  end
         
     | 
| 
       658 
     | 
    
         
            -
             
     | 
| 
       659 
     | 
    
         
            -
                  @args = opts_parser.order!(@args)
         
     | 
| 
       660 
179 
     | 
    
         
             
                end
         
     | 
| 
       661 
180 
     | 
    
         | 
| 
       662 
181 
     | 
    
         
             
                def build_parse_tree
         
     | 
| 
       663 
182 
     | 
    
         
             
                  @parse_tree = ParseTreeNode.new
         
     | 
| 
       664 
183 
     | 
    
         | 
| 
       665 
     | 
    
         
            -
                   
     | 
| 
      
 184 
     | 
    
         
            +
                  Config.commands.each_value do |command|
         
     | 
| 
       666 
185 
     | 
    
         
             
                    p = @parse_tree
         
     | 
| 
       667 
186 
     | 
    
         
             
                    n_kw = command.keywords.size
         
     | 
| 
       668 
187 
     | 
    
         | 
| 
       669 
     | 
    
         
            -
                     
     | 
| 
      
 188 
     | 
    
         
            +
                    command.keywords.each_with_index do |kw, i|
         
     | 
| 
       670 
189 
     | 
    
         
             
                      p[kw] ||= ParseTreeNode.new
         
     | 
| 
       671 
190 
     | 
    
         
             
                      p = p[kw]
         
     | 
| 
       672 
191 
     | 
    
         
             
                      p.command = command if i == n_kw - 1
         
     | 
| 
         @@ -675,81 +194,17 @@ module Bosh::Cli 
     | 
|
| 
       675 
194 
     | 
    
         
             
                end
         
     | 
| 
       676 
195 
     | 
    
         | 
| 
       677 
196 
     | 
    
         
             
                def add_shortcuts
         
     | 
| 
       678 
     | 
    
         
            -
                  { 
     | 
| 
      
 197 
     | 
    
         
            +
                  {
         
     | 
| 
      
 198 
     | 
    
         
            +
                    "st" => "status",
         
     | 
| 
       679 
199 
     | 
    
         
             
                    "props" => "properties",
         
     | 
| 
       680 
     | 
    
         
            -
                    "cck" => "cloudcheck" 
     | 
| 
      
 200 
     | 
    
         
            +
                    "cck" => "cloudcheck"
         
     | 
| 
      
 201 
     | 
    
         
            +
                  }.each do |short, long|
         
     | 
| 
       681 
202 
     | 
    
         
             
                    @parse_tree[short] = @parse_tree[long]
         
     | 
| 
       682 
203 
     | 
    
         
             
                  end
         
     | 
| 
       683 
204 
     | 
    
         
             
                end
         
     | 
| 
       684 
205 
     | 
    
         | 
| 
       685 
     | 
    
         
            -
                def  
     | 
| 
       686 
     | 
    
         
            -
                   
     | 
| 
       687 
     | 
    
         
            -
                      usage: bosh [--verbose] [--config|-c <FILE>] [--cache-dir <DIR]
         
     | 
| 
       688 
     | 
    
         
            -
                                  [--force] [--no-color] [--skip-director-checks] [--quiet]
         
     | 
| 
       689 
     | 
    
         
            -
                                  [--non-interactive]
         
     | 
| 
       690 
     | 
    
         
            -
                                  command [<args>]
         
     | 
| 
       691 
     | 
    
         
            -
                  OUT
         
     | 
| 
       692 
     | 
    
         
            -
                end
         
     | 
| 
       693 
     | 
    
         
            -
             
     | 
| 
       694 
     | 
    
         
            -
                def command_usage(cmd, margin = nil)
         
     | 
| 
       695 
     | 
    
         
            -
                  command = cmd.is_a?(Symbol) ? find_command(cmd) : cmd
         
     | 
| 
       696 
     | 
    
         
            -
                  usage = command.usage
         
     | 
| 
       697 
     | 
    
         
            -
             
     | 
| 
       698 
     | 
    
         
            -
                  margin ||= 2
         
     | 
| 
       699 
     | 
    
         
            -
                  usage_width = 25
         
     | 
| 
       700 
     | 
    
         
            -
                  desc_width = 43
         
     | 
| 
       701 
     | 
    
         
            -
                  option_width = 10
         
     | 
| 
       702 
     | 
    
         
            -
             
     | 
| 
       703 
     | 
    
         
            -
                  output = " " * margin
         
     | 
| 
       704 
     | 
    
         
            -
                  output << usage.ljust(usage_width) + " "
         
     | 
| 
       705 
     | 
    
         
            -
                  char_count = usage.size > usage_width ? 100 : 0
         
     | 
| 
       706 
     | 
    
         
            -
             
     | 
| 
       707 
     | 
    
         
            -
                  command.description.to_s.split(/\s+/).each do |word|
         
     | 
| 
       708 
     | 
    
         
            -
                    if char_count + word.size + 1 > desc_width # +1 accounts for space
         
     | 
| 
       709 
     | 
    
         
            -
                      char_count = 0
         
     | 
| 
       710 
     | 
    
         
            -
                      output << "\n" + " " * (margin + usage_width + 1)
         
     | 
| 
       711 
     | 
    
         
            -
                    end
         
     | 
| 
       712 
     | 
    
         
            -
                    char_count += word.size
         
     | 
| 
       713 
     | 
    
         
            -
                    output << word << " "
         
     | 
| 
       714 
     | 
    
         
            -
                  end
         
     | 
| 
       715 
     | 
    
         
            -
             
     | 
| 
       716 
     | 
    
         
            -
                  command.options.each do |name, value|
         
     | 
| 
       717 
     | 
    
         
            -
                    output << "\n" + " " * (margin + usage_width + 1)
         
     | 
| 
       718 
     | 
    
         
            -
                    output << name.ljust(option_width) + " "
         
     | 
| 
       719 
     | 
    
         
            -
                    # Long option name eats the whole line,
         
     | 
| 
       720 
     | 
    
         
            -
                    # short one gives space to description
         
     | 
| 
       721 
     | 
    
         
            -
                    char_count = name.size > option_width ? 100 : 0
         
     | 
| 
       722 
     | 
    
         
            -
             
     | 
| 
       723 
     | 
    
         
            -
                    value.to_s.split(/\s+/).each do |word|
         
     | 
| 
       724 
     | 
    
         
            -
                      if char_count + word.size + 1 > desc_width - option_width
         
     | 
| 
       725 
     | 
    
         
            -
                        char_count = 0
         
     | 
| 
       726 
     | 
    
         
            -
                        output << "\n" + " " * (margin + usage_width + option_width + 2)
         
     | 
| 
       727 
     | 
    
         
            -
                      end
         
     | 
| 
       728 
     | 
    
         
            -
                      char_count += word.size
         
     | 
| 
       729 
     | 
    
         
            -
                      output << word << " "
         
     | 
| 
       730 
     | 
    
         
            -
                    end
         
     | 
| 
       731 
     | 
    
         
            -
                  end
         
     | 
| 
       732 
     | 
    
         
            -
             
     | 
| 
       733 
     | 
    
         
            -
                  output
         
     | 
| 
       734 
     | 
    
         
            -
                end
         
     | 
| 
       735 
     | 
    
         
            -
             
     | 
| 
       736 
     | 
    
         
            -
                def help_message
         
     | 
| 
       737 
     | 
    
         
            -
                  template = File.join(File.dirname(__FILE__),
         
     | 
| 
       738 
     | 
    
         
            -
                                       "templates", "help_message.erb")
         
     | 
| 
       739 
     | 
    
         
            -
                  ERB.new(File.read(template), 4).result(binding.taint)
         
     | 
| 
       740 
     | 
    
         
            -
                end
         
     | 
| 
       741 
     | 
    
         
            -
             
     | 
| 
       742 
     | 
    
         
            -
                def plugin_help_message
         
     | 
| 
       743 
     | 
    
         
            -
                  help = ['']
         
     | 
| 
       744 
     | 
    
         
            -
             
     | 
| 
       745 
     | 
    
         
            -
                  @plugins.each do |class_name, plugin|
         
     | 
| 
       746 
     | 
    
         
            -
                    help << class_name
         
     | 
| 
       747 
     | 
    
         
            -
                    plugin.commands.keys.each do |name|
         
     | 
| 
       748 
     | 
    
         
            -
                      help << command_usage(name)
         
     | 
| 
       749 
     | 
    
         
            -
                    end
         
     | 
| 
       750 
     | 
    
         
            -
                  end
         
     | 
| 
       751 
     | 
    
         
            -
             
     | 
| 
       752 
     | 
    
         
            -
                  help.join("\n")
         
     | 
| 
      
 206 
     | 
    
         
            +
                def usage
         
     | 
| 
      
 207 
     | 
    
         
            +
                  @option_parser.to_s
         
     | 
| 
       753 
208 
     | 
    
         
             
                end
         
     | 
| 
       754 
209 
     | 
    
         | 
| 
       755 
210 
     | 
    
         
             
                def search_parse_tree(node)
         
     | 
| 
         @@ -770,13 +225,12 @@ module Bosh::Cli 
     | 
|
| 
       770 
225 
     | 
    
         
             
                  # Tries to find best match among aliases (possibly multiple words),
         
     | 
| 
       771 
226 
     | 
    
         
             
                  # then unwinds it onto the remaining args and searches parse tree again.
         
     | 
| 
       772 
227 
     | 
    
         
             
                  # Not the most effective algorithm but does the job.
         
     | 
| 
       773 
     | 
    
         
            -
                  config = Bosh::Cli::Config.new(
         
     | 
| 
       774 
     | 
    
         
            -
                      @options[:config] || Bosh::Cli::DEFAULT_CONFIG_PATH)
         
     | 
| 
      
 228 
     | 
    
         
            +
                  config = Bosh::Cli::Config.new(@options[:config])
         
     | 
| 
       775 
229 
     | 
    
         
             
                  candidate = []
         
     | 
| 
       776 
230 
     | 
    
         
             
                  best_match = nil
         
     | 
| 
       777 
231 
     | 
    
         
             
                  save_args = @args.dup
         
     | 
| 
       778 
232 
     | 
    
         | 
| 
       779 
     | 
    
         
            -
                  while arg = @args.shift
         
     | 
| 
      
 233 
     | 
    
         
            +
                  while (arg = @args.shift)
         
     | 
| 
       780 
234 
     | 
    
         
             
                    candidate << arg
         
     | 
| 
       781 
235 
     | 
    
         
             
                    resolved = config.resolve_alias(:cli, candidate.join(" "))
         
     | 
| 
       782 
236 
     | 
    
         
             
                    if best_match && resolved.nil?
         
     | 
| 
         @@ -791,41 +245,11 @@ module Bosh::Cli 
     | 
|
| 
       791 
245 
     | 
    
         
             
                    return
         
     | 
| 
       792 
246 
     | 
    
         
             
                  end
         
     | 
| 
       793 
247 
     | 
    
         | 
| 
       794 
     | 
    
         
            -
                  best_match.split(/\s+/).reverse.each do | 
     | 
| 
       795 
     | 
    
         
            -
                    @args.unshift( 
     | 
| 
      
 248 
     | 
    
         
            +
                  best_match.split(/\s+/).reverse.each do |keyword|
         
     | 
| 
      
 249 
     | 
    
         
            +
                    @args.unshift(keyword)
         
     | 
| 
       796 
250 
     | 
    
         
             
                  end
         
     | 
| 
       797 
251 
     | 
    
         | 
| 
       798 
252 
     | 
    
         
             
                  search_parse_tree(@parse_tree)
         
     | 
| 
       799 
253 
     | 
    
         
             
                end
         
     | 
| 
       800 
     | 
    
         
            -
             
     | 
| 
       801 
     | 
    
         
            -
                def command_suggestions(args)
         
     | 
| 
       802 
     | 
    
         
            -
                  non_keywords = args - ALL_KEYWORDS
         
     | 
| 
       803 
     | 
    
         
            -
             
     | 
| 
       804 
     | 
    
         
            -
                  COMMANDS.values.select do |cmd|
         
     | 
| 
       805 
     | 
    
         
            -
                    (args & cmd.keywords).size > 0 && args - cmd.keywords == non_keywords
         
     | 
| 
       806 
     | 
    
         
            -
                  end
         
     | 
| 
       807 
     | 
    
         
            -
                end
         
     | 
| 
       808 
     | 
    
         
            -
             
     | 
| 
       809 
     | 
    
         
            -
                def unknown_command(cmd)
         
     | 
| 
       810 
     | 
    
         
            -
                  say("Command `#{cmd}' not found.")
         
     | 
| 
       811 
     | 
    
         
            -
                  say("Please use `bosh help' to get the list of bosh commands.")
         
     | 
| 
       812 
     | 
    
         
            -
                end
         
     | 
| 
       813 
     | 
    
         
            -
             
     | 
| 
       814 
     | 
    
         
            -
                def save_exception(e)
         
     | 
| 
       815 
     | 
    
         
            -
                  say("BOSH CLI Error: #{e.message}".red)
         
     | 
| 
       816 
     | 
    
         
            -
                  begin
         
     | 
| 
       817 
     | 
    
         
            -
                    errfile = File.expand_path("~/.bosh_error")
         
     | 
| 
       818 
     | 
    
         
            -
                    File.open(errfile, "w") do |f|
         
     | 
| 
       819 
     | 
    
         
            -
                      f.write(e.message)
         
     | 
| 
       820 
     | 
    
         
            -
                      f.write("\n")
         
     | 
| 
       821 
     | 
    
         
            -
                      f.write(e.backtrace.join("\n"))
         
     | 
| 
       822 
     | 
    
         
            -
                    end
         
     | 
| 
       823 
     | 
    
         
            -
                    say("Error information saved in #{errfile}")
         
     | 
| 
       824 
     | 
    
         
            -
                  rescue => e
         
     | 
| 
       825 
     | 
    
         
            -
                    say("Error information couldn't be saved: #{e.message}")
         
     | 
| 
       826 
     | 
    
         
            -
                  end
         
     | 
| 
       827 
     | 
    
         
            -
                end
         
     | 
| 
       828 
     | 
    
         
            -
             
     | 
| 
       829 
254 
     | 
    
         
             
              end
         
     | 
| 
       830 
     | 
    
         
            -
             
     | 
| 
       831 
255 
     | 
    
         
             
            end
         
     |