Module: FalkorLib::Puppet::Modules

Defined in:
lib/falkorlib/puppet/modules.rb

Overview

Management of Puppet Modules operations

Class Method Summary collapse

Class Method Details

._get_classdefs(moduledir = Dir.pwd, type = 'classes') ⇒ Object



59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
# File 'lib/falkorlib/puppet/modules.rb', line 59

def _get_classdefs(moduledir = Dir.pwd, type = 'classes')
    name     = File.basename( moduledir )
    error "The module #{name} does not exist" unless File.directory?( moduledir )
    t = case type
        when /class*/i
            'class'
        when /def*/
            'define'
        else
            ''
        end
    error "Undefined type #{type}" if t.empty?
    result = []
    Dir["#{moduledir}/manifests/**/*.pp"].each do |ppfile|
        #puts "=> testing #{ppfile}"
        File.read(ppfile).scan(/^[ \t]*#{t}[\s]+([0-9a-zA-z:-]+).*$/).each do |line|
            result << line[0]
        end
    end
    result.uniq!
    result.sort
end

.classes(moduledir = Dir.pwd) ⇒ Object

Find the classes of a given module



361
362
363
# File 'lib/falkorlib/puppet/modules.rb', line 361

def classes(moduledir = Dir.pwd)
    _get_classdefs(moduledir, 'classes')
end

.definitions(moduledir = Dir.pwd) ⇒ Object

Find the definitions of a given module



368
369
370
# File 'lib/falkorlib/puppet/modules.rb', line 368

def definitions(moduledir = Dir.pwd)
    _get_classdefs(moduledir, 'definitions')
end

.deps(moduledir = Dir.pwd) ⇒ Object

Find the dependencies of a given module



375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
# File 'lib/falkorlib/puppet/modules.rb', line 375

def deps(moduledir = Dir.pwd)
    name     = File.basename( moduledir )
    error "The module #{name} does not exist" unless File.directory?( moduledir )

    result    = Array.new
    result2   = Array.new
    resulttmp = Array.new

    result << name

    while result != result2 do
        resulttmp = result.dup
        (result - result2).each do |x|
            Dir["#{moduledir}/**/*.pp"].each do |ppfile|
                File.read(ppfile).scan(/^\s*(include|require|class\s*{)\s*["']?(::)?([0-9a-zA-Z:{$}\-]*)["']?/) do |m|
                    next if $3.nil?
                    entry = $3.split('::').first
                    result << entry unless entry.nil? or entry.empty?
                end
            end
        end
        result.uniq!
        result2 = resulttmp.dup
    end
    result.delete "#{name}"
    result
end

.init(rootdir = Dir.pwd, name = '', options = {}) ⇒ Object

Initialize a new Puppet Module named ‘name` in `rootdir`. Supported options:

  • :no_iteraction [boolean]



88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
# File 'lib/falkorlib/puppet/modules.rb', line 88

def init(rootdir = Dir.pwd, name = '', options = {})
    config = {}
    #login = `whoami`.chomp
    config[:name] = name unless name.empty?
    moduledir     = rootdir
      #name.empty? ? rootdir : File.join(rootdir, name)
    FalkorLib::Config::Puppet::Modules::DEFAULTS[:metadata].each do |k,v|
        next if v.kind_of?(Array) or k == :license
        next if k == :name and ! name.empty?
        default_answer = case k
                         when :project_page
                             config[:source].nil? ? v : config[:source]
                         when :name
                             File.basename(rootdir).gsub(/^puppet-/, '')
                         when :issues_url
                             config[:project_page].nil? ? v : "#{config[:project_page]}/issues"
                         when :forge_url
                             v + '/' + config[:name].gsub(/-/,'/')
                         when :description
                             config[:summary].nil? ? v : "#{config[:summary]}"
                         when :source
                             v.empty? ? "https://github.com/#{config[:name].gsub(/\//,'/puppet-')}" : v
                         else
                             v
                         end
        config[k.to_sym] = ask( "\t" + sprintf("%-20s", "Module #{k}"), default_answer)
    end
    config[:shortname] = name = config[:name].gsub(/.*[-\/]/, '')
    config[:docs_project] = ask("\tRead the Docs (RTFD) project:", config[:name].downcase.gsub(/\//,'-puppet-'))
    tags = ask("\tKeywords (comma-separated list of tags)", config[:shortname])
    config[:tags] = tags.split(',')
    list_license    = FalkorLib::Config::Puppet::Modules::DEFAULTS[:licenses]
    default_license = FalkorLib::Config::Puppet::Modules::DEFAULTS[:metadata][:license]
    idx = list_license.index(default_license) unless default_license.nil?
    license = select_from(list_license,
                          'Select the license index for the Puppet module:',
                          idx.nil? ? 1 : idx + 1)
    config[:license] = license unless license.empty?
    puts "\t" + sprintf("%-20s", "Module License:") + config[:license]

    # Supported platforms
    config[:platforms] = [ 'debian' ]
    config[:dependencies] = [{
                                 "name"                => "puppetlabs-stdlib",
                                 "version_requirement" => ">=4.2.2 <5.0.0"
                             }]
    config[:params] = [ 'ensure', 'protocol', 'port', 'packagename' ]
    #ap config
    # Bootstrap the directory
    templatedir = File.join( FalkorLib.templates, 'puppet', 'modules')
    init_from_template(templatedir, moduledir, config, {
                           :erb_exclude    => [ 'templates\/[^\/]*variables\.erb$' ],
                           :no_interaction => true
                       })
    # Rename the files / element templatename
    Dir["#{moduledir}/**/*"].each do |e|
        next unless e =~ /templatename/
        info "renaming #{e}"
        newname = e.gsub(/templatename/, "#{name}")
        run %{ mv #{e} #{newname} }
    end
    # Update docs directory
    run %{ ln -s ../README.md #{moduledir}/docs/overview.md }
    info "Generating the License file"
    authors = config[:author].empty? ? 'UNKNOWN' : config[:author]
    Dir.chdir(moduledir) do
        run %{ licgen #{config[:license].downcase} #{authors} }
    end
    info "Initialize RVM"
    init_rvm(moduledir)
    unless FalkorLib::Git.init?(moduledir)
        init_gitflow = FalkorLib::Git.command?('flow')
        warn "Git #{init_gitflow ? '[Flow]' : ''} is not initialized in #{moduledir}."
        a = ask("Proceed to git-flow initialization (Y|n)", 'Yes')
        return if a =~ /n.*/i
        init_gitflow ? FalkorLib::GitFlow.init(moduledir) : FalkorLib::Git.init(moduledir)
    end

    # Propose to commit the key files
    if FalkorLib::Git.init?(moduledir)
        if FalkorLib::GitFlow.init?(moduledir)
            info "=> preparing git-flow feature for the newly created module '#{config[:name]}'"
            FalkorLib::GitFlow.start('feature', "bootstrapping", moduledir)
        end
        [ 'metadata.json',
         'docs/', 'mkdocs.yml', 'LICENSE', '.gitignore', '.pmtignore',
         '.ruby-version', '.ruby-gemset', 'Gemfile',
         '.vagrant_init.rb', 'Rakefile', 'Vagrantfile' ].each do |f|
            FalkorLib::Git.add(File.join(moduledir, f))
        end
    end
end

.metadata(moduledir = Dir.pwd, options = { :use_symbols => true, :extras => true, :no_interaction => false }) ⇒ Object

Retrieves the metadata from the metadata.json file in ‘moduledir`. Supported options:

:use_symbols [boolean]: convert all keys to symbols
:extras  [boolean]: add extra keys


245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
# File 'lib/falkorlib/puppet/modules.rb', line 245

def (moduledir = Dir.pwd, options = {
                 :use_symbols => true,
                 :extras      => true,
                 :no_interaction => false
             })
    add_extras = options[:extras].nil? ? true : options[:extras]
    name     = File.basename( moduledir )
    error "The module #{name} does not exist" unless File.directory?( moduledir )
    jsonfile = File.join( moduledir, 'metadata.json')
    error "Unable to find #{jsonfile}" unless File.exist?( jsonfile )
     = JSON.parse( IO.read( jsonfile ) )
    ["docs_project"] = ask("\tRead the Docs (RTFD) project:", "#{['name'].downcase.gsub(/\//,'-puppet-')}") if ["docs_project"].nil?
    if add_extras
        [:shortname] = name.gsub(/.*-/, '')
        [:platforms] = []
        ["operatingsystem_support"].each do |e|
            [:platforms] << e["operatingsystem"].downcase unless e["operatingsystem"].nil?
        end
        # Analyse params
        params_manifest = File.join(moduledir, 'manifests', 'params.pp')
        if File.exist?(params_manifest)
            params = []
            File.read(params_manifest).scan(/^\s*\$(.*)\s*=/) do |m|
                params << $1.gsub(/\s+$/,'') unless $1.nil?
            end
            [:params] = params.uniq
        end
    end
    if options[:use_symbols]
        # convert string keys to symbols
        .keys.each do |k|
            [(k.to_sym rescue k) || k] = .delete(k)
        end
    end
    
end

.parse(moduledir = Dir.pwd, options = { :no_interaction => false }) ⇒ Object

Parse a given modules to collect information Supported options:

:no_interaction [boolean]: do not interact


186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
# File 'lib/falkorlib/puppet/modules.rb', line 186

def parse(moduledir = Dir.pwd, options = {
              :no_interaction => false
          })
    name = File.basename(moduledir)
     = (moduledir, {
                            :use_symbols    => false,
                            :extras         => false,
                            :no_interaction => options[:no_interaction]
                        })
    puts .to_yaml
    # error "The module #{name} does not exist" unless File.directory?( moduledir )
    jsonfile = File.join( moduledir, 'metadata.json')
    # error "Unable to find #{jsonfile}" unless File.exist?( jsonfile )
    # metadata = JSON.parse( IO.read( jsonfile ) )
    ref = JSON.pretty_generate(  )
    ["classes"]     = classes(moduledir)
    ["definitions"] = definitions(moduledir)
    deps        = deps(moduledir)
    listed_deps = ["dependencies"]
    missed_deps = []
    ["dependencies"].each do |dep|
        lib = dep["name"].gsub(/^[^\/-]+[\/-]/,'')
        if deps.include?( lib )
            deps.delete( lib )
        else
            unless lib =~ /stdlib/
                warn "The library '#{dep["name"]}' is not analyzed as part of the #{['shortname']} module"
                missed_deps << dep
            end
        end
    end
    if ! deps.empty?
        deps.each do |l|
            next if [name, ["name"], name.gsub(/.*-/, ''), ["name"].gsub(/.*-/, '') ].include? ( l )
            warn "The module '#{l}' is missing in the dependencies thus added"
               = ask("[Github] login for the module '#{l}'")
            version = ask("Version requirement (ex: '>=1.0.0 <2.0.0' or '1.2.3' or '1.x')")
            ["dependencies"] << {
                "name"                => "#{}/#{l}",
                "version_requirement" => "#{version}"
            }
        end
    end
    content = JSON.pretty_generate(  )
    info "Metadata configuration for the module '#{name}'"
    puts content
    show_diff_and_write(content, jsonfile, {
                            :no_interaction     => options[:no_interaction],
                            :json_pretty_format => true
                        })
    
end

.upgrade(moduledir = Dir.pwd, options = { :no_interaction => false, :only => nil, :exclude => [] }) ⇒ Object

Upgrade the key files (README etc.) of the puppet module hosted in ‘moduledir` with the latest version of the FalkorLib template Supported options:

:no_interaction [boolean]: do not interact
:only [Array of string]: update only the listed files
:exclude [Array of string]: exclude from the upgrade the listed
                            files

return the number of considered files



293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
# File 'lib/falkorlib/puppet/modules.rb', line 293

def upgrade(moduledir = Dir.pwd,
            options = {
                :no_interaction => false,
                :only    => nil,
                :exclude => []
            })
     = (moduledir)
    templatedir = File.join( FalkorLib.templates, 'puppet', 'modules')
    i = 0
    update_from_erb = [
                       'README.md',
                       'docs/contacts.md',
                       'docs/contributing/index.md', 'docs/contributing/layout.md', 'docs/contributing/setup.md', 'docs/contributing/versioning.md',
                       'docs/index.md', 'docs/rtfd.md', 'docs/vagrant.md'
                      ]
    (update_from_erb + [ 'Gemfile', 'Rakefile', 'Vagrantfile', '.vagrant_init.rb' ]).each do |f|
        next unless options[:exclude].nil? or ! options[:exclude].include?( f )
        next unless options[:only].nil?    or options[:only].include?(f)
        info "Upgrade the content of #{f}"
        ans = options[:no_interaction] ? 'Yes' : ask(cyan("==> procceed? (Y|n)"), 'Yes')
        next if ans =~ /n.*/i
        if update_from_erb.include?(f)
            puts "=> updating #{f}.erb"
            i += write_from_erb_template(File.join(templatedir, "#{f}.erb"),
                                         File.join(moduledir,  f),
                                         ,
                                         options)
        else
            i+= write_from_template(f, moduledir, {
                                        :no_interaction => options[:no_interaction],
                                        :srcdir => templatedir
                                    })
        end
    end
    i
end

.upgrade_from_template(moduledir = Dir.pwd, subdir = 'tests', options = { :no_interaction => false }) ⇒ Object

initializes or update the (tests/specs/etc.) sub-directory of the ‘moduledir` using the correcponding ERB files. Supported options:

:no_interaction [boolean]: do not interactww

returns the number of considered files



337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
# File 'lib/falkorlib/puppet/modules.rb', line 337

def upgrade_from_template(moduledir = Dir.pwd,
                          subdir = 'tests',
                          options = {
                              :no_interaction => false
                          })
     = (moduledir)
    ap 
    i = 0
    templatedir = File.join( FalkorLib.templates, 'puppet', 'modules', subdir)
    error "Unable to find the template directory '#{templatedir}" unless File.directory?( templatedir )
    Dir["#{templatedir}/**/*.erb"].each do |erbfile|
        f = File.join(subdir, File.basename(erbfile, '.erb'))
        info "Upgrade the content of #{f}"
        ans = options[:no_interaction] ? 'Yes' : ask(cyan("==> procceed? (Y|n)"), 'Yes')
        next if ans =~ /n.*/i
        i+= write_from_erb_template(erbfile, File.join(moduledir, f), , options)
    end
    i
end