~ubuntu-branches/ubuntu/quantal/puppet/quantal

« back to all changes in this revision

Viewing changes to lib/puppet/module.rb

  • Committer: Package Import Robot
  • Author(s): Marc Deslauriers
  • Date: 2012-07-14 01:56:30 UTC
  • mfrom: (1.1.29) (3.1.43 sid)
  • Revision ID: package-import@ubuntu.com-20120714015630-ntj41rkvkq4zph4y
Tags: 2.7.18-1ubuntu1
* Resynchronise with Debian. (LP: #1023931) Remaining changes:
  - debian/puppetmaster-passenger.postinst: Make sure we error if puppet
    config print doesn't work
  - debian/puppetmaster-passenger.postinst: Ensure upgrades from
    <= 2.7.11-1 fixup passenger apache configuration.
* Dropped upstreamed patches:
  - debian/patches/CVE-2012-1906_CVE-2012-1986_to_CVE-2012-1989.patch
  - debian/patches/puppet-12844
  - debian/patches/2.7.17-Puppet-July-2012-CVE-fixes.patch
* Drop Build-Depends on ruby-rspec (in universe):
  - debian/control: remove ruby-rspec from Build-Depends
  - debian/patches/no-rspec.patch: make Rakefile work anyway if rspec
    isn't installed so we can use it in debian/rules.

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
1
require 'puppet/util/logging'
 
2
require 'semver'
 
3
require 'puppet/module_tool/applications'
2
4
 
3
5
# Support for modules
4
6
class Puppet::Module
30
32
  attr_reader :name, :environment
31
33
  attr_writer :environment
32
34
 
 
35
  attr_accessor :dependencies, :forge_name
33
36
  attr_accessor :source, :author, :version, :license, :puppetversion, :summary, :description, :project_page
34
37
 
35
38
  def has_metadata?
38
41
    return false unless FileTest.exist?(metadata_file)
39
42
 
40
43
    metadata = PSON.parse File.read(metadata_file)
 
44
 
 
45
 
41
46
    return metadata.is_a?(Hash) && !metadata.keys.empty?
42
47
  end
43
48
 
56
61
    load_metadata if has_metadata?
57
62
 
58
63
    validate_puppet_version
59
 
    validate_dependencies
60
64
  end
61
65
 
62
66
  FILETYPES.each do |type|
107
111
 
108
112
  def load_metadata
109
113
    data = PSON.parse File.read(metadata_file)
110
 
    [:source, :author, :version, :license, :puppetversion].each do |attr|
 
114
    @forge_name = data['name'].gsub('-', '/') if data['name']
 
115
 
 
116
    [:source, :author, :version, :license, :puppetversion, :dependencies].each do |attr|
111
117
      unless value = data[attr.to_s]
112
118
        unless attr == :puppetversion
113
119
          raise MissingMetadata, "No #{attr} module metadata provided for #{self.name}"
114
120
        end
115
121
      end
 
122
 
 
123
      # NOTICE: The fallback to `versionRequirement` is something we'd like to
 
124
      # not have to support, but we have a reasonable number of releases that
 
125
      # don't use `version_requirement`. When we can deprecate this, we should.
 
126
      if attr == :dependencies
 
127
        value.tap do |dependencies|
 
128
          dependencies.each do |dep|
 
129
            dep['version_requirement'] ||= dep['versionRequirement'] || '>= 0.0.0'
 
130
          end
 
131
        end
 
132
      end
 
133
 
116
134
      send(attr.to_s + "=", value)
117
135
    end
118
136
  end
138
156
    @path ||= environment.modulepath.collect { |path| File.join(path, name) }.find { |d| FileTest.directory?(d) }
139
157
  end
140
158
 
 
159
  def modulepath
 
160
    File.dirname(path) if path
 
161
  end
 
162
 
141
163
  # Find all plugin directories.  This is used by the Plugins fileserving mount.
142
164
  def plugin_directory
143
165
    subpath("plugins")
154
176
    result
155
177
  end
156
178
 
157
 
  def validate_dependencies
158
 
    return unless defined?(@requires)
159
 
 
160
 
    @requires.each do |name, version|
161
 
      unless mod = environment.module(name)
162
 
        raise MissingModule, "Missing module #{name} required by #{self.name}"
163
 
      end
164
 
 
165
 
      if version and mod.version != version
166
 
        raise IncompatibleModule, "Required module #{name} is version #{mod.version} but #{self.name} requires #{version}"
167
 
      end
168
 
    end
 
179
  def dependencies_as_modules
 
180
    dependent_modules = []
 
181
    dependencies and dependencies.each do |dep|
 
182
      author, dep_name = dep["name"].split('/')
 
183
      found_module = environment.module(dep_name)
 
184
      dependent_modules << found_module if found_module
 
185
    end
 
186
 
 
187
    dependent_modules
 
188
  end
 
189
 
 
190
  def required_by
 
191
    environment.module_requirements[self.forge_name] || {}
 
192
  end
 
193
 
 
194
  def has_local_changes?
 
195
    changes = Puppet::ModuleTool::Applications::Checksummer.run(path)
 
196
    !changes.empty?
 
197
  end
 
198
 
 
199
  def local_changes
 
200
    Puppet::ModuleTool::Applications::Checksummer.run(path)
 
201
  end
 
202
 
 
203
  # Identify and mark unmet dependencies.  A dependency will be marked unmet
 
204
  # for the following reasons:
 
205
  #
 
206
  #   * not installed and is thus considered missing
 
207
  #   * installed and does not meet the version requirements for this module
 
208
  #   * installed and doesn't use semantic versioning
 
209
  #
 
210
  # Returns a list of hashes representing the details of an unmet dependency.
 
211
  #
 
212
  # Example:
 
213
  #
 
214
  #   [
 
215
  #     {
 
216
  #       :reason => :missing,
 
217
  #       :name   => 'puppetlabs-mysql',
 
218
  #       :version_constraint => 'v0.0.1',
 
219
  #       :mod_details => {
 
220
  #         :installed_version => '0.0.1'
 
221
  #       }
 
222
  #       :parent => {
 
223
  #         :name    => 'puppetlabs-bacula',
 
224
  #         :version => 'v1.0.0'
 
225
  #       }
 
226
  #     }
 
227
  #   ]
 
228
  #
 
229
  def unmet_dependencies
 
230
    unmet_dependencies = []
 
231
    return unmet_dependencies unless dependencies
 
232
 
 
233
    dependencies.each do |dependency|
 
234
      forge_name = dependency['name']
 
235
      version_string = dependency['version_requirement'] || '>= 0.0.0'
 
236
 
 
237
      dep_mod = begin
 
238
        environment.module_by_forge_name(forge_name)
 
239
      rescue => e
 
240
        nil
 
241
      end
 
242
 
 
243
      error_details = {
 
244
        :name => forge_name,
 
245
        :version_constraint => version_string.gsub(/^(?=\d)/, "v"),
 
246
        :parent => {
 
247
          :name => self.forge_name,
 
248
          :version => self.version.gsub(/^(?=\d)/, "v")
 
249
        },
 
250
        :mod_details => {
 
251
          :installed_version => dep_mod.nil? ? nil : dep_mod.version
 
252
        }
 
253
      }
 
254
 
 
255
      unless dep_mod
 
256
        error_details[:reason] = :missing
 
257
        unmet_dependencies << error_details
 
258
        next
 
259
      end
 
260
 
 
261
      if version_string
 
262
        begin
 
263
          required_version_semver_range = SemVer[version_string]
 
264
          actual_version_semver = SemVer.new(dep_mod.version)
 
265
        rescue ArgumentError
 
266
          error_details[:reason] = :non_semantic_version
 
267
          unmet_dependencies << error_details
 
268
          next
 
269
        end
 
270
 
 
271
        unless required_version_semver_range.include? actual_version_semver
 
272
          error_details[:reason] = :version_mismatch
 
273
          unmet_dependencies << error_details
 
274
          next
 
275
        end
 
276
      end
 
277
    end
 
278
 
 
279
    unmet_dependencies
169
280
  end
170
281
 
171
282
  def validate_puppet_version
191
302
  end
192
303
 
193
304
  def assert_validity
194
 
    raise InvalidName, "Invalid module name; module names must be alphanumeric (plus '-'), not '#{name}'" unless name =~ /^[-\w]+$/
 
305
    raise InvalidName, "Invalid module name #{name}; module names must be alphanumeric (plus '-'), not '#{name}'" unless name =~ /^[-\w]+$/
195
306
  end
196
307
 
197
308
  def ==(other)
198
309
    self.name == other.name &&
199
 
      self.version == other.version &&
200
 
      self.path == other.path &&
201
 
      self.environment == other.environment
 
310
    self.version == other.version &&
 
311
    self.path == other.path &&
 
312
    self.environment == other.environment
202
313
  end
203
314
end