lib/pdk/generators/module.rb in pdk-1.0.1 vs lib/pdk/generators/module.rb in pdk-1.1.0
- old
+ new
@@ -7,33 +7,51 @@
require 'pdk/logger'
require 'pdk/module/metadata'
require 'pdk/module/templatedir'
require 'pdk/cli/exec'
require 'pdk/cli/util/interview'
+require 'pdk/cli/util/option_validator'
require 'pdk/util'
require 'pdk/util/version'
module PDK
module Generate
class Module
def self.default_template_url
if !PDK.answers['template-url'].nil?
PDK.answers['template-url']
- elsif PDK::Util.package_install?
+ else
+ puppetlabs_template_url
+ end
+ end
+
+ def self.puppetlabs_template_url
+ if PDK::Util.package_install?
'file://' + File.join(PDK::Util.package_cachedir, 'pdk-module-template.git')
else
'https://github.com/puppetlabs/pdk-module-template'
end
end
- def self.invoke(opts = {})
+ def self.validate_options(opts)
+ unless PDK::CLI::Util::OptionValidator.valid_module_name?(opts[:name])
+ error_msg = _(
+ "'%{module_name}' is not a valid module name.\n" \
+ 'Module names must begin with a lowercase letter and can only include lowercase letters, digits, and underscores.',
+ ) % { module_name: opts[:name] }
+ raise PDK::CLI::ExitWithError, error_msg
+ end
+
target_dir = File.expand_path(opts[:target_dir])
- if File.exist?(target_dir)
- raise PDK::CLI::FatalError, _("The destination directory '%{dir}' already exists") % { dir: target_dir }
- end
+ raise PDK::CLI::ExitWithError, _("The destination directory '%{dir}' already exists") % { dir: target_dir } if File.exist?(target_dir)
+ end
+ def self.invoke(opts = {})
+ validate_options(opts)
+
+ target_dir = File.expand_path(opts[:target_dir])
parent_dir = File.dirname(target_dir)
begin
test_file = File.join(parent_dir, '.pdk-test-writable')
File.open(test_file, 'w') { |f| f.write('This file was created by the Puppet Development Kit to test if this folder was writable, you can safely remove this file.') }
@@ -66,14 +84,25 @@
File.open(File.join(temp_target_dir, 'metadata.json'), 'w') do |metadata_file|
metadata_file.puts metadata.to_json
end
end
- PDK.answers.update!('template-url' => template_url)
+ if template_url == puppetlabs_template_url
+ # If the user specifies our template via the command line, remove the
+ # saved template-url answer.
+ PDK.answers.update!('template-url' => nil) if opts.key?(:'template-url')
+ else
+ # Save the template-url answer if the module was generated using
+ # a template other than ours.
+ PDK.answers.update!('template-url' => template_url)
+ end
begin
- FileUtils.mv(temp_target_dir, target_dir)
+ if FileUtils.mv(temp_target_dir, target_dir)
+ PDK.logger.info(_('Module \'%{name}\' generated at path \'%{path}\'.') % { name: opts[:name], path: target_dir })
+ PDK.logger.info(_('In your module directory, add classes with the \'pdk new class\' command.'))
+ end
rescue Errno::EACCES => e
raise PDK::CLI::FatalError, _("Failed to move '%{source}' to '%{target}': %{message}") % {
source: temp_target_dir,
target: target_dir,
message: e.message,
@@ -85,11 +114,11 @@
login = Etc.getlogin || ''
login_clean = login.gsub(%r{[^0-9a-z]}i, '')
login_clean = 'username' if login_clean.empty?
if login_clean != login
- PDK.logger.warn _('Your username is not a valid Forge username, proceeding with the username %{username}. You can fix this afterwards in metadata.json.') % {
+ PDK.logger.warn _('Your username is not a valid Forge username. Proceeding with the username %{username}. You can fix this later in metadata.json.') % {
username: login_clean,
}
end
login_clean
@@ -99,13 +128,11 @@
username = PDK.answers['forge-username'] || username_from_login
defaults = {
'name' => "#{username}-#{opts[:name]}",
'version' => '0.1.0',
- 'dependencies' => [
- { 'name' => 'puppetlabs-stdlib', 'version_requirement' => '>= 4.13.1 < 5.0.0' },
- ],
+ 'dependencies' => [],
'requirements' => [
{ 'name' => 'puppet', 'version_requirement' => '>= 4.7.0 < 6.0.0' },
],
}
defaults['author'] = PDK.answers['author'] unless PDK.answers['author'].nil?
@@ -158,11 +185,11 @@
default: metadata.data['version'],
},
{
name: 'author',
question: _('Who wrote this module?'),
- help: _('This will be used to credit the module\'s author.'),
+ help: _('This is used to credit the module\'s author.'),
required: true,
default: metadata.data['author'],
},
{
name: 'license',
@@ -170,33 +197,90 @@
help: _('This should be an identifier from https://spdk.org/licenses/. Common values are "Apache-2.0", "MIT", or "proprietary".'),
required: true,
default: metadata.data['license'],
},
{
+ name: 'operatingsystem_support',
+ question: _('What operating systems does this module support?'),
+ help: _('Use the up and down keys to move between the choices, space to select and enter to continue.'),
+ required: true,
+ choices: {
+ 'RedHat based Linux' => [
+ {
+ 'operatingsystem' => 'CentOS',
+ 'operatingsystemrelease' => ['7'],
+ },
+ {
+ 'operatingsystem' => 'OracleLinux',
+ 'operatingsystemrelease' => ['7'],
+ },
+ {
+ 'operatingsystem' => 'RedHat',
+ 'operatingsystemrelease' => ['7'],
+ },
+ {
+ 'operatingsystem' => 'Scientific',
+ 'operatingsystemrelease' => ['7'],
+ },
+ ],
+ 'Debian based Linux' => [
+ {
+ 'operatingsystem' => 'Debian',
+ 'operatingsystemrelease' => ['8'],
+ },
+ {
+ 'operatingsystem' => 'Ubuntu',
+ 'operatingsystemrelease' => ['16.04'],
+ },
+ ],
+ 'Fedora' => {
+ 'operatingsystem' => 'Fedora',
+ 'operatingsystemrelease' => ['25'],
+ },
+ 'OSX' => {
+ 'operatingsystem' => 'Darwin',
+ 'operatingsystemrelease' => ['16'],
+ },
+ 'SLES' => {
+ 'operatingsystem' => 'SLES',
+ 'operatingsystemrelease' => ['12'],
+ },
+ 'Solaris' => {
+ 'operatingsystem' => 'Solaris',
+ 'operatingsystemrelease' => ['11'],
+ },
+ 'Windows' => {
+ 'operatingsystem' => 'windows',
+ 'operatingsystemrelease' => ['2008 R2', '2012 R2', '10'],
+ },
+ },
+ default: [1, 2, 7],
+ },
+ {
name: 'summary',
- question: _('Please summarize the purpose of this module in a single sentence.'),
- help: _('This will help other Puppet users understand what the module does.'),
+ question: _('Summarize the purpose of this module in a single sentence.'),
+ help: _('This helps other Puppet users understand what the module does.'),
required: true,
default: metadata.data['summary'],
},
{
name: 'source',
question: _('If there is a source code repository for this module, enter the URL here.'),
- help: _('Skip this if none exists yet, you can update this later in the metadata.json.'),
+ help: _('Skip this if no repository exists yet. You can update this later in the metadata.json.'),
required: true,
default: metadata.data['source'],
},
{
name: 'project_page',
question: _('If there is a URL where others can learn more about this module, enter it here.'),
- help: _('Optional. As with all questions above, you can update this later in the metadata.json.'),
+ help: _('Optional. You can update this later in the metadata.json.'),
default: metadata.data['project_page'],
},
{
name: 'issues_url',
question: _('If there is a public issue tracker for this module, enter its URL here.'),
- help: _('Optional. As with all questions above, you can update this later in the metadata.json.'),
+ help: _('Optional. You can update this later in the metadata.json.'),
default: metadata.data['issues_url'],
},
]
prompt = TTY::Prompt.new(help_color: :cyan)
@@ -206,37 +290,43 @@
questions.reject! { |q| q[:name] == 'license' } if opts.key?(:license)
interview.add_questions(questions)
puts _(
- "\nWe need to create a metadata.json file for this module, so we\'re going to ask you %{count} quick " \
+ "\nWe need to create a metadata.json file for this module, so we\'re going to ask you %{count} " \
"questions.\n" \
- 'If the question is not applicable to this module, simply leave the answer blank and skip. A default option ' \
- 'is shown after each question. You can modify this or any other answers at any time by manually updating ' \
+ 'If the question is not applicable to this module, accept the default option ' \
+ 'shown after each question. You can modify any answers at any time by manually updating ' \
"the metadata.json file.\n\n",
) % { count: interview.num_questions }
answers = interview.run
if answers.nil?
- PDK.logger.info _('Interview cancelled, not generating the module.')
+ PDK.logger.info _('Interview cancelled; not generating the module.')
exit 0
end
forge_username = answers['name']
answers['name'] = "#{answers['name']}-#{opts[:name]}"
answers['license'] = opts[:license] if opts.key?(:license)
+ answers['operatingsystem_support'].flatten!
metadata.update!(answers)
puts '-' * 40
puts _('SUMMARY')
puts '-' * 40
puts metadata.to_json
puts '-' * 40
puts
- continue = prompt.yes?(_('About to generate this module; continue?')) do |q|
- q.validate(proc { |value| [true, false].include?(value) || value =~ %r{\A(?:yes|y|no|n)\Z}i }, 'Please answer "yes" or "no"')
+ begin
+ continue = prompt.yes?(_('About to generate this module; continue?')) do |q|
+ q.validate(proc { |value| [true, false].include?(value) || value =~ %r{\A(?:yes|y|no|n)\Z}i }, _('Answer "Y" to continue or "n" to cancel.'))
+ end
+ rescue TTY::Prompt::Reader::InputInterrupt
+ PDK.logger.info _('Interview cancelled; not generating the module.')
+ exit 0
end
unless continue
PDK.logger.info _('Module not generated.')
exit 0