RFC: Replacing blacklist with blocklist in our templates


I was taught in schools and books about whitelist and blacklist technical terms. It felt natural and normal to me, until last couple of days. Latest developments from US and all over the world made me to realize how awful these words are. While these words might not associate anything to some of us, there are many out there who might not feel the same. Getting rid of these may be just a small gesture, but I don’t want to sit doing nothing.

The patch I propose removes “blacklist” and “blacklist_kernel_modules” host parameters and replaces both with one called “blocklist_kernel_parameter”. They both served the same purpose - to pass either kernel command line option blacklist and/or create entry in /etc/modprobe.d/blacklist.conf. Insted of two host params we now have a single one. On top of that, the syntax is now common, kernel modules can be separated with a comma or a whitespace, previously it was different for both parameters.

While we cannot get rid of the blacklist keyword in the rendered output because Linux expect these keywords as of today (summer 2020), we can trim down the exposure at least for Foreman users. That’s something. In the initial proposal, using any of the previous host parameters will cause an exception asking the user to change their templates. We can talk about that, we don’t have any deprecation mechanisms for templates (yet), I can create a macro called deprecated which drops a warning message in logs although I have doubts users would catch that until we finally drop it.

We have a huge codebase and lots of plugins, I encourage all of us to take a moment and review other parts of our project. Thanks!


Hi @lzap

Thanks for raising this as an issue. Much like you, I had not stopped to think about the binary of these terms. I have been looking online and see that Google and the Android team, at least, are also looking to move away from these terms:

+1 from me, for what it is worth.

My 2 cents worth: To me, “kernel_parameter_block_list” states the invention / meaning more clearly, but that may be just me. :wink:


Yeah, on the other hand the patch unified both kernel parameter and kernel module configuration file which sits in the modprobe drop directory. Also my thinking is that “blacklist_kernel_modules” is literally the same word with just one letter difference as “blocklist_kernel_modules” therefore the template snippets will be listed near to each other so users can easily spot them. This could make the migration easier.

Regardless of black-/blocklist, I like kernel_parameter_X. If we have more kernel parameters, they are listed together.

For the record, the kernel team does not appear to be changing the term and we agreed in the PR that it is too confusing to perform such change if kernel stays with the old term. Let’s wait and see.

In the meantime, I did a small research across our codebase. Aside of the PXE templates (the PR) and few occurrences in some scripts which are not user-facing we have:


10:    def add_slave(identifier)
14:    def remove_slave(identifier)

556:      name_blacklist = interfaces.map { |i| i[:name]}.reject {|n| n.blank?}
557:      nic_name_num += 1 while name_blacklist.include?("nic#{nic_name_num}")

25:      defaults['ANSIBLE_CALLBACK_WHITELIST'] = '' if rex_command?

286:        steps_with_abort = scenario.steps_with_abort(:whitelisted => false)
295:        steps_with_error = scenario.steps_with_error(:whitelisted => false)
302:          whitelist_labels = steps_with_error.map(&:label_dashed).join(',')
303:          recommend << format(<<-MESSAGE.strip_heredoc, whitelist_labels)
306:          use --whitelist="%s"
310:        steps_with_warning = scenario.steps_with_warning(:whitelisted => false)

4:    PROTECTOR_WHITELIST_FILE = '/etc/yum/pluginconf.d/foreman-protector.whitelist'.freeze
27:        File.exist?(PROTECTOR_WHITELIST_FILE)
33:      install_extras('foreman_protector/foreman-protector.whitelist', PROTECTOR_WHITELIST_FILE)

61:                                      :whitelist => option_wrapper('whitelist') || [],
163:        option(['-w', '--whitelist'], 'whitelist',
164:               'Comma-separated list of labels of steps to be skipped') do |whitelist|
165:          raise ArgumentError, 'value not specified' if whitelist.nil? || whitelist.empty?
166:          whitelist.split(',').map(&:strip)

8:                   :assumeyes?, :whitelisted?, :ask_decision,

10:      options.validate_options!(:assumeyes, :whitelist, :force, :rescue_scenario)
12:      @whitelist = options.fetch(:whitelist, [])
60:    def whitelisted_step?(step)
61:      @whitelist.include?(step.label_dashed.to_s)
67:      decision = if @last_scenario.steps_with_error(:whitelisted => false).any? ||
68:                    @last_scenario.steps_with_abort(:whitelisted => false).any?
70:                 elsif @last_scenario.steps_with_warning(:whitelisted => false).any?
119:                                :whitelisted => whitelisted_step?(step),
135:           execution.fail? && !execution.whitelisted? &&

42:                                                             :whitelist => whitelist || [],

24:        options.validate_options!(:whitelisted, :storage, :force)
29:        @whitelisted = options[:whitelisted]
38:      def whitelisted?
39:        @whitelisted
79:        @status = whitelisted? ? :skipped : :running

108:      filter_whitelisted(executed_steps.find_all(&:fail?), options)
112:      filter_whitelisted(executed_steps.find_all(&:aborted?), options)
116:      filter_whitelisted(executed_steps.find_all(&:warning?), options)
119:    def filter_whitelisted(steps, options)
120:      options.validate_options!(:whitelisted)
121:      if options.key?(:whitelisted)
123:          options[:whitelisted] ? step.whitelisted? : !step.whitelisted?
131:      (steps_with_abort(:whitelisted => false) +
132:        steps_with_error(:whitelisted => false) +
133:        steps_with_warning(:whitelisted => false)).empty?

3:whitelist = /etc/yum/pluginconf.d/foreman-protector.whitelist

17:_package_whitelist = set()
20:def _load_whitelist():
27:            _package_whitelist.add(line.rstrip().lower())
33:    if _package_whitelist:
34:        #  If anything obsoletes something that we have whitelisted ... then
35:        # whitelist that too.
37:            if instTup[0] not in _package_whitelist:
39:            _package_whitelist.add(pkgtup[0].lower())
45:        if p.name in _package_whitelist:
46:            # This one is whitelisted, skip
55:    fileurl = conduit.confString('main', 'whitelist')
57:def _add_package_whitelist_excluders(conduit):
63:    ape(None, exid + str(2), 'wash.name.in', _package_whitelist)
69:    _load_whitelist()
86:    _add_package_whitelist_excluders(conduit)

3:whitelist = /tmp/protector.whitelist

45:  validate :provider_type_whitelist
203:  def provider_type_whitelist

I think the slave for bond NIC is similar case as blacklist - this is a term used in Linux kernel and we need to at least render it, preferably not to confuse users. Blacklist and whitelist can be found at few rather minor places in core, maintain and remote execution.


Thanks @lzap for bringing this up. Totally agree and also want to highlight this blog post by Chris Wright. These terms will change eventually, even though it will take some time due to technical reasons. So it’s a good idea to plan for it.

1 Like

or allow and deny, like in hosts.allow and hosts.deny as that is pretty neutral and describes what is happening.

1 Like