~ubuntu-branches/ubuntu/lucid/puppet/lucid-security

« back to all changes in this revision

Viewing changes to lib/puppet/module.rb

  • Committer: Bazaar Package Importer
  • Author(s): Chuck Short
  • Date: 2009-12-23 00:48:10 UTC
  • mfrom: (1.1.10 upstream) (3.1.7 squeeze)
  • Revision ID: james.westby@ubuntu.com-20091223004810-3i4oryds922g5n59
Tags: 0.25.1-3ubuntu1
* Merge from debian testing.  Remaining changes:
  - debian/rules:
    + Don't start puppet when first installing puppet.
  - debian/puppet.conf, lib/puppet/defaults.rb:
    + Move templates to /etc/puppet
  - lib/puppet/defaults.rb:
    + Fix /var/lib/puppet/state ownership.
  - man/man8/puppet.conf.8: 
    + Fix broken URL in manpage.
  - debian/control:
    + Update maintainer accordint to spec.
    + Puppetmaster Recommends -> Suggests
    + Created puppet-testsuite as a seperate. Allow the users to run puppet's 
      testsuite.
  - tests/Rakefile: Fix rakefile so that the testsuite can acutally be ran.

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
require 'puppet/util/logging'
 
2
 
1
3
# Support for modules
2
4
class Puppet::Module
 
5
    include Puppet::Util::Logging
 
6
 
 
7
    class InvalidName < ArgumentError
 
8
        def message
 
9
            "Invalid module name; module names must be alphanumeric (plus '-')"
 
10
        end
 
11
    end
3
12
 
4
13
    TEMPLATES = "templates"
5
14
    FILES = "files"
6
15
    MANIFESTS = "manifests"
7
 
    
 
16
    PLUGINS = "plugins"
 
17
 
 
18
    FILETYPES = [MANIFESTS, FILES, TEMPLATES, PLUGINS]
 
19
 
8
20
    # Return an array of paths by splitting the +modulepath+ config
9
21
    # parameter. Only consider paths that are absolute and existing
10
22
    # directories
11
23
    def self.modulepath(environment = nil)
12
 
        dirs = Puppet.settings.value(:modulepath, environment).split(":")
13
 
        if ENV["PUPPETLIB"]
14
 
            dirs = ENV["PUPPETLIB"].split(":") + dirs
15
 
        else
16
 
        end
17
 
        dirs.select do |p|
18
 
            p =~ /^#{File::SEPARATOR}/ && File::directory?(p)
19
 
        end
20
 
    end
21
 
 
22
 
    # Return an array of paths by splitting the +templatedir+ config
23
 
    # parameter.
24
 
    def self.templatepath(environment = nil)
25
 
        dirs = Puppet.settings.value(:templatedir, environment).split(":")
26
 
        dirs.select do |p|
27
 
            File::directory?(p)
28
 
        end
 
24
        Puppet::Node::Environment.new(environment).modulepath
29
25
    end
30
26
 
31
27
    # Find and return the +module+ that +path+ belongs to. If +path+ is
32
28
    # absolute, or if there is no module whose name is the first component
33
29
    # of +path+, return +nil+
34
30
    def self.find(modname, environment = nil)
35
 
        if modname =~ %r/^#{File::SEPARATOR}/
36
 
            return nil
37
 
        end
38
 
 
39
 
        modpath = modulepath(environment).collect { |path|
40
 
            File::join(path, modname)
41
 
        }.find { |f| File::directory?(f) }
42
 
        return nil unless modpath
43
 
 
44
 
        return self.new(modname, modpath)
45
 
    end
46
 
 
47
 
    # Return an array of the full path of every subdirectory in each
48
 
    # directory in the modulepath.
49
 
    def self.all(environment = nil)
50
 
        modulepath(environment).map do |mp|
51
 
            Dir.new(mp).map do |modfile|
52
 
                modpath = File.join(mp, modfile)
53
 
                unless modfile == '.' or modfile == '..' or !File.directory?(modpath)
54
 
                    modpath
55
 
                else
56
 
                    nil
57
 
                end
58
 
            end
59
 
        end.flatten.compact
60
 
    end
61
 
 
62
 
    # Instance methods
63
 
 
64
 
    # Find the concrete file denoted by +file+. If +file+ is absolute,
65
 
    # return it directly. Otherwise try to find it as a template in a
66
 
    # module. If that fails, return it relative to the +templatedir+ config
67
 
    # param.
68
 
    # In all cases, an absolute path is returned, which does not
69
 
    # necessarily refer to an existing file
70
 
    def self.find_template(template, environment = nil)
71
 
        if template =~ /^#{File::SEPARATOR}/
72
 
            return template
73
 
        end
74
 
 
75
 
        template_paths = templatepath(environment)
76
 
        if template_paths
77
 
            # If we can find the template in :templatedir, we return that.
78
 
            td_file = template_paths.collect { |path|
79
 
                File::join(path, template)
80
 
            }.find { |f| File.exists?(f) }
81
 
 
82
 
            return td_file unless td_file == nil
83
 
        end
84
 
 
85
 
        td_file = find_template_for_module(template, environment)
86
 
 
87
 
        # check in the default template dir, if there is one
88
 
        if td_file.nil?
89
 
            raise Puppet::Error, "No valid template directory found, please check templatedir settings" if template_paths.nil?
90
 
            td_file = File::join(template_paths.first, template)
91
 
        end
92
 
        td_file
93
 
    end
94
 
 
95
 
    def self.find_template_for_module(template, environment = nil)
96
 
        path, file = split_path(template)
97
 
 
98
 
        # Because templates don't have an assumed template name, like manifests do,
99
 
        # we treat templates with no name as being templates in the main template
100
 
        # directory.
101
 
        if not file.nil?
102
 
            mod = find(path, environment)
103
 
            if mod
104
 
                return mod.template(file)
105
 
            end
106
 
        end
107
 
        nil
108
 
    end
109
 
 
110
 
    # Return a list of manifests (as absolute filenames) that match +pat+
111
 
    # with the current directory set to +cwd+. If the first component of
112
 
    # +pat+ does not contain any wildcards and is an existing module, return
113
 
    # a list of manifests in that module matching the rest of +pat+
114
 
    # Otherwise, try to find manifests matching +pat+ relative to +cwd+
115
 
    def self.find_manifests(start, options = {})
116
 
        cwd = options[:cwd] || Dir.getwd
117
 
        module_name, pattern = split_path(start)
118
 
        if module_name and mod = find(module_name, options[:environment])
119
 
            return mod.manifests(pattern)
120
 
        else
121
 
            abspat = File::expand_path(start, cwd)
122
 
            files = Dir.glob(abspat).reject { |f| FileTest.directory?(f) }
123
 
            if files.size == 0
124
 
                files = Dir.glob(abspat + ".pp").reject { |f| FileTest.directory?(f) }
125
 
            end
126
 
            return files
127
 
        end
128
 
    end
129
 
 
130
 
    # Split the path into the module and the rest of the path.
131
 
    # This method can and often does return nil, so anyone calling
132
 
    # it needs to handle that.
133
 
    def self.split_path(path)
134
 
        if path =~ %r/^#{File::SEPARATOR}/
135
 
            return nil
136
 
        end
137
 
 
138
 
        modname, rest = path.split(File::SEPARATOR, 2)
139
 
        return nil if modname.nil? || modname.empty?
140
 
        return modname, rest
141
 
    end
142
 
 
143
 
    attr_reader :name, :path
144
 
    def initialize(name, path)
 
31
        return nil unless modname
 
32
        Puppet::Node::Environment.new(environment).module(modname)
 
33
    end
 
34
 
 
35
    attr_reader :name, :environment
 
36
    attr_writer :environment
 
37
 
 
38
    def initialize(name, environment = nil)
145
39
        @name = name
146
 
        @path = path
147
 
    end
148
 
 
149
 
    def template(file)
150
 
        return File::join(path, TEMPLATES, file)
151
 
    end
152
 
 
153
 
    def files
154
 
        return File::join(path, FILES)
 
40
 
 
41
        assert_validity()
 
42
 
 
43
        if environment.is_a?(Puppet::Node::Environment)
 
44
            @environment = environment
 
45
        else
 
46
            @environment = Puppet::Node::Environment.new(environment)
 
47
        end
 
48
    end
 
49
 
 
50
    FILETYPES.each do |type|
 
51
        # A boolean method to let external callers determine if
 
52
        # we have files of a given type.
 
53
        define_method(type +'?') do
 
54
            return false unless path
 
55
            return false unless FileTest.exist?(subpath(type))
 
56
            return true
 
57
        end
 
58
 
 
59
        # A method for returning a given file of a given type.
 
60
        # e.g., file = mod.manifest("my/manifest.pp")
 
61
        #
 
62
        # If the file name is nil, then the base directory for the
 
63
        # file type is passed; this is used for fileserving.
 
64
        define_method(type.to_s.sub(/s$/, '')) do |file|
 
65
            return nil unless path
 
66
 
 
67
            # If 'file' is nil then they're asking for the base path.
 
68
            # This is used for things like fileserving.
 
69
            if file
 
70
                full_path = File.join(subpath(type), file)
 
71
            else
 
72
                full_path = subpath(type)
 
73
            end
 
74
 
 
75
            return nil unless FileTest.exist?(full_path)
 
76
            return full_path
 
77
        end
 
78
    end
 
79
 
 
80
    def exist?
 
81
        ! path.nil?
 
82
    end
 
83
 
 
84
    # Find the first 'files' directory.  This is used by the XMLRPC fileserver.
 
85
    def file_directory
 
86
        subpath("files")
155
87
    end
156
88
 
157
89
    # Return the list of manifests matching the given glob pattern,
158
90
    # defaulting to 'init.pp' for empty modules.
159
 
    def manifests(rest)
 
91
    def match_manifests(rest)
 
92
        return find_init_manifest unless rest # Use init.pp
 
93
 
160
94
        rest ||= "init.pp"
161
95
        p = File::join(path, MANIFESTS, rest)
162
 
        files = Dir.glob(p).reject { |f| FileTest.directory?(f) }
163
 
        if files.size == 0
164
 
            files = Dir.glob(p + ".pp")
165
 
        end
166
 
        return files
167
 
    end
168
 
 
169
 
    private :initialize
170
 
    private_class_method :find_template_for_module
 
96
        result = Dir.glob(p).reject { |f| FileTest.directory?(f) }
 
97
        if result.size == 0 and rest !~ /\.pp$/
 
98
            result = Dir.glob(p + ".pp")
 
99
        end
 
100
        result.flatten.compact
 
101
    end
 
102
 
 
103
    # Find this module in the modulepath.
 
104
    def path
 
105
        environment.modulepath.collect { |path| File.join(path, name) }.find { |d| FileTest.exist?(d) }
 
106
    end
 
107
 
 
108
    # Find all plugin directories.  This is used by the Plugins fileserving mount.
 
109
    def plugin_directory
 
110
        subpath("plugins")
 
111
    end
 
112
 
 
113
    def to_s
 
114
        result = "Module %s" % name
 
115
        if path
 
116
            result += "(%s)" % path
 
117
        end
 
118
        result
 
119
    end
 
120
 
 
121
    private
 
122
 
 
123
    def find_init_manifest
 
124
        return [] unless file = manifest("init.pp")
 
125
        return [file]
 
126
    end
 
127
 
 
128
    def subpath(type)
 
129
        return File.join(path, type) unless type.to_s == "plugins"
 
130
 
 
131
        return backward_compatible_plugins_dir
 
132
    end
 
133
 
 
134
    def backward_compatible_plugins_dir
 
135
        if dir = File.join(path, "plugins") and FileTest.exist?(dir)
 
136
            warning "using the deprecated 'plugins' directory for ruby extensions; please move to 'lib'"
 
137
            return dir
 
138
        else
 
139
            return File.join(path, "lib")
 
140
        end
 
141
    end
 
142
 
 
143
    def assert_validity
 
144
        raise InvalidName unless name =~ /^[-\w]+$/
 
145
    end
171
146
end