Hello community,

here is the log from the commit of package yast2-pam for openSUSE:Factory 
checked in at 2020-07-30 09:59:46
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Comparing /work/SRC/openSUSE:Factory/yast2-pam (Old)
 and      /work/SRC/openSUSE:Factory/.yast2-pam.new.3592 (New)
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

Package is "yast2-pam"

Thu Jul 30 09:59:46 2020 rev:41 rq:823151 version:4.3.2

Changes:
--------
--- /work/SRC/openSUSE:Factory/yast2-pam/yast2-pam.changes      2019-08-27 
10:14:22.307967598 +0200
+++ /work/SRC/openSUSE:Factory/.yast2-pam.new.3592/yast2-pam.changes    
2020-07-30 10:00:11.131224262 +0200
@@ -1,0 +2,19 @@
+Tue Jul 28 11:35:47 UTC 2020 - Ancor Gonzalez Sosa <[email protected]>
+
+- Fixed a bug, introduced in the latest version, related to
+  deletion of nsswitch entries (related to bsc#1173119).
+- 4.3.2
+
+-------------------------------------------------------------------
+Tue Jul 28 11:03:14 CEST 2020 - [email protected]
+
+- Added function to query PAM modules (bsc#1171318).
+- 4.3.1
+
+-------------------------------------------------------------------
+Fri Jul 24 11:01:03 UTC 2020 - David Diaz <[email protected]>
+
+- Support reading nsswitch.conf from /usr/etc  (bsc#1173119).
+- 4.3.0
+
+-------------------------------------------------------------------

Old:
----
  yast2-pam-4.2.4.tar.bz2

New:
----
  yast2-pam-4.3.2.tar.bz2

++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

Other differences:
------------------
++++++ yast2-pam.spec ++++++
--- /var/tmp/diff_new_pack.eFgbS5/_old  2020-07-30 10:00:12.035224802 +0200
+++ /var/tmp/diff_new_pack.eFgbS5/_new  2020-07-30 10:00:12.039224804 +0200
@@ -1,7 +1,7 @@
 #
 # spec file for package yast2-pam
 #
-# Copyright (c) 2019 SUSE LINUX GmbH, Nuernberg, Germany.
+# Copyright (c) 2020 SUSE LINUX GmbH, Nuernberg, Germany.
 #
 # All modifications and additions to the file contributed by third parties
 # remain the property of their copyright owners, unless otherwise agreed
@@ -17,27 +17,35 @@
 
 
 Name:           yast2-pam
-Version:        4.2.4
+Version:        4.3.2
 Release:        0
+Summary:        YaST2 - PAM Agent
+License:        GPL-2.0-only
+Group:          System/YaST
 
-BuildRoot:      %{_tmppath}/%{name}-%{version}-build
+URL:            http://github.com/yast/yast-pam
 Source0:        %{name}-%{version}.tar.bz2
+BuildRoot:      %{_tmppath}/%{name}-%{version}-build
 
-Url:            http://github.com/yast/yast-pam
+BuildRequires:  yast2
 BuildRequires:  yast2-devtools >= 3.1.10
 BuildRequires:  rubygem(%{rb_default_ruby_abi}:yast-rake)
+# cfa for parsing nsswitch
+BuildRequires:  rubygem(%rb_default_ruby_abi:cfa) >= 0.6.4
+# lenses are needed to use cfa
+BuildRequires:  augeas-lenses
+# testsuite
+BuildRequires:  rubygem(%rb_default_ruby_abi:rspec)
 
 Requires:       yast2
-
+# cfa for parsing nsswitch
+Requires:       rubygem(%rb_default_ruby_abi:cfa) >= 0.6.4
+# lenses are needed to use cfa
+Requires:       augeas-lenses
 Requires:       pam-config >= 0.8
-
-BuildArch:      noarch
-
 Requires:       yast2-ruby-bindings >= 1.0.0
 
-Summary:        YaST2 - PAM Agent
-License:        GPL-2.0-only
-Group:          System/YaST
+BuildArch:      noarch
 
 %description
 This agent is used by YaST2 to modify the PAM configuration files
@@ -59,6 +67,7 @@
 %{yast_moduledir}/*
 %dir %{yast_scrconfdir}
 %{yast_scrconfdir}/*.scr
+%{yast_libdir}
 %dir %{yast_agentdir}
 %{yast_agentdir}/ag_passwd
 %doc %{yast_docdir}

++++++ yast2-pam-4.2.4.tar.bz2 -> yast2-pam-4.3.2.tar.bz2 ++++++
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/yast2-pam-4.2.4/.rubocop.yml 
new/yast2-pam-4.3.2/.rubocop.yml
--- old/yast2-pam-4.2.4/.rubocop.yml    1970-01-01 01:00:00.000000000 +0100
+++ new/yast2-pam-4.3.2/.rubocop.yml    2020-07-28 14:27:50.000000000 +0200
@@ -0,0 +1,145 @@
+# use the shared YaST defaults
+inherit_from:
+  /usr/share/YaST2/data/devtools/data/rubocop-0.71.0_yast_style.yml
+
+# Offense count: 1
+# Cop supports --auto-correct.
+Layout/EmptyLineAfterGuardClause:
+  Exclude:
+    - 'src/modules/Pam.rb'
+
+# Offense count: 2
+# Cop supports --auto-correct.
+# Configuration parameters: AllowAdjacentOneLineDefs, NumberOfEmptyLines.
+Layout/EmptyLineBetweenDefs:
+  Exclude:
+    - 'src/modules/Autologin.rb'
+    - 'src/modules/Nsswitch.rb'
+
+# Offense count: 3
+# Cop supports --auto-correct.
+Layout/EmptyLines:
+  Exclude:
+    - 'src/modules/Autologin.rb'
+    - 'src/modules/Nsswitch.rb'
+
+# Offense count: 15
+# Cop supports --auto-correct.
+# Configuration parameters: IndentationWidth.
+Layout/Tab:
+  Exclude:
+    - 'src/modules/Autologin.rb'
+    - 'src/modules/Nsswitch.rb'
+    - 'src/modules/Pam.rb'
+
+# Offense count: 1
+Lint/ShadowingOuterLocalVariable:
+  Exclude:
+    - 'src/modules/Pam.rb'
+
+# Offense count: 1
+# Cop supports --auto-correct.
+# Configuration parameters: AllowUnusedKeywordArguments, IgnoreEmptyMethods.
+Lint/UnusedMethodArgument:
+  Exclude:
+    - 'src/modules/Autologin.rb'
+
+# Offense count: 5
+# Configuration parameters: CountComments, ExcludedMethods.
+# ExcludedMethods: refine
+Metrics/BlockLength:
+  Exclude:
+    - 'test/**/*'
+
+# Offense count: 3
+# Configuration parameters: ExpectMatchingDefinition, Regex, 
IgnoreExecutableScripts, AllowedAcronyms.
+# AllowedAcronyms: CLI, DSL, ACL, API, ASCII, CPU, CSS, DNS, EOF, GUID, HTML, 
HTTP, HTTPS, ID, IP, JSON, LHS, QPS, RAM, RHS, RPC, SLA, SMTP, SQL, SSH, TCP, 
TLS, TTL, UDP, UI, UID, UUID, URI, URL, UTF8, VM, XML, XMPP, XSRF, XSS
+Naming/FileName:
+  Exclude:
+    - 'src/modules/Autologin.rb'
+    - 'src/modules/Nsswitch.rb'
+    - 'src/modules/Pam.rb'
+
+# Offense count: 16
+# Configuration parameters: .
+# SupportedStyles: snake_case, camelCase
+Naming/MethodName:
+  Exclude:
+    - 'src/modules/Nsswitch.rb'
+    - 'src/modules/Autologin.rb'
+    - 'src/modules/Pam.rb'
+
+# Offense count: 6
+Style/Documentation:
+  Exclude:
+    - 'spec/**/*'
+    - 'test/**/*'
+    - 'src/modules/Autologin.rb'
+    - 'src/modules/Nsswitch.rb'
+    - 'src/modules/Pam.rb'
+
+# Cop supports --auto-correct.
+# Configuration parameters: EnforcedStyle.
+# SupportedStyles: compact, expanded
+Style/EmptyMethod:
+  Exclude:
+    - 'src/modules/Pam.rb'
+
+# Offense count: 3
+# Cop supports --auto-correct.
+Style/Encoding:
+  Exclude:
+    - 'src/modules/Autologin.rb'
+    - 'src/modules/Nsswitch.rb'
+    - 'src/modules/Pam.rb'
+
+# Offense count: 8
+# Cop supports --auto-correct.
+# Configuration parameters: EnforcedStyle.
+# SupportedStyles: always, never
+Style/FrozenStringLiteralComment:
+  Exclude:
+    - 'Rakefile'
+    - 'src/lib/cfa/nsswitch.rb'
+    - 'src/modules/Autologin.rb'
+    - 'src/modules/Nsswitch.rb'
+    - 'src/modules/Pam.rb'
+    - 'test/cfa/nsswitch_test.rb'
+    - 'test/nsswitch_test.rb'
+    - 'test/test_helper.rb'
+
+# Offense count: 1
+# Configuration parameters: MinBodyLength.
+Style/GuardClause:
+  Exclude:
+    - 'src/lib/cfa/nsswitch.rb'
+
+# Offense count: 43
+# Cop supports --auto-correct.
+# Configuration parameters: EnforcedStyle, UseHashRocketsWithSymbolValues, 
PreferHashRocketsForNonAlnumEndingSymbols.
+# SupportedStyles: ruby19, hash_rockets, no_mixed_keys, ruby19_no_mixed_keys
+Style/HashSyntax:
+  Exclude:
+    - 'src/modules/Autologin.rb'
+    - 'src/modules/Nsswitch.rb'
+    - 'src/modules/Pam.rb'
+
+# Offense count: 2
+# Cop supports --auto-correct.
+Style/LineEndConcatenation:
+  Exclude:
+    - 'src/modules/Autologin.rb'
+
+# Offense count: 1
+# Cop supports --auto-correct.
+# Configuration parameters: EnforcedStyle.
+# SupportedStyles: predicate, comparison
+Style/NilComparison:
+  Exclude:
+    - 'src/modules/Autologin.rb'
+
+# Offense count: 1
+# Cop supports --auto-correct.
+Style/RedundantBegin:
+  Exclude:
+    - 'test/nsswitch_test.rb'
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/yast2-pam-4.2.4/CONTRIBUTING.md 
new/yast2-pam-4.3.2/CONTRIBUTING.md
--- old/yast2-pam-4.2.4/CONTRIBUTING.md 2019-08-22 15:12:21.000000000 +0200
+++ new/yast2-pam-4.3.2/CONTRIBUTING.md 1970-01-01 01:00:00.000000000 +0100
@@ -1,89 +0,0 @@
-YaST Contribution Guidelines
-============================
-
-YaST is an open source project and as such it welcomes all kinds of
-contributions. If you decide to contribute, please follow these guidelines to
-ensure the process is effective and pleasant both for you and the YaST 
maintainers.
-
-There are two main forms of contribution: reporting bugs and performing code
-changes.
-
-Bug Reports
------------
-
-If you find a problem, please report it either using
-[Bugzilla](https://bugzilla.suse.com/enter_bug.cgi?format=guided&product=openSUSE+Factory&component=YaST2)
-or [GitHub issues](../../issues). (For Bugzilla, use the [simplified
-registration](https://secure-www.novell.com/selfreg/jsp/createSimpleAccount.jsp)
-if you don't have an account yet.)
-
-When creating a bug report, please follow our [bug reporting
-guidelines](http://en.opensuse.org/openSUSE:Report_a_YaST_bug).
-
-We can't guarantee that every bug will be fixed, but we'll try.
-
-Code Changes
-------------
-
-We welcome all kinds of code contributions, from simple bug fixes to 
significant
-refactorings and implementation of new features. However, before making any
-non-trivial contribution, get in touch with us first — this can prevent wasted
-effort on both sides. Also, have a look at our [development
-documentation](http://en.opensuse.org/openSUSE:YaST_development).
-
-To send us your code change, use GitHub pull requests. The workflow is as
-follows:
-
-  1. Fork the project.
-
-  2. Create a topic branch based on `master`.
-
-  3. Implement your change, including tests (if possible). Make sure you adhere
-     to the [Ruby style
-     guide](https://github.com/SUSE/style-guides/blob/master/Ruby.md).
-
-  4. Update the package version (in `packages/*.spec`, usually by
-     `rake version:bump`) and add a new entry to the `package/*.changes` file
-     (by `osc vc package`).  
-     For bigger changes or changes which need longer discussion it is advised 
to
-     add this as a separate last commit so it can be easily updated when 
another
-     change is merged in the meantime.
-
-  5. Make sure your change didn't break anything by building the RPM package
-     (`rake osc:build`). The build process includes running the full testsuite.
-
-  6. Publish the branch and create a pull request.
-
-  7. YaST developers will review your change and possibly point out issues.
-     Adapt the code under their guidance until they are all resolved.
-
-  8. Finally, the pull request will get merged or rejected.
-
-See also [GitHub's guide on
-contributing](https://help.github.com/articles/fork-a-repo).
-
-If you want to do multiple unrelated changes, use separate branches and pull
-requests.
-
-### Commits
-
-Each commit in the pull request should do only one thing, which is clearly
-described by its commit message. Especially avoid mixing formatting changes and
-functional changes into one commit. When writing commit messages, adhere to
-[widely used
-conventions](http://tbaggery.com/2008/04/19/a-note-about-git-commit-messages.html).
-
-If your commit is related to a bug in Bugzilla or an issue on GitHub, make sure
-you mention it in the commit message for cross-reference. Use format like
-bnc#775814 or gh#yast/yast-foo#42. See also [GitHub
-autolinking](https://help.github.com/articles/github-flavored-markdown#references)
-and [openSUSE abbreviation
-reference](http://en.opensuse.org/openSUSE:Packaging_Patches_guidelines#Current_set_of_abbreviations).
-
-Additional Information
-----------------------
-
-If you have any question, feel free to ask at the [development mailing
-list](http://lists.opensuse.org/yast-devel/) or at the
-[#yast](http://webchat.freenode.net/?channels=%23yast) IRC channel on freenode.
-We'll do our best to provide a timely and accurate answer.
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/yast2-pam-4.2.4/Rakefile new/yast2-pam-4.3.2/Rakefile
--- old/yast2-pam-4.2.4/Rakefile        2019-08-22 15:12:21.000000000 +0200
+++ new/yast2-pam-4.3.2/Rakefile        2020-07-28 14:27:50.000000000 +0200
@@ -1,6 +1,6 @@
 require "yast/rake"
 
 Yast::Tasks.configuration do |conf|
-  #lets ignore license check for now
+  # lets ignore license check for now
   conf.skip_license_check << /.*/
 end
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/yast2-pam-4.2.4/package/yast2-pam.changes 
new/yast2-pam-4.3.2/package/yast2-pam.changes
--- old/yast2-pam-4.2.4/package/yast2-pam.changes       2019-08-22 
15:12:21.000000000 +0200
+++ new/yast2-pam-4.3.2/package/yast2-pam.changes       2020-07-28 
14:27:50.000000000 +0200
@@ -1,4 +1,23 @@
 -------------------------------------------------------------------
+Tue Jul 28 11:35:47 UTC 2020 - Ancor Gonzalez Sosa <[email protected]>
+
+- Fixed a bug, introduced in the latest version, related to
+  deletion of nsswitch entries (related to bsc#1173119).
+- 4.3.2
+
+-------------------------------------------------------------------
+Tue Jul 28 11:03:14 CEST 2020 - [email protected]
+
+- Added function to query PAM modules (bsc#1171318).
+- 4.3.1
+
+-------------------------------------------------------------------
+Fri Jul 24 11:01:03 UTC 2020 - David Diaz <[email protected]>
+
+- Support reading nsswitch.conf from /usr/etc  (bsc#1173119).
+- 4.3.0
+
+-------------------------------------------------------------------
 Thu Aug 22 15:07:52 CEST 2019 - [email protected]
 
 - Using rb_default_ruby_abi tag in the spec file in order to
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/yast2-pam-4.2.4/package/yast2-pam.spec 
new/yast2-pam-4.3.2/package/yast2-pam.spec
--- old/yast2-pam-4.2.4/package/yast2-pam.spec  2019-08-22 15:12:21.000000000 
+0200
+++ new/yast2-pam-4.3.2/package/yast2-pam.spec  2020-07-28 14:27:50.000000000 
+0200
@@ -15,29 +15,36 @@
 # Please submit bugfixes or comments via http://bugs.opensuse.org/
 #
 
+Name:          yast2-pam
+Version:       4.3.2
+Release:       0
+Summary:       YaST2 - PAM Agent
+
+Group:         System/YaST
+License:       GPL-2.0-only
+URL:           http://github.com/yast/yast-pam
+Source0:       %{name}-%{version}.tar.bz2
+BuildRoot:     %{_tmppath}/%{name}-%{version}-build
+
+BuildRequires: yast2
+BuildRequires: yast2-devtools >= 3.1.10
+BuildRequires: rubygem(%{rb_default_ruby_abi}:yast-rake)
+# cfa for parsing nsswitch
+BuildRequires: rubygem(%rb_default_ruby_abi:cfa) >= 0.6.4
+# lenses are needed to use cfa
+BuildRequires: augeas-lenses
+# testsuite
+BuildRequires: rubygem(%rb_default_ruby_abi:rspec)
+
+Requires:           yast2
+# cfa for parsing nsswitch
+Requires:      rubygem(%rb_default_ruby_abi:cfa) >= 0.6.4
+# lenses are needed to use cfa
+Requires:      augeas-lenses
+Requires:           pam-config >= 0.8
+Requires:      yast2-ruby-bindings >= 1.0.0
 
-Name:           yast2-pam
-Version:        4.2.4
-Release:        0
-
-BuildRoot:      %{_tmppath}/%{name}-%{version}-build
-Source0:        %{name}-%{version}.tar.bz2
-
-Group:          System/YaST
-License:        GPL-2.0-only
-url:            http://github.com/yast/yast-pam
-BuildRequires:  yast2-devtools >= 3.1.10
-BuildRequires:  rubygem(%{rb_default_ruby_abi}:yast-rake)
-
-Requires:      yast2
-
-Requires:      pam-config >= 0.8
-
-BuildArch:      noarch
-
-Requires:       yast2-ruby-bindings >= 1.0.0
-
-Summary:       YaST2 - PAM Agent
+BuildArch:     noarch
 
 %description
 This agent is used by YaST2 to modify the PAM configuration files
@@ -59,6 +66,7 @@
 %{yast_moduledir}/*
 %dir %{yast_scrconfdir}
 %{yast_scrconfdir}/*.scr
+%{yast_libdir}
 %dir %{yast_agentdir}
 %{yast_agentdir}/ag_passwd
 %doc %{yast_docdir}
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/yast2-pam-4.2.4/src/lib/cfa/nsswitch.rb 
new/yast2-pam-4.3.2/src/lib/cfa/nsswitch.rb
--- old/yast2-pam-4.2.4/src/lib/cfa/nsswitch.rb 1970-01-01 01:00:00.000000000 
+0100
+++ new/yast2-pam-4.3.2/src/lib/cfa/nsswitch.rb 2020-07-28 14:27:50.000000000 
+0200
@@ -0,0 +1,260 @@
+# Copyright (c) [2020] SUSE LLC
+#
+# All Rights Reserved.
+#
+# This program is free software; you can redistribute it and/or modify it
+# under the terms of version 2 of the GNU General Public License as published
+# by the Free Software Foundation.
+#
+# This program is distributed in the hope that it will be useful, but WITHOUT
+# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+# FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+# more details.
+#
+# You should have received a copy of the GNU General Public License along
+# with this program; if not, contact SUSE LLC.
+#
+# To contact SUSE LLC about this file by physical or electronic mail, you may
+# find current contact information at www.suse.com.
+
+require "yast"
+require "cfa/base_model"
+require "yast2/target_file"
+
+Yast.import "FileUtils"
+
+module CFA
+  # Model to handle the Name Service Switch configuration file
+  #
+  # @note The NSS configuration file cannot be overwritten partially, which 
means that once
+  #   /etc/nsswith.conf (local) file exists in the system 
/usr/etc/nsswitch.conf (vendor) will be
+  #   completely ignored.  In other words, it does not allow to override 
single entries.
+  #   Consequently, to guarantee not losing full distribution provided 
configuration the content
+  #   will be read from the vendor file if the local one does not exist yet 
but will be always
+  #   written to the local file.
+  #
+  # @example Reading service specifications of a database
+  #   file = Nsswitch.new
+  #   file.load
+  #   file.services_for("hosts") #=> ["db", "files"]
+  #
+  # @example Writing service specifications for a database
+  #   file = Nsswitch.new
+  #   file.load
+  #   file.update_entry("hosts", ["db", "files"])
+  #   file.save
+  #
+  # @example Deleting a database entry
+  #   file = Nsswitch.new
+  #   file.load
+  #   file.delete_entry("hosts")
+  #   file.save
+  #
+  # @example Loading shortcut
+  #   file = Nsswitch.load
+  #   file.entries #=> ["passwd", "group", "shadow", "hosts", "networks", 
"aliases"]
+  class Nsswitch < BaseModel
+    include Yast::Logger
+
+    # Path to local configuration file
+    LOCAL_PATH = "/etc/nsswitch.conf".freeze
+    private_constant :LOCAL_PATH
+
+    # Path to vendor configuration file
+    VENDOR_PATH = "/usr/etc/nsswitch.conf".freeze
+    private_constant :VENDOR_PATH
+
+    class << self
+      # Instantiates and loads the file
+      #
+      # This method is basically a shortcut to instantiate and load the 
content in just one call.
+      #
+      # @param file_handler [#read,#write] something able to read/write a 
string (like File)
+      # @return [Nsswitch] File with the already loaded content
+      def load(file_handler: Yast::TargetFile)
+        new(file_handler: file_handler).tap(&:load)
+      end
+    end
+
+    attr_reader :load_path, :write_path
+
+    # Constructor
+    #
+    # @param file_handler [#read,#write] something able to read/write a string 
(like File)
+    #
+    # @see CFA::BaseModel#initialize
+    def initialize(file_handler: Yast::TargetFile)
+      # Path for loading the content
+      @load_path = Yast::FileUtils.Exists(LOCAL_PATH) ? LOCAL_PATH : 
VENDOR_PATH
+      # Path for writing the content, always the local file
+      @write_path = LOCAL_PATH
+
+      super(AugeasParser.new("nsswitch.lns"), load_path, file_handler: 
file_handler)
+    end
+
+    # Loads the file content
+    #
+    # If the file does not exist, consider it as empty.
+    #
+    # @see CFA::BaseModel#load
+    def load
+      super
+      fix_collection_names(data)
+      @current_content = @parser.serialize(data)
+    rescue Errno::ENOENT # PATH does not exist yet
+      self.data = @parser.empty
+      @loaded = true
+    end
+
+    # Returns a list of defined databases
+    #
+    # @return [Array<String>] List of database names
+    def entries
+      databases.keys
+    end
+
+    # Service specifications for given database name
+    #
+    # @param db_name [String] the database name, e.g., "passwd" or "hosts"
+    #
+    # @return [Array<String>] database service specifications or empty list if 
db_name is not found
+    def services_for(db_name)
+      databases[db_name]&.services || []
+    end
+
+    # Update (or create if it does not exist yet) the entry for given database 
name
+    #
+    #
+    # @note Current services, if any, are completely replaced
+    #
+    # @see #entry_for
+    # @see DatabaseEntry#services=
+    #
+    # @param db_name [String] the database name, e.g., "passwd" or "hosts"
+    # @param services [Array<String>] service specifications for the database
+    def update_entry(db_name, services)
+      database = entry_for(db_name)
+      database.services = services
+    end
+
+    # Delete entry for given database name
+    #
+    # @param db_name [String] the database db_name, e.g., "passwd" or "hosts"
+    def delete_entry(db_name)
+      data.delete(database_matcher(db_name))
+    end
+
+    # Writes the current content to /etc/nsswitch.conf
+    #
+    # @see CFA::BaseModel#save
+    def save
+      @parser.file_name = write_path if @parser.respond_to?(:file_name=)
+      content = @parser.serialize(data)
+
+      if content != @current_content
+        @file_handler.write(write_path, content)
+        @current_content = content
+      end
+    end
+
+  private
+
+    # Return the CFA::Matcher for given database name
+    #
+    # @param db_name [String] the database name, e.g., "passwd" or "hosts"
+    #
+    # @return [CFA::Matcher]
+    def database_matcher(db_name)
+      CFA::Matcher.new { |k, v| k == "database[]" && v.value == db_name }
+    end
+
+    # Find or create the DatabaseEntry for given database name
+    #
+    # @param db_name [String] the database name, e.g., "passwd" or "hosts"
+    #
+    # @return [DatabaseEntry]
+    def entry_for(db_name)
+      return databases[db_name] if databases.keys.include?(db_name)
+
+      database = CFA::AugeasTreeValue.new(CFA::AugeasTree.new, db_name)
+      data.add("database[]", database)
+      DatabaseEntry.new(database)
+    end
+
+    # Available databases
+    #
+    # @return [Hash{String => DatabaseEntry}]
+    def databases
+      raw_databases.each_with_object({}) do |database, collection|
+        name = database[:value].value.to_s
+        collection[name] = DatabaseEntry.new(database[:value])
+      end
+    end
+
+    # Available databases in internal structure
+    #
+    # @return [Array<Hash{Symbol => CFA::AugeasTreeValue, String, Symbol}>]
+    def raw_databases
+      data.select(CFA::Matcher.new(collection: "database"))
+    end
+
+    # Known collection keys
+    COLLECTION_KEYS = ["database", "service"].freeze
+    private_constant :COLLECTION_KEYS
+
+    # Fix collection names adding the missing "[]"
+    #
+    # When a collection has only one element, Augeas does not add "[]" suffix, 
reason why is
+    # necessary to fix at least those collections that are going to be hitted 
for either, read or
+    # write.
+    #
+    # @param tree [AugeasTree,AugeasTreeValue]
+    def fix_collection_names(tree)
+      tree.data.each do |entry|
+        entry[:key] << "[]" if COLLECTION_KEYS.include?(entry[:key])
+        fix_collection_names(entry[:value].tree) if 
entry[:value].is_a?(AugeasTreeValue)
+        fix_collection_names(entry[:value]) if entry[:value].is_a?(AugeasTree)
+      end
+    end
+
+    # Internal class for managing database entries
+    class DatabaseEntry
+      # Constructor
+      #
+      # @param data [CFA::AugeasTreeValue]
+      def initialize(data)
+        @data = data
+      end
+
+      # The database name
+      #
+      # @return [String]
+      def name
+        data.value
+      end
+
+      # The database service specifications
+      #
+      # @return [Array<String>]
+      def services
+        data.tree.collection("service").map(&:to_s)
+      end
+
+      # Set service specifications
+      #
+      # TODO: add support for reactions
+      #
+      # @param services [Array<String>]
+      def services=(services)
+        data.tree.delete("service[]")
+        data.tree.delete("reaction[]")
+
+        services.each { |service| data.tree.add("service[]", service) }
+      end
+
+    private
+
+      attr_reader :data
+    end
+  end
+end
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/yast2-pam-4.2.4/src/modules/Nsswitch.rb 
new/yast2-pam-4.3.2/src/modules/Nsswitch.rb
--- old/yast2-pam-4.2.4/src/modules/Nsswitch.rb 2019-08-22 15:12:21.000000000 
+0200
+++ new/yast2-pam-4.3.2/src/modules/Nsswitch.rb 2020-07-28 14:27:50.000000000 
+0200
@@ -27,78 +27,95 @@
 #
 # $Id$
 require "yast"
+require "cfa/nsswitch"
 
 module Yast
   class NsswitchClass < Module
     def main
-
       Yast.import "Message"
       Yast.import "Report"
     end
 
     # Reads a database entry from nsswitch_conf and returns it as a list
-    # @param [String] db eg. "passwd"
-    # @return   eg. ["files", "nis"]
-    def ReadDb(db)
-      db_s = Convert.to_string(
-        SCR.Read(Builtins.add(path(".etc.nsswitch_conf"), db))
-      )
-      db_s = "" if db_s == nil
-      Builtins.filter(Builtins.splitstring(db_s, " \t")) { |s| s != "" }
+    #
+    # @see CFA::Nsswitch#services_for
+    #
+    # @param db_name [String] database entry name, e.g. "passwd"
+    def ReadDb(db_name)
+      cfa_model.services_for(db_name)
     end
 
 
-    # Writes a database entry as a list to nsswitch_conf
-    # @param [String] db eg. "passwd"
-    # @param [Array<String>] entries eg. ["files", "nis"]
-    # @return success?
-    def WriteDb(db, entries)
-      entries = deep_copy(entries)
-      # if there are no entries, delete the key using nil
-      entry = Builtins.mergestring(entries, " ")
-      SCR.Write(
-        Builtins.add(path(".etc.nsswitch_conf"), db),
-        entry == "" ? nil : entry
-      )
-    end
-    # Configures the name service switch for autofs
-    # according to chosen settings
-    # @param [Boolean] start autofs and service (ldap/nis) should be started
-    # @param [String] source for automounter data (ldap/nis)
-    # @return success?
+    # Writes a database entry as a list to nsswitch_conf or deletes an existing
+    # database entry
+    #
+    # @see CFA::Nsswitch#update_entry
+    # @see CFA::Nsswitch#delete_entry
+    #
+    # @param db_name [String] database entry name, e.g. "passwd"
+    # @param services [Array<String>] use a valid service specs (e.g. 
["files", "nis"])
+    #   to write an entry or an empty array to remove the existing entry
+    def WriteDb(db_name, services)
+      # For improved compatibility with the old implementation, check also [""]
+      if services.empty? || services == [""]
+        cfa_model.delete_entry(db_name)
+      else
+        cfa_model.update_entry(db_name, services)
+      end
+    end
+
+    # Configures the name service switch for autofs according to chosen 
settings
+    #
+    # @see #Write
+    #
+    # @param start [Boolean] whether autofs and service (ldap/nis) should be 
started
+    # @param source [String] source for automounter data (ldap/nis)
+    #
+    # @return [Boolean] true on success; false otherwise
     def WriteAutofs(start, source)
-      ok = true
+      automount_services = cfa_model.services_for("automount")
 
-      # nsswitch automount:
-      # bracket options not allowed, order does not matter
-      automount_l = ReadDb("automount")
-      enabled = Builtins.contains(automount_l, source)
-      # enable it if it is not enabled yet and both services run
-      if start && !enabled
-        automount_l = Builtins.add(automount_l, source)
-        ok = WriteDb("automount", automount_l)
-        ok = ok && SCR.Write(path(".etc.nsswitch_conf"), nil)
-      # disable it if it is enabled and either service does not run
-      elsif !start && enabled
-        automount_l = Builtins.filter(automount_l) { |s| s != source }
-        ok = WriteDb("automount", automount_l)
-        ok = ok && SCR.Write(path(".etc.nsswitch_conf"), nil)
+      if start
+        automount_services |= [source]
+      else
+        automount_services -= [source]
       end
 
-      Report.Error(Message.ErrorWritingFile("/etc/nsswitch.conf")) if !ok
-      ok
+      cfa_model.update_entry("automount", automount_services)
+      Write()
     end
 
-    # Writes the edited files to the disk
-    # @return true on success
+    # Writes changes to the file
+    #
+    # @note sadly, this method will directly report to the user if something 
goes wrong.
+    #
+    # @return [Boolean] true on success; false otherwise
     def Write
-      SCR.Write(path(".etc.nsswitch_conf"), nil)
+      cfa_model.save
+      true
+    rescue CFA::AugeasSerializingError
+      Report.Error(Message.ErrorWritingFile(cfa_model.write_path))
+
+      false
+    end
+
+    # Convenience method to force the CFA model reloading for next action
+    #
+    # Especially useful for testing the behavior
+    def reset
+      @cfa_model = nil
     end
 
     publish :function => :ReadDb, :type => "list <string> (string)"
     publish :function => :WriteDb, :type => "boolean (string, list <string>)"
     publish :function => :WriteAutofs, :type => "boolean (boolean, string)"
     publish :function => :Write, :type => "boolean ()"
+
+  private
+
+    def cfa_model
+      @cfa_model ||= CFA::Nsswitch.load
+    end
   end
 
   Nsswitch = NsswitchClass.new
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/yast2-pam-4.2.4/src/modules/Pam.rb 
new/yast2-pam-4.3.2/src/modules/Pam.rb
--- old/yast2-pam-4.2.4/src/modules/Pam.rb      2019-08-22 15:12:21.000000000 
+0200
+++ new/yast2-pam-4.3.2/src/modules/Pam.rb      2020-07-28 14:27:50.000000000 
+0200
@@ -25,14 +25,43 @@
 # Authors:     Jiri Suchomel <[email protected]>
 # Flags:       Unstable
 #
-# $Id$
-#
 require "yast"
+require "yast2/execute"
 
 module Yast
   class PamClass < Module
+    include Yast::Logger
+
     def main
+    end
+
+    PAM_CONFIG_BIN = "/usr/sbin/pam-config".freeze
+
+    # List PAM modules.
+    #
+    # The returned module names do not include the "pam_" prefix nor
+    # the ".so" suffix. So just "pwquality" instead of "pam_pwquality.so".
+    #
+    # @return [Array{String}]
+    def List
+      begin
+        lines = Yast::Execute.locally!(PAM_CONFIG_BIN, "--list-modules",
+          :stdout => :capture).split("\n")
+      rescue Cheetah::ExecutionFailed => e
+        log.error "pam-config --list-modules failed #{e.message}"
+        return []
+      end
+
+      rx = /[ \t]*pam_([a-z0-9_]+)\.so[ \t]*/
 
+      mods = lines.reduce([]) do |mods, line|
+        m = line.match(rx)
+        m ? mods.push(m[1]) : mods
+      end
+
+      log.info("pam modules #{mods}")
+
+      mods
     end
 
     # Query PAM configuration for status of given module
@@ -42,10 +71,7 @@
     def Query(mod)
       ret = {}
       out = Convert.to_map(
-        SCR.Execute(
-          path(".target.bash_output"),
-          Ops.add("/usr/sbin/pam-config -q --", mod)
-        )
+        SCR.Execute(path(".target.bash_output"), PAM_CONFIG_BIN + " -q --" + 
mod)
       )
       if Ops.get_integer(out, "exit", 0) != 0
         Builtins.y2warning("pam-config for %1 returned %2", mod, out)
@@ -78,10 +104,7 @@
     # @return success
     def Add(mod)
       out = Convert.to_map(
-        SCR.Execute(
-          path(".target.bash_output"),
-          Ops.add("/usr/sbin/pam-config -a --", mod)
-        )
+        SCR.Execute(path(".target.bash_output"), PAM_CONFIG_BIN + " -a --" + 
mod)
       )
       if Ops.get_integer(out, "exit", 0) != 0
         Builtins.y2warning("pam-config for %1 returned %2", mod, out)
@@ -95,10 +118,7 @@
     # @return success
     def Remove(mod)
       out = Convert.to_map(
-        SCR.Execute(
-          path(".target.bash_output"),
-          Ops.add("/usr/sbin/pam-config -d --", mod)
-        )
+        SCR.Execute(path(".target.bash_output"), PAM_CONFIG_BIN + " -d --" + 
mod)
       )
       if Ops.get_integer(out, "exit", 0) != 0
         Builtins.y2warning("pam-config for %1 returned %2", mod, out)
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/yast2-pam-4.2.4/src/scrconf/etc_nsswitch.scr 
new/yast2-pam-4.3.2/src/scrconf/etc_nsswitch.scr
--- old/yast2-pam-4.2.4/src/scrconf/etc_nsswitch.scr    2019-08-22 
15:12:21.000000000 +0200
+++ new/yast2-pam-4.3.2/src/scrconf/etc_nsswitch.scr    1970-01-01 
01:00:00.000000000 +0100
@@ -1,31 +0,0 @@
-/**
- * File:       etc_nsswitch_conf.scr
- * Summary:    Agent for reading/writing /etc/nsswitch.conf
- * Access:     read / write
- * Author:     Petr Blahos <[email protected]>
- *
- * Example:
- *   Dir(.etc.nsswitch_conf)
- *   (["passwd", "group", "hosts", "networks", "services"])
- **
- *   Read(.etc.nsswitch_conf.passwd)
- *   ("compat")
- **
- *   Write(.etc.nsswitch_conf.passwd, "files ldap")
- *   (true)
- *
- * $Id$
- */
-.etc.nsswitch_conf
-
-`ag_ini(
-    `IniAgent( "/etc/nsswitch.conf",
-       $[
-           "options" : [ "ignore_case", "global_values", "flat" ],
-           "comments" : [ "^#.*", "^[ \t]*$", ],
-           "params" : [
-               $[ "match" : [ "^[ \t]*([a-zA-Z0-9_]+)[ \t]*:[ \t]*(.*[^ \t]|)[ 
\t]*$", "%s:\t%s" ] ]
-           ]
-       ]
-    )
-)
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/yast2-pam-4.2.4/test/cfa/nsswitch_test.rb 
new/yast2-pam-4.3.2/test/cfa/nsswitch_test.rb
--- old/yast2-pam-4.2.4/test/cfa/nsswitch_test.rb       1970-01-01 
01:00:00.000000000 +0100
+++ new/yast2-pam-4.3.2/test/cfa/nsswitch_test.rb       2020-07-28 
14:27:50.000000000 +0200
@@ -0,0 +1,184 @@
+# Copyright (c) [2020] SUSE LLC
+#
+# All Rights Reserved.
+#
+# This program is free software; you can redistribute it and/or modify it
+# under the terms of version 2 of the GNU General Public License as published
+# by the Free Software Foundation.
+#
+# This program is distributed in the hope that it will be useful, but WITHOUT
+# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+# FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+# more details.
+#
+# You should have received a copy of the GNU General Public License along
+# with this program; if not, contact SUSE LLC.
+#
+# To contact SUSE LLC about this file by physical or electronic mail, you may
+# find current contact information at www.suse.com.
+
+require_relative "../test_helper"
+require "cfa/nsswitch"
+require "cfa/memory_file"
+
+describe CFA::Nsswitch do
+  subject { described_class.new(file_handler: file_handler) }
+
+  let(:file_handler) { Yast::TargetFile }
+  let(:scenario) { "custom" }
+
+  around do |example|
+    change_scr_root(File.join(DATA_PATH, "nsswitch.conf", scenario), &example)
+  end
+
+  describe "#load" do
+    context "when /etc/nsswitch.conf exists" do
+      before do
+        allow(file_handler).to receive(:read).and_call_original
+      end
+
+      it "does not read /usr/etc/nsswitch.conf file" do
+        expect(file_handler).to_not receive(:read)
+          .with("/usr/etc/nsswitch.conf")
+        subject.load
+      end
+
+      it "reads /etc/nsswitch.conf file" do
+        expect(file_handler).to receive(:read)
+          .with("/etc/nsswitch.conf")
+          .and_call_original
+        subject.load
+      end
+    end
+
+    context "when /etc/nsswitch.conf does not exist" do
+      let(:scenario) { "vendor" }
+
+      it "reads vendor files" do
+        expect(file_handler).to receive(:read)
+          .with("/usr/etc/nsswitch.conf")
+          .and_call_original
+        subject.load
+      end
+    end
+  end
+
+  describe "#save" do
+    before { subject.load }
+
+    let(:file_handler) { CFA::MemoryFile.new(file_content) }
+    let(:file_content) do
+      <<~CONTENT
+        # An custom Name Service Switch config file.
+        #
+        # Valid databases are: aliases, ethers, group, gshadow, hosts,
+        # initgroups, netgroup, networks, passwd, protocols, publickey,
+        # rpc, services, and shadow.
+
+        passwd: compat
+        group:  compat
+        shadow: compat
+
+        hosts:  db files
+      CONTENT
+    end
+
+    context "when it has changed" do
+      before do
+        subject.update_entry("hosts", ["dns", "nis"])
+      end
+
+      it "writes requested changes" do
+        subject.save
+
+        expect(file_handler.content).to match(/hosts:\s+dns nis/)
+        expect(file_handler.content).to_not match(/hosts:  db files/)
+      end
+
+      it "writes to /etc/nsswitch.conf file" do
+        expect(file_handler).to receive(:write)
+          .with("/etc/nsswitch.conf", anything)
+        subject.save
+      end
+
+      it "does not write to /usr/etc/nsswitch.conf file" do
+        expect(file_handler).to_not receive(:write)
+          .with("/user/etc/nsswitch.conf", anything)
+        subject.save
+      end
+    end
+
+    context "when it has not changed" do
+      it "does nothing" do
+        expect(file_handler).to_not receive(:write)
+
+        subject.save
+
+        expect(file_handler.content).to eq(file_content)
+      end
+    end
+  end
+
+  describe "#entries" do
+    before { subject.load }
+
+    it "returns the database names currently present in the configuration" do
+      expect(subject.entries).to eq(["passwd", "group", "shadow", "hosts"])
+    end
+  end
+
+  describe "#services_for" do
+    before { subject.load }
+
+    context "when given an available database entry" do
+      it "returns the service specifications for given database name" do
+        expect(subject.services_for("hosts")).to eq(["db", "files"])
+      end
+    end
+
+    context "when given a not available database entry" do
+      it "returns an empty list" do
+        expect(subject.services_for("foo")).to eq([])
+      end
+    end
+  end
+
+  describe "#update_entry" do
+    before { subject.load }
+
+    context "when given an available database entry" do
+      it "changes database entry to use given services" do
+        old_services = subject.services_for("hosts")
+        new_services = ["other", "services"]
+        subject.update_entry("hosts", new_services)
+        updated_services = subject.services_for("hosts")
+
+        expect(updated_services).to eq(new_services)
+        expect(updated_services).to_not eq(old_services)
+      end
+    end
+
+    context "when given a not available database entry" do
+      it "creates the database entry with given services" do
+        expect(subject.entries).to_not include("foo")
+
+        subject.update_entry("foo", ["bar"])
+
+        expect(subject.entries).to include("foo")
+        expect(subject.services_for("foo")).to eq(["bar"])
+      end
+    end
+  end
+
+  describe "#delete_entry" do
+    before { subject.load }
+
+    it "deletes given entry" do
+      expect(subject.services_for("hosts")).to eq(["db", "files"])
+
+      subject.delete_entry("hosts")
+
+      expect(subject.services_for("hosts")).to eq([])
+    end
+  end
+end
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/yast2-pam-4.2.4/test/data/nsswitch.conf/custom/etc/nsswitch.conf 
new/yast2-pam-4.3.2/test/data/nsswitch.conf/custom/etc/nsswitch.conf
--- old/yast2-pam-4.2.4/test/data/nsswitch.conf/custom/etc/nsswitch.conf        
1970-01-01 01:00:00.000000000 +0100
+++ new/yast2-pam-4.3.2/test/data/nsswitch.conf/custom/etc/nsswitch.conf        
2020-07-28 14:27:50.000000000 +0200
@@ -0,0 +1,13 @@
+# /etc/nsswitch.conf
+#
+# An custom Name Service Switch config file.
+#
+# Valid databases are: aliases, ethers, group, gshadow, hosts,
+# initgroups, netgroup, networks, passwd, protocols, publickey,
+# rpc, services, and shadow.
+
+passwd: compat
+group:  compat
+shadow: compat
+
+hosts:  db files
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/yast2-pam-4.2.4/test/data/nsswitch.conf/custom/usr/etc/nsswitch.conf 
new/yast2-pam-4.3.2/test/data/nsswitch.conf/custom/usr/etc/nsswitch.conf
--- old/yast2-pam-4.2.4/test/data/nsswitch.conf/custom/usr/etc/nsswitch.conf    
1970-01-01 01:00:00.000000000 +0100
+++ new/yast2-pam-4.3.2/test/data/nsswitch.conf/custom/usr/etc/nsswitch.conf    
2020-07-28 14:27:50.000000000 +0200
@@ -0,0 +1,74 @@
+#
+# /etc/nsswitch.conf
+#
+# An example Name Service Switch config file. This file should be
+# sorted with the most-used services at the beginning.
+#
+# Valid databases are: aliases, ethers, group, gshadow, hosts,
+# initgroups, netgroup, networks, passwd, protocols, publickey,
+# rpc, services, and shadow.
+#
+# Valid service provider entries include (in alphabetical order):
+#
+#      compat                  Use /etc files plus *_compat pseudo-db
+#      db                      Use the pre-processed /var/db files
+#      dns                     Use DNS (Domain Name Service)
+#      files                   Use the local files in /etc
+#      hesiod                  Use Hesiod (DNS) for user lookups
+#      nis                     Use NIS (NIS version 2), also called YP
+#      nisplus                 Use NIS+ (NIS version 3)
+#
+# See `info libc 'NSS Basics'` for more information.
+#
+# Commonly used alternative service providers (may need installation):
+#
+#      ldap                    Use LDAP directory server
+#      myhostname              Use systemd host names
+#      mymachines              Use systemd machine names
+#      mdns*, mdns*_minimal    Use Avahi mDNS/DNS-SD
+#      resolve                 Use systemd resolved resolver
+#      sss                     Use System Security Services Daemon (sssd)
+#      systemd                 Use systemd for dynamic user option
+#      winbind                 Use Samba winbind support
+#      wins                    Use Samba wins support
+#      wrapper                 Use wrapper module for testing
+#
+# Notes:
+#
+# 'sssd' performs its own 'files'-based caching, so it should generally
+# come before 'files'.
+#
+# WARNING: Running nscd with a secondary caching service like sssd may
+#         lead to unexpected behaviour, especially with how long
+#         entries are cached.
+#
+# Installation instructions:
+#
+# To use 'db', install the appropriate package(s) (provide 'makedb' and
+# libnss_db.so.*), and place the 'db' in front of 'files' for entries
+# you want to be looked up first in the databases, like this:
+#
+# passwd:    db files
+# shadow:    db files
+# group:     db files
+
+passwd:                compat
+group:         compat
+shadow:                compat
+# Allow initgroups to default to the setting for group.
+# initgroups:  compat
+
+hosts:         files dns
+networks:      files dns
+
+aliases:       files usrfiles
+ethers:                files usrfiles
+gshadow:       files usrfiles
+netgroup:      files nis
+protocols:     files usrfiles
+publickey:     files
+rpc:           files usrfiles
+
+bootparams:    files
+netmasks:      files
+services:      files usrfiles
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/yast2-pam-4.2.4/test/data/nsswitch.conf/vendor/usr/etc/nsswitch.conf 
new/yast2-pam-4.3.2/test/data/nsswitch.conf/vendor/usr/etc/nsswitch.conf
--- old/yast2-pam-4.2.4/test/data/nsswitch.conf/vendor/usr/etc/nsswitch.conf    
1970-01-01 01:00:00.000000000 +0100
+++ new/yast2-pam-4.3.2/test/data/nsswitch.conf/vendor/usr/etc/nsswitch.conf    
2020-07-28 14:27:50.000000000 +0200
@@ -0,0 +1,74 @@
+#
+# /etc/nsswitch.conf
+#
+# An example Name Service Switch config file. This file should be
+# sorted with the most-used services at the beginning.
+#
+# Valid databases are: aliases, ethers, group, gshadow, hosts,
+# initgroups, netgroup, networks, passwd, protocols, publickey,
+# rpc, services, and shadow.
+#
+# Valid service provider entries include (in alphabetical order):
+#
+#      compat                  Use /etc files plus *_compat pseudo-db
+#      db                      Use the pre-processed /var/db files
+#      dns                     Use DNS (Domain Name Service)
+#      files                   Use the local files in /etc
+#      hesiod                  Use Hesiod (DNS) for user lookups
+#      nis                     Use NIS (NIS version 2), also called YP
+#      nisplus                 Use NIS+ (NIS version 3)
+#
+# See `info libc 'NSS Basics'` for more information.
+#
+# Commonly used alternative service providers (may need installation):
+#
+#      ldap                    Use LDAP directory server
+#      myhostname              Use systemd host names
+#      mymachines              Use systemd machine names
+#      mdns*, mdns*_minimal    Use Avahi mDNS/DNS-SD
+#      resolve                 Use systemd resolved resolver
+#      sss                     Use System Security Services Daemon (sssd)
+#      systemd                 Use systemd for dynamic user option
+#      winbind                 Use Samba winbind support
+#      wins                    Use Samba wins support
+#      wrapper                 Use wrapper module for testing
+#
+# Notes:
+#
+# 'sssd' performs its own 'files'-based caching, so it should generally
+# come before 'files'.
+#
+# WARNING: Running nscd with a secondary caching service like sssd may
+#         lead to unexpected behaviour, especially with how long
+#         entries are cached.
+#
+# Installation instructions:
+#
+# To use 'db', install the appropriate package(s) (provide 'makedb' and
+# libnss_db.so.*), and place the 'db' in front of 'files' for entries
+# you want to be looked up first in the databases, like this:
+#
+# passwd:    db files
+# shadow:    db files
+# group:     db files
+
+passwd:                compat
+group:         compat
+shadow:                compat
+# Allow initgroups to default to the setting for group.
+# initgroups:  compat
+
+hosts:         files dns
+networks:      files dns
+
+aliases:       files usrfiles
+ethers:                files usrfiles
+gshadow:       files usrfiles
+netgroup:      files nis
+protocols:     files usrfiles
+publickey:     files
+rpc:           files usrfiles
+
+bootparams:    files
+netmasks:      files
+services:      files usrfiles
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/yast2-pam-4.2.4/test/nsswitch_test.rb 
new/yast2-pam-4.3.2/test/nsswitch_test.rb
--- old/yast2-pam-4.2.4/test/nsswitch_test.rb   1970-01-01 01:00:00.000000000 
+0100
+++ new/yast2-pam-4.3.2/test/nsswitch_test.rb   2020-07-28 14:27:50.000000000 
+0200
@@ -0,0 +1,203 @@
+#!/usr/bin/env rspec
+# Copyright (c) [2020] SUSE LLC
+#
+# All Rights Reserved.
+#
+# This program is free software; you can redistribute it and/or modify it
+# under the terms of version 2 of the GNU General Public License as published
+# by the Free Software Foundation.
+#
+# This program is distributed in the hope that it will be useful, but WITHOUT
+# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+# FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+# more details.
+#
+# You should have received a copy of the GNU General Public License along
+# with this program; if not, contact SUSE LLC.
+#
+# To contact SUSE LLC about this file by physical or electronic mail, you may
+# find current contact information at www.suse.com.
+
+require_relative "test_helper"
+require "tmpdir"
+
+Yast.import "Nsswitch"
+
+describe Yast::Nsswitch do
+  subject(:nsswitch) { Yast::Nsswitch }
+
+  let(:tmpdir) { Dir.mktmpdir }
+  let(:original_data_example) { File.join(DATA_PATH, 
"nsswitch.conf/custom/etc") }
+  let(:file_path) { "#{tmpdir}/etc/nsswitch.conf" }
+
+  around do |example|
+    begin
+      FileUtils.cp_r(original_data_example, tmpdir)
+      change_scr_root(tmpdir, &example)
+      nsswitch.reset
+    ensure
+      FileUtils.remove_entry(tmpdir)
+    end
+  end
+
+  describe "#ReadDb" do
+    context "when given an available database entry" do
+      let(:db_name) { "hosts" }
+
+      it "returns its defined service specifications" do
+        expect(nsswitch.ReadDb(db_name)).to eq(["db", "files"])
+      end
+    end
+
+    context "when given a not available database entry" do
+      let(:db_name) { "ethers" }
+
+      it "returns an empty list" do
+        expect(nsswitch.ReadDb(db_name)).to eq([])
+      end
+    end
+  end
+
+  describe "#WriteDb" do
+    it "changes given database without writing to the file" do
+      expect(File.read(file_path)).to_not match(/ethers:/)
+      expect(nsswitch.ReadDb("ethers")).to eq([])
+
+      nsswitch.WriteDb("ethers", ["nis", "files"])
+
+      expect(nsswitch.ReadDb("ethers")).to eq(["nis", "files"])
+      expect(File.read(file_path)).to_not match(/ethers:/)
+    end
+
+    context "when given an already defined database entry" do
+      it "replaces its service specifications with given ones" do
+        expect(nsswitch.ReadDb("hosts")).to eq(["db", "files"])
+
+        nsswitch.WriteDb("hosts", ["nis", "files"])
+
+        expect(nsswitch.ReadDb("hosts")).to eq(["nis", "files"])
+      end
+
+      context "if the service specification is an empty array" do
+        it "removes the database entry" do
+          expect(nsswitch.ReadDb("hosts")).to eq(["db", "files"])
+
+          nsswitch.WriteDb("hosts", [])
+
+          expect(nsswitch.ReadDb("hosts")).to eq([])
+        end
+      end
+    end
+
+    context "when given not defined yet database entry" do
+      it "adds it to the configuration" do
+        expect(nsswitch.ReadDb("ethers")).to eq([])
+
+        nsswitch.WriteDb("ethers", ["nis", "files"])
+
+        expect(nsswitch.ReadDb("ethers")).to eq(["nis", "files"])
+      end
+
+      context "if the service specification is an empty array" do
+        it "changes nothing" do
+          expect(nsswitch.ReadDb("ethers")).to eq([])
+
+          nsswitch.WriteDb("ethers", [])
+
+          expect(nsswitch.ReadDb("ethers")).to eq([])
+        end
+      end
+    end
+  end
+
+  describe "#WriteAutofs" do
+    let(:db_name) { "automount" }
+
+    context "when services should start" do
+      let(:start) { true }
+
+      context "and it is not enabled yet" do
+        let(:source) { "nis" }
+
+        it "enables it by adding it to service specifications" do
+          nsswitch.WriteAutofs(start, source)
+
+          expect(File.read(file_path)).to match(/automount:\s+nis/)
+        end
+      end
+    end
+
+    context "when services should not start" do
+      let(:start) { false }
+
+      context "but it is enabled" do
+        let(:source) { "nis" }
+
+        before do
+          nsswitch.WriteDb(db_name, ["nis", "ldap"])
+          nsswitch.Write
+        end
+
+        it "disables it by removing it from service specifications" do
+          expect(File.read(file_path)).to match(/automount:\s+nis ldap/)
+
+          nsswitch.WriteAutofs(start, source)
+
+          expect(File.read(file_path)).to match(/automount:\s+ldap/)
+          expect(File.read(file_path)).to_not match(/automount:\s+nis/)
+        end
+      end
+    end
+  end
+
+  describe "#Write" do
+    context "when everything is right" do
+      it "returns true" do
+        nsswitch.WriteDb("ethers", ["nis", "files"])
+        expect(nsswitch.Write).to eq(true)
+      end
+
+      it "writes changes to the file" do
+        expect(File.read(file_path)).to_not match(/ethers:/)
+        expect(File.read(file_path)).to match(/hosts:/)
+        expect(File.read(file_path)).to_not match(/netmasks:/)
+
+        nsswitch.WriteDb("ethers", ["nis", "files"])
+        # Test deleting entries
+        nsswitch.WriteDb("hosts", [])
+        nsswitch.WriteDb("netmasks", [])
+        nsswitch.Write
+
+        expect(File.read(file_path)).to match(/ethers:\s+nis files/)
+        expect(File.read(file_path)).to_not match(/hosts:/)
+        expect(File.read(file_path)).to_not match(/netmasks:/)
+      end
+    end
+
+    context "when something is wrong" do
+      it "returns false" do
+        # there is not support for actions yet
+        nsswitch.WriteDb("ethers", ["nis [NOTFOUND=return]", "files"])
+        expect(nsswitch.Write).to eq(false)
+      end
+
+      it "reports an error" do
+        # there is not support for actions yet
+        nsswitch.WriteDb("ethers", ["nis [NOTFOUND=return]", "files"])
+        expect(Yast::Message).to 
receive(:ErrorWritingFile).with(/nsswitch\.conf/)
+        expect(Yast::Report).to receive(:Error)
+        nsswitch.Write
+      end
+
+      it "does not change the file" do
+        expect(File.read(file_path)).to_not match(/ethers:/)
+
+        # there is not support for actions yet
+        nsswitch.WriteDb("ethers", ["nis [NOTFOUND=return]", "files"])
+        nsswitch.Write
+
+        expect(File.read(file_path)).to_not match(/ethers:\s+nis files/)
+      end
+    end
+  end
+end
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/yast2-pam-4.2.4/test/test_helper.rb 
new/yast2-pam-4.3.2/test/test_helper.rb
--- old/yast2-pam-4.2.4/test/test_helper.rb     1970-01-01 01:00:00.000000000 
+0100
+++ new/yast2-pam-4.3.2/test/test_helper.rb     2020-07-28 14:27:50.000000000 
+0200
@@ -0,0 +1,50 @@
+# Copyright (c) [2020] SUSE LLC
+#
+# All Rights Reserved.
+#
+# This program is free software; you can redistribute it and/or modify it
+# under the terms of version 2 of the GNU General Public License as published
+# by the Free Software Foundation.
+#
+# This program is distributed in the hope that it will be useful, but WITHOUT
+# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+# FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+# more details.
+#
+# You should have received a copy of the GNU General Public License along
+# with this program; if not, contact SUSE LLC.
+#
+# To contact SUSE LLC about this file by physical or electronic mail, you may
+# find current contact information at www.suse.com.
+
+# Set the paths
+SRC_PATH = File.expand_path("../src", __dir__)
+DATA_PATH = File.join(__dir__, "data")
+y2dirs = ENV.fetch("Y2DIR", "").split(":")
+ENV["Y2DIR"] = y2dirs.unshift(SRC_PATH).join(":")
+
+# Ensure the tests runs with English locales
+ENV["LANG"] = "en_US.UTF-8"
+ENV["LC_ALL"] = "en_US.UTF-8"
+
+require "yast"
+require "yast/rspec"
+
+if ENV["COVERAGE"]
+  require "simplecov"
+  SimpleCov.start do
+    add_filter "/test/"
+  end
+
+  # track all ruby files under src
+  SimpleCov.track_files("#{SRC_PATH}/**/*.rb")
+
+  # use coveralls for on-line code coverage reporting at Travis CI
+  if ENV["TRAVIS"]
+    require "coveralls"
+    SimpleCov.formatter = SimpleCov::Formatter::MultiFormatter[
+      SimpleCov::Formatter::HTMLFormatter,
+      Coveralls::SimpleCov::Formatter
+    ]
+  end
+end


Reply via email to