Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
28 changes: 26 additions & 2 deletions service/lib/agama/autoyast/scripts_reader.rb
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
# frozen_string_literal: true

# Copyright (c) [2024] SUSE LLC
# Copyright (c) [2024-2025] SUSE LLC
#
# All Rights Reserved.
#
Expand All @@ -20,6 +20,7 @@
# find current contact information at www.suse.com.

require "yast"
Yast.import "URL"

# :nodoc:
module Agama
Expand Down Expand Up @@ -50,6 +51,7 @@ def initialize(profile)
#
# @return [Hash] Agama "scripts" section
def read
@index = 0
scripts = {}
.merge(read_post_scripts)
.merge(read_init_scripts)
Expand Down Expand Up @@ -100,7 +102,7 @@ def read_init_scripts
# @param section [Hash] AutoYaST script section
def read_script(section)
script = {
"name" => section["file_name"]
"name" => filename_for(section)
}

if section["location"]
Expand All @@ -121,6 +123,28 @@ def read_post_script(section)
read_script(section)
.merge("chroot" => section.fetch("chrooted", false))
end

# Extracts the name of the script
#
# If the "filename" attribute is defined, it is used. Otherwise, it tries
# to infer the name from the "location" attribute. If the "location" is
# not defined, it uses a generic name plus the index of the script.
#
# @param section [Hash] AutoYaST script definition
# @return [String]
def filename_for(section)
return section["filename"] if section["filename"]

location = section["location"].to_s
if !location.empty?
url = Yast::URL.Parse(location)
path = File.basename(url["path"].to_s)
return path unless path.empty? || path == "/"
end

@index += 1
"script-#{@index}"
end
end
end
end
6 changes: 6 additions & 0 deletions service/package/rubygem-agama-yast.changes
Original file line number Diff line number Diff line change
@@ -1,3 +1,9 @@
-------------------------------------------------------------------
Mon Jan 27 17:38:53 UTC 2025 - Imobach Gonzalez Sosa <igonzalezsosa@suse.com>

- Fix handling of script names from AutoYaST profiles
(gh#agama-project/agama#1903).

-------------------------------------------------------------------
Fri Jan 24 09:33:27 UTC 2025 - Imobach Gonzalez Sosa <igonzalezsosa@suse.com>

Expand Down
53 changes: 43 additions & 10 deletions service/test/agama/autoyast/scripts_reader_test.rb
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
# frozen_string_literal: true

# Copyright (c) [2024] SUSE LLC
# Copyright (c) [2024-2025] SUSE LLC
#
# All Rights Reserved.
#
Expand Down Expand Up @@ -32,28 +32,61 @@

context "when the script definition includes the sources" do
let(:script) do
{ "file_name" => "script.sh",
"location" => "https://example.com/script.sh" }
{ "filename" => "script.sh",
"location" => "https://example.com/script.sh" }
end

it "sets the \"url\" to the \"location\"" do
scripts = subject.read["scripts"][section]
expect(scripts.first).to include("url" => "https://example.com/script.sh")
end

context "and the script filename is not specified" do
let(:script) do
{ "location" => "https://example.com/script.sh" }
end

it "uses the path as the filename" do
scripts = subject.read["scripts"][section]
expect(scripts.first).to include("name" => "script.sh")
end

context "but there is no path in the URL" do
let(:script) do
{ "location" => "https://example.com/" }
end

it "uses the script type as the filename" do
scripts = subject.read["scripts"][section]
expect(scripts.first).to include("name" => "script-1")
end
end
end
end

context "when the script definition specifies a location" do
let(:script) do
{
"file_name" => "script.sh",
"source" => "#!/bin/bash\necho 'Hello World!'"
"filename" => "script.sh",
"source" => "#!/bin/bash\necho 'Hello World!'"
}
end

it "sets the \"body\" to the \"sources\"" do
scripts = subject.read["scripts"][section]
expect(scripts.first).to include("body" => "#!/bin/bash\necho 'Hello World!'")
end

context "and the script filename is not specified" do
let(:script) do
{ "source" => "#!/bin/bash\necho 'Hello World!'" }
end

it "uses the script type as the filename" do
scripts = subject.read["scripts"][section]
expect(scripts.first).to include("name" => "script-1")
end
end
end
end

Expand All @@ -77,9 +110,9 @@
it_behaves_like "a script reader", "chroot-scripts", "post"

let(:chroot_script) do
{ "file_name" => "test.sh",
"chrooted" => true,
"source" => "#!/bin/bash\necho 'Hello World!'" }
{ "filename" => "test.sh",
"chrooted" => true,
"source" => "#!/bin/bash\necho 'Hello World!'" }
end

let(:profile) do
Expand All @@ -92,8 +125,8 @@

context "when the \"chrooted\" option is not set" do
let(:chroot_script) do
{ "file_name" => "test.sh",
"source" => "#!/bin/bash\necho 'Hello World!'" }
{ "filename" => "test.sh",
"source" => "#!/bin/bash\necho 'Hello World!'" }
end

it "sets the \"chroot\" option to false" do
Expand Down