chekku 0.0.5 → 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.
- data/README.md +8 -0
- data/chekku.gemspec +1 -0
- data/lib/chekku.rb +2 -0
- data/lib/chekku/checker.rb +1 -0
- data/lib/chekku/definition.rb +125 -62
- data/lib/chekku/definitions.rb +27 -7
- data/lib/chekku/definitions_service.rb +11 -4
- data/lib/chekku/fetcher.rb +5 -1
- data/lib/chekku/version.rb +1 -1
- data/spec/lib/definition_spec.rb +16 -2
- data/spec/lib/definitions_service_spec.rb +1 -0
- data/spec/lib/definitions_spec.rb +3 -0
- data/spec/lib/fetcher_spec.rb +1 -0
- data/spec/spec_helper.rb +2 -15
- metadata +19 -2
data/README.md
CHANGED
@@ -54,6 +54,14 @@ imagemagick:
|
|
54
54
|
executable: 'convert'
|
55
55
|
```
|
56
56
|
|
57
|
+
## Use Definition object in your code
|
58
|
+
|
59
|
+
Example on how to check a software dependency
|
60
|
+
|
61
|
+
```
|
62
|
+
definition = Chekku::Definition.new(name: 'mysql', executable: 'mysqld')
|
63
|
+
definition.chekku('>= 5.0')
|
64
|
+
```
|
57
65
|
|
58
66
|
## Future
|
59
67
|
|
data/chekku.gemspec
CHANGED
@@ -14,6 +14,7 @@ Gem::Specification.new do |gem|
|
|
14
14
|
gem.required_ruby_version = '>= 1.9'
|
15
15
|
gem.required_rubygems_version = '>= 1.3.6'
|
16
16
|
gem.add_development_dependency 'rspec', '>= 2.0'
|
17
|
+
gem.add_development_dependency 'simplecov'
|
17
18
|
gem.add_dependency 'thor'
|
18
19
|
gem.add_dependency 'rake'
|
19
20
|
gem.files = `git ls-files`.split($/)
|
data/lib/chekku.rb
CHANGED
data/lib/chekku/checker.rb
CHANGED
@@ -10,6 +10,7 @@ class Chekku::Checker < Thor
|
|
10
10
|
|
11
11
|
method_option :chekkufile, type: :string, desc: 'Chekkufile Path', default: 'Chekkufile'
|
12
12
|
|
13
|
+
# Checks the software dependencies based on the chekku files
|
13
14
|
def checks
|
14
15
|
@chekkufile = options[:chekkufile]
|
15
16
|
verify_chekku_file_existence
|
data/lib/chekku/definition.rb
CHANGED
@@ -1,85 +1,148 @@
|
|
1
1
|
#encoding: utf-8
|
2
|
-
|
2
|
+
require_relative 'errors'
|
3
3
|
|
4
|
-
|
4
|
+
# This Definition object has attributes for checking
|
5
|
+
# if the software is installed and respect conditions
|
6
|
+
#
|
7
|
+
# You can use this class in your code to easily embed software checks
|
8
|
+
#
|
9
|
+
# @example Check a software Dependency
|
10
|
+
# definition = Chekku::Definition.new(name: 'mysql', executable: 'mysqld')
|
11
|
+
# definition.chekku('>= 5.0', must_run: true)
|
12
|
+
#
|
13
|
+
# @attr [String] name the Definition name used in the Chekkufile and def.yml file
|
14
|
+
# @attr [String] executable the actual software dependency executable name
|
15
|
+
module Chekku
|
16
|
+
class Definition
|
5
17
|
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
18
|
+
attr_accessor :name, :executable
|
19
|
+
|
20
|
+
# Convert a formatted hash to an array of definitions
|
21
|
+
#
|
22
|
+
# @param [Hash] definitions_hash a valid hash of definitions
|
23
|
+
# @return [Array] an Array of Definition
|
24
|
+
def self.load(definitions_hash = {})
|
25
|
+
[].tap do |definitions|
|
26
|
+
definitions_hash.each_pair do |name, hash_definition|
|
27
|
+
definitions << self.new(hash_definition.merge(name: name))
|
28
|
+
end
|
10
29
|
end
|
11
30
|
end
|
12
|
-
end
|
13
31
|
|
14
|
-
|
15
|
-
|
16
|
-
|
32
|
+
def initialize(attributes = {})
|
33
|
+
attributes.each do |name, value|
|
34
|
+
send("#{name}=", value)
|
35
|
+
end
|
17
36
|
end
|
18
|
-
@errors = {}
|
19
|
-
end
|
20
37
|
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
38
|
+
# Check if version and other params are valid for current Definition instance and raise errors
|
39
|
+
#
|
40
|
+
# @param [String] version Version to check in the format '>= 4.0' accepts '~> 3.0'
|
41
|
+
# @param [Hash] args Possible checks that must be verified for current Definition
|
42
|
+
# @option args [Boolean] must_run Check if the software is running on the host
|
43
|
+
# @return [Boolean] true if valid, if not valid errors are raised
|
44
|
+
# @raise [DefinitionValidationError] An exception if the params requirements are not met
|
45
|
+
# @raise [AppNameNotStringError] if Definition is not correct and executable isn't a string
|
46
|
+
# @raise [AppNameNotSaneError] if Definition executable isn't safe (spaces, special chars and so on)
|
47
|
+
def chekku!(version = nil, args = {})
|
48
|
+
raise(DefinitionValidationError, "not installed") unless exists?
|
49
|
+
validates version, args
|
50
|
+
end
|
26
51
|
|
27
|
-
|
28
|
-
|
29
|
-
|
52
|
+
# Check if version and other params are valid for current Definition instance and return false if errors
|
53
|
+
# @param (see #chekku!)
|
54
|
+
# @return [Boolean] version and args are valid => true else false
|
55
|
+
def chekku(version = nil, args = {})
|
56
|
+
chekku!(version, args)
|
57
|
+
rescue
|
58
|
+
false
|
59
|
+
end
|
30
60
|
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
61
|
+
# Verify existence of dependency
|
62
|
+
#
|
63
|
+
# @return [Boolean] corresponding to the existence
|
64
|
+
def exists?
|
65
|
+
verify_executable! && found?
|
66
|
+
end
|
36
67
|
|
37
|
-
|
38
|
-
|
39
|
-
|
68
|
+
# Validates the params provided are the one of the local dependency
|
69
|
+
#
|
70
|
+
# @param (see #chekku)
|
71
|
+
# @return [Boolean] valid?
|
72
|
+
def validates(version = nil, args = {})
|
73
|
+
raise(DefinitionValidationError, "wrong version: wanted #{version}, got #{installed_version}") unless ( !version || check_version(version))
|
74
|
+
raise(DefinitionValidationError, "installed but not running (must_run: true)") unless (!args[:must_run] || is_running?)
|
75
|
+
true
|
76
|
+
end
|
40
77
|
|
41
|
-
|
42
|
-
|
43
|
-
|
78
|
+
# Verify if the executable of the Definition is sane and correct
|
79
|
+
#
|
80
|
+
# @return [Boolean] valid?
|
81
|
+
def verify_executable!
|
82
|
+
raise(AppNameNotStringError, 'You need to use strings for app names') unless executable.is_a?(String)
|
83
|
+
raise(AppNameNotSaneError, "Sorry the app name '#{name}' is not sane") unless sane_executable?
|
84
|
+
true
|
85
|
+
end
|
44
86
|
|
45
|
-
|
46
|
-
|
47
|
-
|
87
|
+
# Actual method which verifies if defined software is present
|
88
|
+
#
|
89
|
+
# @return [Boolean] found?
|
90
|
+
def found?
|
91
|
+
system "which #{executable} > /dev/null 2>&1"
|
92
|
+
end
|
48
93
|
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
94
|
+
# Verify that the executable is harmless for the machine
|
95
|
+
#
|
96
|
+
# @return [Boolean] sane?
|
97
|
+
def sane_executable?
|
98
|
+
executable == sanitized_executable
|
99
|
+
end
|
54
100
|
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
101
|
+
# Get the sanitized name of the executable
|
102
|
+
#
|
103
|
+
# @return [String] sane executable
|
104
|
+
def sanitized_executable
|
105
|
+
executable.gsub /&|"|'|;|\s/, ""
|
60
106
|
end
|
61
|
-
end
|
62
107
|
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
|
108
|
+
# Verify that current executable is running or not on host
|
109
|
+
#
|
110
|
+
# @return [Boolean] running?
|
111
|
+
def is_running?
|
112
|
+
ps_result = `ps aux | grep #{executable}`
|
113
|
+
ps_result_array = ps_result.split("\n")
|
114
|
+
ps_result_array.any? do |ps_line|
|
115
|
+
ps_line.include?(executable) && (executable == 'grep' || !ps_line.include?('grep'))
|
116
|
+
end
|
68
117
|
end
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
|
118
|
+
|
119
|
+
# Verify version
|
120
|
+
#
|
121
|
+
# @param [String] version current version wanted
|
122
|
+
# @return [Boolean] good_version?
|
123
|
+
def check_version(version)
|
124
|
+
operator, version = version.split(' ')
|
125
|
+
if version.nil?
|
126
|
+
version = operator
|
127
|
+
operator = '=='
|
128
|
+
end
|
129
|
+
if operator == '~>'
|
130
|
+
installed_version >= Gem::Version.new(version) && installed_version <= Gem::Version.new(version).bump
|
131
|
+
else
|
132
|
+
installed_version.send(operator, Gem::Version.new(version))
|
133
|
+
end
|
73
134
|
end
|
74
|
-
end
|
75
135
|
|
76
|
-
|
77
|
-
|
78
|
-
|
79
|
-
|
80
|
-
|
136
|
+
# Get the current installed version on the host
|
137
|
+
#
|
138
|
+
# @return [String] string representation of version
|
139
|
+
def installed_version
|
140
|
+
version_matches = `#{executable} --version`.scan(/(\d+[\.\d+]*)/).flatten
|
141
|
+
max_dot_number_version = ''
|
142
|
+
version_matches.each do |version|
|
143
|
+
max_dot_number_version = version if version.count('.') > max_dot_number_version.count('.')
|
144
|
+
end
|
145
|
+
Gem::Version.new(max_dot_number_version)
|
81
146
|
end
|
82
|
-
Gem::Version.new(max_dot_number_version)
|
83
147
|
end
|
84
|
-
|
85
148
|
end
|
data/lib/chekku/definitions.rb
CHANGED
@@ -6,41 +6,61 @@ class Chekku::Definitions
|
|
6
6
|
|
7
7
|
attr_accessor :definitions_service, :dependency_checker
|
8
8
|
|
9
|
-
|
10
|
-
|
9
|
+
# Evaluate the given Chekkufile and check every dependency
|
10
|
+
#
|
11
|
+
# @param [String] file_path Path to Chekkufile
|
12
|
+
def self.evaluate(file_path)
|
13
|
+
new.eval_chekkufile(file_path)
|
11
14
|
end
|
12
15
|
|
16
|
+
# Instanciate a new instance and create a DefinitionService
|
13
17
|
def initialize
|
14
18
|
@definitions_service = Chekku::DefinitionsService.new
|
15
19
|
@definitions_service.load_definitions_for @chekkufile
|
16
20
|
end
|
17
21
|
|
18
|
-
|
19
|
-
|
22
|
+
# Parse the file and evaluate every dependency
|
23
|
+
#
|
24
|
+
# @param [String] file_path Path to Chekkufile
|
25
|
+
# @raise [NoMethodError] Wrong format of Chekkufile
|
26
|
+
def eval_chekkufile(file_path)
|
27
|
+
instance_eval(read_file(file_path))
|
20
28
|
rescue NoMethodError => e
|
21
29
|
puts "\033[31mERROR: Please verify the syntax of your Chekkufile"
|
22
30
|
end
|
23
31
|
|
32
|
+
# Check against the Definition if depency is valid
|
33
|
+
# Actual method written in the Chekkufile
|
34
|
+
# It is responsible to output the result
|
35
|
+
#
|
36
|
+
# @param [String] name Name of the Definition
|
37
|
+
# @param [String] version Current version wanted on the host
|
38
|
+
# @param [Hash] args for the moment only must_run: true false Indicating if is running or not
|
24
39
|
def check(name, version = nil, args = {})
|
25
40
|
unless version.is_a?(String)
|
26
41
|
args = version || {}
|
27
42
|
version = nil
|
28
43
|
end
|
29
44
|
definition = get_definition! name
|
30
|
-
puts definition.chekku(version, args)
|
45
|
+
puts "[\033[32m✓\033[0m] #{name}" if definition.chekku(version, args)
|
31
46
|
rescue DefinitionsError => e
|
32
47
|
puts "[\033[31m✗\033[0m] #{name}: #{e.message}\n"
|
33
48
|
rescue ChekkuError => e
|
34
49
|
puts "\033[31mERROR: #{e.message}\033[0m\n"
|
35
50
|
end
|
36
51
|
|
52
|
+
# Retrieve the Definition instance from the DefinitionService
|
53
|
+
#
|
54
|
+
# @param [String] name Definition name
|
55
|
+
# @return [Definition] actual definition
|
56
|
+
# @raise [DefinitionNotFoundError] if Definition is not found
|
37
57
|
def get_definition!(name)
|
38
58
|
@definitions_service.definition_for(name) ||
|
39
59
|
raise(DefinitionNotFoundError, "#{name} definition not found. Check ~/.chekku/def.yml")
|
40
60
|
end
|
41
61
|
|
42
|
-
def read_file(
|
43
|
-
File.open(
|
62
|
+
def read_file(file_path)
|
63
|
+
File.open(file_path, "r") { |f| f.read }
|
44
64
|
end
|
45
65
|
|
46
66
|
end
|
@@ -4,11 +4,18 @@ class Chekku::DefinitionsService
|
|
4
4
|
|
5
5
|
attr_accessor :definitions
|
6
6
|
|
7
|
-
|
8
|
-
|
7
|
+
# load the Definition list for the needed dependencies
|
8
|
+
#
|
9
|
+
# @param [String] file_path Path to Chekkufile
|
10
|
+
def load_definitions_for(file_path)
|
11
|
+
@definitions = Chekku::Fetcher.fetch_for_chekkufile file_path
|
9
12
|
end
|
10
13
|
|
11
|
-
|
12
|
-
|
14
|
+
# Retrieve one Definition from the list
|
15
|
+
#
|
16
|
+
# @param [String] definition_name The needed Definition name
|
17
|
+
# @return [Definition] The needed Definition
|
18
|
+
def definition_for(definition_name)
|
19
|
+
@definitions.select{ |definition| definition.name == definition_name }.first if @definitions
|
13
20
|
end
|
14
21
|
end
|
data/lib/chekku/fetcher.rb
CHANGED
@@ -8,7 +8,11 @@ class Chekku::Fetcher
|
|
8
8
|
|
9
9
|
attr_accessor :dependencies
|
10
10
|
|
11
|
-
|
11
|
+
# Fetch the Definitions from the file
|
12
|
+
#
|
13
|
+
# @param [String] file_path Path to Chekkufile
|
14
|
+
# @return [Array] a list of Definition instances
|
15
|
+
def self.fetch_for_chekkufile(file_path)
|
12
16
|
# TODO: Implements server side of the file checker
|
13
17
|
# STUB: Load local file
|
14
18
|
fetcher = new
|
data/lib/chekku/version.rb
CHANGED
data/spec/lib/definition_spec.rb
CHANGED
@@ -1,4 +1,5 @@
|
|
1
1
|
#encoding: utf-8
|
2
|
+
require 'spec_helper'
|
2
3
|
require 'chekku/definition'
|
3
4
|
require 'chekku/errors'
|
4
5
|
|
@@ -76,14 +77,27 @@ describe Chekku::Definition do
|
|
76
77
|
end
|
77
78
|
end
|
78
79
|
|
80
|
+
describe '.chekku!' do
|
81
|
+
it 'should says ✓ if soft exists' do
|
82
|
+
definition.stub(:exists?).and_return(true)
|
83
|
+
definition.chekku!.should be_true
|
84
|
+
end
|
85
|
+
|
86
|
+
it 'should says x if soft does not exist' do
|
87
|
+
definition.stub(:exists?).and_return(false)
|
88
|
+
expect { definition.chekku! }.to raise_error(DefinitionValidationError)
|
89
|
+
end
|
90
|
+
end
|
91
|
+
|
79
92
|
describe '.chekku' do
|
80
93
|
it 'should says ✓ if soft exists' do
|
81
94
|
definition.stub(:exists?).and_return(true)
|
82
|
-
definition.chekku.should
|
95
|
+
definition.chekku.should be_true
|
83
96
|
end
|
97
|
+
|
84
98
|
it 'should says x if soft does not exist' do
|
85
99
|
definition.stub(:exists?).and_return(false)
|
86
|
-
|
100
|
+
definition.chekku.should be_false
|
87
101
|
end
|
88
102
|
end
|
89
103
|
|
@@ -1,4 +1,5 @@
|
|
1
1
|
#encoding: utf-8
|
2
|
+
require 'spec_helper'
|
2
3
|
require 'chekku/definitions'
|
3
4
|
require 'chekku/definitions_service'
|
4
5
|
require 'chekku/errors'
|
@@ -13,11 +14,13 @@ describe Chekku::Definitions do
|
|
13
14
|
|
14
15
|
describe '.get_definition' do
|
15
16
|
it 'should return the definition' do
|
17
|
+
Chekku::DefinitionsService.any_instance.stub(:load_definitions_for)
|
16
18
|
definitions.definitions_service.stub(:definition_for).with('mysql').and_return(definition)
|
17
19
|
definitions.get_definition!('mysql').should == definition
|
18
20
|
end
|
19
21
|
|
20
22
|
it 'should raise an error if not found' do
|
23
|
+
Chekku::DefinitionsService.any_instance.stub(:load_definitions_for)
|
21
24
|
definitions.definitions_service.stub(:definition_for).with('mysql').and_return(nil)
|
22
25
|
expect{ definitions.get_definition!('mysql') }.to raise_error(DefinitionNotFoundError)
|
23
26
|
end
|
data/spec/lib/fetcher_spec.rb
CHANGED
data/spec/spec_helper.rb
CHANGED
@@ -1,16 +1,3 @@
|
|
1
|
-
require '
|
2
|
-
|
1
|
+
require 'simplecov'
|
2
|
+
SimpleCov.start
|
3
3
|
|
4
|
-
require 'chekku'
|
5
|
-
# Load support files
|
6
|
-
Dir["#{File.dirname(__FILE__)}/support/**/*.rb"].each { |f| require f }
|
7
|
-
|
8
|
-
# Load fixtures from the engine
|
9
|
-
if ActiveSupport::TestCase.method_defined?(:fixture_path=)
|
10
|
-
ActiveSupport::TestCase.fixture_path = File.expand_path("../fixtures", __FILE__)
|
11
|
-
end
|
12
|
-
|
13
|
-
RSpec.configure do |config|
|
14
|
-
config.before :each do
|
15
|
-
end
|
16
|
-
end
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: chekku
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.0
|
4
|
+
version: 0.1.0
|
5
5
|
prerelease:
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
@@ -9,7 +9,7 @@ authors:
|
|
9
9
|
autorequire:
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
|
-
date: 2012-10-
|
12
|
+
date: 2012-10-24 00:00:00.000000000 Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: rspec
|
@@ -27,6 +27,22 @@ dependencies:
|
|
27
27
|
- - ! '>='
|
28
28
|
- !ruby/object:Gem::Version
|
29
29
|
version: '2.0'
|
30
|
+
- !ruby/object:Gem::Dependency
|
31
|
+
name: simplecov
|
32
|
+
requirement: !ruby/object:Gem::Requirement
|
33
|
+
none: false
|
34
|
+
requirements:
|
35
|
+
- - ! '>='
|
36
|
+
- !ruby/object:Gem::Version
|
37
|
+
version: '0'
|
38
|
+
type: :development
|
39
|
+
prerelease: false
|
40
|
+
version_requirements: !ruby/object:Gem::Requirement
|
41
|
+
none: false
|
42
|
+
requirements:
|
43
|
+
- - ! '>='
|
44
|
+
- !ruby/object:Gem::Version
|
45
|
+
version: '0'
|
30
46
|
- !ruby/object:Gem::Dependency
|
31
47
|
name: thor
|
32
48
|
requirement: !ruby/object:Gem::Requirement
|
@@ -121,3 +137,4 @@ test_files:
|
|
121
137
|
- spec/lib/definitions_spec.rb
|
122
138
|
- spec/lib/fetcher_spec.rb
|
123
139
|
- spec/spec_helper.rb
|
140
|
+
has_rdoc:
|