Class: Chef::Cookbook::SyntaxCheck

Inherits:
Object
  • Object
show all
Includes:
Mixin::ShellOut
Defined in:
lib/chef/cookbook/syntax_check.rb

Overview

Chef::Cookbook::SyntaxCheck

Encapsulates the process of validating the ruby syntax of files in Chef cookbooks.

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Methods included from Mixin::ShellOut

#shell_out, #shell_out!

Constructor Details

#initialize(cookbook_path) ⇒ SyntaxCheck

Create a new SyntaxCheck object

Arguments

cookbook_path:

the (on disk) path to the cookbook



45
46
47
# File 'lib/chef/cookbook/syntax_check.rb', line 45

def initialize(cookbook_path)
  @cookbook_path = cookbook_path
end

Instance Attribute Details

#cookbook_pathObject (readonly)

Returns the value of attribute cookbook_path.



30
31
32
# File 'lib/chef/cookbook/syntax_check.rb', line 30

def cookbook_path
  @cookbook_path
end

Class Method Details

.for_cookbook(cookbook_name, cookbook_path = nil) ⇒ Object

Creates a new SyntaxCheck given the cookbook_name and a cookbook_path. If no cookbook_path is given, Chef::Config.cookbook_path is used.



34
35
36
37
38
39
40
# File 'lib/chef/cookbook/syntax_check.rb', line 34

def self.for_cookbook(cookbook_name, cookbook_path=nil)
  cookbook_path ||= Chef::Config.cookbook_path
  unless cookbook_path
    raise ArgumentError, "Cannot find cookbook #{cookbook_name} unless Chef::Config.cookbook_path is set or an explicit cookbook path is given"
  end
  new(File.join(cookbook_path, cookbook_name.to_s))
end

Instance Method Details

#cacheObject



49
50
51
# File 'lib/chef/cookbook/syntax_check.rb', line 49

def cache
  Chef::ChecksumCache.instance
end

#cache_key(file) ⇒ Object



91
92
93
94
# File 'lib/chef/cookbook/syntax_check.rb', line 91

def cache_key(file)
  @cache_keys ||= {}
  @cache_keys[file] ||= cache.generate_key(file, "chef-test")
end

#ruby_filesObject



53
54
55
# File 'lib/chef/cookbook/syntax_check.rb', line 53

def ruby_files
  Dir[File.join(cookbook_path, '**', '*.rb')]
end

#template_filesObject



68
69
70
# File 'lib/chef/cookbook/syntax_check.rb', line 68

def template_files
  Dir[File.join(cookbook_path, '**', '*.erb')]
end

#untested_ruby_filesObject



57
58
59
60
61
62
63
64
65
66
# File 'lib/chef/cookbook/syntax_check.rb', line 57

def untested_ruby_files
  ruby_files.reject do |file|
    if validated?(file)
      Chef::Log.debug("Ruby file #{file} is unchanged, skipping syntax check")
      true
    else
      false
    end
  end
end

#untested_template_filesObject



72
73
74
75
76
77
78
79
80
81
# File 'lib/chef/cookbook/syntax_check.rb', line 72

def untested_template_files
  template_files.reject do |file| 
    if validated?(file)
      Chef::Log.debug("Template #{file} is unchanged, skipping syntax check")
      true
    else
      false
    end
  end
end

#validate_ruby_file(ruby_file) ⇒ Object



122
123
124
125
126
127
128
129
130
131
132
# File 'lib/chef/cookbook/syntax_check.rb', line 122

def validate_ruby_file(ruby_file)
  Chef::Log.debug("Testing #{ruby_file} for syntax errors...")
  result = shell_out("ruby -c #{ruby_file}")
  result.error!
  true
rescue Chef::Exceptions::ShellCommandFailed
  file_relative_path = ruby_file[/^#{Regexp.escape(cookbook_path+File::Separator)}(.*)/, 1]
  Chef::Log.fatal("Cookbook file #{file_relative_path} has a ruby syntax error:")
  result.stderr.each_line { |l| Chef::Log.fatal(l.chomp) }
  false
end

#validate_ruby_filesObject



96
97
98
99
100
101
# File 'lib/chef/cookbook/syntax_check.rb', line 96

def validate_ruby_files
  untested_ruby_files.each do |ruby_file|
    return false unless validate_ruby_file(ruby_file)
    validated(ruby_file)
  end
end

#validate_template(erb_file) ⇒ Object



110
111
112
113
114
115
116
117
118
119
120
# File 'lib/chef/cookbook/syntax_check.rb', line 110

def validate_template(erb_file)
  Chef::Log.debug("Testing template #{erb_file} for syntax errors...")
  result = shell_out("sh -c 'erubis -x #{erb_file} | ruby -c'")
  result.error!
  true
rescue Chef::Exceptions::ShellCommandFailed
  file_relative_path = erb_file[/^#{Regexp.escape(cookbook_path+File::Separator)}(.*)/, 1]
  Chef::Log.fatal("Erb template #{file_relative_path} has a syntax error:")
  result.stderr.each_line { |l| Chef::Log.fatal(l.chomp) }
  false
end

#validate_templatesObject



103
104
105
106
107
108
# File 'lib/chef/cookbook/syntax_check.rb', line 103

def validate_templates
  untested_template_files.each do |template|
    return false unless validate_template(template)
    validated(template)
  end
end

#validated(file) ⇒ Object



87
88
89
# File 'lib/chef/cookbook/syntax_check.rb', line 87

def validated(file)
  cache.generate_checksum(cache_key(file), file, File.stat(file))
end

#validated?(file) ⇒ Boolean

Returns:

  • (Boolean)


83
84
85
# File 'lib/chef/cookbook/syntax_check.rb', line 83

def validated?(file)
  !!cache.lookup_checksum(cache_key(file), File.stat(file))
end