Class: Ridley::Chef::Cookbook

Inherits:
Object
  • Object
show all
Extended by:
Forwardable
Defined in:
lib/ridley/chef/cookbook.rb,
lib/ridley/chef/cookbook/metadata.rb,
lib/ridley/chef/cookbook/syntax_check.rb

Defined Under Namespace

Classes: Metadata, MinimalMetadata, SyntaxCheck

Constant Summary collapse

CHEF_TYPE =
"cookbook_version".freeze
CHEF_JSON_CLASS =
"Chef::CookbookVersion".freeze

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(name, path, metadata) ⇒ Cookbook

Returns a new instance of Cookbook.



83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
# File 'lib/ridley/chef/cookbook.rb', line 83

def initialize(name, path, )
  @cookbook_name = name
  @path          = Pathname.new(path)
  @metadata      = 
  @files         = Array.new
  @manifest      = Hashie::Mash.new(
    recipes: Array.new,
    definitions: Array.new,
    libraries: Array.new,
    attributes: Array.new,
    files: Array.new,
    templates: Array.new,
    resources: Array.new,
    providers: Array.new,
    root_files: Array.new
  )
  @frozen        = false
  @chefignore    = Ridley::Chef::Chefignore.new(@path) rescue nil

  load_files
end

Instance Attribute Details

#cookbook_nameObject (readonly)

Returns the value of attribute cookbook_name.



54
55
56
# File 'lib/ridley/chef/cookbook.rb', line 54

def cookbook_name
  @cookbook_name
end

#frozenBoolean

Returns:

  • (Boolean)


79
80
81
# File 'lib/ridley/chef/cookbook.rb', line 79

def frozen
  @frozen
end

#manifestHashie::Mash (readonly)

Returns a Hashie::Mash containing Cookbook file category names as keys and an Array of Hashes containing metadata about the files belonging to that category. This is used to communicate what a Cookbook looks like when uploading to a Chef Server.

example:

{
  :recipes => [
    {
      name: "default.rb",
      path: "recipes/default.rb",
      checksum: "fb1f925dcd5fc4ebf682c4442a21c619",
      specificity: "default"
    }
  ]
  ...
  ...
}.

Returns:

  • (Hashie::Mash)

    a Hashie::Mash containing Cookbook file category names as keys and an Array of Hashes containing metadata about the files belonging to that category. This is used to communicate what a Cookbook looks like when uploading to a Chef Server.

    example:

    {
      :recipes => [
        {
          name: "default.rb",
          path: "recipes/default.rb",
          checksum: "fb1f925dcd5fc4ebf682c4442a21c619",
          specificity: "default"
        }
      ]
      ...
      ...
    }
    


76
77
78
# File 'lib/ridley/chef/cookbook.rb', line 76

def manifest
  @manifest
end

#metadataObject (readonly)

Returns the value of attribute metadata.



56
57
58
# File 'lib/ridley/chef/cookbook.rb', line 56

def 
  @metadata
end

#pathObject (readonly)

Returns the value of attribute path.



55
56
57
# File 'lib/ridley/chef/cookbook.rb', line 55

def path
  @path
end

Class Method Details

.checksum(filepath) ⇒ String

Returns a checksum that can be used to uniquely identify the file understood by a Chef Server.

Parameters:

  • filepath (String)

    a path on disk to the location of a file to checksum

Returns:

  • (String)

    a checksum that can be used to uniquely identify the file understood by a Chef Server.



13
14
15
# File 'lib/ridley/chef/cookbook.rb', line 13

def checksum(filepath)
  Ridley::Chef::Digester.md5_checksum_for_file(filepath)
end

.from_path(path, options = {}) ⇒ Ridley::Chef::Cookbook

Creates a new instance of Ridley::Chef::Cookbook from a path on disk containing a Cookbook.

The name of the Cookbook is determined by the value of the name attribute set in the cookbooks’ metadata. If the name attribute is not present the name of the loaded cookbook is determined by directory containing the cookbook.

Parameters:

  • path (#to_s)

    a path on disk to the location of a Cookbook

  • options (Hash) (defaults to: {})

    a customizable set of options

Options Hash (options):

  • :name (String)

    explicitly supply the name of the cookbook we are loading. This is useful if you are dealing with a cookbook that does not have well-formed metadata

Returns:

Raises:

  • (IOError)

    if the path does not contain a metadata.rb or metadata.json file



34
35
36
37
38
39
40
41
42
43
44
45
46
# File 'lib/ridley/chef/cookbook.rb', line 34

def from_path(path, options = {})
  path     = Pathname.new(path)
   = if ( = path.join(Metadata::COMPILED_FILE_NAME)).exist?
    Cookbook::Metadata.from_json(File.read())
  elsif ( = path.join(Metadata::RAW_FILE_NAME)).exist?
    Cookbook::Metadata.from_file()
  else
    raise IOError, "no #{Metadata::COMPILED_FILE_NAME} or #{Metadata::RAW_FILE_NAME} found at #{path}"
  end

  .name(options[:name].presence || .name.presence || File.basename(path))
  new(.name, path, )
end

Instance Method Details

#<=>(other) ⇒ Object



230
231
232
# File 'lib/ridley/chef/cookbook.rb', line 230

def <=>(other)
  [self.cookbook_name, self.version] <=> [other.cookbook_name, other.version]
end

#checksumsHash

Returns an hash containing the checksums and expanded file paths of all of the files found in the instance of CachedCookbook

example:

{
  "da97c94bb6acb2b7900cbf951654fea3" => "/Users/reset/.ridley/nginx-0.101.2/README.md"
}.

Returns:

  • (Hash)

    an hash containing the checksums and expanded file paths of all of the files found in the instance of CachedCookbook

    example:

    {
      "da97c94bb6acb2b7900cbf951654fea3" => "/Users/reset/.ridley/nginx-0.101.2/README.md"
    }
    


113
114
115
116
117
118
119
# File 'lib/ridley/chef/cookbook.rb', line 113

def checksums
  {}.tap do |checksums|
    files.each do |file|
      checksums[self.class.checksum(file)] = file
    end
  end
end

#compile_metadata(out = self.path) ⇒ Object

Compiles the raw metadata of the cookbook and writes it to a metadata.json file at the given out path. The default out path is the directory containing the cookbook itself.

Parameters:

  • out (String) (defaults to: self.path)

    directory to output compiled metadata to



126
127
128
129
130
# File 'lib/ridley/chef/cookbook.rb', line 126

def (out = self.path)
  File.open(File.join(out, Metadata::COMPILED_FILE_NAME), "w+") do |f|
    f.write(.to_json)
  end
end

#compiled_metadata?Boolean

Returns true if the cookbook instance has a compiled metadata file and false if it does not.

Returns:

  • (Boolean)


136
137
138
# File 'lib/ridley/chef/cookbook.rb', line 136

def compiled_metadata?
  manifest[:root_files].any? { |file| file[:name].downcase == Metadata::COMPILED_FILE_NAME }
end

#file_metadata(category, target) ⇒ Hash

Returns a Hash containing a name, path, checksum, and specificity key representing the metadata about a file contained in a Cookbook. This metadata is used when uploading a Cookbook’s files to a Chef Server.

Examples:

(:root_files, "somefile.h") => {
  name: "default.rb",
  path: "recipes/default.rb",
  checksum: "fb1f925dcd5fc4ebf682c4442a21c619",
  specificity: "default"
}

Parameters:

  • category (Symbol)

    the category of file to generate metadata about

  • target (String)

    the filepath to the file to get metadata information about

Returns:

  • (Hash)

    a Hash containing a name, path, checksum, and specificity key representing the metadata about a file contained in a Cookbook. This metadata is used when uploading a Cookbook’s files to a Chef Server.



157
158
159
160
161
162
163
164
165
166
# File 'lib/ridley/chef/cookbook.rb', line 157

def (category, target)
  target = Pathname.new(target)

  {
    name: target.basename.to_s,
    path: target.relative_path_from(path).to_s,
    checksum: self.class.checksum(target),
    specificity: file_specificity(category, target)
  }
end

#file_specificity(category, target) ⇒ String

Parameters:

  • category (Symbol)
  • target (Pathname)

Returns:

  • (String)


172
173
174
175
176
177
178
179
180
# File 'lib/ridley/chef/cookbook.rb', line 172

def file_specificity(category, target)
  case category
  when :files, :templates
    relpath = target.relative_path_from(path).to_s
    relpath.slice(/(.+)\/(.+)\/.+/, 2)
  else
    'default'
  end
end

#nameString

Returns the name of the cookbook and the version number separated by a dash (-).

example:

"nginx-0.101.2".

Returns:

  • (String)

    the name of the cookbook and the version number separated by a dash (-).

    example:

    "nginx-0.101.2"
    


187
188
189
# File 'lib/ridley/chef/cookbook.rb', line 187

def name
  "#{cookbook_name}-#{version}"
end

#reloadObject

Reload the cookbook from the files located on disk at ‘#path`.



192
193
194
# File 'lib/ridley/chef/cookbook.rb', line 192

def reload
  load_files
end

#to_hashObject



209
210
211
212
213
214
215
216
217
218
# File 'lib/ridley/chef/cookbook.rb', line 209

def to_hash
  result                 = manifest.dup
  result[:chef_type]     = CHEF_TYPE
  result[:name]          = name
  result[:cookbook_name] = cookbook_name
  result[:version]       = version
  result[:metadata]      = .to_hash
  result[:frozen?]       = frozen
  result
end

#to_json(*args) ⇒ Object



220
221
222
223
224
# File 'lib/ridley/chef/cookbook.rb', line 220

def to_json(*args)
  result               = self.to_hash
  result['json_class'] = CHEF_JSON_CLASS
  result.to_json(*args)
end

#to_sObject



226
227
228
# File 'lib/ridley/chef/cookbook.rb', line 226

def to_s
  "#{cookbook_name} (#{version}) '#{path}'"
end

#validateObject

Raises:

  • (IOError)


196
197
198
199
200
201
202
203
204
205
206
207
# File 'lib/ridley/chef/cookbook.rb', line 196

def validate
  raise IOError, "No Cookbook found at: #{path}" unless path.exist?

  unless syntax_checker.validate_ruby_files
    raise Ridley::Errors::CookbookSyntaxError, "Invalid ruby files in cookbook: #{cookbook_name} (#{version})."
  end
  unless syntax_checker.validate_templates
    raise Ridley::Errors::CookbookSyntaxError, "Invalid template files in cookbook: #{cookbook_name} (#{version})."
  end

  true
end