vagrant-kubevirt 1.0.0

Sign up to get free protection for your applications and to get access to all the features.
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