serverspec-extra-types 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 +13 -0
- data/.rspec +3 -0
- data/.rubocop.yml +6 -0
- data/.travis.yml +7 -0
- data/CODE_OF_CONDUCT.md +74 -0
- data/Gemfile +6 -0
- data/LICENSE.txt +21 -0
- data/README.md +191 -0
- data/Rakefile +7 -0
- data/bin/console +14 -0
- data/bin/setup +8 -0
- data/lib/serverspec_extra_types.rb +3 -0
- data/lib/serverspec_extra_types/helpers/properties.rb +11 -0
- data/lib/serverspec_extra_types/matchers.rb +34 -0
- data/lib/serverspec_extra_types/matchers/be_a_manager_node.rb +15 -0
- data/lib/serverspec_extra_types/matchers/be_a_worker_node.rb +14 -0
- data/lib/serverspec_extra_types/matchers/be_active.rb +11 -0
- data/lib/serverspec_extra_types/matchers/configure_queue.rb +8 -0
- data/lib/serverspec_extra_types/matchers/have_count.rb +11 -0
- data/lib/serverspec_extra_types/matchers/have_domain_name.rb +10 -0
- data/lib/serverspec_extra_types/matchers/have_engine_version.rb +11 -0
- data/lib/serverspec_extra_types/matchers/have_environment_variable.rb +21 -0
- data/lib/serverspec_extra_types/matchers/have_ha_mode.rb +5 -0
- data/lib/serverspec_extra_types/matchers/have_ha_nodes.rb +8 -0
- data/lib/serverspec_extra_types/matchers/have_ha_sync_mode.rb +5 -0
- data/lib/serverspec_extra_types/matchers/have_host.rb +8 -0
- data/lib/serverspec_extra_types/matchers/have_hostname.rb +6 -0
- data/lib/serverspec_extra_types/matchers/have_image.rb +8 -0
- data/lib/serverspec_extra_types/matchers/have_image_sha.rb +5 -0
- data/lib/serverspec_extra_types/matchers/have_label.rb +20 -0
- data/lib/serverspec_extra_types/matchers/have_mount.rb +11 -0
- data/lib/serverspec_extra_types/matchers/have_network.rb +8 -0
- data/lib/serverspec_extra_types/matchers/have_placement_constraint.rb +8 -0
- data/lib/serverspec_extra_types/matchers/have_replica_count.rb +8 -0
- data/lib/serverspec_extra_types/matchers/have_restart_limit.rb +8 -0
- data/lib/serverspec_extra_types/matchers/have_restart_policy.rb +8 -0
- data/lib/serverspec_extra_types/matchers/have_user.rb +10 -0
- data/lib/serverspec_extra_types/matchers/have_vhost.rb +5 -0
- data/lib/serverspec_extra_types/matchers/include_regex.rb +5 -0
- data/lib/serverspec_extra_types/matchers/map_port.rb +25 -0
- data/lib/serverspec_extra_types/matchers/mirror_all.rb +5 -0
- data/lib/serverspec_extra_types/matchers/publish_all_ports.rb +3 -0
- data/lib/serverspec_extra_types/matchers/read_from_queue.rb +8 -0
- data/lib/serverspec_extra_types/matchers/write_to_queue.rb +8 -0
- data/lib/serverspec_extra_types/types.rb +18 -0
- data/lib/serverspec_extra_types/types/api_base.rb +36 -0
- data/lib/serverspec_extra_types/types/consul_base.rb +40 -0
- data/lib/serverspec_extra_types/types/consul_node.rb +20 -0
- data/lib/serverspec_extra_types/types/consul_node_list.rb +32 -0
- data/lib/serverspec_extra_types/types/consul_service.rb +24 -0
- data/lib/serverspec_extra_types/types/consul_service_list.rb +32 -0
- data/lib/serverspec_extra_types/types/docker_container.rb +124 -0
- data/lib/serverspec_extra_types/types/docker_node.rb +41 -0
- data/lib/serverspec_extra_types/types/docker_service.rb +121 -0
- data/lib/serverspec_extra_types/types/rabbitmq_base.rb +38 -0
- data/lib/serverspec_extra_types/types/rabbitmq_node_list.rb +18 -0
- data/lib/serverspec_extra_types/types/rabbitmq_user_permission.rb +39 -0
- data/lib/serverspec_extra_types/types/rabbitmq_vhost_list.rb +22 -0
- data/lib/serverspec_extra_types/types/rabbitmq_vhost_policy.rb +57 -0
- data/lib/serverspec_extra_types/version.rb +3 -0
- data/properties.yml +23 -0
- data/serverspec-extra-types.gemspec +36 -0
- metadata +232 -0
@@ -0,0 +1,32 @@
|
|
1
|
+
require 'serverspec_extra_types/types/consul_base'
|
2
|
+
|
3
|
+
|
4
|
+
# TODO: List and singular
|
5
|
+
module Serverspec::Type
|
6
|
+
class ConsulNodeList < ConsulBase
|
7
|
+
|
8
|
+
def url
|
9
|
+
"#{@url_base}/v1/catalog/nodes"
|
10
|
+
end
|
11
|
+
|
12
|
+
def to_s
|
13
|
+
msg = "Consul Node List"
|
14
|
+
msg << %( with acl token: "#{@token}") if @token
|
15
|
+
msg
|
16
|
+
end
|
17
|
+
|
18
|
+
def has_node?(node)
|
19
|
+
nodes.include? node
|
20
|
+
end
|
21
|
+
|
22
|
+
def nodes
|
23
|
+
inspection.keys
|
24
|
+
end
|
25
|
+
|
26
|
+
def inspection
|
27
|
+
@inspection ||= ::MultiJson.load(get_inspection.stdout)
|
28
|
+
end
|
29
|
+
|
30
|
+
|
31
|
+
end
|
32
|
+
end
|
@@ -0,0 +1,24 @@
|
|
1
|
+
require 'serverspec_extra_types/types/consul_base'
|
2
|
+
|
3
|
+
|
4
|
+
# TODO: List and singular
|
5
|
+
module Serverspec::Type
|
6
|
+
class ConsulService < ConsulBase
|
7
|
+
|
8
|
+
def url
|
9
|
+
"#{@url_base}/v1/catalog/service/#{@name}"
|
10
|
+
end
|
11
|
+
|
12
|
+
def to_s
|
13
|
+
msg = "Consul Service #{@name}"
|
14
|
+
msg << %( with acl token: "#{@token}") if @token
|
15
|
+
msg
|
16
|
+
end
|
17
|
+
|
18
|
+
def inspection
|
19
|
+
@inspection ||= ::MultiJson.load(get_inspection.stdout)
|
20
|
+
end
|
21
|
+
|
22
|
+
|
23
|
+
end
|
24
|
+
end
|
@@ -0,0 +1,32 @@
|
|
1
|
+
require 'serverspec_extra_types/types/consul_base'
|
2
|
+
|
3
|
+
|
4
|
+
# TODO: List and singular
|
5
|
+
module Serverspec::Type
|
6
|
+
class ConsulServiceList < ConsulBase
|
7
|
+
|
8
|
+
def url
|
9
|
+
"#{@url_base}/v1/catalog/services"
|
10
|
+
end
|
11
|
+
|
12
|
+
def to_s
|
13
|
+
msg = "Consul Service List"
|
14
|
+
msg << %( with acl token: "#{@token}") if @token
|
15
|
+
msg
|
16
|
+
end
|
17
|
+
|
18
|
+
def has_service?(service)
|
19
|
+
services.include? service
|
20
|
+
end
|
21
|
+
|
22
|
+
def services
|
23
|
+
inspection.keys
|
24
|
+
end
|
25
|
+
|
26
|
+
def inspection
|
27
|
+
@inspection ||= ::MultiJson.load(get_inspection.stdout)
|
28
|
+
end
|
29
|
+
|
30
|
+
|
31
|
+
end
|
32
|
+
end
|
@@ -0,0 +1,124 @@
|
|
1
|
+
require 'serverspec'
|
2
|
+
|
3
|
+
module Serverspec::Type
|
4
|
+
# This class monkey patches serverspec's docker container type with some more method to be used in matchers
|
5
|
+
class DockerContainer
|
6
|
+
def include_regex?
|
7
|
+
inspection.find { |str| str =~ regex }
|
8
|
+
end
|
9
|
+
|
10
|
+
def has_image?(image)
|
11
|
+
self.image == image
|
12
|
+
end
|
13
|
+
|
14
|
+
def has_image_sha?(image)
|
15
|
+
self.image_sha == image
|
16
|
+
end
|
17
|
+
|
18
|
+
def image
|
19
|
+
inspection['Config']['Image'].split('@')[0]
|
20
|
+
end
|
21
|
+
|
22
|
+
def image_sha
|
23
|
+
inspection['Config']['Image'].split('@')[1]
|
24
|
+
end
|
25
|
+
|
26
|
+
def has_environment_variable?(regex, value = nil)
|
27
|
+
if value
|
28
|
+
environment_variable(regex) == value
|
29
|
+
else
|
30
|
+
environment_variable(regex)
|
31
|
+
end
|
32
|
+
|
33
|
+
end
|
34
|
+
|
35
|
+
def environment_variable(regex)
|
36
|
+
environment_variables.find { |str| str =~ /^#{regex}=/ }.split('=')[1]
|
37
|
+
end
|
38
|
+
|
39
|
+
def environment_variables
|
40
|
+
inspection['Config']['Env']
|
41
|
+
end
|
42
|
+
|
43
|
+
def has_user?(user)
|
44
|
+
self.user == user
|
45
|
+
end
|
46
|
+
|
47
|
+
def user
|
48
|
+
inspection['Config']['User']
|
49
|
+
end
|
50
|
+
|
51
|
+
def has_hostname?(hostname)
|
52
|
+
self.hostname == hostname
|
53
|
+
end
|
54
|
+
|
55
|
+
def hostname
|
56
|
+
inspection['Config']['Hostname']
|
57
|
+
end
|
58
|
+
|
59
|
+
def has_domainname?(domain)
|
60
|
+
self.domain_name == domain
|
61
|
+
end
|
62
|
+
|
63
|
+
def domain_name
|
64
|
+
inspection['Config']['Domainname']
|
65
|
+
end
|
66
|
+
|
67
|
+
def has_restart_limit?(limit)
|
68
|
+
restart_limit == limit
|
69
|
+
end
|
70
|
+
|
71
|
+
def restart_limit
|
72
|
+
inspection['HostConfig']['RestartPolicy']['MaximumRetryCount']
|
73
|
+
end
|
74
|
+
|
75
|
+
def has_restart_policy?(policy)
|
76
|
+
restart_policy == policy
|
77
|
+
end
|
78
|
+
|
79
|
+
def restart_policy
|
80
|
+
inspection['HostConfig']['RestartPolicy']['Name']
|
81
|
+
end
|
82
|
+
def has_host?(host)
|
83
|
+
hosts.include? host
|
84
|
+
end
|
85
|
+
def hosts
|
86
|
+
inspection['HostConfig']['ExtraHosts'].map {|itm| itm.split(':')[1] + ' ' + itm.split(':')[0]}
|
87
|
+
end
|
88
|
+
|
89
|
+
def privileged?
|
90
|
+
inspection['HostConfig']['Privileged']
|
91
|
+
end
|
92
|
+
|
93
|
+
# TODO: matcher for this
|
94
|
+
def publishes_all_ports?
|
95
|
+
inspection['HostConfig']['PublishAllPorts']
|
96
|
+
end
|
97
|
+
|
98
|
+
|
99
|
+
def map_port?(host, container, protocol = 'tcp')
|
100
|
+
inspection['NetworkSettings']['Ports']["#{container}/#{protocol}"][0]['HostPort'] == host
|
101
|
+
end
|
102
|
+
|
103
|
+
def port_map
|
104
|
+
inspection['HostConfig']['PortBindings']
|
105
|
+
end
|
106
|
+
|
107
|
+
def has_mount?(source, target, type)
|
108
|
+
mounts.find { |mount| mount['Source'] == source && mount['Destination'] == target && mount['Type'] == type }
|
109
|
+
end
|
110
|
+
|
111
|
+
def mounts
|
112
|
+
inspection['Mounts']
|
113
|
+
end
|
114
|
+
|
115
|
+
# TODO: matcher for volumes
|
116
|
+
|
117
|
+
private
|
118
|
+
|
119
|
+
def get_inspection
|
120
|
+
@containers ||= @name.include?('=') ? @runner.run_command("docker ps -qa -f #{@name}").stdout : @name
|
121
|
+
@get_inspection ||= @runner.run_command("docker inspect #{@containers}")
|
122
|
+
end
|
123
|
+
end
|
124
|
+
end
|
@@ -0,0 +1,41 @@
|
|
1
|
+
module Serverspec::Type
|
2
|
+
class DockerNode < DockerBase
|
3
|
+
|
4
|
+
def active?
|
5
|
+
availability == 'active'
|
6
|
+
end
|
7
|
+
|
8
|
+
def availability
|
9
|
+
inspection['Spec']['Availability']
|
10
|
+
end
|
11
|
+
|
12
|
+
def role
|
13
|
+
inspection['Spec']['Role']
|
14
|
+
end
|
15
|
+
|
16
|
+
def manager?
|
17
|
+
role == 'manager'
|
18
|
+
end
|
19
|
+
|
20
|
+
def worker?
|
21
|
+
role == 'worker'
|
22
|
+
end
|
23
|
+
|
24
|
+
def labels
|
25
|
+
inspection['Spec']['Labels']
|
26
|
+
end
|
27
|
+
|
28
|
+
def has_engine_version?(version)
|
29
|
+
engine_version == version
|
30
|
+
end
|
31
|
+
|
32
|
+
def engine_version
|
33
|
+
inspection['Description']['Engine']['EngineVersion']
|
34
|
+
end
|
35
|
+
private
|
36
|
+
|
37
|
+
def get_inspection
|
38
|
+
@get_inspection ||= @runner.run_command("docker service inspect #{@name}")
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end
|
@@ -0,0 +1,121 @@
|
|
1
|
+
require 'serverspec'
|
2
|
+
require 'serverspec/type/base'
|
3
|
+
require 'serverspec/type/docker_base'
|
4
|
+
|
5
|
+
module Serverspec::Type
|
6
|
+
class DockerService < DockerBase
|
7
|
+
def exist?
|
8
|
+
get_inspection.success?
|
9
|
+
end
|
10
|
+
|
11
|
+
def has_restart_policy?(policy)
|
12
|
+
restart_policy == policy
|
13
|
+
end
|
14
|
+
|
15
|
+
def has_restart_limit?(limit)
|
16
|
+
restart_limit == limit
|
17
|
+
end
|
18
|
+
|
19
|
+
def restart_policy
|
20
|
+
inspection['Spec']['TaskTemplate']['RestartPolicy']['Condition']
|
21
|
+
end
|
22
|
+
|
23
|
+
def restart_limit
|
24
|
+
inspection['Spec']['TaskTemplate']['RestartPolicy']['MaxAttempts']
|
25
|
+
end
|
26
|
+
|
27
|
+
def has_image?(image)
|
28
|
+
self.image == image
|
29
|
+
end
|
30
|
+
|
31
|
+
def has_image_sha?(image)
|
32
|
+
self.image == image
|
33
|
+
end
|
34
|
+
|
35
|
+
def image
|
36
|
+
inspection['Spec']['TaskTemplate']['ContainerSpec']['Image'].split('@')[0]
|
37
|
+
end
|
38
|
+
|
39
|
+
def image_sha
|
40
|
+
inspection['Spec']['TaskTemplate']['ContainerSpec']['Image'].split('@')[1]
|
41
|
+
end
|
42
|
+
|
43
|
+
def has_user?(user)
|
44
|
+
self.user == user
|
45
|
+
end
|
46
|
+
|
47
|
+
def user
|
48
|
+
inspection['Spec']['TaskTemplate']['ContainerSpec']['User']
|
49
|
+
end
|
50
|
+
|
51
|
+
def has_mount?(source, target, type)
|
52
|
+
mounts.find do |mount|
|
53
|
+
mount['Source'] == source && mount['Target'] == target && mount['Type'] == type
|
54
|
+
end
|
55
|
+
end
|
56
|
+
|
57
|
+
def mounts
|
58
|
+
inspection['Spec']['TaskTemplate']['ContainerSpec']['Mounts']
|
59
|
+
end
|
60
|
+
|
61
|
+
def has_host?(host)
|
62
|
+
hosts.include? host
|
63
|
+
end
|
64
|
+
|
65
|
+
def hosts
|
66
|
+
inspection['Spec']['TaskTemplate']['ContainerSpec']['Hosts']
|
67
|
+
end
|
68
|
+
|
69
|
+
def has_placement_constraint?(constraint)
|
70
|
+
placement_constraints.include? constraint
|
71
|
+
end
|
72
|
+
|
73
|
+
def placement_constraints
|
74
|
+
inspection['Spec']['TaskTemplate']['Placement']['Constraints']
|
75
|
+
end
|
76
|
+
|
77
|
+
def replicated?
|
78
|
+
inspection['Spec']['Mode']['Replicated']
|
79
|
+
end
|
80
|
+
|
81
|
+
def replicas
|
82
|
+
['Spec']['Mode']['Replicated']['Replicas']
|
83
|
+
end
|
84
|
+
def global?
|
85
|
+
inspection['Spec']['Mode']['Global']
|
86
|
+
end
|
87
|
+
|
88
|
+
def replicas
|
89
|
+
inspection['Spec']['Mode']['Replicated']['Replicas']
|
90
|
+
end
|
91
|
+
|
92
|
+
def networks
|
93
|
+
inspection['Spec']['TaskTemplate']['Networks']
|
94
|
+
end
|
95
|
+
|
96
|
+
def has_network?(name)
|
97
|
+
networks.find { |network| network['Aliases'].include? name }
|
98
|
+
end
|
99
|
+
|
100
|
+
def port_map
|
101
|
+
inspection['Spec']['EndpointSpec']['Ports']
|
102
|
+
end
|
103
|
+
|
104
|
+
def map_port?(published, target, protocol = 'tcp',mode = 'ingress')
|
105
|
+
port_map.find do |port|
|
106
|
+
port['PublishedPort'] == published.to_i &&
|
107
|
+
port['TargetPort'] == target.to_i && port['PublishMode'] == mode &&
|
108
|
+
port['Protocol'] == protocol
|
109
|
+
end
|
110
|
+
end
|
111
|
+
|
112
|
+
|
113
|
+
private
|
114
|
+
|
115
|
+
def get_inspection
|
116
|
+
@get_inspection ||= @runner.run_command("docker service inspect #{@name}")
|
117
|
+
end
|
118
|
+
end
|
119
|
+
end
|
120
|
+
|
121
|
+
include Serverspec::Type
|
@@ -0,0 +1,38 @@
|
|
1
|
+
require 'serverspec'
|
2
|
+
require 'serverspec/type/base'
|
3
|
+
require 'multi_json'
|
4
|
+
require 'serverspec_extra_types/helpers/properties'
|
5
|
+
require 'serverspec_extra_types/types/api_base'
|
6
|
+
|
7
|
+
module Serverspec::Type
|
8
|
+
class RabbitmqBase < ApiBase
|
9
|
+
def initialize(name = nil, options = {})
|
10
|
+
super(name, options)
|
11
|
+
@user = ENV['RABBITMQ_USER'] || 'guest'
|
12
|
+
@password = ENV['RABBITMQ_PASSWORD'] || 'guest'
|
13
|
+
@url_base = property[:variables][:rabbitmq_url] || 'http://localhost:15672'
|
14
|
+
end
|
15
|
+
|
16
|
+
|
17
|
+
def inspection
|
18
|
+
@inspection ||= ::MultiJson.load(get_inspection.stdout)[0]
|
19
|
+
end
|
20
|
+
|
21
|
+
def length
|
22
|
+
if inspection.is_a? String
|
23
|
+
inspection.length
|
24
|
+
elsif inspection.kind_of? Array
|
25
|
+
inspection.length
|
26
|
+
else
|
27
|
+
1
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
31
|
+
private
|
32
|
+
|
33
|
+
def get_inspection
|
34
|
+
command = "curl -s -u #{@user}:#{@password} #{url}"
|
35
|
+
@get_inspection ||= @runner.run_command(command)
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|
@@ -0,0 +1,18 @@
|
|
1
|
+
require 'serverspec_extra_types/types/rabbitmq_base'
|
2
|
+
|
3
|
+
module Serverspec::Type
|
4
|
+
class RabbitmqNodeList < RabbitmqBase
|
5
|
+
|
6
|
+
def url
|
7
|
+
"#{@url_base}/api/vhosts"
|
8
|
+
end
|
9
|
+
|
10
|
+
|
11
|
+
|
12
|
+
def inspection
|
13
|
+
@inspection ||= ::MultiJson.load(get_inspection.stdout)
|
14
|
+
end
|
15
|
+
|
16
|
+
|
17
|
+
end
|
18
|
+
end
|
@@ -0,0 +1,39 @@
|
|
1
|
+
require 'serverspec_extra_types/types/rabbitmq_base'
|
2
|
+
|
3
|
+
module Serverspec::Type
|
4
|
+
class RabbitmqUserPermission < RabbitmqBase
|
5
|
+
|
6
|
+
def url
|
7
|
+
"#{@url_base}/api/users/#{name}/permissions"
|
8
|
+
end
|
9
|
+
|
10
|
+
def read_from_queue?(vhost, queue)
|
11
|
+
queue.match read_permissions(vhost)
|
12
|
+
end
|
13
|
+
|
14
|
+
def write_to_queue?(vhost, queue)
|
15
|
+
queue.match write_permissions(vhost)
|
16
|
+
end
|
17
|
+
|
18
|
+
def configure_queue?(vhost, queue)
|
19
|
+
queue.match configure_permissions(vhost)
|
20
|
+
end
|
21
|
+
|
22
|
+
def read_permissions(vhost)
|
23
|
+
inspection.find { |item| item['vhost'] == vhost}['read']
|
24
|
+
end
|
25
|
+
|
26
|
+
def write_permissions(vhost)
|
27
|
+
inspection.find { |item| item['vhost'] == vhost}['write']
|
28
|
+
end
|
29
|
+
|
30
|
+
def configure_permissions(vhost)
|
31
|
+
inspection.find { |item| item['vhost'] == vhost}['configure']
|
32
|
+
end
|
33
|
+
|
34
|
+
def inspection
|
35
|
+
@inspection ||= ::MultiJson.load(get_inspection.stdout)
|
36
|
+
end
|
37
|
+
|
38
|
+
end
|
39
|
+
end
|