Skip to content

Commit

Permalink
Merge pull request #150 from yast/wsl_systemd
Browse files Browse the repository at this point in the history
Wsl systemd
  • Loading branch information
jreidinger authored Dec 21, 2023
2 parents c02b8a8 + ba68b44 commit 7e3829b
Show file tree
Hide file tree
Showing 7 changed files with 191 additions and 23 deletions.
19 changes: 19 additions & 0 deletions doc/testing_wsl.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
## Testing WSL Changes

This document serve as reminder how is the optimal way to test changes done for WSL firstboot as working with
windows server can be linux unfriendly and we would like to test without any mocking to get the best results.

### Creating Testing APPX

The easiest way is to use OBS. Find the target release for WSL image like `SUSE:SLE-15-SP6:Update:WSL`
and branch there `kiwi-images-wsl` that is responsible for creation of appx. In your branch create package
yast2-firstboot ( as it is usually inherited from target and does not live in WSL subproject ) and copy there
modified sources with rake tarball. It is also mandatory to link or branch package `wsl-appx` as it ensures
that certificate used for appx matches with the one used in kiwi.
Another important think is to ensure that certificate for home repo is valid and not outdated. To check it use
`osc signkey --sslcert home:...` and if it is invalid use `osc signkey --sslcert --create home:...`.

### Installing Modified APPX

Just follow instructions at https://en.opensuse.org/WSL/Manual_Installation
Appx installer reports quite useless error when there is any issue, so use help at https://en.opensuse.org/WSL/Debugging_Hints
6 changes: 6 additions & 0 deletions package/yast2-firstboot.changes
Original file line number Diff line number Diff line change
@@ -1,3 +1,9 @@
-------------------------------------------------------------------
Thu Dec 14 20:38:43 UTC 2023 - Josef Reidinger <[email protected]>

- Allow selecting WSL systemd pattern (jsc#PED-5644, jsc#PED-5099)
- 4.6.3

-------------------------------------------------------------------
Fri Sep 01 19:57:03 UTC 2023 - Josef Reidinger <[email protected]>

Expand Down
2 changes: 1 addition & 1 deletion package/yast2-firstboot.spec
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@


Name: yast2-firstboot
Version: 4.6.2
Version: 4.6.3
Release: 0
Summary: YaST2 - Initial System Configuration
License: GPL-2.0-only
Expand Down
39 changes: 34 additions & 5 deletions src/lib/y2firstboot/clients/wsl_product_selection.rb
Original file line number Diff line number Diff line change
Expand Up @@ -38,12 +38,17 @@ def run
return :auto if products.none?

dialog = Dialogs::WSLProductSelection.new(products,
default_product: product,
wsl_gui_pattern: wsl_gui_pattern?)
default_product: product,
wsl_gui_pattern: wsl_gui_pattern?,
wsl_systemd_pattern: wsl_systemd_pattern?)

result = dialog.run

save(product: dialog.product, wsl_gui_pattern: dialog.wsl_gui_pattern) if result == :next
if result == :next
save(product: dialog.product,
wsl_gui_pattern: dialog.wsl_gui_pattern,
wsl_systemd_pattern: dialog.wsl_systemd_pattern)
end

result
end
Expand All @@ -52,14 +57,17 @@ def run

WSL_GUI_PATTERN = "wsl_gui".freeze
private_constant :WSL_GUI_PATTERN
WSL_SYSTEMD_PATTERN = "wsl_systemd".freeze
private_constant :WSL_SYSTEMD_PATTERN

# Saves changes
#
# @param product [Hash] Selected product
# @param wsl_gui_pattern [Boolean] Whether to install WSL GUI pattern
def save(product:, wsl_gui_pattern:)
def save(product:, wsl_gui_pattern:, wsl_systemd_pattern:)
self.product = product
self.wsl_gui_pattern = wsl_gui_pattern
self.wsl_systemd_pattern = wsl_systemd_pattern
update_registration
end

Expand Down Expand Up @@ -101,6 +109,26 @@ def wsl_gui_pattern=(value)
end
end

# Whether the WSL systemd pattern should be installed
#
# @see ẂSLConfig
#
# @return [Boolean]
def wsl_systemd_pattern?
WSLConfig.instance.patterns.include?(WSL_SYSTEMD_PATTERN)
end

# Sets whether to install the WSL systemd pattern
#
# @param value [Boolean]
def wsl_systemd_pattern=(value)
if value
WSLConfig.instance.patterns.push(WSL_SYSTEMD_PATTERN).uniq!
else
WSLConfig.instance.patterns.delete(WSL_SYSTEMD_PATTERN)
end
end

# Updates values stored in registration
#
# Those values indicates to registration what product was selected and whether the product
Expand All @@ -109,7 +137,8 @@ def wsl_gui_pattern=(value)
# @see Registration::Storage::InstallationOptions
def update_registration
yaml_product = WSLConfig.instance.product
force_registration = WSLConfig.instance.product_switched? || wsl_gui_pattern?
force_registration = WSLConfig.instance.product_switched? ||
wsl_gui_pattern? || wsl_systemd_pattern?

Registration::Storage::InstallationOptions.instance.yaml_product = yaml_product
Registration::Storage::InstallationOptions.instance.force_registration = force_registration
Expand Down
43 changes: 35 additions & 8 deletions src/lib/y2firstboot/dialogs/wsl_product_selection.rb
Original file line number Diff line number Diff line change
Expand Up @@ -39,18 +39,26 @@ class WSLProductSelection < ::UI::InstallationDialog
# @return [Boolean]
attr_reader :wsl_gui_pattern

# Whether the WSL systemd pattern was selected
#
# @return [Boolean]
attr_reader :wsl_systemd_pattern

# Constructor
#
# @param products [Array<Hash>] All possible products
# @param default_product [Hash] Product selected by default
# @param wsl_gui_pattern [Boolean] Whether WSL GUI pattern is selected by default
def initialize(products, default_product: nil, wsl_gui_pattern: false)
# @param wsl_systemd_pattern [Boolean] Whether WSL systemd pattern is selected by default
def initialize(products, default_product: nil, wsl_gui_pattern: false,
wsl_systemd_pattern: false)
textdomain "firstboot"

super()
@products = products
@product = default_product || products.first
@wsl_gui_pattern = wsl_gui_pattern
@wsl_systemd_pattern = wsl_systemd_pattern
end

def next_handler
Expand All @@ -65,6 +73,8 @@ def dialog_title
_("Product Selection")
end

# disable rubocop metrics as yast ui is constructed with methods
# rubocop:disable Metrics/AbcSize
def dialog_content
items = products.map { |p| item_for(p) }

Expand All @@ -81,24 +91,40 @@ def dialog_content
),
VSpacing(2),
# TRANSLATORS:
Label(_("The WSL GUI pattern provides some needed packages for\n" \
"a better experience with graphical applications in WSL.")),
Left(Label(_("The WSL GUI pattern provides some needed packages for\n" \
"a better experience with graphical applications in WSL."))),
VSpacing(1),
# TRANSLATORS: check box label
Left(CheckBox(Id(:wsl_gui_pattern),
_("Install WSL GUI pattern (requires registration)"),
wsl_gui_pattern))
wsl_gui_pattern)),
VSpacing(2),
# TRANSLATORS:
Left(Label(_("The WSL systemd pattern provides wsl.conf adjustment\n" \
"and init symlink for systemd enablement in WSL."))),
VSpacing(1),
# TRANSLATORS: check box label
Left(CheckBox(Id(:wsl_systemd_pattern),
_("Install WSL systemd pattern (requires registration)"),
wsl_systemd_pattern))
)
)
end
# rubocop:enable Metrics/AbcSize

def help_text
# TRANSLATORS: help text (1/2)
# TRANSLATORS: help text (1/3)
_("<p>Select the product to use with Windows Subsystem for Linux (WSL). " \
"Some products might require registration.</p>") +
# TRANSLATORS: help text (2/2)
_("<p>To use graphical programs in WSL you need to install the WSL GUI pattern. " \
"In that case the system needs to be registered as well.</p>")
# TRANSLATORS: help text (2/3)
_("<p>For smoother experience with graphical programs in WSL " \
"the WSL GUI pattern provides recommended config, tools and libraries. " \
"In that case the system needs to be registered as well.</p>") +
# TRANSLATORS: help text (3/3)
_("<p>For enablement of systemd in WSL the WSL systemd pattern provides wsl.conf " \
"and /sbin/init adjustments. " \
"In that case the system needs to be registered as well. " \
"Relaunch is required to use systemd.</p>")
end

private
Expand Down Expand Up @@ -146,6 +172,7 @@ def product_label(product)

def save
@wsl_gui_pattern = Yast::UI.QueryWidget(Id(:wsl_gui_pattern), :Value)
@wsl_systemd_pattern = Yast::UI.QueryWidget(Id(:wsl_systemd_pattern), :Value)

selected_id = Yast::UI.QueryWidget(Id(:product_selector), :Value)
@product = products.find { |p| item_id(p) == selected_id }
Expand Down
64 changes: 56 additions & 8 deletions test/y2firstboot/clients/wsl_product_selection_test.rb
Original file line number Diff line number Diff line change
Expand Up @@ -104,14 +104,16 @@ class InstallationOptions

let(:dialog) do
instance_double(Y2Firstboot::Dialogs::WSLProductSelection,
run: dialog_result,
product: selected_product,
wsl_gui_pattern: wsl_gui_pattern)
run: dialog_result,
product: selected_product,
wsl_gui_pattern: wsl_gui_pattern,
wsl_systemd_pattern: wsl_systemd_pattern)
end

let(:dialog_result) { :abort }
let(:selected_product) { nil }
let(:wsl_gui_pattern) { nil }
let(:wsl_systemd_pattern) { nil }

let(:product_switched) { false }

Expand Down Expand Up @@ -159,6 +161,34 @@ class InstallationOptions
end
end

context "if the WSL systemd pattern was selected" do
let(:wsl_systemd_pattern) { true }

before do
Y2Firstboot::WSLConfig.instance.patterns = []
end

it "stores the WSL systemd pattern in the WSL config" do
subject.run

expect(Y2Firstboot::WSLConfig.instance.patterns).to include("wsl_systemd")
end
end

context "if the WSL systemd pattern was not selected" do
let(:wsl_systemd_pattern) { false }

before do
Y2Firstboot::WSLConfig.instance.patterns = ["wsl_systemd"]
end

it "does not store the WSL systemd pattern in the WSL config" do
subject.run

expect(Y2Firstboot::WSLConfig.instance.patterns).to_not include("wsl_systemd")
end
end

it "updates the product in registration storage" do
Registration::Storage::InstallationOptions.instance.yaml_product = nil

Expand All @@ -170,6 +200,7 @@ class InstallationOptions
context "if the product was switched" do
let(:product_switched) { true }
let(:wsl_gui_pattern) { false }
let(:wsl_systemd_pattern) { false }

it "updates registration storage to force registration" do
Registration::Storage::InstallationOptions.instance.force_registration = false
Expand Down Expand Up @@ -200,13 +231,30 @@ class InstallationOptions
context "and the WSL GUI pattern was not selected" do
let(:wsl_gui_pattern) { false }

it "updates registration storage to not force registration" do
Registration::Storage::InstallationOptions.instance.force_registration = true
context "and the WSL systemd pattern was selected" do
let(:wsl_systemd_pattern) { true }

subject.run
it "updates registration storage to force registration" do
Registration::Storage::InstallationOptions.instance.force_registration = false

expect(Registration::Storage::InstallationOptions.instance.force_registration)
.to eq(false)
subject.run

expect(Registration::Storage::InstallationOptions.instance.force_registration)
.to eq(true)
end
end

context "and the WSL systemd pattern was not selected" do
let(:wsl_systemd_pattern) { false }

it "updates registration storage to not force registration" do
Registration::Storage::InstallationOptions.instance.force_registration = true

subject.run

expect(Registration::Storage::InstallationOptions.instance.force_registration)
.to eq(false)
end
end
end
end
Expand Down
41 changes: 40 additions & 1 deletion test/y2firstboot/dialogs/wsl_product_selection_test.rb
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,9 @@ def find_widget(regexp, content)

subject do
described_class.new(products,
default_product: default_product, wsl_gui_pattern: wsl_gui_pattern)
default_product: default_product,
wsl_gui_pattern: wsl_gui_pattern,
wsl_systemd_pattern: wsl_systemd_pattern)
end

let(:products) { [sles, sled] }
Expand All @@ -52,6 +54,7 @@ def find_widget(regexp, content)

let(:default_product) { sled }
let(:wsl_gui_pattern) { false }
let(:wsl_systemd_pattern) { false }

let(:installed_product) { double(Y2Packager::Resolvable, name: "SLES", version_version: "15.4") }
before do
Expand Down Expand Up @@ -80,6 +83,12 @@ def find_widget(regexp, content)
expect(widget).to_not be_nil
end

it "shows a check box for selecting the WSL systemd pattern" do
widget = find_widget(:wsl_systemd_pattern, subject.send(:dialog_content))

expect(widget).to_not be_nil
end

it "automatically selects the default product" do
widget = find_widget(/SLED/, subject.send(:dialog_content))

Expand All @@ -105,12 +114,34 @@ def find_widget(regexp, content)
expect(widget.params.last).to eq(false)
end
end

context "when WSL systemd pattern is indicated as selected" do
let(:wsl_systemd_pattern) { true }

it "selects WSL systemd pattern checkbox by default" do
widget = find_widget(:wsl_systemd_pattern, subject.send(:dialog_content))

expect(widget.params.last).to eq(true)
end
end

context "when WSL systemd pattern is not indicated as selected" do
let(:wsl_systemd_pattern) { false }

it "does not select WSL systemd pattern checkbox by default" do
widget = find_widget(:wsl_systemd_pattern, subject.send(:dialog_content))

expect(widget.params.last).to eq(false)
end
end
end

describe "#next_handler" do
before do
allow(Yast::UI).to receive(:QueryWidget).and_call_original
allow(Yast::UI).to receive(:QueryWidget).with(Id(:wsl_gui_pattern), :Value).and_return(true)
allow(Yast::UI).to receive(:QueryWidget).with(Id(:wsl_systemd_pattern), :Value)
.and_return(true)
allow(Yast::UI).to receive(:QueryWidget).with(Id(:product_selector), :Value)
.and_return("SLES:15.4")
end
Expand All @@ -123,6 +154,14 @@ def find_widget(regexp, content)
expect(subject.wsl_gui_pattern).to eq(true)
end

it "saves whether the WSL GUI pattern checkbox was selected" do
expect(subject.wsl_systemd_pattern).to eq(false)

subject.next_handler

expect(subject.wsl_systemd_pattern).to eq(true)
end

it "saves the selected product" do
expect(subject.product).to eq(sled)

Expand Down

0 comments on commit 7e3829b

Please sign in to comment.