controlrepo 1.0.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 +1 -0
- data/README.md +274 -0
- data/controlrepo.gemspec +26 -0
- data/lib/controlrepo.rb +323 -0
- data/lib/controlrepo/beaker.rb +185 -0
- data/lib/controlrepo/class.rb +28 -0
- data/lib/controlrepo/group.rb +61 -0
- data/lib/controlrepo/node.rb +43 -0
- data/lib/controlrepo/rake_tasks.rb +150 -0
- data/lib/controlrepo/test.rb +124 -0
- data/lib/controlrepo/testconfig.rb +136 -0
- data/templates/.fixtures.yml.erb +24 -0
- data/templates/Gemfile.erb +5 -0
- data/templates/Rakefile.erb +1 -0
- data/templates/acceptance_test_spec.rb.erb +18 -0
- data/templates/nodeset.yaml.erb +9 -0
- data/templates/spec_helper.rb.erb +7 -0
- data/templates/spec_helper_acceptance.rb.erb +24 -0
- data/templates/test_spec.rb.erb +13 -0
- metadata +162 -0
@@ -0,0 +1,124 @@
|
|
1
|
+
class Controlrepo
|
2
|
+
class Test
|
3
|
+
@@all =[]
|
4
|
+
|
5
|
+
attr_accessor :nodes
|
6
|
+
attr_accessor :classes
|
7
|
+
attr_accessor :options
|
8
|
+
|
9
|
+
# This can accept a bunch of stuff. It can accept nodes, classes or groups anywhere
|
10
|
+
# it will then detect them and expand them out into their respective objects so that
|
11
|
+
# we just end up with a list of nodes and classes
|
12
|
+
def initialize(on_these,test_this,options = {})
|
13
|
+
@nodes = []
|
14
|
+
@classes = []
|
15
|
+
@options = options
|
16
|
+
|
17
|
+
# Get the nodes we are working on
|
18
|
+
if Controlrepo::Group.find(on_these)
|
19
|
+
@nodes << Controlrepo::Group.find(on_these).members
|
20
|
+
elsif Controlrepo::Node.find(on_these)
|
21
|
+
@nodes << Controlrepo::Node.find(on_these)
|
22
|
+
else
|
23
|
+
raise "#{on_these} was not found in the list of nodes or groups!"
|
24
|
+
end
|
25
|
+
|
26
|
+
@nodes.flatten!
|
27
|
+
|
28
|
+
# Check that our nodes list contains only nodes
|
29
|
+
raise "#{@nodes} contained a non-node object." unless @nodes.all? { |item| item.is_a?(Controlrepo::Node) }
|
30
|
+
|
31
|
+
if test_this.is_a?(String)
|
32
|
+
# If we have just given a string then grab all the classes it corresponds to
|
33
|
+
if Controlrepo::Group.find(test_this)
|
34
|
+
@classes << Controlrepo::Group.find(test_this).members
|
35
|
+
elsif Controlrepo::Class.find(test_this)
|
36
|
+
@classes << Controlrepo::Class.find(test_this)
|
37
|
+
else
|
38
|
+
raise "#{test_this} was not found in the list of classes or groups!"
|
39
|
+
end
|
40
|
+
@classes.flatten!
|
41
|
+
elsif test_this.is_a?(Hash)
|
42
|
+
# If it is a hash we need to get creative
|
43
|
+
|
44
|
+
# Get all of the included classes and add them
|
45
|
+
if Controlrepo::Group.find(test_this['include'])
|
46
|
+
@classes << Controlrepo::Group.find(test_this['include']).members
|
47
|
+
elsif Controlrepo::Class.find(test_this['include'])
|
48
|
+
@classes << Controlrepo::Class.find(test_this['include'])
|
49
|
+
else
|
50
|
+
raise "#{test_this['include']} was not found in the list of classes or groups!"
|
51
|
+
end
|
52
|
+
@classes.flatten!
|
53
|
+
|
54
|
+
# Then remove any excluded ones
|
55
|
+
if Controlrepo::Group.find(test_this['exclude'])
|
56
|
+
Controlrepo::Group.find(test_this['exclude']).members.each do |clarse|
|
57
|
+
@classes.delete(clarse)
|
58
|
+
end
|
59
|
+
elsif Controlrepo::Class.find(test_this['exclude'])
|
60
|
+
@classes.delete(Controlrepo::Class.find(test_this['exclude']))
|
61
|
+
else
|
62
|
+
raise "#{test_this['exclude']} was not found in the list of classes or groups!"
|
63
|
+
end
|
64
|
+
elsif test_this.is_a?(Controlrepo::Class)
|
65
|
+
@classes << test_this
|
66
|
+
end
|
67
|
+
end
|
68
|
+
|
69
|
+
def eql?(other)
|
70
|
+
(@nodes.sort.eql?(other.nodes.sort)) and (@classes.sort.eql?(other.classes.sort))
|
71
|
+
end
|
72
|
+
|
73
|
+
def to_s
|
74
|
+
class_msg = ""
|
75
|
+
node_msg = ""
|
76
|
+
if classes.count > 1
|
77
|
+
class_msg = "#{classes.count}_classes"
|
78
|
+
else
|
79
|
+
class_msg = classes[0].name
|
80
|
+
end
|
81
|
+
|
82
|
+
if nodes.count > 1
|
83
|
+
node_msg = "#{nodes.count}_nodes"
|
84
|
+
else
|
85
|
+
node_msg = nodes[0].name
|
86
|
+
end
|
87
|
+
|
88
|
+
"#{class_msg}_on_#{node_msg}"
|
89
|
+
end
|
90
|
+
|
91
|
+
def self.deduplicate(tests)
|
92
|
+
# This should take an array of tests and remove any duplicates from them
|
93
|
+
|
94
|
+
# this will be an array of arrays, or maybe hashes
|
95
|
+
combinations = []
|
96
|
+
new_tests = []
|
97
|
+
tests.each do |test|
|
98
|
+
test.nodes.each do |node|
|
99
|
+
test.classes.each do |cls|
|
100
|
+
combo = {node => cls}
|
101
|
+
unless combinations.member?(combo)
|
102
|
+
combinations << combo
|
103
|
+
new_tests << Controlrepo::Test.new(node,cls,test.options)
|
104
|
+
end
|
105
|
+
end
|
106
|
+
end
|
107
|
+
end
|
108
|
+
|
109
|
+
# The array that this returns should be ephemeral, it does not
|
110
|
+
# represent anything defined in a controlrepo and should just
|
111
|
+
# be passed into the thing doing the testing and then killed,
|
112
|
+
# we don't want too many copies of the same shit going around
|
113
|
+
#
|
114
|
+
# Actually based on the way things are written I don't think this
|
115
|
+
# will duplicated node or class objects, just test objects,
|
116
|
+
# everything else is passed by reference
|
117
|
+
new_tests
|
118
|
+
end
|
119
|
+
|
120
|
+
def self.all
|
121
|
+
@@all
|
122
|
+
end
|
123
|
+
end
|
124
|
+
end
|
@@ -0,0 +1,136 @@
|
|
1
|
+
require 'controlrepo/class'
|
2
|
+
require 'controlrepo/node'
|
3
|
+
require 'controlrepo/group'
|
4
|
+
require 'controlrepo/test'
|
5
|
+
|
6
|
+
class Controlrepo
|
7
|
+
class TestConfig
|
8
|
+
require 'yaml'
|
9
|
+
|
10
|
+
attr_accessor :classes
|
11
|
+
attr_accessor :nodes
|
12
|
+
attr_accessor :groups
|
13
|
+
attr_accessor :tests
|
14
|
+
attr_accessor :environment
|
15
|
+
|
16
|
+
def initialize(file, environment = 'production')
|
17
|
+
begin
|
18
|
+
config = YAML.load(File.read(file))
|
19
|
+
rescue YAML::ParserError
|
20
|
+
raise "Could not parse the YAML file, check that it is valid YAML and that the encoding is correct"
|
21
|
+
end
|
22
|
+
|
23
|
+
@environment = environment
|
24
|
+
@classes = []
|
25
|
+
@nodes = []
|
26
|
+
@groups = []
|
27
|
+
@tests = []
|
28
|
+
|
29
|
+
config['classes'].each { |clarse| @classes << Controlrepo::Class.new(clarse) }
|
30
|
+
config['nodes'].each { |node| @nodes << Controlrepo::Node.new(node) }
|
31
|
+
config['groups'].each { |name, members| @groups << Controlrepo::Group.new(name, members) }
|
32
|
+
|
33
|
+
# Add the 'all_classes' and 'all_nodes' default groups
|
34
|
+
@groups << Controlrepo::Group.new('all_nodes',@nodes)
|
35
|
+
@groups << Controlrepo::Group.new('all_classes',@classes)
|
36
|
+
|
37
|
+
config['test_matrix'].each do |machines, roles|
|
38
|
+
# TODO: Work out some way to set per-test options like idempotency
|
39
|
+
@tests << Controlrepo::Test.new(machines,roles)
|
40
|
+
end
|
41
|
+
end
|
42
|
+
|
43
|
+
def r10k_deploy_local(repo = Controlrepo.new)
|
44
|
+
require 'controlrepo'
|
45
|
+
tempdir = Dir.mktmpdir('r10k')
|
46
|
+
repo.tempdir = tempdir
|
47
|
+
|
48
|
+
# Read in the config and change all the directories, then create them
|
49
|
+
r10k_config = repo.r10k_config
|
50
|
+
r10k_config[:cachedir] = "#{tempdir}#{r10k_config[:cachedir]}"
|
51
|
+
FileUtils::mkdir_p(r10k_config[:cachedir])
|
52
|
+
r10k_config[:sources].map do |name,source_settings|
|
53
|
+
source_settings["basedir"] = "#{tempdir}#{source_settings["basedir"]}"
|
54
|
+
FileUtils::mkdir_p(source_settings["basedir"])
|
55
|
+
# Yes, I realise this is going to set it many times
|
56
|
+
repo.temp_environmentpath = source_settings["basedir"]
|
57
|
+
end
|
58
|
+
File.write("#{tempdir}/r10k.yaml",r10k_config.to_yaml)
|
59
|
+
|
60
|
+
# Pull the trigger!
|
61
|
+
Dir.chdir(tempdir) do
|
62
|
+
`r10k deploy environment #{@environment} -p --color --config #{tempdir}/r10k.yaml --verbose`
|
63
|
+
end
|
64
|
+
|
65
|
+
# Return tempdir for use
|
66
|
+
tempdir
|
67
|
+
end
|
68
|
+
|
69
|
+
def write_spec_test(location, test)
|
70
|
+
# Use an ERB template to write a spec test
|
71
|
+
template_dir = File.expand_path('../../templates',File.dirname(__FILE__))
|
72
|
+
spec_template = File.read(File.expand_path('./test_spec.rb.erb',template_dir))
|
73
|
+
randomness = (0...6).map { (65 + rand(26)).chr }.join
|
74
|
+
File.write("#{location}/#{randomness}_#{test.to_s}_spec.rb",ERB.new(spec_template, nil, '-').result(binding))
|
75
|
+
end
|
76
|
+
|
77
|
+
def write_acceptance_test(location, test)
|
78
|
+
template_dir = File.expand_path('../../templates',File.dirname(__FILE__))
|
79
|
+
acc_test_template = File.read(File.expand_path('./acceptance_test_spec.rb.erb',template_dir))
|
80
|
+
raise 'We only support writing acceptance tests for one node at the moment' unless test.nodes.count == 1
|
81
|
+
randomness = (0...6).map { (65 + rand(26)).chr }.join
|
82
|
+
File.write("#{location}/#{randomness}_#{test.to_s}_spec.rb",ERB.new(acc_test_template, nil, '-').result(binding))
|
83
|
+
end
|
84
|
+
|
85
|
+
def write_spec_helper_acceptance(location, repo)
|
86
|
+
template_dir = File.expand_path('../../templates',File.dirname(__FILE__))
|
87
|
+
spec_heler_acc_template = File.read(File.expand_path('./spec_helper_acceptance.rb.erb',template_dir))
|
88
|
+
File.write("#{location}/spec_helper_acceptance.rb",ERB.new(spec_heler_acc_template, nil, '-').result(binding))
|
89
|
+
end
|
90
|
+
|
91
|
+
def write_rakefile(location, pattern)
|
92
|
+
template_dir = File.expand_path('../../templates',File.dirname(__FILE__))
|
93
|
+
rakefile_template = File.read(File.expand_path('./Rakefile.erb',template_dir))
|
94
|
+
File.write("#{location}/Rakefile",ERB.new(rakefile_template, nil, '-').result(binding))
|
95
|
+
end
|
96
|
+
|
97
|
+
def write_gemfile(location)
|
98
|
+
template_dir = File.expand_path('../../templates',File.dirname(__FILE__))
|
99
|
+
gemfile_template = File.read(File.expand_path('./Gemfile.erb',template_dir))
|
100
|
+
File.write("#{location}/Gemfile",ERB.new(gemfile_template, nil, '-').result(binding))
|
101
|
+
end
|
102
|
+
|
103
|
+
def write_spec_helper(location, repo)
|
104
|
+
environmentpath = repo.temp_environmentpath
|
105
|
+
modulepath = repo.config['modulepath']
|
106
|
+
modulepath.delete("$basemodulepath")
|
107
|
+
modulepath.map! do |path|
|
108
|
+
"#{environmentpath}/#{@environment}/#{path}"
|
109
|
+
end
|
110
|
+
modulepath = modulepath.join(":")
|
111
|
+
repo.temp_modulepath = modulepath
|
112
|
+
|
113
|
+
# Use an ERB template to write a spec test
|
114
|
+
template_dir = File.expand_path('../../templates',File.dirname(__FILE__))
|
115
|
+
spec_helper_template = File.read(File.expand_path('./spec_helper.rb.erb',template_dir))
|
116
|
+
File.write("#{location}/spec_helper.rb",ERB.new(spec_helper_template, nil, '-').result(binding))
|
117
|
+
end
|
118
|
+
|
119
|
+
def create_fixtures_symlinks(repo)
|
120
|
+
FileUtils.mkdir_p("#{repo.tempdir}/spec/fixtures/modules")
|
121
|
+
repo.temp_modulepath.split(':').each do |path|
|
122
|
+
Dir["#{path}/*"].each do |mod|
|
123
|
+
modulename = File.basename(mod)
|
124
|
+
FileUtils.ln_s(mod, "#{repo.tempdir}/spec/fixtures/modules/#{modulename}")
|
125
|
+
end
|
126
|
+
end
|
127
|
+
end
|
128
|
+
|
129
|
+
# TODO: Work out the best way to format the output
|
130
|
+
# TODO: Look into bundling bundler into the temp dir
|
131
|
+
# TODO: Write task for beaker tests *brace yourself* Dont forget about the beaker file you have
|
132
|
+
# TODO: Compare the outlout of the beaker helper that I wrote
|
133
|
+
# with the output from the templated tests, us ethe better one
|
134
|
+
# bearing in minf that beaker has logger options that could help
|
135
|
+
end
|
136
|
+
end
|
@@ -0,0 +1,24 @@
|
|
1
|
+
---
|
2
|
+
fixtures:
|
3
|
+
<% if symlinks.any? then -%>
|
4
|
+
symlinks:
|
5
|
+
<% symlinks.each do |link| -%>
|
6
|
+
<%= link['name'] %>: <%= link['dir'] %>
|
7
|
+
<% end -%>
|
8
|
+
<% end -%>
|
9
|
+
<% if repositories.any? then -%>
|
10
|
+
repositories:
|
11
|
+
<% repositories.each do |repo| -%>
|
12
|
+
<%= repo['name'] %>:
|
13
|
+
repo: <%= repo['repo'] %>
|
14
|
+
ref: <%= repo['ref'] %>
|
15
|
+
<% end -%>
|
16
|
+
<% end -%>
|
17
|
+
<% if forge_modules.any? then -%>
|
18
|
+
forge_modules:
|
19
|
+
<% forge_modules.each do |mod| -%>
|
20
|
+
<%= mod['name'] %>:
|
21
|
+
repo: <%= mod['repo'] %>
|
22
|
+
ref: <%= mod['ref'] %>
|
23
|
+
<% end -%>
|
24
|
+
<% end -%>
|
@@ -0,0 +1 @@
|
|
1
|
+
require 'puppetlabs_spec_helper/rake_tasks'
|
@@ -0,0 +1,18 @@
|
|
1
|
+
require 'spec_helper_acceptance'
|
2
|
+
|
3
|
+
<% test.nodes.each do |node| -%>
|
4
|
+
describe '<%= node.name %>' do
|
5
|
+
<% test.classes.each do |cls| %>
|
6
|
+
context 'when classified with <%= cls.name %>' do
|
7
|
+
role = '<%= cls.name %>'
|
8
|
+
apply_manifest(role, :catch_failures => true)
|
9
|
+
<% if test.options[:runs_for_idempotency] -%>
|
10
|
+
<% (test.options[:runs_for_idempotency] - 1).times do -%>
|
11
|
+
apply_manifest(role, :catch_failures => true)
|
12
|
+
<% end -%>
|
13
|
+
<% end -%>
|
14
|
+
apply_manifest(role, :catch_changes => true)
|
15
|
+
end
|
16
|
+
<% end %>
|
17
|
+
end
|
18
|
+
<% end %>
|
@@ -0,0 +1,24 @@
|
|
1
|
+
require 'beaker-rspec'
|
2
|
+
|
3
|
+
scp_to hosts, '<%= repo.tempdir %>/etc', '/etc' # Check that this wil work recursively
|
4
|
+
|
5
|
+
RSpec.configure do |c|
|
6
|
+
# Project root
|
7
|
+
proj_root = File.expand_path(File.join(File.dirname(__FILE__), '..'))
|
8
|
+
|
9
|
+
# Readable test descriptions
|
10
|
+
c.formatter = :documentation
|
11
|
+
|
12
|
+
# Configure all nodes in nodeset
|
13
|
+
#c.before :suite do
|
14
|
+
# # Install module
|
15
|
+
# puppet_module_install(:source => proj_root, :module_name => 'virtualbox')
|
16
|
+
# hosts.each do |host|
|
17
|
+
# on host, puppet('module','install','puppetlabs-stdlib'), { :acceptable_exit_codes => [0,1] }
|
18
|
+
# on host, puppet('module','install','puppetlabs-apt'), { :acceptable_exit_codes => [0,1] }
|
19
|
+
# on host, puppet('module','install','stahnma-epel'), { :acceptable_exit_codes => [0,1] }
|
20
|
+
# on host, puppet('module','install','camptocamp-archive'), { :acceptable_exit_codes => [0,1] }
|
21
|
+
# on host, puppet('module','install','darin-zypprepo'), { :acceptable_exit_codes => [0,1] }
|
22
|
+
# end
|
23
|
+
#end
|
24
|
+
end
|
@@ -0,0 +1,13 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
<% test.classes.each do |cls| -%>
|
4
|
+
describe "<%= cls.name %>" do
|
5
|
+
<% test.nodes.each do |node| -%>
|
6
|
+
context "using fact set <%= node.name %>" do
|
7
|
+
let(:facts) { <%= node.fact_set %> }
|
8
|
+
it { should compile }
|
9
|
+
end
|
10
|
+
<% end -%>
|
11
|
+
end
|
12
|
+
|
13
|
+
<% end -%>
|
metadata
ADDED
@@ -0,0 +1,162 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: controlrepo
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 1.0.0
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Dylan Ratcliffe
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
date: 2015-10-19 00:00:00.000000000 Z
|
12
|
+
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: rake
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - ">="
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: '0'
|
20
|
+
type: :runtime
|
21
|
+
prerelease: false
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
23
|
+
requirements:
|
24
|
+
- - ">="
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: '0'
|
27
|
+
- !ruby/object:Gem::Dependency
|
28
|
+
name: json
|
29
|
+
requirement: !ruby/object:Gem::Requirement
|
30
|
+
requirements:
|
31
|
+
- - ">="
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: '0'
|
34
|
+
type: :runtime
|
35
|
+
prerelease: false
|
36
|
+
version_requirements: !ruby/object:Gem::Requirement
|
37
|
+
requirements:
|
38
|
+
- - ">="
|
39
|
+
- !ruby/object:Gem::Version
|
40
|
+
version: '0'
|
41
|
+
- !ruby/object:Gem::Dependency
|
42
|
+
name: beaker-rspec
|
43
|
+
requirement: !ruby/object:Gem::Requirement
|
44
|
+
requirements:
|
45
|
+
- - ">="
|
46
|
+
- !ruby/object:Gem::Version
|
47
|
+
version: '0'
|
48
|
+
type: :runtime
|
49
|
+
prerelease: false
|
50
|
+
version_requirements: !ruby/object:Gem::Requirement
|
51
|
+
requirements:
|
52
|
+
- - ">="
|
53
|
+
- !ruby/object:Gem::Version
|
54
|
+
version: '0'
|
55
|
+
- !ruby/object:Gem::Dependency
|
56
|
+
name: rspec-puppet
|
57
|
+
requirement: !ruby/object:Gem::Requirement
|
58
|
+
requirements:
|
59
|
+
- - ">="
|
60
|
+
- !ruby/object:Gem::Version
|
61
|
+
version: '0'
|
62
|
+
type: :runtime
|
63
|
+
prerelease: false
|
64
|
+
version_requirements: !ruby/object:Gem::Requirement
|
65
|
+
requirements:
|
66
|
+
- - ">="
|
67
|
+
- !ruby/object:Gem::Version
|
68
|
+
version: '0'
|
69
|
+
- !ruby/object:Gem::Dependency
|
70
|
+
name: rspec
|
71
|
+
requirement: !ruby/object:Gem::Requirement
|
72
|
+
requirements:
|
73
|
+
- - ">="
|
74
|
+
- !ruby/object:Gem::Version
|
75
|
+
version: '0'
|
76
|
+
type: :runtime
|
77
|
+
prerelease: false
|
78
|
+
version_requirements: !ruby/object:Gem::Requirement
|
79
|
+
requirements:
|
80
|
+
- - ">="
|
81
|
+
- !ruby/object:Gem::Version
|
82
|
+
version: '0'
|
83
|
+
- !ruby/object:Gem::Dependency
|
84
|
+
name: bundler
|
85
|
+
requirement: !ruby/object:Gem::Requirement
|
86
|
+
requirements:
|
87
|
+
- - ">="
|
88
|
+
- !ruby/object:Gem::Version
|
89
|
+
version: '0'
|
90
|
+
type: :runtime
|
91
|
+
prerelease: false
|
92
|
+
version_requirements: !ruby/object:Gem::Requirement
|
93
|
+
requirements:
|
94
|
+
- - ">="
|
95
|
+
- !ruby/object:Gem::Version
|
96
|
+
version: '0'
|
97
|
+
- !ruby/object:Gem::Dependency
|
98
|
+
name: puppet
|
99
|
+
requirement: !ruby/object:Gem::Requirement
|
100
|
+
requirements:
|
101
|
+
- - ">="
|
102
|
+
- !ruby/object:Gem::Version
|
103
|
+
version: '0'
|
104
|
+
type: :runtime
|
105
|
+
prerelease: false
|
106
|
+
version_requirements: !ruby/object:Gem::Requirement
|
107
|
+
requirements:
|
108
|
+
- - ">="
|
109
|
+
- !ruby/object:Gem::Version
|
110
|
+
version: '0'
|
111
|
+
description: ''
|
112
|
+
email:
|
113
|
+
- dylan.ratcliffe@puppetlabs.com
|
114
|
+
executables: []
|
115
|
+
extensions: []
|
116
|
+
extra_rdoc_files: []
|
117
|
+
files:
|
118
|
+
- ".gitignore"
|
119
|
+
- README.md
|
120
|
+
- controlrepo.gemspec
|
121
|
+
- lib/controlrepo.rb
|
122
|
+
- lib/controlrepo/beaker.rb
|
123
|
+
- lib/controlrepo/class.rb
|
124
|
+
- lib/controlrepo/group.rb
|
125
|
+
- lib/controlrepo/node.rb
|
126
|
+
- lib/controlrepo/rake_tasks.rb
|
127
|
+
- lib/controlrepo/test.rb
|
128
|
+
- lib/controlrepo/testconfig.rb
|
129
|
+
- templates/.fixtures.yml.erb
|
130
|
+
- templates/Gemfile.erb
|
131
|
+
- templates/Rakefile.erb
|
132
|
+
- templates/acceptance_test_spec.rb.erb
|
133
|
+
- templates/nodeset.yaml.erb
|
134
|
+
- templates/spec_helper.rb.erb
|
135
|
+
- templates/spec_helper_acceptance.rb.erb
|
136
|
+
- templates/test_spec.rb.erb
|
137
|
+
homepage: ''
|
138
|
+
licenses:
|
139
|
+
- Apache-2.0
|
140
|
+
metadata: {}
|
141
|
+
post_install_message:
|
142
|
+
rdoc_options: []
|
143
|
+
require_paths:
|
144
|
+
- lib
|
145
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
146
|
+
requirements:
|
147
|
+
- - ">="
|
148
|
+
- !ruby/object:Gem::Version
|
149
|
+
version: '0'
|
150
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
151
|
+
requirements:
|
152
|
+
- - ">="
|
153
|
+
- !ruby/object:Gem::Version
|
154
|
+
version: '0'
|
155
|
+
requirements: []
|
156
|
+
rubyforge_project:
|
157
|
+
rubygems_version: 2.4.7
|
158
|
+
signing_key:
|
159
|
+
specification_version: 4
|
160
|
+
summary: ''
|
161
|
+
test_files: []
|
162
|
+
has_rdoc:
|