Dduvall has uploaded a new change for review. https://gerrit.wikimedia.org/r/165589
Change subject: Use 2-space indentation for all Ruby code ...................................................................... Use 2-space indentation for all Ruby code Our Ruby coding conventions specify to use 2 "soft" spaces for indentation. https://www.mediawiki.org/wiki/Manual:Coding_conventions/Ruby Change-Id: I7d57f3a66e7c9b138a27a9615fd2a89732c65e2a --- M lib/labs-vagrant.rb M lib/mediawiki-vagrant.rb M lib/mediawiki-vagrant/config.rb M lib/mediawiki-vagrant/destroy.rb M lib/mediawiki-vagrant/environment.rb M lib/mediawiki-vagrant/forward_port.rb M lib/mediawiki-vagrant/git-update.rb M lib/mediawiki-vagrant/hiera.rb M lib/mediawiki-vagrant/import-dump.rb M lib/mediawiki-vagrant/lsb_check/config.rb M lib/mediawiki-vagrant/lsb_check/provisioner.rb M lib/mediawiki-vagrant/middleware.rb M lib/mediawiki-vagrant/paste-puppet.rb M lib/mediawiki-vagrant/plugin_environment.rb M lib/mediawiki-vagrant/reload.rb M lib/mediawiki-vagrant/run-tests.rb M lib/mediawiki-vagrant/setting.rb M lib/mediawiki-vagrant/settings.rb M lib/mediawiki-vagrant/settings/definitions.rb M lib/mediawiki-vagrant/settings_definer.rb M lib/mediawiki-vagrant/settings_plugin.rb M lib/mediawiki-vagrant/setup.rb M lib/mediawiki-vagrant/version.rb 23 files changed, 1,242 insertions(+), 1,242 deletions(-) git pull ssh://gerrit.wikimedia.org:29418/mediawiki/vagrant refs/changes/89/165589/1 diff --git a/lib/labs-vagrant.rb b/lib/labs-vagrant.rb index b147196..e8e8898 100755 --- a/lib/labs-vagrant.rb +++ b/lib/labs-vagrant.rb @@ -7,84 +7,84 @@ case ARGV.shift when 'list-roles' - puts "Available roles:\n\n" - enabled = @mwv.roles_enabled - roles = @mwv.roles_available.sort.map { |role| - prefix = enabled.include?(role) ? '*' : ' ' - "#{prefix} #{role}" - } - col, *cols = roles.each_slice((roles.size/3.0).ceil).to_a - col.zip(*cols) { |a,b,c| - puts sprintf("%-26s %-26s %-26s", a, b, c) - } - puts "\nRoles marked with '*' are enabled." - puts "Note that roles enabled by dependency are not marked." - puts 'Use "labs-vagrant enable-role" & "labs-vagrant disable-role" to customize.' + puts "Available roles:\n\n" + enabled = @mwv.roles_enabled + roles = @mwv.roles_available.sort.map { |role| + prefix = enabled.include?(role) ? '*' : ' ' + "#{prefix} #{role}" + } + col, *cols = roles.each_slice((roles.size/3.0).ceil).to_a + col.zip(*cols) { |a,b,c| + puts sprintf("%-26s %-26s %-26s", a, b, c) + } + puts "\nRoles marked with '*' are enabled." + puts "Note that roles enabled by dependency are not marked." + puts 'Use "labs-vagrant enable-role" & "labs-vagrant disable-role" to customize.' when 'reset-roles' - if not ARGV.empty? or ['-h', '--help'].include? ARGV.first - puts 'Disable all optional roles.' - puts 'USAGE: labs-vagrant reset-roles' - end - @mwv.update_roles [] + if not ARGV.empty? or ['-h', '--help'].include? ARGV.first + puts 'Disable all optional roles.' + puts 'USAGE: labs-vagrant reset-roles' + end + @mwv.update_roles [] - puts 'All roles were disabled.' - puts COMMIT_CHANGES + puts 'All roles were disabled.' + puts COMMIT_CHANGES when 'enable-role' - if ARGV.empty? or ['-h', '--help'].include? ARGV.first - puts 'Enable an optional role (run "labs-vagrant list-roles" for a list).' - puts 'USAGE: labs-vagrant enable-role ROLE' - return 0 + if ARGV.empty? or ['-h', '--help'].include? ARGV.first + puts 'Enable an optional role (run "labs-vagrant list-roles" for a list).' + puts 'USAGE: labs-vagrant enable-role ROLE' + return 0 + end + avail = @mwv.roles_available + ARGV.each do |r| + if not avail.include? r + puts "'#{r}' is not a valid role." + return 1 end - avail = @mwv.roles_available - ARGV.each do |r| - if not avail.include? r - puts "'#{r}' is not a valid role." - return 1 - end - end - @mwv.update_roles(@mwv.roles_enabled + ARGV) - puts COMMIT_CHANGES + end + @mwv.update_roles(@mwv.roles_enabled + ARGV) + puts COMMIT_CHANGES when 'disable-role' - if ARGV.empty? or ['-h', '--help'].include? ARGV.first - puts 'Disable one or more optional roles.' - puts 'USAGE: labs-vagrant disable-role ROLE' - return 0 + if ARGV.empty? or ['-h', '--help'].include? ARGV.first + puts 'Disable one or more optional roles.' + puts 'USAGE: labs-vagrant disable-role ROLE' + return 0 + end + enabled = @mwv.roles_enabled + ARGV.each do |r| + if not enabled.include? r + puts "'#{r}' is not enabled." end - enabled = @mwv.roles_enabled - ARGV.each do |r| - if not enabled.include? r - puts "'#{r}' is not enabled." - end - end - @mwv.update_roles(enabled - ARGV) - puts COMMIT_CHANGES + end + @mwv.update_roles(enabled - ARGV) + puts COMMIT_CHANGES when 'provision' - puppet_path = '/vagrant/puppet' - exec "sudo env FACTER_environment=labs puppet apply \ - --modulepath #{puppet_path}/modules \ - --manifestdir #{puppet_path}/manifests \ - --templatedir #{puppet_path}/templates \ - --fileserverconfig #{puppet_path}/extra/fileserver.conf \ - --config_version #{puppet_path}/extra/config-version \ - --hiera_config #{puppet_path}/hiera.yaml \ - --verbose \ - --logdest console \ - --detailed-exitcodes \ - #{puppet_path}/manifests/site.pp" + puppet_path = '/vagrant/puppet' + exec "sudo env FACTER_environment=labs puppet apply \ + --modulepath #{puppet_path}/modules \ + --manifestdir #{puppet_path}/manifests \ + --templatedir #{puppet_path}/templates \ + --fileserverconfig #{puppet_path}/extra/fileserver.conf \ + --config_version #{puppet_path}/extra/config-version \ + --hiera_config #{puppet_path}/hiera.yaml \ + --verbose \ + --logdest console \ + --detailed-exitcodes \ + #{puppet_path}/manifests/site.pp" when 'git-update' - exec 'sudo -u vagrant -- /usr/local/bin/run-git-update' + exec 'sudo -u vagrant -- /usr/local/bin/run-git-update' else - puts 'USAGE: labs-vagrant COMMAND ...' - puts ' list-roles : list available roles' - puts ' reset-roles : disable all roles' - puts ' enable-role ROLENAME : enable a given role' - puts ' disable-role ROLENAME : disable a given role' - puts ' git-update : fetches new code from Gerrit' - puts ' provision : run puppet' + puts 'USAGE: labs-vagrant COMMAND ...' + puts ' list-roles : list available roles' + puts ' reset-roles : disable all roles' + puts ' enable-role ROLENAME : enable a given role' + puts ' disable-role ROLENAME : disable a given role' + puts ' git-update : fetches new code from Gerrit' + puts ' provision : run puppet' end diff --git a/lib/mediawiki-vagrant.rb b/lib/mediawiki-vagrant.rb index 3600253..fb2b8ac 100644 --- a/lib/mediawiki-vagrant.rb +++ b/lib/mediawiki-vagrant.rb @@ -1,95 +1,95 @@ module MediaWikiVagrant - class Plugin < Vagrant.plugin('2') - name 'MediaWiki-Vagrant' + class Plugin < Vagrant.plugin('2') + name 'MediaWiki-Vagrant' - command 'roles' do - require 'mediawiki-vagrant/roles/root' - Roles::Root - end - - command 'config' do - require 'mediawiki-vagrant/config' - Config - end - - command 'forward-port' do - require 'mediawiki-vagrant/forward_port' - ForwardPort - end - - command 'paste-puppet' do - require 'mediawiki-vagrant/paste-puppet' - PastePuppet - end - - command 'run-tests' do - require 'mediawiki-vagrant/run-tests' - RunTests - end - - command 'git-update' do - require 'mediawiki-vagrant/git-update' - GitUpdates - end - - command('list-roles', primary: false) do - # deprecated in favor of `vagrant roles list` - require 'mediawiki-vagrant/roles/list' - Roles::List - end - - command('reset-roles', primary: false) do - # deprecated in favor of `vagrant roles reset` - require 'mediawiki-vagrant/roles/reset' - Roles::Reset - end - - command('enable-role', primary: false) do - # deprecated in favor of `vagrant roles enable` - require 'mediawiki-vagrant/roles/enable' - Roles::Enable - end - - command('disable-role', primary: false) do - # deprecated in favor of `vagrant roles disable` - require 'mediawiki-vagrant/roles/disable' - Roles::Disable - end - - command 'import-dump' do - require 'mediawiki-vagrant/import-dump' - ImportDump - end - - command 'hiera' do - require 'mediawiki-vagrant/hiera' - Hiera - end - - action_hook(self::ALL_ACTIONS) do |hook| - require 'mediawiki-vagrant/middleware' - hook.before(Vagrant::Action::Builtin::Provision, Middleware) - end - - action_hook(:mediawiki, :machine_action_destroy) do |hook| - require 'mediawiki-vagrant/destroy' - hook.before(VagrantPlugins::ProviderVirtualBox::Action::Destroy, Destroy) - end - - provisioner 'mediawiki_reload' do - require 'mediawiki-vagrant/reload' - MediaWikiVagrant::Reload - end - - config(:lsb_check, :provisioner) do - require 'mediawiki-vagrant/lsb_check/config' - MediaWikiVagrant::LsbCheck::Config - end - - provisioner :lsb_check do - require 'mediawiki-vagrant/lsb_check/provisioner' - MediaWikiVagrant::LsbCheck::Provisioner - end - + command 'roles' do + require 'mediawiki-vagrant/roles/root' + Roles::Root end + + command 'config' do + require 'mediawiki-vagrant/config' + Config + end + + command 'forward-port' do + require 'mediawiki-vagrant/forward_port' + ForwardPort + end + + command 'paste-puppet' do + require 'mediawiki-vagrant/paste-puppet' + PastePuppet + end + + command 'run-tests' do + require 'mediawiki-vagrant/run-tests' + RunTests + end + + command 'git-update' do + require 'mediawiki-vagrant/git-update' + GitUpdates + end + + command('list-roles', primary: false) do + # deprecated in favor of `vagrant roles list` + require 'mediawiki-vagrant/roles/list' + Roles::List + end + + command('reset-roles', primary: false) do + # deprecated in favor of `vagrant roles reset` + require 'mediawiki-vagrant/roles/reset' + Roles::Reset + end + + command('enable-role', primary: false) do + # deprecated in favor of `vagrant roles enable` + require 'mediawiki-vagrant/roles/enable' + Roles::Enable + end + + command('disable-role', primary: false) do + # deprecated in favor of `vagrant roles disable` + require 'mediawiki-vagrant/roles/disable' + Roles::Disable + end + + command 'import-dump' do + require 'mediawiki-vagrant/import-dump' + ImportDump + end + + command 'hiera' do + require 'mediawiki-vagrant/hiera' + Hiera + end + + action_hook(self::ALL_ACTIONS) do |hook| + require 'mediawiki-vagrant/middleware' + hook.before(Vagrant::Action::Builtin::Provision, Middleware) + end + + action_hook(:mediawiki, :machine_action_destroy) do |hook| + require 'mediawiki-vagrant/destroy' + hook.before(VagrantPlugins::ProviderVirtualBox::Action::Destroy, Destroy) + end + + provisioner 'mediawiki_reload' do + require 'mediawiki-vagrant/reload' + MediaWikiVagrant::Reload + end + + config(:lsb_check, :provisioner) do + require 'mediawiki-vagrant/lsb_check/config' + MediaWikiVagrant::LsbCheck::Config + end + + provisioner :lsb_check do + require 'mediawiki-vagrant/lsb_check/provisioner' + MediaWikiVagrant::LsbCheck::Provisioner + end + + end end diff --git a/lib/mediawiki-vagrant/config.rb b/lib/mediawiki-vagrant/config.rb index 0e98f1d..42b5cd0 100644 --- a/lib/mediawiki-vagrant/config.rb +++ b/lib/mediawiki-vagrant/config.rb @@ -4,166 +4,166 @@ require "optparse" module MediaWikiVagrant - # Provides a command-line interface for configuration of MediaWiki-Vagrant - # settings. - # - class Config < Vagrant.plugin(2, :command) - include PluginEnvironment - include SettingsPlugin + # Provides a command-line interface for configuration of MediaWiki-Vagrant + # settings. + # + class Config < Vagrant.plugin(2, :command) + include PluginEnvironment + include SettingsPlugin - def self.synopsis - "configures mediawiki-vagrant settings" - end - - def execute - options = { - interactive: false, - list: false, - required: false, - get: [], - unset: [], - } - - opts = OptionParser.new do |o| - o.banner = "Usage: vagrant config [options] [name] [value]" - o.separator "" - o.separator "Options:" - o.separator "" - - o.on("--all", "Configure all settings") do - options[:interactive] = true - end - - o.on("--required", "Configure only required settings") do - options[:interactive] = true - options[:required] = true - end - - o.on("--list", "List all settings") do - options[:list] = true - end - - o.on("--get NAME", "Get a configured setting") do |name| - options[:get] << name - end - - o.on("--unset NAME", "Remove a configured setting") do |name| - options[:unset] << name - end - end - - argv = parse_options(opts) - return if !argv - - if options[:list] - list_settings - elsif options[:interactive] - interactively_configure(options) - elsif argv.length == 2 - configure_setting(*argv) - elsif options[:get].any? || options[:unset].any? - get_settings(options[:get]) - unset_settings(options[:unset]) - else - @env.ui.error opts - return 1 - end - - 0 - end - - private - - # Configures the given setting with the given value. - # - def configure_setting(name, value) - configure do |settings| - settings.unset!(name) - settings[name] = parse_setting(settings.setting(name), value) - end - end - - # Displays current values for the given settings. - # - def get_settings(names) - configure do |settings| - names.each do |name| - if setting = settings.setting(name) - @env.ui.info setting.value, :bold => setting.set? - end - end - end - end - - # Wraps the given string according to the current screen width and - # indents the resulting block of text to the given indentation level. - # - def indent(string, n) - tabs = "\t" * n - wrap = screen_width - (n * 8) - 1 - - tabs + string.gsub(/(.{1,#{wrap}})(\s+|\Z)/, "\\1\n#{tabs}").rstrip - end - - # Displays a series of prompts for user configuration of either all - # defined or only required settings. - # - def interactively_configure(options) - configure do |settings| - scope = settings.select do |name, setting| - Settings.definitions.include?(name) && !setting.internal? - end - - if options[:required] - scope = scope.reject { |_, setting| setting.default? || setting.set? } - end - - scope.each do |name, setting| - @env.ui.info setting.description, :bold => true - @env.ui.info setting.help unless setting.help.nil? - - value = setting_display_value(setting.value) - - @env.ui.info name, :bold => true, :new_line => false - - prompt = value.empty? ? "" : " [#{value}]" - prompt += ": " - - input = @env.ui.ask(prompt).strip - @env.ui.info "" - - if !input.empty? - setting.value = parse_setting(setting, input) - elsif setting.allows_empty? - setting.value = input.strip - end - end - end - end - - # Lists all defined settings and their currently set values. - # - def list_settings - Settings.definitions.reject { |_, setting| setting.internal? }.each do |name, setting| - @env.ui.info "#{name}\t#{setting.description}", :bold => true - @env.ui.info indent(setting.help, 2) unless setting.help.nil? - @env.ui.info "" - end - end - - # Current width of the terminal. - # - def screen_width - @screen_width ||= `tput cols`.chomp.to_i rescue 80 - end - - # Unsets the given settings. - # - def unset_settings(names) - configure do |settings| - names.each { |name| settings.unset!(name) } - end - end + def self.synopsis + "configures mediawiki-vagrant settings" end + + def execute + options = { + interactive: false, + list: false, + required: false, + get: [], + unset: [], + } + + opts = OptionParser.new do |o| + o.banner = "Usage: vagrant config [options] [name] [value]" + o.separator "" + o.separator "Options:" + o.separator "" + + o.on("--all", "Configure all settings") do + options[:interactive] = true + end + + o.on("--required", "Configure only required settings") do + options[:interactive] = true + options[:required] = true + end + + o.on("--list", "List all settings") do + options[:list] = true + end + + o.on("--get NAME", "Get a configured setting") do |name| + options[:get] << name + end + + o.on("--unset NAME", "Remove a configured setting") do |name| + options[:unset] << name + end + end + + argv = parse_options(opts) + return if !argv + + if options[:list] + list_settings + elsif options[:interactive] + interactively_configure(options) + elsif argv.length == 2 + configure_setting(*argv) + elsif options[:get].any? || options[:unset].any? + get_settings(options[:get]) + unset_settings(options[:unset]) + else + @env.ui.error opts + return 1 + end + + 0 + end + + private + + # Configures the given setting with the given value. + # + def configure_setting(name, value) + configure do |settings| + settings.unset!(name) + settings[name] = parse_setting(settings.setting(name), value) + end + end + + # Displays current values for the given settings. + # + def get_settings(names) + configure do |settings| + names.each do |name| + if setting = settings.setting(name) + @env.ui.info setting.value, :bold => setting.set? + end + end + end + end + + # Wraps the given string according to the current screen width and + # indents the resulting block of text to the given indentation level. + # + def indent(string, n) + tabs = "\t" * n + wrap = screen_width - (n * 8) - 1 + + tabs + string.gsub(/(.{1,#{wrap}})(\s+|\Z)/, "\\1\n#{tabs}").rstrip + end + + # Displays a series of prompts for user configuration of either all + # defined or only required settings. + # + def interactively_configure(options) + configure do |settings| + scope = settings.select do |name, setting| + Settings.definitions.include?(name) && !setting.internal? + end + + if options[:required] + scope = scope.reject { |_, setting| setting.default? || setting.set? } + end + + scope.each do |name, setting| + @env.ui.info setting.description, :bold => true + @env.ui.info setting.help unless setting.help.nil? + + value = setting_display_value(setting.value) + + @env.ui.info name, :bold => true, :new_line => false + + prompt = value.empty? ? "" : " [#{value}]" + prompt += ": " + + input = @env.ui.ask(prompt).strip + @env.ui.info "" + + if !input.empty? + setting.value = parse_setting(setting, input) + elsif setting.allows_empty? + setting.value = input.strip + end + end + end + end + + # Lists all defined settings and their currently set values. + # + def list_settings + Settings.definitions.reject { |_, setting| setting.internal? }.each do |name, setting| + @env.ui.info "#{name}\t#{setting.description}", :bold => true + @env.ui.info indent(setting.help, 2) unless setting.help.nil? + @env.ui.info "" + end + end + + # Current width of the terminal. + # + def screen_width + @screen_width ||= `tput cols`.chomp.to_i rescue 80 + end + + # Unsets the given settings. + # + def unset_settings(names) + configure do |settings| + names.each { |name| settings.unset!(name) } + end + end + end end diff --git a/lib/mediawiki-vagrant/destroy.rb b/lib/mediawiki-vagrant/destroy.rb index 1e0cf31..9aa8b59 100644 --- a/lib/mediawiki-vagrant/destroy.rb +++ b/lib/mediawiki-vagrant/destroy.rb @@ -1,18 +1,18 @@ require 'mediawiki-vagrant/environment' module MediaWikiVagrant - class Destroy - def initialize(app, env) - @app = app - @mwv = Environment.new(env[:root_path] || env[:cwd]) - end - - def call(env) - if @mwv.valid? - env[:ui].info 'Removing puppet created files...' - @mwv.purge_puppet_created_files - end - @app.call(env) - end + class Destroy + def initialize(app, env) + @app = app + @mwv = Environment.new(env[:root_path] || env[:cwd]) end + + def call(env) + if @mwv.valid? + env[:ui].info 'Removing puppet created files...' + @mwv.purge_puppet_created_files + end + @app.call(env) + end + end end diff --git a/lib/mediawiki-vagrant/environment.rb b/lib/mediawiki-vagrant/environment.rb index db08726..1619dee 100644 --- a/lib/mediawiki-vagrant/environment.rb +++ b/lib/mediawiki-vagrant/environment.rb @@ -3,180 +3,180 @@ require 'yaml' module MediaWikiVagrant - # Represents the current environment from which MediaWiki-Vagrant commands - # are executed. + # Represents the current environment from which MediaWiki-Vagrant commands + # are executed. + # + class Environment + STALENESS = 604800 + + # Initialize a new environment for the given directory. # - class Environment - STALENESS = 604800 - - # Initialize a new environment for the given directory. - # - def initialize(directory) - @directory = directory - @path = Pathname.new(@directory) - end - - # The HEAD commit of local master branch, if we're executing from - # within a cloned Git repo. - # - def commit - master = path('.git/refs/heads/master') - master.read[0..8] if master.exist? - end - - # Returns an absolute path from the given relative path. - # - # @return [Pathname] - # - def path(*subpaths) - @path.join(*subpaths) - end - - # Removes all enabled roles that are no longer available. - # - def prune_roles - migrate_roles - update_roles(roles_enabled & roles_available) - end - - # Returns all available Puppet roles. - # - # @return [Array] - # - def roles_available - manifests = Dir[module_path('role/manifests/*.pp')] - manifests.map! { |file| File.read(file).match(/^class\s*role::(\w+)/) { |m| m[1] } } - manifests.compact.sort.uniq - ['generic', 'mediawiki', 'labs_initial_content'] - end - - # Returns enabled Puppet roles. - # - # @return [Array] - # - def roles_enabled - migrate_roles - - hiera = hiera_load - return [] unless hiera.key?('classes') - - roles = hiera['classes'].map do |r| - r.match(/^role::(\S+)/) { |m| m[1] } - end - roles.compact.sort.uniq - end - - # Updates the enabled Puppet roles to the given set. - # - def update_roles(roles) - classes = roles.sort.uniq.map do |r| - "role::#{r.sub(/^role::/, '')}" - end - hiera_set('classes', classes) - end - - # If it has been a week or more since remote commits have been fetched, - # run 'git fetch origin', unless the user disabled automatic fetching. - # You can disable automatic fetching by creating an empty 'no-updates' - # file in the root directory of your repository. - # - def update - if stale_head? && !(ENV.include?('MWV_NO_UPDATE') || path('no-update').exist?) - system('git fetch origin', chdir: @directory) - end - end - - # Whether this is a valid MediaWiki-Vagrant environment. This should - # be used as a guard in middleware. - # - def valid? - path('lib/mediawiki-vagrant.rb').exist? - end - - # Removes files created by the puppet provisioner. - # - def purge_puppet_created_files - FileUtils.rm_f Dir[path('settings.d/puppet-managed/*.php')] - FileUtils.rm_rf path('settings.d/multiwiki') - FileUtils.rm_rf path('settings.d/wikis') - FileUtils.rm_rf path('vagrant.d') - FileUtils.rm_f path('mediawiki/LocalSettings.php') - end - - # Deletes the given entry from the vagrant-managed hiera file. - # - # @param key [String] - # - def hiera_delete(key) - if hiera_data.exist? - hiera = hiera_load - if hiera.key?(key) - hiera.delete(key) - hiera_save(hiera) - end - end - end - - # Returns the value of the given entry in the vagrant-managed hiera - # file, or nil if none exists. - # - # @param key [String] - # - # @return [Object] - # - def hiera_get(key) - hiera_load[key] - end - - # Saves the given key/value pair to the vagrant-managed hiera file. - # - # @param key [String] - # @param value [Object] - # - # @return [Hash] New hiera settings. - # - def hiera_set(key, value) - hiera_load.tap do |hiera| - hiera[key] = value - hiera_save(hiera) - end - end - - private - - def module_path(*subpaths) - path('puppet/modules', *subpaths) - end - - def hiera_data - path('puppet/hieradata/vagrant-managed.yaml') - end - - def hiera_load - return {} unless hiera_data.exist? - hiera_data.open('r') { |io| YAML.load(io) } - end - - def hiera_save(data) - hiera_data.open('w') { |f| f.write(YAML.dump(data)) } - end - - def stale_head? - head = path('.git/FETCH_HEAD') - head.exist? && (Time.now - head.mtime) > STALENESS - end - - # Migrate legacy roles to new format - # - def migrate_roles - legacy_file = path('puppet/manifests/manifests.d/vagrant-managed.pp') - if legacy_file.exist? - legacy_roles = legacy_file.each_line.map do |l| - l.match(/^[^#]*include role::(\S+)/) { |m| m[1] } - end - update_roles(legacy_roles.compact.sort.uniq) - FileUtils.rm legacy_file - end - end - + def initialize(directory) + @directory = directory + @path = Pathname.new(@directory) end + + # The HEAD commit of local master branch, if we're executing from + # within a cloned Git repo. + # + def commit + master = path('.git/refs/heads/master') + master.read[0..8] if master.exist? + end + + # Returns an absolute path from the given relative path. + # + # @return [Pathname] + # + def path(*subpaths) + @path.join(*subpaths) + end + + # Removes all enabled roles that are no longer available. + # + def prune_roles + migrate_roles + update_roles(roles_enabled & roles_available) + end + + # Returns all available Puppet roles. + # + # @return [Array] + # + def roles_available + manifests = Dir[module_path('role/manifests/*.pp')] + manifests.map! { |file| File.read(file).match(/^class\s*role::(\w+)/) { |m| m[1] } } + manifests.compact.sort.uniq - ['generic', 'mediawiki', 'labs_initial_content'] + end + + # Returns enabled Puppet roles. + # + # @return [Array] + # + def roles_enabled + migrate_roles + + hiera = hiera_load + return [] unless hiera.key?('classes') + + roles = hiera['classes'].map do |r| + r.match(/^role::(\S+)/) { |m| m[1] } + end + roles.compact.sort.uniq + end + + # Updates the enabled Puppet roles to the given set. + # + def update_roles(roles) + classes = roles.sort.uniq.map do |r| + "role::#{r.sub(/^role::/, '')}" + end + hiera_set('classes', classes) + end + + # If it has been a week or more since remote commits have been fetched, + # run 'git fetch origin', unless the user disabled automatic fetching. + # You can disable automatic fetching by creating an empty 'no-updates' + # file in the root directory of your repository. + # + def update + if stale_head? && !(ENV.include?('MWV_NO_UPDATE') || path('no-update').exist?) + system('git fetch origin', chdir: @directory) + end + end + + # Whether this is a valid MediaWiki-Vagrant environment. This should + # be used as a guard in middleware. + # + def valid? + path('lib/mediawiki-vagrant.rb').exist? + end + + # Removes files created by the puppet provisioner. + # + def purge_puppet_created_files + FileUtils.rm_f Dir[path('settings.d/puppet-managed/*.php')] + FileUtils.rm_rf path('settings.d/multiwiki') + FileUtils.rm_rf path('settings.d/wikis') + FileUtils.rm_rf path('vagrant.d') + FileUtils.rm_f path('mediawiki/LocalSettings.php') + end + + # Deletes the given entry from the vagrant-managed hiera file. + # + # @param key [String] + # + def hiera_delete(key) + if hiera_data.exist? + hiera = hiera_load + if hiera.key?(key) + hiera.delete(key) + hiera_save(hiera) + end + end + end + + # Returns the value of the given entry in the vagrant-managed hiera + # file, or nil if none exists. + # + # @param key [String] + # + # @return [Object] + # + def hiera_get(key) + hiera_load[key] + end + + # Saves the given key/value pair to the vagrant-managed hiera file. + # + # @param key [String] + # @param value [Object] + # + # @return [Hash] New hiera settings. + # + def hiera_set(key, value) + hiera_load.tap do |hiera| + hiera[key] = value + hiera_save(hiera) + end + end + + private + + def module_path(*subpaths) + path('puppet/modules', *subpaths) + end + + def hiera_data + path('puppet/hieradata/vagrant-managed.yaml') + end + + def hiera_load + return {} unless hiera_data.exist? + hiera_data.open('r') { |io| YAML.load(io) } + end + + def hiera_save(data) + hiera_data.open('w') { |f| f.write(YAML.dump(data)) } + end + + def stale_head? + head = path('.git/FETCH_HEAD') + head.exist? && (Time.now - head.mtime) > STALENESS + end + + # Migrate legacy roles to new format + # + def migrate_roles + legacy_file = path('puppet/manifests/manifests.d/vagrant-managed.pp') + if legacy_file.exist? + legacy_roles = legacy_file.each_line.map do |l| + l.match(/^[^#]*include role::(\S+)/) { |m| m[1] } + end + update_roles(legacy_roles.compact.sort.uniq) + FileUtils.rm legacy_file + end + end + + end end diff --git a/lib/mediawiki-vagrant/forward_port.rb b/lib/mediawiki-vagrant/forward_port.rb index dcada0a..024fb3e 100644 --- a/lib/mediawiki-vagrant/forward_port.rb +++ b/lib/mediawiki-vagrant/forward_port.rb @@ -4,82 +4,82 @@ require "optparse" module MediaWikiVagrant - # Configures port forwarding from the host to the guest VM. - # - class ForwardPort < Vagrant.plugin(2, :command) - include PluginEnvironment - include SettingsPlugin + # Configures port forwarding from the host to the guest VM. + # + class ForwardPort < Vagrant.plugin(2, :command) + include PluginEnvironment + include SettingsPlugin - def self.synopsis - "configures port forwarding from the host to the guest VM" - end - - def execute - options = { - list: false, - remove: [] - } - - opts = OptionParser.new do |o| - o.banner = "Usage: vagrant forward-port [options] [host-port guest-port [...]]" - o.separator "" - o.separator "Options:" - o.separator "" - - o.on("-l", "--list", "List currently forwarded ports") do - options[:list] = true - end - - o.on("-r", "--remove PORT", "Remove forwarding for the given host port") do |port| - options[:remove] << port - end - end - - argv = parse_options(opts) - return if !argv - - if options[:list] - list - elsif options[:remove].any? - remove(options[:remove].map(&:to_i)) - elsif argv.length == 2 - forward(*(argv.map(&:to_i))) - else - @env.ui.error opts - return 1 - end - - 0 - end - - private - - def forward(host_port, guest_port) - configure do |settings| - setting = settings.setting(:forward_ports) - setting.value = {} unless setting.set? - setting.value[guest_port] = host_port - end - - @env.ui.info "Local port #{host_port} will now forward to your VM's port #{guest_port}" - @env.ui.warn "You'll need to `vagrant reload` for this change to take effect" - end - - def list - @env.ui.info "Local port => VM's port" - @env.ui.info "-----------------------" - configure do |settings| - settings[:forward_ports].each do |guest_port, host_port| - @env.ui.info "#{host_port} => #{guest_port}" - end - end - end - - def remove(ports) - configure do |settings| - setting = settings.setting(:forward_ports) - setting.value.reject! { |guest, host| ports.include?(host) } if setting.set? - end - end + def self.synopsis + "configures port forwarding from the host to the guest VM" end + + def execute + options = { + list: false, + remove: [] + } + + opts = OptionParser.new do |o| + o.banner = "Usage: vagrant forward-port [options] [host-port guest-port [...]]" + o.separator "" + o.separator "Options:" + o.separator "" + + o.on("-l", "--list", "List currently forwarded ports") do + options[:list] = true + end + + o.on("-r", "--remove PORT", "Remove forwarding for the given host port") do |port| + options[:remove] << port + end + end + + argv = parse_options(opts) + return if !argv + + if options[:list] + list + elsif options[:remove].any? + remove(options[:remove].map(&:to_i)) + elsif argv.length == 2 + forward(*(argv.map(&:to_i))) + else + @env.ui.error opts + return 1 + end + + 0 + end + + private + + def forward(host_port, guest_port) + configure do |settings| + setting = settings.setting(:forward_ports) + setting.value = {} unless setting.set? + setting.value[guest_port] = host_port + end + + @env.ui.info "Local port #{host_port} will now forward to your VM's port #{guest_port}" + @env.ui.warn "You'll need to `vagrant reload` for this change to take effect" + end + + def list + @env.ui.info "Local port => VM's port" + @env.ui.info "-----------------------" + configure do |settings| + settings[:forward_ports].each do |guest_port, host_port| + @env.ui.info "#{host_port} => #{guest_port}" + end + end + end + + def remove(ports) + configure do |settings| + setting = settings.setting(:forward_ports) + setting.value.reject! { |guest, host| ports.include?(host) } if setting.set? + end + end + end end diff --git a/lib/mediawiki-vagrant/git-update.rb b/lib/mediawiki-vagrant/git-update.rb index 5f892c4..19c2d37 100644 --- a/lib/mediawiki-vagrant/git-update.rb +++ b/lib/mediawiki-vagrant/git-update.rb @@ -1,17 +1,17 @@ class GitUpdates < Vagrant.plugin(2, :command) - def self.synopsis - "fetches new code from Gerrit" + def self.synopsis + "fetches new code from Gerrit" + end + + def execute + if %w(-h --help).include? @argv.first + @env.ui.info 'Usage: vagrant git-update [-h]' + return 0 end - def execute - if %w(-h --help).include? @argv.first - @env.ui.info 'Usage: vagrant git-update [-h]' - return 0 - end - - with_target_vms(nil, :single_target => true) do |vm| - opts = { :extra_args => @argv.unshift('run-git-update') } - vm.action :ssh, :ssh_opts => opts - end + with_target_vms(nil, :single_target => true) do |vm| + opts = { :extra_args => @argv.unshift('run-git-update') } + vm.action :ssh, :ssh_opts => opts end + end end diff --git a/lib/mediawiki-vagrant/hiera.rb b/lib/mediawiki-vagrant/hiera.rb index 8c95588..6316d4f 100644 --- a/lib/mediawiki-vagrant/hiera.rb +++ b/lib/mediawiki-vagrant/hiera.rb @@ -2,61 +2,61 @@ require "optparse" module MediaWikiVagrant - # Provides a command-line interface for configuration of hiera settings. - # - class Hiera < Vagrant.plugin(2, :command) - include PluginEnvironment + # Provides a command-line interface for configuration of hiera settings. + # + class Hiera < Vagrant.plugin(2, :command) + include PluginEnvironment - def self.synopsis - "configures hiera settings" - end - - def execute - options = { - unset: [], - } - - opts = OptionParser.new do |o| - o.banner = "Usage: vagrant hiera [options] [key] [value]" - o.separator "" - o.separator "Options:" - o.separator "" - - o.on("--unset NAME", "Remove a configured key") do |name| - options[:unset] << name - end - end - - argv = parse_options(opts) - return if !argv - - if options[:unset].any? - unset_key(options[:unset]) - elsif argv.length == 2 - set_key(*argv) - else - @env.ui.error opts - return 1 - end - - 0 - end - - private - - # Configures the given key with the given value. - # - def set_key(name, value) - # Let yaml coerce the provided value to a native type - # This is especially useful for booleans and numbers - @mwv.hiera_set(name, YAML.load(value)) - end - - # Unsets the given keys. - # - def unset_key(names) - names.each { |name| @mwv.hiera_delete(name) } - end + def self.synopsis + "configures hiera settings" end + + def execute + options = { + unset: [], + } + + opts = OptionParser.new do |o| + o.banner = "Usage: vagrant hiera [options] [key] [value]" + o.separator "" + o.separator "Options:" + o.separator "" + + o.on("--unset NAME", "Remove a configured key") do |name| + options[:unset] << name + end + end + + argv = parse_options(opts) + return if !argv + + if options[:unset].any? + unset_key(options[:unset]) + elsif argv.length == 2 + set_key(*argv) + else + @env.ui.error opts + return 1 + end + + 0 + end + + private + + # Configures the given key with the given value. + # + def set_key(name, value) + # Let yaml coerce the provided value to a native type + # This is especially useful for booleans and numbers + @mwv.hiera_set(name, YAML.load(value)) + end + + # Unsets the given keys. + # + def unset_key(names) + names.each { |name| @mwv.hiera_delete(name) } + end + end end diff --git a/lib/mediawiki-vagrant/import-dump.rb b/lib/mediawiki-vagrant/import-dump.rb index 9e1388b..8ae86ec 100644 --- a/lib/mediawiki-vagrant/import-dump.rb +++ b/lib/mediawiki-vagrant/import-dump.rb @@ -1,16 +1,16 @@ class ImportDump < Vagrant.plugin(2, :command) - def self.synopsis - "imports an XML file into MediaWiki" - end + def self.synopsis + "imports an XML file into MediaWiki" + end - def execute - if ['-h', '--help'].include? @argv.first - @env.ui.info "Usage: vagrant import-dump dumpfile.xml [-h]" - return 0 - end - opts = { extra_args: @argv.unshift('import-mediawiki-dump') } - with_target_vms(nil, :single_target => true) do |vm| - vm.action :ssh, ssh_opts: opts - end + def execute + if ['-h', '--help'].include? @argv.first + @env.ui.info "Usage: vagrant import-dump dumpfile.xml [-h]" + return 0 end + opts = { extra_args: @argv.unshift('import-mediawiki-dump') } + with_target_vms(nil, :single_target => true) do |vm| + vm.action :ssh, ssh_opts: opts + end + end end diff --git a/lib/mediawiki-vagrant/lsb_check/config.rb b/lib/mediawiki-vagrant/lsb_check/config.rb index 3531a41..0ce68ba 100644 --- a/lib/mediawiki-vagrant/lsb_check/config.rb +++ b/lib/mediawiki-vagrant/lsb_check/config.rb @@ -1,27 +1,27 @@ module MediaWikiVagrant - module LsbCheck - class Config < Vagrant.plugin('2', :config) - attr_accessor :vendor - attr_accessor :version + module LsbCheck + class Config < Vagrant.plugin('2', :config) + attr_accessor :vendor + attr_accessor :version - def initialize - @vendor = UNSET_VALUE - @version = UNSET_VALUE - end + def initialize + @vendor = UNSET_VALUE + @version = UNSET_VALUE + end - def finalize! - @vendor = 'Ubuntu' if @vendor == UNSET_VALUE - @version = nil if @version == UNSET_VALUE - end + def finalize! + @vendor = 'Ubuntu' if @vendor == UNSET_VALUE + @version = nil if @version == UNSET_VALUE + end - def validate(machine) - errors = _detected_errors - if !version - errors << '`version` must be set.' - end - { 'lsb_check provisioner' => errors } - end + def validate(machine) + errors = _detected_errors + if !version + errors << '`version` must be set.' end + { 'lsb_check provisioner' => errors } + end end + end end diff --git a/lib/mediawiki-vagrant/lsb_check/provisioner.rb b/lib/mediawiki-vagrant/lsb_check/provisioner.rb index 2a3874a..e6c60e0 100644 --- a/lib/mediawiki-vagrant/lsb_check/provisioner.rb +++ b/lib/mediawiki-vagrant/lsb_check/provisioner.rb @@ -1,41 +1,41 @@ module MediaWikiVagrant - module LsbCheck - # Validates lsb_release vendor and version - # - class Provisioner < Vagrant.plugin('2', :provisioner) - def provision - execute_inline <<-end_ - set -e - REQUIRED_VENDOR=#{config.vendor} - REQUIRED_VERSION=#{config.version} - VENDOR=$(lsb_release -is) - VERSION=$(lsb_release -rs) - if ! [[ $VENDOR == $REQUIRED_VENDOR && $VERSION == $REQUIRED_VERSION ]]; then - echo "MediaWiki-Vagrant requires a $REQUIRED_VENDOR $REQUIRED_VERSION guest OS" - echo 'Your guest OS reports:' - lsb_release -irc | sed 's/^/ /' - echo 'Please rebuild using `vagrant destroy -f; vagrant up`' - echo 'NOTE: this will cause you to lose any data saved in the VM.' - exit 1 - fi - end_ - end + module LsbCheck + # Validates lsb_release vendor and version + # + class Provisioner < Vagrant.plugin('2', :provisioner) + def provision + execute_inline <<-end_ + set -e + REQUIRED_VENDOR=#{config.vendor} + REQUIRED_VERSION=#{config.version} + VENDOR=$(lsb_release -is) + VERSION=$(lsb_release -rs) + if ! [[ $VENDOR == $REQUIRED_VENDOR && $VERSION == $REQUIRED_VERSION ]]; then + echo "MediaWiki-Vagrant requires a $REQUIRED_VENDOR $REQUIRED_VERSION guest OS" + echo 'Your guest OS reports:' + lsb_release -irc | sed 's/^/ /' + echo 'Please rebuild using `vagrant destroy -f; vagrant up`' + echo 'NOTE: this will cause you to lose any data saved in the VM.' + exit 1 + fi + end_ + end - private + private - def execute_inline(script) - @machine.communicate.tap do |comm| - comm.execute("cat <<'EOF' | /usr/bin/env bash\n#{script}\nEOF", error_class: Error) - end - end + def execute_inline(script) + @machine.communicate.tap do |comm| + comm.execute("cat <<'EOF' | /usr/bin/env bash\n#{script}\nEOF", error_class: Error) end - - # Custom error to avoid need for l10n keys - # - class Error < Vagrant::Errors::VagrantError - def to_s - extra_data[:stdout] - end - end + end end + + # Custom error to avoid need for l10n keys + # + class Error < Vagrant::Errors::VagrantError + def to_s + extra_data[:stdout] + end + end + end end diff --git a/lib/mediawiki-vagrant/middleware.rb b/lib/mediawiki-vagrant/middleware.rb index fe3b674..448fb14 100644 --- a/lib/mediawiki-vagrant/middleware.rb +++ b/lib/mediawiki-vagrant/middleware.rb @@ -1,19 +1,19 @@ require 'mediawiki-vagrant/environment' module MediaWikiVagrant - class Middleware - def initialize(app, env) - @app = app - @mwv = Environment.new(env[:root_path]) - end - - def call(env) - if @mwv.valid? - @mwv.prune_roles - $FACTER['provider_name'] = env[:machine].provider_name - end - - @app.call(env) - end + class Middleware + def initialize(app, env) + @app = app + @mwv = Environment.new(env[:root_path]) end + + def call(env) + if @mwv.valid? + @mwv.prune_roles + $FACTER['provider_name'] = env[:machine].provider_name + end + + @app.call(env) + end + end end diff --git a/lib/mediawiki-vagrant/paste-puppet.rb b/lib/mediawiki-vagrant/paste-puppet.rb index 9db7283..9745595 100644 --- a/lib/mediawiki-vagrant/paste-puppet.rb +++ b/lib/mediawiki-vagrant/paste-puppet.rb @@ -2,33 +2,33 @@ class PastePuppet < Vagrant.plugin(2, :command) - URL = URI('http://dpaste.de/api/') + URL = URI('http://dpaste.de/api/') - def self.synopsis - "uploads your puppet logs to dpaste.de pastebin" - end + def self.synopsis + "uploads your puppet logs to dpaste.de pastebin" + end - def latest_logfile - Dir[File.join $DIR, '/logs/puppet/*.log'].max_by { |f| File.mtime f } - end + def latest_logfile + Dir[File.join $DIR, '/logs/puppet/*.log'].max_by { |f| File.mtime f } + end - def execute - begin - res = Net::HTTP.post_form URL, content: File.read(latest_logfile) - raise unless res.value.nil? and res.body =~ /^"[^"]+"$/ - rescue RuntimeError - @env.ui.error "Unexpected response from #{URL}." - 1 - rescue TypeError - @env.ui.error 'No Puppet log files found.' - 1 - rescue SocketError, Net::HTTPExceptions - @env.ui.error "Unable to connect to #{URL}." - 1 - else - @env.ui.success "HTTP #{res.code} #{res.msg}" - @env.ui.info res.body[1...-1] - 0 - end + def execute + begin + res = Net::HTTP.post_form URL, content: File.read(latest_logfile) + raise unless res.value.nil? and res.body =~ /^"[^"]+"$/ + rescue RuntimeError + @env.ui.error "Unexpected response from #{URL}." + 1 + rescue TypeError + @env.ui.error 'No Puppet log files found.' + 1 + rescue SocketError, Net::HTTPExceptions + @env.ui.error "Unable to connect to #{URL}." + 1 + else + @env.ui.success "HTTP #{res.code} #{res.msg}" + @env.ui.info res.body[1...-1] + 0 end + end end diff --git a/lib/mediawiki-vagrant/plugin_environment.rb b/lib/mediawiki-vagrant/plugin_environment.rb index db7e8c0..102bf96 100644 --- a/lib/mediawiki-vagrant/plugin_environment.rb +++ b/lib/mediawiki-vagrant/plugin_environment.rb @@ -1,10 +1,10 @@ require 'mediawiki-vagrant/environment' module MediaWikiVagrant - module PluginEnvironment - def initialize(*args) - super - @mwv = Environment.new(@env.root_path || @env.cwd) - end + module PluginEnvironment + def initialize(*args) + super + @mwv = Environment.new(@env.root_path || @env.cwd) end + end end diff --git a/lib/mediawiki-vagrant/reload.rb b/lib/mediawiki-vagrant/reload.rb index c632c88..a7719ec 100644 --- a/lib/mediawiki-vagrant/reload.rb +++ b/lib/mediawiki-vagrant/reload.rb @@ -1,18 +1,18 @@ module MediaWikiVagrant - class Reload < Vagrant.plugin('2', :provisioner) - def provision - vagrant_home = File.expand_path @machine.env.root_path - settings_dir = File.join(vagrant_home, 'vagrant.d') - reload_trigger = File.join(settings_dir, 'RELOAD') - if File.exists?(reload_trigger) - @machine.ui.warn 'Reloading vagrant...' - File.delete(reload_trigger) - @machine.action(:reload, {}) - until @machine.communicate.ready? do - sleep 0.5 - end - @machine.ui.success 'Vagrant reloaded.' - end + class Reload < Vagrant.plugin('2', :provisioner) + def provision + vagrant_home = File.expand_path @machine.env.root_path + settings_dir = File.join(vagrant_home, 'vagrant.d') + reload_trigger = File.join(settings_dir, 'RELOAD') + if File.exists?(reload_trigger) + @machine.ui.warn 'Reloading vagrant...' + File.delete(reload_trigger) + @machine.action(:reload, {}) + until @machine.communicate.ready? do + sleep 0.5 end + @machine.ui.success 'Vagrant reloaded.' + end end + end end diff --git a/lib/mediawiki-vagrant/run-tests.rb b/lib/mediawiki-vagrant/run-tests.rb index 4e50245..1e6bcee 100644 --- a/lib/mediawiki-vagrant/run-tests.rb +++ b/lib/mediawiki-vagrant/run-tests.rb @@ -1,16 +1,16 @@ class RunTests < Vagrant.plugin(2, :command) - def self.synopsis - "runs MediaWiki's test suite" - end + def self.synopsis + "runs MediaWiki's test suite" + end - def execute - if ['-h', '--help'].include? @argv.first - @env.ui.info "Usage: vagrant run-tests [tests] [-h]" - return 0 - end - opts = { extra_args: @argv.unshift('run-mediawiki-tests') } - with_target_vms(nil, :single_target => true) do |vm| - vm.action :ssh, ssh_opts: opts - end + def execute + if ['-h', '--help'].include? @argv.first + @env.ui.info "Usage: vagrant run-tests [tests] [-h]" + return 0 end + opts = { extra_args: @argv.unshift('run-mediawiki-tests') } + with_target_vms(nil, :single_target => true) do |vm| + vm.action :ssh, ssh_opts: opts + end + end end diff --git a/lib/mediawiki-vagrant/setting.rb b/lib/mediawiki-vagrant/setting.rb index 60e1c5c..ee21afc 100644 --- a/lib/mediawiki-vagrant/setting.rb +++ b/lib/mediawiki-vagrant/setting.rb @@ -1,52 +1,52 @@ module MediaWikiVagrant - # A MediaWiki-Vagrant setting. - # - # @attr_reader name [Symbol] Name of the setting. - # - # @attr description [String] Brief description of the setting - # @attr help [String] Additional help text - # @attr default [Object] Default value - # @attr coercion [Proc] Used to process a given setting value - # @attr internal [true, false] Whether the setting is only used internally - # @attr allows_empty [true, false] Whether to allow empty string values - # @attr value [Object] Current value - # - # @see Settings - # - class Setting - attr_reader :name - attr_accessor :description, :help, :default, :coercion, :internal, :allows_empty + # A MediaWiki-Vagrant setting. + # + # @attr_reader name [Symbol] Name of the setting. + # + # @attr description [String] Brief description of the setting + # @attr help [String] Additional help text + # @attr default [Object] Default value + # @attr coercion [Proc] Used to process a given setting value + # @attr internal [true, false] Whether the setting is only used internally + # @attr allows_empty [true, false] Whether to allow empty string values + # @attr value [Object] Current value + # + # @see Settings + # + class Setting + attr_reader :name + attr_accessor :description, :help, :default, :coercion, :internal, :allows_empty - def initialize(name, value = nil) - @name = name - @value = value - @coercion = ->(_, new) { new } - @internal = false - @allows_empty = false - end - - alias allows_empty? allows_empty - - alias internal? internal - - def default? - [email protected]? - end - - def set? - [email protected]? - end - - def unset! - @value = nil - end - - def value - @value.nil? ? default : @value - end - - def value=(other) - @value = @coercion.call(self, other) - end + def initialize(name, value = nil) + @name = name + @value = value + @coercion = ->(_, new) { new } + @internal = false + @allows_empty = false end + + alias allows_empty? allows_empty + + alias internal? internal + + def default? + [email protected]? + end + + def set? + [email protected]? + end + + def unset! + @value = nil + end + + def value + @value.nil? ? default : @value + end + + def value=(other) + @value = @coercion.call(self, other) + end + end end diff --git a/lib/mediawiki-vagrant/settings.rb b/lib/mediawiki-vagrant/settings.rb index 6662a19..73cafdb 100644 --- a/lib/mediawiki-vagrant/settings.rb +++ b/lib/mediawiki-vagrant/settings.rb @@ -4,182 +4,182 @@ require 'mediawiki-vagrant/settings_definer' module MediaWikiVagrant - # A collection of MediaWiki-Vagrant settings that can be loaded from and - # written to a YAML-serialized file. + # A collection of MediaWiki-Vagrant settings that can be loaded from and + # written to a YAML-serialized file. + # + # Predefined settings can be declared using {.define} and given additional + # options such as default values, descriptions to be used by interactive + # prompts, and value coercion to enforce minimums, maximums, etc. + # + # @example Define settings + # Settings.define do + # setting :vagrant_ram, + # description: "Amount (in MB) of memory allocated to the VM", + # help: "Specify more memory for hungry tasks like browser tests", + # default: 1024, + # coercion: ->(setting, value) { [setting.default, value].max } + # + # @example Load settings from a file + # settings = Settings.new + # settings.load("file/path.yaml") + # + # @example Load settings from all .yaml files in a directory + # settings = Settings.new + # settings.load("settings.d") + # + # @example Change a setting and save to a file + # settings = Settings.new + # settings[:vagrant_ram] = 2048 + # settings.save("file/path.yaml") + # + # @see Setting + # @see SettingsDefiner + # @see {file:settings/definitions.rb} + # + class Settings + include Enumerable + include SettingsDefiner + + # Safely configure the settings stored in the given file using the + # provided block. The file is locked for exclusive write access during + # evaluation. # - # Predefined settings can be declared using {.define} and given additional - # options such as default values, descriptions to be used by interactive - # prompts, and value coercion to enforce minimums, maximums, etc. + # @param path [String] Path to settings file. # - # @example Define settings - # Settings.define do - # setting :vagrant_ram, - # description: "Amount (in MB) of memory allocated to the VM", - # help: "Specify more memory for hungry tasks like browser tests", - # default: 1024, - # coercion: ->(setting, value) { [setting.default, value].max } - # - # @example Load settings from a file - # settings = Settings.new - # settings.load("file/path.yaml") - # - # @example Load settings from all .yaml files in a directory - # settings = Settings.new - # settings.load("settings.d") - # - # @example Change a setting and save to a file - # settings = Settings.new - # settings[:vagrant_ram] = 2048 - # settings.save("file/path.yaml") - # - # @see Setting - # @see SettingsDefiner - # @see {file:settings/definitions.rb} - # - class Settings - include Enumerable - include SettingsDefiner + def self.configure(path) + settings = Settings.new - # Safely configure the settings stored in the given file using the - # provided block. The file is locked for exclusive write access during - # evaluation. - # - # @param path [String] Path to settings file. - # - def self.configure(path) - settings = Settings.new + File.open(path, File::RDWR | File::CREAT) do |file| + file.flock(File::LOCK_EX) - File.open(path, File::RDWR | File::CREAT) do |file| - file.flock(File::LOCK_EX) + begin + settings.load(file) + file.rewind - begin - settings.load(file) - file.rewind + yield settings - yield settings - - settings.save(file) - file.flush - file.truncate(file.pos) - ensure - file.flock(File::LOCK_UN) - end - end + settings.save(file) + file.flush + file.truncate(file.pos) + ensure + file.flock(File::LOCK_UN) end - - def initialize - @settings = self.class.definitions.clone - end - - # The given setting's current value. - # - def [](key) - key = normalize_key(key) - - @settings[key] && @settings[key].value - end - - # Changes the given setting's value. - # - def []=(key, value) - key = normalize_key(key) - - if @settings.include?(key) - @settings[key].value = value - else - @settings[key] = Setting.new(key, value) - end - end - - # Iterate over each setting. - # - # @yield [name, setting] - # - def each(&blk) - @settings.each(&blk) - end - - # Load YAML-serialized settings from the given path. If a directory is - # given, all files matching *.yaml are loaded. - # - # @param path_or_io [String, IO] Path to file, open IO, or directory - # - def load(path_or_io) - case path_or_io - when IO - update(YAML.load(path_or_io)) - else - if File.directory?(path_or_io) - Dir.glob("#{path_or_io}/*.yaml").each { |f| load(f) } - else - load(File.new(path_or_io)) - end - end - end - - # Returns only those of the current settings that are required (have - # no default value). - # - # @return [Hash] - # - def required - select { |name, setting| setting.default.nil? } - end - - # Serializes and saves the current settings to the given file path. - # - # @param path_or_io [String, #write] File path or open IO object. - # - # @return [Integer] Number of bytes written. - # - def save(path_or_io) - yaml = YAML.dump(to_yaml_hash) - - case path_or_io - when IO - path_or_io.write(yaml) - else - File.open(path_or_io, 'w') { |f| f.write(yaml) } - end - end - - # Returns the setting with the given name. - # - # @param name [String, Symbol] Setting name - # - # @return [Setting] - # - def setting(name) - @settings[normalize_key(name)] - end - - # Updates settings from the given `{ name: value }` hash. - # - # @param other [Hash] - # - def update(other) - other.each { |key, value| self[key] = value } if other.is_a?(Hash) - self - end - - # Unset the given setting. - # - # @param name [String] Setting name. - # - def unset!(name) - (s = setting(name)) && s.unset! - end - - private - - def normalize_key(key) - key.to_s.downcase.to_sym - end - - def to_yaml_hash(options = {}) - @settings.each.with_object({}) do |(key, setting), hash| - hash[key.to_s] = setting.value if setting.value != setting.default - end - end + end end + + def initialize + @settings = self.class.definitions.clone + end + + # The given setting's current value. + # + def [](key) + key = normalize_key(key) + + @settings[key] && @settings[key].value + end + + # Changes the given setting's value. + # + def []=(key, value) + key = normalize_key(key) + + if @settings.include?(key) + @settings[key].value = value + else + @settings[key] = Setting.new(key, value) + end + end + + # Iterate over each setting. + # + # @yield [name, setting] + # + def each(&blk) + @settings.each(&blk) + end + + # Load YAML-serialized settings from the given path. If a directory is + # given, all files matching *.yaml are loaded. + # + # @param path_or_io [String, IO] Path to file, open IO, or directory + # + def load(path_or_io) + case path_or_io + when IO + update(YAML.load(path_or_io)) + else + if File.directory?(path_or_io) + Dir.glob("#{path_or_io}/*.yaml").each { |f| load(f) } + else + load(File.new(path_or_io)) + end + end + end + + # Returns only those of the current settings that are required (have + # no default value). + # + # @return [Hash] + # + def required + select { |name, setting| setting.default.nil? } + end + + # Serializes and saves the current settings to the given file path. + # + # @param path_or_io [String, #write] File path or open IO object. + # + # @return [Integer] Number of bytes written. + # + def save(path_or_io) + yaml = YAML.dump(to_yaml_hash) + + case path_or_io + when IO + path_or_io.write(yaml) + else + File.open(path_or_io, 'w') { |f| f.write(yaml) } + end + end + + # Returns the setting with the given name. + # + # @param name [String, Symbol] Setting name + # + # @return [Setting] + # + def setting(name) + @settings[normalize_key(name)] + end + + # Updates settings from the given `{ name: value }` hash. + # + # @param other [Hash] + # + def update(other) + other.each { |key, value| self[key] = value } if other.is_a?(Hash) + self + end + + # Unset the given setting. + # + # @param name [String] Setting name. + # + def unset!(name) + (s = setting(name)) && s.unset! + end + + private + + def normalize_key(key) + key.to_s.downcase.to_sym + end + + def to_yaml_hash(options = {}) + @settings.each.with_object({}) do |(key, setting), hash| + hash[key.to_s] = setting.value if setting.value != setting.default + end + end + end end diff --git a/lib/mediawiki-vagrant/settings/definitions.rb b/lib/mediawiki-vagrant/settings/definitions.rb index b2d08fe..e8fac67 100644 --- a/lib/mediawiki-vagrant/settings/definitions.rb +++ b/lib/mediawiki-vagrant/settings/definitions.rb @@ -1,46 +1,46 @@ require 'mediawiki-vagrant/settings' MediaWikiVagrant::Settings.define do - setting :git_user, - description: "Your git/Gerrit username", - help: "Enter 'anonymous' for anonymous access, leave blank to manage it yourself", - allows_empty: true + setting :git_user, + description: "Your git/Gerrit username", + help: "Enter 'anonymous' for anonymous access, leave blank to manage it yourself", + allows_empty: true - setting :vagrant_ram, - description: "Amount of RAM (in MB) allocated to the guest VM", - help: "Tasks such as browser tests may require more memory (minimum of 1024)", - default: 1024, - coercion: ->(setting, new) { [setting.value, new.to_i].max } + setting :vagrant_ram, + description: "Amount of RAM (in MB) allocated to the guest VM", + help: "Tasks such as browser tests may require more memory (minimum of 1024)", + default: 1024, + coercion: ->(setting, new) { [setting.value, new.to_i].max } - setting :vagrant_cores, - description: "CPU cores allocated to the guest VM", - help: "If you're on a single-core system, be sure to enter '1'", - default: 2, - coercion: ->(setting, new) { new && new.to_i } + setting :vagrant_cores, + description: "CPU cores allocated to the guest VM", + help: "If you're on a single-core system, be sure to enter '1'", + default: 2, + coercion: ->(setting, new) { new && new.to_i } - setting :static_ip, - description: "IP address assigned to the guest VM", - default: "10.11.12.13" + setting :static_ip, + description: "IP address assigned to the guest VM", + default: "10.11.12.13" - setting :http_port, - description: "Host port forwarded to the guest VM's HTTP server (port 80)", - default: 8080, - coercion: ->(setting, new) { new && new.to_i } + setting :http_port, + description: "Host port forwarded to the guest VM's HTTP server (port 80)", + default: 8080, + coercion: ->(setting, new) { new && new.to_i } - setting :nfs_shares, - description: "Use synced folders backed by NFS", - help: "Enter 'yes' or 'no'. NFS is faster, but unsupported on Windows and with some encrypted filesystems on Linux", - default: !Vagrant::Util::Platform.windows?, - coercion: ->(setting, new) { !!(new.to_s =~ /^(true|t|yes|y|1)$/i) } + setting :nfs_shares, + description: "Use synced folders backed by NFS", + help: "Enter 'yes' or 'no'. NFS is faster, but unsupported on Windows and with some encrypted filesystems on Linux", + default: !Vagrant::Util::Platform.windows?, + coercion: ->(setting, new) { !!(new.to_s =~ /^(true|t|yes|y|1)$/i) } - setting :forward_agent, - description: "Enable agent forwarding over SSH connections by default", - help: "Enter 'yes' or 'no'. Agent forwarding requires an SSH agent running on the host computer.", - default: false, - coercion: ->(setting, new) { !!(new.to_s =~ /^(true|t|yes|y|1)$/i) } + setting :forward_agent, + description: "Enable agent forwarding over SSH connections by default", + help: "Enter 'yes' or 'no'. Agent forwarding requires an SSH agent running on the host computer.", + default: false, + coercion: ->(setting, new) { !!(new.to_s =~ /^(true|t|yes|y|1)$/i) } - setting :forward_ports, - internal: true, - default: {}, - coercion: ->(setting, new) { setting.value.merge(Hash[new.map { |kv| kv.map(&:to_i) }]) } + setting :forward_ports, + internal: true, + default: {}, + coercion: ->(setting, new) { setting.value.merge(Hash[new.map { |kv| kv.map(&:to_i) }]) } end diff --git a/lib/mediawiki-vagrant/settings_definer.rb b/lib/mediawiki-vagrant/settings_definer.rb index f71a81f..5191c3d 100644 --- a/lib/mediawiki-vagrant/settings_definer.rb +++ b/lib/mediawiki-vagrant/settings_definer.rb @@ -1,28 +1,28 @@ module MediaWikiVagrant - module SettingsDefiner - def self.included(other) - super + module SettingsDefiner + def self.included(other) + super - class << other - attr_accessor :definitions - end + class << other + attr_accessor :definitions + end - other.extend(Macros) - other.definitions ||= {} - end - - private - - module Macros - def define(&blk) - class_exec(&blk) - end - - def setting(name, params = {}) - self.definitions[name] = Setting.new(name).tap do |setting| - params.each { |name, value| setting.send("#{name}=", value) } - end - end - end + other.extend(Macros) + other.definitions ||= {} end + + private + + module Macros + def define(&blk) + class_exec(&blk) + end + + def setting(name, params = {}) + self.definitions[name] = Setting.new(name).tap do |setting| + params.each { |name, value| setting.send("#{name}=", value) } + end + end + end + end end diff --git a/lib/mediawiki-vagrant/settings_plugin.rb b/lib/mediawiki-vagrant/settings_plugin.rb index 25a7a4f..c28ceea 100644 --- a/lib/mediawiki-vagrant/settings_plugin.rb +++ b/lib/mediawiki-vagrant/settings_plugin.rb @@ -2,30 +2,30 @@ require "yaml" module MediaWikiVagrant - # Provides helpers for plugins that access .settings.yaml. + # Provides helpers for plugins that access .settings.yaml. + # + module SettingsPlugin + protected + + # Configures .settings.yaml with the given block. # - module SettingsPlugin - protected - - # Configures .settings.yaml with the given block. - # - def configure(&blk) - Settings.configure(@mwv.path(".settings.yaml"), &blk) - end - - # Parses user input and returns a Ruby object. User input is expected - # to be valid YAML. - # - def parse_setting(setting, input) - YAML.parse(input).to_ruby - rescue Psych::SyntaxError - nil - end - - # The given setting value, suitable for display during configuration. - # - def setting_display_value(value) - value.to_yaml.lines.first.match(/^--- (.+)$/) { |m| m[1] } || "" - end + def configure(&blk) + Settings.configure(@mwv.path(".settings.yaml"), &blk) end + + # Parses user input and returns a Ruby object. User input is expected + # to be valid YAML. + # + def parse_setting(setting, input) + YAML.parse(input).to_ruby + rescue Psych::SyntaxError + nil + end + + # The given setting value, suitable for display during configuration. + # + def setting_display_value(value) + value.to_yaml.lines.first.match(/^--- (.+)$/) { |m| m[1] } || "" + end + end end diff --git a/lib/mediawiki-vagrant/setup.rb b/lib/mediawiki-vagrant/setup.rb index 65dbb06..070d297 100644 --- a/lib/mediawiki-vagrant/setup.rb +++ b/lib/mediawiki-vagrant/setup.rb @@ -2,169 +2,169 @@ require "rubygems" module MediaWikiVagrant - # Assists with the setup of MediaWiki-Vagrant. - # - # Provides an interactive set of prompts for configuration of required - # settings, installs plugin dependencies, and builds and installs the - # mediawiki-vagrant plugin. - # - class Setup - PLUGINS = ["vagrant-vbguest"] + # Assists with the setup of MediaWiki-Vagrant. + # + # Provides an interactive set of prompts for configuration of required + # settings, installs plugin dependencies, and builds and installs the + # mediawiki-vagrant plugin. + # + class Setup + PLUGINS = ["vagrant-vbguest"] - class ExecutionError < RuntimeError - attr_reader :command, :status + class ExecutionError < RuntimeError + attr_reader :command, :status - def initialize(command, status) - @command = command - @status = status - end + def initialize(command, status) + @command = command + @status = status + end - def to_s - "Failed to execute command `#{command}` (#{status})" - end - end - - attr_reader :directory, :options - - # Creates a new setup runner from the given command-line invocation. - # - def initialize(invocation) - @silent = false - @directory = File.expand_path("..", invocation) - - @options = OptionParser.new do |parser| - parser.banner = "Usage: #{invocation}" - - parser.on("-s", "--silent", "Run silently with no prompts or output") do - @silent = true - end - - parser.on_tail("-h", "--help", "Show this help message.") do - puts parser - exit - end - end - end - - # Executes the setup runner. Installs plugin dependencies, builds and - # installs the mediawiki-vagrant plugin, and prompts the user to - # configure any required settings. - # - def run - @options.parse! - - # Install/update plugins - (PLUGINS & installed_plugins).each { |plugin| update_plugin(plugin) } - (PLUGINS - installed_plugins).each { |plugin| install_plugin(plugin) } - - # Install/update mediawiki-vagrant plugin - gem_path = build_gem - - begin - install_plugin(gem_path) - ensure - Dir["mediawiki-vagrant-*.gem"].each { |gem| File.unlink(gem) } - end - - # Configure required settings - configure_settings unless @silent - - notify "\nYou're all set! Simply run `vagrant up` to boot your new environment." - end - - private - - # Builds mediawiki-vagrant from the bundled gemspec. - # - def build_gem - spec = Gem::Specification.load(File.join(@directory, "mediawiki-vagrant.gemspec")) - - # Support older versions of RubyGems as best we can - if defined?(Gem::Builder) - build_gem_using_builder(spec) - else - build_gem_using_package(spec) - end - end - - # Builds mediawiki-vagrant on systems with an older version of - # RubyGems (< 2.0). - # - def build_gem_using_builder(spec) - pwd = Dir.pwd - verbose = Gem.configuration.verbose - - Dir.chdir(File.expand_path("..", spec.loaded_from)) - Gem.configuration.verbose = false - - Gem::Builder.new(spec).build - ensure - Dir.chdir(pwd) - Gem.configuration.verbose = verbose - end - - # Builds mediawiki-vagrant on systems with a newer version of RubyGems - # (>= 2.0). - # - def build_gem_using_package(spec) - require "rubygems/package" - - package = Gem::Package.new(spec.file_name) - package.spec = spec - package.use_ui(Gem::SilentUI.new) { package.build } - - spec.file_name - end - - # Prompts the user to configure required settings. - # - def configure_settings - vagrant("config", "--required") { |pipe| pipe.each_char { |c| print c } } - end - - # Installs the given Vagrant plugin. - # - def install_plugin(name) - notify "Installing plugin #{name}" - vagrant("plugin", "install", name) - end - - # Currently installed Vagrant plugins. - # - def installed_plugins - @installed_plugins ||= vagrant("plugin", "list") do |pipe| - pipe.each_line.with_object([]) do |line, plugins| - line.match(/^([\w\-]+) \([\w\.]+\)/) { |m| plugins << m[1] } - end - end - end - - # Outputs the given message at the given indentation level unless we're - # operating in silent mode. - # - def notify(message_or_io, level = 0) - unless @silent - prefix = ("-" * level) + (level > 0 ? " " : "") - message_or_io.each_line { |line| puts "#{prefix}#{line}" } - end - end - - # Skips updates for already installed plugins. - # - def update_plugin(name) - notify "Plugin #{name} is already installed" - end - - # Executes the vagrant commands with the given arguments. - # - def vagrant(*args, &blk) - command = ["vagrant"] + args - blk ||= proc { |pipe| notify pipe, 1 } - - result = IO.popen(command, err: [:child, :out], &blk) - raise ExecutionError.new(command.join(" "), $?) unless $?.success? - - result - end + def to_s + "Failed to execute command `#{command}` (#{status})" + end end + + attr_reader :directory, :options + + # Creates a new setup runner from the given command-line invocation. + # + def initialize(invocation) + @silent = false + @directory = File.expand_path("..", invocation) + + @options = OptionParser.new do |parser| + parser.banner = "Usage: #{invocation}" + + parser.on("-s", "--silent", "Run silently with no prompts or output") do + @silent = true + end + + parser.on_tail("-h", "--help", "Show this help message.") do + puts parser + exit + end + end + end + + # Executes the setup runner. Installs plugin dependencies, builds and + # installs the mediawiki-vagrant plugin, and prompts the user to + # configure any required settings. + # + def run + @options.parse! + + # Install/update plugins + (PLUGINS & installed_plugins).each { |plugin| update_plugin(plugin) } + (PLUGINS - installed_plugins).each { |plugin| install_plugin(plugin) } + + # Install/update mediawiki-vagrant plugin + gem_path = build_gem + + begin + install_plugin(gem_path) + ensure + Dir["mediawiki-vagrant-*.gem"].each { |gem| File.unlink(gem) } + end + + # Configure required settings + configure_settings unless @silent + + notify "\nYou're all set! Simply run `vagrant up` to boot your new environment." + end + + private + + # Builds mediawiki-vagrant from the bundled gemspec. + # + def build_gem + spec = Gem::Specification.load(File.join(@directory, "mediawiki-vagrant.gemspec")) + + # Support older versions of RubyGems as best we can + if defined?(Gem::Builder) + build_gem_using_builder(spec) + else + build_gem_using_package(spec) + end + end + + # Builds mediawiki-vagrant on systems with an older version of + # RubyGems (< 2.0). + # + def build_gem_using_builder(spec) + pwd = Dir.pwd + verbose = Gem.configuration.verbose + + Dir.chdir(File.expand_path("..", spec.loaded_from)) + Gem.configuration.verbose = false + + Gem::Builder.new(spec).build + ensure + Dir.chdir(pwd) + Gem.configuration.verbose = verbose + end + + # Builds mediawiki-vagrant on systems with a newer version of RubyGems + # (>= 2.0). + # + def build_gem_using_package(spec) + require "rubygems/package" + + package = Gem::Package.new(spec.file_name) + package.spec = spec + package.use_ui(Gem::SilentUI.new) { package.build } + + spec.file_name + end + + # Prompts the user to configure required settings. + # + def configure_settings + vagrant("config", "--required") { |pipe| pipe.each_char { |c| print c } } + end + + # Installs the given Vagrant plugin. + # + def install_plugin(name) + notify "Installing plugin #{name}" + vagrant("plugin", "install", name) + end + + # Currently installed Vagrant plugins. + # + def installed_plugins + @installed_plugins ||= vagrant("plugin", "list") do |pipe| + pipe.each_line.with_object([]) do |line, plugins| + line.match(/^([\w\-]+) \([\w\.]+\)/) { |m| plugins << m[1] } + end + end + end + + # Outputs the given message at the given indentation level unless we're + # operating in silent mode. + # + def notify(message_or_io, level = 0) + unless @silent + prefix = ("-" * level) + (level > 0 ? " " : "") + message_or_io.each_line { |line| puts "#{prefix}#{line}" } + end + end + + # Skips updates for already installed plugins. + # + def update_plugin(name) + notify "Plugin #{name} is already installed" + end + + # Executes the vagrant commands with the given arguments. + # + def vagrant(*args, &blk) + command = ["vagrant"] + args + blk ||= proc { |pipe| notify pipe, 1 } + + result = IO.popen(command, err: [:child, :out], &blk) + raise ExecutionError.new(command.join(" "), $?) unless $?.success? + + result + end + end end diff --git a/lib/mediawiki-vagrant/version.rb b/lib/mediawiki-vagrant/version.rb index 05194b9..4f70654 100644 --- a/lib/mediawiki-vagrant/version.rb +++ b/lib/mediawiki-vagrant/version.rb @@ -1,3 +1,3 @@ module MediaWikiVagrant - VERSION = '0.2.0' + VERSION = '0.2.0' end -- To view, visit https://gerrit.wikimedia.org/r/165589 To unsubscribe, visit https://gerrit.wikimedia.org/r/settings Gerrit-MessageType: newchange Gerrit-Change-Id: I7d57f3a66e7c9b138a27a9615fd2a89732c65e2a Gerrit-PatchSet: 1 Gerrit-Project: mediawiki/vagrant Gerrit-Branch: master Gerrit-Owner: Dduvall <[email protected]> _______________________________________________ MediaWiki-commits mailing list [email protected] https://lists.wikimedia.org/mailman/listinfo/mediawiki-commits
