vagrant-skytap 0.2.5 → 0.2.6

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.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 24c83e15798abd9dd2e7df78bd984c2768dae164
4
- data.tar.gz: 0198f2146818c63d8ef7fc0bf9808a20fdea288e
3
+ metadata.gz: df35f6df87630a3718560fe3900aa38b7eb7d946
4
+ data.tar.gz: 98caf819eed011f11be89c6072c5df6e3a8a4664
5
5
  SHA512:
6
- metadata.gz: 533b0663bcd1ceee2c749db4cc4bc95a77bb2a1a940d90422fdb118ae182b72dcf10dfc84ccde3510590193511eec4d24ae9421dbbeb4cd2c601db6a5d402804
7
- data.tar.gz: 231290cdc514f59aa84187f951a47b13742447a7a5fcfa78af9c1675c1e1efd02a4a2522c5e1f74817b39090ad10cc408b2c8c8fca031766b7ec6bbf30c8abb1
6
+ metadata.gz: d3798da927dafe1c1f69b8b2f5bbe5fb8ef8480c71fce6866f7ce268c476b7be4ce9ed0226e683e493f957d492d799c67ea9798e273f208fdce1ba32ca61c71c
7
+ data.tar.gz: 0641307fac52c06148d0554eae1455783834fe745a7bf7432086e27d9001a55660d3e3f41392df8561e69d52be4c78248954cf0aa5b981e6078f75666243747a
data/.gitignore CHANGED
@@ -19,11 +19,10 @@ Vagrantfile
19
19
  # RVM files for gemset/ruby setting
20
20
  .ruby-*
21
21
  .rvmrc
22
- .ruby-version
23
22
 
24
- # other source control
25
23
  .hg
26
24
  .hgignore
27
- .byebug_history
25
+ .agignore
26
+ .project
27
+ .ruby-version
28
28
  .project
29
- .rspec
data/CHANGELOG.md CHANGED
@@ -1,3 +1,13 @@
1
+ # 0.2.6 (February 16, 2016)
2
+
3
+ * Changes to support logging in to base boxes with the default `vagrant` user and
4
+ insecure keypair. Previously, if the SSH username and password were omitted
5
+ from the `Vagrantfile`, the user was prompted to enter them. We now default
6
+ to the `vagrant` login. If the source VM (image) has saved credentials
7
+ (a Skytap-specific feature; see [Accessing and Saving VM Credentials](http://help.skytap.com/#VM_Settings_Credentials.html))
8
+ then the user will be shown a menu of the stored credentials,
9
+ as well as an option for the default `vagrant` login.
10
+
1
11
  # 0.2.5 (February 3, 2016)
2
12
 
3
13
  * Initial push to GitHub. Random cleanup, including getting rid of some unused test files.
data/README.md CHANGED
@@ -120,8 +120,6 @@ will install the provider only. It will be necess
120
120
  ### Sharing Environments via Published URLs
121
121
  The Skytap Vagrant provider has basic support for [published URLs](http://help.skytap.com/#Published_URLs.html). Publishing an environment gives full anonymous access to the Skytap environment to anyone with the URL (and optional password). This feature differs from [Vagrant Share](https://www.vagrantup.com/docs/share/index.html) in that the user will have browser-based access to a shared view of all VMs in the environment, including details at a glance, thumbnails, and desktop access using SmartClient.
122
122
 
123
- ![Shared environment view](//help.skytap.com/Content/Resources/Images/PublishedURLView.png)
124
-
125
123
 
126
124
  A password may be specified. Anonymous access may be revoked by deleting the published URL, using the `vagrant publish-url delete` subcommand. (Skytap users with appropriate
127
125
  permissions may still access the environment through the UI if desired.)
@@ -44,7 +44,9 @@ module VagrantPlugins
44
44
  end
45
45
 
46
46
  def using_nfs?
47
- @machine.config.vm.synced_folders.any? { |_, opts| opts[:type] == :nfs }
47
+ @machine.config.vm.synced_folders.any? { |_, opts| opts[:type] == :nfs }.tap do |ret|
48
+ @logger.debug("PrepareNFSSettings#using_nfs? returning #{ret}. Synced folders: #{@machine.config.vm.synced_folders.inspect}")
49
+ end
48
50
  end
49
51
 
50
52
  # Returns the IP address of the host, preferring one on an interface which
@@ -54,7 +56,7 @@ module VagrantPlugins
54
56
  s.connect(machine.ssh_info[:host], 1)
55
57
  s.addr.last
56
58
  end.tap do |ret|
57
- @logger.debug "read_host_ip returning #{ret}"
59
+ @logger.debug("PrepareNFSSettings#read_host_ip returning #{ret}")
58
60
  end
59
61
  end
60
62
 
@@ -63,6 +63,7 @@ module VagrantPlugins
63
63
  # This action is called to terminate the remote machine.
64
64
  def self.action_destroy
65
65
  Vagrant::Action::Builder.new.tap do |b|
66
+ b.use ConfigValidate
66
67
  b.use action_fetch_environment
67
68
  b.use Call, ExistenceCheck do |env, b1|
68
69
  case existence_state = env[:result]
@@ -98,6 +99,7 @@ module VagrantPlugins
98
99
  # This action is called when `vagrant provision` is called.
99
100
  def self.action_provision
100
101
  Vagrant::Action::Builder.new.tap do |b|
102
+ b.use ConfigValidate
101
103
  b.use action_fetch_environment
102
104
  b.use Call, ExistenceCheck do |env, b1|
103
105
  case result = env[:result]
@@ -228,6 +230,7 @@ module VagrantPlugins
228
230
  def self.action_create
229
231
  Vagrant::Action::Builder.new.tap do |b|
230
232
  b.use HandleBox
233
+ b.use ConfigValidate
231
234
  b.use action_fetch_environment
232
235
  b.use ComposeEnvironment
233
236
  end
@@ -281,6 +284,7 @@ module VagrantPlugins
281
284
 
282
285
  def self.action_reload
283
286
  Vagrant::Action::Builder.new.tap do |b|
287
+ b.use ConfigValidate
284
288
  b.use action_fetch_environment
285
289
  b.use Call, ExistenceCheck do |env, b1|
286
290
  case env[:result]
@@ -300,7 +304,6 @@ module VagrantPlugins
300
304
 
301
305
  def self.action_fetch_environment
302
306
  Vagrant::Action::Builder.new.tap do |b|
303
- b.use ConfigValidate
304
307
  b.use InitializeAPIClient
305
308
  b.use FetchEnvironment
306
309
  end
@@ -66,74 +66,54 @@ module VagrantPlugins
66
66
 
67
67
  def ask_credentials
68
68
  @logger.debug("ask_credentials")
69
- return if username && password
70
69
 
71
- env[:ui].info("Note that the machine password will be stored in " \
72
- "cleartext on your local filesystem.")
73
-
74
- creds = current_vm.credentials.select(&:recognized?)
75
-
76
- if username
77
- env[:ui].info("SSH username found in Vagrantfile: #{username}")
78
- match = creds.detect{|c| c.username == username}
79
-
80
- if match
81
- @logger.info("Found username in Vagrantfile. Using matching password from credentials.")
82
- env[:ui].info("Matched SSH password in Skytap VM credentials.")
83
- @password = match.password
84
- else
85
- @logger.info("Found username in Vagrantfile. Will use manual password entry.")
86
- end
87
- elsif creds.present?
88
- question = "How do you want to choose SSH credentials for machine '#{@machine.name}'?"
89
- choices = creds.collect do |c|
90
- "Use VM credentials stored in Skytap: #{c}"
91
- end
92
- choices << 'Type credentials manually'
93
-
94
- ask_from_list(question, choices, 0) do |i|
95
- if cred = creds[i]
96
- @username = cred.username
97
- @password = cred.password
70
+ if !username
71
+ creds = current_vm.credentials.select(&:recognized?)
72
+ if creds.present?
73
+ question = "How do you want to choose SSH credentials for machine '#{@machine.name}'?\n" \
74
+ "Note that credentials retrieved from the Skytap VM will be stored in cleartext on your local filesystem."
75
+ ask_from_list(question, credentials_choices(creds), 0) do |i|
76
+ if cred = creds[i]
77
+ @username = cred.username
78
+ @password = cred.password
79
+ end
98
80
  end
81
+ else
82
+ @logger.info("No login credentials found for the VM. Allowing fallback to default vagrant login.")
99
83
  end
100
- else
101
- @logger.info("No login credentials found for the VM. Prompting for manual username/password entry.")
102
84
  end
103
-
104
- @username ||= ask_username
105
- @password ||= ask_password
85
+ [@username, @password]
106
86
  end
107
87
 
108
- def ask_username
109
- @username = ask('Enter SSH username:').strip
110
- end
111
-
112
- def ask_password
113
- @password = ask('Enter SSH password (no output will appear):', echo: false).strip
88
+ def credentials_choices(creds)
89
+ creds.collect do |c|
90
+ "Use VM credentials stored in Skytap: #{c}"
91
+ end.tap do |choices|
92
+ choices << "Don't specify credentials: Use standard 'vagrant' login with insecure keypair"
93
+ end
114
94
  end
115
95
 
116
96
  def ask_routing
117
97
  @logger.debug("ask_routing")
118
- return if host && port
119
-
120
- iface = current_vm.interfaces.first
121
- choices = connection_choices(iface).select(&:valid?)
122
- raise Errors::NoConnectionOptions unless choices.present?
123
-
124
- if vpn_url = @provider_config.vpn_url
125
- choice = choices.detect do |choice|
126
- choice.vpn && vpn_url.include?(choice.vpn.id)
98
+ unless host && port
99
+ iface = current_vm.interfaces.first
100
+ choices = connection_choices(iface).select(&:valid?)
101
+ raise Errors::NoConnectionOptions unless choices.present?
102
+
103
+ if vpn_url = @provider_config.vpn_url
104
+ choice = choices.detect do |choice|
105
+ choice.vpn && vpn_url.include?(choice.vpn.id)
106
+ end
107
+ raise Errors::DoesNotExist, object_name: vpn_url unless choice
108
+ @host, @port = choice.choose
109
+ else
110
+ question = "How do you want to connect to machine '#{@machine.name}'?"
111
+ ask_from_list(question, choices, 0) do |i, choice|
112
+ @host, @port = choice.choose
113
+ end
127
114
  end
128
- raise Errors::DoesNotExist, object_name: vpn_url unless choice
129
- @host, @port = choice.choose
130
- return
131
- end
132
-
133
- question = "How do you want to connect to machine '#{@machine.name}'?"
134
- ask_from_list(question, choices, 0) do |i, choice|
135
- @host, @port = choice.choose
136
115
  end
116
+ [@host, @port]
137
117
  end
138
118
 
139
119
  def connection_choices(iface)
@@ -22,6 +22,6 @@
22
22
 
23
23
  module VagrantPlugins
24
24
  module Skytap
25
- VERSION = "0.2.5"
25
+ VERSION = "0.2.6"
26
26
  end
27
27
  end
@@ -0,0 +1,53 @@
1
+ # Copyright (c) 2014-2016 Skytap, Inc.
2
+ #
3
+ # The MIT License (MIT)
4
+ #
5
+ # Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ # of this software and associated documentation files (the "Software"), to deal
7
+ # in the Software without restriction, including without limitation the rights
8
+ # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ # copies of the Software, and to permit persons to whom the Software is
10
+ # furnished to do so, subject to the following conditions:
11
+ #
12
+ # The above copyright notice and this permission notice shall be included in
13
+ # all copies or substantial portions of the Software.
14
+ #
15
+ # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
20
+ # FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
21
+ # DEALINGS IN THE SOFTWARE.
22
+
23
+ require_relative 'base'
24
+
25
+ describe VagrantPlugins::Skytap::API::Credentials do
26
+ include_context "rest_api"
27
+
28
+ let(:instance) { described_class.new(credential_attrs, nil, {}) }
29
+
30
+ describe "recognized?" do
31
+ subject { instance.recognized? }
32
+
33
+ context "when text is xxx/yyy" do
34
+ let(:credential_attrs) {{ "text" => "xxx/yyy" }}
35
+ it { should be true }
36
+ end
37
+
38
+ context "when text is xxx / yyy" do
39
+ let(:credential_attrs) {{ "text" => "xxx / yyy" }}
40
+ it { should be true }
41
+ end
42
+
43
+ context "when text is blank" do
44
+ let(:credential_attrs) {{ "text" => "" }}
45
+ it { should be false }
46
+ end
47
+
48
+ context "when text is xxx, yyy" do
49
+ let(:credential_attrs) {{ "text" => "xxx, yyy" }}
50
+ it { should be false }
51
+ end
52
+ end
53
+ end
@@ -22,60 +22,56 @@
22
22
 
23
23
  require_relative 'base'
24
24
  require "vagrant-skytap/setup_helper"
25
- require "vagrant-skytap/api/environment"
26
- require "vagrant-skytap/api/vpn"
27
- require "vagrant-skytap/api/vpn_attachment"
28
- require "vagrant-skytap/config"
29
25
 
30
26
  describe VagrantPlugins::Skytap::SetupHelper do
31
27
  include_context "rest_api"
32
28
 
33
- let(:instance) { described_class.new }
34
- let(:json_path) { File.join(File.expand_path('..', __FILE__), 'support', 'api_responses') }
29
+ let(:json_path) { File.join(File.expand_path('..', __FILE__), 'support', 'api_responses') }
30
+ let(:vpn_attachment_attrs) { read_json(json_path, 'vpn_attachment1.json') }
35
31
 
36
- let(:vm1_attrs) { read_json(json_path, 'vm1.json') }
37
- let(:network1_attrs) { read_json(json_path, 'network1.json') }
38
- let(:vpn1_attrs) { read_json(json_path, 'vpn1.json') }
39
- let(:vpn_attachment1_attrs) { read_json(json_path, 'vpn_attachment1.json') }
40
- let(:empty_environment_attrs) { read_json(json_path, 'empty_environment.json')}
41
-
42
- let(:network_attrs) do
43
- network1_attrs.dup.tap do |ret|
44
- ret['vpn_attachments'] = [vpn_attachment1_attrs]
32
+ let(:vm_attrs) do
33
+ read_json(json_path, 'vm1.json').tap do |ret|
34
+ ret['interfaces'].first['nat_addresses']['vpn_nat_addresses'] = {}
45
35
  end
46
36
  end
47
37
 
48
- let(:vm_attrs) do
49
- vm1_attrs.dup.tap do |ret|
50
- ret['interfaces'].first['nat_addresses']['vpn_nat_addresses'] = {}
38
+ let(:network_attrs) do
39
+ read_json(json_path, 'network1.json').tap do |ret|
40
+ ret['vpn_attachments'] = [vpn_attachment_attrs]
51
41
  end
52
42
  end
53
43
 
54
44
  let(:environment_attrs) do
55
- empty_environment_attrs.dup.tap do |ret|
56
- ret['vms'] = [vm_attrs]
57
- ret['networks'] = [network1_attrs]
45
+ read_json(json_path, 'empty_environment.json').tap do |ret|
46
+ ret['vms'] = [vm_attrs]
47
+ ret['networks'] = [network_attrs]
58
48
  end
59
49
  end
60
50
 
61
- let(:environment) { VagrantPlugins::Skytap::API::Environment.new(environment_attrs, env) }
51
+ let(:environment) do
52
+ API::Environment.new(environment_attrs, env)
53
+ end
62
54
 
63
55
  let(:vpn_attrs) do
64
- vpn1_attrs.dup.tap do |ret|
65
- ret['network_attachments'] = [vpn_attachment1_attrs]
56
+ read_json(json_path, 'vpn1.json').dup.tap do |ret|
57
+ ret['network_attachments'] = [vpn_attachment_attrs]
66
58
  end
67
59
  end
68
60
 
69
- let(:vpn) {VagrantPlugins::Skytap::API::Vpn.new(vpn_attrs, env)}
61
+ let(:vpn) {API::Vpn.new(vpn_attrs, env)}
62
+ let(:vpns) {[vpn]}
63
+ let(:vpn_choice) {double(:vpn_choice, vpn: vpn, choose: ["1.2.3.4", 22], :valid? => true)}
64
+ let(:user_input) { "" }
70
65
 
71
66
  let(:ssh_config) do
72
- double(:ssh, username: "foo", password: "bar", host: nil, port: nil)
67
+ double(:ssh_config, username: nil, password: nil, host: nil, port: nil)
73
68
  end
74
69
  let(:machine_config) do
75
70
  double(:machine_config, ssh: ssh_config)
76
71
  end
72
+ let(:vpn_url) {"/vpns/vpn-123"}
77
73
  let(:provider_config) do
78
- double(:provider_config, vm_url: "/vms/1", username: "jsmith", api_token: "123123", base_url: base_url)
74
+ double(:provider_config, vm_url: "/vms/1", username: "jsmith", api_token: "123123", base_url: base_url, vpn_url: vpn_url)
79
75
  end
80
76
  let(:api_client) { API::Client.new(provider_config) }
81
77
  let(:machine) { double(:machine, name: "vm1", id: "6981850", config: machine_config, provider_config: provider_config) }
@@ -85,48 +81,115 @@ describe VagrantPlugins::Skytap::SetupHelper do
85
81
  before :each do
86
82
  # Ensure tests are not affected by Skytap credential environment variables
87
83
  ENV.stub(:[] => nil)
88
- stub_request(:get, /.*/).to_return(body: '{}', status: 200)
89
- stub_request(:get, %r{/configurations/\d+}).to_return(body: JSON.dump(environment_attrs), status: 200)
90
- stub_request(:get, %r{/vpns$}).to_return(body: JSON.dump([vpn_attrs]), status: 200)
84
+ allow(ui).to receive(:ask).and_return(user_input)
85
+ allow(instance).to receive(:vpns).and_return(vpns)
86
+ allow(vpn).to receive(:choice_for_setup).and_return(vpn_choice)
87
+ stub_request(:get, /.*/).to_return(body: "{}", status: 200)
88
+ end
89
+
90
+ describe "connection_choices" do
91
+ subject do
92
+ instance.send(:connection_choices, instance.current_vm.interfaces.first)
93
+ end
94
+
95
+ context "when there are choices" do
96
+ it "should return a matching choice" do
97
+ expect(subject.count).to be 1
98
+ expect(subject.first.vpn).to be vpn
99
+ end
100
+ end
101
+
102
+ context "when there are no choices" do
103
+ let(:vpns) {[]}
104
+ it { should eq [] }
105
+ end
91
106
  end
92
107
 
93
108
  describe "ask_routing" do
94
109
  subject do
95
- instance
110
+ instance.send(:ask_routing)
96
111
  end
97
112
 
98
- before :each do
99
- allow(subject).to receive(:vpns).and_return([vpn])
113
+ context "when valid vpn_url specified" do
114
+ it {should eq ["1.2.3.4", 22]}
100
115
  end
101
116
 
102
- after(:each) do
103
- allow_any_instance_of(VpnChoice).to receive(:choose).and_call_original
117
+ context "when invalid vpn_url specified" do
118
+ let(:vpn_url) {"bogus"}
119
+ it "raises error" do
120
+ expect{subject}.to raise_error Errors::DoesNotExist
121
+ end
104
122
  end
105
123
 
106
- it "has connection_choices" do
107
- interface = subject.current_vm.interfaces.first
108
- choices = subject.send(:connection_choices, interface)
109
- expect(choices.count).to eq 1
110
- expect(choices.first.vpn).to_not be_nil
124
+ context "when vpn_url unspecified" do
125
+ let(:vpn_url) {nil}
126
+ let(:user_input) {"1"}
127
+ it {should eq ["1.2.3.4", 22]}
111
128
  end
112
129
 
113
- it "does not show choices if vpn_url specified" do
114
- allow(provider_config).to receive(:vpn_url).and_return(vpn.url)
115
- vpn_choice = double(:choice, vpn: vpn, choose: ['1.2.3.4', 22], :valid? => true)
116
- allow(vpn).to receive(:choice_for_setup).and_return(vpn_choice)
117
- expect(subject).not_to receive(:ask_from_list)
118
- subject.send(:ask_routing)
130
+ context "when no valid vpns exist" do
131
+ before do
132
+ allow(vpn_choice).to receive(:valid?).and_return(false)
133
+ end
134
+ it "raises error" do
135
+ expect{subject}.to raise_error Errors::NoConnectionOptions
136
+ end
119
137
  end
138
+ end
120
139
 
121
- it "raises DoesNotExist if non-existent vpn_url specified" do
122
- allow(provider_config).to receive(:vpn_url).and_return("bogus")
123
- expect{subject.send(:ask_routing)}.to raise_error(Errors::DoesNotExist)
140
+ describe "ask_credentials" do
141
+ subject do
142
+ instance.send(:ask_credentials)
124
143
  end
125
144
 
126
- it "shows choices if vpn_url unspecified" do
127
- allow(provider_config).to receive(:vpn_url).and_return(nil)
128
- expect(subject).to receive(:ask_from_list)
129
- subject.send(:ask_routing)
145
+ context "when username and password are set" do
146
+ let(:ssh_config) {double(:ssh_config, username: "foo", password: "bar", host: nil, port: nil)}
147
+ it {should eq %w[foo bar]}
148
+ end
149
+
150
+ context "when only username is set and it matches a set of stored credentials" do
151
+ let(:ssh_config) {double(:ssh_config, username: "skytap", password: nil, host: nil, port: nil)}
152
+ it {should eq ["skytap", nil]}
153
+ end
154
+
155
+ context "when username and password are not set but stored credentials exist" do
156
+ let(:user_input) {"1"}
157
+ it {should eq %w[skytap skypass]}
158
+ end
159
+
160
+ context "when username and password are not set and no stored credentials exist" do
161
+ before do
162
+ allow(instance.current_vm).to receive(:credentials).and_return([])
163
+ end
164
+ it {should eq [nil, nil]}
165
+ end
166
+ end
167
+
168
+ describe "ask_from_list" do
169
+ subject do
170
+ instance.send(:ask_from_list, "Prompt", ["aaa", "bbb"], 0)
171
+ end
172
+
173
+ context "when user enters nothing" do
174
+ let(:user_input) {""}
175
+ it {should eq 0}
176
+ end
177
+
178
+ context "when user enters numeral" do
179
+ let(:user_input) {" 2 "}
180
+ it {should eq 1}
181
+ end
182
+ end
183
+
184
+ describe "credentials_choices" do
185
+ subject do
186
+ instance.send(:credentials_choices, instance.current_vm.credentials)
187
+ end
188
+ it "returns a list of the vm's credentials plus the default vagrant login" do
189
+ expect(subject).to eq([
190
+ "Use VM credentials stored in Skytap: skytap / skypass",
191
+ "Don't specify credentials: Use standard 'vagrant' login with insecure keypair"
192
+ ])
130
193
  end
131
194
  end
132
195
  end
@@ -72,7 +72,7 @@
72
72
  "credentials": [
73
73
  {
74
74
  "id": "5695620",
75
- "text": "xxx / yyy"
75
+ "text": "skytap / skypass"
76
76
  }
77
77
  ],
78
78
  "desktop_resizable": true,
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: vagrant-skytap
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.2.5
4
+ version: 0.2.6
5
5
  platform: ruby
6
6
  authors:
7
7
  - Eric True
@@ -9,7 +9,7 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2016-02-04 00:00:00.000000000 Z
12
+ date: 2016-02-17 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: json_pure
@@ -216,6 +216,7 @@ files:
216
216
  - spec/unit/actions/update_hardware_spec.rb
217
217
  - spec/unit/base.rb
218
218
  - spec/unit/config_spec.rb
219
+ - spec/unit/credentials_spec.rb
219
220
  - spec/unit/environment_spec.rb
220
221
  - spec/unit/forwarded_port_spec.rb
221
222
  - spec/unit/hosts/common/cap/ssh_tunnel_spec.rb