rhc 1.19.5 → 1.20.3

Sign up to get free protection for your applications and to get access to all the features.
data/README.md CHANGED
@@ -7,8 +7,8 @@ info on installing the tool on each supported operating system.
7
7
 
8
8
  Please stop by #openshift on irc.freenode.net if you have any questions or
9
9
  comments. For more information about OpenShift, visit https://openshift.redhat.com
10
- or the OpenShift forum
11
- https://openshift.redhat.com/community/forums/openshift.
10
+ or the OpenShift support page
11
+ https://openshift.redhat.com/support.
12
12
 
13
13
 
14
14
  ## Using RHC to create an application
@@ -17,7 +17,7 @@ describe "rhc sshkey scenarios" do
17
17
  app = @domain.applications.first
18
18
  keyname = "key#{rand(1000000000000)}"
19
19
  keycontent = "principal#{rand(1000000000000)}"
20
-
20
+
21
21
  r = rhc 'sshkey', 'add', keyname, '--type', 'krb5-principal', '--content', keycontent
22
22
  r.status.should == 0
23
23
 
@@ -52,18 +52,21 @@ module RHC::Commands
52
52
  say c.description
53
53
  paragraph{ say "Tagged with: #{tags.sort.join(', ')}" } if tags.present?
54
54
  paragraph{ say format_usage_message(c) } if c.usage_rate?
55
+ paragraph{ warn "Does not receive automatic security updates" } unless c.automatic_updates?
55
56
  end
56
57
  end
57
58
  else
58
59
  say table(carts.collect do |c|
59
- [c.usage_rate? ? "#{c.name} (*)" : c.name,
60
+ [[c.name, c.usage_rate? ? " (*)" : "", c.automatic_updates? ? '' : ' (!)'].join(''),
60
61
  c.display_name,
61
- c.only_in_existing? ? 'addon' : 'web']
62
+ c.only_in_existing? ? 'addon' : 'web',
63
+ ]
62
64
  end)
63
65
  end
64
66
 
65
67
  paragraph{ say "Note: Web cartridges can only be added to new applications." }
66
- paragraph{ say "(*) denotes a cartridge with additional usage costs." } if carts.any? { |c| c.usage_rate? }
68
+ paragraph{ say "(*) denotes a cartridge with additional usage costs." } if carts.any?(&:usage_rate?)
69
+ paragraph{ say "(!) denotes a cartridge that will not receive automatic security updates." } unless options.verbose || carts.none?(&:automatic_updates?)
67
70
 
68
71
  0
69
72
  end
@@ -0,0 +1,54 @@
1
+ require 'rhc/commands/base'
2
+ require 'rhc/scp_helpers'
3
+
4
+
5
+ module RHC::Commands
6
+ class Scp < Base
7
+ suppress_wizard
8
+
9
+ summary "SCP a file to or from your application"
10
+ description <<-DESC
11
+ Transfer files to and from your applications using SCP. This will transfer
12
+ files to and from your primary gear (the one with the Git repository and web
13
+ cartridge) by default.
14
+
15
+ Examples:
16
+ Uploading a file from your workding directory to your app-root/data directory
17
+ rhc scp myapp upload somefile.txt app-root/data
18
+
19
+ Downloading a file from your app-root/data directory to your working directory
20
+ rhc scp myapp download ./ app-root/data/somebigarchive.tar.gz
21
+ DESC
22
+ syntax "[<app> --] <action> <local_path> <remote_path>"
23
+ takes_application :argument => true
24
+ argument :action, "Transfer direction: upload|download", ["-t", "--transfer_direction upload|download"], :optional => false
25
+ argument :local_path, "Local filesystem path", ["-l", "--local_path file_path"], :optional => false
26
+ argument :remote_path, "Remote filesystem path", ["-r", "--remote_path file_path"], :optional => false
27
+ alias_action 'app scp', :root_command => true
28
+ def run(_, action, local_path, remote_path)
29
+ rest_app = find_app
30
+ ssh_opts = rest_app.ssh_url.gsub("ssh://","").split("@")
31
+
32
+ raise RHC::ArgumentNotValid.new("'#{action}' is not a valid argument for this command. Please use upload or download.") unless action == 'download' || action == 'upload'
33
+ raise RHC::FileOrPathNotFound.new("Local file, file_path, or directory could not be found.") unless File.exist?(local_path)
34
+
35
+ begin
36
+ start_time = Time.now
37
+ Net::SCP.send("#{action}!".to_sym, ssh_opts[1], ssh_opts[0], (action == 'upload' ? local_path : remote_path), (action == 'upload' ? remote_path : local_path)) do |ch, name, sent, total|
38
+ #:nocov:
39
+ $stderr.print "\r #{action}ing #{name}: #{((sent.to_f/total.to_f)*100).to_i}% complete. #{sent}/#{total} bytes transferred " + (sent == total ? "in #{Time.now - start_time} seconds \n" : "")
40
+ #:nocov:
41
+ end
42
+ rescue Errno::ECONNREFUSED
43
+ raise RHC::SSHConnectionRefused.new(ssh_opts[0], ssh_opts[1])
44
+ rescue SocketError => e
45
+ raise RHC::ConnectionFailed, "The connection to #{ssh_opts[1]} failed: #{e.message}"
46
+ rescue Net::SCP::Error => e
47
+ raise RHC::RemoteFileOrPathNotFound.new("Remote file, file_path, or directory could not be found.")
48
+ end
49
+ end
50
+
51
+ protected
52
+ include RHC::SCPHelpers
53
+ end
54
+ end
@@ -230,6 +230,24 @@ module RHC
230
230
  end
231
231
  end
232
232
 
233
+ class FileOrPathNotFound < Exception
234
+ def initialize(message="File, file path, or directory could not be found")
235
+ super message
236
+ end
237
+ end
238
+
239
+ class RemoteFileOrPathNotFound < FileOrPathNotFound
240
+ def initialize(message="Remote File, file path, or directory could not be found")
241
+ super message
242
+ end
243
+ end
244
+
245
+ class ArgumentNotValid < Exception
246
+ def initialize(message="Argument is not valid for this command")
247
+ super message
248
+ end
249
+ end
250
+
233
251
  class NoDomainsForUser < Exception
234
252
  def initialize(message="In order to deploy applications, you must create a domain with 'rhc setup' or 'rhc create-domain'.")
235
253
  super message, 1
@@ -5,7 +5,7 @@ module RHC
5
5
 
6
6
  define_attr :type, :name, :display_name, :properties, :gear_profile, :status_messages, :scales_to, :scales_from, :scales_with,
7
7
  :current_scale, :supported_scales_to, :supported_scales_from, :tags, :description, :collocated_with, :base_gear_storage,
8
- :additional_gear_storage, :url, :environment_variables, :gear_size
8
+ :additional_gear_storage, :url, :environment_variables, :gear_size, :automatic_updates
9
9
 
10
10
  def scalable?
11
11
  supported_scales_to != supported_scales_from
@@ -23,6 +23,14 @@ module RHC
23
23
  type == 'embedded'
24
24
  end
25
25
 
26
+ def automatic_updates?
27
+ v = attribute(:automatic_updates)
28
+ if v.nil?
29
+ v = !(tags.include?('no_updates') || custom?)
30
+ end
31
+ v
32
+ end
33
+
26
34
  def shares_gears?
27
35
  Array(collocated_with).present?
28
36
  end
data/lib/rhc/rest/key.rb CHANGED
@@ -30,7 +30,7 @@ module RHC
30
30
  @fingerprint ||= begin
31
31
  public_key = Net::SSH::KeyFactory.load_data_public_key("#{type} #{content}")
32
32
  public_key.fingerprint
33
- rescue NotImplementedError, OpenSSL::PKey::PKeyError => e
33
+ rescue NotImplementedError, Net::SSH::Exception, OpenSSL::PKey::PKeyError
34
34
  'Invalid key'
35
35
  end if is_ssh?
36
36
  end
@@ -61,7 +61,7 @@ module RHC::Rest
61
61
  def compact_members
62
62
  arr = members.reject(&:owner?) rescue []
63
63
  if arr.length > 5
64
- arr.sort_by!(&:name)
64
+ arr = arr.sort_by(&:name)
65
65
  admin, arr = arr.partition(&:admin?)
66
66
  edit, arr = arr.partition(&:editor?)
67
67
  view, arr = arr.partition(&:viewer?)
@@ -97,7 +97,7 @@ module RHC::Rest
97
97
  end
98
98
 
99
99
  def owner
100
- if o = Array(attribute(:members)).find{ |m| m['owner'] == true }
100
+ if o = Array(attributes['members']).find{ |m| m['owner'] == true }
101
101
  o['name'] || o['login']
102
102
  end
103
103
  end
data/lib/rhc/rest/mock.rb CHANGED
@@ -697,6 +697,7 @@ module RHC::Rest::Mock
697
697
 
698
698
  def add_member(member)
699
699
  (@members ||= []) << member
700
+ (attributes['members'] ||= []) << member.attributes
700
701
  self
701
702
  end
702
703
  end
@@ -902,6 +903,7 @@ module RHC::Rest::Mock
902
903
 
903
904
  def add_member(member)
904
905
  (@members ||= []) << member
906
+ (attributes['members'] ||= []) << member.attributes
905
907
  self
906
908
  end
907
909
 
@@ -0,0 +1,27 @@
1
+ ###
2
+ # ssh_key_helpers.rb - methods to help manipulate ssh keys
3
+ #
4
+ # Copyright 2012 Red Hat, Inc. and/or its affiliates.
5
+ #
6
+ # Licensed under the Apache License, Version 2.0 (the "License");
7
+ # you may not use this file except in compliance with the License.
8
+ # You may obtain a copy of the License at
9
+ #
10
+ # http://www.apache.org/licenses/LICENSE-2.0
11
+ #
12
+ # Unless required by applicable law or agreed to in writing, software
13
+ # distributed under the License is distributed on an "AS IS" BASIS,
14
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15
+ # See the License for the specific language governing permissions and
16
+ # limitations under the License.
17
+
18
+ require 'net/ssh'
19
+ require 'net/scp'
20
+ require 'rhc/ssh_helpers'
21
+ require 'rhc/vendor/sshkey'
22
+
23
+ module RHC
24
+ module SCPHelpers
25
+ include SSHHelpers
26
+ end
27
+ end
@@ -169,7 +169,9 @@ module RHC
169
169
  def ssh_ruby(host, username, command, compression=false, request_pty=false, &block)
170
170
  debug "Opening Net::SSH connection to #{host}, #{username}, #{command}"
171
171
  exit_status = 0
172
- Net::SSH.start(host, username, :compression => compression) do |session|
172
+ options = {:compression => compression}
173
+ options[:verbose] = :debug if debug?
174
+ Net::SSH.start(host, username, options) do |session|
173
175
  #:nocov:
174
176
  channel = session.open_channel do |channel|
175
177
  if request_pty
@@ -385,7 +385,7 @@ describe RHC::Commands::Domain do
385
385
  rest_client.domains.empty?.should be_true
386
386
  end
387
387
  end
388
-
388
+
389
389
  end
390
390
 
391
391
  describe 'help' do
@@ -37,8 +37,27 @@ describe RHC::Commands::Member do
37
37
 
38
38
  let(:owner){ RHC::Rest::Membership::Member.new(:id => '1', :role => 'admin', :owner => true, :login => 'alice') }
39
39
  let(:other_admin){ RHC::Rest::Membership::Member.new(:id => '2', :role => 'admin', :login => 'Bob') }
40
- let(:other_editor){ RHC::Rest::Membership::Member.new(:id => '3', :role => 'editor', :name => 'Carol', :login => 'carol') }
41
- let(:other_viewer){ RHC::Rest::Membership::Member.new(:id => '4', :role => 'viewer', :name => 'Doug', :login => 'doug@doug.com') }
40
+ let(:other_editor){ RHC::Rest::Membership::Member.new(:id => '3', :role => 'edit', :name => 'Carol', :login => 'carol') }
41
+ let(:other_viewer){ RHC::Rest::Membership::Member.new(:id => '4', :role => 'view', :name => 'Doug', :login => 'doug@doug.com') }
42
+ let(:other_viewer2){ RHC::Rest::Membership::Member.new(:id => '5', :role => 'view', :name => 'ViewerC', :login => 'viewerc@viewer.com') }
43
+ let(:other_viewer3){ RHC::Rest::Membership::Member.new(:id => '6', :role => 'view', :name => 'ViewerB', :login => 'viewerb@viewer.com') }
44
+ let(:other_viewer4){ RHC::Rest::Membership::Member.new(:id => '7', :role => 'view', :name => 'ViewerA', :login => 'viewera@viewer.com') }
45
+
46
+ describe 'show-domain' do
47
+ context 'with members' do
48
+ let(:arguments) { ['domain', 'show', 'mock-domain-0'] }
49
+ let(:supports_members){ true }
50
+
51
+ before{ with_mock_domain.add_member(owner).add_member(other_editor).add_member(other_admin).add_member(other_viewer).add_member(other_viewer2).add_member(other_viewer3).add_member(other_viewer4) }
52
+ it { expect { run }.to exit_with_code(0) }
53
+ it { run_output.should =~ /owned by alice/ }
54
+ it { run_output.should =~ /Bob\s+\(admin\)/ }
55
+ it { run_output.should =~ /<carol>\s+\(edit\)/ }
56
+ it { run_output.should =~ /<doug@doug\.com>\s+\(view\)/ }
57
+ it("should order the members by role then by name") { run_output.should =~ /Bob.*admin.*Admins.*Carol.*Editors.*ViewerA.*ViewerB.*ViewerC.*Viewers/m }
58
+ it("should include the login value") { run_output.should =~ /alice.*Bob.*carol.*doug@doug\.com/m }
59
+ end
60
+ end
42
61
 
43
62
  describe 'list-member' do
44
63
  context 'on a domain' do
@@ -79,8 +98,8 @@ describe RHC::Commands::Member do
79
98
  it { expect { run }.to exit_with_code(0) }
80
99
  it { run_output.should =~ /alice\s+admin \(owner\)/ }
81
100
  it { run_output.should =~ /Bob\s+admin/ }
82
- it { run_output.should =~ /carol\s+editor/ }
83
- it { run_output.should =~ /doug\.com\s+viewer/ }
101
+ it { run_output.should =~ /carol\s+edit/ }
102
+ it { run_output.should =~ /doug\.com\s+view/ }
84
103
  it("should order the members by role") { run_output.should =~ /admin.*owner.*admin.*edit.*view/m }
85
104
  it("should include the login value") { run_output.should =~ /alice.*Bob.*carol.*doug@doug\.com/m }
86
105
  it("should show the name column") { run_output.should =~ /^Name\s+Login\s+Role$/ }
@@ -0,0 +1,77 @@
1
+ require 'spec_helper'
2
+ require 'rest_spec_helper'
3
+ require 'rhc/commands/scp'
4
+
5
+ describe RHC::Commands::Scp do
6
+ let!(:rest_client){ MockRestClient.new }
7
+ let!(:config){ user_config }
8
+ before{ RHC::Config.stub(:home_dir).and_return('/home/mock_user') }
9
+ before{ Kernel.stub(:exec).and_raise(RuntimeError) }
10
+
11
+ describe 'scp default' do
12
+ context 'scp' do
13
+ let(:arguments) { ['scp'] }
14
+ it { run_output.should match('Usage:') }
15
+ end
16
+ end
17
+
18
+ describe 'scp with invalid option' do
19
+ let (:arguments) {['app', 'scp', 'app1', 'invalid_command', 'file.txt', 'app-root/data']}
20
+
21
+ context 'when run' do
22
+ before(:each) do
23
+ @domain = rest_client.add_domain("mockdomain")
24
+ @domain.add_application("app1", "mock_type")
25
+ end
26
+ it { run_output.should match("'invalid_command' is not a valid argument for this command. Please use upload or download.") }
27
+ end
28
+ end
29
+
30
+ describe 'local file or path does not exist' do
31
+ let (:arguments) {['app', 'scp', 'app1', 'upload', 'file.txt', 'app-root/data']}
32
+
33
+ context 'when run' do
34
+ before(:each) do
35
+ @domain = rest_client.add_domain("mockdomain")
36
+ @domain.add_application("app1", "mock_type")
37
+ File.should_receive(:exist?).with("file.txt").once.and_return(false)
38
+ end
39
+ it { run_output.should match("Local file, file_path, or directory could not be found.") }
40
+ end
41
+ end
42
+
43
+ describe 'scp connections' do
44
+ let (:arguments) {['app', 'scp', 'app1', 'upload', 'file.txt', 'app-root/data']}
45
+
46
+ context 'connection refused' do
47
+ before(:each) do
48
+ @domain = rest_client.add_domain("mockdomain")
49
+ @domain.add_application("app1", "mock_type")
50
+ File.should_receive(:exist?).with("file.txt").once.and_return(true)
51
+ Net::SCP.should_receive("upload!".to_sym).with("127.0.0.1", "fakeuuidfortestsapp1","file.txt","app-root/data").and_raise(Errno::ECONNREFUSED)
52
+ end
53
+ it { run_output.should match("The server fakeuuidfortestsapp1 refused a connection with user 127.0.0.1. The application may be unavailable.") }
54
+ end
55
+
56
+ context 'socket error' do
57
+ before(:each) do
58
+ @domain = rest_client.add_domain("mockdomain")
59
+ @domain.add_application("app1", "mock_type")
60
+ File.should_receive(:exist?).with("file.txt").once.and_return(true)
61
+ Net::SCP.should_receive("upload!".to_sym).with("127.0.0.1", "fakeuuidfortestsapp1","file.txt","app-root/data").and_raise(SocketError)
62
+ end
63
+ it { run_output.should match("The connection to 127.0.0.1 failed: SocketError") }
64
+ end
65
+
66
+ context 'remote file not found' do
67
+ before(:each) do
68
+ @domain = rest_client.add_domain("mockdomain")
69
+ @domain.add_application("app1", "mock_type")
70
+ File.should_receive(:exist?).with("file.txt").once.and_return(true)
71
+ Net::SCP.should_receive("upload!".to_sym).with("127.0.0.1", "fakeuuidfortestsapp1","file.txt","app-root/data").and_raise(Net::SCP::Error)
72
+ end
73
+ it { run_output.should match("Remote file, file_path, or directory could not be found.") }
74
+ end
75
+ end
76
+
77
+ end
@@ -14,13 +14,13 @@ describe RHC::Commands::Sshkey do
14
14
  let(:arguments) { %w[sshkey list --noprompt --config test.conf -l test@test.foo -p password --trace] }
15
15
 
16
16
  it { expect { run }.to exit_with_code(0) }
17
-
17
+
18
18
  it { run_output.should match(/mockkey1 \(type: ssh-rsa\)/) }
19
19
  it { run_output.should match(/Fingerprint:.*0f:ce:86:80:df:a0:81:ca:db:f1:a7:0c:70:85:ce:00/) }
20
-
20
+
21
21
  it { run_output.should match(/mockkey3 \(type: krb5-principal\)/) }
22
22
  it { run_output.should match(/Principal:.* mockuser@mockdomain/) }
23
- it { run_output.should_not match(/Fingerprint:.*Invalid key/) }
23
+ # it { run_output.should match(/Fingerprint:.*Invalid key/) }
24
24
  end
25
25
  end
26
26
 
@@ -127,25 +127,25 @@ describe RHC::Commands::Sshkey do
127
127
 
128
128
  context "when adding a nonexistent key" do
129
129
  let(:arguments) { %w[sshkey add --noprompt --config test.conf -l test@test.foo -p password foobar id_rsa.pub] }
130
-
130
+
131
131
  it "exits with status code Errno::ENOENT::Errno" do
132
132
  expect { run }.to exit_with_code(128)
133
133
  end
134
134
  end
135
-
135
+
136
136
  context "when attempting to add an existing but inaccessible key" do
137
137
  let(:arguments) { %w[sshkey add --noprompt --config test.conf -l test@test.foo -p password foobar inaccessible_key.pub] }
138
-
138
+
139
139
  #before :all do
140
140
  # @inaccessible_key = 'inaccessible_key.pub'
141
141
  # File.new(@inaccessible_key, 'w+')
142
142
  # File.chmod(0000, @inaccessible_key)
143
143
  #end
144
-
144
+
145
145
  #after :all do
146
146
  # File.delete @inaccessible_key
147
147
  #end
148
-
148
+
149
149
  it "exits with status code Errno::EACCES::Errno" do
150
150
  IO.should_receive(:read).and_raise(Errno::EACCES)
151
151
  expect { run }.to exit_with_code(128)
@@ -155,7 +155,7 @@ describe RHC::Commands::Sshkey do
155
155
 
156
156
  context "when adding a key without correct arguments" do
157
157
  let(:arguments) { %w[sshkey add --noprompt --config test.conf -l test@test.foo -p password foobar] }
158
-
158
+
159
159
  it "exits with argument error" do
160
160
  expect { run }.to exit_with_code(1)
161
161
  end
@@ -1,6 +1,7 @@
1
1
  require 'spec_helper'
2
2
  require 'rhc'
3
3
  require 'rhc/ssh_helpers'
4
+ require 'rhc/scp_helpers'
4
5
  require 'rhc/cartridge_helpers'
5
6
  require 'rhc/git_helpers'
6
7
  require 'rhc/core_ext'
@@ -13,6 +14,7 @@ require 'ostruct'
13
14
  class AllRhcHelpers
14
15
  include RHC::Helpers
15
16
  include RHC::SSHHelpers
17
+ include RHC::SCPHelpers
16
18
  include RHC::CartridgeHelpers
17
19
 
18
20
  def config
@@ -23,7 +23,7 @@ class OutputTests < SimpleDelegator
23
23
  def output_no_breaks
24
24
  say "section #{next_print_num} "
25
25
  end
26
-
26
+
27
27
  def section_same_line
28
28
  section { output_no_breaks; say 'word' }
29
29
  end
metadata CHANGED
@@ -1,13 +1,13 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: rhc
3
3
  version: !ruby/object:Gem::Version
4
- hash: 81
4
+ hash: 65
5
5
  prerelease:
6
6
  segments:
7
7
  - 1
8
- - 19
9
- - 5
10
- version: 1.19.5
8
+ - 20
9
+ - 3
10
+ version: 1.20.3
11
11
  platform: ruby
12
12
  authors:
13
13
  - Red Hat
@@ -15,7 +15,7 @@ autorequire:
15
15
  bindir: bin
16
16
  cert_chain: []
17
17
 
18
- date: 2014-01-28 00:00:00 Z
18
+ date: 2014-02-24 00:00:00 Z
19
19
  dependencies:
20
20
  - !ruby/object:Gem::Dependency
21
21
  name: net-ssh
@@ -34,9 +34,25 @@ dependencies:
34
34
  type: :runtime
35
35
  version_requirements: *id001
36
36
  - !ruby/object:Gem::Dependency
37
- name: net-ssh-multi
37
+ name: net-scp
38
38
  prerelease: false
39
39
  requirement: &id002 !ruby/object:Gem::Requirement
40
+ none: false
41
+ requirements:
42
+ - - ">="
43
+ - !ruby/object:Gem::Version
44
+ hash: 23
45
+ segments:
46
+ - 1
47
+ - 1
48
+ - 2
49
+ version: 1.1.2
50
+ type: :runtime
51
+ version_requirements: *id002
52
+ - !ruby/object:Gem::Dependency
53
+ name: net-ssh-multi
54
+ prerelease: false
55
+ requirement: &id003 !ruby/object:Gem::Requirement
40
56
  none: false
41
57
  requirements:
42
58
  - - ">="
@@ -48,11 +64,11 @@ dependencies:
48
64
  - 0
49
65
  version: 1.2.0
50
66
  type: :runtime
51
- version_requirements: *id002
67
+ version_requirements: *id003
52
68
  - !ruby/object:Gem::Dependency
53
69
  name: archive-tar-minitar
54
70
  prerelease: false
55
- requirement: &id003 !ruby/object:Gem::Requirement
71
+ requirement: &id004 !ruby/object:Gem::Requirement
56
72
  none: false
57
73
  requirements:
58
74
  - - ">="
@@ -62,11 +78,11 @@ dependencies:
62
78
  - 0
63
79
  version: "0"
64
80
  type: :runtime
65
- version_requirements: *id003
81
+ version_requirements: *id004
66
82
  - !ruby/object:Gem::Dependency
67
83
  name: commander
68
84
  prerelease: false
69
- requirement: &id004 !ruby/object:Gem::Requirement
85
+ requirement: &id005 !ruby/object:Gem::Requirement
70
86
  none: false
71
87
  requirements:
72
88
  - - ">="
@@ -77,11 +93,11 @@ dependencies:
77
93
  - 0
78
94
  version: "4.0"
79
95
  type: :runtime
80
- version_requirements: *id004
96
+ version_requirements: *id005
81
97
  - !ruby/object:Gem::Dependency
82
98
  name: highline
83
99
  prerelease: false
84
- requirement: &id005 !ruby/object:Gem::Requirement
100
+ requirement: &id006 !ruby/object:Gem::Requirement
85
101
  none: false
86
102
  requirements:
87
103
  - - ~>
@@ -93,11 +109,11 @@ dependencies:
93
109
  - 11
94
110
  version: 1.6.11
95
111
  type: :runtime
96
- version_requirements: *id005
112
+ version_requirements: *id006
97
113
  - !ruby/object:Gem::Dependency
98
114
  name: httpclient
99
115
  prerelease: false
100
- requirement: &id006 !ruby/object:Gem::Requirement
116
+ requirement: &id007 !ruby/object:Gem::Requirement
101
117
  none: false
102
118
  requirements:
103
119
  - - ">="
@@ -108,11 +124,11 @@ dependencies:
108
124
  - 2
109
125
  version: "2.2"
110
126
  type: :runtime
111
- version_requirements: *id006
127
+ version_requirements: *id007
112
128
  - !ruby/object:Gem::Dependency
113
129
  name: open4
114
130
  prerelease: false
115
- requirement: &id007 !ruby/object:Gem::Requirement
131
+ requirement: &id008 !ruby/object:Gem::Requirement
116
132
  none: false
117
133
  requirements:
118
134
  - - ">="
@@ -122,11 +138,11 @@ dependencies:
122
138
  - 0
123
139
  version: "0"
124
140
  type: :runtime
125
- version_requirements: *id007
141
+ version_requirements: *id008
126
142
  - !ruby/object:Gem::Dependency
127
143
  name: rake
128
144
  prerelease: false
129
- requirement: &id008 !ruby/object:Gem::Requirement
145
+ requirement: &id009 !ruby/object:Gem::Requirement
130
146
  none: false
131
147
  requirements:
132
148
  - - ">="
@@ -138,11 +154,11 @@ dependencies:
138
154
  - 7
139
155
  version: 0.8.7
140
156
  type: :development
141
- version_requirements: *id008
157
+ version_requirements: *id009
142
158
  - !ruby/object:Gem::Dependency
143
159
  name: webmock
144
160
  prerelease: false
145
- requirement: &id009 !ruby/object:Gem::Requirement
161
+ requirement: &id010 !ruby/object:Gem::Requirement
146
162
  none: false
147
163
  requirements:
148
164
  - - <
@@ -153,11 +169,11 @@ dependencies:
153
169
  - 12
154
170
  version: "1.12"
155
171
  type: :development
156
- version_requirements: *id009
172
+ version_requirements: *id010
157
173
  - !ruby/object:Gem::Dependency
158
174
  name: rspec
159
175
  prerelease: false
160
- requirement: &id010 !ruby/object:Gem::Requirement
176
+ requirement: &id011 !ruby/object:Gem::Requirement
161
177
  none: false
162
178
  requirements:
163
179
  - - ">="
@@ -169,11 +185,11 @@ dependencies:
169
185
  - 0
170
186
  version: 2.8.0
171
187
  type: :development
172
- version_requirements: *id010
188
+ version_requirements: *id011
173
189
  - !ruby/object:Gem::Dependency
174
190
  name: fakefs
175
191
  prerelease: false
176
- requirement: &id011 !ruby/object:Gem::Requirement
192
+ requirement: &id012 !ruby/object:Gem::Requirement
177
193
  none: false
178
194
  requirements:
179
195
  - - ">="
@@ -184,11 +200,11 @@ dependencies:
184
200
  - 4
185
201
  version: "0.4"
186
202
  type: :development
187
- version_requirements: *id011
203
+ version_requirements: *id012
188
204
  - !ruby/object:Gem::Dependency
189
205
  name: thor
190
206
  prerelease: false
191
- requirement: &id012 !ruby/object:Gem::Requirement
207
+ requirement: &id013 !ruby/object:Gem::Requirement
192
208
  none: false
193
209
  requirements:
194
210
  - - ">="
@@ -198,11 +214,11 @@ dependencies:
198
214
  - 0
199
215
  version: "0"
200
216
  type: :development
201
- version_requirements: *id012
217
+ version_requirements: *id013
202
218
  - !ruby/object:Gem::Dependency
203
219
  name: cucumber
204
220
  prerelease: false
205
- requirement: &id013 !ruby/object:Gem::Requirement
221
+ requirement: &id014 !ruby/object:Gem::Requirement
206
222
  none: false
207
223
  requirements:
208
224
  - - ">="
@@ -212,11 +228,11 @@ dependencies:
212
228
  - 0
213
229
  version: "0"
214
230
  type: :development
215
- version_requirements: *id013
231
+ version_requirements: *id014
216
232
  - !ruby/object:Gem::Dependency
217
233
  name: activesupport
218
234
  prerelease: false
219
- requirement: &id014 !ruby/object:Gem::Requirement
235
+ requirement: &id015 !ruby/object:Gem::Requirement
220
236
  none: false
221
237
  requirements:
222
238
  - - ~>
@@ -227,7 +243,7 @@ dependencies:
227
243
  - 0
228
244
  version: "3.0"
229
245
  type: :development
230
- version_requirements: *id014
246
+ version_requirements: *id015
231
247
  description: The client tools for the OpenShift platform that allow for application management.
232
248
  email: dev@lists.openshift.redhat.com
233
249
  executables:
@@ -243,6 +259,7 @@ files:
243
259
  - lib/rhc/core_ext.rb
244
260
  - lib/rhc/json.rb
245
261
  - lib/rhc/wizard.rb
262
+ - lib/rhc/scp_helpers.rb
246
263
  - lib/rhc/rest.rb
247
264
  - lib/rhc/autocomplete.rb
248
265
  - lib/rhc/git_helpers.rb
@@ -258,6 +275,7 @@ files:
258
275
  - lib/rhc/commands/setup.rb
259
276
  - lib/rhc/commands/deployment.rb
260
277
  - lib/rhc/commands/tail.rb
278
+ - lib/rhc/commands/scp.rb
261
279
  - lib/rhc/commands/server.rb
262
280
  - lib/rhc/commands/ssh.rb
263
281
  - lib/rhc/commands/apps.rb
@@ -344,6 +362,7 @@ files:
344
362
  - spec/rhc/commands/tail_spec.rb
345
363
  - spec/rhc/commands/setup_spec.rb
346
364
  - spec/rhc/commands/alias_spec.rb
365
+ - spec/rhc/commands/scp_spec.rb
347
366
  - spec/rhc/commands/env_spec.rb
348
367
  - spec/rhc/commands/port_forward_spec.rb
349
368
  - spec/rhc/commands/git_clone_spec.rb
@@ -438,6 +457,7 @@ test_files:
438
457
  - spec/rhc/commands/tail_spec.rb
439
458
  - spec/rhc/commands/setup_spec.rb
440
459
  - spec/rhc/commands/alias_spec.rb
460
+ - spec/rhc/commands/scp_spec.rb
441
461
  - spec/rhc/commands/env_spec.rb
442
462
  - spec/rhc/commands/port_forward_spec.rb
443
463
  - spec/rhc/commands/git_clone_spec.rb