vagrant-hmurca 0.1.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.
- checksums.yaml +7 -0
- data/.gitignore +20 -0
- data/Gemfile +9 -0
- data/LICENSE.txt +22 -0
- data/README.md +31 -0
- data/Rakefile +10 -0
- data/Vagrantfile +15 -0
- data/dot_gitignore +2 -0
- data/hmurca.conf +12 -0
- data/hmurca.conf.sample +32 -0
- data/lib/vagrant-hmurca.rb +1 -0
- data/lib/vagrant/hmurca.rb +33 -0
- data/lib/vagrant/hmurca/command.rb +75 -0
- data/lib/vagrant/hmurca/config_parser.rb +225 -0
- data/lib/vagrant/hmurca/errors.rb +96 -0
- data/lib/vagrant/hmurca/templates/Vagrantfile +15 -0
- data/lib/vagrant/hmurca/templates/dot_gitignore +2 -0
- data/lib/vagrant/hmurca/templates/hmurca.conf.sample.tt +32 -0
- data/lib/vagrant/hmurca/vagrantfile.rb +36 -0
- data/lib/vagrant/hmurca/version.rb +5 -0
- data/test/config_parser_test.rb +590 -0
- data/test/helper.rb +6 -0
- data/test/vagrant_command_test.rb +69 -0
- data/test/version_test.rb +7 -0
- data/vagrant-hmurca.gemspec +26 -0
- metadata +142 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: 6e1d3d8b8c0364076264a98dfb745de017382bae
|
4
|
+
data.tar.gz: 820fe62cfe4b5ccbe417c61d0867ca08e3401f58
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: 1d11604f05257f785cb599128a9a4b4f1bd0709579163ca15d997e793c62e33aaa06c7c7fc75dacecdd8f3cdf9df5ded0cd383bd3376a82a9adfff79143bebfb
|
7
|
+
data.tar.gz: ea182236bd13693bcbf1d79077acfb558c9e01116c5b0913b0ee4553583206bfd46d5eab7bc157e9957cd83f1337238576a397032b4388c19e118cc747600007
|
data/.gitignore
ADDED
data/Gemfile
ADDED
data/LICENSE.txt
ADDED
@@ -0,0 +1,22 @@
|
|
1
|
+
Copyright (c) 2014 Kris Kovalik
|
2
|
+
|
3
|
+
MIT License
|
4
|
+
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
6
|
+
a copy of this software and associated documentation files (the
|
7
|
+
"Software"), to deal in the Software without restriction, including
|
8
|
+
without limitation the rights to use, copy, modify, merge, publish,
|
9
|
+
distribute, sublicense, and/or sell copies of the Software, and to
|
10
|
+
permit persons to whom the Software is furnished to do so, subject to
|
11
|
+
the following conditions:
|
12
|
+
|
13
|
+
The above copyright notice and this permission notice shall be
|
14
|
+
included in all copies or substantial portions of the Software.
|
15
|
+
|
16
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
17
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
18
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
19
|
+
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
20
|
+
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
21
|
+
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
22
|
+
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/README.md
ADDED
@@ -0,0 +1,31 @@
|
|
1
|
+
# Hmurca's Vagrant Kit
|
2
|
+
|
3
|
+
This toolkit (codename *Hobo*) is a *Vagrant* plugin that wraps and simplifies
|
4
|
+
building of *Hmurca* powered development formations.
|
5
|
+
|
6
|
+
## Installation
|
7
|
+
|
8
|
+
Install this gem as a *Vagrant* plugin.
|
9
|
+
|
10
|
+
$ vagrant plugin install vagrant-hmurca
|
11
|
+
|
12
|
+
## Usage
|
13
|
+
|
14
|
+
Check project documentation [here](http://docs.hmurca.com/en/latest/vagrant-hmurca.html).
|
15
|
+
|
16
|
+
## End-to-end testing
|
17
|
+
|
18
|
+
Because there's not mean to run end-to-end test automatically (for example Vagrant
|
19
|
+
doesn't work on drone.io that we use for CI testing), you should test it manually
|
20
|
+
before making any changes. There's a test `Vagrantfile` and `hmurca.conf` in project
|
21
|
+
root directory, use them to bring the formation up and check if everything works as
|
22
|
+
expected. Run the following from project root directory:
|
23
|
+
|
24
|
+
$ bundle exec vagrant up
|
25
|
+
|
26
|
+
## Contributing
|
27
|
+
|
28
|
+
1. Work on your changes in a feature branch.
|
29
|
+
2. Make sure that tests are passing.
|
30
|
+
3. Send a pull request.
|
31
|
+
4. Wait for feedback.
|
data/Rakefile
ADDED
data/Vagrantfile
ADDED
@@ -0,0 +1,15 @@
|
|
1
|
+
# -*- mode: ruby -*-
|
2
|
+
# vi: set ft=ruby :
|
3
|
+
|
4
|
+
# WARNING: Never ever edit this file if you want Hmurca Kit to work properly!
|
5
|
+
|
6
|
+
ui = Vagrant::UI::Colored.new
|
7
|
+
|
8
|
+
begin
|
9
|
+
require 'vagrant-hmurca'
|
10
|
+
Vagrant::Hmurca.configure!
|
11
|
+
rescue LoadError => err
|
12
|
+
ui.error("Oops! Looks like `vagrant-hmurca' plugin is not installed!")
|
13
|
+
ui.error("Execute `vagrant plugin install vagrant-hmurca` to fix this error...")
|
14
|
+
exit(1)
|
15
|
+
end
|
data/dot_gitignore
ADDED
data/hmurca.conf
ADDED
data/hmurca.conf.sample
ADDED
@@ -0,0 +1,32 @@
|
|
1
|
+
# hmurca.conf - The Hmurca Vagrant Kit configuration file.
|
2
|
+
#
|
3
|
+
# If this file is named `hmurca.conf.sample`, copy it to `hmurca.conf`
|
4
|
+
# and adjust settings specific for your host machine or your own preferences.
|
5
|
+
|
6
|
+
# General setup
|
7
|
+
#-------------------------------------------------------------------------------
|
8
|
+
|
9
|
+
# Domain name used by this formation.
|
10
|
+
domain example
|
11
|
+
|
12
|
+
# Name of the base box from Vagrant Cloud.
|
13
|
+
base-box hmurca/debian75-x64
|
14
|
+
|
15
|
+
# Configure synchronized folders from host to guests...
|
16
|
+
sync-folder . /vagrant
|
17
|
+
|
18
|
+
# Use Network File System to share folders?
|
19
|
+
use-nfs yes
|
20
|
+
|
21
|
+
# Nodes configuration...
|
22
|
+
#-------------------------------------------------------------------------------
|
23
|
+
|
24
|
+
node
|
25
|
+
# Short host name of the node.
|
26
|
+
name all-in-one
|
27
|
+
# The number of virtual processors.
|
28
|
+
cpus 2
|
29
|
+
# The number of virtual memory limit.
|
30
|
+
memory 1024
|
31
|
+
# Configure which ports to forward from guest to host...
|
32
|
+
forward-port 80 8080
|
@@ -0,0 +1 @@
|
|
1
|
+
require 'vagrant/hmurca'
|
@@ -0,0 +1,33 @@
|
|
1
|
+
require "vagrant"
|
2
|
+
require "booby"
|
3
|
+
|
4
|
+
module Vagrant
|
5
|
+
module Hmurca
|
6
|
+
require "vagrant/hmurca/version"
|
7
|
+
require "vagrant/hmurca/errors"
|
8
|
+
require "vagrant/hmurca/config_parser"
|
9
|
+
|
10
|
+
# Internal: Hmurca vagrant plugin.
|
11
|
+
class Plugin < Vagrant.plugin(2)
|
12
|
+
name "Hmurca"
|
13
|
+
description "Hmurka's Vagrant Kit"
|
14
|
+
|
15
|
+
command "hmurca", primary: true do
|
16
|
+
require "vagrant/hmurca/command"
|
17
|
+
Command
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
# Public: Sets up vagrant configuration.
|
22
|
+
def self.configure!
|
23
|
+
begin
|
24
|
+
config_file = File.join(Dir.pwd, "hmurca.conf")
|
25
|
+
$CONF = ConfigParser.parse_file(config_file)
|
26
|
+
load(File.expand_path("../hmurca/vagrantfile.rb", __FILE__))
|
27
|
+
rescue ParserError, Errno::ENOENT => err
|
28
|
+
$stderr.write("ERROR: #{err.to_s}\n")
|
29
|
+
exit(1)
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
@@ -0,0 +1,75 @@
|
|
1
|
+
require "thor"
|
2
|
+
|
3
|
+
module Vagrant
|
4
|
+
module Hmurca
|
5
|
+
# Internal: Files generator for hmurca default command.
|
6
|
+
class Generator < Thor::Group
|
7
|
+
include Thor::Actions
|
8
|
+
|
9
|
+
argument :domain
|
10
|
+
argument :project_root, :optional => true, :default => "."
|
11
|
+
|
12
|
+
def self.source_root
|
13
|
+
File.expand_path("../templates", __FILE__)
|
14
|
+
end
|
15
|
+
|
16
|
+
def create_project_root
|
17
|
+
empty_directory(project_root)
|
18
|
+
end
|
19
|
+
|
20
|
+
def create_hmurca_conf_sample
|
21
|
+
target = File.join(project_root, "hmurca.conf.sample")
|
22
|
+
template("hmurca.conf.sample.tt", target)
|
23
|
+
end
|
24
|
+
|
25
|
+
def copy_dot_gitignore
|
26
|
+
target = File.join(project_root, ".gitignore")
|
27
|
+
copy_file("dot_gitignore", target)
|
28
|
+
end
|
29
|
+
|
30
|
+
def copy_vagrantfile
|
31
|
+
target = File.join(project_root, "Vagrantfile")
|
32
|
+
copy_file("Vagrantfile", target)
|
33
|
+
end
|
34
|
+
end
|
35
|
+
|
36
|
+
# Internal: Hmurca command that generates project scaffold.
|
37
|
+
class Command < Vagrant.plugin(2, :command)
|
38
|
+
def self.synopsis
|
39
|
+
"initializes hmurca-powered project"
|
40
|
+
end
|
41
|
+
|
42
|
+
def execute
|
43
|
+
argv = parse_options(option_parser)
|
44
|
+
|
45
|
+
if argv.empty?
|
46
|
+
@env.ui.error "You must specify domain name for development formation."
|
47
|
+
exit(1)
|
48
|
+
end
|
49
|
+
|
50
|
+
if argv.size > 2
|
51
|
+
@env.ui.error "Too many actual arguments."
|
52
|
+
exit(1)
|
53
|
+
end
|
54
|
+
|
55
|
+
Generator.start(argv)
|
56
|
+
end
|
57
|
+
|
58
|
+
def option_parser
|
59
|
+
OptionParser.new do |o|
|
60
|
+
o.banner = "Usage: vagrant hmurca DOMAIN [ROOT]"
|
61
|
+
|
62
|
+
o.on("-h", "--help", "Print this help.") do
|
63
|
+
safe_puts(o.help)
|
64
|
+
exit(0)
|
65
|
+
end
|
66
|
+
|
67
|
+
o.on("-p", "--plugin-version", "Print version of installed Hmurca Kit.") do
|
68
|
+
safe_puts("Hmurca Vagrant Kit #{Vagrant::Hmurca::VERSION}")
|
69
|
+
exit(0)
|
70
|
+
end
|
71
|
+
end
|
72
|
+
end
|
73
|
+
end
|
74
|
+
end
|
75
|
+
end
|
@@ -0,0 +1,225 @@
|
|
1
|
+
module Vagrant
|
2
|
+
module Hmurca
|
3
|
+
# Public: Processor that handles node definition groups.
|
4
|
+
class NodeGroupProcessor
|
5
|
+
ARITY = {
|
6
|
+
'name' => 1,
|
7
|
+
'cpus' => 1,
|
8
|
+
'memory' => 1,
|
9
|
+
'forward-port' => 2,
|
10
|
+
}
|
11
|
+
|
12
|
+
attr_reader :name, :cpus, :memory, :forward_ports
|
13
|
+
|
14
|
+
def initialize(line_no, name=nil)
|
15
|
+
@name = name
|
16
|
+
@forward_ports = {}
|
17
|
+
|
18
|
+
return unless name
|
19
|
+
raise InvalidNodeNameError.new(name, line_no) unless valid_name?(name)
|
20
|
+
end
|
21
|
+
|
22
|
+
def process(line_no, cmd, *args)
|
23
|
+
case cmd
|
24
|
+
when "name"
|
25
|
+
n = args.first
|
26
|
+
raise InvalidNodeNameError.new(n, line_no) unless valid_name?(n)
|
27
|
+
@name = n
|
28
|
+
when "cpus"
|
29
|
+
@cpus = parse_int(args.first, line_no)
|
30
|
+
when "memory"
|
31
|
+
@memory = parse_int(args.first, line_no)
|
32
|
+
when "forward-port"
|
33
|
+
guest, host = parse_int(args[0], line_no), parse_int(args[1], line_no)
|
34
|
+
|
35
|
+
if @forward_ports[host]
|
36
|
+
raise NodeForwardPortDuplicatedError.new(host)
|
37
|
+
end
|
38
|
+
|
39
|
+
@forward_ports[host] = guest
|
40
|
+
else
|
41
|
+
return false
|
42
|
+
end
|
43
|
+
|
44
|
+
true
|
45
|
+
end
|
46
|
+
|
47
|
+
# Internal: Validates post-parsing constraints, like presence checking, etc.
|
48
|
+
#
|
49
|
+
# Returns itself.
|
50
|
+
def validate!
|
51
|
+
raise NoNodeNameSpecifiedError unless self.name
|
52
|
+
raise NoNodeCpusCountSpecifiedError.new(name) unless self.cpus
|
53
|
+
raise NoNodeMemorySizeSpecifiedError.new(name) unless self.memory
|
54
|
+
|
55
|
+
return self
|
56
|
+
end
|
57
|
+
|
58
|
+
# Internal: Checks if given node name is valid.
|
59
|
+
#
|
60
|
+
# name - The String node name to check.
|
61
|
+
#
|
62
|
+
# Return true if node name is valid.
|
63
|
+
def valid_name?(name)
|
64
|
+
name =~ /^[\w\d\-]+$/
|
65
|
+
end
|
66
|
+
|
67
|
+
# Internal: Parses given string value and converts it to integer if
|
68
|
+
# it's possible. If given value is not a valid integer, it raises
|
69
|
+
# an error.
|
70
|
+
#
|
71
|
+
# v - The String value to covnert.
|
72
|
+
# line_no - The Integer number of the current parsed line.
|
73
|
+
#
|
74
|
+
# Returns converted int value.
|
75
|
+
# Raises InvalidIntegerValueError if value can't be converted.
|
76
|
+
def parse_int(v, line_no)
|
77
|
+
v_int = v.to_i
|
78
|
+
raise InvalidIntegerValueError.new(v, line_no) if v_int.to_s != v
|
79
|
+
v_int
|
80
|
+
end
|
81
|
+
end
|
82
|
+
|
83
|
+
# Public: Processor for top level configuration.
|
84
|
+
class GeneralProcessor
|
85
|
+
ARITY = {
|
86
|
+
'domain' => 1,
|
87
|
+
'base-box' => 1,
|
88
|
+
'sync-folder' => 2,
|
89
|
+
'use-nfs' => 1
|
90
|
+
}
|
91
|
+
|
92
|
+
attr_reader :domain, :base_box, :sync_folders, :use_nfs, :nodes
|
93
|
+
|
94
|
+
def initialize
|
95
|
+
@nodes = []
|
96
|
+
@sync_folders = []
|
97
|
+
end
|
98
|
+
|
99
|
+
def process(line_no, cmd, *args)
|
100
|
+
case cmd
|
101
|
+
when 'domain'
|
102
|
+
d = args.first
|
103
|
+
raise InvalidDomainNameError.new(d, line_no) unless valid_domain?(d)
|
104
|
+
@domain = d
|
105
|
+
when 'base-box'
|
106
|
+
b = args.first
|
107
|
+
@base_box = b
|
108
|
+
when 'sync-folder'
|
109
|
+
host, guest = *args
|
110
|
+
|
111
|
+
unless File.directory?(host)
|
112
|
+
raise SyncedFolderNotFoundError.new(host, line_no)
|
113
|
+
end
|
114
|
+
|
115
|
+
@sync_folders << [host, guest]
|
116
|
+
when 'use-nfs'
|
117
|
+
@use_nfs = parse_bool(args.first, line_no)
|
118
|
+
when 'node'
|
119
|
+
if args.size > 1
|
120
|
+
raise Booby::InvalidNumberOfParametersError.new(
|
121
|
+
"0 or 1", args.size, cmd, line_no
|
122
|
+
)
|
123
|
+
end
|
124
|
+
|
125
|
+
@nodes << (p = NodeGroupProcessor.new(line_no, *args))
|
126
|
+
return p
|
127
|
+
else
|
128
|
+
return false
|
129
|
+
end
|
130
|
+
|
131
|
+
true
|
132
|
+
end
|
133
|
+
|
134
|
+
# Public: Produces reverse domain name to use as a box prefix.
|
135
|
+
def name_as_prefix
|
136
|
+
return self.domain.split('.').reverse.join('.')
|
137
|
+
end
|
138
|
+
|
139
|
+
# Internal: Validates post-parsing constraints, like presence checking, etc.
|
140
|
+
#
|
141
|
+
# Returns itself.
|
142
|
+
def validate!
|
143
|
+
raise NoDomainSpecifiedError unless self.domain
|
144
|
+
|
145
|
+
# Validate each node separately...
|
146
|
+
self.nodes.each(&:validate!)
|
147
|
+
|
148
|
+
# Check for duplicated nodes...
|
149
|
+
# XXX: Yes this way of checking might be slow, but who cares with max
|
150
|
+
# 10 defined nodes?
|
151
|
+
unique_nodes = {}
|
152
|
+
self.nodes.each do |node|
|
153
|
+
name = node.name
|
154
|
+
raise NodeDuplicatedError.new(name) if unique_nodes[name]
|
155
|
+
unique_nodes[name] = true
|
156
|
+
end
|
157
|
+
|
158
|
+
# Check for duplicated forward ports...
|
159
|
+
# XXX: Same here in terms of efficiency.
|
160
|
+
unique_ports = {}
|
161
|
+
self.nodes.each do |node|
|
162
|
+
node.forward_ports.keys.each do |port|
|
163
|
+
raise NodeForwardPortDuplicatedError.new(port) if unique_ports[port]
|
164
|
+
unique_ports[port] = true
|
165
|
+
end
|
166
|
+
end
|
167
|
+
|
168
|
+
return self
|
169
|
+
end
|
170
|
+
|
171
|
+
# Internal: Checks weather given domain name is valid or not.
|
172
|
+
#
|
173
|
+
# domain - The String domain name to check.
|
174
|
+
#
|
175
|
+
# Returns true if domain name is valid.
|
176
|
+
def valid_domain?(domain)
|
177
|
+
domain =~ /^[a-z0-9]+([\-\.]{1}[a-z0-9]+)*\.[a-z]{2,5}(:[0-9]{1,5})?(\/.*)?$/ix
|
178
|
+
end
|
179
|
+
|
180
|
+
# Internal: Converts given string value to boolean. If value isn't one
|
181
|
+
# of 'yes' or 'no', then it raises an error.
|
182
|
+
#
|
183
|
+
# v - The String value to covnert.
|
184
|
+
# line_no - The Integer number of the current parsed line.
|
185
|
+
#
|
186
|
+
# Returns true if value equals 'yes', false if 'no'.
|
187
|
+
# Raises InvalidBooleanValueError if value can't be converted.
|
188
|
+
def parse_bool(v, line_no)
|
189
|
+
case v
|
190
|
+
when "yes"
|
191
|
+
true
|
192
|
+
when "no"
|
193
|
+
false
|
194
|
+
else
|
195
|
+
raise InvalidBooleanValueError.new(v, line_no)
|
196
|
+
end
|
197
|
+
end
|
198
|
+
end
|
199
|
+
|
200
|
+
# Public: Global entry point to config parser features.
|
201
|
+
module ConfigParser
|
202
|
+
PROCESSOR = GeneralProcessor
|
203
|
+
|
204
|
+
# Public: Loads given file and parses it.
|
205
|
+
#
|
206
|
+
# fname - The String name of the config file.
|
207
|
+
#
|
208
|
+
# Returns filled processor.
|
209
|
+
def self.parse_file(fname)
|
210
|
+
p = Booby.open(fname)
|
211
|
+
p.parse_with(PROCESSOR).validate!
|
212
|
+
end
|
213
|
+
|
214
|
+
# Public: Parses given source of the config file.
|
215
|
+
#
|
216
|
+
# str - The String source to parse.
|
217
|
+
#
|
218
|
+
# Returns filled processor.
|
219
|
+
def self.parse_string(str)
|
220
|
+
p = Booby.prepare(str)
|
221
|
+
p.parse_with(PROCESSOR).validate!
|
222
|
+
end
|
223
|
+
end
|
224
|
+
end
|
225
|
+
end
|