Class: KitchenInspector::Inspector::HealthBureau

Inherits:
Object
  • Object
show all
Includes:
Utils
Defined in:
lib/kitchen-inspector/inspector/health_bureau.rb

Overview

Main class that, starting from a cookbook, analyzes its dependencies using its “inspectors” and returns a collection of analyzed dependencies

Instance Attribute Summary collapse

Instance Method Summary collapse

Methods included from Utils

#config_msg, #eval_metadata, #fix_version_name, #get_latest_version, #read_config, #satisfy

Constructor Details

#initialize(config) ⇒ HealthBureau

Returns a new instance of HealthBureau.

Raises:



35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
# File 'lib/kitchen-inspector/inspector/health_bureau.rb', line 35

def initialize(config)
  configuration = read_config(config)

  begin
    self.instance_eval configuration
  rescue NoMethodError => e
    raise ConfigurationError, "Unsupported configuration: #{e.name}."
  end

  raise ConfigurationError, "Chef Server is not configured properly, " \
                            "please check your 'chef_server' configuration." unless validate_chef_inspector

  raise ConfigurationError, "Repository Manager is not configured properly, " \
                            "please check your 'repository_manager' configuration." unless @repo_inspector
end

Instance Attribute Details

#chef_inspectorObject (readonly)

Returns the value of attribute chef_inspector.



33
34
35
# File 'lib/kitchen-inspector/inspector/health_bureau.rb', line 33

def chef_inspector
  @chef_inspector
end

#repo_inspectorObject (readonly)

Returns the value of attribute repo_inspector.



33
34
35
# File 'lib/kitchen-inspector/inspector/health_bureau.rb', line 33

def repo_inspector
  @repo_inspector
end

Instance Method Details

#analyze_dependency(dependency, recursive) ⇒ Array<Dependency>

Analyze Chef repo and Repository manager in order to find more information about a given dependency

Parameters:

  • dependency (Dependency)

    dependency to be analyzed

  • recursive (Boolean)

    whether transitive dependencies should be analyzed

Returns:

  • (Array<Dependency>)

    analyzed dependency and its transitive dependencies



73
74
75
76
77
78
79
80
81
82
83
84
# File 'lib/kitchen-inspector/inspector/health_bureau.rb', line 73

def analyze_dependency(dependency, recursive)
  chef_info = @chef_inspector.investigate(dependency)

  # Grab information from the Repository Manager
  info_repo = @repo_inspector.investigate(dependency, chef_info[:version_used], recursive)
  deps = info_repo.collect do |dep, repo_info|
    dep_chef_info = @chef_inspector.investigate(dep)
    update_dependency(dep, dep_chef_info, repo_info)
    dep
  end
  deps
end

#chef_server(config) ⇒ Object

Initialize the Chef Server configuration



177
178
179
# File 'lib/kitchen-inspector/inspector/health_bureau.rb', line 177

def chef_server(config)
  @chef_inspector = ChefInspector.new config
end

#compare_repo_chef(chef_info, repo_info) ⇒ Hash

Compare Repository Manager and Chef Server

Parameters:

  • chef_info (Hash)

    information from Chef Server

  • repo_info (Hash)

    information from Repository Manager

Returns:

  • (Hash)

    containing servers statuses and remarks



141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
# File 'lib/kitchen-inspector/inspector/health_bureau.rb', line 141

def compare_repo_chef(chef_info, repo_info)
  comparison = {:chef => :up_to_date, :repo => :up_to_date,
            :remarks => []}

  if chef_info[:latest_version] && repo_info[:latest_metadata]
    if chef_info[:latest_version] > repo_info[:latest_metadata]
      comparison[:repo] = :warn_outofdate_repo
      changelog_url = @repo_inspector.get_changelog(repo_info,
                                    repo_info[:latest_metadata].to_s,
                                    chef_info[:latest_version].to_s)
      comparison[:remarks] << "#{@repo_inspector.manager.type} out-of-date! #{changelog_url}"
      return comparison
    elsif chef_info[:latest_version] < repo_info[:latest_metadata]
      comparison[:chef] = :warn_chef
      changelog_url = @repo_inspector.get_changelog(repo_info,
                                    chef_info[:latest_version].to_s,
                                    repo_info[:latest_metadata].to_s)
      comparison[:remarks] << "A new version might appear on Chef server. #{changelog_url}"
      return comparison
    end
  end

  unless repo_info[:latest_metadata]
    comparison[:repo] = :err_repo
    comparison[:remarks] << "#{@repo_inspector.manager.type} doesn't contain any versions."
  end

  unless chef_info[:latest_version]
    comparison[:chef] = :err_chef
    comparison[:remarks] << "Chef Server doesn't contain any versions."
  end

  comparison
end

#investigate(path, recursive = true) ⇒ Array<Dependency>

Inspect your kitchen!

If recursive is specified, dependencies’ metadata are downloaded and recursively analyzed

Parameters:

  • path (String)

    path to the cookbook to be analyzed

  • recursive (Boolean) (defaults to: true)

    whether transitive dependencies should be analyzed

Returns:

  • (Array<Dependency>)

    analyzed dependency and its transitive dependencies

Raises:



58
59
60
61
62
63
64
65
# File 'lib/kitchen-inspector/inspector/health_bureau.rb', line 58

def investigate(path, recursive=true)
  raise NotACookbookError, 'Path is not a cookbook' unless File.exists?(File.join(path, 'metadata.rb'))

   = Ridley::Chef::Cookbook::Metadata.from_file(File.join(path, 'metadata.rb'))
  .dependencies.collect do |name, version|
    analyze_dependency(Models::Dependency.new(name, version), recursive)
  end.flatten
end

#repository_manager(config) ⇒ Object

Initialize the Repository Manager



182
183
184
# File 'lib/kitchen-inspector/inspector/health_bureau.rb', line 182

def repository_manager(config)
  @repo_inspector = RepositoryInspector.new config
end

#update_dependency(dependency, chef_info, repo_info) ⇒ Object

Update in-place a dependency based on information retrieved from Chef Server and Repository Manager

Parameters:

  • dependency (Dependency)

    dependency to be updated

  • chef_info (Hash)

    information from Chef Server

  • repo_info (Hash)

    information from Repository Manager



92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
# File 'lib/kitchen-inspector/inspector/health_bureau.rb', line 92

def update_dependency(dependency, chef_info, repo_info)
  dependency.status = :up_to_date

  if !chef_info[:version_used]
    dependency.status = :err_req
    msg = 'No versions found'
    reference_version = @repo_inspector.get_reference_version(nil, repo_info)
    msg << ", using #{reference_version} for recursive analysis" if reference_version

    dependency.remarks << msg
  else
    relaxed_version = satisfy("~> #{chef_info[:version_used]}", chef_info[:versions])
    if relaxed_version != chef_info[:version_used]
      dependency.status = :warn_req
      changelog_url = @repo_inspector.get_changelog(repo_info,
                                    chef_info[:version_used],
                                    relaxed_version)
      dependency.remarks << "#{relaxed_version} is available. #{changelog_url}"
    end
  end

  # Compare Chef and Repository Manager versions
  comparison = compare_repo_chef(chef_info, repo_info)
  chef_info[:status] = comparison[:chef]
  repo_info[:status] = comparison[:repo]
  dependency.remarks.push(*comparison[:remarks]) if comparison[:remarks]

  if repo_info[:not_unique]
    repo_info[:status] = :warn_notunique_repo
    dependency.remarks << "Not unique on #{@repo_inspector.manager.type} (this is #{repo_info[:source_url]})"
  end

  # Check whether latest tag and metadata version in Repository Manager are
  # consistent
  unless @repo_inspector.consistent_version?(repo_info)
    repo_info[:status] = :warn_mismatch_repo
    dependency.remarks << "#{@repo_inspector.manager.type}'s last tag is #{repo_info[:latest_tag]} " \
                            "but found #{repo_info[:latest_metadata]} in metadata.rb"
  end

  dependency.repomanager = repo_info
  dependency.chef = chef_info
end

#validate_chef_inspectorChefInspector

Initialize a Chef Inspector using knife.rb settings if not already initialized

Returns:



190
191
192
193
194
195
196
197
198
199
200
201
202
# File 'lib/kitchen-inspector/inspector/health_bureau.rb', line 190

def validate_chef_inspector
  @chef_inspector ||= begin
    # Fallback to knife.rb if possible
    knife_cfg = "#{Dir.home}/.chef/knife.rb"
    if File.exists?(knife_cfg)
      Chef::Config.from_file knife_cfg
      chef_server({ :username => Chef::Config.node_name,
                    :url => Chef::Config.chef_server_url,
                    :client_pem => Chef::Config.client_key
                  })
    end
  end
end