vagrant-skytap 0.2.10 → 0.3.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (44) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +7 -0
  3. data/lib/vagrant-skytap/action/check_created.rb +43 -0
  4. data/lib/vagrant-skytap/action/check_running.rb +43 -0
  5. data/lib/vagrant-skytap/action/get_host_vm.rb +52 -0
  6. data/lib/vagrant-skytap/action/prepare_nfs_settings.rb +22 -5
  7. data/lib/vagrant-skytap/action.rb +11 -18
  8. data/lib/vagrant-skytap/api/connectable.rb +50 -0
  9. data/lib/vagrant-skytap/api/environment.rb +10 -5
  10. data/lib/vagrant-skytap/api/interface.rb +9 -0
  11. data/lib/vagrant-skytap/api/network.rb +60 -1
  12. data/lib/vagrant-skytap/api/public_ip.rb +7 -75
  13. data/lib/vagrant-skytap/api/publish_set.rb +4 -0
  14. data/lib/vagrant-skytap/api/published_service.rb +7 -71
  15. data/lib/vagrant-skytap/api/resource.rb +25 -3
  16. data/lib/vagrant-skytap/api/tunnel.rb +69 -0
  17. data/lib/vagrant-skytap/api/vm.rb +10 -2
  18. data/lib/vagrant-skytap/api/vpn.rb +2 -106
  19. data/lib/vagrant-skytap/cap/host_metadata.rb +45 -0
  20. data/lib/vagrant-skytap/connection/public_ip_choice.rb +94 -0
  21. data/lib/vagrant-skytap/connection/published_service_choice.rb +100 -0
  22. data/lib/vagrant-skytap/connection/tunnel_choice.rb +118 -0
  23. data/lib/vagrant-skytap/connection/vpn_choice.rb +132 -0
  24. data/lib/vagrant-skytap/connection.rb +123 -0
  25. data/lib/vagrant-skytap/errors.rb +4 -0
  26. data/lib/vagrant-skytap/plugin.rb +5 -0
  27. data/lib/vagrant-skytap/setup_helper.rb +34 -8
  28. data/lib/vagrant-skytap/version.rb +1 -1
  29. data/locales/en.yml +46 -0
  30. data/spec/unit/actions/prepare_nfs_settings_spec.rb +63 -16
  31. data/spec/unit/cap/host_metadata_spec.rb +43 -0
  32. data/spec/unit/connections/public_ip_choice_spec.rb +57 -0
  33. data/spec/unit/connections/published_service_choice_spec.rb +79 -0
  34. data/spec/unit/connections/tunnel_choice_spec.rb +124 -0
  35. data/spec/unit/connections/vpn_choice_spec.rb +109 -0
  36. data/spec/unit/interface_spec.rb +53 -0
  37. data/spec/unit/network_spec.rb +123 -0
  38. data/spec/unit/setup_helper_spec.rb +59 -19
  39. data/spec/unit/support/api_responses/tunnel1.json +7 -0
  40. data/spec/unit/support/api_responses/vm1.json +12 -1
  41. data/spec/unit/support/shared/rest_api_context.rb +1 -0
  42. data/spec/unit/tunnel_spec.rb +62 -0
  43. data/spec/unit/vm_spec.rb +53 -60
  44. metadata +22 -2
@@ -21,90 +21,26 @@
21
21
  # DEALINGS IN THE SOFTWARE.
22
22
 
23
23
  require 'vagrant-skytap/api/resource'
24
-
25
- class PublishedServiceChoice
26
- attr_reader :env, :iface, :service, :execution
27
-
28
- def self.uncreated_choice(env, iface)
29
- new(env, iface, nil)
30
- end
31
-
32
- def initialize(env, iface, service=nil)
33
- @env = env
34
- @iface = iface
35
- @service = service
36
- @execution = ServiceExecution.make(env, iface, service)
37
- end
38
-
39
- def to_s
40
- execution.message
41
- end
42
-
43
- def choose
44
- execution.execute
45
- @service = execution.service
46
- [service.external_ip, service.external_port]
47
- end
48
-
49
- def valid?
50
- service.nil? || service.internal_port == 22
51
- end
52
-
53
- class ServiceExecution
54
- def self.make(env, iface, service=nil)
55
- if service
56
- UseServiceExecution.new(env, iface, service)
57
- else
58
- CreateAndUseServiceExecution.new(env, iface, service)
59
- end
60
- end
61
-
62
- attr_reader :env, :iface, :service
63
-
64
- def initialize(env, iface, service)
65
- @env = env
66
- @iface = iface
67
- @service = service
68
- end
69
- end
70
-
71
- class UseServiceExecution < ServiceExecution
72
- def message
73
- "Use published service #{service.external_ip}:#{service.external_port}"
74
- end
75
-
76
- def execute
77
- # No-op
78
- end
79
- end
80
-
81
- class CreateAndUseServiceExecution < ServiceExecution
82
- def message
83
- 'Create and use published service'
84
- end
85
-
86
- def execute
87
- @service = iface.create_published_service(22)
88
- end
89
- end
90
- end
24
+ require 'vagrant-skytap/api/connectable'
91
25
 
92
26
  module VagrantPlugins
93
27
  module Skytap
94
28
  module API
95
29
  class PublishedService < Resource
30
+ include Connectable
31
+
96
32
  attr_reader :interface
97
33
 
98
34
  reads :id, :internal_port, :external_ip, :external_port
99
35
 
36
+ def self.rest_name
37
+ "published_service"
38
+ end
39
+
100
40
  def initialize(attrs, interface, env)
101
41
  super
102
42
  @interface = interface
103
43
  end
104
-
105
- def choice_for_setup
106
- PublishedServiceChoice.new(env, self)
107
- end
108
44
  end
109
45
  end
110
46
  end
@@ -22,6 +22,8 @@
22
22
 
23
23
  require_relative 'specified_attributes'
24
24
 
25
+ # Base class for all resources accessible through the REST API.
26
+
25
27
  module VagrantPlugins
26
28
  module Skytap
27
29
  module API
@@ -31,8 +33,12 @@ module VagrantPlugins
31
33
  attr_reader :attrs, :env
32
34
 
33
35
  class << self
34
- def resource_name
35
- name.split("::").last
36
+ # Resource name suitable for use in URLs. This should be overridden
37
+ # for classes with camel-cased names (e.g., VpnAttachment).
38
+ #
39
+ # @return [String]
40
+ def rest_name
41
+ name.split("::").last.downcase
36
42
  end
37
43
  end
38
44
 
@@ -41,15 +47,27 @@ module VagrantPlugins
41
47
  @env = args.last
42
48
  end
43
49
 
50
+ # The URL for this specific instance. This method should be overridden
51
+ # for more complex routes such as Rails nested resources.
52
+ #
53
+ # @return [String]
44
54
  def url
45
- "/#{self.class.resource_name.downcase}s/#{id}"
55
+ "/#{self.class.rest_name}s/#{id}"
46
56
  end
47
57
 
58
+ # Re-fetch the object from the API and update attributes.
59
+ #
60
+ # @return [API::Resource]
48
61
  def reload
49
62
  resp = api_client.get(url)
50
63
  refresh(JSON.load(resp.body))
51
64
  end
52
65
 
66
+ # Replace the object's attributes hash. Subclasses may override this
67
+ # method to perform additional operations such as discarding cached child
68
+ # collections.
69
+ #
70
+ # @return [API::Resource]
53
71
  def refresh(attrs)
54
72
  @attrs = attrs
55
73
  self
@@ -57,6 +75,10 @@ module VagrantPlugins
57
75
 
58
76
  private
59
77
 
78
+ # Return a reference to the API client which was passed in when
79
+ # the object was created.
80
+ #
81
+ # @return [API::Client]
60
82
  def api_client
61
83
  env[:api_client]
62
84
  end
@@ -0,0 +1,69 @@
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 'vagrant-skytap/api/resource'
24
+ require 'vagrant-skytap/api/network'
25
+
26
+ # Represents an inter-configuration network routing (ICNR) tunnel,
27
+ # allowing connections between networks in two different environments.
28
+
29
+ module VagrantPlugins
30
+ module Skytap
31
+ module API
32
+ class Tunnel < Resource
33
+ reads :status
34
+ attr_reader :source_network, :target_network
35
+
36
+ class << self
37
+ # Creates a tunnel between two networks in different environments.
38
+ # The API response includes information about both networks, but
39
+ # omits their tunnel collections, so no attempt is made to update
40
+ # the network objects automatically.
41
+ #
42
+ # @param [Hash] env The environment hash
43
+ # @param [API::Network] network The network making the connection
44
+ # @param [API::Network] other_network The tunnelable network being
45
+ # connected to
46
+ # @return [API::Tunnel]
47
+ def create!(env, network, other_network)
48
+ params = {source_network_id: network.id, target_network_id: other_network.id}
49
+ resp = env[:api_client].post("/tunnels", JSON.dump(params))
50
+ new(JSON.load(resp.body), env)
51
+ end
52
+ end
53
+
54
+ def initialize(attrs, env)
55
+ super
56
+ @source_network = Network.new(get_api_attribute('source_network'), env[:environment], env)
57
+ @target_network = Network.new(get_api_attribute('target_network'), env[:environment], env)
58
+ end
59
+
60
+ # Indicates whether the tunnel is busy.
61
+ #
62
+ # @return [Boolean]
63
+ def busy?
64
+ status == "busy"
65
+ end
66
+ end
67
+ end
68
+ end
69
+ end
@@ -32,7 +32,6 @@ module VagrantPlugins
32
32
  include RunstateOperations
33
33
 
34
34
  attr_reader :provider_config
35
- attr_reader :environment
36
35
 
37
36
  reads :id, :interfaces, :credentials, :name, :configuration_url, :template_url
38
37
 
@@ -46,7 +45,7 @@ module VagrantPlugins
46
45
 
47
46
  def initialize(attrs, environment, env)
48
47
  super
49
- @environment = environment
48
+ @parent = environment
50
49
  @provider_config = env[:machine].provider_config
51
50
  end
52
51
 
@@ -62,6 +61,14 @@ module VagrantPlugins
62
61
  end
63
62
  end
64
63
 
64
+ def get_interfaces_by_id(ids)
65
+ interfaces.select{|iface| ids.include?(iface.id)}
66
+ end
67
+
68
+ def get_interface_by_id(id)
69
+ get_interfaces_by_id([id]).first
70
+ end
71
+
65
72
  def credentials
66
73
  @credentials ||= (get_api_attribute('credentials') || []).collect do |cred_attrs|
67
74
  Credentials.new(cred_attrs, self, env)
@@ -93,6 +100,7 @@ module VagrantPlugins
93
100
  def parent
94
101
  @parent ||= Environment.fetch(env, parent_url)
95
102
  end
103
+ alias_method :environment, :parent
96
104
 
97
105
  def region
98
106
  @region ||= parent.region
@@ -23,113 +23,13 @@
23
23
  require 'vagrant-skytap/util/subnet'
24
24
  require 'vagrant-skytap/api/resource'
25
25
  require 'vagrant-skytap/api/vpn_attachment'
26
-
27
- class VpnChoice
28
- attr_reader :env, :vpn, :vm, :iface, :attachment, :execution
29
-
30
- def initialize(env, vpn, vm)
31
- @env = env
32
- @vpn = vpn
33
- @vm = vm
34
- @iface = vm.interfaces.select(&:network).tap do |ifaces|
35
- unless vpn.nat_enabled?
36
- ifaces.select! {|i| vpn.subsumes?(i.network) }
37
- end
38
- end.first
39
- @execution = AttachmentExecution.make(env, vpn, iface)
40
- end
41
-
42
- def to_s
43
- "#{execution.verb} VPN: #{vpn.name}".tap do |ret|
44
- if vpn.nat_enabled?
45
- ret << " (NAT-enabled)"
46
- else
47
- ret << " (local subnet: #{vpn.local_subnet})"
48
- end
49
- end
50
- end
51
-
52
- def choose
53
- execution.execute
54
-
55
- @iface = vm.reload.interfaces.detect{|i| i.id == iface.id }
56
- host = iface.address_for(vpn)
57
- port = 22
58
-
59
- [host, port]
60
- end
61
-
62
- def valid?
63
- true
64
- end
65
-
66
- class AttachmentExecution
67
- attr_reader :env, :vpn, :iface, :attachment
68
-
69
- def self.make(env, vpn, iface)
70
- attachment = iface.attachment_for(vpn)
71
-
72
- if attachment.try(:connected?)
73
- UseAttachmentExecution.new(env, vpn, iface, attachment)
74
- elsif attachment
75
- ConnectAttachmentExecution.new(env, vpn, iface, attachment)
76
- else
77
- CreateAttachmentExecution.new(env, vpn, iface)
78
- end
79
- end
80
-
81
- def initialize(env, vpn, iface, attachment=nil)
82
- @env = env
83
- @vpn = vpn
84
- @iface = iface
85
- @attachment = attachment
86
- end
87
-
88
- def verb
89
- raise NotImplementedError.new('Must override')
90
- end
91
-
92
- def execute
93
- raise NotImplementedError.new('Must override')
94
- end
95
- end
96
-
97
- class UseAttachmentExecution < AttachmentExecution
98
- def verb
99
- 'Use'
100
- end
101
-
102
- def execute
103
- # No-op
104
- end
105
- end
106
-
107
- class ConnectAttachmentExecution < AttachmentExecution
108
- def verb
109
- 'Connect to and use'
110
- end
111
-
112
- def execute
113
- attachment.connect!
114
- end
115
- end
116
-
117
- class CreateAttachmentExecution < AttachmentExecution
118
- def verb
119
- 'Attach to and use'
120
- end
121
-
122
- def execute
123
- @attachment = VagrantPlugins::Skytap::API::VpnAttachment.create(iface.network, vpn, env)
124
- @attachment.connect!
125
- end
126
- end
127
- end
26
+ require 'vagrant-skytap/api/connectable'
128
27
 
129
28
  module VagrantPlugins
130
29
  module Skytap
131
30
  module API
132
31
  class Vpn < Resource
32
+ include Connectable
133
33
 
134
34
  class << self
135
35
  def all(env, options = {})
@@ -146,10 +46,6 @@ module VagrantPlugins
146
46
 
147
47
  reads :id, :local_subnet, :name, :nat_local_subnet
148
48
 
149
- def choice_for_setup(vm)
150
- VpnChoice.new(env, self, vm)
151
- end
152
-
153
49
  def nat_enabled?
154
50
  !!nat_local_subnet
155
51
  end
@@ -0,0 +1,45 @@
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 "socket"
24
+ require "net/http"
25
+
26
+ module VagrantPlugins
27
+ module Skytap
28
+ module Cap
29
+ module HostMetadata
30
+
31
+ # Attempt to retrieve information about the Vagrant host
32
+ # from the metadata service. If found, we're running in a
33
+ # Skytap VM.
34
+ def self.host_metadata(machine)
35
+ begin
36
+ http = Net::HTTP.new("gw", 80)
37
+ response = http.request(Net::HTTP::Get.new("/skytap"))
38
+ JSON.parse(response.body) if response.is_a?(Net::HTTPOK)
39
+ rescue SocketError, Net::HTTPNotFound => ex
40
+ end
41
+ end
42
+ end
43
+ end
44
+ end
45
+ end
@@ -0,0 +1,94 @@
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 'vagrant-skytap/connection'
24
+
25
+ module VagrantPlugins
26
+ module Skytap
27
+ module Connection
28
+ class PublicIpChoice < Choice
29
+ attr_reader :ip
30
+
31
+ def initialize(env, ip, iface)
32
+ @env = env
33
+ @ip = ip
34
+ @iface = iface
35
+ @execution = PublicIpAttachmentExecution.make(env, iface, ip)
36
+ end
37
+
38
+ def choose
39
+ execution.execute
40
+
41
+ host = ip.address
42
+ [host, DEFAULT_PORT]
43
+ end
44
+
45
+ class PublicIpAttachmentExecution < Execution
46
+ attr_reader :ip
47
+
48
+ def self.make(env, iface, ip)
49
+ if ip.attached?
50
+ UseExecution.new(env, iface, ip)
51
+ else
52
+ AttachAndUseExecution.new(env, iface, ip)
53
+ end
54
+ end
55
+
56
+ def initialize(env, iface, ip)
57
+ super
58
+ @ip = ip
59
+ end
60
+
61
+ def message
62
+ "#{verb}: #{ip.address}".tap do |ret|
63
+ if ip.deployed?
64
+ ret << " " << I18n.t("vagrant_skytap.connections.public_ip.deployed")
65
+ elsif ip.attached?
66
+ ret << " " << I18n.t("vagrant_skytap.connections.public_ip.attached")
67
+ end
68
+ end
69
+ end
70
+ end
71
+
72
+ class UseExecution < PublicIpAttachmentExecution
73
+ def verb
74
+ I18n.t("vagrant_skytap.connections.public_ip.verb_use")
75
+ end
76
+
77
+ def execute
78
+ # No-op
79
+ end
80
+ end
81
+
82
+ class AttachAndUseExecution < PublicIpAttachmentExecution
83
+ def verb
84
+ I18n.t("vagrant_skytap.connections.public_ip.verb_attach")
85
+ end
86
+
87
+ def execute
88
+ iface.attach_public_ip(ip)
89
+ end
90
+ end
91
+ end
92
+ end
93
+ end
94
+ end
@@ -0,0 +1,100 @@
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 'vagrant-skytap/connection'
24
+
25
+ module VagrantPlugins
26
+ module Skytap
27
+ module Connection
28
+ class PublishedServiceChoice < Choice
29
+ attr_reader :service
30
+
31
+ def self.uncreated_choice(env, iface)
32
+ new(env, iface, nil)
33
+ end
34
+
35
+ def initialize(env, iface, service=nil)
36
+ @env = env
37
+ @iface = iface
38
+ @service = service
39
+ @execution = PublishedServiceExecution.make(env, iface, service)
40
+ end
41
+
42
+ def choose
43
+ execution.execute
44
+ @service = execution.service
45
+ [service.external_ip, service.external_port]
46
+ end
47
+
48
+ def valid?
49
+ service.nil? || service.internal_port == DEFAULT_PORT
50
+ end
51
+
52
+ class PublishedServiceExecution < Execution
53
+ attr_reader :service
54
+
55
+ def self.make(env, iface, service=nil)
56
+ if service
57
+ UseExecution.new(env, iface, service)
58
+ else
59
+ CreateAndUseExecution.new(env, iface, service)
60
+ end
61
+ end
62
+
63
+ def initialize(env, iface, service)
64
+ @env = env
65
+ @iface = iface
66
+ @service = service
67
+ end
68
+
69
+ def message
70
+ verb.tap do |ret|
71
+ if self.is_a?(UseExecution)
72
+ ret << " #{service.external_ip}:#{service.external_port}"
73
+ end
74
+ end
75
+ end
76
+ end
77
+
78
+ class UseExecution < PublishedServiceExecution
79
+ def verb
80
+ I18n.t("vagrant_skytap.connections.published_service.verb_use")
81
+ end
82
+
83
+ def execute
84
+ # No-op
85
+ end
86
+ end
87
+
88
+ class CreateAndUseExecution < PublishedServiceExecution
89
+ def verb
90
+ I18n.t("vagrant_skytap.connections.published_service.verb_create_and_use")
91
+ end
92
+
93
+ def execute
94
+ @service = iface.create_published_service(DEFAULT_PORT)
95
+ end
96
+ end
97
+ end
98
+ end
99
+ end
100
+ end