kitchen-inspector 1.0.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: 9b52453ef08f59048fe9d23eba2dd17f270cab33
4
+ data.tar.gz: 7806ba21b1e19419f5d6356ea49078718871a44a
5
+ SHA512:
6
+ metadata.gz: cf646ff7130df24e3406c26269ae2eff1524e4a9ae6e726efe146b6d7ef0d4c690bbfe5584b647e4225cfb47acd935a909e81b5d0f72cc1a847f12d496596860
7
+ data.tar.gz: 6f399d5232c70cfe2106ba867c6ef61f9af77e4185666ba8908e91fd3c2c4ceba4357766c91a35cf917550a932460bc2d021a4a12b1d8c6638df02e922b6ed11
@@ -0,0 +1,14 @@
1
+ *.gem
2
+ *.rbc
3
+ .bundle
4
+ .config
5
+ .yardoc
6
+ Gemfile.lock
7
+ InstalledFiles
8
+ _yardoc
9
+ doc/
10
+ lib/bundler/man
11
+ pkg
12
+ rdoc
13
+ tmp
14
+ examples
data/Gemfile ADDED
@@ -0,0 +1,4 @@
1
+ source 'https://rubygems.org'
2
+
3
+ gemspec
4
+ gem 'byebug'
data/INFO.md ADDED
@@ -0,0 +1,44 @@
1
+ # Dependency Matrix
2
+
3
+ Note: _Used_ refers to the version that would be retrieved from the Chef Server.
4
+
5
+ ## Aligned Servers
6
+ Gitlab | Chef Server
7
+ ------ | -----------
8
+ 1.10 | 1.10
9
+ 1.9.7 | 1.9.7
10
+ 1.9.6 | 1.9.6
11
+
12
+ Scenario | Req | Used | Status Req | Status servers | Remarks
13
+ :- | :- | :- | :- | :- | :-
14
+ Behind req. | = 1.9.6 | 1.9.6 | ! warning-req | √ | You could relax requirements
15
+ Last match | ~> 1.9.6 or = 1.9.7 | 1.9.7 | √ | √ |
16
+ Forward req. | > 1.10 or > 1.9.7 | | X error | √ | Version not found
17
+
18
+ ## Gitlab out-of-date
19
+ Gitlab | Chef Server
20
+ ------ | -----------
21
+ | 1.10
22
+ 1.9.7 | 1.9.7
23
+ 1.9.6 | 1.9.6
24
+
25
+ Scenario | Req | Used | Status Req | Status servers | Remarks
26
+ :- | :- | :- | :- | :- | :-
27
+ Behind req. | = 1.9.6 | 1.9.6 | ! warning-req | ! warning-gitlab | You could relax requirements. Gitlab not aligned
28
+ Last match gitlab | ~> 1.9.6 or = 1.9.7 | 1.9.7 | √ | ! warning-gitlab | Gitlab not aligned
29
+ Last match Chef | ~> 1.10 | 1.10 | √ | ! warning-gitlab | Gitlab not aligned
30
+ Forward req. | > 1.10 or > 1.9.7 | | X error | ! warning-gitlab | Version not found
31
+
32
+ ## Chef server out-of-date
33
+ Gitlab | Chef Server
34
+ ------ | -----------
35
+ 1.10 |
36
+ 1.9.7 | 1.9.7
37
+ 1.9.6 | 1.9.6
38
+
39
+ Scenario | Req | Used | Status Req | Status servers | Remarks
40
+ :- | :- | :- | :- | :- | :-
41
+ Behind req. | = 1.9.6 | 1.9.6 | ! warning-req | ! warning-chef | You could relax requirements. Chef Server not aligned
42
+ Last match gitlab | ~> 1.10 | | X error | ! warning-chef | Chef Server not aligned
43
+ Last match Chef | ~> 1.9.6 | 1.9.7 | √ | ! warning-chef | Chef Server not aligned
44
+ Forward req. | > 1.10 | | X error | ! warning-chef | Version not found
@@ -0,0 +1,22 @@
1
+ Copyright (c) 2013 Stefano Tortarolo <stefano.tortarolo@gmail.com>
2
+
3
+ MIT License
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining
6
+ a copy of this software and associated documentation files (the
7
+ "Software"), to deal in the Software without restriction, including
8
+ without limitation the rights to use, copy, modify, merge, publish,
9
+ distribute, sublicense, and/or sell copies of the Software, and to
10
+ permit persons to whom the Software is furnished to do so, subject to
11
+ the following conditions:
12
+
13
+ The above copyright notice and this permission notice shall be
14
+ included in all copies or substantial portions of the Software.
15
+
16
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
17
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
19
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
20
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
21
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
22
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
@@ -0,0 +1,80 @@
1
+ # Kitchen Inspector
2
+
3
+ Kitchen Ispector is a CLI utility inspired by chef-taste to check a cookbook's dependency status against a Chef server and a Gitlab instance.
4
+
5
+ It assumes that your kitchen is composed by:
6
+
7
+ * a Chef server containing the cookbooks to be used
8
+ * a Gitlab instance hosting cookbook's development
9
+
10
+ This tool checks whether the dependencies specified are up to date or not.
11
+ It also shows whether one of the servers must be aligned.
12
+
13
+ ## Installation
14
+
15
+ Add this line to your application's Gemfile:
16
+
17
+ gem 'kitchen-inspector'
18
+
19
+ And then execute:
20
+
21
+ $ bundle
22
+
23
+ Or install it with:
24
+
25
+ $ gem install kitchen-inspector
26
+
27
+ ## Usage
28
+
29
+ The following variables must be exported in order to configure the Chef and Gitlab servers:
30
+
31
+ * GITLAB_URL: Url of the Gitlab server
32
+ * GITLAB_TOKEN: Gitlab private token (Profile > Account)
33
+ * CHEF_SERVER_URL: Url of the Chef server
34
+ * CHEF_USERNAME: Client username
35
+ * CHEF_CLIENT_PEM: Location of the client pem
36
+
37
+ From inside the cookbook's directory, type `kitchen-inspector` to inspect your kitchen.
38
+ It's also possible to specify a target directory with `kitchen-inspector investigate PATH`.
39
+
40
+ The `metadata.rb` of the cookbook is parsed to obtain the dependencies, then the configured Chef server and Gitlab server are queried to define which versions are available.
41
+ The Chef server's version is the one that will define the used version.
42
+
43
+ It will display a table that contains the following rows:
44
+
45
+ * `Name` - The name of the cookbook
46
+ * `Requirement` - The version requirement specified in the metadata
47
+ * `Used` - The final version used based on the requirement constraint
48
+ * `Latest Chef` - The latest version available on the Chef server
49
+ * `Latest Gitlab` - The latest version available on the Gitlab server
50
+ * `Requirement Status` - The status of the cookbook: up-to-date (a green tick mark), warning-req (a yellow esclamation point) or out-of-date (a red x mark)
51
+ * `Chef Server Status` - The status of the chef server: up-to-date (a green tick mark), warning-req (a yellow esclamation point) or out-of-date (a red x mark)
52
+ * `Gitlab Status` - The status of the Gitlab server: up-to-date (a green tick mark), warning-req (a yellow esclamation point) or out-of-date (a red x mark)
53
+
54
+ The overall status will also be displayed in the bottom of the table.
55
+
56
+ ### Display Format
57
+
58
+ Two display formats are supported: table and json
59
+
60
+ 1. The table format will display the dependency status as an ASCII table
61
+ 2. The json format will display the dependency status as a JSON object
62
+
63
+ ### Examples
64
+
65
+ +-----------+-------------+-------+--------+--------+-------------+-------------+--------+--------------------+
66
+ | Name | Requirement | Used | Latest | Latest | Requirement | Chef Server | Gitlab | Remarks |
67
+ | | | | Chef | Gitlab | Status | Status | Status | |
68
+ +-----------+-------------+-------+--------+--------+-------------+-------------+--------+--------------------+
69
+ | apt | = 2.3.4 | 2.3.4 | 2.3.4 | 2.3.8 | ✔ | ! | ✔ | A new version might appear on Chef server|
70
+ | jbosseap6 | ~> 0.9.3 | 0.9.8 | 0.10.0 | 0.10.0 | ✔ | ✔ | ✔ | |
71
+ | database | = 1.5.2 | 1.5.2 | 1.5.3 | 1.5.2 | ! | ✔ | !! | 1.5.3 is available, Gitlab out-of-date! |
72
+ | yum | = 2.3.4 | 2.3.4 | 2.3.4 | 2.3.4 | ✔ | ✔ | ✔ | |
73
+ | git | = 1.8.1 | 1.8.1 | 1.8.4 | 1.8.4 | ! | ✔ | ✔ | 1.8.4 is available |
74
+ | hadoop | ~> 1.1.0 | | | 1.0.0 | ✖ | ! | ✔ | No versions found |
75
+ | zookeeper | = 1.0.0 | | | 1.0.0 | ✖ | ! | ✔ | No versions found |
76
+ +-----------+-------------+-------+--------+--------+-------------+-------------+--------+--------------------+
77
+ Status: error (✖)
78
+
79
+ ## Credits
80
+ This code was heavily inspired by Kannan Manickam's [chef-taste](https://github.com/arangamani/chef-taste)
@@ -0,0 +1 @@
1
+ require "bundler/gem_tasks"
@@ -0,0 +1,5 @@
1
+ #!/usr/bin/env ruby
2
+ $LOAD_PATH.push File.expand_path('../../lib', __FILE__)
3
+ require 'kitchen-inspector/inspector'
4
+
5
+ KitchenInspector::Inspector::Cli.start
@@ -0,0 +1,31 @@
1
+ table {
2
+ margin-bottom: 10px !important;
3
+ margin:0px;padding:0px;
4
+ border:1px solid #000;
5
+ border-collapse: collapse;
6
+ border-spacing: 0;
7
+ width:90%;
8
+ height:100%;
9
+ }
10
+ table tr:nth-child(odd){ background-color:#f5f5f5; }
11
+ table tr:nth-child(even){ background-color:#ffffff; }
12
+
13
+ table td{
14
+ vertical-align:middle;
15
+ border:1px solid #000;
16
+ text-align:left;
17
+ padding:8px;
18
+ font-size:11px;
19
+ font-family:Arial;
20
+ font-weight:normal;
21
+ color:#000;
22
+ }
23
+ table th{
24
+ background-color:#b2b2b2;
25
+ border:1px solid #000;
26
+ text-align:center;
27
+ font-size:14px;
28
+ font-family:Arial;
29
+ font-weight:bold;
30
+ color:#333;
31
+ }
@@ -0,0 +1,32 @@
1
+ # coding: utf-8
2
+ lib = File.expand_path('../lib', __FILE__)
3
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
+ require 'kitchen-inspector/inspector/version'
5
+
6
+ Gem::Specification.new do |spec|
7
+ spec.name = "kitchen-inspector"
8
+ spec.version = KitchenInspector::Inspector::VERSION
9
+ spec.authors = ["Stefano Tortarolo"]
10
+ spec.email = ["stefano.tortarolo@gmail.com"]
11
+ spec.description = %q{This gem verifies that dependencies are updated in regard with a Chef Server and Gitlab}
12
+ spec.summary = %q{Chef server and Gitlab dependency checker}
13
+ spec.homepage = "https://github.com/astratto/kitchen-inspector"
14
+ spec.license = "MIT"
15
+
16
+ spec.files = `git ls-files`.split($/)
17
+ spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
18
+ spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
19
+ spec.require_paths = ["lib"]
20
+
21
+ spec.add_development_dependency "bundler", "~> 1.3"
22
+ spec.add_development_dependency "rubocop", "~> 0.14"
23
+ spec.add_development_dependency "rake"
24
+
25
+ spec.add_dependency "solve", "~> 0.8.0"
26
+ spec.add_dependency "berkshelf", "~> 2.0.10"
27
+ spec.add_dependency "thor", "~> 0.18.0"
28
+ spec.add_dependency "terminal-table", "~> 1.4.5"
29
+ spec.add_dependency "colorize", "~> 0.6.0"
30
+ spec.add_dependency "gitlab"
31
+ spec.add_dependency "chef", ">= 11.0.0"
32
+ end
@@ -0,0 +1,39 @@
1
+ #
2
+ # Copyright (c) 2013 Stefano Tortarolo <stefano.tortarolo@gmail.com>
3
+ #
4
+ # MIT License
5
+ #
6
+ # Permission is hereby granted, free of charge, to any person obtaining
7
+ # a copy of this software and associated documentation files (the
8
+ # "Software"), to deal in the Software without restriction, including
9
+ # without limitation the rights to use, copy, modify, merge, publish,
10
+ # distribute, sublicense, and/or sell copies of the Software, and to
11
+ # permit persons to whom the Software is furnished to do so, subject to
12
+ # the following conditions:
13
+ #
14
+ # The above copyright notice and this permission notice shall be
15
+ # included in all copies or substantial portions of the Software.
16
+ #
17
+ # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
18
+ # EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
19
+ # MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
20
+ # NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
21
+ # LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
22
+ # OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
23
+ # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
24
+ #
25
+
26
+ require 'chef/rest'
27
+ require 'berkshelf'
28
+ require 'colorize'
29
+ require 'ridley'
30
+ require 'terminal-table'
31
+ require 'thor'
32
+ require 'gitlab'
33
+
34
+ require 'kitchen-inspector/inspector/cli'
35
+ require 'kitchen-inspector/inspector/error'
36
+ require 'kitchen-inspector/inspector/dependency'
37
+ require 'kitchen-inspector/inspector/dependency_inspector'
38
+ require 'kitchen-inspector/inspector/report'
39
+ require 'kitchen-inspector/inspector/version'
@@ -0,0 +1,53 @@
1
+ #
2
+ # Copyright (c) 2013 Stefano Tortarolo <stefano.tortarolo@gmail.com>
3
+ #
4
+ # MIT License
5
+ #
6
+ # Permission is hereby granted, free of charge, to any person obtaining
7
+ # a copy of this software and associated documentation files (the
8
+ # "Software"), to deal in the Software without restriction, including
9
+ # without limitation the rights to use, copy, modify, merge, publish,
10
+ # distribute, sublicense, and/or sell copies of the Software, and to
11
+ # permit persons to whom the Software is furnished to do so, subject to
12
+ # the following conditions:
13
+ #
14
+ # The above copyright notice and this permission notice shall be
15
+ # included in all copies or substantial portions of the Software.
16
+ #
17
+ # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
18
+ # EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
19
+ # MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
20
+ # NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
21
+ # LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
22
+ # OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
23
+ # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
24
+ #
25
+
26
+ module KitchenInspector
27
+ module Inspector
28
+ class Cli < Thor
29
+ default_task :investigate
30
+
31
+ method_option :format, type: :string,
32
+ desc: 'The format to use for display',
33
+ enum: %w(table json),
34
+ default: 'table',
35
+ aliases: '-t'
36
+
37
+ desc 'investigate (COOKBOOK_PATH)', 'Check Gitlab/Chef status of dependent cookbooks'
38
+
39
+ def investigate(path=Dir.pwd)
40
+ dependencies = DependencyInspector.investigate path
41
+ if dependencies.empty?
42
+ puts 'No dependent cookbooks'.yellow
43
+ else
44
+ puts Report.generate(dependencies, options[:format])
45
+ end
46
+ rescue NotACookbookError
47
+ puts 'The path is not a cookbook path'.red
48
+ rescue UnsupportedReportFormatError
49
+ puts "The report format #{options[:format]} is not supported".red
50
+ end
51
+ end
52
+ end
53
+ end
@@ -0,0 +1,101 @@
1
+ #
2
+ # Copyright (c) 2013 Stefano Tortarolo <stefano.tortarolo@gmail.com>
3
+ #
4
+ # MIT License
5
+ #
6
+ # Permission is hereby granted, free of charge, to any person obtaining
7
+ # a copy of this software and associated documentation files (the
8
+ # "Software"), to deal in the Software without restriction, including
9
+ # without limitation the rights to use, copy, modify, merge, publish,
10
+ # distribute, sublicense, and/or sell copies of the Software, and to
11
+ # permit persons to whom the Software is furnished to do so, subject to
12
+ # the following conditions:
13
+ #
14
+ # The above copyright notice and this permission notice shall be
15
+ # included in all copies or substantial portions of the Software.
16
+ #
17
+ # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
18
+ # EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
19
+ # MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
20
+ # NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
21
+ # LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
22
+ # OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
23
+ # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
24
+ #
25
+
26
+ module KitchenInspector
27
+ module Inspector
28
+ # The class that contains information about a dependent cookbook
29
+ class Dependency
30
+ # The name of the dependency
31
+ attr_reader :name
32
+
33
+ # The requirement for the dependency
34
+ attr_reader :requirement
35
+
36
+ # The version of cookbook used after applying the version constraint
37
+ attr_accessor :version_used
38
+
39
+ # The versions available on Chef Server
40
+ attr_accessor :chef_versions
41
+
42
+ # The latest version available on Chef Server
43
+ attr_accessor :latest_chef
44
+
45
+ # The versions available on Gitlab
46
+ attr_accessor :gitlab_versions
47
+
48
+ # The latest version available on Gitlab
49
+ attr_accessor :latest_gitlab
50
+
51
+ # The status of the dependency
52
+ attr_accessor :status
53
+
54
+ # The status of Gitlab
55
+ attr_accessor :gitlab_status
56
+
57
+ # The status of Chef Server
58
+ attr_accessor :chef_status
59
+
60
+ # The source URL for a cookbook
61
+ attr_accessor :source_url
62
+
63
+ # The changelog link for the dependency if available
64
+ attr_accessor :changelog
65
+
66
+ # Remarks field
67
+ attr_accessor :remarks
68
+
69
+ def initialize(name, requirement)
70
+ @name = name
71
+ @requirement = requirement
72
+ @version_used = nil
73
+ @chef_versions = []
74
+ @latest_chef = nil
75
+ @gitlab_versions = []
76
+ @latest_gitlab = nil
77
+ @status = nil
78
+ @gitlab_status = nil
79
+ @chef_status = nil
80
+ @source_url = nil
81
+ @remarks = []
82
+ end
83
+
84
+ def to_hash
85
+ {}.tap do |hash|
86
+ hash[:requirement] = requirement
87
+ hash[:used] = version_used
88
+ hash[:chef_versions] = chef_versions
89
+ hash[:latest_chef] = latest_chef
90
+ hash[:gitlab_versions] = gitlab_versions
91
+ hash[:latest_gitlab] = latest_gitlab
92
+ hash[:status] = status
93
+ hash[:gitlab_status] = gitlab_status
94
+ hash[:chef_status] = chef_status
95
+ hash[:source_url] = source_url
96
+ hash[:remarks] = remarks
97
+ end
98
+ end
99
+ end
100
+ end
101
+ end
@@ -0,0 +1,150 @@
1
+ #
2
+ # Copyright (c) 2013 Stefano Tortarolo <stefano.tortarolo@gmail.com>
3
+ #
4
+ # MIT License
5
+ #
6
+ # Permission is hereby granted, free of charge, to any person obtaining
7
+ # a copy of this software and associated documentation files (the
8
+ # "Software"), to deal in the Software without restriction, including
9
+ # without limitation the rights to use, copy, modify, merge, publish,
10
+ # distribute, sublicense, and/or sell copies of the Software, and to
11
+ # permit persons to whom the Software is furnished to do so, subject to
12
+ # the following conditions:
13
+ #
14
+ # The above copyright notice and this permission notice shall be
15
+ # included in all copies or substantial portions of the Software.
16
+ #
17
+ # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
18
+ # EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
19
+ # MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
20
+ # NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
21
+ # LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
22
+ # OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
23
+ # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
24
+ #
25
+
26
+ module KitchenInspector
27
+ module Inspector
28
+ class DependencyInspector
29
+ REPO_PER_PAGE = 1000
30
+ GITLAB_BASE_URL = ENV['GITLAB_URL']
31
+ GITLAB_API_URL = "#{GITLAB_BASE_URL}/api/v3"
32
+ CHEF_SERVER_URL = ENV['CHEF_SERVER_URL']
33
+ CHEF_USERNAME = ENV['CHEF_USERNAME']
34
+ CHEF_CLIENT_PEM = ENV['CHEF_CLIENT_PEM']
35
+ GITLAB_TOKEN = ENV['GITLAB_TOKEN']
36
+
37
+ raise GitlabAccessNotConfiguredError, "Gitlab URL not configured. Please set it in ENV['GITLAB_URL']" unless GITLAB_BASE_URL
38
+ raise GitlabAccessNotConfiguredError, "Private Token not configured. Please set it in ENV['GITLAB_TOKEN']" unless GITLAB_TOKEN
39
+
40
+ raise ChefAccessNotConfiguredError, "Please set ENV['CHEF_SERVER_URL']" unless CHEF_SERVER_URL
41
+ raise ChefAccessNotConfiguredError, "Please set ENV['CHEF_USERNAME']" unless CHEF_USERNAME
42
+ raise ChefAccessNotConfiguredError, "Please set ENV['CHEF_CLIENT_PEM']" unless CHEF_CLIENT_PEM
43
+
44
+ Gitlab.configure do |config|
45
+ config.endpoint = GITLAB_API_URL
46
+ config.private_token = GITLAB_TOKEN
47
+ config.user_agent = 'Kitchen Inspector'
48
+ end
49
+
50
+ def self.investigate(path)
51
+ raise NotACookbookError, 'Path is not a cookbook' unless File.exists?(File.join(path, 'metadata.rb'))
52
+ ridley = Ridley::Chef::Cookbook::Metadata.from_file(File.join(path, 'metadata.rb'))
53
+ dependencies =
54
+ ridley.dependencies.map do |name, version|
55
+ Dependency.new(name, version)
56
+ end
57
+ populate_fields(dependencies)
58
+ end
59
+
60
+ def self.populate_fields(dependencies)
61
+ projects = Gitlab.projects(:per_page => REPO_PER_PAGE)
62
+
63
+ dependencies.each do |dependency|
64
+ # Skip cookbooks that are not available on Gitlab.
65
+ project = projects.select do |pr|
66
+ pr.instance_variable_get("@data")["path"] == "#{dependency.name}"
67
+ end
68
+
69
+ next unless project
70
+
71
+ raise DuplicateCookbookError, "Found two versions for #{dependency.name} on Gitlab." if project.size > 1
72
+ project = project.first
73
+
74
+ dependency.gitlab_versions = find_gitlab_versions(project)
75
+ dependency.chef_versions = find_chef_server_versions(project.path)
76
+ dependency.version_used = satisfy(dependency.requirement, dependency.chef_versions)
77
+ dependency.source_url = "#{GITLAB_BASE_URL}/#{project.path_with_namespace}"
78
+
79
+ update_status(dependency)
80
+ end
81
+ end
82
+
83
+ def self.satisfy(constraint, versions)
84
+ Solve::Solver.satisfy_best(constraint, versions).to_s
85
+ rescue Solve::Errors::NoSolutionError
86
+ nil
87
+ end
88
+
89
+ # Updates the status of the dependency based on the version used and the latest version available on Gitlab
90
+ def self.update_status(dependency)
91
+ dependency.latest_chef = get_latest_version(dependency.chef_versions)
92
+ dependency.latest_gitlab = get_latest_version(dependency.gitlab_versions)
93
+
94
+ dependency.status = 'up-to-date'
95
+ dependency.chef_status = 'up-to-date'
96
+ dependency.gitlab_status = 'up-to-date'
97
+
98
+ if !dependency.version_used
99
+ dependency.status = 'error'
100
+ dependency.remarks << 'No versions found'
101
+ else
102
+ relaxed_version = satisfy("~> #{dependency.version_used}", dependency.chef_versions)
103
+ if relaxed_version != dependency.version_used
104
+ dependency.status = 'warning-req'
105
+ dependency.remarks << "#{relaxed_version} is available"
106
+ end
107
+ end
108
+
109
+ if dependency.latest_chef && dependency.latest_gitlab
110
+ if dependency.latest_chef > dependency.latest_gitlab
111
+ dependency.chef_status = 'up-to-date'
112
+ dependency.gitlab_status = 'warning-gitlab'
113
+ dependency.remarks << "Gitlab out-of-date!"
114
+ elsif dependency.latest_chef < dependency.latest_gitlab
115
+ dependency.chef_status = 'warning-chef'
116
+ dependency.gitlab_status = 'up-to-date'
117
+ dependency.remarks << "A new version might appear on Chef server"
118
+ end
119
+ else
120
+ dependency.gitlab_status = 'warning-gitlab' unless dependency.latest_gitlab
121
+ dependency.chef_status = 'warning-chef' unless dependency.latest_chef
122
+ end
123
+ end
124
+
125
+ def self.find_chef_server_versions(project)
126
+ rest = Chef::REST.new(CHEF_SERVER_URL, CHEF_USERNAME, CHEF_CLIENT_PEM)
127
+ cookbook = rest.get("cookbooks/#{project}")
128
+ versions = []
129
+ versions = cookbook[project]["versions"].collect{|c| fix_version_name(c["version"])} if cookbook
130
+ versions
131
+ rescue Net::HTTPServerException
132
+ []
133
+ end
134
+
135
+ def self.find_gitlab_versions(project)
136
+ Gitlab.tags(project.id).collect do |t|
137
+ fix_version_name(t.instance_variable_get("@data")["name"])
138
+ end
139
+ end
140
+
141
+ def self.fix_version_name(version)
142
+ version.gsub(/[v][\.]*/i, "")
143
+ end
144
+
145
+ def self.get_latest_version(versions)
146
+ versions.collect{|v| Solve::Version.new(v)}.max
147
+ end
148
+ end
149
+ end
150
+ end
@@ -0,0 +1,34 @@
1
+ #
2
+ # Copyright (c) 2013 Stefano Tortarolo <stefano.tortarolo@gmail.com>
3
+ #
4
+ # MIT License
5
+ #
6
+ # Permission is hereby granted, free of charge, to any person obtaining
7
+ # a copy of this software and associated documentation files (the
8
+ # "Software"), to deal in the Software without restriction, including
9
+ # without limitation the rights to use, copy, modify, merge, publish,
10
+ # distribute, sublicense, and/or sell copies of the Software, and to
11
+ # permit persons to whom the Software is furnished to do so, subject to
12
+ # the following conditions:
13
+ #
14
+ # The above copyright notice and this permission notice shall be
15
+ # included in all copies or substantial portions of the Software.
16
+ #
17
+ # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
18
+ # EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
19
+ # MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
20
+ # NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
21
+ # LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
22
+ # OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
23
+ # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
24
+ #
25
+
26
+ module KitchenInspector
27
+ module Inspector
28
+ class GitlabAccessNotConfiguredError < StandardError; end
29
+ class ChefAccessNotConfiguredError < StandardError; end
30
+ class NotACookbookError < StandardError; end
31
+ class DuplicateCookbookError < StandardError; end
32
+ class UnsupportedReportFormatError < ArgumentError; end
33
+ end
34
+ end
@@ -0,0 +1,148 @@
1
+ #
2
+ # Copyright (c) 2013 Stefano Tortarolo <stefano.tortarolo@gmail.com>
3
+ #
4
+ # MIT License
5
+ #
6
+ # Permission is hereby granted, free of charge, to any person obtaining
7
+ # a copy of this software and associated documentation files (the
8
+ # "Software"), to deal in the Software without restriction, including
9
+ # without limitation the rights to use, copy, modify, merge, publish,
10
+ # distribute, sublicense, and/or sell copies of the Software, and to
11
+ # permit persons to whom the Software is furnished to do so, subject to
12
+ # the following conditions:
13
+ #
14
+ # The above copyright notice and this permission notice shall be
15
+ # included in all copies or substantial portions of the Software.
16
+ #
17
+ # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
18
+ # EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
19
+ # MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
20
+ # NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
21
+ # LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
22
+ # OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
23
+ # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
24
+ #
25
+
26
+ module KitchenInspector
27
+ module Inspector
28
+ # The ASCII code for tick mark symbol
29
+ TICK_MARK = "\u2714"
30
+ # The ASCII code for X mark symbol
31
+ X_MARK = "\u2716"
32
+ # The ! symbol
33
+ ESCLAMATION_MARK = "!"
34
+
35
+ class Report
36
+ class << self
37
+ # Generates the status of dependent cookbooks in specified format
38
+ #
39
+ # @param dependencies [Array<Dependency>] list of cookbook dependency objects
40
+ # @param format [String] the format used for Report
41
+ #
42
+ def generate(dependencies, format)
43
+ case format
44
+ when 'table'
45
+ TableReport.generate(dependencies)
46
+ when'json'
47
+ JSONReport.generate(dependencies)
48
+ else
49
+ raise UnsupportedReportFormatError, "Report format '#{format}' is not supported"
50
+ end
51
+ end
52
+ end
53
+ end
54
+
55
+ # Reports the cookbook dependency status in a table format
56
+ #
57
+ class TableReport
58
+ class << self
59
+ # Generates the status of dependent cookbooks as a table
60
+ #
61
+ # @param dependencies [Array<Dependency>] list of cookbook dependency objects
62
+ #
63
+ def generate(dependencies)
64
+ rows = []
65
+ headings = ["Name", "Requirement", "Used", "Latest\nChef", "Latest\nGitlab", "Requirement\nStatus",
66
+ "Chef Server\nStatus", "Gitlab\nStatus", "Remarks"]
67
+ dependencies.each do |dependency|
68
+ status = status_to_mark(dependency.status)
69
+ chef_status = status_to_mark(dependency.chef_status)
70
+ gitlab_status = status_to_mark(dependency.gitlab_status)
71
+
72
+ name = dependency.name.dup
73
+ name = name.red if dependency.status == 'error'
74
+
75
+ rows << [
76
+ name,
77
+ dependency.requirement,
78
+ dependency.version_used,
79
+ dependency.latest_chef,
80
+ dependency.latest_gitlab,
81
+ { value: status, alignment: :center },
82
+ { value: chef_status, alignment: :center },
83
+ { value: gitlab_status, alignment: :center },
84
+ dependency.remarks.join(', ')
85
+ ]
86
+ end
87
+
88
+ # Show Table
89
+ table = Terminal::Table.new headings: headings, rows: rows
90
+
91
+ # Show Status
92
+ if dependencies.any? { |dep| dep.status == 'error' }
93
+ status = "Status: error (#{X_MARK})".red
94
+ elsif dependencies.any? { |dep| dep.status == 'warning-req' }
95
+ status = "Status: warning-req (#{ESCLAMATION_MARK})".yellow
96
+ elsif dependencies.any? { |dep| dep.status == 'warning-gitlab' }
97
+ status = "Status: warning-gitlab (#{ESCLAMATION_MARK})".yellow
98
+ elsif dependencies.any? { |dep| dep.status == 'warning-chef' }
99
+ status = "Status: warning-chef (#{ESCLAMATION_MARK})".yellow
100
+ else
101
+ status = "Status: up-to-date (#{TICK_MARK})".green
102
+ end
103
+
104
+ "#{table}\n#{status}"
105
+ end
106
+
107
+ # Given a status return a mark
108
+ def status_to_mark(status)
109
+ case status
110
+ when 'up-to-date'
111
+ return TICK_MARK.green
112
+ when 'error'
113
+ return X_MARK.red
114
+ when /warning-req/
115
+ return ESCLAMATION_MARK.bold.yellow
116
+ when /warning-chef/
117
+ return "i".bold.blue
118
+ when /warning-gitlab/
119
+ return (ESCLAMATION_MARK * 2).bold.light_red
120
+ else
121
+ return ''.white
122
+ end
123
+ end
124
+ end
125
+ end
126
+
127
+ # Return Kitchen's status in JSON format
128
+ class JSONReport
129
+ class << self
130
+ def generate(dependencies)
131
+ JSON.pretty_generate(dependencies_hash(dependencies))
132
+ end
133
+
134
+ # Converts the dependency objects to JSON object
135
+ #
136
+ # @param dependencies [Array<Dependency>] list of cookbook dependency objects
137
+ #
138
+ def dependencies_hash(dependencies)
139
+ {}.tap do |hash|
140
+ dependencies.each do |dependency|
141
+ hash[dependency.name] = dependency.to_hash
142
+ end
143
+ end
144
+ end
145
+ end
146
+ end
147
+ end
148
+ end
@@ -0,0 +1,30 @@
1
+ #
2
+ # Copyright (c) 2013 Stefano Tortarolo <stefano.tortarolo@gmail.com>
3
+ #
4
+ # MIT License
5
+ #
6
+ # Permission is hereby granted, free of charge, to any person obtaining
7
+ # a copy of this software and associated documentation files (the
8
+ # "Software"), to deal in the Software without restriction, including
9
+ # without limitation the rights to use, copy, modify, merge, publish,
10
+ # distribute, sublicense, and/or sell copies of the Software, and to
11
+ # permit persons to whom the Software is furnished to do so, subject to
12
+ # the following conditions:
13
+ #
14
+ # The above copyright notice and this permission notice shall be
15
+ # included in all copies or substantial portions of the Software.
16
+ #
17
+ # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
18
+ # EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
19
+ # MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
20
+ # NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
21
+ # LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
22
+ # OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
23
+ # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
24
+ #
25
+ module KitchenInspector
26
+ module Inspector
27
+ # The version string
28
+ VERSION = '1.0.0'
29
+ end
30
+ end
metadata ADDED
@@ -0,0 +1,202 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: kitchen-inspector
3
+ version: !ruby/object:Gem::Version
4
+ version: 1.0.0
5
+ platform: ruby
6
+ authors:
7
+ - Stefano Tortarolo
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2013-11-15 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: bundler
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - ~>
18
+ - !ruby/object:Gem::Version
19
+ version: '1.3'
20
+ type: :development
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - ~>
25
+ - !ruby/object:Gem::Version
26
+ version: '1.3'
27
+ - !ruby/object:Gem::Dependency
28
+ name: rubocop
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - ~>
32
+ - !ruby/object:Gem::Version
33
+ version: '0.14'
34
+ type: :development
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - ~>
39
+ - !ruby/object:Gem::Version
40
+ version: '0.14'
41
+ - !ruby/object:Gem::Dependency
42
+ name: rake
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - '>='
46
+ - !ruby/object:Gem::Version
47
+ version: '0'
48
+ type: :development
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: solve
57
+ requirement: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - ~>
60
+ - !ruby/object:Gem::Version
61
+ version: 0.8.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.8.0
69
+ - !ruby/object:Gem::Dependency
70
+ name: berkshelf
71
+ requirement: !ruby/object:Gem::Requirement
72
+ requirements:
73
+ - - ~>
74
+ - !ruby/object:Gem::Version
75
+ version: 2.0.10
76
+ type: :runtime
77
+ prerelease: false
78
+ version_requirements: !ruby/object:Gem::Requirement
79
+ requirements:
80
+ - - ~>
81
+ - !ruby/object:Gem::Version
82
+ version: 2.0.10
83
+ - !ruby/object:Gem::Dependency
84
+ name: thor
85
+ requirement: !ruby/object:Gem::Requirement
86
+ requirements:
87
+ - - ~>
88
+ - !ruby/object:Gem::Version
89
+ version: 0.18.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.18.0
97
+ - !ruby/object:Gem::Dependency
98
+ name: terminal-table
99
+ requirement: !ruby/object:Gem::Requirement
100
+ requirements:
101
+ - - ~>
102
+ - !ruby/object:Gem::Version
103
+ version: 1.4.5
104
+ type: :runtime
105
+ prerelease: false
106
+ version_requirements: !ruby/object:Gem::Requirement
107
+ requirements:
108
+ - - ~>
109
+ - !ruby/object:Gem::Version
110
+ version: 1.4.5
111
+ - !ruby/object:Gem::Dependency
112
+ name: colorize
113
+ requirement: !ruby/object:Gem::Requirement
114
+ requirements:
115
+ - - ~>
116
+ - !ruby/object:Gem::Version
117
+ version: 0.6.0
118
+ type: :runtime
119
+ prerelease: false
120
+ version_requirements: !ruby/object:Gem::Requirement
121
+ requirements:
122
+ - - ~>
123
+ - !ruby/object:Gem::Version
124
+ version: 0.6.0
125
+ - !ruby/object:Gem::Dependency
126
+ name: gitlab
127
+ requirement: !ruby/object:Gem::Requirement
128
+ requirements:
129
+ - - '>='
130
+ - !ruby/object:Gem::Version
131
+ version: '0'
132
+ type: :runtime
133
+ prerelease: false
134
+ version_requirements: !ruby/object:Gem::Requirement
135
+ requirements:
136
+ - - '>='
137
+ - !ruby/object:Gem::Version
138
+ version: '0'
139
+ - !ruby/object:Gem::Dependency
140
+ name: chef
141
+ requirement: !ruby/object:Gem::Requirement
142
+ requirements:
143
+ - - '>='
144
+ - !ruby/object:Gem::Version
145
+ version: 11.0.0
146
+ type: :runtime
147
+ prerelease: false
148
+ version_requirements: !ruby/object:Gem::Requirement
149
+ requirements:
150
+ - - '>='
151
+ - !ruby/object:Gem::Version
152
+ version: 11.0.0
153
+ description: This gem verifies that dependencies are updated in regard with a Chef
154
+ Server and Gitlab
155
+ email:
156
+ - stefano.tortarolo@gmail.com
157
+ executables:
158
+ - kitchen-inspector
159
+ extensions: []
160
+ extra_rdoc_files: []
161
+ files:
162
+ - .gitignore
163
+ - Gemfile
164
+ - INFO.md
165
+ - LICENSE.txt
166
+ - README.md
167
+ - Rakefile
168
+ - bin/kitchen-inspector
169
+ - info.css
170
+ - kitchen-inspector.gemspec
171
+ - lib/kitchen-inspector/inspector.rb
172
+ - lib/kitchen-inspector/inspector/cli.rb
173
+ - lib/kitchen-inspector/inspector/dependency.rb
174
+ - lib/kitchen-inspector/inspector/dependency_inspector.rb
175
+ - lib/kitchen-inspector/inspector/error.rb
176
+ - lib/kitchen-inspector/inspector/report.rb
177
+ - lib/kitchen-inspector/inspector/version.rb
178
+ homepage: https://github.com/astratto/kitchen-inspector
179
+ licenses:
180
+ - MIT
181
+ metadata: {}
182
+ post_install_message:
183
+ rdoc_options: []
184
+ require_paths:
185
+ - lib
186
+ required_ruby_version: !ruby/object:Gem::Requirement
187
+ requirements:
188
+ - - '>='
189
+ - !ruby/object:Gem::Version
190
+ version: '0'
191
+ required_rubygems_version: !ruby/object:Gem::Requirement
192
+ requirements:
193
+ - - '>='
194
+ - !ruby/object:Gem::Version
195
+ version: '0'
196
+ requirements: []
197
+ rubyforge_project:
198
+ rubygems_version: 2.1.11
199
+ signing_key:
200
+ specification_version: 4
201
+ summary: Chef server and Gitlab dependency checker
202
+ test_files: []