From 600930d2ec407bb31f3118371d5c0c23d18bf099 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ladislav=20Slez=C3=A1k?= Date: Tue, 21 Apr 2020 16:12:24 +0200 Subject: [PATCH 1/6] Adapt Rakefile and Dockerfile for SLE-15-SP2 --- Dockerfile | 2 +- Rakefile | 2 ++ 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/Dockerfile b/Dockerfile index c54e79161..633ef065d 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,7 +1,7 @@ # Use this base image # - built: https://registry.opensuse.org # - source: https://github.com/yast/ci-ruby-container -FROM registry.opensuse.org/yast/head/containers/yast-ruby +FROM registry.opensuse.org/yast/sle-15/sp2/containers/yast-ruby COPY . /usr/src/app # English messages, UTF-8, "C" locale for numeric formatting tests ENV LC_ALL= LANG=en_US.UTF-8 LC_NUMERIC=C diff --git a/Rakefile b/Rakefile index 09e49223b..27038d0b0 100644 --- a/Rakefile +++ b/Rakefile @@ -1,5 +1,7 @@ require "yast/rake" +Yast::Tasks.submit_to :sle15sp2 + Yast::Tasks.configuration do |conf| # lets ignore license check for now conf.skip_license_check << /.*/ From 3bf7accf0d13f0cca1066a29df2cbbd81f801911 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Knut=20Alejandro=20Anderssen=20Gonz=C3=A1lez?= Date: Fri, 24 Apr 2020 16:22:24 +0100 Subject: [PATCH 2/6] Return InstallationUnitProperties when running inside a chroot --- library/systemd/src/lib/yast2/systemd/unit.rb | 4 +++- library/systemd/test/yast2/systemctl_test.rb | 1 + library/systemd/test/yast2/systemd_unit_test.rb | 3 ++- 3 files changed, 6 insertions(+), 2 deletions(-) diff --git a/library/systemd/src/lib/yast2/systemd/unit.rb b/library/systemd/src/lib/yast2/systemd/unit.rb index 0441a0a42..219d43699 100644 --- a/library/systemd/src/lib/yast2/systemd/unit.rb +++ b/library/systemd/src/lib/yast2/systemd/unit.rb @@ -106,7 +106,9 @@ def refresh! # @return [Yast2::Systemd::UnitProperties] def show(property_text = nil) # Using different handler during first stage (installation, update, ...) - if Yast::Stage.initial && !Yast::Systemd.Running + # Avoid to call systemctl when running inside a chroot (bsc#1168849) as + # it reports an error by default. + if Yast::WFM.scr_chrooted? || (Yast::Stage.initial && !Yast::Systemd.Running) UnitInstallationProperties.new(self) else UnitProperties.new(self, property_text) diff --git a/library/systemd/test/yast2/systemctl_test.rb b/library/systemd/test/yast2/systemctl_test.rb index 743d1f1ef..e63e6983a 100755 --- a/library/systemd/test/yast2/systemctl_test.rb +++ b/library/systemd/test/yast2/systemctl_test.rb @@ -9,6 +9,7 @@ module Yast2 before do allow(Yast::Systemd).to receive(:Running).and_return(true) + allow(Yast::WFM).to receive(:scr_chrooted?).and_return(false) end describe ".execute" do diff --git a/library/systemd/test/yast2/systemd_unit_test.rb b/library/systemd/test/yast2/systemd_unit_test.rb index 793ee1d49..7a07e8f61 100755 --- a/library/systemd/test/yast2/systemd_unit_test.rb +++ b/library/systemd/test/yast2/systemd_unit_test.rb @@ -22,7 +22,8 @@ def trigger_reloading_properties(command) context "Installation system without full support of systemd" do before do allow(Yast::Stage).to receive(:initial).and_return(true) - allow(Yast::Systemd).to receive(:Running).and_return(false) + allow(Yast::WFM).to receive(:scr_chrooted?).and_return(true) + allow(Yast::Systemd).to receive(:Running).and_return(true) end describe "#properties" do From 3aadb7dc4f1e93be2ea0c68dd937b0a760fce7a6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Knut=20Alejandro=20Anderssen=20Gonz=C3=A1lez?= Date: Fri, 24 Apr 2020 16:22:30 +0100 Subject: [PATCH 3/6] Bump version & changelog --- package/yast2.changes | 7 +++++++ package/yast2.spec | 2 +- 2 files changed, 8 insertions(+), 1 deletion(-) diff --git a/package/yast2.changes b/package/yast2.changes index 288d1c61b..d014cca67 100644 --- a/package/yast2.changes +++ b/package/yast2.changes @@ -1,3 +1,10 @@ +------------------------------------------------------------------- +Fri Apr 24 14:53:03 UTC 2020 - Knut Anderssen + +- Avoid using systemctl calls when already started with the + installation and thus, running inside the chroot (bsc#1168849) +- 4.2.83 + ------------------------------------------------------------------- Mon Apr 13 12:36:58 UTC 2020 - Knut Anderssen diff --git a/package/yast2.spec b/package/yast2.spec index dabc2100e..cf1f577a4 100644 --- a/package/yast2.spec +++ b/package/yast2.spec @@ -17,7 +17,7 @@ Name: yast2 -Version: 4.2.82 +Version: 4.2.83 Release: 0 Summary: YaST2 Main Package License: GPL-2.0-only From 6c8f4e334301d703db0af00928c91a22d245fcc1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Knut=20Alejandro=20Anderssen=20Gonz=C3=A1lez?= Date: Fri, 24 Apr 2020 18:40:10 +0100 Subject: [PATCH 4/6] Revert "Adapt Rakefile and Dockerfile for SLE-15-SP2" This reverts commit 600930d2ec407bb31f3118371d5c0c23d18bf099. --- Dockerfile | 2 +- Rakefile | 2 -- 2 files changed, 1 insertion(+), 3 deletions(-) diff --git a/Dockerfile b/Dockerfile index 633ef065d..c54e79161 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,7 +1,7 @@ # Use this base image # - built: https://registry.opensuse.org # - source: https://github.com/yast/ci-ruby-container -FROM registry.opensuse.org/yast/sle-15/sp2/containers/yast-ruby +FROM registry.opensuse.org/yast/head/containers/yast-ruby COPY . /usr/src/app # English messages, UTF-8, "C" locale for numeric formatting tests ENV LC_ALL= LANG=en_US.UTF-8 LC_NUMERIC=C diff --git a/Rakefile b/Rakefile index 27038d0b0..09e49223b 100644 --- a/Rakefile +++ b/Rakefile @@ -1,7 +1,5 @@ require "yast/rake" -Yast::Tasks.submit_to :sle15sp2 - Yast::Tasks.configuration do |conf| # lets ignore license check for now conf.skip_license_check << /.*/ From e10956847a3bd9f71746f035888365c1f360dc44 Mon Sep 17 00:00:00 2001 From: Stefan Schubert Date: Thu, 7 May 2020 11:18:09 +0200 Subject: [PATCH 5/6] Cleanup issue handling (#1050) * cleanup issue handling --- .../lib/installation/autoinst_issues/issue.rb | 51 +++++ .../autoinst_issues/issues_presenter.rb | 154 +++++++++++++++ .../lib/installation/autoinst_issues/list.rb | 90 +++++++++ .../section_with_attributes.rb | 185 ++++++++++++++++++ .../test/autoinst_issues/issue_test.rb | 82 ++++++++ .../autoinst_issues/issues_presenter_test.rb | 169 ++++++++++++++++ .../general/test/autoinst_issues/list_test.rb | 115 +++++++++++ package/yast2.changes | 6 + package/yast2.spec | 2 +- 9 files changed, 853 insertions(+), 1 deletion(-) create mode 100644 library/general/src/lib/installation/autoinst_issues/issue.rb create mode 100644 library/general/src/lib/installation/autoinst_issues/issues_presenter.rb create mode 100644 library/general/src/lib/installation/autoinst_issues/list.rb create mode 100644 library/general/src/lib/installation/autoinst_profile/section_with_attributes.rb create mode 100755 library/general/test/autoinst_issues/issue_test.rb create mode 100755 library/general/test/autoinst_issues/issues_presenter_test.rb create mode 100755 library/general/test/autoinst_issues/list_test.rb diff --git a/library/general/src/lib/installation/autoinst_issues/issue.rb b/library/general/src/lib/installation/autoinst_issues/issue.rb new file mode 100644 index 000000000..ccd732bc1 --- /dev/null +++ b/library/general/src/lib/installation/autoinst_issues/issue.rb @@ -0,0 +1,51 @@ +module Installation + module AutoinstIssues + # Base class for autoinstallation problems. + # + # Installation::AutoinstIssues offers an API to register and report + # AutoYaST problems. + class Issue + include Yast::I18n + + # @return [#parent,#section_name] Section where it was detected (see {AutoinstProfile}) + attr_reader :section + + # Return problem severity + # + # * :fatal: abort the installation. + # * :warn: display a warning. + # + # @return [Symbol] Issue severity (:warn, :fatal) + # @raise NotImplementedError + def severity + raise NotImplementedError + end + + # Return the error message to be displayed + # + # @return [String] Error message + # @raise NotImplementedError + def message + raise NotImplementedError + end + + # Determine whether an error is fatal + # + # This is just a convenience method. + # + # @return [Boolean] + def fatal? + severity == :fatal + end + + # Determine whether an error is just a warning + # + # This is just a convenience method. + # + # @return [Boolean] + def warn? + severity == :warn + end + end + end +end diff --git a/library/general/src/lib/installation/autoinst_issues/issues_presenter.rb b/library/general/src/lib/installation/autoinst_issues/issues_presenter.rb new file mode 100644 index 000000000..066c3950f --- /dev/null +++ b/library/general/src/lib/installation/autoinst_issues/issues_presenter.rb @@ -0,0 +1,154 @@ +# 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. + +Yast.import "HTML" +Yast.import "RichText" + +module Installation + module AutoinstIssues + # This class converts a list of issues into a message to be shown to users + # + # The message will summarize the list of issues, separating them into non-fatal + # and fatal issues. + class IssuesPresenter + include Yast::I18n + + # @return [Installation::AutoinstIssues::List] List of issues + attr_reader :issues_list + + # Constructor + # + # @param issues_list [Installation::AutoinstIssues::List] List of issues + def initialize(issues_list) + textdomain "base" + @issues_list = issues_list + end + + # Return the text to be shown to the user regarding the list of issues + # + # @return [String] Plain text + def to_plain + Yast::RichText.Rich2Plain(to_html) + end + + # Return the text to be shown to the user regarding the list of issues + # + # @return [String] HTML formatted text + def to_html + fatal, non_fatal = issues_list.partition(&:fatal?) + + parts = [] + parts << error_text(fatal) unless fatal.empty? + parts << warning_text(non_fatal) unless non_fatal.empty? + parts << Yast::HTML.Newline + + parts << + if fatal.empty? + _("Do you want to continue?") + else + _("Please, correct these problems and try again.") + end + + parts.join + end + + # Return warning message with a list of issues + # + # @param issues [Array] Array containing issues + # @return [String] Message + def warning_text(issues) + Yast::HTML.Para( + _("Minor issues were detected:") + ) + issues_list_content(issues) + end + + # Return error message with a list of issues + # + # @param issues [Array] Array containing issues + # @return [String] Message + def error_text(issues) + Yast::HTML.Para( + _("Important issues were detected:") + ) + issues_list_content(issues) + end + + # Return an HTML representation for a list of issues + # + # The issues are grouped by the section of the profile where they were detected. + # General issues (with no section) are listed first. + # + # @return [String] Issues list content + # + # @see issues_by_section + def issues_list_content(issues) + all_issues = [] + issues_map = issues_by_section(issues) + + if issues_map[:nosection] + all_issues += issues_map[:nosection].map(&:message) + issues_map.delete(:nosection) + end + + issues_map.each do |section, items| + messages = Yast::HTML.List(items.map(&:message)) + all_issues << "#{location(section)}:#{messages}" + end + + Yast::HTML.List(all_issues) + end + + # Return issues grouped by section where they were found + # + # @return [Hash<(#parent,#section_name),Installation::AutoinstIssues::Issue>] + # Issues grouped by AutoYaST profile section + def issues_by_section(issues) + issues.each_with_object({}) do |issue, all| + section = issue.section || :nosection + all[section] ||= [] + all[section] << issue + end + end + + # Return a human string identifying in which section was detected + # + # For instance: "drive[0] > partitions[2] > raid_options" + # + # @param section [#parent,#section_name] Section where the problem was detected + # @return [String] + # + # @see Y2Storage::AutoinstProfile + def location(section) + return section.section_name if section.parent.nil? + + value = section.parent.send(section.section_name) + text = + if value.is_a?(Array) + index = value.index(section) + "#{section.section_name}[#{index + 1}]" + else + section.section_name + end + + prefix = location(section.parent) + prefix << " > " unless prefix.empty? + prefix + text + end + end + end +end diff --git a/library/general/src/lib/installation/autoinst_issues/list.rb b/library/general/src/lib/installation/autoinst_issues/list.rb new file mode 100644 index 000000000..55b70c72a --- /dev/null +++ b/library/general/src/lib/installation/autoinst_issues/list.rb @@ -0,0 +1,90 @@ +# 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 "forwardable" + +module Installation + module AutoinstIssues + # List of AutoYaST problems + # + # @example Registering some partition problems + # section = PartitionSection.new({}) + # list = List.new + # list.add(:missing_root) + # list.add(:invalid_value, section, :size, "auto") + # + # @example Adding a problem with additional arguments + # list = List.new + # list.add(:ay_invalid_value, "firewall", "FW_DEV_INT", "1", + # _("Is not supported anymore.")) + # list.empty? #=> false + # + # @example Iterating through the list of problems + # list.map(&:severity) #=> [:warn] + class List + include Enumerable + extend Forwardable + + def_delegators :@items, :each, :empty?, :<< + + # Constructor + def initialize + @items = [] + end + + # Add a problem to the list + # + # The type of the problem is identified as a symbol which name is the + # underscore version of the class which implements it. For instance, + # `MissingRoot` would be referred as `:missing_root`. + # + # If a given type of problem requires some additional arguments, they + # should be added when calling this method. See the next example. + # + # @example Adding a problem with additional arguments + # list = List.new + # list.add(:ay_invalid_value, "firewall", "FW_DEV_INT", "1", + # _("Is not supported anymore.")) + # list.empty? #=> false + # + # @param type [Symbol] Issue type + # @param extra_args [Array] Additional arguments for the given problem + # @return [Array] List of problems + def add(type, *extra_args) + class_name = type.to_s.split("_").map(&:capitalize).join + klass = Installation::AutoinstIssues.const_get(class_name) + self << klass.new(*extra_args) + end + + # Determine whether any of the problem on the list is fatal + # + # @return [Boolean] true if any of them is a fatal problem + def fatal? + any?(&:fatal?) + end + + # Returns an array containing registered problems + # + # @return [Array] List of problems + def to_a + @items + end + end + end +end diff --git a/library/general/src/lib/installation/autoinst_profile/section_with_attributes.rb b/library/general/src/lib/installation/autoinst_profile/section_with_attributes.rb new file mode 100644 index 000000000..a5db9caf7 --- /dev/null +++ b/library/general/src/lib/installation/autoinst_profile/section_with_attributes.rb @@ -0,0 +1,185 @@ +# 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" + +module Installation + module AutoinstProfile + # Abstract base class for some AutoYaST profile sections + class SectionWithAttributes + include Yast::Logger + + class << self + # Description of the attributes in the section. + # + # To be defined by each subclass. Each entry contains a hash with the + # mandatory key :name and an optional key :xml_name. + # + # @return [Array] + def attributes + [] + end + + # Creates an instance based on the profile representation used by the + # AutoYaST modules (nested arrays and hashes). + # + # This method provides no extra validation, type conversion or + # initialization to default values. Those responsibilities belong to the + # AutoYaST modules. The hash is expected to be valid and + # contain the relevant information. Attributes are set to nil for + # missing keys and for blank values. + # + # @param hash [Hash] content of the corresponding section of the profile. + # Each element of the hash corresponds to one of the attributes + # defined in the section. + # @param parent [#parent,#section_name] parent section + # @return [SectionWithAttributes] + def new_from_hashes(hash, parent = nil) + result = new(parent) + result.init_from_hashes(hash) + result + end + + protected + + # Macro used in the subclasses to define accessors for all the + # attributes defined by {.attributes} + def define_attr_accessors + attributes.each do |attrib| + attr_accessor attrib[:name] + end + end + end + + # This value only makes sense when {.new_from_hashes} is used. + # + # @return [#parent,#section_name] Parent section + attr_reader :parent + + # Constructor + # + # @param parent [SectionWithAttributes] Parent section + def initialize(parent = nil) + @parent = parent + end + + # Method used by {.new_from_hashes} to populate the attributes. + # + # By default, it simply assigns the non-empty hash values to the + # corresponding attributes, logging unknown keys. The subclass is expected + # to refine this behavior if needed. + # + # @param hash [Hash] see {.new_from_hashes} + def init_from_hashes(hash) + init_scalars_from_hash(hash) + end + + # Content of the section in the format used by the AutoYaST modules + # (nested arrays and hashes). + # + # @return [Hash] each element of the hash corresponds to one of the + # attributes defined in the section. Blank attributes are not + # included. + def to_hashes + attributes.each_with_object({}) do |attrib, result| + value = attrib_value(attrib) + next if attrib_skip?(value) + + key = attrib_key(attrib) + result[key] = value + end + end + + # Returns the section name + # + # In some cases, the section name does not match with the XML name + # and this method should be redefined. + # + # @example + # section = PartitioningSection.new + # section.section_name #=> "partitioning" + # + # @return [String] Section name + def section_name + klass_name = self.class.name.split("::").last + klass_name + .gsub(/([a-z])([A-Z])/, "\\1_\\2").downcase + .chomp("_section") + end + + protected + + def attributes + self.class.attributes + end + + # Whether an attribute must be skipped during import/export. + # + # @return [Boolean] true is the value is blank + def attrib_skip?(value) + value.nil? || value == [] || value == "" + end + + def attrib_key(attrib) + (attrib[:xml_name] || attrib[:name]).to_s + end + + def attrib_value(attrib) + value = send(attrib[:name]) + if value.is_a?(Array) + value.map { |v| attrib_scalar(v) } + else + attrib_scalar(value) + end + end + + def attrib_scalar(element) + element.respond_to?(:to_hashes) ? element.to_hashes : element + end + + def attrib_name(key) + attrib = attributes.detect { |a| a[:xml_name] == key.to_sym || a[:name] == key.to_sym } + return nil unless attrib + + attrib[:name] + end + + def init_scalars_from_hash(hash) + hash.each_pair do |key, value| + name = attrib_name(key) + + if name.nil? + log.warn "Attribute #{key} not recognized by #{self.class}. Check the XML schema." + next + end + + # This method only reads scalar values + next if value.is_a?(Array) || value.is_a?(Hash) + + if attrib_skip?(value) + log.debug "Ignored blank value (#{value}) for #{key}" + next + end + + send(:"#{name}=", value) + end + end + end + end +end diff --git a/library/general/test/autoinst_issues/issue_test.rb b/library/general/test/autoinst_issues/issue_test.rb new file mode 100755 index 000000000..dcb4b0269 --- /dev/null +++ b/library/general/test/autoinst_issues/issue_test.rb @@ -0,0 +1,82 @@ +#!/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 "installation/autoinst_issues/issue" + +describe Installation::AutoinstIssues::Issue do + subject(:issue) { described_class.new } + + describe "#message" do + it "raises a NotImplementedError exception" do + expect { issue.message }.to raise_error(NotImplementedError) + end + end + + describe "#severity" do + it "raises a NotImplementedError exception" do + expect { issue.severity }.to raise_error(NotImplementedError) + end + end + + describe "#warn?" do + before do + allow(issue).to receive(:severity).and_return(severity) + end + + context "when severity is :warn" do + let(:severity) { :warn } + + it "returns true" do + expect(issue).to be_warn + end + end + + context "when severity is not :warn" do + let(:severity) { :fatal } + + it "returns false" do + expect(issue).to_not be_warn + end + end + end + + describe "#fatal?" do + before do + allow(issue).to receive(:severity).and_return(severity) + end + + context "when severity is :fatal" do + let(:severity) { :fatal } + + it "returns true" do + expect(issue).to be_fatal + end + end + + context "when severity is not :fatal" do + let(:severity) { :warn } + + it "returns false" do + expect(issue).to_not be_fatal + end + end + end +end diff --git a/library/general/test/autoinst_issues/issues_presenter_test.rb b/library/general/test/autoinst_issues/issues_presenter_test.rb new file mode 100755 index 000000000..076eb6d0b --- /dev/null +++ b/library/general/test/autoinst_issues/issues_presenter_test.rb @@ -0,0 +1,169 @@ +#!/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 "installation/autoinst_profile/section_with_attributes" +require "installation/autoinst_issues/issue" +require "installation/autoinst_issues/list" +require "installation/autoinst_issues/issues_presenter" + +module Installation + module AutoinstIssues + class MissingSection < ::Installation::AutoinstIssues::Issue + def initialize(*args) + super + end + + def severity + :fatal + end + + def message + "No section was found." + end + end + + class InvalidValue < ::Installation::AutoinstIssues::Issue + attr_reader :attr + attr_reader :value + + def initialize(section, attr, value) + @section = section + @attr = attr + @value = value + end + + def severity + :warn + end + + def message + format( + "Invalid value '%{value}' for attribute '%{attr}'.", + value: value, + attr: attr + ) + end + end + end +end + +describe Installation::AutoinstIssues::IssuesPresenter do + subject(:presenter) { described_class.new(list) } + let(:section) do + ::Installation::AutoinstProfile::SectionWithAttributes.new_from_hashes({}) + end + + let(:list) { ::Installation::AutoinstIssues::List.new } + + describe "#to_html" do + context "when a fatal issue was found" do + before do + list.add(:missing_section) + end + + it "includes issues messages" do + issue = list.first + expect(presenter.to_html.to_s).to include "
  • #{issue.message}
  • " + end + + it "includes an introduction to fatal issues list" do + expect(presenter.to_html.to_s).to include "

    Important issues" + end + end + + context "when a non fatal issue was found" do + before do + list.add(:invalid_value, section, "foo", "bar") + end + + it "includes issues messages" do + issue = list.first + expect(presenter.to_html.to_s).to include "

  • #{issue.message}
  • " + end + + it "includes an introduction to non fatal issues list" do + expect(presenter.to_html.to_s).to include "

    Minor issues" + end + + it "includes the location information" do + expect(presenter.to_html).to include "

  • Invalid value" + end + end + + context "when a non located issue was found" do + before do + list.add(:missing_section) + end + + it "includes issues messages" do + issue = list.first + expect(presenter.to_html.to_s).to include "
  • #{issue.message}
  • " + end + end + end + + describe "#to_plain" do + context "when a fatal issue was found" do + before do + list.add(:missing_section) + end + + it "includes issues messages" do + issue = list.first + expect(presenter.to_plain.to_s).to include "* #{issue.message}" + end + + it "includes an introduction to fatal issues list" do + expect(presenter.to_plain.to_s).to include "Important issues" + end + end + + context "when a non fatal issue was found" do + before do + list.add(:invalid_value, section, "foo", "bar") + end + + it "includes issues messages" do + issue = list.first + expect(presenter.to_plain.to_s).to include "* #{issue.message}" + end + + it "includes an introduction to non fatal issues list" do + expect(presenter.to_plain.to_s).to include "Minor issues" + end + + it "includes the location information" do + expect(presenter.to_plain).to include "* Invalid value" + end + end + + context "when a non located issue was found" do + before do + list.add(:missing_section) + end + + it "includes issues messages" do + issue = list.first + expect(presenter.to_plain.to_s).to include "* #{issue.message}" + end + end + end +end diff --git a/library/general/test/autoinst_issues/list_test.rb b/library/general/test/autoinst_issues/list_test.rb new file mode 100755 index 000000000..2b608422d --- /dev/null +++ b/library/general/test/autoinst_issues/list_test.rb @@ -0,0 +1,115 @@ +#!/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 "installation/autoinst_issues/issue" +require "installation/autoinst_issues/list" + +module Installation + module AutoinstIssues + # Represents a problem that occurs when an exception is raised. + class Exception < ::Installation::AutoinstIssues::Issue + # @return [StandardError] + attr_reader :error + + # @param error [StandardError] + def initialize(error) + @error = error + end + + # Return problem severity + # + # @return [Symbol] :fatal + # @see Issue#severity + def severity + :fatal + end + + # Return the error message to be displayed + # + # @return [String] Error message + # @see Issue#message + def message + format( + "A problem ocurred: %s", + error.message + ) + end + end + end +end + +describe Installation::AutoinstIssues::List do + subject(:list) { described_class.new } + + let(:issue) { instance_double(Installation::AutoinstIssues::Exception) } + + describe "#add" do + it "adds a new issue to the list" do + list.add(:exception, StandardError.new) + expect(list.to_a).to all(be_an(Installation::AutoinstIssues::Exception)) + end + end + + describe "#to_a" do + context "when list is empty" do + it "returns an empty array" do + expect(list.to_a).to eq([]) + end + end + + context "when some issue was added" do + before do + 2.times { list.add(:exception, StandardError.new) } + end + + it "returns an array containing added issues" do + expect(list.to_a).to all(be_a(Installation::AutoinstIssues::Exception)) + expect(list.to_a.size).to eq(2) + end + end + end + + describe "#empty?" do + context "when list is empty" do + it "returns true" do + expect(list).to be_empty + end + end + + context "when some issue was added" do + before { list.add(:exception, StandardError.new) } + + it "returns false" do + expect(list).to_not be_empty + end + end + end + + describe "#fatal?" do + context "when contains some fatal error" do + before { list.add(:exception, StandardError.new) } + + it "returns true" do + expect(list).to be_fatal + end + end + end +end diff --git a/package/yast2.changes b/package/yast2.changes index d014cca67..01a06920a 100644 --- a/package/yast2.changes +++ b/package/yast2.changes @@ -1,3 +1,9 @@ +------------------------------------------------------------------- +Wed May 6 17:43:51 CEST 2020 - schubi@suse.de + +- AutoYaST: Cleanup/improve issue handling (bsc#1171335). +- 4.2.84 + ------------------------------------------------------------------- Fri Apr 24 14:53:03 UTC 2020 - Knut Anderssen diff --git a/package/yast2.spec b/package/yast2.spec index cf1f577a4..770304f79 100644 --- a/package/yast2.spec +++ b/package/yast2.spec @@ -17,7 +17,7 @@ Name: yast2 -Version: 4.2.83 +Version: 4.2.84 Release: 0 Summary: YaST2 Main Package License: GPL-2.0-only From b0b6a59b0c43945c86a7d7b4c51f2a75e1e6ef72 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Imobach=20Gonz=C3=A1lez=20Sosa?= Date: Thu, 7 May 2020 15:29:15 +0100 Subject: [PATCH 6/6] Document X-SuSE-DocTeamID key for .desktop files --- doc/desktop_file.md | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/doc/desktop_file.md b/doc/desktop_file.md index 1d4dd4730..07c516509 100644 --- a/doc/desktop_file.md +++ b/doc/desktop_file.md @@ -112,3 +112,8 @@ Auto prefix: * *X-SuSE-YaST-AutoLogResource* Specifies whether data in profile can be logged. Useful if data contains sensitive information. Possible values are `true` and `false`. By default `true`. + +## Miscellaneous Keys + +* *X-SuSE-DocTeamID* Specifies the identifier to be used when translating + the module's name. To be used by `Yast::Builtins.dpgettext`.