kitchen-vmpool 0.2.0 → 0.3.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 +4 -4
- data/CHANGELOG.md +14 -0
- data/README.md +171 -5
- data/exe/vra_create_pool +2 -2
- data/lib/kitchen-vmpool/version.rb +1 -1
- data/lib/kitchen/driver/vmpool.rb +8 -84
- data/lib/kitchen/driver/vmpool_stores/base_store.rb +12 -38
- data/lib/kitchen/driver/vmpool_stores/file_base_store.rb +113 -0
- data/lib/kitchen/driver/vmpool_stores/file_store.rb +4 -6
- data/lib/kitchen/driver/vmpool_stores/gitlab_base_store.rb +40 -0
- data/lib/kitchen/driver/vmpool_stores/gitlab_commit_store.rb +9 -13
- data/lib/kitchen/driver/vmpool_stores/gitlab_snippet_store.rb +5 -11
- data/vmpool.yaml +1 -0
- metadata +5 -2
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA1:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 8e0a7a42b3db814a96216aaa4292bef0fa20b866
|
|
4
|
+
data.tar.gz: 405f15c69be0901b3fd7d6d3450fa7eeea54ac02
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 6a5e6bdc0e6e2235b76b52bb4331a5bc088372c6430e4af37d29f87e0b0aa2d77efe42ced1c061904eafb21642c29afe91d81803d8999e329b3675f51729058b
|
|
7
|
+
data.tar.gz: b0eec9a6b626562359f18293310938471ddf094ce15009b8a8a8ab6da4ae3d4eefca8255aa295dfff75dac971e2e58dec6dddfadc57ac649a45401fb7ff4316a
|
data/CHANGELOG.md
ADDED
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
# Kitchen-Vmpool
|
|
2
|
+
|
|
3
|
+
## Unreleased
|
|
4
|
+
|
|
5
|
+
## v0.3.0
|
|
6
|
+
* Major refactor of file based stores
|
|
7
|
+
* changes instances to size
|
|
8
|
+
* removes separate pool_name in vmpool config
|
|
9
|
+
* removes reference too payload_file since it is provider specific
|
|
10
|
+
* Creates base gitlabstore class, moves gitlab monkey patch
|
|
11
|
+
|
|
12
|
+
## v0.2.0
|
|
13
|
+
* adds a gitlab commit store
|
|
14
|
+
* Fix accounting bugs with used and pool instances
|
data/README.md
CHANGED
|
@@ -1,9 +1,11 @@
|
|
|
1
1
|
# Kitchen::Vmpool
|
|
2
2
|
|
|
3
|
-
|
|
4
|
-
|
|
3
|
+
Ever wished you didn't have to wait for test-kitchen to create a test node? With kitchen-vmpool you can create your test nodes
|
|
4
|
+
ahead of time and simply populate the pool with the list of hostnames. During the create step test kitchen will select a member
|
|
5
|
+
of the test pool and you will instantly have a system to work with.
|
|
5
6
|
|
|
6
|
-
|
|
7
|
+
Kitchen-vmpool allows external scripts or programs to populate the pool so it is not tied to any single vm/container technology.
|
|
8
|
+
Additionaly, kitchen-vmpool contains a pluggable storage backend so that you can store the pool information in just about anything.
|
|
7
9
|
|
|
8
10
|
## Installation
|
|
9
11
|
|
|
@@ -22,12 +24,176 @@ Or install it yourself as:
|
|
|
22
24
|
|
|
23
25
|
## Usage
|
|
24
26
|
|
|
25
|
-
|
|
27
|
+
To use setup the kitchen driver to use the vmpool store and configure one of the stores if required.
|
|
28
|
+
|
|
29
|
+
### Gitlab Commit Store Example
|
|
30
|
+
If you have no central place to store files the gitlab_commit store may be an option for you.
|
|
31
|
+
If you have a simple setup thus may suffice. If you plan to expand your usage of test kitchen to
|
|
32
|
+
include multiple parallel test runs, you may run into race conditions due to the lack of a central queue
|
|
33
|
+
to handle reads and writes. Perfect for simple setups. Later on you can move to a different state store.
|
|
34
|
+
|
|
35
|
+
```yaml
|
|
36
|
+
driver:
|
|
37
|
+
name: vmpool
|
|
38
|
+
reuse_instances: false
|
|
39
|
+
state_store: gitlab_commit
|
|
40
|
+
store_options:
|
|
41
|
+
pool_file: 'vmpool'
|
|
42
|
+
project_id: 329302
|
|
43
|
+
|
|
44
|
+
platforms:
|
|
45
|
+
- name: rhel6
|
|
46
|
+
driver:
|
|
47
|
+
pool_name: base_rhel6_pool
|
|
48
|
+
- name: windows10
|
|
49
|
+
driver:
|
|
50
|
+
pool_name: windows10_pool
|
|
51
|
+
|
|
52
|
+
```
|
|
53
|
+
|
|
54
|
+
### Gitlab Snippet Store Example
|
|
55
|
+
I don't recommend using the snippet store because gitlab's permission's model only allows a single
|
|
56
|
+
user to make changes. Therefore this is a bad central place to keep things if only a single user can update.
|
|
57
|
+
Use this as an example to create your own store providers.
|
|
58
|
+
|
|
59
|
+
```yaml
|
|
60
|
+
driver:
|
|
61
|
+
name: vmpool
|
|
62
|
+
reuse_instances: false
|
|
63
|
+
state_store: gitlab_snippet
|
|
64
|
+
store_options:
|
|
65
|
+
pool_file: 'vmpool'
|
|
66
|
+
project_id: 329302
|
|
67
|
+
snippet_id: 49
|
|
68
|
+
|
|
69
|
+
platforms:
|
|
70
|
+
- name: rhel6
|
|
71
|
+
driver:
|
|
72
|
+
pool_name: base_rhel6_pool
|
|
73
|
+
- name: windows10
|
|
74
|
+
driver:
|
|
75
|
+
pool_name: windows10_pool
|
|
76
|
+
```
|
|
77
|
+
|
|
78
|
+
### Plain old file store
|
|
79
|
+
Probably the easiest to setup, but is useful only for a single person on the same system.
|
|
80
|
+
|
|
81
|
+
```yaml
|
|
82
|
+
driver:
|
|
83
|
+
name: vmpool
|
|
84
|
+
reuse_instances: false
|
|
85
|
+
state_store: file
|
|
86
|
+
store_options:
|
|
87
|
+
pool_file: 'vmpool'
|
|
88
|
+
|
|
89
|
+
platforms:
|
|
90
|
+
- name: rhel6
|
|
91
|
+
driver:
|
|
92
|
+
pool_name: base_rhel6_pool
|
|
93
|
+
- name: windows10
|
|
94
|
+
driver:
|
|
95
|
+
pool_name: windows10_pool
|
|
96
|
+
```
|
|
97
|
+
|
|
98
|
+
### Pool data structure
|
|
99
|
+
The basic structure of the pool data can be found below. This is the current format that each state store will follow.
|
|
100
|
+
|
|
101
|
+
```yaml
|
|
102
|
+
base_rhel6_pool:
|
|
103
|
+
payload_file: base_rhel6_payload.json
|
|
104
|
+
size: 1
|
|
105
|
+
pool_instances: []
|
|
106
|
+
requests: []
|
|
107
|
+
used_instances: []
|
|
108
|
+
|
|
109
|
+
windows10_pool:
|
|
110
|
+
payload_file: windows10_payload.json
|
|
111
|
+
size: 1
|
|
112
|
+
pool_instances: []
|
|
113
|
+
requests: []
|
|
114
|
+
used_instances: []
|
|
115
|
+
|
|
116
|
+
```
|
|
117
|
+
|
|
118
|
+
The payload_file key is not required and was used for other purposes outside of kitchen-vmpool in order to create the instances.
|
|
119
|
+
It can be expected that some users will throw extra metadata in these pools for their own purposes. So care must be
|
|
120
|
+
taken to not wipe out this data when creating a store.
|
|
121
|
+
|
|
122
|
+
### Puppet's VMpooler
|
|
123
|
+
Consider the VMpooler state store to be the ultimate backend for kitchen-vmpool. While vmpool doesn't currently support vmpooler
|
|
124
|
+
it is on the roadmap to support.
|
|
125
|
+
|
|
126
|
+
https://github.com/puppetlabs/vmpooler
|
|
127
|
+
|
|
128
|
+
Once the vmpooler state store is implemented this kitchen plugin might be pretty popular.
|
|
26
129
|
|
|
27
130
|
## Development
|
|
28
131
|
|
|
29
|
-
|
|
132
|
+
This plugin was intended to support multiple ways to populate the pool and multiple ways to store the state of those pools.
|
|
133
|
+
Therefore we leave it up to the user to create the pool instances while kitchen's job is only to interface with the pool information.
|
|
134
|
+
Pool members need to be created outside of kitchen-vmpool. Additionally pool member information must also be updated outside of kitchen-vmpool.
|
|
135
|
+
|
|
136
|
+
Puppet's vmpooler will handle the maintenance of the pool state which is probably what you want.
|
|
137
|
+
|
|
30
138
|
|
|
139
|
+
### Creating a State Store
|
|
140
|
+
|
|
141
|
+
In order to create a new state store you must do the following:
|
|
142
|
+
|
|
143
|
+
1. inherit from the BaseStore or a subclass of the BaseStore
|
|
144
|
+
2. Implement the following methods:
|
|
145
|
+
* initialize(options = {})
|
|
146
|
+
* take_pool_member
|
|
147
|
+
* mark_unused
|
|
148
|
+
|
|
149
|
+
4. All other methods used with your store must be private
|
|
150
|
+
|
|
151
|
+
You must be careful to overwrite the entire pool data. It is expected that some users
|
|
152
|
+
will put other metadata in the pool file for other purposes. So when you write your data
|
|
153
|
+
please ensure you merge with the previous data first.
|
|
154
|
+
|
|
155
|
+
Example:
|
|
156
|
+
|
|
157
|
+
```ruby
|
|
158
|
+
module Kitchen
|
|
159
|
+
module Driver
|
|
160
|
+
module VmpoolStores
|
|
161
|
+
class FileBaseStore < BaseStore
|
|
162
|
+
# @return [String] - a random host from the list of systems
|
|
163
|
+
# mark them used so nobody else can use it
|
|
164
|
+
def take_pool_member(pool_name)
|
|
165
|
+
member = pool_hosts(pool_name).sample
|
|
166
|
+
raise Kitchen::Driver::PoolMemberNotFound.new("No pool members exist for #{pool_name}, please create some pool members") unless member
|
|
167
|
+
mark_used(member, pool_name)
|
|
168
|
+
return member
|
|
169
|
+
end
|
|
170
|
+
|
|
171
|
+
# @param name [String] - the hostname to mark not used
|
|
172
|
+
# @return Array[String] - list of unused instances
|
|
173
|
+
def mark_unused(name, pool_name, reuse = false)
|
|
174
|
+
if reuse
|
|
175
|
+
used_hosts(pool_name).delete(name)
|
|
176
|
+
pool_hosts(pool_name) << name unless pool_hosts(pool_name).include?(name)
|
|
177
|
+
end
|
|
178
|
+
save
|
|
179
|
+
pool_hosts(pool_name)
|
|
180
|
+
end
|
|
181
|
+
end
|
|
182
|
+
end
|
|
183
|
+
end
|
|
184
|
+
end
|
|
185
|
+
|
|
186
|
+
```
|
|
187
|
+
|
|
188
|
+
### Adding Configuration for your store
|
|
189
|
+
|
|
190
|
+
You can pass configuration to your store by setting the `store_options` in the driver section. This is a simple hash
|
|
191
|
+
that allows the user to pass in required settings if your store requires configuration. It is up to you
|
|
192
|
+
use these options since not every store will require configuration.
|
|
193
|
+
|
|
194
|
+
|
|
195
|
+
### Development Setup
|
|
196
|
+
After checking out the repo, run `bin/setup` to install dependencies. Then, run `rake spec` to run the tests. You can also run `bin/console` for an interactive prompt that will allow you to experiment.
|
|
31
197
|
To install this gem onto your local machine, run `bundle exec rake install`. To release a new version, update the version number in `version.rb`, and then run `bundle exec rake release`, which will create a git tag for the version, push git commits and tags, and push the `.gem` file to [rubygems.org](https://rubygems.org).
|
|
32
198
|
|
|
33
199
|
## Contributing
|
data/exe/vra_create_pool
CHANGED
|
@@ -20,7 +20,7 @@ def options
|
|
|
20
20
|
end
|
|
21
21
|
|
|
22
22
|
def create_pool(pool_data)
|
|
23
|
-
(1..pool_data['
|
|
23
|
+
(1..pool_data['size']).map do |num|
|
|
24
24
|
puts pool_data['payload_file']
|
|
25
25
|
submit_new_request(pool_data['payload_file']).id
|
|
26
26
|
end
|
|
@@ -86,7 +86,7 @@ def create_pools
|
|
|
86
86
|
# create the pool, and save the request in the requests
|
|
87
87
|
# do not create if the number of systems and requests are more than the requested amount
|
|
88
88
|
current_total = value['pool_instances'].count + pools[key]['requests'].count
|
|
89
|
-
unless current_total >= value['
|
|
89
|
+
unless current_total >= value['size']
|
|
90
90
|
reqs = create_pool(value)
|
|
91
91
|
pools[key]['requests'] = reqs
|
|
92
92
|
end
|
|
@@ -26,8 +26,6 @@ require 'kitchen-vmpool/version'
|
|
|
26
26
|
module Kitchen
|
|
27
27
|
module Driver
|
|
28
28
|
|
|
29
|
-
class PoolMemberNotFound < Exception; end
|
|
30
|
-
|
|
31
29
|
class Vmpool < Kitchen::Driver::Base
|
|
32
30
|
include Kitchen::Logging
|
|
33
31
|
|
|
@@ -44,78 +42,24 @@ module Kitchen
|
|
|
44
42
|
|
|
45
43
|
# (see Base#create)
|
|
46
44
|
def create(state)
|
|
47
|
-
|
|
45
|
+
member = store.take_pool_member(config[:pool_name])
|
|
46
|
+
info("Pool member #{member} was selected")
|
|
47
|
+
state[:hostname] = member
|
|
48
48
|
end
|
|
49
49
|
|
|
50
50
|
# (see Base#destroy)
|
|
51
51
|
def destroy(state)
|
|
52
52
|
return if state[:hostname].nil?
|
|
53
|
-
mark_unused(state[:hostname])
|
|
54
|
-
state.delete(:hostname)
|
|
55
|
-
end
|
|
56
|
-
|
|
57
|
-
private
|
|
58
|
-
|
|
59
|
-
# @return [String] - a random host from the list of systems
|
|
60
|
-
# mark them used so nobody else can use it
|
|
61
|
-
def take_pool_member
|
|
62
|
-
member = pool_hosts.sample
|
|
63
|
-
raise PoolMemberNotFound.new("No pool members exist for #{config[:pool_name]}, please create some pool members") unless member
|
|
64
|
-
mark_used(member)
|
|
65
|
-
info("Pool member #{member} was selected")
|
|
66
|
-
return member
|
|
67
|
-
end
|
|
68
|
-
|
|
69
|
-
# @return Array[String] - a list of pool names
|
|
70
|
-
def pool_names
|
|
71
|
-
store.pool_data.keys
|
|
72
|
-
end
|
|
73
|
-
|
|
74
|
-
# @return [Hash] - a pool hash by the given pool_name from the config
|
|
75
|
-
def pool
|
|
76
|
-
name = config[:pool_name]
|
|
77
|
-
raise ArgumentError.new("Pool #{name} does not exist") unless pool_exists?(name)
|
|
78
|
-
store.pool_data[name]
|
|
79
|
-
end
|
|
80
|
-
|
|
81
|
-
# @return [Boolean] - true if the pool exists
|
|
82
|
-
def pool_exists?(name)
|
|
83
|
-
pool_names.include?(name)
|
|
84
|
-
end
|
|
85
|
-
|
|
86
|
-
# @return Array[String] - a list of host names in the pool
|
|
87
|
-
def pool_hosts
|
|
88
|
-
pool['pool_instances'] ||= []
|
|
89
|
-
end
|
|
90
|
-
|
|
91
|
-
# @return Array[String] - a list of used host names in the pool
|
|
92
|
-
def used_hosts
|
|
93
|
-
pool['used_instances'] ||= []
|
|
94
|
-
end
|
|
95
|
-
|
|
96
|
-
# @param name [String] - the hostname to mark not used
|
|
97
|
-
# @return Array[String] - list of unused instances
|
|
98
|
-
def mark_unused(name)
|
|
53
|
+
store.mark_unused(state[:hostname], config[:pool_name], config[:reuse_instances])
|
|
99
54
|
if config[:reuse_instances]
|
|
100
55
|
info("Marking pool member #{name} as unused")
|
|
101
|
-
|
|
102
|
-
|
|
56
|
+
else
|
|
57
|
+
info("Marking pool member #{name} as used")
|
|
103
58
|
end
|
|
104
|
-
|
|
105
|
-
pool_hosts
|
|
59
|
+
state.delete(:hostname)
|
|
106
60
|
end
|
|
107
61
|
|
|
108
|
-
|
|
109
|
-
# @return Array[String] - list of used instances
|
|
110
|
-
def mark_used(name)
|
|
111
|
-
debug("Marking pool member #{name} as used")
|
|
112
|
-
# ideally the member should not already be in this array
|
|
113
|
-
# but just in case we will protect against that
|
|
114
|
-
pool_hosts.delete(name)
|
|
115
|
-
used_hosts << name unless used_hosts.include?(name)
|
|
116
|
-
store.save
|
|
117
|
-
used_hosts
|
|
118
|
-
end
|
|
62
|
+
private
|
|
119
63
|
|
|
120
64
|
# @return [Hash] - a store hash that contains one or more pools
|
|
121
65
|
def store
|
|
@@ -140,23 +84,3 @@ module Kitchen
|
|
|
140
84
|
end
|
|
141
85
|
end
|
|
142
86
|
|
|
143
|
-
require 'gitlab'
|
|
144
|
-
# monkey patch error in error code until it is fixed upstream
|
|
145
|
-
module Gitlab
|
|
146
|
-
module Error
|
|
147
|
-
class ResponseError
|
|
148
|
-
# Human friendly message.
|
|
149
|
-
#
|
|
150
|
-
# @return [String]
|
|
151
|
-
private
|
|
152
|
-
def build_error_message
|
|
153
|
-
parsed_response = @response.parsed_response
|
|
154
|
-
message = parsed_response.respond_to?(:message) ? parsed_response.message : parsed_response['message']
|
|
155
|
-
message = parsed_response.error unless message
|
|
156
|
-
"Server responded with code #{@response.code}, message: " \
|
|
157
|
-
"#{handle_message(message)}. " \
|
|
158
|
-
"Request URI: #{@response.request.base_uri}#{@response.request.path}"
|
|
159
|
-
end
|
|
160
|
-
end
|
|
161
|
-
end
|
|
162
|
-
end
|
|
@@ -1,51 +1,25 @@
|
|
|
1
1
|
require 'yaml'
|
|
2
|
-
require 'kitchen/logger'
|
|
3
2
|
require 'kitchen'
|
|
4
|
-
require 'kitchen/logging'
|
|
5
3
|
|
|
6
4
|
module Kitchen
|
|
7
5
|
module Driver
|
|
6
|
+
class PoolMemberNotFound < Exception; end
|
|
7
|
+
|
|
8
8
|
module VmpoolStores
|
|
9
9
|
class BaseStore
|
|
10
|
-
attr_reader :pool_file, :pool_data
|
|
11
|
-
include Kitchen::Logging
|
|
12
|
-
|
|
13
|
-
def update(content = nil)
|
|
14
|
-
#info("Updating vmpool data")
|
|
15
|
-
write_content(content)
|
|
16
|
-
read
|
|
17
|
-
end
|
|
18
|
-
|
|
19
|
-
def create
|
|
20
|
-
#info("Creating new vmpool data")
|
|
21
|
-
write_content(base_content)
|
|
22
|
-
read
|
|
23
|
-
end
|
|
24
|
-
|
|
25
|
-
def read
|
|
26
|
-
#info("Reading vmpool data")
|
|
27
|
-
read_content
|
|
28
|
-
end
|
|
29
|
-
|
|
30
|
-
def reread
|
|
31
|
-
pool_data(true)
|
|
32
|
-
end
|
|
33
10
|
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
11
|
+
# @return [String] - a random host from the list of systems
|
|
12
|
+
# mark them used so nobody else can use it
|
|
13
|
+
# @param pool_name [String] - the name of the pool to yank the memeber from
|
|
14
|
+
def take_pool_member(pool_name)
|
|
15
|
+
raise NotImplemented
|
|
38
16
|
end
|
|
39
17
|
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
private
|
|
46
|
-
|
|
47
|
-
def read_content
|
|
48
|
-
raise NotImplementedError
|
|
18
|
+
# @param name [String] - the hostname to mark not used
|
|
19
|
+
# @param pool_name [String] - the name of the pool to yank the memeber from
|
|
20
|
+
# @return Array[String] - list of unused instances
|
|
21
|
+
def mark_unused(name, pool_name, reuse = false)
|
|
22
|
+
raise NotImplemented
|
|
49
23
|
end
|
|
50
24
|
end
|
|
51
25
|
end
|
|
@@ -0,0 +1,113 @@
|
|
|
1
|
+
require "kitchen/driver/vmpool_stores/base_store"
|
|
2
|
+
|
|
3
|
+
module Kitchen
|
|
4
|
+
module Driver
|
|
5
|
+
class PoolMemberNotFound < Exception; end
|
|
6
|
+
|
|
7
|
+
module VmpoolStores
|
|
8
|
+
class FileBaseStore < BaseStore
|
|
9
|
+
attr_reader :pool_file, :pool_data
|
|
10
|
+
include Kitchen::Logging
|
|
11
|
+
|
|
12
|
+
# @return [String] - a random host from the list of systems
|
|
13
|
+
# mark them used so nobody else can use it
|
|
14
|
+
def take_pool_member(pool_name)
|
|
15
|
+
member = pool_hosts(pool_name).sample
|
|
16
|
+
raise Kitchen::Driver::PoolMemberNotFound.new("No pool members exist for #{pool_name}, please create some pool members") unless member
|
|
17
|
+
mark_used(member, pool_name)
|
|
18
|
+
return member
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
# @param name [String] - the hostname to mark not used
|
|
22
|
+
# @return Array[String] - list of unused instances
|
|
23
|
+
def mark_unused(name, pool_name, reuse = false)
|
|
24
|
+
if reuse
|
|
25
|
+
used_hosts(pool_name).delete(name)
|
|
26
|
+
pool_hosts(pool_name) << name unless pool_hosts(pool_name).include?(name)
|
|
27
|
+
end
|
|
28
|
+
save
|
|
29
|
+
pool_hosts(pool_name)
|
|
30
|
+
end
|
|
31
|
+
|
|
32
|
+
def pool_data(refresh = false)
|
|
33
|
+
@pool_data = nil if refresh
|
|
34
|
+
@pool_data ||= YAML.load(read_content)
|
|
35
|
+
end
|
|
36
|
+
|
|
37
|
+
private
|
|
38
|
+
|
|
39
|
+
# @return Array[String] - a list of pool names
|
|
40
|
+
def pool_names
|
|
41
|
+
pool_data.keys
|
|
42
|
+
end
|
|
43
|
+
|
|
44
|
+
# @return [Hash] - a pool hash by the given pool_name from the config
|
|
45
|
+
def pool(name)
|
|
46
|
+
raise ArgumentError.new("Pool #{name} does not exist") unless pool_exists?(name)
|
|
47
|
+
pool_data[name]
|
|
48
|
+
end
|
|
49
|
+
|
|
50
|
+
# @return [Boolean] - true if the pool exists
|
|
51
|
+
def pool_exists?(name)
|
|
52
|
+
pool_names.include?(name)
|
|
53
|
+
end
|
|
54
|
+
|
|
55
|
+
# @return Array[String] - a list of host names in the pool
|
|
56
|
+
def pool_hosts(pool_name)
|
|
57
|
+
pool(pool_name)['pool_instances'] ||= []
|
|
58
|
+
end
|
|
59
|
+
|
|
60
|
+
# @return Array[String] - a list of used host names in the pool
|
|
61
|
+
def used_hosts(pool_name)
|
|
62
|
+
pool(pool_name)['used_instances'] ||= []
|
|
63
|
+
end
|
|
64
|
+
|
|
65
|
+
# @param name [String] - the hostname to mark used
|
|
66
|
+
# @return Array[String] - list of used instances
|
|
67
|
+
def mark_used(name, pool_name)
|
|
68
|
+
# ideally the member should not already be in this array
|
|
69
|
+
# but just in case we will protect against that
|
|
70
|
+
pool_hosts(pool_name).delete(name)
|
|
71
|
+
used_hosts(pool_name) << name unless used_hosts(pool_name).include?(name)
|
|
72
|
+
save
|
|
73
|
+
used_hosts(pool_name)
|
|
74
|
+
end
|
|
75
|
+
|
|
76
|
+
def update(content = nil)
|
|
77
|
+
#info("Updating vmpool data")
|
|
78
|
+
write_content(content)
|
|
79
|
+
read
|
|
80
|
+
end
|
|
81
|
+
|
|
82
|
+
def create
|
|
83
|
+
#info("Creating new vmpool data")
|
|
84
|
+
write_content(base_content)
|
|
85
|
+
read
|
|
86
|
+
end
|
|
87
|
+
|
|
88
|
+
def read
|
|
89
|
+
#info("Reading vmpool data")
|
|
90
|
+
read_content
|
|
91
|
+
end
|
|
92
|
+
|
|
93
|
+
def reread
|
|
94
|
+
pool_data(true)
|
|
95
|
+
end
|
|
96
|
+
|
|
97
|
+
def save
|
|
98
|
+
#info("Saving vmpool data")
|
|
99
|
+
write_content
|
|
100
|
+
read
|
|
101
|
+
end
|
|
102
|
+
|
|
103
|
+
def read_content
|
|
104
|
+
raise NotImplementedError
|
|
105
|
+
end
|
|
106
|
+
|
|
107
|
+
def write_content(content = pool_data)
|
|
108
|
+
raise NotImplementedError
|
|
109
|
+
end
|
|
110
|
+
end
|
|
111
|
+
end
|
|
112
|
+
end
|
|
113
|
+
end
|
|
@@ -1,9 +1,8 @@
|
|
|
1
|
-
require
|
|
2
|
-
require "kitchen/driver/vmpool_stores/base_store"
|
|
1
|
+
require "kitchen/driver/vmpool_stores/file_base_store"
|
|
3
2
|
module Kitchen
|
|
4
3
|
module Driver
|
|
5
4
|
module VmpoolStores
|
|
6
|
-
class FileStore <
|
|
5
|
+
class FileStore < FileBaseStore
|
|
7
6
|
|
|
8
7
|
# @option pool_file [String] - the file path that holds the pool information
|
|
9
8
|
def initialize(options = nil)
|
|
@@ -17,10 +16,9 @@ module Kitchen
|
|
|
17
16
|
def base_content
|
|
18
17
|
{
|
|
19
18
|
pool1: {
|
|
20
|
-
|
|
21
|
-
payload_file: pool1_payload.yaml,
|
|
22
|
-
instances: 1,
|
|
19
|
+
size: 1,
|
|
23
20
|
pool_instances: [],
|
|
21
|
+
used_instances: [],
|
|
24
22
|
requests: []
|
|
25
23
|
}
|
|
26
24
|
}
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
require 'gitlab'
|
|
2
|
+
require "kitchen/driver/vmpool_stores/file_base_store"
|
|
3
|
+
require 'yaml'
|
|
4
|
+
|
|
5
|
+
module Kitchen
|
|
6
|
+
module Driver
|
|
7
|
+
module VmpoolStores
|
|
8
|
+
class GitlabBaseStore < FileBaseStore
|
|
9
|
+
|
|
10
|
+
private
|
|
11
|
+
|
|
12
|
+
def client
|
|
13
|
+
@client ||= Gitlab.client
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
end
|
|
17
|
+
end
|
|
18
|
+
end
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
# monkey patch error in error code until it is fixed upstream
|
|
22
|
+
module Gitlab
|
|
23
|
+
module Error
|
|
24
|
+
class ResponseError
|
|
25
|
+
# Human friendly message.
|
|
26
|
+
#
|
|
27
|
+
# @return [String]
|
|
28
|
+
private
|
|
29
|
+
def build_error_message
|
|
30
|
+
parsed_response = @response.parsed_response
|
|
31
|
+
message = parsed_response.respond_to?(:message) ? parsed_response.message : parsed_response['message']
|
|
32
|
+
message = parsed_response.error unless message
|
|
33
|
+
"Server responded with code #{@response.code}, message: " \
|
|
34
|
+
"#{handle_message(message)}. " \
|
|
35
|
+
"Request URI: #{@response.request.base_uri}#{@response.request.path}"
|
|
36
|
+
end
|
|
37
|
+
end
|
|
38
|
+
end
|
|
39
|
+
end
|
|
40
|
+
|
|
@@ -1,11 +1,9 @@
|
|
|
1
|
-
require
|
|
2
|
-
require "kitchen/driver/vmpool_stores/base_store"
|
|
3
|
-
require 'yaml'
|
|
1
|
+
require "kitchen/driver/vmpool_stores/gitlab_base_store"
|
|
4
2
|
|
|
5
3
|
module Kitchen
|
|
6
4
|
module Driver
|
|
7
5
|
module VmpoolStores
|
|
8
|
-
class GitlabCommitStore <
|
|
6
|
+
class GitlabCommitStore < GitlabBaseStore
|
|
9
7
|
|
|
10
8
|
attr_accessor :project_id
|
|
11
9
|
attr_reader :pool_file, :branch
|
|
@@ -14,13 +12,17 @@ module Kitchen
|
|
|
14
12
|
# @option commit_id [Integer] - the snipppet id in the gitlab project
|
|
15
13
|
# @option pool_file [String] - the snipppet file name
|
|
16
14
|
def initialize(options = nil)
|
|
17
|
-
|
|
15
|
+
# there is currently some sort of weird bug in gitlab that prevents us from creating files with a yaml extension
|
|
16
|
+
# thus we have ranmed the default pool file to vmpool
|
|
17
|
+
options ||= { "project_id" => nil, "pool_file" => 'vmpool'}
|
|
18
18
|
raise ArgumentError.new("You must pass the project_id option") unless options['project_id'].to_i > 0
|
|
19
19
|
@project_id = options['project_id'] #ie. 89
|
|
20
|
-
@pool_file = options['pool_file'] || 'vmpool
|
|
20
|
+
@pool_file = options['pool_file'] || 'vmpool'
|
|
21
21
|
@branch = 'master'
|
|
22
22
|
end
|
|
23
23
|
|
|
24
|
+
private
|
|
25
|
+
|
|
24
26
|
def update(content = nil)
|
|
25
27
|
#info("Updating vmpool data")
|
|
26
28
|
update_file
|
|
@@ -34,7 +36,7 @@ module Kitchen
|
|
|
34
36
|
end
|
|
35
37
|
|
|
36
38
|
def save
|
|
37
|
-
|
|
39
|
+
# info("Saving vmpool data")
|
|
38
40
|
update_file
|
|
39
41
|
read
|
|
40
42
|
end
|
|
@@ -43,12 +45,6 @@ module Kitchen
|
|
|
43
45
|
read_content(project, file)
|
|
44
46
|
end
|
|
45
47
|
|
|
46
|
-
private
|
|
47
|
-
|
|
48
|
-
def client
|
|
49
|
-
@client ||= Gitlab.client
|
|
50
|
-
end
|
|
51
|
-
|
|
52
48
|
def create_file(project = project_id)
|
|
53
49
|
actions = [{
|
|
54
50
|
"action" => "create",
|
|
@@ -1,10 +1,8 @@
|
|
|
1
|
-
require
|
|
2
|
-
require "kitchen/driver/vmpool_stores/base_store"
|
|
3
|
-
require 'yaml'
|
|
1
|
+
require "kitchen/driver/vmpool_stores/gitlab_base_store"
|
|
4
2
|
module Kitchen
|
|
5
3
|
module Driver
|
|
6
4
|
module VmpoolStores
|
|
7
|
-
class GitlabSnippetStore <
|
|
5
|
+
class GitlabSnippetStore < GitlabBaseStore
|
|
8
6
|
|
|
9
7
|
attr_accessor :project_id, :snippet_id
|
|
10
8
|
attr_reader :pool_file
|
|
@@ -15,11 +13,13 @@ module Kitchen
|
|
|
15
13
|
def initialize(options = nil)
|
|
16
14
|
options ||= { project_id: nil, snippet_id: nil, pool_file: 'vmpool'}
|
|
17
15
|
raise ArgumentError.new("You must pass the project_id option") unless options['project_id'].to_i > 0
|
|
18
|
-
@snippet_id = options['snippet_id'] #ie.
|
|
16
|
+
@snippet_id = options['snippet_id'] #ie. 34422
|
|
19
17
|
@project_id = options['project_id'] #ie. 89
|
|
20
18
|
@pool_file = options['pool_file']
|
|
21
19
|
end
|
|
22
20
|
|
|
21
|
+
private
|
|
22
|
+
|
|
23
23
|
def update(content = nil)
|
|
24
24
|
#info("Updating vmpool data")
|
|
25
25
|
update_snippet
|
|
@@ -39,12 +39,6 @@ module Kitchen
|
|
|
39
39
|
read
|
|
40
40
|
end
|
|
41
41
|
|
|
42
|
-
private
|
|
43
|
-
|
|
44
|
-
def client
|
|
45
|
-
@client ||= Gitlab.client
|
|
46
|
-
end
|
|
47
|
-
|
|
48
42
|
def snippet_exists?(project = project_id)
|
|
49
43
|
return false unless snippet_id
|
|
50
44
|
client.snippets(project, {
|
data/vmpool.yaml
CHANGED
metadata
CHANGED
|
@@ -1,14 +1,14 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: kitchen-vmpool
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 0.
|
|
4
|
+
version: 0.3.0
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Corey Osman
|
|
8
8
|
autorequire:
|
|
9
9
|
bindir: exe
|
|
10
10
|
cert_chain: []
|
|
11
|
-
date: 2017-09-
|
|
11
|
+
date: 2017-09-08 00:00:00.000000000 Z
|
|
12
12
|
dependencies:
|
|
13
13
|
- !ruby/object:Gem::Dependency
|
|
14
14
|
name: gitlab
|
|
@@ -78,6 +78,7 @@ files:
|
|
|
78
78
|
- ".gitignore"
|
|
79
79
|
- ".rspec"
|
|
80
80
|
- ".travis.yml"
|
|
81
|
+
- CHANGELOG.md
|
|
81
82
|
- CODE_OF_CONDUCT.md
|
|
82
83
|
- Gemfile
|
|
83
84
|
- LICENSE.txt
|
|
@@ -91,7 +92,9 @@ files:
|
|
|
91
92
|
- lib/kitchen-vmpool/version.rb
|
|
92
93
|
- lib/kitchen/driver/vmpool.rb
|
|
93
94
|
- lib/kitchen/driver/vmpool_stores/base_store.rb
|
|
95
|
+
- lib/kitchen/driver/vmpool_stores/file_base_store.rb
|
|
94
96
|
- lib/kitchen/driver/vmpool_stores/file_store.rb
|
|
97
|
+
- lib/kitchen/driver/vmpool_stores/gitlab_base_store.rb
|
|
95
98
|
- lib/kitchen/driver/vmpool_stores/gitlab_commit_store.rb
|
|
96
99
|
- lib/kitchen/driver/vmpool_stores/gitlab_snippet_store.rb
|
|
97
100
|
- vmpool.yaml
|