vagrant-skytap 0.2.10 → 0.3.0

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.
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