vagrant-alpine 0.1.1

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: c2fc2915174a868f52ce574bb9af430ac32bdfc3
4
+ data.tar.gz: 0716848819f01d49981e4da58430d3d6a015bb94
5
+ SHA512:
6
+ metadata.gz: 4c5693032537c8775b1a0396e01cb26683f25aa992561f3d85c8a154f5f81cf56b25f7ef5d0e90d2817c75500800def2bc8a62f62c3043e213cd4ba697d1ac15
7
+ data.tar.gz: bfdd58c7edc571e0de7dd59bbad1fff77b7e0de3dad43e367f920cd71ebb593babda86cd4489a982242a89f5f091703bb9ff6aac53d967eb69ac5f1533ead7a3
data/.gitignore ADDED
@@ -0,0 +1,13 @@
1
+ /.bundle/
2
+ /.yardoc
3
+ /Gemfile.lock
4
+ /_yardoc/
5
+ /doc/
6
+ /pkg/
7
+ /spec/reports/
8
+ /tmp/
9
+ /vendor/
10
+ Vagrantfile
11
+ .vagrant
12
+ TODO.md
13
+
data/.rspec ADDED
@@ -0,0 +1,5 @@
1
+ --format doc
2
+ --order random
3
+ --color
4
+ --fail-fast
5
+
data/.rubocop.yml ADDED
@@ -0,0 +1,4 @@
1
+ Metrics/LineLength:
2
+ Enabled: false
3
+ Documentation:
4
+ Enabled: false
data/.ruby-gemset ADDED
@@ -0,0 +1 @@
1
+ vagrant-alpine
data/.ruby-version ADDED
@@ -0,0 +1 @@
1
+ ruby-2.2.0
data/.travis.yml ADDED
@@ -0,0 +1,13 @@
1
+ language: ruby
2
+ before_install:
3
+ - sudo apt-get update -qq
4
+ - sudo apt-get install -qq -y bsdtar
5
+ - rvm @global do gem uninstall bundler --all --executables
6
+ - gem uninstall bundler --all --executables
7
+ - gem install bundler --version '< 1.7.0'
8
+ rvm:
9
+ - 2.2.0
10
+ env:
11
+ global:
12
+ - NOKOGIRI_USE_SYSTEM_LIBRARIES=true
13
+ script: rake
data/Gemfile ADDED
@@ -0,0 +1,17 @@
1
+ source 'https://rubygems.org'
2
+
3
+ gemspec
4
+
5
+ group :development do
6
+ gem 'vagrant', git: 'https://github.com/mitchellh/vagrant.git'
7
+ end
8
+
9
+ group :plugins do
10
+ gem 'vagrant-alpine', path: '.'
11
+ end
12
+
13
+ group :test do
14
+ gem 'rake'
15
+ gem 'rubocop'
16
+ end
17
+
data/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ The MIT License (MIT)
2
+
3
+ Copyright (c) 2015 matt maier
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 FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
21
+ THE SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,70 @@
1
+ # [Vagrant Alpine Linux Guest](https://github.com/maier/vagrant-alpine)
2
+
3
+ This is a [Vagrant](http://vagrantup.com/) plugin adding support for [Alpine Linux](http://alpinelinx.org) guests.
4
+
5
+ > **NOTE:** The vagrant-alpine requires Vagrant 1.7+
6
+
7
+ ## Features
8
+
9
+ * Detection
10
+ * Set hostname
11
+ * Configure networking DHCP or static
12
+ * Halt/Shutdown the guest
13
+ * RSync detection and installation
14
+ * NFS client installation
15
+
16
+ ## Installation
17
+
18
+ ```
19
+ $ vagrant plugin install vagrant-alpine
20
+ ```
21
+
22
+ ## Usage
23
+
24
+ ```
25
+ $ vagrant init maier/alpine-3.1.3
26
+ $ vagrant up
27
+ ```
28
+
29
+ ## Configuration
30
+
31
+ The vagrant-alpine plugin does not offer any configuration options.
32
+
33
+
34
+ ## Development
35
+
36
+ To work on the `vagrant-alpine` plugin, clone this repository, and use
37
+ [Bundler](http://gembundler.com) to get the dependencies:
38
+
39
+ ```
40
+ $ gem install bundler -v '~> 1.7.0'
41
+ $ bundle install --path vendor/bundle
42
+ ```
43
+
44
+ Once you have the dependencies, verify the unit tests pass with `rake`:
45
+
46
+ ```
47
+ $ bundle exec rake
48
+ ```
49
+
50
+ If those pass, you're ready to start developing. You can test
51
+ the plugin without installing it into your Vagrant environment
52
+ by creating a `Vagrantfile` in teh top level directory (it is gitignored).
53
+ There is an example supplied in this repository.
54
+ (`cp Vagrantfile.example Vagrantfile` and edit.)
55
+
56
+ Use bundler to execute Vagrant:
57
+ ```
58
+ $ bundle exec vagrant up
59
+ ```
60
+
61
+
62
+ ## Notes
63
+
64
+ Alpine Linux boxes for testing are available on
65
+ [Atlas](https://atlas.hashicorp.com/maier/). Packer templates
66
+ for building the boxes are in this
67
+ [GitHub repository](https://github.com/maier/packer-templates/).
68
+
69
+ Using `VAGRANT_LOG=info`, Vagrant's `--debug` switch, and `vb.gui = true`
70
+ were all very useful when originally developing this guest plugin.
data/Rakefile ADDED
@@ -0,0 +1,9 @@
1
+ require 'rubygems'
2
+ require 'bundler/setup'
3
+ require 'bundler/gem_tasks'
4
+ require 'rspec/core/rake_task'
5
+
6
+ Bundler::GemHelper.install_tasks
7
+
8
+ RSpec::Core::RakeTask.new
9
+ task :default => 'spec'
@@ -0,0 +1,49 @@
1
+ # -*- mode: ruby -*-
2
+ # vi: set ft=ruby :
3
+
4
+ #
5
+ # Vagrantfile for testing vagrant-alpine
6
+ #
7
+
8
+ Vagrant.configure(2) do |config|
9
+
10
+ config.vm.box = 'maier/alpine-3.1.3-x86_64'
11
+
12
+ # config.ssh.username = 'vagrant'
13
+ # config.ssh.password = 'vagrant'
14
+ # config.ssh.shell = '/bin/sh'
15
+
16
+ #
17
+ # Networking
18
+ #
19
+ # DHCP
20
+ # config.vm.network 'private_network', type: 'dhcp'
21
+ #
22
+ # Static (replace <IP> with an appropriate private address)
23
+ # config.vm.network 'private_network', ip: '<IP>', auto_config: true
24
+
25
+ #
26
+ # Shared folders
27
+ #
28
+ # Note, for shared folders via NFS a static IP *must* be provided
29
+ # until guest additions can be built and installed out of main.
30
+ # The reason being that although a DHCP interface does successfully
31
+ # get an IP, virtualbox is unaware of it and therefore cannot
32
+ # provide it to Vagrant.
33
+ #
34
+ # If not assigning a static IP, ensure the default
35
+ # share is disabled.
36
+ config.vm.synced_folder '.', '/vagrant', disabled: true
37
+ #
38
+ # Define NFS shares (comment out above when enabling
39
+ # this 'default' folder, or mount a different folder.)
40
+ # config.vm.synced_folder '.', '/vagrant', type: 'nfs'
41
+
42
+ config.vm.provider 'virtualbox' do |vb|
43
+ vb.name = 'vagrant-alpine-test'
44
+ vb.cpus = 1
45
+ vb.memory = 1024
46
+ # vb.gui = true
47
+ end
48
+
49
+ end
@@ -0,0 +1,23 @@
1
+ # rubocop:disable Style/FileName
2
+ #
3
+ # squelch:
4
+ # lib/vagrant-alpine.rb:1:1: C: Use snake_case for source file names.
5
+ # require 'pathname'
6
+ #
7
+ require 'pathname'
8
+ require 'vagrant-alpine/plugin'
9
+
10
+ module VagrantPlugins
11
+ module GuestAlpine
12
+ # lib_path = Pathname.new(File.expand_path('../vagrant-alpine', __FILE__))
13
+ # autoload :Action, lib_path.join('action')
14
+ # autoload :Errors, lib_path.join('errors')
15
+
16
+ # This returns the path to the source of this plugin.
17
+ #
18
+ # @return [Pathname]
19
+ def self.source_root
20
+ @source_root ||= Pathname.new(File.expand_path('../../', __FILE__))
21
+ end
22
+ end
23
+ end
@@ -0,0 +1,95 @@
1
+ module VagrantPlugins
2
+ module GuestAlpine
3
+ module Cap
4
+ class ChangeHostName
5
+ def self.change_host_name(machine, name)
6
+ new(machine, name).change!
7
+ end
8
+
9
+ attr_reader :machine, :new_hostname
10
+
11
+ def initialize(machine, new_hostname)
12
+ @machine = machine
13
+ @new_hostname = new_hostname
14
+ end
15
+
16
+ def change!
17
+ return unless should_change?
18
+
19
+ update_etc_hostname
20
+ update_etc_hosts
21
+ refresh_hostname_service
22
+ update_mailname
23
+ renew_dhcp
24
+ end
25
+
26
+ def should_change?
27
+ new_hostname != current_hostname
28
+ end
29
+
30
+ def current_hostname
31
+ @current_hostname ||= fetch_current_hostname
32
+ end
33
+
34
+ def fetch_current_hostname
35
+ hostname = ''
36
+ sudo 'hostname -f' do |type, data|
37
+ hostname = data.chomp if type == :stdout && hostname.empty?
38
+ end
39
+
40
+ hostname
41
+ end
42
+
43
+ def update_etc_hostname
44
+ sudo("echo '#{short_hostname}' > /etc/hostname")
45
+ end
46
+
47
+ # /etc/hosts should resemble:
48
+ # 127.0.0.1 localhost
49
+ # 127.0.1.1 host.fqdn.com host.fqdn host
50
+ def update_etc_hosts
51
+ if test("grep '#{current_hostname}' /etc/hosts")
52
+ # Current hostname entry is in /etc/hosts
53
+ ip_address = '([0-9]{1,3}\.){3}[0-9]{1,3}'
54
+ search = "^(#{ip_address})\\s+#{Regexp.escape(current_hostname)}(\\s.*)?$"
55
+ replace = "\\1 #{fqdn} #{short_hostname}"
56
+ expression = ['s', search, replace, 'g'].join('@')
57
+
58
+ sudo("sed -ri '#{expression}' /etc/hosts")
59
+ else
60
+ # Current hostname entry isn't in /etc/hosts, just append it
61
+ sudo("echo '127.0.1.1 #{fqdn} #{short_hostname}' >>/etc/hosts")
62
+ end
63
+ end
64
+
65
+ def refresh_hostname_service
66
+ sudo('hostname -F /etc/hostname')
67
+ end
68
+
69
+ def update_mailname
70
+ sudo('hostname --fqdn > /etc/mailname')
71
+ end
72
+
73
+ def renew_dhcp
74
+ sudo('ifdown -a; ifup -a; ifup eth0')
75
+ end
76
+
77
+ def fqdn
78
+ new_hostname
79
+ end
80
+
81
+ def short_hostname
82
+ new_hostname.split('.').first
83
+ end
84
+
85
+ def sudo(cmd, &block)
86
+ machine.communicate.sudo(cmd, &block)
87
+ end
88
+
89
+ def test(cmd)
90
+ machine.communicate.test(cmd)
91
+ end
92
+ end
93
+ end
94
+ end
95
+ end
@@ -0,0 +1,64 @@
1
+ # rubocop:disable Metrics/MethodLength
2
+ # rubocop:disable Metrics/AbcSize
3
+ # rubocop:disable Style/BracesAroundHashParameters
4
+ #
5
+ # FIXME: address disabled warnings
6
+ #
7
+ require 'set'
8
+ require 'tempfile'
9
+
10
+ require 'vagrant/util/template_renderer'
11
+
12
+ module VagrantPlugins
13
+ module GuestAlpine
14
+ module Cap
15
+ class ConfigureNetworks
16
+ include Vagrant::Util
17
+ def self.configure_networks(machine, networks)
18
+ machine.communicate.tap do |comm|
19
+ # First, remove any previous network modifications
20
+ # from the interface file.
21
+ comm.sudo("sed -e '/^#VAGRANT-BEGIN/,$ d' /etc/network/interfaces > /tmp/vagrant-network-interfaces.pre")
22
+ comm.sudo("sed -ne '/^#VAGRANT-END/,$ p' /etc/network/interfaces | tail -n +2 > /tmp/vagrant-network-interfaces.post")
23
+
24
+ # Accumulate the configurations to add to the interfaces file as
25
+ # well as what interfaces we're actually configuring since we use that
26
+ # later.
27
+ interfaces = Set.new
28
+ entries = []
29
+ networks.each do |network|
30
+ interfaces.add(network[:interface])
31
+ entry = TemplateRenderer.render("guests/alpine/network_#{network[:type]}", { options: network, template_root: GuestAlpine.source_root.join('templates') })
32
+ entries << entry
33
+ end
34
+
35
+ # Perform the careful dance necessary to reconfigure
36
+ # the network interfaces
37
+ temp = Tempfile.new('vagrant')
38
+ temp.binmode
39
+ temp.write(entries.join("\n"))
40
+ temp.close
41
+
42
+ comm.upload(temp.path, '/tmp/vagrant-network-entry')
43
+
44
+ # Bring down all the interfaces we're reconfiguring. By bringing down
45
+ # each specifically, we avoid reconfiguring eth0 (the NAT interface) so
46
+ # SSH never dies.
47
+ interfaces.each do |interface|
48
+ comm.sudo("/sbin/ifdown eth#{interface} 2> /dev/null")
49
+ comm.sudo("/sbin/ip addr flush dev eth#{interface} 2> /dev/null")
50
+ end
51
+
52
+ comm.sudo('cat /tmp/vagrant-network-interfaces.pre /tmp/vagrant-network-entry /tmp/vagrant-network-interfaces.post > /etc/network/interfaces')
53
+ comm.sudo('rm -f /tmp/vagrant-network-interfaces.pre /tmp/vagrant-network-entry /tmp/vagrant-network-interfaces.post')
54
+
55
+ # Bring back up each network interface, reconfigured
56
+ interfaces.each do |interface|
57
+ comm.sudo("/sbin/ifup eth#{interface}")
58
+ end
59
+ end
60
+ end
61
+ end
62
+ end
63
+ end
64
+ end
@@ -0,0 +1,21 @@
1
+ # rubocop:disable Style/RedundantBegin
2
+ # rubocop:disable Lint/HandleExceptions
3
+ #
4
+ # FIXME: address disabled warnings
5
+ #
6
+ module VagrantPlugins
7
+ module GuestAlpine
8
+ module Cap
9
+ class Halt
10
+ def self.halt(machine)
11
+ begin
12
+ machine.communicate.sudo('poweroff')
13
+ rescue Net::SSH::Disconnect, IOError
14
+ # Ignore, this probably means connection closed because it
15
+ # shut down and SSHd was stopped.
16
+ end
17
+ end
18
+ end
19
+ end
20
+ end
21
+ end
@@ -0,0 +1,15 @@
1
+ module VagrantPlugins
2
+ module GuestAlpine
3
+ module Cap
4
+ class NFSClient
5
+ def self.nfs_client_install(machine)
6
+ machine.communicate.tap do |comm|
7
+ comm.sudo('apk add nfs-utils')
8
+ comm.sudo('rc-update add rpc.statd')
9
+ comm.sudo('rc-service rpc.statd start')
10
+ end
11
+ end
12
+ end
13
+ end
14
+ end
15
+ end
@@ -0,0 +1,17 @@
1
+ module VagrantPlugins
2
+ module GuestAlpine
3
+ module Cap
4
+ class RSync
5
+ def self.rsync_installed(machine)
6
+ machine.communicate.test('test -f /usr/bin/rsync')
7
+ end
8
+
9
+ def self.rsync_install(machine)
10
+ machine.communicate.tap do |comm|
11
+ comm.sudo('apk add rsync')
12
+ end
13
+ end
14
+ end
15
+ end
16
+ end
17
+ end
@@ -0,0 +1,19 @@
1
+ begin
2
+ require 'vagrant'
3
+ rescue LoadError
4
+ raise 'The Vagrant Alpine Linux Guest plugin must be run within Vagrant.'
5
+ end
6
+
7
+ if Vagrant::VERSION < '1.7.0'
8
+ fail 'The vagrant-alpine plugin is only compatible with Vagrant 1.7+'
9
+ end
10
+
11
+ module VagrantPlugins
12
+ module GuestAlpine
13
+ class Guest < Vagrant.plugin('2', :guest)
14
+ def detect?(machine)
15
+ machine.communicate.test('cat /etc/alpine-release')
16
+ end
17
+ end
18
+ end
19
+ end
@@ -0,0 +1,53 @@
1
+ begin
2
+ require 'vagrant'
3
+ rescue LoadError
4
+ raise 'The Vagrant Alpine Linux Guest plugin must be run within Vagrant.'
5
+ end
6
+
7
+ if Vagrant::VERSION < '1.7.0'
8
+ fail 'The vagrant-alpine plugin is only compatible with Vagrant 1.7+'
9
+ end
10
+
11
+ module VagrantPlugins
12
+ module GuestAlpine
13
+ class Plugin < Vagrant.plugin('2')
14
+ name 'Alpine guest'
15
+ description 'Alpine Linux guest support.'
16
+
17
+ guest('alpine', 'linux') do
18
+ require File.expand_path('../guest', __FILE__)
19
+ Guest
20
+ end
21
+
22
+ guest_capability('alpine', 'configure_networks') do
23
+ require_relative 'cap/configure_networks'
24
+ Cap::ConfigureNetworks
25
+ end
26
+
27
+ guest_capability('alpine', 'halt') do
28
+ require_relative 'cap/halt'
29
+ Cap::Halt
30
+ end
31
+
32
+ guest_capability('alpine', 'change_host_name') do
33
+ require_relative 'cap/change_host_name'
34
+ Cap::ChangeHostName
35
+ end
36
+
37
+ guest_capability('alpine', 'nfs_client_install') do
38
+ require_relative 'cap/nfs_client'
39
+ Cap::NFSClient
40
+ end
41
+
42
+ guest_capability('alpine', 'rsync_installed') do
43
+ require_relative 'cap/rsync'
44
+ Cap::RSync
45
+ end
46
+
47
+ guest_capability('alpine', 'rsync_install') do
48
+ require_relative 'cap/rsync'
49
+ Cap::RSync
50
+ end
51
+ end
52
+ end
53
+ end
@@ -0,0 +1,6 @@
1
+ module VagrantPlugins
2
+ # Alpine Linux guest gem + plugin version
3
+ module GuestAlpine
4
+ VERSION = '0.1.1'
5
+ end
6
+ end
@@ -0,0 +1,128 @@
1
+
2
+ require 'spec_helper'
3
+
4
+ describe 'VagrantPlugins::GuestAlpine::Cap::ChangeHostname' do
5
+ let(:described_class) do
6
+ VagrantPlugins::GuestAlpine::Plugin.components.guest_capabilities[:alpine].get(:change_host_name)
7
+ end
8
+ let(:machine) { double('machine') }
9
+ let(:communicator) { VagrantTests::DummyCommunicator::Communicator.new(machine) }
10
+ let(:old_hostname) { 'oldhostname.olddomain.tld' }
11
+
12
+ before do
13
+ allow(machine).to receive(:communicate).and_return(communicator)
14
+ communicator.stub_command('hostname -f', stdout: old_hostname)
15
+ end
16
+
17
+ after do
18
+ communicator.verify_expectations!
19
+ end
20
+
21
+ describe '.change_host_name' do
22
+ it 'updates /etc/hostname on the machine' do
23
+ communicator.expect_command("echo 'newhostname' > /etc/hostname")
24
+ described_class.change_host_name(machine, 'newhostname.newdomain.tld')
25
+ end
26
+
27
+ it 'does nothing when the provided hostname is not different' do
28
+ described_class.change_host_name(machine, 'oldhostname.olddomain.tld')
29
+ expect(communicator.received_commands).to eq(['hostname -f'])
30
+ end
31
+
32
+ it 'refreshes the hostname service with the hostname command' do
33
+ communicator.expect_command('hostname -F /etc/hostname')
34
+ described_class.change_host_name(machine, 'newhostname.newdomain.tld')
35
+ end
36
+
37
+ it 'renews dhcp on the system with the new hostname' do
38
+ communicator.expect_command('ifdown -a; ifup -a; ifup eth0')
39
+ described_class.change_host_name(machine, 'newhostname.newdomain.tld')
40
+ end
41
+
42
+ describe 'flipping out the old hostname in /etc/hosts' do
43
+ let(:sed_command) do
44
+ # Here we run the change_host_name through and extract the recorded sed
45
+ # command from the dummy communicator
46
+ described_class.change_host_name(machine, 'newhostname.newdomain.tld')
47
+ communicator.received_commands.find { |cmd| cmd =~ /^sed/ }
48
+ end
49
+
50
+ # Now we extract the regexp from that sed command so we can do some
51
+ # verification on it
52
+ let(:expression) { sed_command.sub(%r{^sed -ri '\(.*\)' /etc/hosts$}, "\1") }
53
+ let(:search) { Regexp.new(expression.split('@')[1], Regexp::EXTENDED) }
54
+ let(:replace) { expression.split('@')[2] }
55
+
56
+ let(:grep_command) { "grep '#{old_hostname}' /etc/hosts" }
57
+
58
+ before do
59
+ communicator.stub_command(grep_command, exit_code: 0)
60
+ end
61
+
62
+ it 'works on an simple /etc/hosts file' do
63
+ original_etc_hosts = <<-ETC_HOSTS.gsub(/^ */, '')
64
+ 127.0.0.1 localhost
65
+ 127.0.1.1 oldhostname.olddomain.tld oldhostname
66
+ ETC_HOSTS
67
+
68
+ modified_etc_hosts = original_etc_hosts.gsub(search, replace)
69
+
70
+ expect(modified_etc_hosts).to eq <<-RESULT.gsub(/^ */, '')
71
+ 127.0.0.1 localhost
72
+ 127.0.1.1 newhostname.newdomain.tld newhostname
73
+ RESULT
74
+ end
75
+
76
+ it 'does not modify lines which contain similar hostnames' do
77
+ original_etc_hosts = <<-ETC_HOSTS.gsub(/^ */, '')
78
+ 127.0.0.1 localhost
79
+ 127.0.1.1 oldhostname.olddomain.tld oldhostname
80
+ # common prefix, but different fqdn
81
+ 192.168.12.34 oldhostname.olddomain.tld.different
82
+ # different characters at the dot
83
+ 192.168.34.56 oldhostname-olddomain.tld
84
+ ETC_HOSTS
85
+
86
+ modified_etc_hosts = original_etc_hosts.gsub(search, replace)
87
+
88
+ expect(modified_etc_hosts).to eq <<-RESULT.gsub(/^ */, '')
89
+ 127.0.0.1 localhost
90
+ 127.0.1.1 newhostname.newdomain.tld newhostname
91
+ # common prefix, but different fqdn
92
+ 192.168.12.34 oldhostname.olddomain.tld.different
93
+ # different characters at the dot
94
+ 192.168.34.56 oldhostname-olddomain.tld
95
+ RESULT
96
+ end
97
+
98
+ it "appends 127.0.1.1 if it isn't there" do
99
+ communicator.stub_command(grep_command, exit_code: 1)
100
+ described_class.change_host_name(machine, 'newhostname.newdomain.tld')
101
+
102
+ sed = communicator.received_commands.find { |cmd| cmd =~ /^sed/ }
103
+ expect(sed).to be_nil
104
+
105
+ echo = communicator.received_commands.find { |cmd| cmd =~ /^echo/ }
106
+ expect(echo).to_not be_nil
107
+ end
108
+
109
+ context 'when the old fqdn has a trailing dot' do
110
+ let(:old_hostname) { 'oldhostname.withtrailing.dot.' }
111
+
112
+ it 'modifies /etc/hosts properly' do
113
+ original_etc_hosts = <<-ETC_HOSTS.gsub(/^ */, '')
114
+ 127.0.0.1 localhost
115
+ 127.0.1.1 oldhostname.withtrailing.dot. oldhostname
116
+ ETC_HOSTS
117
+
118
+ modified_etc_hosts = original_etc_hosts.gsub(search, replace)
119
+
120
+ expect(modified_etc_hosts).to eq <<-RESULT.gsub(/^ */, '')
121
+ 127.0.0.1 localhost
122
+ 127.0.1.1 newhostname.newdomain.tld newhostname
123
+ RESULT
124
+ end
125
+ end
126
+ end
127
+ end
128
+ end
@@ -0,0 +1,40 @@
1
+
2
+ require 'spec_helper'
3
+
4
+ describe 'VagrantPlugins::GuestAlpine::Cap::ConfigureNetworks' do
5
+ let(:described_class) do
6
+ VagrantPlugins::GuestAlpine::Plugin.components.guest_capabilities[:alpine].get(:configure_networks)
7
+ end
8
+ let(:machine) { double('machine') }
9
+ let(:communicator) { VagrantTests::DummyCommunicator::Communicator.new(machine) }
10
+
11
+ before do
12
+ allow(machine).to receive(:communicate).and_return(communicator)
13
+ end
14
+
15
+ after do
16
+ communicator.verify_expectations!
17
+ end
18
+
19
+ it 'should configure networks' do
20
+ networks = [
21
+ { type: :static, ip: '192.168.10.10', netmask: '255.255.255.0', interface: 0, name: 'eth0' },
22
+ { type: :dhcp, interface: 1, name: 'eth1' }
23
+ ]
24
+
25
+ communicator.should_receive(:sudo).with("sed -e '/^#VAGRANT-BEGIN/,$ d' /etc/network/interfaces > /tmp/vagrant-network-interfaces.pre")
26
+ communicator.should_receive(:sudo).with("sed -ne '/^#VAGRANT-END/,$ p' /etc/network/interfaces | tail -n +2 > /tmp/vagrant-network-interfaces.post")
27
+ communicator.should_receive(:sudo).with('/sbin/ifdown eth0 2> /dev/null')
28
+ communicator.should_receive(:sudo).with('/sbin/ip addr flush dev eth0 2> /dev/null')
29
+ communicator.should_receive(:sudo).with('/sbin/ifdown eth1 2> /dev/null')
30
+ communicator.should_receive(:sudo).with('/sbin/ip addr flush dev eth1 2> /dev/null')
31
+ communicator.should_receive(:sudo).with('cat /tmp/vagrant-network-interfaces.pre /tmp/vagrant-network-entry /tmp/vagrant-network-interfaces.post > /etc/network/interfaces')
32
+ communicator.should_receive(:sudo).with('rm -f /tmp/vagrant-network-interfaces.pre /tmp/vagrant-network-entry /tmp/vagrant-network-interfaces.post')
33
+ communicator.should_receive(:sudo).with('/sbin/ifup eth0')
34
+ communicator.should_receive(:sudo).with('/sbin/ifup eth1')
35
+
36
+ allow_message_expectations_on_nil
37
+
38
+ described_class.configure_networks(machine, networks)
39
+ end
40
+ end
@@ -0,0 +1,24 @@
1
+
2
+ require 'spec_helper'
3
+
4
+ describe 'VagrantPlugins::GuestAlpine::Cap::Halt' do
5
+ let(:described_class) do
6
+ VagrantPlugins::GuestAlpine::Plugin.components.guest_capabilities[:alpine].get(:halt)
7
+ end
8
+ let(:machine) { double('machine') }
9
+ let(:communicator) { VagrantTests::DummyCommunicator::Communicator.new(machine) }
10
+
11
+ before do
12
+ allow(machine).to receive(:communicate).and_return(communicator)
13
+ end
14
+
15
+ after do
16
+ communicator.verify_expectations!
17
+ end
18
+
19
+ it 'should halt guest' do
20
+ communicator.should_receive(:sudo).with('poweroff')
21
+ allow_message_expectations_on_nil
22
+ described_class.halt(machine)
23
+ end
24
+ end
@@ -0,0 +1,27 @@
1
+
2
+ require 'spec_helper'
3
+
4
+ describe 'VagrantPlugins::GuestAlpine::Cap::NFSClient' do
5
+ let(:described_class) do
6
+ VagrantPlugins::GuestAlpine::Plugin.components.guest_capabilities[:alpine].get(:nfs_client_install)
7
+ end
8
+ let(:machine) { double('machine') }
9
+ let(:communicator) { VagrantTests::DummyCommunicator::Communicator.new(machine) }
10
+
11
+ before do
12
+ allow(machine).to receive(:communicate).and_return(communicator)
13
+ end
14
+
15
+ after do
16
+ communicator.verify_expectations!
17
+ end
18
+
19
+ it 'should install nfs client' do
20
+ communicator.should_receive(:sudo).with('apk add nfs-utils')
21
+ communicator.should_receive(:sudo).with('rc-update add rpc.statd')
22
+ communicator.should_receive(:sudo).with('rc-service rpc.statd start')
23
+
24
+ allow_message_expectations_on_nil
25
+ described_class.nfs_client_install(machine)
26
+ end
27
+ end
@@ -0,0 +1,35 @@
1
+
2
+ require 'spec_helper'
3
+
4
+ describe 'VagrantPlugins::GuestAlpine::Cap::RSync' do
5
+ let(:machine) { double('machine') }
6
+ let(:communicator) { VagrantTests::DummyCommunicator::Communicator.new(machine) }
7
+
8
+ before do
9
+ allow(machine).to receive(:communicate).and_return(communicator)
10
+ end
11
+
12
+ after do
13
+ communicator.verify_expectations!
14
+ end
15
+
16
+ let(:described_class) do
17
+ VagrantPlugins::GuestAlpine::Plugin.components.guest_capabilities[:alpine].get(:rsync_install)
18
+ end
19
+
20
+ it 'should install rsync' do
21
+ communicator.should_receive(:sudo).with('apk add rsync')
22
+ allow_message_expectations_on_nil
23
+ described_class.rsync_install(machine)
24
+ end
25
+
26
+ let(:described_class) do
27
+ VagrantPlugins::GuestAlpine::Plugin.components.guest_capabilities[:alpine].get(:rsync_installed)
28
+ end
29
+
30
+ it 'should verify rsync installed' do
31
+ communicator.should_receive(:test).with('test -f /usr/bin/rsync')
32
+ allow_message_expectations_on_nil
33
+ described_class.rsync_installed(machine)
34
+ end
35
+ end
@@ -0,0 +1,29 @@
1
+ require 'vagrant-alpine/guest'
2
+
3
+ require 'vagrant-alpine/plugin'
4
+
5
+ require 'vagrant-alpine/cap/change_host_name'
6
+ require 'vagrant-alpine/cap/configure_networks'
7
+ require 'vagrant-alpine/cap/halt'
8
+ require 'vagrant-alpine/cap/rsync'
9
+ require 'vagrant-alpine/cap/nfs_client'
10
+
11
+ describe VagrantPlugins::GuestAlpine::Plugin do
12
+ it 'should be loaded with alpine' do
13
+ expect(described_class.components.guests[:alpine].first).to eq(VagrantPlugins::GuestAlpine::Guest)
14
+ end
15
+
16
+ {
17
+ change_host_name: VagrantPlugins::GuestAlpine::Cap::ChangeHostName,
18
+ configure_networks: VagrantPlugins::GuestAlpine::Cap::ConfigureNetworks,
19
+ halt: VagrantPlugins::GuestAlpine::Cap::Halt,
20
+ rsync_installed: VagrantPlugins::GuestAlpine::Cap::RSync,
21
+ rsync_install: VagrantPlugins::GuestAlpine::Cap::RSync,
22
+ nfs_client_install: VagrantPlugins::GuestAlpine::Cap::NFSClient
23
+ }.each do |cap, cls|
24
+ it "should be capable of #{cap} with alpine" do
25
+ expect(described_class.components.guest_capabilities[:alpine][cap])
26
+ .to eq(cls)
27
+ end
28
+ end
29
+ end
@@ -0,0 +1,3 @@
1
+ require 'vagrant'
2
+ require 'support/dummy_communicator'
3
+
@@ -0,0 +1,84 @@
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
+
84
+
@@ -0,0 +1,13 @@
1
+ #VAGRANT-BEGIN
2
+ # The contents below are automatically generated by Vagrant. Do not modify.
3
+ auto eth<%= options[:interface] %>
4
+ iface eth<%= options[:interface] %> inet dhcp
5
+ <% if !options[:use_dhcp_assigned_default_route] %>
6
+ post-up route del default dev $IFACE || true
7
+ <% else %>
8
+ # We need to disable eth0, see GH-2648
9
+ post-up route del default dev eth0
10
+ post-up dhclient $IFACE
11
+ pre-down route add default dev eth0
12
+ <% end %>
13
+ #VAGRANT-END
@@ -0,0 +1,7 @@
1
+ #VAGRANT-BEGIN
2
+ # The contents below are automatically generated by Vagrant. Do not modify.
3
+ auto eth<%= options[:interface] %>
4
+ iface eth<%= options[:interface] %> inet static
5
+ address <%= options[:ip] %>
6
+ netmask <%= options[:netmask] %>
7
+ #VAGRANT-END
@@ -0,0 +1,26 @@
1
+ # coding: utf-8
2
+ lib = File.expand_path('../lib', __FILE__)
3
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
+ require 'vagrant-alpine/version'
5
+
6
+ Gem::Specification.new do |spec|
7
+ spec.name = 'vagrant-alpine'
8
+ spec.version = VagrantPlugins::GuestAlpine::VERSION
9
+ spec.license = 'MIT'
10
+
11
+ spec.authors = ['matt maier']
12
+ spec.email = ['maier@users.noreply.github.com']
13
+
14
+ spec.summary = 'Enables Vagrant to manage Alpine Linux Guests.'
15
+ spec.description = 'Enables Vagrant to manage Alpine Linux Guests.'
16
+ spec.homepage = 'https://github.com/maier/vagrant-alpine'
17
+
18
+ spec.add_development_dependency 'rake', '~> 10.4.2'
19
+ spec.add_development_dependency 'rspec-core', '~> 2.14'
20
+ spec.add_development_dependency 'rspec-expectations', '~> 2.14'
21
+ spec.add_development_dependency 'rspec-mocks', '~> 2.14'
22
+
23
+ spec.files = `git ls-files -z`.split("\x0")
24
+ spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
25
+ spec.require_path = 'lib'
26
+ end
metadata ADDED
@@ -0,0 +1,131 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: vagrant-alpine
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.1
5
+ platform: ruby
6
+ authors:
7
+ - matt maier
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2015-04-21 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: rake
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - "~>"
18
+ - !ruby/object:Gem::Version
19
+ version: 10.4.2
20
+ type: :development
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - "~>"
25
+ - !ruby/object:Gem::Version
26
+ version: 10.4.2
27
+ - !ruby/object:Gem::Dependency
28
+ name: rspec-core
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - "~>"
32
+ - !ruby/object:Gem::Version
33
+ version: '2.14'
34
+ type: :development
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - "~>"
39
+ - !ruby/object:Gem::Version
40
+ version: '2.14'
41
+ - !ruby/object:Gem::Dependency
42
+ name: rspec-expectations
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - "~>"
46
+ - !ruby/object:Gem::Version
47
+ version: '2.14'
48
+ type: :development
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - "~>"
53
+ - !ruby/object:Gem::Version
54
+ version: '2.14'
55
+ - !ruby/object:Gem::Dependency
56
+ name: rspec-mocks
57
+ requirement: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - "~>"
60
+ - !ruby/object:Gem::Version
61
+ version: '2.14'
62
+ type: :development
63
+ prerelease: false
64
+ version_requirements: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - "~>"
67
+ - !ruby/object:Gem::Version
68
+ version: '2.14'
69
+ description: Enables Vagrant to manage Alpine Linux Guests.
70
+ email:
71
+ - maier@users.noreply.github.com
72
+ executables: []
73
+ extensions: []
74
+ extra_rdoc_files: []
75
+ files:
76
+ - ".gitignore"
77
+ - ".rspec"
78
+ - ".rubocop.yml"
79
+ - ".ruby-gemset"
80
+ - ".ruby-version"
81
+ - ".travis.yml"
82
+ - Gemfile
83
+ - LICENSE
84
+ - README.md
85
+ - Rakefile
86
+ - Vagrantfile.example
87
+ - lib/vagrant-alpine.rb
88
+ - lib/vagrant-alpine/cap/change_host_name.rb
89
+ - lib/vagrant-alpine/cap/configure_networks.rb
90
+ - lib/vagrant-alpine/cap/halt.rb
91
+ - lib/vagrant-alpine/cap/nfs_client.rb
92
+ - lib/vagrant-alpine/cap/rsync.rb
93
+ - lib/vagrant-alpine/guest.rb
94
+ - lib/vagrant-alpine/plugin.rb
95
+ - lib/vagrant-alpine/version.rb
96
+ - spec/cap/change_host_name_spec.rb
97
+ - spec/cap/configure_networks_spec.rb
98
+ - spec/cap/halt_spec.rb
99
+ - spec/cap/nfs_client_spec.rb
100
+ - spec/cap/rsync_spec.rb
101
+ - spec/guest_spec.rb
102
+ - spec/spec_helper.rb
103
+ - spec/support/dummy_communicator.rb
104
+ - templates/guests/alpine/network_dhcp.erb
105
+ - templates/guests/alpine/network_static.erb
106
+ - vagrant-alpine.gemspec
107
+ homepage: https://github.com/maier/vagrant-alpine
108
+ licenses:
109
+ - MIT
110
+ metadata: {}
111
+ post_install_message:
112
+ rdoc_options: []
113
+ require_paths:
114
+ - lib
115
+ required_ruby_version: !ruby/object:Gem::Requirement
116
+ requirements:
117
+ - - ">="
118
+ - !ruby/object:Gem::Version
119
+ version: '0'
120
+ required_rubygems_version: !ruby/object:Gem::Requirement
121
+ requirements:
122
+ - - ">="
123
+ - !ruby/object:Gem::Version
124
+ version: '0'
125
+ requirements: []
126
+ rubyforge_project:
127
+ rubygems_version: 2.4.6
128
+ signing_key:
129
+ specification_version: 4
130
+ summary: Enables Vagrant to manage Alpine Linux Guests.
131
+ test_files: []