vagrant-kubevirt 1.0.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 (45) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +20 -0
  3. data/.travis.yml +12 -0
  4. data/CHANGELOG.md +3 -0
  5. data/Gemfile +12 -0
  6. data/LICENSE +13 -0
  7. data/README.md +109 -0
  8. data/Rakefile +22 -0
  9. data/example_box/README.md +9 -0
  10. data/example_box/Vagrantfile +20 -0
  11. data/example_box/kubevirt.box +0 -0
  12. data/example_box/metadata.json +3 -0
  13. data/lib/vagrant-kubevirt.rb +18 -0
  14. data/lib/vagrant-kubevirt/action.rb +176 -0
  15. data/lib/vagrant-kubevirt/action/connect_kubevirt.rb +37 -0
  16. data/lib/vagrant-kubevirt/action/create_vm.rb +133 -0
  17. data/lib/vagrant-kubevirt/action/destroy_vm.rb +30 -0
  18. data/lib/vagrant-kubevirt/action/is_created.rb +18 -0
  19. data/lib/vagrant-kubevirt/action/is_stopped.rb +18 -0
  20. data/lib/vagrant-kubevirt/action/read_ssh_info.rb +54 -0
  21. data/lib/vagrant-kubevirt/action/read_state.rb +44 -0
  22. data/lib/vagrant-kubevirt/action/set_domain_name.rb +33 -0
  23. data/lib/vagrant-kubevirt/action/start_vm.rb +35 -0
  24. data/lib/vagrant-kubevirt/action/stop_vm.rb +37 -0
  25. data/lib/vagrant-kubevirt/action/wait_for_state.rb +64 -0
  26. data/lib/vagrant-kubevirt/config.rb +60 -0
  27. data/lib/vagrant-kubevirt/errors.rb +39 -0
  28. data/lib/vagrant-kubevirt/plugin.rb +73 -0
  29. data/lib/vagrant-kubevirt/provider.rb +50 -0
  30. data/lib/vagrant-kubevirt/version.rb +5 -0
  31. data/locales/en.yml +69 -0
  32. data/spec/spec_helper.rb +6 -0
  33. data/spec/support/environment_helper.rb +18 -0
  34. data/spec/support/kubevirt_context.rb +15 -0
  35. data/spec/support/sharedcontext.rb +33 -0
  36. data/spec/unit/action/create_vm_spec.rb +122 -0
  37. data/spec/unit/action/destroy_vm_spec.rb +33 -0
  38. data/spec/unit/action/read_ssh_info_spec.rb +45 -0
  39. data/spec/unit/action/read_state_spec.rb +44 -0
  40. data/spec/unit/action/start_vm_spec.rb +44 -0
  41. data/spec/unit/action/stop_vm_spec.rb +57 -0
  42. data/spec/unit/action/wait_for_state_spec.rb +57 -0
  43. data/spec/unit/config_spec.rb +41 -0
  44. data/vagrant-kubevirt.gemspec +26 -0
  45. metadata +161 -0
@@ -0,0 +1,60 @@
1
+ require "vagrant"
2
+ require "iniparse"
3
+
4
+ module VagrantPlugins
5
+ module Kubevirt
6
+ class Config < Vagrant.plugin("2", :config)
7
+
8
+ attr_accessor :token
9
+ attr_accessor :hostname
10
+ attr_accessor :port
11
+ attr_accessor :namespace
12
+
13
+ # Domain specific settings used while creating new machine.
14
+ attr_accessor :memory
15
+ attr_accessor :cpus
16
+ attr_accessor :template
17
+ attr_accessor :image
18
+ attr_accessor :pvc
19
+ attr_accessor :port_node
20
+
21
+ def initialize
22
+ @token = UNSET_VALUE
23
+ @hostname = UNSET_VALUE
24
+ @port = UNSET_VALUE
25
+ @namespace = UNSET_VALUE
26
+
27
+ @memory = UNSET_VALUE
28
+ @cpus = UNSET_VALUE
29
+ @template = UNSET_VALUE
30
+ @image = UNSET_VALUE
31
+ @pvc = UNSET_VALUE
32
+ @port_node = UNSET_VALUE
33
+ end
34
+
35
+ def finalize!
36
+ @token = nil if @token == UNSET_VALUE
37
+ @hostname = 'localhost' if @hostname == UNSET_VALUE
38
+ @port = '8443' if @port == UNSET_VALUE
39
+ @namespace = 'default' if @namespace == UNSET_VALUE
40
+
41
+ @memory = 512 if @memory == UNSET_VALUE
42
+ @cpus = 1 if @cpus == UNSET_VALUE
43
+ @template = nil if @template == UNSET_VALUE
44
+ @image = nil if @image == UNSET_VALUE
45
+ @pvc = nil if @pvc == UNSET_VALUE
46
+ @port_node = 30000 if @port_node == UNSET_VALUE
47
+ end
48
+
49
+ def validate(machine)
50
+ errors = _detected_errors
51
+
52
+ config = machine.provider_config
53
+
54
+ errors << I18n.t("vagrant_kubevirt.config.image_info_required") if config.template.nil? and config.image.nil? and config.pvc.nil?
55
+
56
+ { 'Kubevirt Provider' => errors }
57
+ end
58
+ end
59
+ end
60
+ end
@@ -0,0 +1,39 @@
1
+ require "vagrant"
2
+
3
+ module VagrantPlugins
4
+ module Kubevirt
5
+ module Errors
6
+ class VagrantKubevirtError < Vagrant::Errors::VagrantError
7
+ error_namespace("vagrant_kubevirt.errors")
8
+ end
9
+
10
+ class FogError < VagrantKubevirtError
11
+ error_key(:fog_error)
12
+ end
13
+
14
+ class NoVMError < VagrantKubevirtError
15
+ error_key(:no_vm_error)
16
+ end
17
+
18
+ class StartVMError < VagrantKubevirtError
19
+ error_key(:start_vm_error)
20
+ end
21
+
22
+ class StopVMError < VagrantKubevirtError
23
+ error_key(:stop_vm_error)
24
+ end
25
+
26
+ class VMReadyTimeout < VagrantKubevirtError
27
+ error_key(:vm_ready_timeout)
28
+ end
29
+
30
+ class NoNodeError < VagrantKubevirtError
31
+ error_key(:no_node_error)
32
+ end
33
+
34
+ class NoServiceError < VagrantKubevirtError
35
+ error_key(:no_service_error)
36
+ end
37
+ end
38
+ end
39
+ end
@@ -0,0 +1,73 @@
1
+ begin
2
+ require "vagrant"
3
+ rescue LoadError
4
+ raise "The Vagrant Kubevirt plugin must be run within Vagrant."
5
+ end
6
+
7
+ # This is a sanity check to make sure no one is attempting to install
8
+ # this into an early Vagrant version.
9
+ if Vagrant::VERSION < "1.2.0"
10
+ raise "The Vagrant Kubevirt plugin is only compatible with Vagrant 1.2+"
11
+ end
12
+
13
+ module VagrantPlugins
14
+ module Kubevirt
15
+ class Plugin < Vagrant.plugin('2')
16
+ name "Kubevirt"
17
+ description <<-DESC
18
+ This plugin installs a provider that allows Vagrant to manage
19
+ Kubevirt machines.
20
+ DESC
21
+
22
+ config(:kubevirt, :provider) do
23
+ require_relative "config"
24
+ Config
25
+ end
26
+
27
+ provider(:kubevirt, parallel: true) do
28
+ # Setup logging and i18n
29
+ setup_logging
30
+ setup_i18n
31
+
32
+ # Return the provider
33
+ require_relative "provider"
34
+ Provider
35
+ end
36
+
37
+ # This initializes the internationalization strings.
38
+ def self.setup_i18n
39
+ I18n.load_path << File.expand_path("locales/en.yml", Kubevirt.source_root)
40
+ I18n.reload!
41
+ end
42
+
43
+ # This sets up our log level to be whatever VAGRANT_LOG is.
44
+ def self.setup_logging
45
+ require "log4r"
46
+
47
+ level = nil
48
+ begin
49
+ level = Log4r.const_get(ENV["VAGRANT_LOG"].upcase)
50
+ rescue NameError
51
+ # This means that the logging constant wasn't found,
52
+ # which is fine. We just keep `level` as `nil`. But
53
+ # we tell the user.
54
+ level = nil
55
+ end
56
+
57
+ # Some constants, such as "true" resolve to booleans, so the
58
+ # above error checking doesn't catch it. This will check to make
59
+ # sure that the log level is an integer, as Log4r requires.
60
+ level = nil if !level.is_a?(Integer)
61
+
62
+ # Set the logging level on all "vagrant" namespaced
63
+ # logs as long as we have a valid level.
64
+ if level
65
+ logger = Log4r::Logger.new("vagrant_kubevirt")
66
+ logger.outputters = Log4r::Outputter.stderr
67
+ logger.level = level
68
+ logger = nil
69
+ end
70
+ end
71
+ end
72
+ end
73
+ end
@@ -0,0 +1,50 @@
1
+ require "log4r"
2
+ require "vagrant"
3
+
4
+ module VagrantPlugins
5
+ module Kubevirt
6
+ class Provider < Vagrant.plugin("2", :provider)
7
+ def initialize(machine)
8
+ @machine = machine
9
+ end
10
+
11
+ def action(name)
12
+ # Attempt to get the action method from the Action class if it
13
+ # exists, otherwise return nil to show that we don't support the
14
+ # given action.
15
+ action_method = "action_#{name}"
16
+ return Action.send(action_method) if Action.respond_to?(action_method)
17
+ nil
18
+ end
19
+
20
+ def ssh_info
21
+ # Run a custom action called "read_ssh_info" which does what it
22
+ # says and puts the resulting SSH info into the `:machine_ssh_info`
23
+ # key in the environment.
24
+ env = @machine.action("read_ssh_info", lock: false)
25
+ env[:machine_ssh_info]
26
+ end
27
+
28
+ def state
29
+ # Run a custom action we define called "read_state" which does
30
+ # what it says. It puts the state in the `:machine_state_id`
31
+ # key in the environment.
32
+ env = @machine.action("read_state", lock: false)
33
+
34
+ state_id = env[:machine_state_id]
35
+
36
+ # Get the short and long description
37
+ short = I18n.t("vagrant_kubevirt.states.short_#{state_id}")
38
+ long = I18n.t("vagrant_kubevirt.states.long_#{state_id}")
39
+
40
+ # Return the MachineState object
41
+ Vagrant::MachineState.new(state_id, short, long)
42
+ end
43
+
44
+ def to_s
45
+ id = @machine.id.nil? ? "new" : @machine.id
46
+ "Kubevirt (#{id})"
47
+ end
48
+ end
49
+ end
50
+ end
@@ -0,0 +1,5 @@
1
+ module VagrantPlugins
2
+ module Kubevirt
3
+ VERSION = '1.0.0'
4
+ end
5
+ end
@@ -0,0 +1,69 @@
1
+ en:
2
+ vagrant_kubevirt:
3
+ creating_vm: |-
4
+ Creating VM with the following settings...
5
+ already_status: |-
6
+ The VM is already %{status}.
7
+ error_recovering: |-
8
+ An error occured. Recovering..
9
+ starting_vm: |-
10
+ Starting the VM...
11
+ wait_for_state: |-
12
+ Waiting for VM to reach state %{state}
13
+ not_created: |-
14
+ Virtual machine is not created. Please run `vagrant up` first.
15
+ action_failed: |-
16
+ %{action} failed.
17
+ stopping: |-
18
+ Stopping the VM...
19
+ destroy_vm: |-
20
+ Removing the VM...
21
+ vm_not_found: |-
22
+ The VM not found or terminated, assuming it got destroyed.
23
+ vm_exists: |-
24
+ The VM is already created
25
+ not_running: |-
26
+ The VM is not running
27
+ wait_for_boot: |-
28
+ Waiting for VM to boot
29
+
30
+ config:
31
+ kubevirt_info_required: |-
32
+ One or more of the needed Kubevirt connection details are missing.
33
+ image_info_required: |-
34
+ Either template, pvc or image details are required.
35
+
36
+ states:
37
+ short_not_created: |-
38
+ not created
39
+ long_not_created: |-
40
+ The virtual machine is not created. Run `vagrant up` to create it.
41
+ short_running: |-
42
+ running
43
+ long_running: |-
44
+ The virtual machine is running. To stop this machine, you can run
45
+ `vagrant halt`. To destroy the machine, you can run `vagrant destroy`.
46
+ short_stopped: |-
47
+ stopped
48
+ long_stopped: |-
49
+ The virtual machine is stopped. Run `vagrant up` to start it.
50
+
51
+ errors:
52
+ fog_error: |-
53
+ There was an error talking to Kubevirt. The error message is shown
54
+ below:
55
+
56
+ %{message}
57
+ no_vm_error: |-
58
+ No VM %{vm_name} found.
59
+ start_vm_error: |-
60
+ Unable to start VM: %{message}
61
+ stop_vm_error: |-
62
+ Unable to stop VM: %{message}
63
+ vm_ready_timeout: |-
64
+ The VM never became "ready" in AWS. The timeout currently
65
+ set waiting for the vm to become ready is %{timeout} seconds.
66
+ no_node_error: |-
67
+ The VM is not running on a node.
68
+ no_service_error: |-
69
+ No service configured for VM: %{name}
@@ -0,0 +1,6 @@
1
+ require 'vagrant-kubevirt'
2
+ require 'support/environment_helper'
3
+ require 'vagrant-spec/unit'
4
+
5
+ RSpec.configure do |spec|
6
+ end
@@ -0,0 +1,18 @@
1
+ class EnvironmentHelper
2
+
3
+ def cpus
4
+ 1
5
+ end
6
+
7
+ def memory
8
+ 512
9
+ end
10
+
11
+ def machine
12
+ self
13
+ end
14
+
15
+ def provider_config
16
+ self
17
+ end
18
+ end
@@ -0,0 +1,15 @@
1
+ require 'fog/kubevirt'
2
+
3
+ shared_context 'kubevirt' do
4
+ include_context 'unit'
5
+
6
+ let(:kubevirt_context) { true }
7
+ let(:id) { 'dummy-vagrant_dummy' }
8
+
9
+ before (:each) do
10
+ stub_const('Fog::Kubevirt::Compute', compute)
11
+ allow(compute).to receive(:new).with(hash_including(:kubevirt_hostname, :kubevirt_port, :kubevirt_token, :kubevirt_namespace, :kubevirt_log)).and_return(compute)
12
+
13
+ allow(machine).to receive(:id).and_return(id)
14
+ end
15
+ end
@@ -0,0 +1,33 @@
1
+ require 'spec_helper'
2
+
3
+ shared_context 'unit' do
4
+ include_context 'vagrant-unit'
5
+
6
+ let(:vagrantfile) do
7
+ <<-EOF
8
+ Vagrant.configure('2') do |config|
9
+ config.vm.box = 'kubevirt'
10
+ config.vm.define :test
11
+
12
+ config.vm.provider :kubevirt do |kubevirt|
13
+ kubevirt.token = 'abc'
14
+ kubevirt.template = 'working'
15
+ end
16
+ end
17
+ EOF
18
+ end
19
+ let(:test_env) do
20
+ test_env = isolated_environment
21
+ test_env.vagrantfile vagrantfile
22
+ test_env
23
+ end
24
+ let(:env) { { env: iso_env, machine: machine, ui: ui, root_path: File.expand_path(File.dirname(__FILE__)), kubevirt_compute: compute, domain_name: 'Test', action_runner: runner} }
25
+ let(:conf) { Vagrant::Config::V2::DummyConfig.new }
26
+ let(:ui) { Vagrant::UI::Basic.new }
27
+ let(:iso_env) { test_env.create_vagrant_env ui_class: Vagrant::UI::Basic }
28
+ let(:machine) { iso_env.machine(:test, :kubevirt) }
29
+ let(:app) { ->(env) {} }
30
+ let(:plugin) { register_plugin }
31
+ let(:compute) { double('compute') }
32
+ let(:runner) { double('runner') }
33
+ end
@@ -0,0 +1,122 @@
1
+ require 'support/sharedcontext'
2
+ require 'support/kubevirt_context'
3
+
4
+ require 'vagrant-kubevirt/action/create_vm'
5
+
6
+ describe VagrantPlugins::Kubevirt::Action::CreateVM do
7
+ subject { described_class.new(app, env) }
8
+
9
+ include_context 'unit'
10
+ include_context 'kubevirt'
11
+
12
+ let(:services) { double('service') }
13
+ let(:vms) { double('vms') }
14
+ let(:vm) { double('vm') }
15
+
16
+ describe '#call' do
17
+ before do
18
+ allow(compute).to receive(:vms).and_return(vms)
19
+ allow(compute).to receive(:services).and_return(services)
20
+ allow(services).to receive(:create)
21
+
22
+ allow(vms).to receive(:get).and_return(vm)
23
+ allow(vm).to receive(:name).and_return('Test')
24
+
25
+ expect(ui).to receive(:info).with('Creating VM with the following settings...')
26
+ expect(ui).to receive(:info).with(' -- Name: Test')
27
+ expect(ui).to receive(:info).with(' -- Namespace: default')
28
+ expect(ui).to receive(:info).with(' -- Cpus: 1')
29
+ expect(ui).to receive(:info).with(' -- Memory: 512M')
30
+ end
31
+
32
+ context 'when template defined' do
33
+ let(:templates) { double('templates') }
34
+ let(:template) { double('template') }
35
+
36
+ before do
37
+ allow(compute).to receive(:templates).and_return(templates)
38
+ allow(templates).to receive(:get).and_return(template)
39
+
40
+ expect(template).to receive(:clone)
41
+ expect(ui).to receive(:info).with(' -- Template: working')
42
+ end
43
+
44
+ it 'clones a template' do
45
+ expect(subject.call(env)).to be_nil
46
+ end
47
+
48
+ it 'recovers after interruption' do
49
+ env[:interrupted] = true
50
+ expect(runner).to receive(:run)
51
+
52
+ expect(subject.call(env)).to be_nil
53
+ end
54
+ end
55
+
56
+ context 'when image defined' do
57
+ let(:vagrantfile) do
58
+ <<-EOF
59
+ Vagrant.configure('2') do |config|
60
+ config.vm.box = 'kubevirt'
61
+ config.vm.define :test
62
+
63
+ config.vm.provider :kubevirt do |kubevirt|
64
+ kubevirt.token = 'abc'
65
+ kubevirt.image = 'kubevirt/fedora'
66
+ end
67
+ end
68
+ EOF
69
+ end
70
+
71
+ it 'creates a vm using image' do
72
+ expect(vms).to receive(:create).with(hash_including(:vm_name => "Test", :cpus => 1, :memory_size => 512, :image => 'kubevirt/fedora', :pvc => nil))
73
+
74
+ expect(subject.call(env)).to be_nil
75
+ end
76
+ end
77
+
78
+ context 'when pvc defined' do
79
+ let(:vagrantfile) do
80
+ <<-EOF
81
+ Vagrant.configure('2') do |config|
82
+ config.vm.box = 'kubevirt'
83
+ config.vm.define :test
84
+
85
+ config.vm.provider :kubevirt do |kubevirt|
86
+ kubevirt.token = 'abc'
87
+ kubevirt.pvc = 'my_disk'
88
+ end
89
+ end
90
+ EOF
91
+ end
92
+
93
+ it 'creates a vm using pvc' do
94
+ expect(vms).to receive(:create).with(hash_including(:vm_name => "Test", :cpus => 1, :memory_size => 512, :image => nil, :pvc => "my_disk"))
95
+
96
+ expect(subject.call(env)).to be_nil
97
+ end
98
+ end
99
+
100
+ context 'with folders synchronized' do
101
+ let(:vagrantfile) do
102
+ <<-EOF
103
+ Vagrant.configure('2') do |config|
104
+ config.vm.box = 'kubevirt'
105
+ config.vm.define :test
106
+ config.vm.synced_folder "", "/srv/website"
107
+ config.vm.provider :kubevirt do |kubevirt|
108
+ kubevirt.token = 'abc'
109
+ kubevirt.image = 'kubevirt/fedora'
110
+ end
111
+ end
112
+ EOF
113
+ end
114
+
115
+ it 'creates a vm with folder defined' do
116
+ expect(vms).to receive(:create).with(hash_including(:vm_name => "Test", :cpus => 1, :memory_size => 512, :image => 'kubevirt/fedora', :pvc => nil))
117
+
118
+ expect(subject.call(env)).to be_nil
119
+ end
120
+ end
121
+ end
122
+ end