vagrant-skytap 0.1.8 → 0.1.9

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.
@@ -9,9 +9,7 @@ module VagrantPlugins
9
9
  # This action is called to halt the remote machine.
10
10
  def self.action_halt
11
11
  Vagrant::Action::Builder.new.tap do |b|
12
- b.use ConfigValidate
13
- b.use InitializeAPIClient
14
- b.use FetchEnvironment
12
+ b.use action_fetch_environment
15
13
  b.use Call, ExistenceCheck do |env1, b1|
16
14
  case result = env1[:result]
17
15
  when :missing_environment, :missing_vm, :no_vms
@@ -26,9 +24,7 @@ module VagrantPlugins
26
24
  # This action is called to suspend the remote machine.
27
25
  def self.action_suspend
28
26
  Vagrant::Action::Builder.new.tap do |b|
29
- b.use ConfigValidate
30
- b.use InitializeAPIClient
31
- b.use FetchEnvironment
27
+ b.use action_fetch_environment
32
28
  b.use Call, ExistenceCheck do |env1, b1|
33
29
  case result = env1[:result]
34
30
  when :missing_environment, :missing_vm, :no_vms
@@ -43,9 +39,7 @@ module VagrantPlugins
43
39
  # This action is called to terminate the remote machine.
44
40
  def self.action_destroy
45
41
  Vagrant::Action::Builder.new.tap do |b|
46
- b.use ConfigValidate
47
- b.use InitializeAPIClient
48
- b.use FetchEnvironment
42
+ b.use action_fetch_environment
49
43
  b.use Call, ExistenceCheck do |env, b1|
50
44
  case existence_state = env[:result]
51
45
  when :missing_environment, :no_vms
@@ -79,9 +73,7 @@ module VagrantPlugins
79
73
  # This action is called when `vagrant provision` is called.
80
74
  def self.action_provision
81
75
  Vagrant::Action::Builder.new.tap do |b|
82
- b.use ConfigValidate
83
- b.use InitializeAPIClient
84
- b.use FetchEnvironment
76
+ b.use action_fetch_environment
85
77
  b.use Call, ExistenceCheck do |env, b1|
86
78
  case result = env[:result]
87
79
  when :missing_environment, :missing_vm, :no_vms
@@ -115,9 +107,7 @@ module VagrantPlugins
115
107
  # key.
116
108
  def self.action_read_ssh_info
117
109
  Vagrant::Action::Builder.new.tap do |b|
118
- b.use ConfigValidate
119
- b.use InitializeAPIClient
120
- b.use FetchEnvironment
110
+ b.use action_fetch_environment
121
111
  b.use ReadSSHInfo
122
112
  end
123
113
  end
@@ -127,9 +117,7 @@ module VagrantPlugins
127
117
  # key.
128
118
  def self.action_read_state
129
119
  Vagrant::Action::Builder.new.tap do |b|
130
- b.use ConfigValidate
131
- b.use InitializeAPIClient
132
- b.use FetchEnvironment
120
+ b.use action_fetch_environment
133
121
  #TODO:NLA Can this whole action be removed?
134
122
  b.use ReadState
135
123
  end
@@ -138,9 +126,7 @@ module VagrantPlugins
138
126
  # This action is called to SSH into the machine.
139
127
  def self.action_ssh
140
128
  Vagrant::Action::Builder.new.tap do |b|
141
- b.use ConfigValidate
142
- b.use InitializeAPIClient
143
- b.use FetchEnvironment
129
+ b.use action_fetch_environment
144
130
  b.use Call, ExistenceCheck do |env1, b1|
145
131
  case result = env1[:result]
146
132
  when :missing_environment, :missing_vm, :no_vms
@@ -154,9 +140,7 @@ module VagrantPlugins
154
140
 
155
141
  def self.action_ssh_run
156
142
  Vagrant::Action::Builder.new.tap do |b|
157
- b.use ConfigValidate
158
- b.use InitializeAPIClient
159
- b.use FetchEnvironment
143
+ b.use action_fetch_environment
160
144
  b.use Call, ExistenceCheck do |env1, b1|
161
145
  case result = env1[:result]
162
146
  when :missing_environment, :missing_vm, :no_vms
@@ -185,15 +169,12 @@ module VagrantPlugins
185
169
 
186
170
  def self.action_resume
187
171
  Vagrant::Action::Builder.new.tap do |b|
188
- Vagrant::Action::Builder.new.tap do |b|
189
- b.use InitializeAPIClient
190
- b.use FetchEnvironment
191
- b.use Call, IsSuspended do |env, b1|
192
- if env[:result]
193
- b1.use MessageResuming
194
- b1.use RunVm
195
- b1.use WaitForCommunicator
196
- end
172
+ b.use action_fetch_environment
173
+ b.use Call, IsSuspended do |env, b1|
174
+ if env[:result]
175
+ b1.use MessageResuming
176
+ b1.use RunVm
177
+ b1.use WaitForCommunicator
197
178
  end
198
179
  end
199
180
  end
@@ -209,9 +190,7 @@ module VagrantPlugins
209
190
  def self.action_create
210
191
  Vagrant::Action::Builder.new.tap do |b|
211
192
  b.use HandleBox
212
- b.use ConfigValidate
213
- b.use InitializeAPIClient
214
- b.use FetchEnvironment
193
+ b.use action_fetch_environment
215
194
  b.use Call, ExistenceCheck do |env, b1|
216
195
  case result = env[:result]
217
196
  when :missing_environment
@@ -277,9 +256,7 @@ module VagrantPlugins
277
256
 
278
257
  def self.action_reload
279
258
  Vagrant::Action::Builder.new.tap do |b|
280
- b.use ConfigValidate
281
- b.use InitializeAPIClient
282
- b.use FetchEnvironment
259
+ b.use action_fetch_environment
283
260
  b.use Call, ExistenceCheck do |env, b1|
284
261
  case env[:result]
285
262
  when :missing_environment, :missing_vm, :no_vms
@@ -296,6 +273,14 @@ module VagrantPlugins
296
273
  end
297
274
  end
298
275
 
276
+ def self.action_fetch_environment
277
+ Vagrant::Action::Builder.new.tap do |b|
278
+ b.use ConfigValidate
279
+ b.use InitializeAPIClient
280
+ b.use FetchEnvironment
281
+ end
282
+ end
283
+
299
284
  # The autoload farm
300
285
  action_root = Pathname.new(File.expand_path("../action", __FILE__))
301
286
  autoload :StoreExtraData, action_root.join("store_extra_data")
@@ -4,6 +4,8 @@ require 'vagrant-skytap/environment_properties'
4
4
  require 'vagrant-skytap/api/resource'
5
5
  require 'vagrant-skytap/api/vm'
6
6
  require 'vagrant-skytap/api/network'
7
+ require 'vagrant-skytap/api/publish_set'
8
+
7
9
  require_relative 'runstate_operations'
8
10
 
9
11
  module VagrantPlugins
@@ -54,8 +56,12 @@ module VagrantPlugins
54
56
  end
55
57
  end
56
58
 
59
+ def get_vms_by_id(ids=[])
60
+ vms.select{|vm| ids.include?(vm.id)}
61
+ end
62
+
57
63
  def get_vm_by_id(id)
58
- vms.find{|vm|vm.id == id}
64
+ get_vms_by_id([id]).first
59
65
  end
60
66
 
61
67
  def current_vm
@@ -68,6 +74,12 @@ module VagrantPlugins
68
74
  end
69
75
  end
70
76
 
77
+ def publish_sets
78
+ @publish_sets ||= (get_api_attribute('publish_sets') || []).collect do |ps_attrs|
79
+ PublishSet.new(ps_attrs, self, env)
80
+ end
81
+ end
82
+
71
83
  def region
72
84
  get_api_attribute('region')
73
85
  end
@@ -75,6 +87,7 @@ module VagrantPlugins
75
87
  def refresh(attrs)
76
88
  @vms = nil
77
89
  @networks = nil
90
+ @publish_sets = nil
78
91
  super
79
92
  end
80
93
 
@@ -104,6 +117,11 @@ module VagrantPlugins
104
117
  self.class.check_vm_before_adding(env, vm)
105
118
  end
106
119
 
120
+ def create_publish_set(attrs={})
121
+ resp = api_client.post("#{url}/publish_sets", JSON.dump(attrs))
122
+ PublishSet.new(JSON.load(resp.body), self, env)
123
+ end
124
+
107
125
  def properties
108
126
  @properties ||= EnvironmentProperties.new(env[:machine].env.local_data_path)
109
127
  end
@@ -0,0 +1,36 @@
1
+ require 'vagrant-skytap/api/resource'
2
+
3
+ module VagrantPlugins
4
+ module Skytap
5
+ module API
6
+ class PublishSet < Resource
7
+
8
+ attr_reader :environment
9
+ reads :id, :url, :desktops_url
10
+
11
+ def initialize(attrs, environment, env)
12
+ super
13
+ @environment = environment
14
+ end
15
+
16
+ def password_protected?
17
+ # password attribute contains asterisks or null
18
+ get_api_attribute('password').present?
19
+ end
20
+
21
+ def vm_ids
22
+ vm_refs = get_api_attribute("vms").collect{|ref| ref['vm_ref']}
23
+ vm_refs.collect{|ref| ref.match(/\/vms\/(\d+)/)}.compact.map{|match| match[1]}
24
+ end
25
+
26
+ def vms
27
+ environment.get_vms_by_id(vm_ids)
28
+ end
29
+
30
+ def delete
31
+ api_client.delete(url)
32
+ end
33
+ end
34
+ end
35
+ end
36
+ end
@@ -12,7 +12,7 @@ module VagrantPlugins
12
12
  attr_reader :provider_config
13
13
  attr_reader :environment
14
14
 
15
- reads :id, :interfaces, :credentials
15
+ reads :id, :interfaces, :credentials, :name
16
16
 
17
17
  class << self
18
18
  def fetch(env, url)
@@ -0,0 +1,14 @@
1
+ module VagrantPlugins
2
+ module Skytap
3
+ module Cap
4
+ module PublicAddress
5
+ def self.public_address(machine)
6
+ if machine.state.id == :running
7
+ ssh_info = machine.ssh_info
8
+ ssh_info[:host] if ssh_info
9
+ end
10
+ end
11
+ end
12
+ end
13
+ end
14
+ end
@@ -0,0 +1,30 @@
1
+ module VagrantPlugins
2
+ module Skytap
3
+ module Command
4
+ module Helpers
5
+ def target_vms
6
+ @target_vms ||= [].tap do |ret|
7
+ with_target_vms{|machine| ret << machine}
8
+ end
9
+ end
10
+
11
+ def fetch_environment
12
+ if machine = target_vms.first
13
+ @environment ||= machine.action(:fetch_environment)[:environment]
14
+ end
15
+ end
16
+
17
+ def target_skytap_vms
18
+ fetch_environment.get_vms_by_id(target_vms.collect(&:id))
19
+ end
20
+
21
+ def machine_names(vm_ids)
22
+ target_vms.select{|m| vm_ids.include?(m.id)}.collect{|m| m.name.to_s}
23
+ end
24
+ end
25
+ end
26
+ end
27
+ end
28
+
29
+
30
+
@@ -0,0 +1,65 @@
1
+ require 'optparse'
2
+ require 'vagrant-skytap/command/helpers'
3
+
4
+ module VagrantPlugins
5
+ module Skytap
6
+ module Command
7
+ module PublishUrl
8
+ class Create < Vagrant.plugin("2", :command)
9
+ include Command::Helpers
10
+
11
+ def execute
12
+ options = {}
13
+
14
+ opts = OptionParser.new do |o|
15
+ o.banner = "Usage: vagrant publish-url create [options]"
16
+ o.separator ""
17
+ o.separator "Options:"
18
+ o.separator ""
19
+
20
+
21
+ o.on("-p", "--password PASSWORD", "Set a password for the publish set") do |p|
22
+ options[:password] = p
23
+ end
24
+
25
+ o.on("-np", "--no-password", "Do not set a password") do |np|
26
+ options[:no_password] = true
27
+ end
28
+
29
+ o.separator ""
30
+ o.separator "You will be prompted for a password unless one of the"
31
+ o.separator "options --password or --no-password have been provided."
32
+ o.separator "Blank passwords are allowed."
33
+ o.separator ""
34
+ end
35
+
36
+ return unless argv = parse_options(opts)
37
+
38
+ unless options[:no_password] || password = options[:password]
39
+ password = @env.ui.ask("Password for publish set (will be hidden; blank for no password): ", echo: false)
40
+ end
41
+ password ||= ""
42
+
43
+ ps = fetch_environment.create_publish_set(
44
+ name: "Vagrant publish set",
45
+ publish_set_type: "single_url",
46
+ vms: target_skytap_vms.collect do |vm|
47
+ {
48
+ vm_ref: vm.url,
49
+ access: "run_and_use",
50
+ }
51
+ end,
52
+ password: password
53
+ )
54
+ @logger.debug("New publish set: #{ps.url}")
55
+
56
+ @env.ui.info(I18n.t("vagrant_skytap.commands.publish_urls.created", url: ps.desktops_url))
57
+
58
+ # Success, exit status 0
59
+ 0
60
+ end
61
+ end
62
+ end
63
+ end
64
+ end
65
+ end
@@ -0,0 +1,49 @@
1
+ require 'optparse'
2
+ require 'vagrant-skytap/command/helpers'
3
+
4
+ module VagrantPlugins
5
+ module Skytap
6
+ module Command
7
+ module PublishUrl
8
+ class Delete < Vagrant.plugin("2", :command)
9
+ include Command::Helpers
10
+
11
+ def execute
12
+ options = {}
13
+
14
+ opts = OptionParser.new do |o|
15
+ o.separator ""
16
+ o.separator "Deletes all published URLs for this project, including any"
17
+ o.separator "created through the Skytap UI."
18
+
19
+ o.banner = "Usage: vagrant publish-url delete [options]"
20
+ o.separator ""
21
+ o.separator "Options:"
22
+ o.separator ""
23
+
24
+ o.on("-f", "--force", "Delete without prompting") do |f|
25
+ options[:force] = f
26
+ end
27
+ end
28
+
29
+ return unless argv = parse_options(opts)
30
+
31
+ if publish_sets = fetch_environment.publish_sets.presence
32
+ unless options[:force]
33
+ confirm = @env.ui.ask(I18n.t("vagrant_skytap.commands.publish_urls.confirm_delete"))
34
+ return unless confirm.downcase == 'y'
35
+ end
36
+ publish_sets.each(&:delete)
37
+ @env.ui.info(I18n.t("vagrant_skytap.commands.publish_urls.deleted"))
38
+ else
39
+ @env.ui.info(I18n.t("vagrant_skytap.commands.publish_urls.empty_list"))
40
+ end
41
+
42
+ # Success, exit status 0
43
+ 0
44
+ end
45
+ end
46
+ end
47
+ end
48
+ end
49
+ end
@@ -0,0 +1,76 @@
1
+ require 'optparse'
2
+
3
+ module VagrantPlugins
4
+ module Skytap
5
+ module Command
6
+ module PublishUrl
7
+ class Root < Vagrant.plugin("2", :command)
8
+ def self.synopsis
9
+ "manages published URLs"
10
+ end
11
+
12
+ def initialize(argv, env)
13
+ super
14
+
15
+ @main_args, @sub_command, @sub_args = split_main_and_subcommand(argv)
16
+
17
+ @subcommands = Vagrant::Registry.new
18
+ @subcommands.register(:create) do
19
+ require_relative "create"
20
+ Create
21
+ end
22
+
23
+ @subcommands.register(:delete) do
24
+ require_relative "delete"
25
+ Delete
26
+ end
27
+
28
+ @subcommands.register(:show) do
29
+ require_relative "show"
30
+ Show
31
+ end
32
+ end
33
+
34
+ def execute
35
+ if @main_args.include?("-h") || @main_args.include?("--help")
36
+ # Print the help for all the box commands.
37
+ return help
38
+ end
39
+
40
+ # If we reached this far then we must have a subcommand. If not,
41
+ # then we also just print the help and exit.
42
+ command_class = @subcommands.get(@sub_command.to_sym) if @sub_command
43
+ return help if !command_class || !@sub_command
44
+ @logger.debug("Invoking command class: #{command_class} #{@sub_args.inspect}")
45
+
46
+ # Initialize and execute the command class
47
+ command_class.new(@sub_args, @env).execute
48
+ end
49
+
50
+ # Prints the help out for this command
51
+ def help
52
+ opts = OptionParser.new do |opts|
53
+ opts.banner = "Usage: vagrant publish-url <subcommand> [<args>]"
54
+ opts.separator ""
55
+ opts.separator "Available subcommands:"
56
+
57
+ # Add the available subcommands as separators in order to print them
58
+ # out as well.
59
+ keys = []
60
+ @subcommands.each { |key, value| keys << key.to_s }
61
+
62
+ keys.sort.each do |key|
63
+ opts.separator " #{key}"
64
+ end
65
+
66
+ opts.separator ""
67
+ opts.separator "For help on any individual subcommand run `vagrant publish-url <subcommand> -h`"
68
+ end
69
+
70
+ @env.ui.info(opts.help, prefix: false)
71
+ end
72
+ end
73
+ end
74
+ end
75
+ end
76
+ end
@@ -0,0 +1,29 @@
1
+ require 'vagrant-skytap/command/helpers'
2
+
3
+ module VagrantPlugins
4
+ module Skytap
5
+ module Command
6
+ module PublishUrl
7
+ class Show < Vagrant.plugin("2", :command)
8
+ include Command::Helpers
9
+
10
+ def execute
11
+ if publish_sets = fetch_environment.publish_sets.presence
12
+ results = publish_sets.collect do |ps|
13
+ "#{ps.desktops_url || 'n/a'}\n" \
14
+ " VMs: #{machine_names(ps.vm_ids).join(', ').presence || '(none)'}" \
15
+ " Password protected? #{ps.password_protected? ? 'yes' : 'no'}"
16
+ end
17
+ @env.ui.info(I18n.t("vagrant_skytap.commands.publish_urls.list", publish_urls: results.join("\n")))
18
+ else
19
+ @env.ui.info(I18n.t("vagrant_skytap.commands.publish_urls.empty_list"))
20
+ end
21
+
22
+ # Success, exit status 0
23
+ 0
24
+ end
25
+ end
26
+ end
27
+ end
28
+ end
29
+ end
@@ -36,7 +36,17 @@ module VagrantPlugins
36
36
 
37
37
  command("up", primary: true) do
38
38
  require_relative "command/up"
39
- Command::Up
39
+ Skytap::Command::Up
40
+ end
41
+
42
+ command("publish-url", primary: true) do
43
+ require_relative "command/publish_url/root"
44
+ Skytap::Command::PublishUrl::Root
45
+ end
46
+
47
+ provider_capability(:skytap, :public_address) do
48
+ require_relative "cap/public_address"
49
+ Cap::PublicAddress
40
50
  end
41
51
 
42
52
  # This initializes the internationalization strings.
@@ -1,5 +1,5 @@
1
1
  module VagrantPlugins
2
2
  module Skytap
3
- VERSION = "0.1.8"
3
+ VERSION = "0.1.9"
4
4
  end
5
5
  end
data/locales/en.yml CHANGED
@@ -136,3 +136,32 @@ en:
136
136
  long_busy: |-
137
137
  The Skytap instance is busy. Wait for the current operation to complete.
138
138
 
139
+ commands:
140
+ publish_urls:
141
+ list: |-
142
+ The VMs in this Skytap environment can be accessed through the
143
+ following published URL(s):
144
+ %{publish_urls}
145
+ empty_list: |-
146
+ No published URLs were found for this Skytap environment. Run
147
+ `vagrant publish-url create` to create one.
148
+ created: |-
149
+ This Skytap environment (or the specified subset of VMs) can be
150
+ accessed at the following URL: %{url}
151
+ Note that anyone with this URL and password will have full control
152
+ of the VMs until the published URL is deleted. (Finer-grained
153
+ control is available through the Skytap UI.)
154
+ already_exists: |-
155
+ There is already a published URL for this Skytap environment.
156
+ To modify the published URL, please delete it and create a new
157
+ one. (Finer-grained control is available through the Skytap UI.)
158
+ confirm_delete: |-
159
+ This action will delete ALL published URLs for this Skytap
160
+ environment, including those created through the Skytap UI.
161
+ Are you sure you wish to do this? [yN]
162
+ deleted: |-
163
+ All published URLs for this Skytap environment (including those
164
+ created through the Skytap UI) have been deleted. Users cannot
165
+ manage these VMs, or access them through SmartClient, unless they
166
+ have a Skytap user account with appropriate permissions.
167
+
data/spec/unit/base.rb CHANGED
@@ -23,10 +23,7 @@ require "unit/support/shared/capability_helpers_context"
23
23
  require "unit/support/shared/plugin_command_context"
24
24
  require "unit/support/shared/skytap_context"
25
25
 
26
- require "vagrant-skytap/core_ext/object/blank"
27
- require "vagrant-skytap/core_ext/object/tap"
28
- require "vagrant-skytap/core_ext/try"
29
- require "vagrant-skytap/plugin"
26
+ require "vagrant-skytap"
30
27
 
31
28
  # Do not buffer output
32
29
  $stdout.sync = true
@@ -1,7 +1,6 @@
1
1
  require_relative 'base'
2
2
  require "vagrant-skytap/api/environment"
3
3
  require "vagrant-skytap/api/vm"
4
- require "vagrant-skytap/errors"
5
4
 
6
5
  describe VagrantPlugins::Skytap::API::Environment do
7
6
  include_context "unit"
@@ -13,6 +12,7 @@ describe VagrantPlugins::Skytap::API::Environment do
13
12
  let(:network1_attrs) { JSON.load(File.read(File.join(File.expand_path('..', __FILE__), 'skeletons', 'network1.json'))) }
14
13
  let(:vpn_attachment1_attrs) { JSON.load(File.read(File.join(File.expand_path('..', __FILE__), 'skeletons', 'vpn_attachment1.json'))) }
15
14
  let(:empty_environment_attrs) { JSON.load(File.read(File.join(File.expand_path('..', __FILE__), 'skeletons', 'empty_environment.json')))}
15
+ let(:empty_publish_set_attrs) { JSON.load(File.read(File.join(File.expand_path('..', __FILE__), 'skeletons', 'empty_publish_set.json')))}
16
16
 
17
17
  let(:attrs_one_vm) do
18
18
  empty_environment_attrs.dup.tap do |ret|
@@ -26,6 +26,11 @@ describe VagrantPlugins::Skytap::API::Environment do
26
26
  let(:attrs) do
27
27
  attrs_one_vm.dup.tap do |ret|
28
28
  ret['vms'] = [vm1_attrs, vm2_attrs]
29
+ ret['publish_sets'] = [empty_publish_set_attrs.dup]
30
+ ret['publish_sets'].first['vms'] = [
31
+ {"vm_ref" => "http://example.com/vms/#{vm1_attrs['id']}"},
32
+ {"vm_ref" => "http://example.com/vms/#{vm2_attrs['id']}"}
33
+ ]
29
34
  end
30
35
  end
31
36
 
@@ -123,6 +128,13 @@ describe VagrantPlugins::Skytap::API::Environment do
123
128
  it { should be_a VagrantPlugins::Skytap::API::Network }
124
129
  end
125
130
 
131
+ describe "publish_sets" do
132
+ subject do
133
+ instance.publish_sets.first
134
+ end
135
+ it { should be_a VagrantPlugins::Skytap::API::PublishSet }
136
+ end
137
+
126
138
  describe "get_vm_by_id" do
127
139
  subject do
128
140
  instance
@@ -135,9 +147,20 @@ describe VagrantPlugins::Skytap::API::Environment do
135
147
  end
136
148
  end
137
149
 
150
+ describe "get_vms_by_id" do
151
+ subject do
152
+ instance
153
+ end
154
+
155
+ it "should return the appropriate vms from the collection" do
156
+ expect(subject.vms.count).to eq 2
157
+ expect(subject.get_vms_by_id(['6981850', '6981851']).collect(&:name)).to eq ['VM1', 'VM2']
158
+ end
159
+ end
160
+
138
161
  describe "reload" do
139
162
  subject do
140
- old_attrs = attrs_one_vm.merge('networks' => [])
163
+ old_attrs = attrs_one_vm.merge('networks' => [], 'publish_sets' => [])
141
164
  new_attrs = attrs.merge('name' => 'Environment with 2 vms')
142
165
  client = double('api_client',
143
166
  get: double('resp', body: JSON.dump(new_attrs))
@@ -146,14 +169,16 @@ describe VagrantPlugins::Skytap::API::Environment do
146
169
  described_class.new(old_attrs, myenv)
147
170
  end
148
171
 
149
- it "reloads the list of vms and networks" do
172
+ it "reloads the child objects" do
150
173
  expect(subject.name).to eq 'Environment 1'
151
174
  expect(subject.vms.count).to eq 1
152
175
  expect(subject.networks.count).to eq 0
176
+ expect(subject.publish_sets.count).to eq 0
153
177
  subject.reload
154
178
  expect(subject.name).to eq 'Environment with 2 vms'
155
179
  expect(subject.vms.count).to eq 2
156
180
  expect(subject.networks.count).to eq 1
181
+ expect(subject.publish_sets.count).to eq 1
157
182
  end
158
183
  end
159
184