vagrant-skytap 0.1.1a
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/.gitignore +21 -0
- data/.hgignore +22 -0
- data/.project +11 -0
- data/.rspec +1 -0
- data/CHANGELOG.md +85 -0
- data/Gemfile +29 -0
- data/LICENSE +8 -0
- data/README.md +292 -0
- data/Rakefile +31 -0
- data/Vagrantfile.orig +34 -0
- data/bar/checksums.yaml +7 -0
- data/bar/data.tar +0 -0
- data/bar/metadata +242 -0
- data/dummy.box +0 -0
- data/example_box/README.md +13 -0
- data/example_box/metadata.json +3 -0
- data/lib/vagrant-skytap/action/add_vm_to_environment.rb +35 -0
- data/lib/vagrant-skytap/action/create_environment.rb +44 -0
- data/lib/vagrant-skytap/action/delete_environment.rb +26 -0
- data/lib/vagrant-skytap/action/delete_vm.rb +27 -0
- data/lib/vagrant-skytap/action/existence_check.rb +35 -0
- data/lib/vagrant-skytap/action/fetch_environment.rb +32 -0
- data/lib/vagrant-skytap/action/initialize_api_client.rb +28 -0
- data/lib/vagrant-skytap/action/is_running.rb +19 -0
- data/lib/vagrant-skytap/action/is_stopped.rb +19 -0
- data/lib/vagrant-skytap/action/is_suspended.rb +19 -0
- data/lib/vagrant-skytap/action/message_already_created.rb +16 -0
- data/lib/vagrant-skytap/action/message_already_running.rb +16 -0
- data/lib/vagrant-skytap/action/message_environment_url.rb +16 -0
- data/lib/vagrant-skytap/action/message_not_created.rb +16 -0
- data/lib/vagrant-skytap/action/message_will_not_destroy.rb +16 -0
- data/lib/vagrant-skytap/action/mixin_machine_index.rb +22 -0
- data/lib/vagrant-skytap/action/prepare_nfs_settings.rb +46 -0
- data/lib/vagrant-skytap/action/prepare_nfs_valid_ids.rb +28 -0
- data/lib/vagrant-skytap/action/read_ssh_info.rb +23 -0
- data/lib/vagrant-skytap/action/read_state.rb +42 -0
- data/lib/vagrant-skytap/action/run_environment.rb +53 -0
- data/lib/vagrant-skytap/action/run_vm.rb +51 -0
- data/lib/vagrant-skytap/action/set_hostname.rb +31 -0
- data/lib/vagrant-skytap/action/set_up_vm.rb +21 -0
- data/lib/vagrant-skytap/action/stop_environment.rb +43 -0
- data/lib/vagrant-skytap/action/stop_vm.rb +43 -0
- data/lib/vagrant-skytap/action/store_extra_data.rb +35 -0
- data/lib/vagrant-skytap/action/suspend_environment.rb +32 -0
- data/lib/vagrant-skytap/action/suspend_vm.rb +32 -0
- data/lib/vagrant-skytap/action/timed_provision.rb +21 -0
- data/lib/vagrant-skytap/action/update_hardware.rb +37 -0
- data/lib/vagrant-skytap/action.rb +272 -0
- data/lib/vagrant-skytap/api/busyable.rb +37 -0
- data/lib/vagrant-skytap/api/client.rb +127 -0
- data/lib/vagrant-skytap/api/credentials.rb +41 -0
- data/lib/vagrant-skytap/api/environment.rb +99 -0
- data/lib/vagrant-skytap/api/interface.rb +123 -0
- data/lib/vagrant-skytap/api/network.rb +40 -0
- data/lib/vagrant-skytap/api/public_ip.rb +103 -0
- data/lib/vagrant-skytap/api/published_service.rb +90 -0
- data/lib/vagrant-skytap/api/resource.rb +44 -0
- data/lib/vagrant-skytap/api/runstate_operations.rb +63 -0
- data/lib/vagrant-skytap/api/specified_attributes.rb +27 -0
- data/lib/vagrant-skytap/api/vm.rb +88 -0
- data/lib/vagrant-skytap/api/vpn.rb +146 -0
- data/lib/vagrant-skytap/api/vpn_attachment.rb +57 -0
- data/lib/vagrant-skytap/config.rb +106 -0
- data/lib/vagrant-skytap/core_ext/object/blank.rb +82 -0
- data/lib/vagrant-skytap/core_ext/object/tap.rb +8 -0
- data/lib/vagrant-skytap/core_ext/try.rb +42 -0
- data/lib/vagrant-skytap/environment_properties.rb +11 -0
- data/lib/vagrant-skytap/errors.rb +59 -0
- data/lib/vagrant-skytap/plugin.rb +73 -0
- data/lib/vagrant-skytap/properties.rb +42 -0
- data/lib/vagrant-skytap/provider.rb +50 -0
- data/lib/vagrant-skytap/setup_helper.rb +193 -0
- data/lib/vagrant-skytap/util/ip_address.rb +69 -0
- data/lib/vagrant-skytap/util/subnet.rb +97 -0
- data/lib/vagrant-skytap/util/timer.rb +17 -0
- data/lib/vagrant-skytap/version.rb +5 -0
- data/lib/vagrant-skytap/version.rb.orig +5 -0
- data/lib/vagrant-skytap/vm_properties.rb +22 -0
- data/lib/vagrant-skytap.rb +23 -0
- data/locales/en.yml +127 -0
- data/skytap-dummy.box +0 -0
- data/spec/acceptance/base.rb +2 -0
- data/spec/acceptance/provider/halt_spec.rb +3 -0
- data/spec/acceptance/shared/context_skytap.rb +3 -0
- data/spec/spec_helper.rb +1 -0
- data/spec/support/isolated_environment.rb +45 -0
- data/spec/unit/base.rb +57 -0
- data/spec/unit/config_spec.rb +73 -0
- data/spec/unit/environment_spec.rb +144 -0
- data/spec/unit/skeletons/empty_environment.json +19 -0
- data/spec/unit/skeletons/network1.json +36 -0
- data/spec/unit/skeletons/vm1.json +85 -0
- data/spec/unit/support/dummy_communicator.rb +83 -0
- data/spec/unit/support/dummy_provider.rb +41 -0
- data/spec/unit/support/isolated_environment.rb +217 -0
- data/spec/unit/support/shared/action_synced_folders_context.rb +15 -0
- data/spec/unit/support/shared/base_context.rb +116 -0
- data/spec/unit/support/shared/capability_helpers_context.rb +29 -0
- data/spec/unit/support/shared/plugin_command_context.rb +12 -0
- data/spec/unit/support/shared/skytap_context.rb +3 -0
- data/spec/unit/vm_spec.rb +118 -0
- data/tasks/acceptance.rake +22 -0
- data/tasks/bundler.rake +3 -0
- data/tasks/test.rake +14 -0
- data/vagrant-skytap.gemspec +62 -0
- data/vagrant-spec.config.rb +10 -0
- metadata +247 -0
@@ -0,0 +1,144 @@
|
|
1
|
+
require_relative 'base'
|
2
|
+
require "vagrant-skytap/api/environment"
|
3
|
+
|
4
|
+
describe VagrantPlugins::Skytap::API::Environment do
|
5
|
+
include_context "unit"
|
6
|
+
Errors = VagrantPlugins::Skytap::Errors
|
7
|
+
|
8
|
+
let(:vm1_attrs) { JSON.load(File.read(File.join(File.expand_path('..', __FILE__), 'skeletons', 'vm1.json'))) }
|
9
|
+
let(:vm2_attrs) { vm1_attrs.merge("id" => "6981851", "name" => "VM2") }
|
10
|
+
let(:network1_attrs) { JSON.load(File.read(File.join(File.expand_path('..', __FILE__), 'skeletons', 'network1.json'))) }
|
11
|
+
let(:empty_environment_attrs) { JSON.load(File.read(File.join(File.expand_path('..', __FILE__), 'skeletons', 'empty_environment.json')))}
|
12
|
+
|
13
|
+
let(:attrs_one_vm) do
|
14
|
+
empty_environment_attrs.dup.tap do |ret|
|
15
|
+
ret['vms'] = [vm1_attrs]
|
16
|
+
ret['networks'] = [network1_attrs]
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
20
|
+
let(:attrs) do
|
21
|
+
attrs_one_vm.dup.tap do |ret|
|
22
|
+
ret['vms'] = [vm1_attrs, vm2_attrs]
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
let(:iso_env) do
|
27
|
+
# We have to create a Vagrantfile so there is a root path
|
28
|
+
env = isolated_environment
|
29
|
+
env.vagrantfile("")
|
30
|
+
env.create_vagrant_env
|
31
|
+
end
|
32
|
+
|
33
|
+
let(:machine) { iso_env.machine(iso_env.machine_names[0], :dummy) }
|
34
|
+
let(:env) {{ machine: machine }}
|
35
|
+
let(:instance) { described_class.new(attrs, env) }
|
36
|
+
|
37
|
+
let(:api_client) do
|
38
|
+
# By default, all GET requests will return an environment with VM1, VM2, and 1 network
|
39
|
+
double('api_client',
|
40
|
+
get: double('resp', body: JSON.dump(attrs))
|
41
|
+
)
|
42
|
+
end
|
43
|
+
|
44
|
+
# Ensure tests are not affected by Skytap credential environment variables
|
45
|
+
before :each do
|
46
|
+
ENV.stub(:[] => nil)
|
47
|
+
end
|
48
|
+
|
49
|
+
describe "check_vm_before_adding" do
|
50
|
+
subject do
|
51
|
+
instance.vms.first
|
52
|
+
end
|
53
|
+
|
54
|
+
it "raises SourceVmNotStopped if the vm is running" do
|
55
|
+
allow(subject).to receive(:runstate).and_return('running')
|
56
|
+
expect {described_class.check_vm_before_adding(env, subject)}.to raise_error(Errors::SourceVmNotStopped)
|
57
|
+
allow(subject).to receive(:runstate).and_call_original
|
58
|
+
end
|
59
|
+
|
60
|
+
it "raises SourceVmNotStopped if the vm is suspended" do
|
61
|
+
allow(subject).to receive(:runstate).and_return('suspended')
|
62
|
+
expect {described_class.check_vm_before_adding(env, subject)}.to raise_error(Errors::SourceVmNotStopped)
|
63
|
+
allow(subject).to receive(:runstate).and_call_original
|
64
|
+
end
|
65
|
+
|
66
|
+
it "raises nothing if the vm is stopped" do
|
67
|
+
allow(subject).to receive(:runstate).and_return('stopped')
|
68
|
+
expect {described_class.check_vm_before_adding(env, subject)}.to_not raise_error
|
69
|
+
allow(subject).to receive(:runstate).and_call_original
|
70
|
+
end
|
71
|
+
end
|
72
|
+
|
73
|
+
describe "vms" do
|
74
|
+
subject do
|
75
|
+
instance.vms.first
|
76
|
+
end
|
77
|
+
it { should be_a VagrantPlugins::Skytap::API::Vm }
|
78
|
+
end
|
79
|
+
|
80
|
+
describe "networks" do
|
81
|
+
subject do
|
82
|
+
instance.networks.first
|
83
|
+
end
|
84
|
+
it { should be_a VagrantPlugins::Skytap::API::Network }
|
85
|
+
end
|
86
|
+
|
87
|
+
describe "get_vm_by_id" do
|
88
|
+
subject do
|
89
|
+
instance
|
90
|
+
end
|
91
|
+
|
92
|
+
it "should return the appropriate vm from the collection" do
|
93
|
+
expect(subject.vms.count).to eq 2
|
94
|
+
expect(subject.get_vm_by_id('6981850').get_api_attribute('name')).to eq 'VM1'
|
95
|
+
expect(subject.get_vm_by_id('6981851').get_api_attribute('name')).to eq 'VM2'
|
96
|
+
end
|
97
|
+
end
|
98
|
+
|
99
|
+
describe "reload" do
|
100
|
+
subject do
|
101
|
+
old_attrs = attrs_one_vm.merge('networks' => [])
|
102
|
+
new_attrs = attrs.merge('name' => 'Environment with 2 vms')
|
103
|
+
client = double('api_client',
|
104
|
+
get: double('resp', body: JSON.dump(new_attrs))
|
105
|
+
)
|
106
|
+
myenv = env.merge(api_client: client)
|
107
|
+
described_class.new(old_attrs, myenv)
|
108
|
+
end
|
109
|
+
|
110
|
+
it "reloads the list of vms and networks" do
|
111
|
+
expect(subject.name).to eq 'Environment 1'
|
112
|
+
expect(subject.vms.count).to eq 1
|
113
|
+
expect(subject.networks.count).to eq 0
|
114
|
+
subject.reload
|
115
|
+
expect(subject.name).to eq 'Environment with 2 vms'
|
116
|
+
expect(subject.vms.count).to eq 2
|
117
|
+
expect(subject.networks.count).to eq 1
|
118
|
+
end
|
119
|
+
end
|
120
|
+
|
121
|
+
describe "busy?" do
|
122
|
+
subject do
|
123
|
+
instance
|
124
|
+
end
|
125
|
+
|
126
|
+
it "returns false when stopped" do
|
127
|
+
allow(subject).to receive(:runstate).and_return('stopped')
|
128
|
+
expect(subject.busy?).to eq false
|
129
|
+
allow(subject).to receive(:runstate).and_call_original
|
130
|
+
end
|
131
|
+
|
132
|
+
it "returns false when running" do
|
133
|
+
allow(subject).to receive(:runstate).and_return('running')
|
134
|
+
expect(subject.busy?).to eq false
|
135
|
+
allow(subject).to receive(:runstate).and_call_original
|
136
|
+
end
|
137
|
+
|
138
|
+
it "returns true when runstate is busy" do
|
139
|
+
allow(subject).to receive(:runstate).and_return('busy')
|
140
|
+
expect(subject.busy?).to eq true
|
141
|
+
allow(subject).to receive(:runstate).and_call_original
|
142
|
+
end
|
143
|
+
end
|
144
|
+
end
|
@@ -0,0 +1,19 @@
|
|
1
|
+
{
|
2
|
+
"id": "5570024",
|
3
|
+
"url": "https://example.com/templates/5570024",
|
4
|
+
"name": "Environment 1",
|
5
|
+
"error": "",
|
6
|
+
"runstate": "running",
|
7
|
+
"description": "",
|
8
|
+
"suspend_on_idle": 86400,
|
9
|
+
"routable": false,
|
10
|
+
"vms": [],
|
11
|
+
"networks": [],
|
12
|
+
"lockversion": "60afa50045216f791278c10285a3a82bb1e4c5b8",
|
13
|
+
"use_smart_client": true,
|
14
|
+
"disable_internet": false,
|
15
|
+
"region": "US-West",
|
16
|
+
"region_backend": "skytap",
|
17
|
+
"owner": "https://example.com/users/15386",
|
18
|
+
"publish_sets": []
|
19
|
+
}
|
@@ -0,0 +1,36 @@
|
|
1
|
+
{
|
2
|
+
"id": "3288116",
|
3
|
+
"url": "https://example.com/templates/5570024/networks/3288116",
|
4
|
+
"name": "Default Network",
|
5
|
+
"network_type": "automatic",
|
6
|
+
"subnet": "10.0.0.0/24",
|
7
|
+
"subnet_addr": "10.0.0.0",
|
8
|
+
"subnet_size": 24,
|
9
|
+
"gateway": "10.0.0.254",
|
10
|
+
"primary_nameserver": null,
|
11
|
+
"secondary_nameserver": null,
|
12
|
+
"region": "US-West",
|
13
|
+
"domain": "skytap.example",
|
14
|
+
"vpn_attachments": [
|
15
|
+
{
|
16
|
+
"id": "3288116-vpn-711360",
|
17
|
+
"connected": true,
|
18
|
+
"network": {
|
19
|
+
"id": "3288116",
|
20
|
+
"subnet": "10.0.0.0/24",
|
21
|
+
"network_name": "Default Network",
|
22
|
+
"configuration_id": "5570024"
|
23
|
+
},
|
24
|
+
"vpn": {
|
25
|
+
"id": "vpn-711360",
|
26
|
+
"name": "Skytap sea9 NAT VPN",
|
27
|
+
"enabled": true,
|
28
|
+
"nat_enabled": true,
|
29
|
+
"remote_subnets": "10.1.0.0/24, 10.1.1.0/24, 10.1.2.0/24, 10.1.4.0/24, 10.1.6.0/24, 10.1.8.0/24, 10.1.16.0/24, 172.16.89.0/24, 192.168.0.0/16",
|
30
|
+
"remote_peer_ip": "66.193.98.66"
|
31
|
+
}
|
32
|
+
}
|
33
|
+
],
|
34
|
+
"tunnelable": false,
|
35
|
+
"tunnels": []
|
36
|
+
}
|
@@ -0,0 +1,85 @@
|
|
1
|
+
{
|
2
|
+
"id": "6981850",
|
3
|
+
"name": "VM1",
|
4
|
+
"runstate": "stopped",
|
5
|
+
"hardware": {
|
6
|
+
"cpus": 1,
|
7
|
+
"supports_multicore": true,
|
8
|
+
"cpus_per_socket": 1,
|
9
|
+
"ram": 1024,
|
10
|
+
"svms": 1,
|
11
|
+
"guestOS": "ubuntu-64",
|
12
|
+
"max_cpus": 12,
|
13
|
+
"min_ram": 256,
|
14
|
+
"max_ram": 131072,
|
15
|
+
"vnc_keymap": null,
|
16
|
+
"uuid": null,
|
17
|
+
"disks": [
|
18
|
+
{
|
19
|
+
"id": "disk-3089616-7086702-scsi-0-0",
|
20
|
+
"size": 20480,
|
21
|
+
"type": "SCSI",
|
22
|
+
"controller": "0",
|
23
|
+
"lun": "0"
|
24
|
+
}
|
25
|
+
],
|
26
|
+
"storage": 20480,
|
27
|
+
"upgradable": false,
|
28
|
+
"instance_type": null,
|
29
|
+
"time_sync_enabled": true,
|
30
|
+
"copy_paste_enabled": true,
|
31
|
+
"nested_virtualization": false
|
32
|
+
},
|
33
|
+
"error": false,
|
34
|
+
"asset_id": null,
|
35
|
+
"hardware_version": 10,
|
36
|
+
"interfaces": [
|
37
|
+
{
|
38
|
+
"id": "nic-3089616-7086702-0",
|
39
|
+
"ip": "10.0.0.1",
|
40
|
+
"hostname": "host-1",
|
41
|
+
"mac": "00:50:56:14:34:E4",
|
42
|
+
"services_count": 0,
|
43
|
+
"services": [],
|
44
|
+
"public_ips_count": 0,
|
45
|
+
"public_ips": [],
|
46
|
+
"vm_id": "6981850",
|
47
|
+
"vm_name": "Ubuntu Server 14.04 - 64-bit",
|
48
|
+
"status": "Running",
|
49
|
+
"nat_addresses": {
|
50
|
+
"network_nat_addresses": [],
|
51
|
+
"vpn_nat_addresses": [
|
52
|
+
{
|
53
|
+
"ip_address": "10.1.130.104",
|
54
|
+
"vpn_id": "vpn-711360",
|
55
|
+
"vpn_name": "Skytap sea9 NAT VPN",
|
56
|
+
"vpn_url": "https://example.com/vpns/vpn-711360"
|
57
|
+
}
|
58
|
+
]
|
59
|
+
},
|
60
|
+
"network_id": "3288116",
|
61
|
+
"network_name": "Default Network",
|
62
|
+
"network_url": "https://example.com/templates/5570024/networks/3288116",
|
63
|
+
"network_type": "automatic",
|
64
|
+
"network_subnet": "10.0.0.0/24",
|
65
|
+
"nic_type": "vmxnet3",
|
66
|
+
"promiscuous": false,
|
67
|
+
"secondary_ips": []
|
68
|
+
}
|
69
|
+
],
|
70
|
+
"notes": [],
|
71
|
+
"labels": [],
|
72
|
+
"credentials": [
|
73
|
+
{
|
74
|
+
"id": "5695620",
|
75
|
+
"text": "skytap / ChangeMe!"
|
76
|
+
}
|
77
|
+
],
|
78
|
+
"desktop_resizable": true,
|
79
|
+
"local_mouse_cursor": true,
|
80
|
+
"maintenance_lock_engaged": false,
|
81
|
+
"region_backend": "skytap",
|
82
|
+
"created_at": "2015/09/24 14:10:55 -0700",
|
83
|
+
"can_change_object_state": true,
|
84
|
+
"template_url": "https://example.com/templates/5570024"
|
85
|
+
}
|
@@ -0,0 +1,83 @@
|
|
1
|
+
module VagrantTests
|
2
|
+
module DummyCommunicator
|
3
|
+
class Communicator < Vagrant.plugin("2", :communicator)
|
4
|
+
def ready?
|
5
|
+
true
|
6
|
+
end
|
7
|
+
|
8
|
+
attr_reader :known_commands
|
9
|
+
|
10
|
+
def initialize(machine)
|
11
|
+
@known_commands = Hash.new do |hash, key|
|
12
|
+
hash[key] = { expected: 0, received: 0, response: nil }
|
13
|
+
end
|
14
|
+
end
|
15
|
+
|
16
|
+
def expected_commands
|
17
|
+
known_commands.select do |command, info|
|
18
|
+
info[:expected] > 0
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
22
|
+
def received_commands
|
23
|
+
known_commands.select do |command, info|
|
24
|
+
info[:received] > 0
|
25
|
+
end.keys
|
26
|
+
end
|
27
|
+
|
28
|
+
def stub_command(command, response)
|
29
|
+
known_commands[command][:response] = response
|
30
|
+
end
|
31
|
+
|
32
|
+
def expect_command(command)
|
33
|
+
known_commands[command][:expected] += 1
|
34
|
+
end
|
35
|
+
|
36
|
+
def received_summary
|
37
|
+
received_commands.map { |cmd| " - #{cmd}" }.unshift('received:').join("\n")
|
38
|
+
end
|
39
|
+
|
40
|
+
def verify_expectations!
|
41
|
+
expected_commands.each do |command, info|
|
42
|
+
if info[:expected] != info[:received]
|
43
|
+
fail([
|
44
|
+
"expected to receive '#{command}' #{info[:expected]} times",
|
45
|
+
"got #{info[:received]} times instead",
|
46
|
+
received_summary
|
47
|
+
].join("\n"))
|
48
|
+
end
|
49
|
+
end
|
50
|
+
end
|
51
|
+
|
52
|
+
def execute(command, opts=nil)
|
53
|
+
known = known_commands[command]
|
54
|
+
known[:received] += 1
|
55
|
+
response = known[:response]
|
56
|
+
return unless response
|
57
|
+
|
58
|
+
if block_given?
|
59
|
+
[:stdout, :stderr].each do |type|
|
60
|
+
Array(response[type]).each do |line|
|
61
|
+
yield type, line
|
62
|
+
end
|
63
|
+
end
|
64
|
+
end
|
65
|
+
|
66
|
+
if response[:raise]
|
67
|
+
raise response[:raise]
|
68
|
+
end
|
69
|
+
|
70
|
+
response[:exit_code]
|
71
|
+
end
|
72
|
+
|
73
|
+
def sudo(command, opts=nil, &block)
|
74
|
+
execute(command, opts, &block)
|
75
|
+
end
|
76
|
+
|
77
|
+
def test(command, opts=nil)
|
78
|
+
execute(command, opts) == 0
|
79
|
+
end
|
80
|
+
end
|
81
|
+
end
|
82
|
+
end
|
83
|
+
|
@@ -0,0 +1,41 @@
|
|
1
|
+
module VagrantTests
|
2
|
+
class DummyProviderPlugin < Vagrant.plugin("2")
|
3
|
+
name "Dummy Provider"
|
4
|
+
description <<-EOF
|
5
|
+
This creates a provider named "dummy" which does nothing, so that
|
6
|
+
the unit tests aren't reliant on VirtualBox (or any other real
|
7
|
+
provider for that matter).
|
8
|
+
EOF
|
9
|
+
|
10
|
+
provider(:dummy) { DummyProvider }
|
11
|
+
end
|
12
|
+
|
13
|
+
class DummyProvider < Vagrant.plugin("2", :provider)
|
14
|
+
def initialize(machine)
|
15
|
+
@machine = machine
|
16
|
+
end
|
17
|
+
|
18
|
+
def state=(id)
|
19
|
+
state_file.open("w+") do |f|
|
20
|
+
f.write(id.to_s)
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
24
|
+
def state
|
25
|
+
if !state_file.file?
|
26
|
+
new_state = @machine.id
|
27
|
+
new_state = Vagrant::MachineState::NOT_CREATED_ID if !new_state
|
28
|
+
self.state = new_state
|
29
|
+
end
|
30
|
+
|
31
|
+
state_id = state_file.read.to_sym
|
32
|
+
Vagrant::MachineState.new(state_id, state_id.to_s, state_id.to_s)
|
33
|
+
end
|
34
|
+
|
35
|
+
protected
|
36
|
+
|
37
|
+
def state_file
|
38
|
+
@machine.data_dir.join("dummy_state")
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end
|
@@ -0,0 +1,217 @@
|
|
1
|
+
require "fileutils"
|
2
|
+
require "pathname"
|
3
|
+
require "tempfile"
|
4
|
+
require "tmpdir"
|
5
|
+
|
6
|
+
require "json"
|
7
|
+
require "log4r"
|
8
|
+
|
9
|
+
require "vagrant/util/platform"
|
10
|
+
require "vagrant/util/subprocess"
|
11
|
+
|
12
|
+
require "support/isolated_environment"
|
13
|
+
|
14
|
+
module Unit
|
15
|
+
class IsolatedEnvironment < ::IsolatedEnvironment
|
16
|
+
def create_vagrant_env(options=nil)
|
17
|
+
options = {
|
18
|
+
cwd: @workdir,
|
19
|
+
home_path: @homedir
|
20
|
+
}.merge(options || {})
|
21
|
+
|
22
|
+
Vagrant::Environment.new(options)
|
23
|
+
end
|
24
|
+
|
25
|
+
# This creates a file in the isolated environment. By default this file
|
26
|
+
# will be created in the working directory of the isolated environment.
|
27
|
+
def file(name, contents)
|
28
|
+
@workdir.join(name).open("w+") do |f|
|
29
|
+
f.write(contents)
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
33
|
+
def vagrantfile(contents, root=nil)
|
34
|
+
root ||= @workdir
|
35
|
+
root.join("Vagrantfile").open("w+") do |f|
|
36
|
+
f.write(contents)
|
37
|
+
end
|
38
|
+
end
|
39
|
+
|
40
|
+
def box(name, vagrantfile_contents="")
|
41
|
+
# Create the box directory
|
42
|
+
box_dir = boxes_dir.join(name)
|
43
|
+
box_dir.mkpath
|
44
|
+
|
45
|
+
# Create the "box.ovf" file because that is how Vagrant heuristically
|
46
|
+
# determines a box is a V1 box.
|
47
|
+
box_dir.join("box.ovf").open("w") { |f| f.write("") }
|
48
|
+
|
49
|
+
# Populate the vagrantfile
|
50
|
+
vagrantfile(vagrantfile_contents, box_dir)
|
51
|
+
|
52
|
+
# Return the directory
|
53
|
+
box_dir
|
54
|
+
end
|
55
|
+
|
56
|
+
# Create an alias because "box" makes a V1 box, so "box1"
|
57
|
+
alias :box1 :box
|
58
|
+
|
59
|
+
# Creates a fake box to exist in this environment.
|
60
|
+
#
|
61
|
+
# @param [String] name Name of the box
|
62
|
+
# @param [Symbol] provider Provider the box was built for.
|
63
|
+
# @return [Pathname] Path to the box directory.
|
64
|
+
def box2(name, provider, options=nil)
|
65
|
+
# Default options
|
66
|
+
options = {
|
67
|
+
vagrantfile: ""
|
68
|
+
}.merge(options || {})
|
69
|
+
|
70
|
+
# Make the box directory
|
71
|
+
box_dir = boxes_dir.join(name, provider.to_s)
|
72
|
+
box_dir.mkpath
|
73
|
+
|
74
|
+
# Create a metadata.json file
|
75
|
+
box_metadata_file = box_dir.join("metadata.json")
|
76
|
+
box_metadata_file.open("w") do |f|
|
77
|
+
f.write(JSON.generate({
|
78
|
+
provider: provider.to_s
|
79
|
+
}))
|
80
|
+
end
|
81
|
+
|
82
|
+
# Create a Vagrantfile
|
83
|
+
box_vagrantfile = box_dir.join("Vagrantfile")
|
84
|
+
box_vagrantfile.open("w") do |f|
|
85
|
+
f.write(options[:vagrantfile])
|
86
|
+
end
|
87
|
+
|
88
|
+
# Return the box directory
|
89
|
+
box_dir
|
90
|
+
end
|
91
|
+
|
92
|
+
# Creates a fake box to exist in this environment according
|
93
|
+
# to the "gen-3" box format.
|
94
|
+
#
|
95
|
+
# @param [String] name
|
96
|
+
# @param [String] version
|
97
|
+
# @param [String] provider
|
98
|
+
# @return [Pathname]
|
99
|
+
def box3(name, version, provider, **opts)
|
100
|
+
# Create the directory for the box
|
101
|
+
box_dir = boxes_dir.join(name, version, provider.to_s)
|
102
|
+
box_dir.mkpath
|
103
|
+
|
104
|
+
# Create the metadata.json for it
|
105
|
+
box_metadata_file = box_dir.join("metadata.json")
|
106
|
+
box_metadata_file.open("w") do |f|
|
107
|
+
f.write(JSON.generate({
|
108
|
+
provider: provider.to_s
|
109
|
+
}))
|
110
|
+
end
|
111
|
+
|
112
|
+
# Create a Vagrantfile
|
113
|
+
if opts[:vagrantfile]
|
114
|
+
box_vagrantfile = box_dir.join("Vagrantfile")
|
115
|
+
box_vagrantfile.open("w") do |f|
|
116
|
+
f.write(opts[:vagrantfile])
|
117
|
+
end
|
118
|
+
end
|
119
|
+
|
120
|
+
# Create the metadata URL
|
121
|
+
if opts[:metadata_url]
|
122
|
+
boxes_dir.join(name, "metadata_url").open("w") do |f|
|
123
|
+
f.write(opts[:metadata_url])
|
124
|
+
end
|
125
|
+
end
|
126
|
+
|
127
|
+
box_dir
|
128
|
+
end
|
129
|
+
|
130
|
+
# This creates a "box" file that is a valid V1 box.
|
131
|
+
#
|
132
|
+
# @return [Pathname] Path to the newly created box.
|
133
|
+
def box1_file
|
134
|
+
# Create a temporary directory to store our data we will tar up
|
135
|
+
td_source = Dir.mktmpdir
|
136
|
+
td_dest = Dir.mktmpdir
|
137
|
+
|
138
|
+
# Store the temporary directory so it is not deleted until
|
139
|
+
# this instance is garbage collected.
|
140
|
+
@_box2_file_temp ||= []
|
141
|
+
@_box2_file_temp << td_dest
|
142
|
+
|
143
|
+
# The source as a Pathname, which is easier to work with
|
144
|
+
source = Pathname.new(td_source)
|
145
|
+
|
146
|
+
# The destination file
|
147
|
+
result = Pathname.new(td_dest).join("temporary.box")
|
148
|
+
|
149
|
+
# Put a "box.ovf" in there.
|
150
|
+
source.join("box.ovf").open("w") do |f|
|
151
|
+
f.write("FOO!")
|
152
|
+
end
|
153
|
+
|
154
|
+
Dir.chdir(source) do
|
155
|
+
# Find all the files in our current directory and tar it up!
|
156
|
+
files = Dir.glob(File.join(".", "**", "*"))
|
157
|
+
|
158
|
+
# Package!
|
159
|
+
Vagrant::Util::Subprocess.execute("bsdtar", "-czf", result.to_s, *files)
|
160
|
+
end
|
161
|
+
|
162
|
+
# Resulting box
|
163
|
+
result
|
164
|
+
end
|
165
|
+
|
166
|
+
# This creates a "box" file with the given provider.
|
167
|
+
#
|
168
|
+
# @param [Symbol] provider Provider for the box.
|
169
|
+
# @return [Pathname] Path to the newly created box.
|
170
|
+
def box2_file(provider, options=nil)
|
171
|
+
options ||= {}
|
172
|
+
|
173
|
+
# This is the metadata we want to store in our file
|
174
|
+
metadata = {
|
175
|
+
"type" => "v2_box",
|
176
|
+
"provider" => provider
|
177
|
+
}.merge(options[:metadata] || {})
|
178
|
+
|
179
|
+
# Create a temporary directory to store our data we will tar up
|
180
|
+
td_source = Dir.mktmpdir
|
181
|
+
td_dest = Dir.mktmpdir
|
182
|
+
|
183
|
+
# Store the temporary directory so it is not deleted until
|
184
|
+
# this instance is garbage collected.
|
185
|
+
@_box2_file_temp ||= []
|
186
|
+
@_box2_file_temp << td_dest
|
187
|
+
|
188
|
+
# The source as a Pathname, which is easier to work with
|
189
|
+
source = Pathname.new(td_source)
|
190
|
+
|
191
|
+
# The destination file
|
192
|
+
result = Pathname.new(td_dest).join("temporary.box")
|
193
|
+
|
194
|
+
# Put the metadata.json in here.
|
195
|
+
source.join("metadata.json").open("w") do |f|
|
196
|
+
f.write(JSON.generate(metadata))
|
197
|
+
end
|
198
|
+
|
199
|
+
Dir.chdir(source) do
|
200
|
+
# Find all the files in our current directory and tar it up!
|
201
|
+
files = Dir.glob(File.join(".", "**", "*"))
|
202
|
+
|
203
|
+
# Package!
|
204
|
+
Vagrant::Util::Subprocess.execute("bsdtar", "-czf", result.to_s, *files)
|
205
|
+
end
|
206
|
+
|
207
|
+
# Resulting box
|
208
|
+
result
|
209
|
+
end
|
210
|
+
|
211
|
+
def boxes_dir
|
212
|
+
dir = @homedir.join("boxes")
|
213
|
+
dir.mkpath
|
214
|
+
dir
|
215
|
+
end
|
216
|
+
end
|
217
|
+
end
|
@@ -0,0 +1,15 @@
|
|
1
|
+
shared_context "synced folder actions" do
|
2
|
+
# This creates a synced folder implementation.
|
3
|
+
def impl(usable, name)
|
4
|
+
Class.new(Vagrant.plugin("2", :synced_folder)) do
|
5
|
+
define_method(:name) do
|
6
|
+
name
|
7
|
+
end
|
8
|
+
|
9
|
+
define_method(:usable?) do |machine, raise_error=false|
|
10
|
+
raise "#{name}: usable" if raise_error && !usable
|
11
|
+
usable
|
12
|
+
end
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|