ruby-cute 0.13 → 0.24

Sign up to get free protection for your applications and to get access to all the features.
data/lib/cute/g5k_api.rb CHANGED
@@ -24,7 +24,7 @@ module Cute
24
24
  # - {Cute::G5K::Unauthorized} it means that there is an authentication problem.
25
25
  # - {Cute::G5K::EventTimeout} this exception is triggered by the methods that wait for events such as:
26
26
  # job submission and environment deployment.
27
- class Error < Exception
27
+ class Error < StandardError
28
28
  attr_accessor :orig # Original exception
29
29
 
30
30
  def initialize(message = nil, object = nil)
@@ -63,6 +63,7 @@ module Cute
63
63
  #
64
64
  # end
65
65
  class BadRequest < Error
66
+ attr_accessor :inner_url, :inner_code, :inner_title, :inner_message
66
67
  end
67
68
 
68
69
  # It wraps all Restclient exceptions with http codes: 403, 405,406, 412, 415, 500, 502, 503 and 504.
@@ -205,7 +206,8 @@ module Cute
205
206
  # @param user [String] user if authentication is needed
206
207
  # @param pass [String] password if authentication is needed
207
208
  # @param on_error [Symbol] option to deactivate the {Cute::G5K::RequestFailed RequestFailed} exceptions
208
- def initialize(uri,api_version,user,pass,on_error)
209
+ # @param timeout [Integer] timeout for Rest request
210
+ def initialize(uri,api_version,user,pass,on_error,timeout)
209
211
  @user = user
210
212
  @pass = pass
211
213
  @api_version = api_version.nil? ? "stable" : api_version
@@ -217,9 +219,8 @@ module Cute
217
219
  @endpoint = "https://#{user_escaped}:#{pass_escaped}@#{uri.split("https://")[1]}"
218
220
  end
219
221
 
220
- machine =`uname -ov`.chop
221
222
  @user_agent = "ruby-cute/#{VERSION} Ruby/#{RUBY_VERSION}"
222
- @api = RestClient::Resource.new(@endpoint, :timeout => 30,:verify_ssl => false)
223
+ @api = RestClient::Resource.new(@endpoint, :timeout => timeout,:verify_ssl => false)
223
224
  # some versions of restclient do not verify by default SSL certificates , :verify_ssl => true)
224
225
  # SSL verify is disabled due to Grid'5000 API certificate problem
225
226
  @on_error = on_error
@@ -241,7 +242,7 @@ module Cute
241
242
  def get_json(path)
242
243
  return G5KJSON.parse(get_raw(path))
243
244
  end
244
-
245
+
245
246
  # @return [String] the HTTP response
246
247
  # @param path [String] this complements the URI to address to a specific resource
247
248
  def get_raw(path)
@@ -320,7 +321,7 @@ module Cute
320
321
  end
321
322
 
322
323
  # Issues a Cute::G5K exception according to the http status code
323
- def handle_exception(e, req = nil)
324
+ def handle_exception(e, _req = nil)
324
325
  puts("Error: #{$!}")
325
326
  puts("Backtrace:\n\t"+e.backtrace.join("\n\t"))
326
327
  if e.respond_to? :http_code
@@ -338,11 +339,24 @@ module Cute
338
339
  case e.http_code
339
340
 
340
341
  when 400
341
- raise BadRequest.new("Bad request", e)
342
+ br = BadRequest.new("Bad request (error 400): #{e.http_body}", e)
343
+ if e.http_body =~ /^Request to ([^ ]*) failed with status 400: (.*)$/m
344
+ br.inner_url = $1
345
+ json = $2
346
+ begin
347
+ d = JSON::parse(json)
348
+ br.inner_code = d['code']
349
+ br.inner_title = d['title']
350
+ br.inner_message = d['message']
351
+ rescue JSON::ParserError
352
+ # Ignore error
353
+ end
354
+ end
355
+ raise br
342
356
  when 404
343
- raise NotFound.new("Resource not found", e)
357
+ raise NotFound.new("Resource not found (error 404): #{e.http_body}", e)
344
358
  when 401
345
- raise Unauthorized.new("Authentication problem",e)
359
+ raise Unauthorized.new("Authentication problem (error 401): #{e.http_body}",e)
346
360
  else
347
361
  if @on_error == :ignore
348
362
  return nil
@@ -555,6 +569,7 @@ module Cute
555
569
  # @option params [String] :password Password to access the REST API
556
570
  # @option params [Symbol] :on_error Set to :ignore if you want to ignore {Cute::G5K::RequestFailed ResquestFailed} exceptions.
557
571
  # @option params [Boolean] :debug Activate the debug mode
572
+ # @option params [Integer] :timeout Set the timeout in sec, default is 30 sec
558
573
  def initialize(params={})
559
574
  config = {}
560
575
  default_file = "#{ENV['HOME']}/.grid5000_api.yml"
@@ -573,9 +588,10 @@ module Cute
573
588
  @api_version = params[:version] || config["version"] || "stable"
574
589
  @logger = nil
575
590
  @debug = params[:debug] || false
591
+ @timeout = params[:timeout] || 30
576
592
 
577
593
  begin
578
- @g5k_connection = G5KRest.new(@uri,@api_version,@user,@pass,params[:on_error])
594
+ @g5k_connection = G5KRest.new(@uri,@api_version,@user,@pass,params[:on_error], @timeout)
579
595
  rescue => e
580
596
 
581
597
  msg_create_file = ""
@@ -701,7 +717,9 @@ module Cute
701
717
  # @param site [String] a valid Grid'5000 site name
702
718
  # @param uid [String] user name in Grid'5000
703
719
  # @param states [Array] or [String] jobs state: running, waiting (multiple states can be specified)
704
- def get_jobs(site, uid = nil, states = nil)
720
+ # @param details [String] pass "resources=yes to the query to get the list of resources
721
+ # @param recurse [String] after fetching the list of jobs, fetch details about each job individualy
722
+ def get_jobs(site, uid = nil, states = nil, details = false, recurse = true)
705
723
 
706
724
  parameters = []
707
725
  if states then
@@ -709,12 +727,18 @@ module Cute
709
727
  parameters.push("state=#{states.join(",")}")
710
728
  end
711
729
  parameters.push("user=#{uid}") if uid
712
- parameters.push("limit=25") if (states.nil? and uid.nil?)
730
+ parameters.push("limit=1000000")
731
+ parameters.push("resources=yes") if details
713
732
 
733
+ info(debug_cmd(api_uri("/sites/#{site}/jobs?#{parameters.join("&")}"),"GET"), :debug)
714
734
  jobs = @g5k_connection.get_json(api_uri("/sites/#{site}/jobs?#{parameters.join("&")}")).items
715
- jobs.map{ |j| @g5k_connection.get_json(j.rel_self)}
716
- # This request sometime is could take a little long when all jobs are requested
717
- # The API return by default 50 the limit was set to 25 (e.g., 23 seconds).
735
+ if recurse
736
+ jobs.map! do |j|
737
+ info(debug_cmd(j.rel_self, "GET"), :debug)
738
+ @g5k_connection.get_json(j.rel_self)
739
+ end
740
+ end
741
+ jobs.to_a
718
742
  end
719
743
 
720
744
  # @return [Hash] the last 50 deployments performed in a Grid'5000 site
@@ -976,6 +1000,7 @@ module Cute
976
1000
  # @option opts [String] :cmd The command to execute when the job starts (e.g. ./my-script.sh).
977
1001
  # @option opts [String] :cluster Valid Grid'5000 cluster
978
1002
  # @option opts [String] :queue A specific job queue
1003
+ # @option opts [String] :project A specific OAR project
979
1004
  # @option opts [Array] :subnets 1) prefix_size, 2) number of subnets
980
1005
  # @option opts [String] :env Environment name for {http://kadeploy3.gforge.inria.fr/ Kadeploy}
981
1006
  # @option opts [String] :vlan VLAN type and number: kavlan-local, kavlan, kavlan-topo, etc
@@ -990,12 +1015,12 @@ module Cute
990
1015
  # checking valid options
991
1016
  valid_opts = [:site, :cluster, :switches, :cpus, :cores, :nodes, :walltime, :cmd,
992
1017
  :type, :name, :subnets, :env, :vlan, :num_vlan,:properties, :resources,
993
- :reservation, :wait, :keys, :queue, :env_user]
1018
+ :reservation, :wait, :keys, :queue, :project, :env_user]
994
1019
  unre_opts = opts.keys - valid_opts
995
1020
  raise ArgumentError, "Unrecognized option #{unre_opts}" unless unre_opts.empty?
996
1021
 
997
1022
  nodes = opts.fetch(:nodes, 1)
998
- walltime = opts.fetch(:walltime, '01:00:00')
1023
+ walltime = opts[:walltime]
999
1024
  site = opts[:site]
1000
1025
  type = opts.fetch(:type, [])
1001
1026
  name = opts.fetch(:name, 'rubyCute job')
@@ -1013,6 +1038,7 @@ module Cute
1013
1038
  type = [type] if type.is_a?(Symbol)
1014
1039
  keys = opts[:keys]
1015
1040
  queue = opts[:queue]
1041
+ project = opts[:project]
1016
1042
  vlan = opts[:vlan]
1017
1043
  num_vlan = opts.fetch(:num_vlan, 1)
1018
1044
 
@@ -1027,14 +1053,11 @@ module Cute
1027
1053
  raise ArgumentError, "VLAN type not available in site #{site}" unless available_vlans.include?(vlan)
1028
1054
  end
1029
1055
 
1030
- raise 'At least nodes, time and site must be given' if [nodes, walltime, site].any? { |x| x.nil? }
1031
-
1032
- raise 'nodes should be an integer or a string containing either ALL or BEST' unless (nodes.is_a?(Fixnum) or ["ALL","BEST"].include?(nodes))
1056
+ raise 'At least nodes and site must be given' if [nodes, site].any? { |x| x.nil? }
1033
1057
 
1034
- secs = walltime.to_secs
1035
- walltime = walltime.to_time
1058
+ raise 'nodes should be an integer or a string containing either ALL or BEST' unless (nodes.is_a?(Integer) or ["ALL","BEST"].include?(nodes))
1036
1059
 
1037
- command = "sleep #{secs}" if command.nil?
1060
+ command = "sleep infinity" if command.nil?
1038
1061
 
1039
1062
  if resources == ""
1040
1063
  resources = "/switch=#{switches}" unless switches.nil?
@@ -1043,14 +1066,16 @@ module Cute
1043
1066
  resources += "/core=#{cores}" unless cores.nil?
1044
1067
 
1045
1068
  if cluster
1046
- resources = (cluster.is_a?(Fixnum) ? "/cluster=#{cluster}" : "{cluster='#{cluster}'}") + resources
1069
+ resources = (cluster.is_a?(Integer) ? "/cluster=#{cluster}" : "{cluster='#{cluster}'}") + resources
1047
1070
  end
1048
1071
 
1049
1072
  resources = "{type='#{vlan}'}/vlan=#{num_vlan}+" + resources unless vlan.nil?
1050
1073
  resources = "slash_#{subnets[0]}=#{subnets[1]}+" + resources unless subnets.nil?
1051
1074
  end
1052
1075
 
1053
- resources += ",walltime=#{walltime}" unless resources.include?("walltime")
1076
+ if walltime
1077
+ resources += ",walltime=#{walltime}" unless resources.include?("walltime")
1078
+ end
1054
1079
 
1055
1080
  payload = {
1056
1081
  'resources' => resources,
@@ -1058,12 +1083,13 @@ module Cute
1058
1083
  'command' => command
1059
1084
  }
1060
1085
 
1061
- info "Reserving resources: #{resources} (type: #{type}) (in #{site})"
1086
+ info "Reserving resources: #{resources} (types: #{type.join(' ')}) (in #{site})"
1062
1087
 
1063
1088
  payload['properties'] = properties unless properties.nil?
1064
1089
  payload['types'] = type.map{ |t| t.to_s} unless type.nil?
1065
1090
  type.map!{|t| t.to_sym} unless type.nil?
1066
1091
  payload['queue'] = queue if queue
1092
+ payload['project'] = project if project
1067
1093
 
1068
1094
  unless type.include?(:deploy)
1069
1095
  if opts[:keys]
@@ -1073,18 +1099,10 @@ module Cute
1073
1099
 
1074
1100
  if reservation
1075
1101
  payload['reservation'] = reservation
1076
- info "Starting this reservation at #{reservation}"
1077
1102
  end
1078
1103
 
1079
- begin
1080
- info debug_cmd(api_uri("sites/#{site}/jobs"),"POST",payload.to_json), :debug
1081
- r = @g5k_connection.post_json(api_uri("sites/#{site}/jobs"),payload) # This makes reference to the same class
1082
- rescue Error => e
1083
- info "Fail to submit job"
1084
- info e.message
1085
- e.http_body.split("\\n").each{ |line| info line}
1086
- raise
1087
- end
1104
+ info debug_cmd(api_uri("sites/#{site}/jobs"),"POST",payload.to_json), :debug
1105
+ r = @g5k_connection.post_json(api_uri("sites/#{site}/jobs"),payload) # This makes reference to the same class
1088
1106
 
1089
1107
  job = @g5k_connection.get_json(r.rel_self)
1090
1108
  job = wait_for_job(job) if opts[:wait] == true
@@ -1274,7 +1292,7 @@ module Cute
1274
1292
 
1275
1293
  job["deploy"].map!{ |d| d.refresh(@g5k_connection) }
1276
1294
 
1277
- filter.keep_if{ |k,v| v} # removes nil values
1295
+ filter.keep_if{ |_k,v| v} # removes nil values
1278
1296
  if filter.empty?
1279
1297
  status = job["deploy"].map{ |d| d["status"] }
1280
1298
  else
@@ -1352,7 +1370,7 @@ module Cute
1352
1370
  # @return [Array] machines that did not deploy successfully
1353
1371
  # @param deploy_info [Hash] deployment structure information
1354
1372
  def check_deployment(deploy_info)
1355
- deploy_info["result"].select{ |p,v| v["state"] == "KO"}.keys
1373
+ deploy_info["result"].select{ |_p,v| v["state"] == "KO"}.keys
1356
1374
  end
1357
1375
 
1358
1376
  # Returns a valid URI using the current G5K API version.
@@ -14,17 +14,18 @@ class Net::SSH::Connection::Session
14
14
  res[:stderr] = ""
15
15
  res[:exit_code] = nil
16
16
  res[:exit_signal] = nil
17
+ ts = Time::now
17
18
  open_channel do |channel|
18
- channel.exec(command) do |ch, success|
19
+ channel.exec(command) do |_ch, success|
19
20
  unless success
20
21
  abort "FAILED: couldn't execute command (ssh.channel.exec)"
21
22
  end
22
- channel.on_data do |ch,data|
23
+ channel.on_data do |_ch,data|
23
24
  print data unless o[:no_output]
24
25
  res[:stdout]+=data
25
26
  end
26
27
 
27
- channel.on_extended_data do |ch,type,data|
28
+ channel.on_extended_data do |_ch,_type,data|
28
29
  print data unless o[:no_output]
29
30
  if o[:merge_outputs]
30
31
  res[:stdout]+=data
@@ -33,14 +34,16 @@ class Net::SSH::Connection::Session
33
34
  end
34
35
  end
35
36
 
36
- channel.on_request("exit-status") do |ch,data|
37
+ channel.on_request("exit-status") do |_ch,data|
37
38
  res[:exit_code] = data.read_long
38
- puts "EXITCODE: #{res[:exit_code]}" unless o[:no_log]
39
+ d = sprintf("%.1f", Time::now - ts)
40
+ puts "EXITCODE: #{res[:exit_code]} (duration: #{d}s)" unless o[:no_log]
39
41
  end
40
42
 
41
- channel.on_request("exit-signal") do |ch, data|
43
+ channel.on_request("exit-signal") do |_ch, data|
42
44
  res[:exit_signal] = data.read_long
43
- puts "EXITSIGNAL: #{res[:exit_signal]}" unless o[:no_log]
45
+ d = sprintf("%.1f", Time::now - ts)
46
+ puts "EXITSIGNAL: #{res[:exit_signal]} (duration: #{d}s)" unless o[:no_log]
44
47
  end
45
48
  end
46
49
  end
data/lib/cute/net-ssh.rb CHANGED
@@ -115,7 +115,7 @@ module SessionActions
115
115
  Multi.logger.debug("[#{c.connection.host}] #{data.strip}")
116
116
  end
117
117
  end
118
- channel.on_extended_data do |c, type, data|
118
+ channel.on_extended_data do |c, _type, data|
119
119
  if block
120
120
  block.call(c, :stderr, data)
121
121
  else
@@ -129,7 +129,7 @@ module SessionActions
129
129
  results[c.connection.host][:status] = c[:exit_status]
130
130
  if c[:exit_status] != 0
131
131
  Multi.logger.info("execution of '#{command}' on #{c.connection.host}
132
- failed with return status #{c[:exit_status].to_s}")
132
+ failed with return status #{c[:exit_status]}")
133
133
  if results[c.connection.host][:stdout]
134
134
  Multi.logger.info("--- stdout dump ---")
135
135
  Multi.logger.info(results[c.connection.host][:stdout])
data/lib/cute/net.rb CHANGED
@@ -13,14 +13,12 @@ module Cute
13
13
  end
14
14
 
15
15
  def Network::wait_open_port(host, port, timeout = 120)
16
- def now()
17
- return Time.now.to_f
18
- end
19
- bound = now() + timeout
20
- while now() < bound do
21
- t = now()
16
+ now = -> { return Time.now.to_f }
17
+ bound = now.call + timeout
18
+ while now.call < bound do
19
+ t = now.call
22
20
  return true if port_open?(host, port)
23
- dt = now() - t
21
+ dt = now.call - t
24
22
  sleep(0.5 - dt) if dt < 0.5
25
23
  end
26
24
  return false
@@ -1,8 +1,6 @@
1
1
  module Cute
2
2
  module Synchronization
3
- require 'thread'
4
-
5
- class Semaphore
3
+ class Semaphore
6
4
  def initialize(max)
7
5
  @lock = Mutex.new
8
6
  @cond = ConditionVariable.new
data/lib/cute/taktuk.rb CHANGED
@@ -123,7 +123,6 @@ module Cute
123
123
  yield taktuk_cmd
124
124
  taktuk_cmd.loop unless taktuk_cmd.commands.empty?
125
125
  taktuk_cmd.free! if taktuk_cmd
126
- taktuk_cmd = nil
127
126
  end
128
127
  else
129
128
  return taktuk_cmd
@@ -372,9 +371,9 @@ module Cute
372
371
  def to_cmd
373
372
  self.inject([]) do |ret,val|
374
373
  if val =~ /^\[(.*)\]$/
375
- ret += ['[',Regexp.last_match(1).strip,']']
374
+ ret + ['[',Regexp.last_match(1).strip,']']
376
375
  else
377
- ret += val.split(' ')
376
+ ret + val.split(' ')
378
377
  end
379
378
  end
380
379
  end
@@ -417,7 +416,7 @@ module Cute
417
416
 
418
417
  @streams.types.each{ |name|
419
418
  @args << '-o'
420
- @args << "#{name.to_s}=#{@streams.to_cmd}"
419
+ @args << "#{name}=#{@streams.to_cmd}"
421
420
  }
422
421
 
423
422
  connector = build_connector
@@ -563,7 +562,7 @@ module Cute
563
562
  # tak.input(:file => "test_file.tar")
564
563
  def input(opts = {})
565
564
  mode = "broadcast"
566
- @commands << "#{mode} input #{opts.keys.first.to_s}"
565
+ @commands << "#{mode} input #{opts.keys.first}"
567
566
  @commands << "[ #{opts.values.first} ]"
568
567
  @commands << ';'
569
568
  end
data/lib/cute/version.rb CHANGED
@@ -1,3 +1,3 @@
1
1
  module Cute
2
- VERSION = "0.13"
2
+ VERSION = "0.24"
3
3
  end
data/ruby-cute.gemspec CHANGED
@@ -5,9 +5,9 @@ require 'cute/version'
5
5
  Gem::Specification.new do |s|
6
6
  s.name = "ruby-cute"
7
7
  s.version = Cute::VERSION
8
- s.authors = ["Algorille team"]
9
- s.email = "ruby-cute-staff@lists.gforge.inria.fr"
10
- s.homepage = "http://ruby-cute.gforge.inria.fr/"
8
+ s.authors = ["Algorille/Madynes/RESIST teams at Inria/LORIA"]
9
+ s.email = "lucas.nussbaum@inria.fr"
10
+ s.homepage = "http://ruby-cute.github.io/"
11
11
  s.summary = "Critically Useful Tools for Experiments"
12
12
  s.description = "Ruby library for controlling experiments"
13
13
  s.required_rubygems_version = ">= 1.3.6"
@@ -26,7 +26,10 @@ Gem::Specification.new do |s|
26
26
  s.add_dependency 'rest-client', '>= 1.6'
27
27
  s.add_dependency 'json', '>= 1.8'
28
28
  s.add_dependency 'ipaddress', '>= 0.8'
29
+ s.add_dependency 'net-ssh', '>= 3.2'
29
30
  s.add_dependency 'net-ssh-multi', '>= 1.2'
31
+ s.add_dependency 'net-scp', '>= 1.2'
32
+ s.add_dependency 'peach', '>= 0.5.1'
30
33
 
31
34
  s.extra_rdoc_files = ['README.md', 'LICENSE']
32
35
  s.license = 'CeCILL-B'
@@ -4,7 +4,7 @@ require 'spec_helper'
4
4
 
5
5
  describe Cute::G5K::API do
6
6
 
7
- subject { g5k = ENV['TEST_REAL'].nil?? Cute::G5K::API.new(:user => "test") : Cute::G5K::API.new() }
7
+ subject { ENV['TEST_REAL'].nil?? Cute::G5K::API.new(:user => "test") : Cute::G5K::API.new() }
8
8
 
9
9
  before :each do
10
10
  if ENV['TEST_REAL']
data/spec/g5k_api_spec.rb CHANGED
@@ -4,9 +4,9 @@ require 'spec_helper'
4
4
  describe Cute::G5K::API do
5
5
 
6
6
  if ENV['TEST_REAL']
7
- subject { g5k = ENV['DEBUG'].nil?? Cute::G5K::API.new() : Cute::G5K::API.new(:debug => true) }
7
+ subject { ENV['DEBUG'].nil?? Cute::G5K::API.new() : Cute::G5K::API.new(:debug => true) }
8
8
  else
9
- subject { g5k = ENV['DEBUG'].nil?? Cute::G5K::API.new(:user => "test") : Cute::G5K::API.new(:user => "test",:debug => true) }
9
+ subject { ENV['DEBUG'].nil?? Cute::G5K::API.new(:user => "test") : Cute::G5K::API.new(:user => "test",:debug => true) }
10
10
  end
11
11
 
12
12
  let(:sites) { subject.site_uids}
@@ -79,15 +79,6 @@ describe Cute::G5K::API do
79
79
  expect{subject.get_jobs("not-found")}.to raise_error(Cute::G5K::NotFound)
80
80
  end
81
81
 
82
- it "raises a bad request error" do
83
- expect{ subject.reserve(:site => @rand_site, :resources =>"/slash_22=1+{nonsense}")}.to raise_error(Cute::G5K::BadRequest)
84
- # expect{ subject.reserve(:site => @rand_site, :resources =>"{ib30g='YES'}/nodes=2")}.to raise_error(Cute::G5K::BadRequest)
85
- end
86
-
87
- it "raises a bad request using OAR API" do
88
- expect{subject.reserve(:site => @rand_site, :resources =>"nodes=1",:keys => "~/jobkey_nonexisting")}.to raise_error(Cute::G5K::BadRequest)
89
- end
90
-
91
82
  # it "raises an exception at deploying" do
92
83
  # expect{ subject.reserve(:site => @rand_site, :nodes => 1, :env => "nonsense")}.to raise_error(Cute::G5K::RequestFailed)
93
84
  # end
@@ -199,7 +190,6 @@ describe Cute::G5K::API do
199
190
  end
200
191
 
201
192
  it "submit and does not wait for the reservation" do
202
- cluster = subject.cluster_uids(@rand_site).first
203
193
  job = subject.reserve(:site => @rand_site, :wait => false)
204
194
  job = subject.wait_for_job(job, :wait_time => 600)
205
195
  expect(job).to include('state' => "running")
data/spec/spec_helper.rb CHANGED
@@ -30,6 +30,7 @@ class FakeG5KResponse < Hash
30
30
  'nodes' => {"node1" => {"hard"=> "alive", "soft"=>"busy"}}
31
31
  }
32
32
  def initialize(num_items = 2)
33
+ super
33
34
  MEDIA_TYPE.each { |key,value| self[key] = value}
34
35
  self['items'] = []
35
36
  num_items.times.each{ self['items'].push(MEDIA_TYPE) }
data/test/test_execute.rb CHANGED
File without changes
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: ruby-cute
3
3
  version: !ruby/object:Gem::Version
4
- version: '0.13'
4
+ version: '0.24'
5
5
  platform: ruby
6
6
  authors:
7
- - Algorille team
8
- autorequire:
7
+ - Algorille/Madynes/RESIST teams at Inria/LORIA
8
+ autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2020-03-23 00:00:00.000000000 Z
11
+ date: 2024-02-13 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: bundler
@@ -150,6 +150,20 @@ dependencies:
150
150
  - - ">="
151
151
  - !ruby/object:Gem::Version
152
152
  version: '0.8'
153
+ - !ruby/object:Gem::Dependency
154
+ name: net-ssh
155
+ requirement: !ruby/object:Gem::Requirement
156
+ requirements:
157
+ - - ">="
158
+ - !ruby/object:Gem::Version
159
+ version: '3.2'
160
+ type: :runtime
161
+ prerelease: false
162
+ version_requirements: !ruby/object:Gem::Requirement
163
+ requirements:
164
+ - - ">="
165
+ - !ruby/object:Gem::Version
166
+ version: '3.2'
153
167
  - !ruby/object:Gem::Dependency
154
168
  name: net-ssh-multi
155
169
  requirement: !ruby/object:Gem::Requirement
@@ -164,10 +178,39 @@ dependencies:
164
178
  - - ">="
165
179
  - !ruby/object:Gem::Version
166
180
  version: '1.2'
181
+ - !ruby/object:Gem::Dependency
182
+ name: net-scp
183
+ requirement: !ruby/object:Gem::Requirement
184
+ requirements:
185
+ - - ">="
186
+ - !ruby/object:Gem::Version
187
+ version: '1.2'
188
+ type: :runtime
189
+ prerelease: false
190
+ version_requirements: !ruby/object:Gem::Requirement
191
+ requirements:
192
+ - - ">="
193
+ - !ruby/object:Gem::Version
194
+ version: '1.2'
195
+ - !ruby/object:Gem::Dependency
196
+ name: peach
197
+ requirement: !ruby/object:Gem::Requirement
198
+ requirements:
199
+ - - ">="
200
+ - !ruby/object:Gem::Version
201
+ version: 0.5.1
202
+ type: :runtime
203
+ prerelease: false
204
+ version_requirements: !ruby/object:Gem::Requirement
205
+ requirements:
206
+ - - ">="
207
+ - !ruby/object:Gem::Version
208
+ version: 0.5.1
167
209
  description: Ruby library for controlling experiments
168
- email: ruby-cute-staff@lists.gforge.inria.fr
210
+ email: lucas.nussbaum@inria.fr
169
211
  executables:
170
212
  - cute
213
+ - grd
171
214
  extensions: []
172
215
  extra_rdoc_files:
173
216
  - README.md
@@ -181,8 +224,9 @@ files:
181
224
  - README.md
182
225
  - Rakefile
183
226
  - bin/cute
227
+ - bin/grd
228
+ - debian/.gitattributes
184
229
  - debian/changelog
185
- - debian/compat
186
230
  - debian/control
187
231
  - debian/copyright
188
232
  - debian/ruby-cute.docs
@@ -216,11 +260,11 @@ files:
216
260
  - spec/taktuk_spec.rb
217
261
  - test/test_bash.rb
218
262
  - test/test_execute.rb
219
- homepage: http://ruby-cute.gforge.inria.fr/
263
+ homepage: http://ruby-cute.github.io/
220
264
  licenses:
221
265
  - CeCILL-B
222
266
  metadata: {}
223
- post_install_message:
267
+ post_install_message:
224
268
  rdoc_options: []
225
269
  require_paths:
226
270
  - lib
@@ -235,9 +279,8 @@ required_rubygems_version: !ruby/object:Gem::Requirement
235
279
  - !ruby/object:Gem::Version
236
280
  version: 1.3.6
237
281
  requirements: []
238
- rubyforge_project:
239
- rubygems_version: 2.7.6.2
240
- signing_key:
282
+ rubygems_version: 3.3.15
283
+ signing_key:
241
284
  specification_version: 4
242
285
  summary: Critically Useful Tools for Experiments
243
286
  test_files:
data/debian/compat DELETED
@@ -1 +0,0 @@
1
- 8