souschef 0.4.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/.gitignore +22 -0
- data/Gemfile +4 -0
- data/LICENSE.txt +22 -0
- data/README.md +177 -0
- data/Rakefile +1 -0
- data/bin/souschef +33 -0
- data/data/chefspec/chefspec.erb +6 -0
- data/data/chefspec/spec_helper.rb +8 -0
- data/data/gemfile.yml +23 -0
- data/data/license.erb +3 -0
- data/data/metadata.erb +7 -0
- data/data/rakefile.erb +39 -0
- data/data/readme.erb +47 -0
- data/data/recipe/recipe.erb +6 -0
- data/data/rubocop/rubocop.yml +19 -0
- data/data/serverspec/serverspec.erb +2 -0
- data/data/serverspec/serverspec_helper.rb +10 -0
- data/data/testkitchen/kitchen.default.erb +22 -0
- data/lib/souschef.rb +16 -0
- data/lib/souschef/berkshelf.rb +93 -0
- data/lib/souschef/config.rb +20 -0
- data/lib/souschef/configure/file.rb +46 -0
- data/lib/souschef/gemfile.rb +42 -0
- data/lib/souschef/print.rb +40 -0
- data/lib/souschef/runner.rb +104 -0
- data/lib/souschef/scaffold.rb +145 -0
- data/lib/souschef/template.rb +26 -0
- data/lib/souschef/template/base.rb +69 -0
- data/lib/souschef/template/chefspec.rb +26 -0
- data/lib/souschef/template/license.rb +25 -0
- data/lib/souschef/template/metadata.rb +30 -0
- data/lib/souschef/template/rakefile.rb +23 -0
- data/lib/souschef/template/readme.rb +24 -0
- data/lib/souschef/template/rubocop.rb +22 -0
- data/lib/souschef/template/serverspec.rb +27 -0
- data/lib/souschef/testkitchen.rb +135 -0
- data/lib/souschef/testkitchen/docker.rb +97 -0
- data/lib/souschef/testkitchen/solusvm.rb +101 -0
- data/lib/souschef/testkitchen/virtualbox.rb +66 -0
- data/lib/souschef/version.rb +4 -0
- data/souschef.gemspec +33 -0
- metadata +254 -0
@@ -0,0 +1,26 @@
|
|
1
|
+
require 'souschef/template/base'
|
2
|
+
require 'souschef/template/metadata'
|
3
|
+
require 'souschef/template/license'
|
4
|
+
require 'souschef/template/readme'
|
5
|
+
require 'souschef/template/rubocop'
|
6
|
+
require 'souschef/template/chefspec'
|
7
|
+
require 'souschef/template/serverspec'
|
8
|
+
require 'souschef/template/rakefile'
|
9
|
+
|
10
|
+
module Souschef
|
11
|
+
# Creates various files from predefined templates
|
12
|
+
class Template
|
13
|
+
# Public - Create needed standardised files
|
14
|
+
#
|
15
|
+
# Returns nil
|
16
|
+
def self.run(opts)
|
17
|
+
Souschef::Template::Rubocop.new(opts).create
|
18
|
+
Souschef::Template::Chefspec.new(opts).create
|
19
|
+
Souschef::Template::Serverspec.new(opts).create
|
20
|
+
Souschef::Template::Metadata.new(opts).create
|
21
|
+
Souschef::Template::License.new(opts).create
|
22
|
+
Souschef::Template::Readme.new(opts).create
|
23
|
+
Souschef::Template::Rakefile.new(opts).create
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
@@ -0,0 +1,69 @@
|
|
1
|
+
module Souschef
|
2
|
+
class Template
|
3
|
+
# Base class containing reusable functions
|
4
|
+
class Base
|
5
|
+
attr_accessor :path, :ots
|
6
|
+
|
7
|
+
def initialize(opts)
|
8
|
+
@opts = opts
|
9
|
+
@path = opts[:path]
|
10
|
+
end
|
11
|
+
|
12
|
+
private
|
13
|
+
|
14
|
+
# Private - Return location of a custom template file if it exists, or
|
15
|
+
# return the default version
|
16
|
+
#
|
17
|
+
# Return String
|
18
|
+
def datafile_path(file)
|
19
|
+
local_profile = "~/.souschef/#{@opts[:profile]}/#{file}"
|
20
|
+
profile = File.expand_path(local_profile, __FILE__)
|
21
|
+
|
22
|
+
if File.exist?(profile)
|
23
|
+
profile
|
24
|
+
else
|
25
|
+
p = "../../../../data/#{file}"
|
26
|
+
File.expand_path(p, __FILE__)
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
# Private - Print out message if verbose option is selected
|
31
|
+
#
|
32
|
+
# Return nil
|
33
|
+
def info(msg)
|
34
|
+
Souschef::Print.info(msg) if @opts[:verbose]
|
35
|
+
end
|
36
|
+
|
37
|
+
# Private - Return path to the file inside cookbook directory
|
38
|
+
#
|
39
|
+
# Return String
|
40
|
+
def cookbook_file_path(file)
|
41
|
+
File.join(@path, file)
|
42
|
+
end
|
43
|
+
|
44
|
+
# Private - Write data to the desired file
|
45
|
+
#
|
46
|
+
# Returns nil
|
47
|
+
def write_file(file, data)
|
48
|
+
File.open(file, 'w') { |fd| fd.write(data) }
|
49
|
+
end
|
50
|
+
|
51
|
+
# Private - Load ERB template
|
52
|
+
#
|
53
|
+
# file - String file name
|
54
|
+
#
|
55
|
+
# Returns String
|
56
|
+
def load_erb_file(file)
|
57
|
+
File.read(datafile_path(file))
|
58
|
+
end
|
59
|
+
|
60
|
+
# Private - Creates spec/ directory if missing
|
61
|
+
#
|
62
|
+
# Return nil
|
63
|
+
def create_spec_dir(spec_dir)
|
64
|
+
info "Create #{spec_dir} directory"
|
65
|
+
Dir.mkdir(spec_dir)
|
66
|
+
end
|
67
|
+
end
|
68
|
+
end
|
69
|
+
end
|
@@ -0,0 +1,26 @@
|
|
1
|
+
module Souschef
|
2
|
+
class Template
|
3
|
+
# Create spechelper for Chefspec
|
4
|
+
class Chefspec < Souschef::Template::Base
|
5
|
+
def initialize(opts)
|
6
|
+
super(opts)
|
7
|
+
end
|
8
|
+
# Public - Create spec/spec_helper.rb file
|
9
|
+
#
|
10
|
+
# cookbook - String Cookbook name
|
11
|
+
#
|
12
|
+
# Returns nil
|
13
|
+
def create
|
14
|
+
spec_dir = File.join(@path, 'spec')
|
15
|
+
|
16
|
+
tmpl = ERB.new(load_erb_file('chefspec/spec_helper.rb'))
|
17
|
+
data = tmpl.result(binding)
|
18
|
+
|
19
|
+
create_spec_dir(spec_dir) unless File.directory?(spec_dir)
|
20
|
+
|
21
|
+
info 'Creating Chefspec helper'
|
22
|
+
write_file(cookbook_file_path('spec/spec_helper.rb'), data)
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
@@ -0,0 +1,25 @@
|
|
1
|
+
module Souschef
|
2
|
+
class Template
|
3
|
+
# Create standard LICENSE
|
4
|
+
class License < Souschef::Template::Base
|
5
|
+
def initialize(opts)
|
6
|
+
super(opts)
|
7
|
+
end
|
8
|
+
|
9
|
+
# Public - Create a valid License file
|
10
|
+
#
|
11
|
+
# cookbook - String Cookbook name
|
12
|
+
#
|
13
|
+
# Returns nil
|
14
|
+
def create
|
15
|
+
tmpl = ERB.new(load_erb_file('license.erb'))
|
16
|
+
@year = Time.now.year
|
17
|
+
@maintainer = @opts[:souschef][:maintainer]
|
18
|
+
data = tmpl.result(binding)
|
19
|
+
|
20
|
+
info 'Updating LICENSE file'
|
21
|
+
write_file(cookbook_file_path('LICENSE'), data)
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
@@ -0,0 +1,30 @@
|
|
1
|
+
# Souschef
|
2
|
+
module Souschef
|
3
|
+
class Template
|
4
|
+
# Creates a well defined maetadata.rb
|
5
|
+
class Metadata < Souschef::Template::Base
|
6
|
+
attr_accessor :cookbook
|
7
|
+
|
8
|
+
def initialize(opts)
|
9
|
+
super(opts)
|
10
|
+
end
|
11
|
+
|
12
|
+
# Public - Create file start
|
13
|
+
#
|
14
|
+
# cookbook - String cookbook name
|
15
|
+
#
|
16
|
+
# Returns nil
|
17
|
+
def create
|
18
|
+
tmpl = ERB.new(load_erb_file('metadata.erb'))
|
19
|
+
@cookbook = @opts[:cookbook]
|
20
|
+
@maintainer = @opts[:souschef][:maintainer]
|
21
|
+
@maintainer_email = @opts[:souschef][:maintainer_email]
|
22
|
+
@license = @opts[:souschef][:license]
|
23
|
+
data = tmpl.result(binding)
|
24
|
+
|
25
|
+
info 'Updating metadata.rb'
|
26
|
+
write_file(cookbook_file_path('metadata.rb'), data)
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
@@ -0,0 +1,23 @@
|
|
1
|
+
module Souschef
|
2
|
+
class Template
|
3
|
+
# Add Rakefile for testing support
|
4
|
+
class Rakefile < Souschef::Template::Base
|
5
|
+
def initialize(opts)
|
6
|
+
super(opts)
|
7
|
+
end
|
8
|
+
|
9
|
+
# Public - Create a Rakefile from our Template
|
10
|
+
#
|
11
|
+
# cookbook - String Cookbook name
|
12
|
+
#
|
13
|
+
# Returns nil
|
14
|
+
def create
|
15
|
+
tmpl = ERB.new(load_erb_file('rakefile.erb'))
|
16
|
+
data = tmpl.result(binding)
|
17
|
+
|
18
|
+
info 'Setting up Rakefile'
|
19
|
+
write_file(cookbook_file_path('Rakefile'), data)
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
@@ -0,0 +1,24 @@
|
|
1
|
+
module Souschef
|
2
|
+
class Template
|
3
|
+
# Updates README.md inside cookbook folder
|
4
|
+
class Readme < Souschef::Template::Base
|
5
|
+
def initialize(opts)
|
6
|
+
super(opts)
|
7
|
+
end
|
8
|
+
|
9
|
+
# Public - Create standardised README
|
10
|
+
#
|
11
|
+
# Return nil
|
12
|
+
def create
|
13
|
+
tmpl = ERB.new(load_erb_file('readme.erb'))
|
14
|
+
@cookbook = @opts[:cookbook]
|
15
|
+
@maintainer = @opts[:souschef][:maintainer]
|
16
|
+
@maintainer_email = @opts[:souschef][:maintainer_email]
|
17
|
+
data = tmpl.result(binding)
|
18
|
+
|
19
|
+
info 'Updating README file'
|
20
|
+
write_file(cookbook_file_path('README.md'), data)
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
@@ -0,0 +1,22 @@
|
|
1
|
+
module Souschef
|
2
|
+
class Template
|
3
|
+
# Configure Rubocop configuratiopn
|
4
|
+
class Rubocop < Souschef::Template::Base
|
5
|
+
def initialize(opts)
|
6
|
+
super(opts)
|
7
|
+
end
|
8
|
+
# Public - Create a .rubocop file
|
9
|
+
#
|
10
|
+
# cookbook - String Cookbook name
|
11
|
+
#
|
12
|
+
# Returns nil
|
13
|
+
def create
|
14
|
+
tmpl = ERB.new(load_erb_file('rubocop/rubocop.yml'))
|
15
|
+
data = tmpl.result(binding)
|
16
|
+
|
17
|
+
info 'Setting up Rubocop configuration'
|
18
|
+
write_file(cookbook_file_path('.rubocop.yml'), data)
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
@@ -0,0 +1,27 @@
|
|
1
|
+
module Souschef
|
2
|
+
class Template
|
3
|
+
# Serverspec configurator
|
4
|
+
class Serverspec < Souschef::Template::Base
|
5
|
+
def initialize(opts)
|
6
|
+
super(opts)
|
7
|
+
end
|
8
|
+
# Public - Create serverspec helper
|
9
|
+
#
|
10
|
+
# cookbook - String Cookbook name
|
11
|
+
#
|
12
|
+
# Returns nil
|
13
|
+
def create
|
14
|
+
spec_dir = File.join(@path, 'test', 'integration', 'default',
|
15
|
+
'serverspec')
|
16
|
+
spec_helper = File.join(spec_dir, 'spec_helper.rb')
|
17
|
+
|
18
|
+
tmpl = ERB.new(load_erb_file('serverspec/serverspec_helper.rb'))
|
19
|
+
data = tmpl.result(binding)
|
20
|
+
|
21
|
+
create_spec_dir(spec_dir) unless File.directory?(spec_dir)
|
22
|
+
info 'Creating Serverspec helper'
|
23
|
+
write_file(spec_helper, data)
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
@@ -0,0 +1,135 @@
|
|
1
|
+
require 'souschef/testkitchen/docker'
|
2
|
+
require 'souschef/testkitchen/solusvm'
|
3
|
+
require 'souschef/testkitchen/virtualbox'
|
4
|
+
|
5
|
+
module Souschef
|
6
|
+
# TestKitchen generator
|
7
|
+
class Testkitchen
|
8
|
+
attr_accessor :files, :cookbook, :opts, :metadata
|
9
|
+
|
10
|
+
def initialize(opts)
|
11
|
+
@opts = opts
|
12
|
+
@cookbook = opts[:cookbook]
|
13
|
+
@file = kitchen_driver_file
|
14
|
+
metadata_info
|
15
|
+
end
|
16
|
+
|
17
|
+
# Public - Write down TestKitchen configuration
|
18
|
+
#
|
19
|
+
# Returns nil
|
20
|
+
def configure
|
21
|
+
if @opts[:docker]
|
22
|
+
Souschef::Print.info 'Creating Docker configuration .kitchen.local.yml'
|
23
|
+
write(:docker, Souschef::Testkitchen::Docker.new(@cookbook).yaml)
|
24
|
+
end
|
25
|
+
if @opts[:solusvm]
|
26
|
+
Souschef::Print.info 'Creating SolusVM configuraton .kitchen.local.yml'
|
27
|
+
write(:solusvm, Souschef::Testkitchen::Solusvm.new(@cookbook).yaml)
|
28
|
+
end
|
29
|
+
|
30
|
+
Souschef::Print.info 'Creating Vagrant configuration in .kitchen.yml'
|
31
|
+
write(:virtualbox, Souschef::Testkitchen::Virtualbox.new(@cookbook).yaml)
|
32
|
+
end
|
33
|
+
|
34
|
+
# Public - Copy the already generated files from the data/ directory
|
35
|
+
#
|
36
|
+
# Returns nil
|
37
|
+
def setup
|
38
|
+
templates = ['default']
|
39
|
+
templates << @opts[:testkitchen] if @opts[:testkitchen]
|
40
|
+
|
41
|
+
templates.each { |type| create_file(type) }
|
42
|
+
end
|
43
|
+
|
44
|
+
private
|
45
|
+
|
46
|
+
# Private - Read metadata file
|
47
|
+
#
|
48
|
+
# Return Hash
|
49
|
+
def metadata_info
|
50
|
+
@metadata = Chef::Cookbook::Metadata.new
|
51
|
+
@metadata.from_file(File.join(@opts[:path], 'metadata.rb'))
|
52
|
+
end
|
53
|
+
|
54
|
+
# Private - Creates the TestKitchen YML file based on the provided template
|
55
|
+
#
|
56
|
+
# Returns nil
|
57
|
+
def create_file(type)
|
58
|
+
cb_file, source_file = get_locations(type)
|
59
|
+
|
60
|
+
File.open(cb_file, 'w') { |f| f.write(process_template(source_file)) }
|
61
|
+
|
62
|
+
if @opts[:verbose]
|
63
|
+
Souschef::Print.info "Creating Testkitchen #{type} configuration"
|
64
|
+
end
|
65
|
+
rescue TypeError
|
66
|
+
Souschef::Print.error 'SKipping'
|
67
|
+
end
|
68
|
+
|
69
|
+
# Private - Return location of cookbook file and source template file
|
70
|
+
#
|
71
|
+
# Return Array
|
72
|
+
def get_locations(type)
|
73
|
+
case type
|
74
|
+
when 'default'
|
75
|
+
cb_file = File.join(@opts[:path], '.kitchen.yml')
|
76
|
+
source_file = template_location(type)
|
77
|
+
else
|
78
|
+
cb_file = File.join(@opts[:path], '.kitchen.local.yml')
|
79
|
+
source_file = template_location(type)
|
80
|
+
end
|
81
|
+
|
82
|
+
[cb_file, source_file]
|
83
|
+
end
|
84
|
+
|
85
|
+
# Private - Generate the .kitchen.yml file based on our cookbook
|
86
|
+
#
|
87
|
+
# Returns String
|
88
|
+
def process_template(source_file)
|
89
|
+
rfile = ERB.new(File.read(source_file))
|
90
|
+
@cookbook = @metadata.name
|
91
|
+
|
92
|
+
rfile.result(binding)
|
93
|
+
end
|
94
|
+
|
95
|
+
# Private - Return location of the preconfigured .kitchen*.yml files
|
96
|
+
#
|
97
|
+
# Returns String
|
98
|
+
def template_location(type)
|
99
|
+
local = File.expand_path(
|
100
|
+
"~/.souschef/#{@opts[:profile]}/testkitchen/kitchen.#{type}.erb",
|
101
|
+
__FILE__)
|
102
|
+
|
103
|
+
bundled = File.expand_path(
|
104
|
+
"../../../data/testkitchen/kitchen.#{type}.erb", __FILE__)
|
105
|
+
|
106
|
+
if !File.exist?(local) && !File.exist?(bundled)
|
107
|
+
if @opts[:verbose]
|
108
|
+
Souschef::Print.error "Missing custom configuration for TestKitchen \
|
109
|
+
#{@opts[:testkitchen]} configuration"
|
110
|
+
end
|
111
|
+
else
|
112
|
+
File.exist?(local) ? local : bundled
|
113
|
+
end
|
114
|
+
end
|
115
|
+
|
116
|
+
# Private - Return full locations for files
|
117
|
+
#
|
118
|
+
# Returns Hash
|
119
|
+
def kitchen_driver_file
|
120
|
+
{ virtualbox: File.join(@opts[:path], '.kitchen.yml'),
|
121
|
+
docker: File.join(@opts[:path], '.kitchen.local.yml'),
|
122
|
+
solusvm: File.join(@opts[:path], '.kitchen.local.yml')
|
123
|
+
}
|
124
|
+
end
|
125
|
+
|
126
|
+
# Private - Write down the configuration file
|
127
|
+
#
|
128
|
+
# Returns nile
|
129
|
+
def write(driver, data)
|
130
|
+
fd = File.open(kitchen_driver_file[driver], 'w')
|
131
|
+
fd.write(data)
|
132
|
+
fd.close unless fd.nil?
|
133
|
+
end
|
134
|
+
end
|
135
|
+
end
|
@@ -0,0 +1,97 @@
|
|
1
|
+
module Souschef
|
2
|
+
class Testkitchen
|
3
|
+
# Testkitchen Docker configuration
|
4
|
+
class Docker
|
5
|
+
attr_accessor :config, :cookbook
|
6
|
+
|
7
|
+
def initialize(cookbook)
|
8
|
+
@cookbook = cookbook
|
9
|
+
populate_configuration
|
10
|
+
end
|
11
|
+
|
12
|
+
# Public - Return YAML formatted data
|
13
|
+
#
|
14
|
+
# Returns String
|
15
|
+
def yaml
|
16
|
+
@config.to_yaml
|
17
|
+
end
|
18
|
+
|
19
|
+
private
|
20
|
+
|
21
|
+
# Private - Populate @config
|
22
|
+
#
|
23
|
+
# Returns nil
|
24
|
+
def populate_configuration
|
25
|
+
@config = { 'driver' => define_driver,
|
26
|
+
'provisioner' => define_provisioner,
|
27
|
+
'platforms' => define_platforms,
|
28
|
+
'suits' => define_suits }
|
29
|
+
end
|
30
|
+
|
31
|
+
# Private - Define driver section
|
32
|
+
#
|
33
|
+
# Returns Hash
|
34
|
+
def define_driver
|
35
|
+
{ 'name' => 'docker',
|
36
|
+
'privileged' => true
|
37
|
+
}
|
38
|
+
end
|
39
|
+
|
40
|
+
# Private - Define provisioner
|
41
|
+
#
|
42
|
+
# Returns Hash
|
43
|
+
def define_provisioner
|
44
|
+
{ 'name' => 'chef_zero',
|
45
|
+
'require_chef_omnibus' => 'latest' }
|
46
|
+
end
|
47
|
+
|
48
|
+
# Private - Define platforms configuration
|
49
|
+
#
|
50
|
+
# Returns Array
|
51
|
+
def define_platforms
|
52
|
+
if define_run_list['run_list'].empty?
|
53
|
+
[define_centos_5, define_centos_6]
|
54
|
+
else
|
55
|
+
[define_centos_5, define_centos_6, define_run_list]
|
56
|
+
end
|
57
|
+
end
|
58
|
+
|
59
|
+
# Private - Define CentOS 5.10 platforms
|
60
|
+
#
|
61
|
+
# Returns Hash
|
62
|
+
def define_centos_5
|
63
|
+
{ 'name' => 'centos-5.10',
|
64
|
+
'driver_config' => { 'image' => 'akrasic/centos5',
|
65
|
+
'platform' => 'centos',
|
66
|
+
'use_sudo' => false,
|
67
|
+
'privileged' => true } }
|
68
|
+
end
|
69
|
+
|
70
|
+
# Private - Define CentOS 6.4 platform
|
71
|
+
#
|
72
|
+
# Returns Hash
|
73
|
+
def define_centos_6
|
74
|
+
{ 'name' => 'centos-6.4',
|
75
|
+
'driver_config' => { 'image' => 'centos:6.4',
|
76
|
+
'platform' => 'centos',
|
77
|
+
'use_sudo' => false,
|
78
|
+
'privileged' => true } }
|
79
|
+
end
|
80
|
+
|
81
|
+
# Private - Define Runlist for platforms
|
82
|
+
#
|
83
|
+
# Returs Hash
|
84
|
+
def define_run_list
|
85
|
+
{ 'run_list' => '' }
|
86
|
+
end
|
87
|
+
|
88
|
+
# Private - Define suits
|
89
|
+
#
|
90
|
+
# Returns Hash
|
91
|
+
def define_suits
|
92
|
+
[{ 'name' => 'default',
|
93
|
+
'run_list' => ["recipe[#{@cookbook}::default]"] }]
|
94
|
+
end
|
95
|
+
end
|
96
|
+
end
|
97
|
+
end
|