• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

yast / yast-yast2 / 13440235285

20 Feb 2025 04:40PM UTC coverage: 41.869% (-0.02%) from 41.889%
13440235285

push

github

web-flow
Merge pull request #1316 from yast/agama_kernel_conf

Respect Agama kernel parameters

2 of 4 new or added lines in 1 file covered. (50.0%)

265 existing lines in 40 files now uncovered.

12605 of 30106 relevant lines covered (41.87%)

10.76 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

77.34
/library/control/src/modules/ProductFeatures.rb
1
# ***************************************************************************
2
#
3
# Copyright (c) 2002 - 2014 Novell, Inc.
4
# All Rights Reserved.
5
#
6
# This program is free software; you can redistribute it and/or
7
# modify it under the terms of version 2 of the GNU General Public License as
8
# published by the Free Software Foundation.
9
#
10
# This program is distributed in the hope that it will be useful,
11
# but WITHOUT ANY WARRANTY; without even the implied warranty of
12
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.   See the
13
# GNU General Public License for more details.
14
#
15
# You should have received a copy of the GNU General Public License
16
# along with this program; if not, contact Novell, Inc.
17
#
18
# To contact Novell about this file by physical or electronic mail,
19
# you may find current contact information at www.novell.com
20
#
21
# ***************************************************************************
22
# File:  modules/ProductFetures.ycp
23
# Package:  installation
24
# Summary:  Product features
25
# Authors:  Anas Nashif <nashif@suse.de>
26
#              Jiri Srain <jsrain@suse.cz>
27
#
28
# $Id$
29
require "yast"
1✔
30

31
module Yast
1✔
32
  class ProductFeaturesClass < Module
1✔
33
    def main
1✔
34
      textdomain "base"
1✔
35

36
      Yast.import "Misc"
1✔
37
      Yast.import "Mode"
1✔
38
      Yast.import "Stage"
1✔
39

40
      # Map of all features
41
      # See defaults map below for sample contents
42
      @features = nil
1✔
43

44
      # See SetOverlay and ClearOverlay
45
      @backup_features = nil
1✔
46

47
      # Default values for features
48
      # two-level map, section_name -> [ feature -> value ]
49
      @defaults = {
50
        "globals"                  => {
1✔
51
          "additional_kernel_parameters"    => "",
52
          # FATE #304865
53
          "base_product_license_directory"  => "/usr/share/licenses/product/base/",
54
          # jsc#SLE-22667
55
          "boot_timeout"                    => 8,
56
          "default_target"                  => "",
57
          "disable_os_prober"               => false,
58
          "enable_autologin"                => true,
59
          "enable_clone"                    => false,
60
          "enable_firewall"                 => true,
61
          "enable_local_users"              => true,
62
          "enable_sshd"                     => false,
63
          "fam_local_only"                  => "never",
64
          "firewall_enable_ssh"             => false,
65
          "flags"                           => [],
66
          "full_system_download_url"        => "",
67
          "full_system_media_name"          => "",
68
          "incomplete_translation_treshold" => "95",
69
          "keyboard"                        => "",
70
          "language"                        => "",
71
          "propose_hibernation"             => true,
72
          "relnotesurl"                     => "",
73
          "run_you"                         => true,
74
          "save_y2logs"                     => true,
75
          "skip_language_dialog"            => false,
76
          "timezone"                        => "",
77
          "ui_mode"                         => "expert",
78
          "vendor_url"                      => ""
79
        },
80
        "partitioning"             => {
81
          "use_flexible_partitioning"    => false,
82
          "flexible_partitioning"        => {},
83
          "vm_keep_unpartitioned_region" => false
84
        },
85
        "software"                 => {
86
          "software_proposal"                    => "selection",
87
          "selection_type"                       => :auto,
88
          "delete_old_packages"                  => true,
89
          "only_update_installed"                => false,
90
          "packages_transmogrify"                => "",
91
          "base_selection"                       => "",
92
          "packages"                             => [],
93
          "kernel_packages"                      => [],
94
          "addon_selections"                     => [],
95
          "inform_about_suboptimal_distribution" => false
96
        },
97
        "network"                  => { "force_static_ip" => false },
98
        # Defaults are defined in the ConfigurationManagement::Configurations classes:
99
        # https://github.com/yast/yast-configuration-management/blob/27c93ba9d592271a299706aca323d9d371d44058/src/lib/configuration_management/configurations/base.rb#L13
100
        "configuration_management" => {}
101
      }
102
    end
103

104
    # Initialize default values of features
105
    # @param [Boolean] force boolean drop all settings which were set before
106
    def InitFeatures(force)
1✔
107
      return if @features && !force
59✔
108

109
      @features = deep_copy(@defaults)
1✔
110

111
      nil
1✔
112
    end
113

114
    # Set a feature section
115
    # Default values will be used where value not defined
116
    # @note This is a stable API function
117
    # @param section name string the name of the section
118
    # @param [Hash{String => Object}] section_map a map containing data of the section
119
    def SetSection(section_name, section_map)
1✔
120
      section_map = deep_copy(section_map)
5✔
121
      InitFeatures(false)
5✔
122
      Builtins.y2debug("Setting section: %1", section_name)
5✔
123
      section_map = Convert.convert(
5✔
124
        Builtins.union(Ops.get(@defaults, section_name, {}), section_map),
125
        from: "map",
126
        to:   "map <string, any>"
127
      )
128
      Ops.set(@features, section_name, section_map)
5✔
129

130
      nil
5✔
131
    end
132

133
    # Get a complete section for evaluation
134
    # @note This is a stable API function
135
    # @param [String] section_name string name of the section
136
    # @return a map key->value, options in the section
137
    def GetSection(section_name)
1✔
138
      InitFeatures(false)
×
139
      Ops.get(@features, section_name, {})
×
140
    end
141

142
    # Save product features
143
    # @note This is a stable API function
144
    def Save
1✔
145
      InitFeatures(false)
×
146
      if Mode.update # in case of update old file has different format
×
147
        SCR.Execute(
×
148
          path(".target.bash"),
149
          "test -f /etc/YaST2/ProductFeatures && /bin/rm /etc/YaST2/ProductFeatures"
150
        )
151
      end
152
      Builtins.foreach(@features) do |group, options|
×
153
        Builtins.foreach(options) do |key, value|
×
154
          if Ops.is_map?(value) || Ops.is_list?(value) || Ops.is_symbol?(value)
×
155
            Builtins.y2debug("Skipping option %1", key)
×
156
          else
157
            strval = GetStringFeature(group, key)
×
158
            SCR.Write(
×
159
              Ops.add(Ops.add(path(".product.features.value"), group), key),
160
              strval
161
            )
162
          end
163
        end
164
      end
165
      SCR.Write(path(".product.features"), nil) # flush
×
166

UNCOV
167
      nil
×
168
    end
169

170
    # Restore product features in running system
171
    # @note This is a stable API function
172
    def Restore
1✔
173
      InitFeatures(false)
24✔
174

175
      groups = SCR.Dir(path(".product.features.section"))
24✔
176
      Builtins.foreach(groups) do |group|
24✔
177
        Ops.set(@features, group, Ops.get(@features, group, {}))
4✔
178
        values = SCR.Dir(Ops.add(path(".product.features.value"), group))
4✔
179
        Builtins.foreach(values) do |v|
4✔
180
          Ops.set(
55✔
181
            @features,
182
            [group, v],
183
            SCR.Read(
184
              Ops.add(Ops.add(path(".product.features.value"), group), v)
185
            )
186
          )
187
        end
188
      end
189

190
      nil
24✔
191
    end
192

193
    # Initialize the features structure if needed
194
    #
195
    # @note The values are normally read from a control file or set to default values. But, in normal
196
    # mode, the values are taken from /etc/YaST2/ProductFeatures. Also note that for firstboot mode, the
197
    # values are taken from the firstboot.xml control file.
198
    #
199
    # @note This is a stable API function
200
    def InitIfNeeded
1✔
201
      if Stage.normal
56✔
202
        Restore()
25✔
203
      else
204
        InitFeatures(false)
31✔
205
      end
206

207
      nil
56✔
208
    end
209

210
    # Get value of a feature
211
    # @note This is a stable API function
212
    # @param [String] section string section of the feature
213
    # @param features string feature name
214
    # @return [Object] the feature value, "" if not found
215
    def GetFeature(section, feature)
1✔
216
      InitIfNeeded()
45✔
217
      ret = Ops.get(@features, [section, feature])
45✔
218
      ret = "" if ret.nil?
45✔
219
      deep_copy(ret)
45✔
220
    end
221

222
    # Get value of a feature
223
    # @note This is a stable API function
224
    # @param [String] section string section of the feature
225
    # @param features string feature name
226
    # @return [String] the feature value, "" if not found
227
    def GetStringFeature(section, feature)
1✔
228
      value = GetFeature(section, feature)
×
229

230
      case value
×
231
      when ::String
232
        value
×
233
      when true, false
234
        value ? "yes" : "no"
×
235
      else
236
        Builtins.sformat("%1", value)
×
237
      end
238
    end
239

240
    # Get value of a feature
241
    # If the feature is missing `false` is returned. So it is not possible to
242
    # distingush between a missing value and a false value.
243
    # @note This is a stable API function
244
    # @param [String] section string section of the feature
245
    # @param features string feature name
246
    # @return [Boolean] the feature value
247
    def GetBooleanFeature(section, feature)
1✔
248
      value = GetFeature(section, feature)
6✔
249
      return value if Ops.is_boolean?(value)
6✔
250

251
      Ops.is_string?(value) && Builtins.tolower(Convert.to_string(value)) == "yes"
4✔
252
    end
253

254
    # Get value of a boolean feature with a fallback value.
255
    #
256
    # @note This is a stable API function
257
    # @param [String] section string section of the feature
258
    # @param [String] feature feature name
259
    # @param [Boolean] fallback
260
    #
261
    # @return [Boolean] the feature value or fallback if not specified
262
    def GetBooleanFeatureWithFallback(section, feature, fallback)
1✔
263
      value = GetFeature(section, feature)
8✔
264
      return fallback if value.nil?
8✔
265
      return value if Ops.is_boolean?(value)
8✔
266

267
      if value.respond_to?(:downcase)
6✔
268
        return true  if ["yes", "true"].include?(value.downcase)
6✔
269
        return false if ["no", "false"].include?(value.downcase)
5✔
270
      end
271

272
      fallback
4✔
273
    end
274

275
    # Get value of a feature
276
    # @note This is a stable API function
277
    # @param [String] section string section of the feature
278
    # @param features string feature name
279
    # @return [Fixnum] the feature value, nil if not found
280
    def GetIntegerFeature(section, feature)
1✔
281
      value = GetFeature(section, feature)
×
282
      if Ops.is_integer?(value)
×
283
        value
×
284
      elsif Ops.is_string?(value)
×
285
        Builtins.tointeger(Convert.to_string(value))
×
286
      end
287
    end
288

289
    # Set value of a feature
290
    # @note This is a stable API function
291
    # @param [String] section string section of the feature
292
    # @param features string feature name
293
    # @param [Object] value any the feature value
294
    def SetFeature(section, feature, value)
1✔
295
      value = deep_copy(value)
9✔
296
      InitIfNeeded()
9✔
297
      Ops.set(@features, section, {}) if !Builtins.haskey(@features, section)
9✔
298
      Ops.set(@features, [section, feature], value)
9✔
299

300
      nil
9✔
301
    end
302

303
    # Set value of a feature
304
    # @note This is a stable API function
305
    # @param [String] section string section of the feature
306
    # @param features string feature name
307
    # @param [String] value string the feature value
308
    def SetStringFeature(section, feature, value)
1✔
309
      SetFeature(section, feature, value)
×
310

UNCOV
311
      nil
×
312
    end
313

314
    # Set value of a feature
315
    # @note This is a stable API function
316
    # @param [String] section string section of the feature
317
    # @param features string feature name
318
    # @param [Boolean] value boolean the feature value
319
    def SetBooleanFeature(section, feature, value)
1✔
320
      SetFeature(section, feature, value)
×
321

UNCOV
322
      nil
×
323
    end
324

325
    # Set value of a feature
326
    # @note This is a stable API function
327
    # @param [String] section string section of the feature
328
    # @param features string feature name
329
    # @param [Fixnum] value integer the feature value
330
    def SetIntegerFeature(section, feature, value)
1✔
331
      SetFeature(section, feature, value)
×
332

UNCOV
333
      nil
×
334
    end
335

336
    # Exports the current set of ProductFeatures
337
    #
338
    # @return [Hash <String, Hash{String => Object>}] features
339
    def Export
1✔
340
      deep_copy(@features)
4✔
341
    end
342

343
    # Imports product features
344
    #
345
    # @param map <string, map <string, any> > features
346
    def Import(import_settings)
1✔
347
      @features = deep_copy(import_settings)
31✔
348

349
      nil
31✔
350
    end
351

352
    # Overlay, or override, some features.
353
    # The intended use is to use SetOverlay to apply some features
354
    # specified by a system role (FATE#317481).
355
    # Clear would be called only when coming Back
356
    # to the role selection dialog (and then SetOverlay with a different one)
357
    # @param features [Hash{String => Hash{String => Object}}] in the same
358
    #   format as `@features` or `@defaults`
359
    # @return void
360
    # @raise RuntimeError if called twice without {ClearOverlay}
361
    def SetOverlay(features)
1✔
362
      raise "SetOverlay called when old overlay was not cleared" if @backup_features
5✔
363

364
      @backup_features = deep_copy(@features)
4✔
365

366
      features.each do |section_name, section|
4✔
367
        section.each do |k, v|
8✔
368
          SetFeature(section_name, k, v)
8✔
369
        end
370
      end
371
    end
372

373
    # Remove a `@features` overlay; does nothing if SetOverlay was never called.
374
    # @see SetOverlay
375
    # @return void
376
    def ClearOverlay
1✔
377
      return if @backup_features.nil?
9✔
378

379
      @features = deep_copy(@backup_features)
4✔
380
      # when overlay is cleared, remove backup as it can become invalid over-time
381
      # when new extensions is applied
382
      @backup_features = nil
4✔
383
    end
384

385
    publish function: :GetStringFeature, type: "string (string, string)"
1✔
386
    publish function: :SetSection, type: "void (string, map <string, any>)"
1✔
387
    publish function: :GetSection, type: "map <string, any> (string)"
1✔
388
    publish function: :Save, type: "void ()"
1✔
389
    publish function: :Restore, type: "void ()"
1✔
390
    publish function: :InitIfNeeded, type: "void ()"
1✔
391
    publish function: :GetFeature, type: "any (string, string)"
1✔
392
    publish function: :GetBooleanFeature, type: "boolean (string, string)"
1✔
393
    publish function: :GetBooleanFeatureWithFallback, type: "boolean (string, string, boolean)"
1✔
394
    publish function: :GetIntegerFeature, type: "integer (string, string)"
1✔
395
    publish function: :SetFeature, type: "void (string, string, any)"
1✔
396
    publish function: :SetStringFeature, type: "void (string, string, string)"
1✔
397
    publish function: :SetBooleanFeature, type: "void (string, string, boolean)"
1✔
398
    publish function: :SetIntegerFeature, type: "void (string, string, integer)"
1✔
399
    publish function: :Export, type: "map <string, map <string, any>> ()"
1✔
400
    publish function: :Import, type: "void (map <string, map <string, any>>)"
1✔
401
  end
402

403
  ProductFeatures = ProductFeaturesClass.new
1✔
404
  ProductFeatures.main
1✔
405
end
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc