mortar 0.7.2 → 0.7.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
    
        data/lib/mortar/command/jobs.rb
    CHANGED
    
    | @@ -23,6 +23,10 @@ class Mortar::Command::Jobs < Mortar::Command::Base | |
| 23 23 |  | 
| 24 24 | 
             
              include Mortar::Git
         | 
| 25 25 |  | 
| 26 | 
            +
              CLUSTER_TYPE__SINGLE_JOB = 'single_job'
         | 
| 27 | 
            +
              CLUSTER_TYPE__PERSISTENT = 'persistent'
         | 
| 28 | 
            +
              CLUSTER_TYPE__PERMANENT = 'permanent'
         | 
| 29 | 
            +
             | 
| 26 30 | 
             
              # jobs
         | 
| 27 31 | 
             
              #
         | 
| 28 32 | 
             
              # Show recent and running jobs.
         | 
| @@ -57,6 +61,7 @@ class Mortar::Command::Jobs < Mortar::Command::Base | |
| 57 61 | 
             
              # -c, --clusterid CLUSTERID   # Run job on an existing cluster with ID of CLUSTERID (optional)
         | 
| 58 62 | 
             
              # -s, --clustersize NUMNODES  # Run job on a new cluster, with NUMNODES nodes (optional; must be >= 2 if provided)
         | 
| 59 63 | 
             
              # -1, --singlejobcluster      # Stop the cluster after job completes.  (Default: false—-cluster can be used for other jobs, and will shut down after 1 hour of inactivity)
         | 
| 64 | 
            +
              # -2, --permanentcluster      # Don't automatically stop the cluster after it has been idle for an hour (Default: false--cluster will be shut down after 1 hour of inactivity)
         | 
| 60 65 | 
             
              # -p, --parameter NAME=VALUE  # Set a pig parameter value in your script.
         | 
| 61 66 | 
             
              # -f, --param-file PARAMFILE  # Load pig parameter values from a file.
         | 
| 62 67 | 
             
              # -d, --donotnotify           # Don't send an email on job completion.  (Default: false--an email will be sent to you once the job completes)
         | 
| @@ -102,7 +107,7 @@ class Mortar::Command::Jobs < Mortar::Command::Base | |
| 102 107 | 
             
                end
         | 
| 103 108 |  | 
| 104 109 | 
             
                if options[:clusterid]
         | 
| 105 | 
            -
                  [:clustersize, :singlejobcluster].each do |opt|
         | 
| 110 | 
            +
                  [:clustersize, :singlejobcluster, :permanentcluster].each do |opt|
         | 
| 106 111 | 
             
                    unless options[opt].nil?
         | 
| 107 112 | 
             
                      error("Option #{opt.to_s} cannot be set when running a job on an existing cluster (with --clusterid option)")
         | 
| 108 113 | 
             
                    end
         | 
| @@ -116,11 +121,19 @@ class Mortar::Command::Jobs < Mortar::Command::Base | |
| 116 121 | 
             
                # post job to API    
         | 
| 117 122 | 
             
                response = action("Requesting job execution") do
         | 
| 118 123 | 
             
                  if options[:clustersize]
         | 
| 124 | 
            +
                    if options[:singlejobcluster] && options[:permanentcluster]
         | 
| 125 | 
            +
                      error("Cannot declare cluster as both --singlejobcluster and --permanentcluster")
         | 
| 126 | 
            +
                    end
         | 
| 119 127 | 
             
                    cluster_size = options[:clustersize].to_i
         | 
| 120 | 
            -
                     | 
| 128 | 
            +
                    cluster_type = CLUSTER_TYPE__PERSISTENT
         | 
| 129 | 
            +
                    if options[:singlejobcluster]
         | 
| 130 | 
            +
                      cluster_type = CLUSTER_TYPE__SINGLE_JOB
         | 
| 131 | 
            +
                    elsif options[:permanentcluster]
         | 
| 132 | 
            +
                      cluster_type = CLUSTER_TYPE__PERMANENT
         | 
| 133 | 
            +
                    end
         | 
| 121 134 | 
             
                    api.post_job_new_cluster(project.name, script.name, git_ref, cluster_size, 
         | 
| 122 135 | 
             
                      :parameters => pig_parameters,
         | 
| 123 | 
            -
                      : | 
| 136 | 
            +
                      :cluster_type => cluster_type,
         | 
| 124 137 | 
             
                      :notify_on_job_finish => notify_on_job_finish,
         | 
| 125 138 | 
             
                      :is_control_script => is_control_script).body
         | 
| 126 139 | 
             
                  else
         | 
| @@ -22,7 +22,7 @@ require "mortar/local/jython" | |
| 22 22 |  | 
| 23 23 |  | 
| 24 24 | 
             
            class Mortar::Local::Controller
         | 
| 25 | 
            -
              include Mortar:: | 
| 25 | 
            +
              include Mortar::Local::InstallUtil
         | 
| 26 26 |  | 
| 27 27 | 
             
              NO_JAVA_ERROR_MESSAGE = <<EOF
         | 
| 28 28 | 
             
            A suitable java installation could not be found.  If you already have java installed
         | 
| @@ -42,8 +42,8 @@ https://pypi.python.org/pypi/virtualenv | |
| 42 42 | 
             
            EOF
         | 
| 43 43 |  | 
| 44 44 | 
             
              NO_AWS_KEYS_ERROR_MESSAGE = <<EOF
         | 
| 45 | 
            -
            Please specify your aws access key via  | 
| 46 | 
            -
            and your aws secret key via  | 
| 45 | 
            +
            Please specify your aws access key via environment variable AWS_ACCESS_KEY
         | 
| 46 | 
            +
            and your aws secret key via environment variable AWS_SECRET_KEY"
         | 
| 47 47 | 
             
            EOF
         | 
| 48 48 |  | 
| 49 49 |  | 
| @@ -91,6 +91,19 @@ EOF | |
| 91 91 |  | 
| 92 92 | 
             
                jy = Mortar::Local::Jython.new()
         | 
| 93 93 | 
             
                jy.install_or_update()
         | 
| 94 | 
            +
             | 
| 95 | 
            +
                ensure_local_install_dir_in_gitignore
         | 
| 96 | 
            +
              end
         | 
| 97 | 
            +
             | 
| 98 | 
            +
              def ensure_local_install_dir_in_gitignore()
         | 
| 99 | 
            +
                if File.exists? local_project_gitignore
         | 
| 100 | 
            +
                  open(local_project_gitignore, 'r+') do |gitignore|
         | 
| 101 | 
            +
                    unless gitignore.read().include? local_install_directory_name
         | 
| 102 | 
            +
                      gitignore.seek(0, IO::SEEK_END)
         | 
| 103 | 
            +
                      gitignore.puts local_install_directory_name
         | 
| 104 | 
            +
                    end
         | 
| 105 | 
            +
                  end
         | 
| 106 | 
            +
                end
         | 
| 94 107 | 
             
              end
         | 
| 95 108 |  | 
| 96 109 | 
             
              # Main entry point for user running a pig script
         | 
| @@ -28,10 +28,26 @@ module Mortar | |
| 28 28 |  | 
| 29 29 | 
             
                  include Mortar::Helpers
         | 
| 30 30 |  | 
| 31 | 
            -
                  def  | 
| 31 | 
            +
                  def local_install_directory_name
         | 
| 32 | 
            +
                    ".mortar-local"
         | 
| 33 | 
            +
                  end
         | 
| 34 | 
            +
             | 
| 35 | 
            +
                  def project_root
         | 
| 32 36 | 
             
                    # note: assumes that CWD is the project root, is
         | 
| 33 37 | 
             
                    # this a safe assumption?
         | 
| 34 | 
            -
                     | 
| 38 | 
            +
                    Dir.getwd
         | 
| 39 | 
            +
                  end
         | 
| 40 | 
            +
             | 
| 41 | 
            +
                  def local_install_directory
         | 
| 42 | 
            +
                    File.join(project_root, local_install_directory_name)
         | 
| 43 | 
            +
                  end
         | 
| 44 | 
            +
             | 
| 45 | 
            +
                  def local_pig_logfile
         | 
| 46 | 
            +
                    project_root + "/local-pig.log"
         | 
| 47 | 
            +
                  end
         | 
| 48 | 
            +
             | 
| 49 | 
            +
                  def local_project_gitignore
         | 
| 50 | 
            +
                    project_root + "/.gitignore"
         | 
| 35 51 | 
             
                  end
         | 
| 36 52 |  | 
| 37 53 | 
             
                  def jython_directory
         | 
| @@ -42,6 +58,10 @@ module Mortar | |
| 42 58 | 
             
                    jython_directory + "/cachedir"
         | 
| 43 59 | 
             
                  end
         | 
| 44 60 |  | 
| 61 | 
            +
                  def gitignore_template_path
         | 
| 62 | 
            +
                    File.expand_path("../../templates/project/gitignore", __FILE__)
         | 
| 63 | 
            +
                  end
         | 
| 64 | 
            +
             | 
| 45 65 | 
             
                  # Drops a marker file for an installed package, used
         | 
| 46 66 | 
             
                  # to help determine if updates should be performed
         | 
| 47 67 | 
             
                  def note_install(subdirectory)
         | 
    
        data/lib/mortar/local/pig.rb
    CHANGED
    
    | @@ -224,6 +224,7 @@ class Mortar::Local::Pig | |
| 224 224 | 
             
              # get it to do something interesting, such as '-f some-file.pig'
         | 
| 225 225 | 
             
              def run_pig_command(cmd, parameters = nil, jython_output = true)
         | 
| 226 226 | 
             
                unset_hadoop_env_vars
         | 
| 227 | 
            +
                delete_local_log_file
         | 
| 227 228 | 
             
                # Generate the script for running the command, then
         | 
| 228 229 | 
             
                # write it to a temp script which will be exectued
         | 
| 229 230 | 
             
                script_text = script_for_command(cmd, parameters)
         | 
| @@ -243,6 +244,12 @@ class Mortar::Local::Pig | |
| 243 244 | 
             
                ENV['HADOOP_CONF_DIR'] = ''
         | 
| 244 245 | 
             
              end
         | 
| 245 246 |  | 
| 247 | 
            +
              def delete_local_log_file
         | 
| 248 | 
            +
                if File.exists? local_pig_logfile
         | 
| 249 | 
            +
                  FileUtils.rm local_pig_logfile
         | 
| 250 | 
            +
                end
         | 
| 251 | 
            +
              end
         | 
| 252 | 
            +
             | 
| 246 253 | 
             
              # Generates a bash script which sets up the necessary environment and
         | 
| 247 254 | 
             
              # then runs the pig command
         | 
| 248 255 | 
             
              def script_for_command(cmd, parameters, jython_output = true)
         | 
| @@ -278,6 +285,7 @@ class Mortar::Local::Pig | |
| 278 285 | 
             
                opts['fs.s3n.awsAccessKeyId'] = ENV['AWS_ACCESS_KEY']
         | 
| 279 286 | 
             
                opts['fs.s3n.awsSecretAccessKey'] = ENV['AWS_SECRET_KEY']
         | 
| 280 287 | 
             
                opts['pig.events.logformat'] = PIG_LOG_FORMAT
         | 
| 288 | 
            +
                opts['pig.logfile'] = local_pig_logfile
         | 
| 281 289 | 
             
                opts['python.verbose'] = 'error'
         | 
| 282 290 | 
             
                opts['jython.output'] = true
         | 
| 283 291 | 
             
                opts['python.home'] = jython_directory
         | 
    
        data/lib/mortar/version.rb
    CHANGED
    
    
| @@ -48,7 +48,7 @@ module Mortar::Command | |
| 48 48 |  | 
| 49 49 | 
             
                      mock(Mortar::Auth.api).post_job_new_cluster("myproject", "my_script", is_a(String), cluster_size, 
         | 
| 50 50 | 
             
                        :parameters => match_array([{"name" => "FIRST_PARAM", "value" => "FOO"}, {"name" => "SECOND_PARAM", "value" => "BAR"}]), 
         | 
| 51 | 
            -
                        : | 
| 51 | 
            +
                        :cluster_type => Jobs::CLUSTER_TYPE__SINGLE_JOB,
         | 
| 52 52 | 
             
                        :notify_on_job_finish => true,
         | 
| 53 53 | 
             
                        :is_control_script=> false) {Excon::Response.new(:body => {"job_id" => job_id, "web_job_url" => job_url})}
         | 
| 54 54 |  | 
| @@ -71,7 +71,64 @@ Or by running: | |
| 71 71 | 
             
            STDOUT
         | 
| 72 72 | 
             
                    end
         | 
| 73 73 | 
             
                  end
         | 
| 74 | 
            -
             | 
| 74 | 
            +
             | 
| 75 | 
            +
                  it "handles permanentcluster parameter" do
         | 
| 76 | 
            +
                    with_git_initialized_project do |p|
         | 
| 77 | 
            +
                      # stub api requests
         | 
| 78 | 
            +
                      job_id = "c571a8c7f76a4fd4a67c103d753e2dd5"
         | 
| 79 | 
            +
                      job_url = "http://127.0.0.1:5000/jobs/job_detail?job_id=c571a8c7f76a4fd4a67c103d753e2dd5"
         | 
| 80 | 
            +
                      cluster_size = 5
         | 
| 81 | 
            +
             | 
| 82 | 
            +
                      mock(Mortar::Auth.api).post_job_new_cluster("myproject", "my_script", is_a(String), cluster_size,
         | 
| 83 | 
            +
                                                                  :parameters => match_array([{"name" => "FIRST_PARAM", "value" => "FOO"}, {"name" => "SECOND_PARAM", "value" => "BAR"}]),
         | 
| 84 | 
            +
                                                                  :cluster_type => Jobs::CLUSTER_TYPE__PERMANENT,
         | 
| 85 | 
            +
                                                                  :notify_on_job_finish => true,
         | 
| 86 | 
            +
                                                                  :is_control_script=> false) {Excon::Response.new(:body => {"job_id" => job_id, "web_job_url" => job_url})}
         | 
| 87 | 
            +
             | 
| 88 | 
            +
                      write_file(File.join(p.pigscripts_path, "my_script.pig"))
         | 
| 89 | 
            +
                      stderr, stdout = execute("jobs:run my_script -2 --clustersize 5 -p FIRST_PARAM=FOO -p SECOND_PARAM=BAR", p, @git)
         | 
| 90 | 
            +
                      stdout.should == <<-STDOUT
         | 
| 91 | 
            +
            Taking code snapshot... done
         | 
| 92 | 
            +
            Sending code snapshot to Mortar... done
         | 
| 93 | 
            +
            Requesting job execution... done
         | 
| 94 | 
            +
            job_id: c571a8c7f76a4fd4a67c103d753e2dd5
         | 
| 95 | 
            +
             | 
| 96 | 
            +
            Job status can be viewed on the web at:
         | 
| 97 | 
            +
             | 
| 98 | 
            +
             http://127.0.0.1:5000/jobs/job_detail?job_id=c571a8c7f76a4fd4a67c103d753e2dd5
         | 
| 99 | 
            +
             | 
| 100 | 
            +
            Or by running:
         | 
| 101 | 
            +
             | 
| 102 | 
            +
              mortar jobs:status c571a8c7f76a4fd4a67c103d753e2dd5 --poll
         | 
| 103 | 
            +
             | 
| 104 | 
            +
                      STDOUT
         | 
| 105 | 
            +
                    end
         | 
| 106 | 
            +
                  end
         | 
| 107 | 
            +
             | 
| 108 | 
            +
             | 
| 109 | 
            +
                  it "throws error on singlejobcluster and permanentcluster" do
         | 
| 110 | 
            +
                    with_git_initialized_project do |p|
         | 
| 111 | 
            +
             | 
| 112 | 
            +
                      write_file(File.join(p.pigscripts_path, "my_script.pig"))
         | 
| 113 | 
            +
                      stderr, stdout = execute("jobs:run my_script -2 -1 --clustersize 5 -p FIRST_PARAM=FOO -p SECOND_PARAM=BAR", p, @git)
         | 
| 114 | 
            +
                      stderr.should == <<-STDERR
         | 
| 115 | 
            +
             !    Cannot declare cluster as both --singlejobcluster and --permanentcluster
         | 
| 116 | 
            +
            STDERR
         | 
| 117 | 
            +
                    end
         | 
| 118 | 
            +
                  end
         | 
| 119 | 
            +
             | 
| 120 | 
            +
                  it "throws error on clusterid and permanentcluster" do
         | 
| 121 | 
            +
                    with_git_initialized_project do |p|
         | 
| 122 | 
            +
                      cluster_id = "e2790e7e8c7d48e39157238d58191346"
         | 
| 123 | 
            +
             | 
| 124 | 
            +
                      write_file(File.join(p.pigscripts_path, "my_script.pig"))
         | 
| 125 | 
            +
                      stderr, stdout = execute("jobs:run my_script -2 --clusterid e2790e7e8c7d48e39157238d58191346 -p FIRST_PARAM=FOO -p SECOND_PARAM=BAR", p, @git)
         | 
| 126 | 
            +
                      stderr.should == <<-STDERR
         | 
| 127 | 
            +
             !    Option permanentcluster cannot be set when running a job on an existing cluster (with --clusterid option)
         | 
| 128 | 
            +
                      STDERR
         | 
| 129 | 
            +
                    end
         | 
| 130 | 
            +
                  end
         | 
| 131 | 
            +
             | 
| 75 132 | 
             
                  it "runs a job on a new cluster" do
         | 
| 76 133 | 
             
                    with_git_initialized_project do |p|
         | 
| 77 134 | 
             
                      # stub api requests
         | 
| @@ -81,7 +138,7 @@ STDOUT | |
| 81 138 |  | 
| 82 139 | 
             
                      mock(Mortar::Auth.api).post_job_new_cluster("myproject", "my_script", is_a(String), cluster_size, 
         | 
| 83 140 | 
             
                        :parameters => match_array([{"name" => "FIRST_PARAM", "value" => "FOO"}, {"name" => "SECOND_PARAM", "value" => "BAR"}]), 
         | 
| 84 | 
            -
                        : | 
| 141 | 
            +
                        :cluster_type => Jobs::CLUSTER_TYPE__PERSISTENT,
         | 
| 85 142 | 
             
                        :notify_on_job_finish => true,
         | 
| 86 143 | 
             
                        :is_control_script=>false) {Excon::Response.new(:body => {"job_id" => job_id, "web_job_url" => job_url})}
         | 
| 87 144 |  | 
| @@ -146,7 +203,7 @@ STDOUT | |
| 146 203 | 
             
                      mock(Mortar::Auth.api).get_clusters() {Excon::Response.new(:body => {'clusters' => []})}
         | 
| 147 204 | 
             
                      mock(Mortar::Auth.api).post_job_new_cluster("myproject", "my_script", is_a(String), cluster_size, 
         | 
| 148 205 | 
             
                        :parameters => [], 
         | 
| 149 | 
            -
                        : | 
| 206 | 
            +
                        :cluster_type => Jobs::CLUSTER_TYPE__PERSISTENT,
         | 
| 150 207 | 
             
                        :notify_on_job_finish => true,
         | 
| 151 208 | 
             
                        :is_control_script=>false) {Excon::Response.new(:body => {"job_id" => job_id, "web_job_url" => job_url})}
         | 
| 152 209 |  | 
| @@ -262,11 +319,10 @@ STDOUT | |
| 262 319 | 
             
                    with_git_initialized_project do |p|
         | 
| 263 320 | 
             
                      job_id = "c571a8c7f76a4fd4a67c103d753e2dd5"
         | 
| 264 321 | 
             
                      cluster_size = 5
         | 
| 265 | 
            -
                      keepalive = true
         | 
| 266 322 |  | 
| 267 323 | 
             
                      mock(Mortar::Auth.api).post_job_new_cluster("myproject", "my_script", is_a(String), cluster_size, 
         | 
| 268 324 | 
             
                        :parameters => match_array([{"name" => "FIRST", "value" => "FOO"}, {"name" => "SECOND", "value" => "BAR"}, {"name" => "THIRD", "value" => "BEAR\n"}]), 
         | 
| 269 | 
            -
                        : | 
| 325 | 
            +
                        :cluster_type => Jobs::CLUSTER_TYPE__PERSISTENT,
         | 
| 270 326 | 
             
                        :notify_on_job_finish => true,
         | 
| 271 327 | 
             
                        :is_control_script=>false) {Excon::Response.new(:body => {"job_id" => job_id})}
         | 
| 272 328 |  | 
| @@ -288,11 +344,10 @@ PARAMS | |
| 288 344 | 
             
                    with_git_initialized_project do |p|
         | 
| 289 345 | 
             
                      job_id = "c571a8c7f76a4fd4a67c103d753e2dd5"
         | 
| 290 346 | 
             
                      cluster_size = 5
         | 
| 291 | 
            -
                      keepalive = true
         | 
| 292 347 |  | 
| 293 348 | 
             
                      mock(Mortar::Auth.api).post_job_new_cluster("myproject", "my_script", is_a(String), cluster_size, 
         | 
| 294 349 | 
             
                        :parameters => match_array([{"name" => "FIRST", "value" => "FOO"}, {"name" => "SECOND", "value" => "BAR"}, {"name" => "THIRD", "value" => "BEAR\n"}]), 
         | 
| 295 | 
            -
                        : | 
| 350 | 
            +
                        :cluster_type => Jobs::CLUSTER_TYPE__PERSISTENT,
         | 
| 296 351 | 
             
                        :notify_on_job_finish => true,
         | 
| 297 352 | 
             
                        :is_control_script=>false) {Excon::Response.new(:body => {"job_id" => job_id})}
         | 
| 298 353 |  | 
| @@ -315,7 +370,6 @@ PARAMS | |
| 315 370 | 
             
                    with_git_initialized_project do |p|
         | 
| 316 371 | 
             
                      job_id = "c571a8c7f76a4fd4a67c103d753e2dd5"
         | 
| 317 372 | 
             
                      cluster_size = 5
         | 
| 318 | 
            -
                      keepalive = true
         | 
| 319 373 |  | 
| 320 374 | 
             
                      write_file(File.join(p.pigscripts_path, "my_script.pig"))
         | 
| 321 375 |  | 
| @@ -140,6 +140,9 @@ STDERR | |
| 140 140 | 
             
                    any_instance_of(Mortar::Local::Jython) do |j|
         | 
| 141 141 | 
             
                      mock(j).install_or_update.returns(true)
         | 
| 142 142 | 
             
                    end
         | 
| 143 | 
            +
                    any_instance_of(Mortar::Local::Controller) do |j|
         | 
| 144 | 
            +
                      mock(j).ensure_local_install_dir_in_gitignore.returns(true)
         | 
| 145 | 
            +
                    end
         | 
| 143 146 | 
             
                    stderr, stdout = execute("local:configure")
         | 
| 144 147 | 
             
                    stderr.should == ""
         | 
| 145 148 | 
             
                  end
         | 
    
        metadata
    CHANGED
    
    | @@ -1,13 +1,13 @@ | |
| 1 1 | 
             
            --- !ruby/object:Gem::Specification 
         | 
| 2 2 | 
             
            name: mortar
         | 
| 3 3 | 
             
            version: !ruby/object:Gem::Version 
         | 
| 4 | 
            -
              hash:  | 
| 4 | 
            +
              hash: 5
         | 
| 5 5 | 
             
              prerelease: 
         | 
| 6 6 | 
             
              segments: 
         | 
| 7 7 | 
             
              - 0
         | 
| 8 8 | 
             
              - 7
         | 
| 9 | 
            -
              -  | 
| 10 | 
            -
              version: 0.7. | 
| 9 | 
            +
              - 3
         | 
| 10 | 
            +
              version: 0.7.3
         | 
| 11 11 | 
             
            platform: ruby
         | 
| 12 12 | 
             
            authors: 
         | 
| 13 13 | 
             
            - Mortar Data
         | 
| @@ -15,7 +15,7 @@ autorequire: | |
| 15 15 | 
             
            bindir: bin
         | 
| 16 16 | 
             
            cert_chain: []
         | 
| 17 17 |  | 
| 18 | 
            -
            date: 2013-03- | 
| 18 | 
            +
            date: 2013-03-29 00:00:00 Z
         | 
| 19 19 | 
             
            dependencies: 
         | 
| 20 20 | 
             
            - !ruby/object:Gem::Dependency 
         | 
| 21 21 | 
             
              name: mortar-api-ruby
         | 
| @@ -25,12 +25,12 @@ dependencies: | |
| 25 25 | 
             
                requirements: 
         | 
| 26 26 | 
             
                - - ~>
         | 
| 27 27 | 
             
                  - !ruby/object:Gem::Version 
         | 
| 28 | 
            -
                    hash:  | 
| 28 | 
            +
                    hash: 1
         | 
| 29 29 | 
             
                    segments: 
         | 
| 30 30 | 
             
                    - 0
         | 
| 31 31 | 
             
                    - 6
         | 
| 32 | 
            -
                    -  | 
| 33 | 
            -
                    version: 0.6. | 
| 32 | 
            +
                    - 3
         | 
| 33 | 
            +
                    version: 0.6.3
         | 
| 34 34 | 
             
              type: :runtime
         | 
| 35 35 | 
             
              version_requirements: *id001
         | 
| 36 36 | 
             
            - !ruby/object:Gem::Dependency 
         |