lib/pdk/generate/module.rb in pdk-2.4.0 vs lib/pdk/generate/module.rb in pdk-2.5.0
- old
+ new
@@ -1,352 +1,352 @@
-require 'pdk'
-
-module PDK
- module Generate
- class Module
- def self.validate_options(opts)
- require 'pdk/cli/util/option_validator'
-
- unless PDK::CLI::Util::OptionValidator.valid_module_name?(opts[:module_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[:module_name] }
- raise PDK::CLI::ExitWithError, error_msg
- end
-
- target_dir = PDK::Util::Filesystem.expand_path(opts[:target_dir])
- raise PDK::CLI::ExitWithError, _("The destination directory '%{dir}' already exists") % { dir: target_dir } if PDK::Util::Filesystem.exist?(target_dir)
- end
-
- def self.invoke(opts = {})
- require 'pdk/util'
- require 'pdk/util/template_uri'
- require 'pathname'
-
- validate_options(opts) unless opts[:module_name].nil?
-
- metadata = prepare_metadata(opts)
-
- target_dir = PDK::Util::Filesystem.expand_path(opts[:target_dir] || opts[:module_name])
- parent_dir = File.dirname(target_dir)
-
- begin
- test_file = File.join(parent_dir, '.pdk-test-writable')
- PDK::Util::Filesystem.write_file(test_file, 'This file was created by the Puppet Development Kit to test if this folder was writable, you can safely remove this file.')
- PDK::Util::Filesystem.rm_f(test_file)
- rescue Errno::EACCES
- raise PDK::CLI::FatalError, _("You do not have permission to write to '%{parent_dir}'") % {
- parent_dir: parent_dir,
- }
- end
-
- temp_target_dir = PDK::Util.make_tmpdir_name('pdk-module-target')
-
- prepare_module_directory(temp_target_dir)
-
- template_uri = PDK::Util::TemplateURI.new(opts)
-
- if template_uri.default? && template_uri.default_ref?
- PDK.logger.info _('Using the default template-url and template-ref.')
- else
- PDK.logger.info _(
- "Using the %{method} template-url and template-ref '%{template_uri}'." % {
- method: opts.key?(:'template-url') ? _('specified') : _('saved'),
- template_uri: template_uri.metadata_format,
- },
- )
- end
-
- begin
- context = PDK::Context::None.new(temp_target_dir)
- PDK::Template.with(template_uri, context) do |template_dir|
- template_dir.render_new_module(metadata.data['name'], metadata.data) do |relative_file_path, file_content, file_status|
- next if [:delete, :unmanage].include?(file_status)
- file = Pathname.new(temp_target_dir) + relative_file_path
- file.dirname.mkpath
- PDK::Util::Filesystem.write_file(file, file_content)
- end
-
- # Add information about the template used to generate the module to the
- # metadata (for a future update command).
- metadata.update!(template_dir.metadata)
-
- metadata.write!(File.join(temp_target_dir, 'metadata.json'))
- end
- rescue ArgumentError => e
- raise PDK::CLI::ExitWithError, e
- end
-
- # Only update the answers files after metadata has been written.
- require 'pdk/answer_file'
- if template_uri.default? && template_uri.default_ref?
- # If the user specifies our default template url via the command
- # line, remove the saved template-url answer so that the template_uri
- # resolution can find new default URLs in the future.
- PDK.config.set(%w[user module_defaults template-url], nil) if opts.key?(:'template-url')
- else
- # Save the template-url answers if the module was generated using a
- # template/reference other than ours.
- PDK.config.set(%w[user module_defaults template-url], template_uri.metadata_format)
- end
-
- begin
- if PDK::Util::Filesystem.mv(temp_target_dir, target_dir)
- unless opts[:'skip-bundle-install']
- Dir.chdir(target_dir) do
- require 'pdk/util/bundler'
- PDK::Util::Bundler.ensure_bundle!
- end
- end
-
- PDK.logger.info _("Module '%{name}' generated at path '%{path}'.") % {
- name: opts[:module_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,
- }
- end
- end
-
- def self.username_from_login
- require 'etc'
-
- login = Etc.getlogin || ''
- login_clean = login.downcase.gsub(%r{[^0-9a-z]}i, '')
- login_clean = 'username' if login_clean.empty?
-
- if login_clean != login
- PDK.logger.debug _('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
- end
-
- def self.prepare_metadata(opts = {})
- require 'pdk/answer_file'
- require 'pdk/module/metadata'
-
- opts[:username] = (opts[:username] || PDK.config.get_within_scopes('module_defaults.forge_username') || username_from_login).downcase
-
- defaults = PDK::Module::Metadata::DEFAULTS.dup
-
- defaults['name'] = "#{opts[:username]}-#{opts[:module_name]}" unless opts[:module_name].nil?
- PDK.config.with_scoped_value('module_defaults.author') { |val| defaults['author'] = val }
- PDK.config.with_scoped_value('module_defaults.license') { |val| defaults['license'] = val }
- defaults['license'] = opts[:license] if opts.key?(:license)
-
- metadata = PDK::Module::Metadata.new(defaults)
- module_interview(metadata, opts) unless opts[:'skip-interview']
-
- metadata
- end
-
- def self.prepare_module_directory(target_dir)
- [
- File.join(target_dir, 'examples'),
- File.join(target_dir, 'files'),
- File.join(target_dir, 'manifests'),
- File.join(target_dir, 'templates'),
- File.join(target_dir, 'tasks'),
- ].each do |dir|
- begin
- PDK::Util::Filesystem.mkdir_p(dir)
- rescue SystemCallError => e
- raise PDK::CLI::FatalError, _("Unable to create directory '%{dir}': %{message}") % {
- dir: dir,
- message: e.message,
- }
- end
- end
- end
-
- def self.module_interview(metadata, opts = {})
- require 'pdk/module/metadata'
- require 'pdk/cli/util/interview'
-
- questions = [
- {
- name: 'module_name',
- question: _('If you have a name for your module, add it here.'),
- help: _('This is the name that will be associated with your module, it should be relevant to the modules content.'),
- required: true,
- validate_pattern: %r{\A[a-z][a-z0-9_]*\Z}i,
- validate_message: _('Module names must begin with a lowercase letter and can only include lowercase letters, numbers, and underscores.'),
- },
- {
- name: 'forge_username',
- question: _('If you have a Puppet Forge username, add it here.'),
- help: _('We can use this to upload your module to the Forge when it\'s complete.'),
- required: true,
- validate_pattern: %r{\A[a-z0-9]+\Z}i,
- validate_message: _('Forge usernames can only contain lowercase letters and numbers'),
- default: opts[:username],
- },
- {
- name: 'version',
- question: _('What version is this module?'),
- help: _('Puppet uses Semantic Versioning (semver.org) to version modules.'),
- required: true,
- validate_pattern: %r{\A[0-9]+\.[0-9]+\.[0-9]+},
- validate_message: _('Semantic Version numbers must be in the form MAJOR.MINOR.PATCH'),
- default: metadata.data['version'],
- forge_only: true,
- },
- {
- name: 'author',
- question: _('Who wrote this module?'),
- help: _('This is used to credit the module\'s author.'),
- required: true,
- default: metadata.data['author'],
- },
- {
- name: 'license',
- question: _('What license does this module code fall under?'),
- help: _('This should be an identifier from https://spdx.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,
- type: :multi_select,
- choices: PDK::Module::Metadata::OPERATING_SYSTEMS,
- default: PDK::Module::Metadata::DEFAULT_OPERATING_SYSTEMS.map do |os_name|
- # tty-prompt uses a 1-index
- PDK::Module::Metadata::OPERATING_SYSTEMS.keys.index(os_name) + 1
- end,
- },
- {
- name: 'summary',
- 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'],
- forge_only: true,
- },
- {
- name: 'source',
- question: _('If there is a source code repository for this module, enter the URL here.'),
- help: _('Skip this if no repository exists yet. You can update this later in the metadata.json.'),
- required: true,
- default: metadata.data['source'],
- forge_only: true,
- },
- {
- name: 'project_page',
- question: _('If there is a URL where others can learn more about this module, enter it here.'),
- help: _('Optional. You can update this later in the metadata.json.'),
- default: metadata.data['project_page'],
- forge_only: true,
- },
- {
- name: 'issues_url',
- question: _('If there is a public issue tracker for this module, enter its URL here.'),
- help: _('Optional. You can update this later in the metadata.json.'),
- default: metadata.data['issues_url'],
- forge_only: true,
- },
- ]
-
- prompt = TTY::Prompt.new(help_color: :cyan)
-
- interview = PDK::CLI::Util::Interview.new(prompt)
-
- if opts[:only_ask]
- questions.reject! do |question|
- if %w[module_name forge_username].include?(question[:name])
- metadata.data['name'] && metadata.data['name'] =~ %r{\A[a-z0-9]+-[a-z][a-z0-9_]*\Z}i
- else
- !opts[:only_ask].include?(question[:name])
- end
- end
- else
- questions.reject! { |q| q[:name] == 'module_name' } if opts.key?(:module_name)
- questions.reject! { |q| q[:name] == 'license' } if opts.key?(:license)
- questions.reject! { |q| q[:forge_only] } unless opts[:'full-interview']
- end
-
- interview.add_questions(questions)
-
- if PDK::Util::Filesystem.file?('metadata.json')
- puts _(
- "\nWe need to update the metadata.json file for this module, so we\'re going to ask you %{count} " \
- "questions.\n",
- ) % {
- count: interview.num_questions,
- }
- else
- puts _(
- "\nWe need to create the metadata.json file for this module, so we\'re going to ask you %{count} " \
- "questions.\n",
- ) % {
- count: interview.num_questions,
- }
- end
-
- puts _(
- '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",
- )
-
- answers = interview.run
-
- if answers.nil?
- PDK.logger.info _('No answers given, interview cancelled.')
- exit 0
- end
-
- unless answers['forge_username'].nil?
- opts[:username] = answers['forge_username']
-
- unless answers['module_name'].nil?
- opts[:module_name] = answers['module_name']
-
- answers.delete('module_name')
- end
-
- answers['name'] = "#{opts[:username]}-" + (opts[:module_name])
- answers.delete('forge_username')
- end
-
- answers['license'] = opts[:license] if opts.key?(:license)
- answers['operatingsystem_support'].flatten! if answers.key?('operatingsystem_support')
-
- metadata.update!(answers)
-
- if opts[:prompt].nil? || opts[:prompt]
- require 'pdk/cli/util'
-
- continue = PDK::CLI::Util.prompt_for_yes(
- _('Metadata will be generated based on this information, continue?'),
- prompt: prompt,
- cancel_message: _('Interview cancelled; exiting.'),
- )
-
- unless continue
- PDK.logger.info _('Process cancelled; exiting.')
- exit 0
- end
- end
-
- require 'pdk/answer_file'
- PDK.config.set(%w[user module_defaults forge_username], opts[:username]) unless opts[:username].nil?
- PDK.config.set(%w[user module_defaults author], answers['author']) unless answers['author'].nil?
- PDK.config.set(%w[user module_defaults license], answers['license']) unless answers['license'].nil?
- end
- end
- end
-end
+require 'pdk'
+
+module PDK
+ module Generate
+ class Module
+ def self.validate_options(opts)
+ require 'pdk/cli/util/option_validator'
+
+ unless PDK::CLI::Util::OptionValidator.valid_module_name?(opts[:module_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[:module_name] }
+ raise PDK::CLI::ExitWithError, error_msg
+ end
+
+ target_dir = PDK::Util::Filesystem.expand_path(opts[:target_dir])
+ raise PDK::CLI::ExitWithError, _("The destination directory '%{dir}' already exists") % { dir: target_dir } if PDK::Util::Filesystem.exist?(target_dir)
+ end
+
+ def self.invoke(opts = {})
+ require 'pdk/util'
+ require 'pdk/util/template_uri'
+ require 'pathname'
+
+ validate_options(opts) unless opts[:module_name].nil?
+
+ metadata = prepare_metadata(opts)
+
+ target_dir = PDK::Util::Filesystem.expand_path(opts[:target_dir] || opts[:module_name])
+ parent_dir = File.dirname(target_dir)
+
+ begin
+ test_file = File.join(parent_dir, '.pdk-test-writable')
+ PDK::Util::Filesystem.write_file(test_file, 'This file was created by the Puppet Development Kit to test if this folder was writable, you can safely remove this file.')
+ PDK::Util::Filesystem.rm_f(test_file)
+ rescue Errno::EACCES
+ raise PDK::CLI::FatalError, _("You do not have permission to write to '%{parent_dir}'") % {
+ parent_dir: parent_dir,
+ }
+ end
+
+ temp_target_dir = PDK::Util.make_tmpdir_name('pdk-module-target')
+
+ prepare_module_directory(temp_target_dir)
+
+ template_uri = PDK::Util::TemplateURI.new(opts)
+
+ if template_uri.default? && template_uri.default_ref?
+ PDK.logger.info _('Using the default template-url and template-ref.')
+ else
+ PDK.logger.info _(
+ "Using the %{method} template-url and template-ref '%{template_uri}'." % {
+ method: opts.key?(:'template-url') ? _('specified') : _('saved'),
+ template_uri: template_uri.metadata_format,
+ },
+ )
+ end
+
+ begin
+ context = PDK::Context::None.new(temp_target_dir)
+ PDK::Template.with(template_uri, context) do |template_dir|
+ template_dir.render_new_module(metadata.data['name'], metadata.data) do |relative_file_path, file_content, file_status|
+ next if [:delete, :unmanage].include?(file_status)
+ file = Pathname.new(temp_target_dir) + relative_file_path
+ file.dirname.mkpath
+ PDK::Util::Filesystem.write_file(file, file_content)
+ end
+
+ # Add information about the template used to generate the module to the
+ # metadata (for a future update command).
+ metadata.update!(template_dir.metadata)
+
+ metadata.write!(File.join(temp_target_dir, 'metadata.json'))
+ end
+ rescue ArgumentError => e
+ raise PDK::CLI::ExitWithError, e
+ end
+
+ # Only update the answers files after metadata has been written.
+ require 'pdk/answer_file'
+ if template_uri.default? && template_uri.default_ref?
+ # If the user specifies our default template url via the command
+ # line, remove the saved template-url answer so that the template_uri
+ # resolution can find new default URLs in the future.
+ PDK.config.set(%w[user module_defaults template-url], nil) if opts.key?(:'template-url')
+ else
+ # Save the template-url answers if the module was generated using a
+ # template/reference other than ours.
+ PDK.config.set(%w[user module_defaults template-url], template_uri.metadata_format)
+ end
+
+ begin
+ if PDK::Util::Filesystem.mv(temp_target_dir, target_dir)
+ unless opts[:'skip-bundle-install']
+ Dir.chdir(target_dir) do
+ require 'pdk/util/bundler'
+ PDK::Util::Bundler.ensure_bundle!
+ end
+ end
+
+ PDK.logger.info _("Module '%{name}' generated at path '%{path}'.") % {
+ name: opts[:module_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,
+ }
+ end
+ end
+
+ def self.username_from_login
+ require 'etc'
+
+ login = Etc.getlogin || ''
+ login_clean = login.downcase.gsub(%r{[^0-9a-z]}i, '')
+ login_clean = 'username' if login_clean.empty?
+
+ if login_clean != login
+ PDK.logger.debug _('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
+ end
+
+ def self.prepare_metadata(opts = {})
+ require 'pdk/answer_file'
+ require 'pdk/module/metadata'
+
+ opts[:username] = (opts[:username] || PDK.config.get_within_scopes('module_defaults.forge_username') || username_from_login).downcase
+
+ defaults = PDK::Module::Metadata::DEFAULTS.dup
+
+ defaults['name'] = "#{opts[:username]}-#{opts[:module_name]}" unless opts[:module_name].nil?
+ PDK.config.with_scoped_value('module_defaults.author') { |val| defaults['author'] = val }
+ PDK.config.with_scoped_value('module_defaults.license') { |val| defaults['license'] = val }
+ defaults['license'] = opts[:license] if opts.key?(:license)
+
+ metadata = PDK::Module::Metadata.new(defaults)
+ module_interview(metadata, opts) unless opts[:'skip-interview']
+
+ metadata
+ end
+
+ def self.prepare_module_directory(target_dir)
+ [
+ File.join(target_dir, 'examples'),
+ File.join(target_dir, 'files'),
+ File.join(target_dir, 'manifests'),
+ File.join(target_dir, 'templates'),
+ File.join(target_dir, 'tasks'),
+ ].each do |dir|
+ begin
+ PDK::Util::Filesystem.mkdir_p(dir)
+ rescue SystemCallError => e
+ raise PDK::CLI::FatalError, _("Unable to create directory '%{dir}': %{message}") % {
+ dir: dir,
+ message: e.message,
+ }
+ end
+ end
+ end
+
+ def self.module_interview(metadata, opts = {})
+ require 'pdk/module/metadata'
+ require 'pdk/cli/util/interview'
+
+ questions = [
+ {
+ name: 'module_name',
+ question: _('If you have a name for your module, add it here.'),
+ help: _('This is the name that will be associated with your module, it should be relevant to the modules content.'),
+ required: true,
+ validate_pattern: %r{\A[a-z][a-z0-9_]*\Z}i,
+ validate_message: _('Module names must begin with a lowercase letter and can only include lowercase letters, numbers, and underscores.'),
+ },
+ {
+ name: 'forge_username',
+ question: _('If you have a Puppet Forge username, add it here.'),
+ help: _('We can use this to upload your module to the Forge when it\'s complete.'),
+ required: true,
+ validate_pattern: %r{\A[a-z0-9]+\Z}i,
+ validate_message: _('Forge usernames can only contain lowercase letters and numbers'),
+ default: opts[:username],
+ },
+ {
+ name: 'version',
+ question: _('What version is this module?'),
+ help: _('Puppet uses Semantic Versioning (semver.org) to version modules.'),
+ required: true,
+ validate_pattern: %r{\A[0-9]+\.[0-9]+\.[0-9]+},
+ validate_message: _('Semantic Version numbers must be in the form MAJOR.MINOR.PATCH'),
+ default: metadata.data['version'],
+ forge_only: true,
+ },
+ {
+ name: 'author',
+ question: _('Who wrote this module?'),
+ help: _('This is used to credit the module\'s author.'),
+ required: true,
+ default: metadata.data['author'],
+ },
+ {
+ name: 'license',
+ question: _('What license does this module code fall under?'),
+ help: _('This should be an identifier from https://spdx.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,
+ type: :multi_select,
+ choices: PDK::Module::Metadata::OPERATING_SYSTEMS,
+ default: PDK::Module::Metadata::DEFAULT_OPERATING_SYSTEMS.map do |os_name|
+ # tty-prompt uses a 1-index
+ PDK::Module::Metadata::OPERATING_SYSTEMS.keys.index(os_name) + 1
+ end,
+ },
+ {
+ name: 'summary',
+ 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'],
+ forge_only: true,
+ },
+ {
+ name: 'source',
+ question: _('If there is a source code repository for this module, enter the URL here.'),
+ help: _('Skip this if no repository exists yet. You can update this later in the metadata.json.'),
+ required: true,
+ default: metadata.data['source'],
+ forge_only: true,
+ },
+ {
+ name: 'project_page',
+ question: _('If there is a URL where others can learn more about this module, enter it here.'),
+ help: _('Optional. You can update this later in the metadata.json.'),
+ default: metadata.data['project_page'],
+ forge_only: true,
+ },
+ {
+ name: 'issues_url',
+ question: _('If there is a public issue tracker for this module, enter its URL here.'),
+ help: _('Optional. You can update this later in the metadata.json.'),
+ default: metadata.data['issues_url'],
+ forge_only: true,
+ },
+ ]
+
+ prompt = TTY::Prompt.new(help_color: :cyan)
+
+ interview = PDK::CLI::Util::Interview.new(prompt)
+
+ if opts[:only_ask]
+ questions.reject! do |question|
+ if %w[module_name forge_username].include?(question[:name])
+ metadata.data['name'] && metadata.data['name'] =~ %r{\A[a-z0-9]+-[a-z][a-z0-9_]*\Z}i
+ else
+ !opts[:only_ask].include?(question[:name])
+ end
+ end
+ else
+ questions.reject! { |q| q[:name] == 'module_name' } if opts.key?(:module_name)
+ questions.reject! { |q| q[:name] == 'license' } if opts.key?(:license)
+ questions.reject! { |q| q[:forge_only] } unless opts[:'full-interview']
+ end
+
+ interview.add_questions(questions)
+
+ if PDK::Util::Filesystem.file?('metadata.json')
+ puts _(
+ "\nWe need to update the metadata.json file for this module, so we\'re going to ask you %{count} " \
+ "questions.\n",
+ ) % {
+ count: interview.num_questions,
+ }
+ else
+ puts _(
+ "\nWe need to create the metadata.json file for this module, so we\'re going to ask you %{count} " \
+ "questions.\n",
+ ) % {
+ count: interview.num_questions,
+ }
+ end
+
+ puts _(
+ '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",
+ )
+
+ answers = interview.run
+
+ if answers.nil?
+ PDK.logger.info _('No answers given, interview cancelled.')
+ exit 0
+ end
+
+ unless answers['forge_username'].nil?
+ opts[:username] = answers['forge_username']
+
+ unless answers['module_name'].nil?
+ opts[:module_name] = answers['module_name']
+
+ answers.delete('module_name')
+ end
+
+ answers['name'] = "#{opts[:username]}-" + (opts[:module_name])
+ answers.delete('forge_username')
+ end
+
+ answers['license'] = opts[:license] if opts.key?(:license)
+ answers['operatingsystem_support'].flatten! if answers.key?('operatingsystem_support')
+
+ metadata.update!(answers)
+
+ if opts[:prompt].nil? || opts[:prompt]
+ require 'pdk/cli/util'
+
+ continue = PDK::CLI::Util.prompt_for_yes(
+ _('Metadata will be generated based on this information, continue?'),
+ prompt: prompt,
+ cancel_message: _('Interview cancelled; exiting.'),
+ )
+
+ unless continue
+ PDK.logger.info _('Process cancelled; exiting.')
+ exit 0
+ end
+ end
+
+ require 'pdk/answer_file'
+ PDK.config.set(%w[user module_defaults forge_username], opts[:username]) unless opts[:username].nil?
+ PDK.config.set(%w[user module_defaults author], answers['author']) unless answers['author'].nil?
+ PDK.config.set(%w[user module_defaults license], answers['license']) unless answers['license'].nil?
+ end
+ end
+ end
+end