hosties 1.1.0.alpha → 1.1.0.alpha2
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/lib/hosties/definitions.rb +118 -111
- data/lib/hosties/easydata.rb +35 -8
- data/lib/hosties/reification.rb +87 -83
- data/spec/definitions_spec.rb +33 -6
- data/spec/easydata_spec.rb +2 -2
- data/spec/hosties_spec.rb +23 -5
- data/spec/reification_spec.rb +5 -5
- metadata +1 -1
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: c5aad13eda9a31ed69dda41c369424d5311e4d60
|
4
|
+
data.tar.gz: 3a37f4fed44c321a37ec488580e164e7c521fd55
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 2c27fff8d37d95deb87f6387c360e5eb7a259aced2e88fd1ea730928100b1b9990bad978261b6ed0ce20d8806a8dc1b575dd1b75d12f24142965d9e8db120c8e
|
7
|
+
data.tar.gz: 0e18fd57a070555657954bb4433a147e6c4a9dd10a51e9a5e59b28976cf9f892de63459219147cacb71d58a9e710008fd5123e98f6e708335415e7b8af0e8470
|
data/lib/hosties/definitions.rb
CHANGED
@@ -4,138 +4,145 @@
|
|
4
4
|
# have in order to be valid. #
|
5
5
|
#######################################################################
|
6
6
|
|
7
|
-
|
8
|
-
#
|
9
|
-
# for
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
7
|
+
module Hosties
|
8
|
+
# Constrains a named attribute to a provided set of values. This is good
|
9
|
+
# for things like describing environments that a set of hosts can be in,
|
10
|
+
# for instance Dev, QA, etc
|
11
|
+
class AttributeConstraint
|
12
|
+
attr_reader :name, :possible_vals
|
13
|
+
|
14
|
+
def initialize(name)
|
15
|
+
@name = name
|
16
|
+
@possible_vals = []
|
17
|
+
end
|
17
18
|
|
18
|
-
|
19
|
-
|
19
|
+
def can_be(val, *more)
|
20
|
+
@possible_vals += (more << val)
|
21
|
+
end
|
20
22
|
end
|
21
|
-
end
|
22
23
|
|
23
|
-
# Superclass for the host and environment requirement types. This
|
24
|
-
# class handles the plumbing of tracking, constraining, and eventually
|
25
|
-
# reifying attributes.
|
26
|
-
class HasAttributes
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
24
|
+
# Superclass for the host and environment requirement types. This
|
25
|
+
# class handles the plumbing of tracking, constraining, and eventually
|
26
|
+
# reifying attributes.
|
27
|
+
class HasAttributes
|
28
|
+
attr_accessor :constraints
|
29
|
+
attr_accessor :attributes
|
30
|
+
|
31
|
+
def initialize(verbotten = [])
|
32
|
+
@constraints = {}
|
33
|
+
@attributes = []
|
34
|
+
@verbotten = verbotten
|
35
|
+
end
|
33
36
|
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
37
|
+
# Specify symbols that will later be reified into attributes
|
38
|
+
def have_attributes(attr, *more)
|
39
|
+
sum = (more << attr)
|
40
|
+
sum.each do |name|
|
41
|
+
raise ArgumentError, "Reserved attribute name #{name}" if @verbotten.include?(name)
|
42
|
+
end
|
43
|
+
@attributes += sum
|
44
|
+
end
|
38
45
|
|
39
|
-
|
40
|
-
|
41
|
-
|
46
|
+
alias_method :have_attribute, :have_attributes
|
47
|
+
alias_method :has_attribute, :have_attribute
|
48
|
+
alias_method :has_attributes, :have_attributes
|
42
49
|
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
50
|
+
# Helpful method to define constraints
|
51
|
+
def where(name)
|
52
|
+
# Must define the attributes before constraining them
|
53
|
+
raise ArgumentError, "Unknown attribute: #{name}" unless @attributes.include? name
|
54
|
+
@constraints[name] = AttributeConstraint.new(name)
|
55
|
+
end
|
49
56
|
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
57
|
+
# Check if a given name-value pair is valid given the constraints
|
58
|
+
def valid?(name, value)
|
59
|
+
if @constraints.include? name then
|
60
|
+
constraints[name].possible_vals.include? value
|
61
|
+
else true end
|
62
|
+
end
|
55
63
|
end
|
56
|
-
end
|
57
64
|
|
58
|
-
# Defines what a host of a certain type looks like
|
59
|
-
class HostRequirement < HasAttributes
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
65
|
+
# Defines what a host of a certain type looks like
|
66
|
+
class HostRequirement < HasAttributes
|
67
|
+
attr_reader :type, :services
|
68
|
+
def initialize(type)
|
69
|
+
super([:hostname, :type])
|
70
|
+
@type = type
|
71
|
+
@services = []
|
72
|
+
end
|
66
73
|
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
|
74
|
+
# Services will be provided with a host definition. In order for
|
75
|
+
# a host definition to be valid, it must provide service details
|
76
|
+
# for all of the services specified by its matching
|
77
|
+
# HostRequirement
|
78
|
+
def have_services(service, *more)
|
79
|
+
@services += (more << service)
|
80
|
+
end
|
74
81
|
|
75
|
-
|
76
|
-
|
77
|
-
|
82
|
+
alias_method :have_service, :have_services
|
83
|
+
alias_method :has_service, :have_service
|
84
|
+
alias_method :has_services, :have_services
|
78
85
|
|
79
|
-
|
80
|
-
|
86
|
+
def finished
|
87
|
+
Hosties::HostDefinitions[@type] = self
|
88
|
+
end
|
81
89
|
end
|
82
|
-
end
|
83
90
|
|
84
|
-
# Builder method
|
85
|
-
def host_type(symbol, &block)
|
86
|
-
builder = HostRequirement.new(symbol)
|
87
|
-
begin
|
88
|
-
builder.instance_eval(&block)
|
89
|
-
builder.finished
|
90
|
-
rescue ArgumentError => ex
|
91
|
-
# TODO: There must be a better way!
|
92
|
-
# I'd like to provide some feedback in this case, but I don't
|
93
|
-
# like having this show up in test output.
|
94
|
-
#puts "Problem defining host \"#{symbol}\": #{ex}"
|
95
|
-
end
|
96
|
-
end
|
97
91
|
|
98
|
-
# Used to describe an environment.
|
99
|
-
class EnvironmentRequirement < HasAttributes
|
100
|
-
|
101
|
-
|
102
|
-
|
103
|
-
|
104
|
-
|
105
|
-
|
92
|
+
# Used to describe an environment.
|
93
|
+
class EnvironmentRequirement < HasAttributes
|
94
|
+
attr_reader :type, :hosts, :grouping, :host_attributes
|
95
|
+
def initialize(type)
|
96
|
+
super([:type, :hosts])
|
97
|
+
@type = type
|
98
|
+
@host_attributes = []
|
99
|
+
@hosts = []
|
100
|
+
end
|
106
101
|
|
107
|
-
|
108
|
-
|
109
|
-
|
110
|
-
|
111
|
-
|
112
|
-
|
113
|
-
|
114
|
-
|
102
|
+
# Define the hosts that an environment needs to be valid,
|
103
|
+
# for instance, maybe you need a :logger host and a
|
104
|
+
# :service host at a minimum.
|
105
|
+
def need(host1, *more)
|
106
|
+
sum = more << host1
|
107
|
+
# Array doesn't have an 'exists' method, so behold - map reduce wankery!
|
108
|
+
unless sum.map { |x| Hosties::HostDefinitions.include? x }.reduce(true) { |xs, x| x & xs }
|
109
|
+
raise ArgumentError, "Unrecognized host type"
|
110
|
+
end
|
111
|
+
@hosts += sum
|
115
112
|
end
|
116
|
-
@hosts += sum
|
117
|
-
end
|
118
113
|
|
119
|
-
|
120
|
-
|
121
|
-
|
122
|
-
|
123
|
-
|
124
|
-
|
114
|
+
alias_method :needs, :need
|
115
|
+
|
116
|
+
def hosts_inherit(attr)
|
117
|
+
unless self.attributes.include? attr then
|
118
|
+
raise ArgumentError, "Unrecognized attribute #{attr}"
|
119
|
+
end
|
120
|
+
@host_attributes << attr
|
121
|
+
end
|
125
122
|
|
126
|
-
|
127
|
-
|
123
|
+
# Optionally specify an attribute to group by when registering
|
124
|
+
# environments of this type.
|
125
|
+
def grouped_by(attr)
|
126
|
+
raise ArgumentError, "Unknown attribute #{attr}" unless @attributes.include?(attr)
|
127
|
+
@grouping = attr
|
128
|
+
end
|
129
|
+
|
130
|
+
def finished
|
131
|
+
Hosties::EnvironmentDefinitions[@type] = self
|
132
|
+
end
|
128
133
|
end
|
129
134
|
end
|
130
135
|
|
131
|
-
|
136
|
+
## Globally accessible builder methods
|
137
|
+
|
132
138
|
def environment_type(symbol, &block)
|
133
|
-
builder = EnvironmentRequirement.new(symbol)
|
134
|
-
|
135
|
-
|
136
|
-
|
137
|
-
|
138
|
-
|
139
|
-
|
140
|
-
|
139
|
+
builder = Hosties::EnvironmentRequirement.new(symbol)
|
140
|
+
builder.instance_eval(&block)
|
141
|
+
builder.finished
|
142
|
+
end
|
143
|
+
|
144
|
+
def host_type(symbol, &block)
|
145
|
+
builder = Hosties::HostRequirement.new(symbol)
|
146
|
+
builder.instance_eval(&block)
|
147
|
+
builder.finished
|
141
148
|
end
|
data/lib/hosties/easydata.rb
CHANGED
@@ -2,23 +2,33 @@
|
|
2
2
|
# Provide a more convenient data structure to work with once #
|
3
3
|
# environment declarations have been read. #
|
4
4
|
###############################################################
|
5
|
-
class DataWrapper
|
6
|
-
def metaclass
|
7
|
-
class << self
|
8
|
-
self
|
9
|
-
end
|
10
|
-
end
|
11
|
-
end
|
12
|
-
|
13
5
|
module Hosties
|
14
6
|
module EasyData
|
7
|
+
class DataWrapper
|
8
|
+
def metaclass
|
9
|
+
class << self
|
10
|
+
self
|
11
|
+
end
|
12
|
+
end
|
13
|
+
end
|
14
|
+
|
15
15
|
def self.fromHost(hash)
|
16
16
|
result = DataWrapper.new
|
17
17
|
hash.each do |k, v|
|
18
18
|
result.metaclass.send(:define_method, k) do v end
|
19
19
|
end
|
20
|
+
# Define a human-friendly to_s
|
21
|
+
# NOTE: Application behavior should not rely on the stability of this
|
22
|
+
# string representation! It is subject to change whenever I'm feeling
|
23
|
+
# squirrely.
|
24
|
+
filtered_hash = hash.reject { |k,v| k == :type or k == :hostname }
|
25
|
+
attr_string = filtered_hash.map{|k,v| "#{k}: #{v}"}.join(", ")
|
26
|
+
result.metaclass.send(:define_method, :to_s) do
|
27
|
+
"<#{hash[:type]} host @ #{hash[:hostname]} attrs: #{attr_string}>"
|
28
|
+
end
|
20
29
|
result
|
21
30
|
end
|
31
|
+
|
22
32
|
def self.fromEnv(hash)
|
23
33
|
result = DataWrapper.new
|
24
34
|
hash.each do |k, v|
|
@@ -34,6 +44,23 @@ module Hosties
|
|
34
44
|
result.metaclass.send(:define_method, :each_host) do |&block|
|
35
45
|
yield self.hosts
|
36
46
|
end
|
47
|
+
# Apply all of the host_attributes to our little host children
|
48
|
+
definition = Hosties::EnvironmentDefinitions[hash[:type]]
|
49
|
+
inheritance = definition.host_attributes
|
50
|
+
hash[:hosts].each do |host|
|
51
|
+
inheritance.each do |attr|
|
52
|
+
val = hash[attr]
|
53
|
+
host.metaclass.send(:define_method, attr) do val end
|
54
|
+
end
|
55
|
+
end
|
56
|
+
# Human friendly to_s
|
57
|
+
# NOTE: As above, this representation is subject to change whenever,
|
58
|
+
# don't rely on it for application behavior!
|
59
|
+
filtered_hash = hash.reject { |k,v| k == :type or k == :hosts }
|
60
|
+
attr_string = filtered_hash.map{|k,v| "#{k}: #{v}"}.join(", ")
|
61
|
+
result.metaclass.send(:define_method, :to_s) do
|
62
|
+
"<#{hash[:type]} environment, attrs: #{attr_string}, hosts: #{hash[:hosts].join(", ")}>"
|
63
|
+
end
|
37
64
|
result
|
38
65
|
end
|
39
66
|
end
|
data/lib/hosties/reification.rb
CHANGED
@@ -2,113 +2,117 @@
|
|
2
2
|
# Provide some classes to turn a declarative host definition into something
|
3
3
|
# more useful in code, applying rules from the definition files to ensure we
|
4
4
|
# only get valid stuff.
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
5
|
+
|
6
|
+
module Hosties
|
7
|
+
class UsesAttributes
|
8
|
+
# Oh this old thing...
|
9
|
+
def metaclass
|
10
|
+
class << self
|
11
|
+
self
|
12
|
+
end
|
10
13
|
end
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
14
|
+
def initialize(has_attributes)
|
15
|
+
@attributes = has_attributes.attributes
|
16
|
+
# Magic.
|
17
|
+
has_attributes.attributes.each do |attr|
|
18
|
+
# Add in the attribute
|
19
|
+
self.metaclass.send(:attr_accessor, attr)
|
20
|
+
# Define a constrained setter
|
21
|
+
self.metaclass.send(:define_method, attr) do |val|
|
22
|
+
raise ArgumentError, "Invalid value" unless has_attributes.valid?(attr, val)
|
23
|
+
instance_variable_set "@#{attr}", val
|
24
|
+
end
|
22
25
|
end
|
23
26
|
end
|
24
|
-
end
|
25
27
|
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
28
|
+
# Return a hash after verifying everything was set correctly
|
29
|
+
def finish
|
30
|
+
retval = {}
|
31
|
+
# Ensure all required attributes have been set
|
32
|
+
@attributes.each do |attr|
|
33
|
+
val = instance_variable_get "@#{attr}"
|
34
|
+
raise ArgumentError, "Missing attribute #{attr}" if val.nil?
|
35
|
+
retval[attr] = val
|
36
|
+
end
|
37
|
+
retval
|
34
38
|
end
|
35
|
-
retval
|
36
39
|
end
|
37
|
-
end
|
38
40
|
|
39
|
-
class HostBuilder < UsesAttributes
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
41
|
+
class HostBuilder < UsesAttributes
|
42
|
+
def initialize(type, hostname)
|
43
|
+
if Hosties::HostDefinitions[type].nil? then
|
44
|
+
raise ArgumentError, "Unrecognized host type"
|
45
|
+
end
|
46
|
+
@type = type
|
47
|
+
@definition = Hosties::HostDefinitions[@type]
|
48
|
+
@hostname = hostname
|
49
|
+
@service_ports = {} # Map of service type to port
|
50
|
+
super(@definition) # Creates attribute code
|
51
|
+
# Services are really just a special kind of attribute, but for now I'll
|
52
|
+
# keep them separate. I'm thinking maybe I could add a new type of attribute
|
53
|
+
# constraint that let's a user specify that an attribute must be numeric, or
|
54
|
+
# a string for instance.
|
55
|
+
@definition.services.each do |service_type|
|
56
|
+
self.metaclass.send(:attr_accessor, service_type)
|
57
|
+
self.metaclass.send(:define_method, service_type) do |port|
|
58
|
+
raise ArgumentError, "Port number required" unless port.is_a? Integer
|
59
|
+
@service_ports[service_type] = port
|
60
|
+
end
|
58
61
|
end
|
59
62
|
end
|
60
|
-
end
|
61
63
|
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
64
|
+
def finish
|
65
|
+
# Ensure all services have been set
|
66
|
+
@definition.services.each do |svc|
|
67
|
+
raise ArgumentError, "Missing service #{svc}" if @service_ports[svc].nil?
|
68
|
+
end
|
69
|
+
# TODO: Declare these reserved names
|
70
|
+
super.merge({ :hostname => @hostname, :type => @type }).merge(@service_ports)
|
66
71
|
end
|
67
|
-
# TODO: Declare these reserved names
|
68
|
-
super.merge({ :hostname => @hostname, :type => @type }).merge(@service_ports)
|
69
72
|
end
|
70
|
-
end
|
71
73
|
|
72
|
-
# Turn a description into a useful data structure - and it's validated!
|
73
|
-
class EnvironmentBuilder < UsesAttributes
|
74
|
-
|
75
|
-
|
76
|
-
|
77
|
-
|
78
|
-
|
79
|
-
|
80
|
-
|
81
|
-
|
82
|
-
|
83
|
-
|
84
|
-
|
85
|
-
|
86
|
-
|
87
|
-
|
88
|
-
|
89
|
-
|
90
|
-
|
91
|
-
|
92
|
-
|
74
|
+
# Turn a description into a useful data structure - and it's validated!
|
75
|
+
class EnvironmentBuilder < UsesAttributes
|
76
|
+
def initialize(type)
|
77
|
+
if Hosties::EnvironmentDefinitions[type].nil? then
|
78
|
+
raise ArgumentError, "Unrecognized environment type"
|
79
|
+
end
|
80
|
+
@hosts = []
|
81
|
+
@type = type
|
82
|
+
@definition = Hosties::EnvironmentDefinitions[@type]
|
83
|
+
super(@definition) # Creates attribute code
|
84
|
+
# More magic, this time create a parameterized host builder based
|
85
|
+
# on the type of hosts this environment wants. Poor man's currying
|
86
|
+
@definition.hosts.each do |host_type|
|
87
|
+
self.metaclass.send(:define_method, host_type) do |hostname, &block|
|
88
|
+
begin
|
89
|
+
builder = HostBuilder.new(host_type, hostname)
|
90
|
+
builder.instance_eval(&block)
|
91
|
+
@hosts << Hosties::EasyData.fromHost(builder.finish)
|
92
|
+
rescue ArgumentError => ex
|
93
|
+
#puts "Problem declaring host: #{ex}"
|
94
|
+
raise ex
|
95
|
+
end
|
93
96
|
end
|
94
97
|
end
|
95
98
|
end
|
96
|
-
end
|
97
99
|
|
98
|
-
|
99
|
-
|
100
|
-
|
101
|
-
|
102
|
-
|
100
|
+
def finish
|
101
|
+
# Verify all of the required hosts were set
|
102
|
+
@definition.hosts.each do |host_type|
|
103
|
+
unless @hosts.detect { |host| host.type == host_type } then
|
104
|
+
raise ArgumentError, "Missing #{host_type} host"
|
105
|
+
end
|
103
106
|
end
|
107
|
+
super.merge({ :type => @type, :hosts => @hosts })
|
104
108
|
end
|
105
|
-
super.merge({ :hosts => @hosts })
|
106
109
|
end
|
107
110
|
end
|
108
111
|
|
112
|
+
## Globally accessible builder methods
|
109
113
|
def environment_for(type, &block)
|
110
114
|
begin
|
111
|
-
builder = EnvironmentBuilder.new(type)
|
115
|
+
builder = Hosties::EnvironmentBuilder.new(type)
|
112
116
|
builder.instance_eval(&block)
|
113
117
|
data = builder.finish
|
114
118
|
nice_version = Hosties::EasyData.fromEnv(data)
|
data/spec/definitions_spec.rb
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
require 'spec_helper'
|
2
2
|
|
3
|
-
describe HasAttributes do
|
3
|
+
describe Hosties::HasAttributes do
|
4
4
|
it 'rejects definitions with constraints on nonexistent attributes' do
|
5
|
-
instance = HasAttributes.new
|
5
|
+
instance = Hosties::HasAttributes.new
|
6
6
|
instance.have_attributes :foo, :bar
|
7
7
|
expect { instance.where(:baz).can_be("anything") }.to raise_error(ArgumentError)
|
8
8
|
end
|
9
9
|
end
|
10
10
|
|
11
|
-
describe HostRequirement do
|
11
|
+
describe Hosties::HostRequirement do
|
12
12
|
it 'defines host types' do
|
13
13
|
# Declare a host type
|
14
14
|
host_type :logger do
|
@@ -16,9 +16,17 @@ describe HostRequirement do
|
|
16
16
|
have_attributes :control_mbean, :default_user
|
17
17
|
end
|
18
18
|
end
|
19
|
+
|
20
|
+
it 'rejects definitions with reserved attribute names' do
|
21
|
+
builder = Hosties::HostRequirement.new(:failsauce)
|
22
|
+
# hostname
|
23
|
+
expect { builder.have_attributes(:hostname) }.to raise_error(ArgumentError)
|
24
|
+
# type
|
25
|
+
expect { builder.have_attributes(:type) }.to raise_error(ArgumentError)
|
26
|
+
end
|
19
27
|
end
|
20
28
|
|
21
|
-
describe EnvironmentRequirement do
|
29
|
+
describe Hosties::EnvironmentRequirement do
|
22
30
|
it 'defines environments with host and attribute requirements' do
|
23
31
|
host_type :mutant_maker do end
|
24
32
|
host_type :turkey_blaster do end
|
@@ -28,13 +36,32 @@ describe EnvironmentRequirement do
|
|
28
36
|
end
|
29
37
|
end
|
30
38
|
|
39
|
+
it 'rejects definitions with reserved attribute names' do
|
40
|
+
builder = Hosties::EnvironmentRequirement.new(:failsauce)
|
41
|
+
# hosts
|
42
|
+
expect { builder.have_attributes(:hosts) }.to raise_error(ArgumentError)
|
43
|
+
# type
|
44
|
+
expect { builder.have_attributes(:type) }.to raise_error(ArgumentError)
|
45
|
+
end
|
46
|
+
|
31
47
|
it 'rejects environment definitions that need undefined host types' do
|
32
|
-
builder = EnvironmentRequirement.new(:failure)
|
48
|
+
builder = Hosties::EnvironmentRequirement.new(:failure)
|
33
49
|
expect { builder.need(:nonexistent) }.to raise_error(ArgumentError)
|
34
50
|
end
|
35
51
|
|
36
52
|
it 'rejects groupings for unknown attributes' do
|
37
|
-
builder = EnvironmentRequirement.new(:failure)
|
53
|
+
builder = Hosties::EnvironmentRequirement.new(:failure)
|
38
54
|
expect { builder.grouped_by(:nonexistent) }.to raise_error(ArgumentError)
|
39
55
|
end
|
56
|
+
|
57
|
+
it 'can define host-inherited attributes ' do
|
58
|
+
builder = Hosties::EnvironmentRequirement.new(:inherit_provider)
|
59
|
+
builder.has_attribute :to_inherit
|
60
|
+
builder.hosts_inherit :to_inherit
|
61
|
+
end
|
62
|
+
|
63
|
+
it 'catches faulty hosts_inherit clauses' do
|
64
|
+
builder = Hosties::EnvironmentRequirement.new(:inherit_failure)
|
65
|
+
expect { builder.hosts_inherit :to_inherit }.to raise_error(ArgumentError)
|
66
|
+
end
|
40
67
|
end
|
data/spec/easydata_spec.rb
CHANGED
@@ -6,7 +6,7 @@ describe Hosties::EasyData do
|
|
6
6
|
have_service :http
|
7
7
|
have_attribute :attr_one
|
8
8
|
end
|
9
|
-
builder = HostBuilder.new(:easydata_one, "localhost")
|
9
|
+
builder = Hosties::HostBuilder.new(:easydata_one, "localhost")
|
10
10
|
builder.http 80
|
11
11
|
builder.attr_one "One!"
|
12
12
|
result = Hosties::EasyData.fromHost(builder.finish)
|
@@ -24,7 +24,7 @@ describe Hosties::EasyData do
|
|
24
24
|
have_attribute :environment
|
25
25
|
where(:environment).can_be :dev, :testing
|
26
26
|
end
|
27
|
-
builder = EnvironmentBuilder.new :easydata_one
|
27
|
+
builder = Hosties::EnvironmentBuilder.new :easydata_one
|
28
28
|
builder.easydata_two "0.0.0.0" do end
|
29
29
|
builder.easydata_three "1.1.1.1" do end
|
30
30
|
builder.environment :dev
|
data/spec/hosties_spec.rb
CHANGED
@@ -4,7 +4,7 @@ describe Hosties do
|
|
4
4
|
it 'can declare a host' do
|
5
5
|
host_type :special_host do
|
6
6
|
end
|
7
|
-
instance = HostBuilder.new(:special_host, "0.0.0.0")
|
7
|
+
instance = Hosties::HostBuilder.new(:special_host, "0.0.0.0")
|
8
8
|
expect(instance.finish).to eq({ :hostname => "0.0.0.0", :type => :special_host})
|
9
9
|
end
|
10
10
|
|
@@ -12,7 +12,7 @@ describe Hosties do
|
|
12
12
|
host_type :web_host do
|
13
13
|
have_service :http
|
14
14
|
end
|
15
|
-
instance = HostBuilder.new(:web_host, "0.0.0.0")
|
15
|
+
instance = Hosties::HostBuilder.new(:web_host, "0.0.0.0")
|
16
16
|
expect { instance.finish }.to raise_error(ArgumentError)
|
17
17
|
end
|
18
18
|
|
@@ -20,7 +20,7 @@ describe Hosties do
|
|
20
20
|
host_type :mud_server do
|
21
21
|
have_attribute :version
|
22
22
|
end
|
23
|
-
instance = HostBuilder.new(:mud_server, "0.0.0.0")
|
23
|
+
instance = Hosties::HostBuilder.new(:mud_server, "0.0.0.0")
|
24
24
|
expect { instance.finish }.to raise_error(ArgumentError)
|
25
25
|
end
|
26
26
|
|
@@ -28,7 +28,7 @@ describe Hosties do
|
|
28
28
|
host_type :web_host do
|
29
29
|
have_service :http
|
30
30
|
end
|
31
|
-
instance = HostBuilder.new(:web_host, "0.0.0.0")
|
31
|
+
instance = Hosties::HostBuilder.new(:web_host, "0.0.0.0")
|
32
32
|
expect { instance.http 10.4 }.to raise_error(ArgumentError)
|
33
33
|
end
|
34
34
|
|
@@ -40,7 +40,7 @@ describe Hosties do
|
|
40
40
|
environment_type :needy_environment do
|
41
41
|
need :type_a, :type_b
|
42
42
|
end
|
43
|
-
builder = EnvironmentBuilder.new(:needy_environment)
|
43
|
+
builder = Hosties::EnvironmentBuilder.new(:needy_environment)
|
44
44
|
builder.type_a "0.0.0.0" do end
|
45
45
|
# No type_b specified
|
46
46
|
expect { builder.finish }.to raise_error(ArgumentError)
|
@@ -85,6 +85,7 @@ describe Hosties do
|
|
85
85
|
expect(data.hosts_by_type(:monitoring).size).to eq(2) # Two monitoring hosts
|
86
86
|
expect(data.hosts_by_type(:service_host).size).to eq(1)
|
87
87
|
service_host = data.hosts_by_type(:service_host).first
|
88
|
+
expect(service_host.hostname).to eq("192.168.0.3")
|
88
89
|
expect(service_host.service_port).to eq(1234)
|
89
90
|
expect(service_host.uuid).to eq("81E3C1D4-C040-4D59-A56F-4273384D576B")
|
90
91
|
end
|
@@ -111,4 +112,21 @@ describe Hosties do
|
|
111
112
|
expect(Hosties::GroupedEnvironments[:foobar][:dev].size).to eq(1)
|
112
113
|
expect(Hosties::GroupedEnvironments[:foobar][:qa].size).to eq(1)
|
113
114
|
end
|
115
|
+
|
116
|
+
it 'lets hosts inherit attributes' do
|
117
|
+
host_type :beneficiary do end# ha.
|
118
|
+
environment_type :benefactor do
|
119
|
+
need :beneficiary
|
120
|
+
has_attribute :monies
|
121
|
+
hosts_inherit :monies # Lucky!
|
122
|
+
end
|
123
|
+
amount = 1000000
|
124
|
+
environment_for :benefactor do
|
125
|
+
beneficiary "0.0.0.0" do end
|
126
|
+
# Prove that ordering doesn't matter here
|
127
|
+
monies amount
|
128
|
+
end
|
129
|
+
beneficiary = Hosties::Environments[:benefactor].first.hosts.first
|
130
|
+
expect(beneficiary.monies).to eq(amount)
|
131
|
+
end
|
114
132
|
end
|
data/spec/reification_spec.rb
CHANGED
@@ -1,18 +1,18 @@
|
|
1
1
|
require 'spec_helper'
|
2
2
|
|
3
|
-
describe UsesAttributes do
|
3
|
+
describe Hosties::UsesAttributes do
|
4
4
|
it 'can enforce attribute constraints' do
|
5
|
-
definition = HasAttributes.new
|
5
|
+
definition = Hosties::HasAttributes.new
|
6
6
|
definition.have_attributes(:x)
|
7
7
|
definition.where(:x).can_be("hello")
|
8
|
-
instance = UsesAttributes.new(definition)
|
8
|
+
instance = Hosties::UsesAttributes.new(definition)
|
9
9
|
instance.x "hello"
|
10
10
|
expect { instance.x 31 }.to raise_error(ArgumentError)
|
11
11
|
end
|
12
12
|
it 'catches missing attributes' do
|
13
|
-
definition = HasAttributes.new
|
13
|
+
definition = Hosties::HasAttributes.new
|
14
14
|
definition.have_attributes(:x)
|
15
|
-
instance = UsesAttributes.new(definition)
|
15
|
+
instance = Hosties::UsesAttributes.new(definition)
|
16
16
|
expect { instance.finish }.to raise_error(ArgumentError)
|
17
17
|
end
|
18
18
|
end
|