cupper 0.0.1 → 0.1.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.gitignore +9 -0
- data/.rspec +2 -0
- data/.travis.yml +16 -0
- data/Gemfile +18 -0
- data/README.md +30 -0
- data/Rakefile +6 -0
- data/bin/cupper +1 -1
- data/cupper.gemspec +28 -0
- data/lib/cupper.rb +18 -1
- data/lib/cupper/cli.rb +63 -0
- data/lib/cupper/collect.rb +51 -0
- data/lib/cupper/cookbook.rb +71 -0
- data/lib/cupper/cookbook_file.rb +10 -0
- data/lib/cupper/cupperfile.rb +22 -0
- data/lib/cupper/entity.rb +63 -0
- data/lib/cupper/environment.rb +177 -0
- data/lib/cupper/errors.rb +84 -0
- data/lib/cupper/ohai_plugins.rb +13 -0
- data/lib/cupper/platform_collector.rb +40 -0
- data/lib/cupper/plugins/cupper/arch.rb +43 -0
- data/lib/cupper/plugins/cupper/debian.rb +48 -0
- data/lib/cupper/plugins/ohai/dpci.rb +30 -0
- data/lib/cupper/plugins/ohai/files.rb +68 -0
- data/lib/cupper/plugins/ohai/init_system.rb +14 -0
- data/lib/cupper/plugins/ohai/pacman.rb +31 -0
- data/lib/cupper/plugins/ohai/pkg_deps.rb +30 -0
- data/lib/cupper/plugins/ohai/pkg_manager.rb +31 -0
- data/lib/cupper/plugins/ohai/services.rb +20 -0
- data/lib/cupper/project.rb +40 -0
- data/lib/cupper/recipe.rb +240 -0
- data/lib/cupper/templates/CupperFile.erb +1 -0
- data/lib/cupper/templates/_cookbook_file.erb +9 -0
- data/lib/cupper/templates/_groups.erb +10 -0
- data/lib/cupper/templates/_links.erb +10 -0
- data/lib/cupper/templates/_package.erb +19 -0
- data/lib/cupper/templates/_services.erb +7 -0
- data/lib/cupper/templates/_templates.erb +11 -0
- data/lib/cupper/templates/_users.erb +10 -0
- data/lib/cupper/templates/cookbook_file.erb +1 -0
- data/lib/cupper/templates/recipe.erb +7 -0
- data/lib/cupper/version.rb +3 -0
- data/templates/locales/en.yml +17 -0
- metadata +125 -8
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 4cb1f5ee3842ee97e25770577a390f8547a47e3a
|
4
|
+
data.tar.gz: c2e64363e16d0d940d9a542fec515b1524d93b1c
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: c4216eeb5b6377d1e1240b15dde4b585fc347a1e34d1188529b0e7ffc0a8337626e80f24dc1cb35153e11080f4b1e4ac267590660591744343a9103499581fda
|
7
|
+
data.tar.gz: 394040efd699a88b89d51ff7361abc483f93b9b034fb90929d79c033201bdbac469425819c6c15a75274677285b4d5673d25ea404b09f4863e555d1e290bcb84
|
data/.gitignore
ADDED
data/.rspec
ADDED
data/.travis.yml
ADDED
data/Gemfile
ADDED
@@ -0,0 +1,18 @@
|
|
1
|
+
source 'https://rubygems.org'
|
2
|
+
|
3
|
+
# Specify your gem's dependencies in cupper.gemspec
|
4
|
+
gemspec
|
5
|
+
|
6
|
+
gem 'ohai'
|
7
|
+
gem 'thor'
|
8
|
+
gem 'i18n'
|
9
|
+
gem 'colorize'
|
10
|
+
gem 'coveralls', require: false
|
11
|
+
|
12
|
+
group :development do
|
13
|
+
gem 'rubocop'
|
14
|
+
end
|
15
|
+
|
16
|
+
group :test do
|
17
|
+
gem 'rspec'
|
18
|
+
end
|
data/README.md
ADDED
@@ -0,0 +1,30 @@
|
|
1
|
+
# Cupper
|
2
|
+
|
3
|
+
[![Join the chat at https://gitter.im/cupper-reverse-recipe/cupper](https://badges.gitter.im/cupper-reverse-recipe/cupper.svg)](https://gitter.im/cupper-reverse-recipe/cupper?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge)
|
4
|
+
[![Coverage Status](https://coveralls.io/repos/github/cupper-reverse-recipe/cupper/badge.svg?branch=master)](https://coveralls.io/github/cupper-reverse-recipe/cupper?branch=master)
|
5
|
+
|
6
|
+
## Installation
|
7
|
+
|
8
|
+
Add this line to your application's Gemfile:
|
9
|
+
|
10
|
+
```ruby
|
11
|
+
gem 'cupper'
|
12
|
+
```
|
13
|
+
|
14
|
+
And then execute:
|
15
|
+
|
16
|
+
$ bundle
|
17
|
+
|
18
|
+
Or install it yourself as:
|
19
|
+
|
20
|
+
$ gem install cupper
|
21
|
+
|
22
|
+
## Usage
|
23
|
+
|
24
|
+
|
25
|
+
## Development
|
26
|
+
|
27
|
+
|
28
|
+
## Contributing
|
29
|
+
|
30
|
+
|
data/Rakefile
ADDED
data/bin/cupper
CHANGED
data/cupper.gemspec
ADDED
@@ -0,0 +1,28 @@
|
|
1
|
+
# coding: utf-8
|
2
|
+
lib = File.expand_path('../lib', __FILE__)
|
3
|
+
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
4
|
+
require 'cupper/version'
|
5
|
+
|
6
|
+
Gem::Specification.new do |spec|
|
7
|
+
spec.name = 'cupper'
|
8
|
+
spec.version = Cupper::VERSION
|
9
|
+
spec.authors = ['Paulo Tada', 'Lucas Severo']
|
10
|
+
spec.email = ['paulohtfs@gmail.com', 'lucassalves65@gmail.com']
|
11
|
+
|
12
|
+
spec.summary = 'Reverse recipe'
|
13
|
+
spec.description = 'Taste your system and create a recipe'
|
14
|
+
spec.homepage = 'https://github.com/cupper-reverse-recipe/cupper'
|
15
|
+
|
16
|
+
spec.files = `git ls-files -z`.split("\x0").reject { |f| f.match(%r{^(test|spec|features)/}) }
|
17
|
+
spec.bindir = 'bin'
|
18
|
+
spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
|
19
|
+
spec.test_files = spec.files.grep(/^(test|spec|featires)/)
|
20
|
+
spec.require_paths = ['lib']
|
21
|
+
|
22
|
+
spec.add_development_dependency 'bundler', '~> 1.12'
|
23
|
+
spec.add_development_dependency 'rake', '~> 10.0'
|
24
|
+
spec.add_development_dependency 'rspec', '~> 3.0'
|
25
|
+
|
26
|
+
spec.add_runtime_dependency 'thor', '~> 0.19.1'
|
27
|
+
spec.add_runtime_dependency 'ohai', '~> 8.15', '>= 8.15.1'
|
28
|
+
end
|
data/lib/cupper.rb
CHANGED
@@ -1,3 +1,20 @@
|
|
1
|
+
require 'cupper/version'
|
2
|
+
require 'cupper/project'
|
3
|
+
require 'cupper/cli'
|
4
|
+
require 'cupper/ohai_plugins'
|
5
|
+
require 'cupper/collect'
|
6
|
+
require 'cupper/cookbook'
|
7
|
+
require 'cupper/entity'
|
1
8
|
|
2
|
-
|
9
|
+
|
10
|
+
module Cupper
|
11
|
+
CUPPER_ROOT = File.expand_path(File.dirname(__FILE__))
|
12
|
+
OHAI_PLUGINS_PATH = CUPPER_ROOT + '/cupper/plugins/ohai'
|
13
|
+
CUPPER_PLUGINS_PATH = CUPPER_ROOT + '/cupper/plugins/cupper'
|
14
|
+
TEMPLATE_PATH = CUPPER_ROOT + '/cupper/templates'
|
15
|
+
|
16
|
+
# REVIEW: maybe there is a better way and place to load all plugins
|
17
|
+
# Loading all cupper plugins
|
18
|
+
Dir["#{CUPPER_PLUGINS_PATH}/*.rb"].each { |file| require file }
|
3
19
|
end
|
20
|
+
|
data/lib/cupper/cli.rb
ADDED
@@ -0,0 +1,63 @@
|
|
1
|
+
# This module defines all the class responsable for the command line tool
|
2
|
+
# It should call all the others module and classes to provides for the user
|
3
|
+
# all the features avaible
|
4
|
+
#
|
5
|
+
|
6
|
+
require 'thor'
|
7
|
+
require 'cupper/project'
|
8
|
+
require 'cupper/cookbook'
|
9
|
+
require 'cupper/ohai_plugins'
|
10
|
+
|
11
|
+
module Cupper
|
12
|
+
class Cli < Thor
|
13
|
+
desc 'create [PROJECT_NAME]', 'Create the project structure'
|
14
|
+
def create(project_name)
|
15
|
+
project = Project.new(project_name)
|
16
|
+
project.create
|
17
|
+
end
|
18
|
+
|
19
|
+
desc 'ohai', 'List Ohai plugins'
|
20
|
+
def ohai_plugins
|
21
|
+
ohai_plugins = OhaiPlugin.new
|
22
|
+
plugins = ohai_plugins.list
|
23
|
+
puts "Ohai Plugins"
|
24
|
+
puts "------------"
|
25
|
+
plugins.each do |plugin|
|
26
|
+
puts plugin
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
desc 'generate', 'Extract configuration and create a cookbook'
|
31
|
+
method_option :verbose, :aliases => '-v', :desc => 'Enable output log'
|
32
|
+
def generate
|
33
|
+
puts "Generating the Cookbook"
|
34
|
+
cookbook = Cookbook.new
|
35
|
+
if options.verbose?
|
36
|
+
puts "Verbose mode enabled"
|
37
|
+
cookbook.generate
|
38
|
+
else
|
39
|
+
Cupper.suppress_output{ cookbook.generate }
|
40
|
+
end
|
41
|
+
end
|
42
|
+
end
|
43
|
+
|
44
|
+
# When necessary, use this method to supress outputs
|
45
|
+
# don't suppress Exeptions
|
46
|
+
def self.suppress_output
|
47
|
+
begin
|
48
|
+
origin_stderr = $stderr.clone
|
49
|
+
origin_stdout = $stdout.clone
|
50
|
+
$stderr.reopen(File.new('/dev/null', 'w'))
|
51
|
+
$stdout.reopen(File.new('/dev/null', 'w'))
|
52
|
+
retval = yield
|
53
|
+
rescue Exception => e
|
54
|
+
$stderr.reopen(origin_stderr)
|
55
|
+
$stdout.reopen(origin_stdout)
|
56
|
+
raise e
|
57
|
+
ensure
|
58
|
+
$stderr.reopen(origin_stderr)
|
59
|
+
$stdout.reopen(origin_stdout)
|
60
|
+
end
|
61
|
+
retval
|
62
|
+
end
|
63
|
+
end
|
@@ -0,0 +1,51 @@
|
|
1
|
+
require 'ohai'
|
2
|
+
require 'cupper/ohai_plugins'
|
3
|
+
|
4
|
+
module Cupper
|
5
|
+
class Collect
|
6
|
+
ADDITIONAL_OHAI_PLUGINS = [
|
7
|
+
'packages',
|
8
|
+
'platform_family',
|
9
|
+
'etc'
|
10
|
+
]
|
11
|
+
|
12
|
+
def initialize
|
13
|
+
@data_extraction = Hash.new('No data!')
|
14
|
+
@ohai = Ohai::System.new
|
15
|
+
@ohai_plugin = OhaiPlugin.new
|
16
|
+
|
17
|
+
# TODO: Ohai::Config[:plugin_path] is decrepted
|
18
|
+
@plugins_path = Cupper::OHAI_PLUGINS_PATH
|
19
|
+
Ohai::Config[:plugin_path] << @plugins_path
|
20
|
+
end
|
21
|
+
|
22
|
+
def extract(attribute)
|
23
|
+
begin
|
24
|
+
object = 'Cupper::'.concat self.platform.capitalize
|
25
|
+
platform = Object.const_get(object).new
|
26
|
+
extract = platform.method attribute
|
27
|
+
extract.call @data_extraction
|
28
|
+
rescue NameError
|
29
|
+
puts 'Not supported platform' # TODO: treat this better
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
33
|
+
def setup
|
34
|
+
plugins = @ohai_plugin.list
|
35
|
+
plugins.concat ADDITIONAL_OHAI_PLUGINS
|
36
|
+
plugins.each do |plugin|
|
37
|
+
extract = @ohai.all_plugins(plugin)
|
38
|
+
@data_extraction.update({ plugin => extract.first.data }) # Assuming that the first is the default plugin extractor
|
39
|
+
end
|
40
|
+
true
|
41
|
+
end
|
42
|
+
|
43
|
+
def platform
|
44
|
+
@data_extraction['platform_family']['platform_family']
|
45
|
+
end
|
46
|
+
|
47
|
+
def data
|
48
|
+
@data_extraction
|
49
|
+
end
|
50
|
+
end
|
51
|
+
end
|
@@ -0,0 +1,71 @@
|
|
1
|
+
require 'cupper/collect'
|
2
|
+
require 'cupper/recipe'
|
3
|
+
require 'cupper/cookbook_file'
|
4
|
+
|
5
|
+
module Cupper
|
6
|
+
class Cookbook
|
7
|
+
# TODO: Read config file to tell the project path and configs
|
8
|
+
def initialize(cookbookname='default')
|
9
|
+
@cookbook_path = "#{Dir.getwd}/#{cookbookname}"
|
10
|
+
@cookbook_files_path = "#{@cookbook_path}/files"
|
11
|
+
@cookbook_recipes_path = "#{@cookbook_path}/recipes"
|
12
|
+
@recipe_deps = [ # TODO this is hard code to reflect all_recipes. Refactor this later
|
13
|
+
"#{cookbookname}::cookbook_file",
|
14
|
+
"#{cookbookname}::links",
|
15
|
+
"#{cookbookname}::groups",
|
16
|
+
"#{cookbookname}::services",
|
17
|
+
"#{cookbookname}::users",
|
18
|
+
"#{cookbookname}::packages",
|
19
|
+
]
|
20
|
+
setup_paths
|
21
|
+
end
|
22
|
+
|
23
|
+
def setup_paths
|
24
|
+
Dir.mkdir(@cookbook_path) unless Dir.exists?(@cookbook_path)
|
25
|
+
Dir.mkdir(@cookbook_files_path) unless Dir.exists?(@cookbook_files_path)
|
26
|
+
Dir.mkdir(@cookbook_recipes_path) unless Dir.exists?(@cookbook_recipes_path)
|
27
|
+
end
|
28
|
+
|
29
|
+
def generate
|
30
|
+
collector = Collect.new
|
31
|
+
collector.setup
|
32
|
+
all_recipes(collector)
|
33
|
+
all_cookbook_files(collector)
|
34
|
+
end
|
35
|
+
|
36
|
+
def all_recipes(collector)
|
37
|
+
Recipe.new(@cookbook_recipes_path, collector, 'recipe', 'default', @recipe_deps).create
|
38
|
+
Recipe.new(@cookbook_recipes_path, collector, '_cookbook_file', 'cookbook_files').create
|
39
|
+
Recipe.new(@cookbook_recipes_path, collector, '_links', 'links').create
|
40
|
+
Recipe.new(@cookbook_recipes_path, collector, '_groups', 'groups').create
|
41
|
+
Recipe.new(@cookbook_recipes_path, collector, '_services', 'services').create
|
42
|
+
Recipe.new(@cookbook_recipes_path, collector, '_users', 'users').create
|
43
|
+
Recipe.new(@cookbook_recipes_path, collector, '_package', 'packages').create
|
44
|
+
end
|
45
|
+
|
46
|
+
def all_cookbook_files(collector)
|
47
|
+
expand_cookbook_files(collector.extract 'files')
|
48
|
+
end
|
49
|
+
|
50
|
+
def text_type?(file)
|
51
|
+
file[1]['type'].match('text') or file[1]['type'].match('ASCII')
|
52
|
+
end
|
53
|
+
|
54
|
+
def expand_cookbook_files(files)
|
55
|
+
files.each do |attr|
|
56
|
+
if text_type?(attr) and !(attr[1]['related'].nil?)
|
57
|
+
source = attr[0].split('/').last
|
58
|
+
content = attr[1]['content']
|
59
|
+
CookbookFile.new(@cookbook_files_path, source, content, 'cookbook_file').create
|
60
|
+
end
|
61
|
+
# TODO: This is a work around to source list file
|
62
|
+
# should be replaced for a better logic
|
63
|
+
if text_type?(attr) and attr[0].include? "/etc/apt/sources.list"
|
64
|
+
source = attr[0].split('/').last
|
65
|
+
content = attr[1]['content']
|
66
|
+
CookbookFile.new(@cookbook_files_path, source, content, 'cookbook_file').create
|
67
|
+
end
|
68
|
+
end
|
69
|
+
end
|
70
|
+
end
|
71
|
+
end
|
@@ -0,0 +1,22 @@
|
|
1
|
+
module Cupper
|
2
|
+
class Cupperfile
|
3
|
+
|
4
|
+
def initialize(loader, keys)
|
5
|
+
@keys = keys
|
6
|
+
@loader = loader
|
7
|
+
@config, _ = loader.load(keys)
|
8
|
+
end
|
9
|
+
|
10
|
+
protected
|
11
|
+
|
12
|
+
def find_cupperfile(search_path)
|
13
|
+
["Cupperfile", "cupperfile"].each do |cupperfile|
|
14
|
+
current_path = search_path.join(cupperfile)
|
15
|
+
return current_path if current_path.file?
|
16
|
+
end
|
17
|
+
|
18
|
+
nil
|
19
|
+
end
|
20
|
+
|
21
|
+
end
|
22
|
+
end
|
@@ -0,0 +1,63 @@
|
|
1
|
+
module Cupper
|
2
|
+
# Entity represents a Entity
|
3
|
+
module Entity
|
4
|
+
require 'erb'
|
5
|
+
|
6
|
+
FILE = 'file'
|
7
|
+
DIR = 'dir'
|
8
|
+
|
9
|
+
# As default the Entity is treated as a file
|
10
|
+
def initialize(name, dest_path, erb_file = nil, type = nil, extension = '')
|
11
|
+
@name = name
|
12
|
+
@dest_path = dest_path
|
13
|
+
@erb_file = erb_file
|
14
|
+
@type = type.nil? ? FILE : type
|
15
|
+
@ext = extension
|
16
|
+
|
17
|
+
@full_path = "#{@dest_path}/#{@name}#{@ext}"
|
18
|
+
end
|
19
|
+
|
20
|
+
# Create the actual file or dir in the correct place
|
21
|
+
def create
|
22
|
+
content(@erb_file)
|
23
|
+
save
|
24
|
+
end
|
25
|
+
|
26
|
+
# Returns the content of the file
|
27
|
+
def content(erb_file)
|
28
|
+
return false if self.dir?
|
29
|
+
@template = File.read("#{TEMPLATE_PATH}/#{erb_file}.erb")
|
30
|
+
end
|
31
|
+
|
32
|
+
def save
|
33
|
+
File.open(@full_path,"a+") { |f| f.write(self.render_template) } if self.file?
|
34
|
+
Dir.mkdir(@full_path) if self.dir? && !(self.exist?)
|
35
|
+
end
|
36
|
+
|
37
|
+
def render_template
|
38
|
+
ERB.new(@template).result(binding)
|
39
|
+
end
|
40
|
+
|
41
|
+
# Treats entity as a file or as a dir
|
42
|
+
def file?
|
43
|
+
@type == FILE
|
44
|
+
end
|
45
|
+
def dir?
|
46
|
+
@type == DIR
|
47
|
+
end
|
48
|
+
|
49
|
+
def exist?
|
50
|
+
return File.exist?(@full_path) if self.file?
|
51
|
+
return Dir.exist?(@full_path) if self.dir?
|
52
|
+
end
|
53
|
+
|
54
|
+
def full_path
|
55
|
+
@full_path
|
56
|
+
end
|
57
|
+
end
|
58
|
+
|
59
|
+
class Attribute
|
60
|
+
attr_reader :attr
|
61
|
+
end
|
62
|
+
|
63
|
+
end
|