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.
Files changed (64) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +13 -0
  3. data/.rspec +3 -0
  4. data/.rubocop.yml +6 -0
  5. data/.travis.yml +7 -0
  6. data/CODE_OF_CONDUCT.md +74 -0
  7. data/Gemfile +6 -0
  8. data/LICENSE.txt +21 -0
  9. data/README.md +191 -0
  10. data/Rakefile +7 -0
  11. data/bin/console +14 -0
  12. data/bin/setup +8 -0
  13. data/lib/serverspec_extra_types.rb +3 -0
  14. data/lib/serverspec_extra_types/helpers/properties.rb +11 -0
  15. data/lib/serverspec_extra_types/matchers.rb +34 -0
  16. data/lib/serverspec_extra_types/matchers/be_a_manager_node.rb +15 -0
  17. data/lib/serverspec_extra_types/matchers/be_a_worker_node.rb +14 -0
  18. data/lib/serverspec_extra_types/matchers/be_active.rb +11 -0
  19. data/lib/serverspec_extra_types/matchers/configure_queue.rb +8 -0
  20. data/lib/serverspec_extra_types/matchers/have_count.rb +11 -0
  21. data/lib/serverspec_extra_types/matchers/have_domain_name.rb +10 -0
  22. data/lib/serverspec_extra_types/matchers/have_engine_version.rb +11 -0
  23. data/lib/serverspec_extra_types/matchers/have_environment_variable.rb +21 -0
  24. data/lib/serverspec_extra_types/matchers/have_ha_mode.rb +5 -0
  25. data/lib/serverspec_extra_types/matchers/have_ha_nodes.rb +8 -0
  26. data/lib/serverspec_extra_types/matchers/have_ha_sync_mode.rb +5 -0
  27. data/lib/serverspec_extra_types/matchers/have_host.rb +8 -0
  28. data/lib/serverspec_extra_types/matchers/have_hostname.rb +6 -0
  29. data/lib/serverspec_extra_types/matchers/have_image.rb +8 -0
  30. data/lib/serverspec_extra_types/matchers/have_image_sha.rb +5 -0
  31. data/lib/serverspec_extra_types/matchers/have_label.rb +20 -0
  32. data/lib/serverspec_extra_types/matchers/have_mount.rb +11 -0
  33. data/lib/serverspec_extra_types/matchers/have_network.rb +8 -0
  34. data/lib/serverspec_extra_types/matchers/have_placement_constraint.rb +8 -0
  35. data/lib/serverspec_extra_types/matchers/have_replica_count.rb +8 -0
  36. data/lib/serverspec_extra_types/matchers/have_restart_limit.rb +8 -0
  37. data/lib/serverspec_extra_types/matchers/have_restart_policy.rb +8 -0
  38. data/lib/serverspec_extra_types/matchers/have_user.rb +10 -0
  39. data/lib/serverspec_extra_types/matchers/have_vhost.rb +5 -0
  40. data/lib/serverspec_extra_types/matchers/include_regex.rb +5 -0
  41. data/lib/serverspec_extra_types/matchers/map_port.rb +25 -0
  42. data/lib/serverspec_extra_types/matchers/mirror_all.rb +5 -0
  43. data/lib/serverspec_extra_types/matchers/publish_all_ports.rb +3 -0
  44. data/lib/serverspec_extra_types/matchers/read_from_queue.rb +8 -0
  45. data/lib/serverspec_extra_types/matchers/write_to_queue.rb +8 -0
  46. data/lib/serverspec_extra_types/types.rb +18 -0
  47. data/lib/serverspec_extra_types/types/api_base.rb +36 -0
  48. data/lib/serverspec_extra_types/types/consul_base.rb +40 -0
  49. data/lib/serverspec_extra_types/types/consul_node.rb +20 -0
  50. data/lib/serverspec_extra_types/types/consul_node_list.rb +32 -0
  51. data/lib/serverspec_extra_types/types/consul_service.rb +24 -0
  52. data/lib/serverspec_extra_types/types/consul_service_list.rb +32 -0
  53. data/lib/serverspec_extra_types/types/docker_container.rb +124 -0
  54. data/lib/serverspec_extra_types/types/docker_node.rb +41 -0
  55. data/lib/serverspec_extra_types/types/docker_service.rb +121 -0
  56. data/lib/serverspec_extra_types/types/rabbitmq_base.rb +38 -0
  57. data/lib/serverspec_extra_types/types/rabbitmq_node_list.rb +18 -0
  58. data/lib/serverspec_extra_types/types/rabbitmq_user_permission.rb +39 -0
  59. data/lib/serverspec_extra_types/types/rabbitmq_vhost_list.rb +22 -0
  60. data/lib/serverspec_extra_types/types/rabbitmq_vhost_policy.rb +57 -0
  61. data/lib/serverspec_extra_types/version.rb +3 -0
  62. data/properties.yml +23 -0
  63. data/serverspec-extra-types.gemspec +36 -0
  64. 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