Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
27 changes: 26 additions & 1 deletion lib/puppet/module.rb
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
require 'puppet/util/logging'
require 'semver'
require 'puppet/module_tool/applications'

# Support for modules
class Puppet::Module
Expand Down Expand Up @@ -31,7 +32,7 @@ def self.find(modname, environment = nil)
attr_reader :name, :environment
attr_writer :environment

attr_accessor :dependencies
attr_accessor :dependencies, :forge_name
attr_accessor :source, :author, :version, :license, :puppetversion, :summary, :description, :project_page

def has_metadata?
Expand All @@ -40,6 +41,8 @@ def has_metadata?
return false unless FileTest.exist?(metadata_file)

metadata = PSON.parse File.read(metadata_file)


return metadata.is_a?(Hash) && !metadata.keys.empty?
end

Expand Down Expand Up @@ -108,6 +111,8 @@ def license_file

def load_metadata
data = PSON.parse File.read(metadata_file)
@forge_name = data['name'].gsub('-', '/') if data['name']

[:source, :author, :version, :license, :puppetversion, :dependencies].each do |attr|
unless value = data[attr.to_s]
unless attr == :puppetversion
Expand Down Expand Up @@ -155,6 +160,26 @@ def to_s
result
end

def dependencies_as_modules
dependent_modules = []
dependencies and dependencies.each do |dep|
author, dep_name = dep["name"].split('/')
found_module = environment.module(dep_name)
dependent_modules << found_module if found_module
end

dependent_modules
end

def required_by
environment.module_requirements[self.forge_name] || {}
end

def has_local_changes?
changes = Puppet::Module::Tool::Applications::Checksummer.run(path)
!changes.empty?
end

def unmet_dependencies
return [] unless dependencies

Expand Down
26 changes: 15 additions & 11 deletions lib/puppet/module_tool/applications.rb
Original file line number Diff line number Diff line change
@@ -1,13 +1,17 @@
module Puppet::Module::Tool
module Applications
require 'puppet/module_tool/applications/application'
require 'puppet/module_tool/applications/builder'
require 'puppet/module_tool/applications/checksummer'
require 'puppet/module_tool/applications/cleaner'
require 'puppet/module_tool/applications/generator'
require 'puppet/module_tool/applications/installer'
require 'puppet/module_tool/applications/searcher'
require 'puppet/module_tool/applications/unpacker'
require 'puppet/module_tool/applications/uninstaller'
require 'puppet/module'

class Puppet::Module
module Tool
module Applications
require 'puppet/module_tool/applications/application'
require 'puppet/module_tool/applications/builder'
require 'puppet/module_tool/applications/checksummer'
require 'puppet/module_tool/applications/cleaner'
require 'puppet/module_tool/applications/generator'
require 'puppet/module_tool/applications/installer'
require 'puppet/module_tool/applications/searcher'
require 'puppet/module_tool/applications/unpacker'
require 'puppet/module_tool/applications/uninstaller'
end
end
end
3 changes: 2 additions & 1 deletion lib/puppet/module_tool/applications/application.rb
Original file line number Diff line number Diff line change
@@ -1,10 +1,11 @@
require 'net/http'
require 'semver'
require 'puppet/module_tool/utils/interrogation'

module Puppet::Module::Tool
module Applications
class Application
include Utils::Interrogation
include Puppet::Module::Tool::Utils::Interrogation

def self.run(*args)
new(*args).run
Expand Down
26 changes: 26 additions & 0 deletions lib/puppet/node/environment.rb
Original file line number Diff line number Diff line change
Expand Up @@ -93,6 +93,14 @@ def module(name)
mod
end

def module_by_forge_name(forge_name)
author, modname = forge_name.split('/')
found_mod = self.module(modname)
found_mod and found_mod.forge_name == forge_name ?
found_mod :
nil
end

# Cache the modulepath, so that we aren't searching through
# all known directories all the time.
cached_attr(:modulepath, Puppet[:filetimeout]) do
Expand Down Expand Up @@ -128,6 +136,24 @@ def modules_by_path
modules_by_path
end

def module_requirements
deps = {}
modules.each do |mod|
next unless mod.forge_name
deps[mod.forge_name] ||= []
mod.dependencies and mod.dependencies.sort_by {|mod_dep| mod_dep['name']}.each do |mod_dep|
deps[mod_dep['name']] ||= []
dep_details = {
'name' => mod.forge_name,
'version' => mod.version,
'version_requirement' => mod_dep['version_requirement']
}
deps[mod_dep['name']] << dep_details
end
end
deps
end

def to_s
name.to_s
end
Expand Down
26 changes: 26 additions & 0 deletions spec/lib/puppet_spec/modules.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
module PuppetSpec::Modules
class << self
def create(name, dir, options = {})
module_dir = File.join(dir, name)
FileUtils.mkdir_p(module_dir)

environment = Puppet::Node::Environment.new(options[:environment])

if metadata = options[:metadata]
metadata[:source] ||= 'github'
metadata[:author] ||= 'puppetlabs'
metadata[:version] ||= '9.9.9'
metadata[:license] ||= 'to kill'
metadata[:dependencies] ||= []

metadata[:name] = "#{metadata[:author]}/#{name}"

File.open(File.join(module_dir, 'metadata.json'), 'w') do |f|
f.write(metadata.to_pson)
end
end

Puppet::Module.new(name, :environment => environment, :path => module_dir)
end
end
end
85 changes: 78 additions & 7 deletions spec/unit/module_spec.rb
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
#!/usr/bin/env rspec
require 'spec_helper'
require 'puppet_spec/files'
require 'puppet_spec/modules'
require 'puppet/module_tool/checksums'

describe Puppet::Module do
include PuppetSpec::Files
Expand Down Expand Up @@ -532,13 +534,14 @@
end

describe Puppet::Module do
include PuppetSpec::Files
before do
Puppet::Module.any_instance.stubs(:path).returns "/my/mod/path"
@module = Puppet::Module.new("foo")
@modpath = tmpdir('modpath')
@module = PuppetSpec::Modules.create('mymod', @modpath)
end

it "should use 'License' in its current path as its metadata file" do
@module.license_file.should == "/my/mod/path/License"
@module.license_file.should == "#{@modpath}/mymod/License"
end

it "should return nil as its license file when the module has no path" do
Expand All @@ -547,13 +550,13 @@
end

it "should cache the license file" do
Puppet::Module.any_instance.expects(:path).once.returns nil
mod = Puppet::Module.new("foo")
mod.license_file.should == mod.license_file
@module.expects(:path).once.returns nil
@module.license_file
@module.license_file
end

it "should use 'metadata.json' in its current path as its metadata file" do
@module.metadata_file.should == "/my/mod/path/metadata.json"
@module.metadata_file.should == "#{@modpath}/mymod/metadata.json"
end

it "should return nil as its metadata file when the module has no path" do
Expand Down Expand Up @@ -657,4 +660,72 @@

it "should fail if the discovered name is different than the metadata name"
end

it "should be able to tell if there are local changes" do
modpath = tmpdir('modpath')
foo_checksum = 'acbd18db4cc2f85cedef654fccc4a4d8'
checksummed_module = PuppetSpec::Modules.create(
'changed',
modpath,
:metadata => {
:checksums => {
"foo" => foo_checksum,
}
}
)

foo_path = Pathname.new(File.join(checksummed_module.path, 'foo'))

IO.binwrite(foo_path, 'notfoo')
Puppet::Module::Tool::Checksums.new(foo_path).checksum(foo_path).should_not == foo_checksum
checksummed_module.has_local_changes?.should be_true

IO.binwrite(foo_path, 'foo')

Puppet::Module::Tool::Checksums.new(foo_path).checksum(foo_path).should == foo_checksum
checksummed_module.has_local_changes?.should be_false
end

it "should know what other modules require it" do
Puppet.settings[:modulepath] = @modpath
dependable = PuppetSpec::Modules.create(
'dependable',
@modpath,
:metadata => {:author => 'puppetlabs'}
)
PuppetSpec::Modules.create(
'needy',
@modpath,
:metadata => {
:author => 'beggar',
:dependencies => [{
"version_requirement" => ">= 2.2.0",
"name" => "puppetlabs/dependable"
}]
}
)
PuppetSpec::Modules.create(
'wantit',
@modpath,
:metadata => {
:author => 'spoiled',
:dependencies => [{
"version_requirement" => "< 5.0.0",
"name" => "puppetlabs/dependable"
}]
}
)
dependable.required_by.should =~ [
{
"name" => "beggar/needy",
"version" => "9.9.9",
"version_requirement" => ">= 2.2.0"
},
{
"name" => "spoiled/wantit",
"version" => "9.9.9",
"version_requirement" => "< 5.0.0"
}
]
end
end
Loading