@@ -48,13 +48,16 @@ Example:
4848
4949- private-key -- provide the client's private key in a file separate from the certificate.
5050
51- - parent-suite -- release code name which this suite is based on. Useful for downstreams which do
52- not use debian codenames for their suite names (e.g. "stable").
51+ - debootstrap-suite -- name of the suite to use for debootstrap itself. This usually
52+ selects the builtin debootstrap script and is typically the direct parent of a
53+ downstream (e.g. "buster" for an old Apertis release, "jammy" for Ubuntu derivatives).
5354
54- - script -- the full path of the script to use to build the target rootfs. (e.g. `/usr/share/debootstrap/scripts/kali`)
55- If unspecified, the property will be automatically determined in the following order,
56- with the path "/usr/share/debootstrap/scripts/" prepended:
57- `suite` property, `parent-suite` property then `unstable`.
55+ - debootstrap-script -- path (inside the recipe origin) to a custom debootstrap
56+ script to use instead of the builtin ones.
57+
58+ If neither debootstrap-suite nor debootstrap-script is set, debos will use the
59+ builtin script for the `suite` if one exists, otherwise it falls back to the
60+ "unstable" debootstrap script (preserving the historic behaviour).
5861*/
5962package actions
6063
@@ -73,19 +76,19 @@ import (
7376)
7477
7578type DebootstrapAction struct {
76- debos.BaseAction `yaml:",inline"`
77- ParentSuite string `yaml:"parent -suite"`
78- Suite string
79- Mirror string
80- Variant string
81- KeyringPackage string `yaml:"keyring-package"`
82- KeyringFile string `yaml:"keyring-file"`
83- Certificate string
84- PrivateKey string `yaml:"private-key"`
85- Components []string
86- MergedUsr bool `yaml:"merged-usr"`
87- CheckGpg bool `yaml:"check-gpg"`
88- Script string
79+ debos.BaseAction `yaml:",inline"`
80+ DebootstrapSuite string `yaml:"debootstrap -suite"`
81+ Suite string
82+ Mirror string
83+ Variant string
84+ KeyringPackage string `yaml:"keyring-package"`
85+ KeyringFile string `yaml:"keyring-file"`
86+ Certificate string
87+ PrivateKey string `yaml:"private-key"`
88+ Components []string
89+ MergedUsr bool `yaml:"merged-usr"`
90+ CheckGpg bool `yaml:"check-gpg"`
91+ DebootstrapScript string `yaml:"debootstrap-script"`
8992}
9093
9194func NewDebootstrapAction () * DebootstrapAction {
@@ -119,6 +122,11 @@ func (d *DebootstrapAction) listOptionFiles(context *debos.Context) []string {
119122 files = append (files , d .KeyringFile )
120123 }
121124
125+ if d .DebootstrapScript != "" {
126+ d .DebootstrapScript = debos .CleanPathAt (d .DebootstrapScript , context .RecipeDir )
127+ files = append (files , d .DebootstrapScript )
128+ }
129+
122130 return files
123131}
124132
@@ -127,18 +135,35 @@ func (d *DebootstrapAction) Verify(context *debos.Context) error {
127135 return fmt .Errorf ("suite property not specified" )
128136 }
129137
130- if len (d .ParentSuite ) == 0 {
131- d .ParentSuite = d .Suite
138+ // You can't sensibly specify both.
139+ if d .DebootstrapSuite != "" && d .DebootstrapScript != "" {
140+ return fmt .Errorf ("only one of debootstrap-suite or debootstrap-script may be set" )
132141 }
133142
134143 files := d .listOptionFiles (context )
135144
136- // Check if all needed files exists
145+ // Check if all needed files exist
137146 for _ , f := range files {
138147 if _ , err := os .Stat (f ); os .IsNotExist (err ) {
139148 return err
140149 }
141150 }
151+
152+ // If debootstrap-suite is set, require that a script for it exists.
153+ if d .DebootstrapSuite != "" {
154+ // If the suite already has a builtin script, using debootstrap-suite is
155+ // confusing - error out
156+ suiteScript := getDebootstrapScriptPath (d .Suite )
157+ if _ , err := os .Stat (suiteScript ); err == nil {
158+ return fmt .Errorf ("suite %q already has a builtin debootstrap script; debootstrap-suite should not be set" , d .Suite )
159+ }
160+
161+ parentScript := getDebootstrapScriptPath (d .DebootstrapSuite )
162+ if _ , err := os .Stat (parentScript ); err != nil {
163+ return fmt .Errorf ("cannot find debootstrap script for debootstrap-suite %q" , d .DebootstrapSuite )
164+ }
165+ }
166+
142167 return nil
143168}
144169
@@ -178,21 +203,23 @@ func (d *DebootstrapAction) RunSecondStage(context debos.Context) error {
178203 return err
179204}
180205
181- // Check if suite is something before usr-is-merged was introduced
206+ // shouldExcludeUsrIsMerged returns true for Debian suites where usr-is-merged
207+ // is not available and the old debos workaround is still needed.
182208func shouldExcludeUsrIsMerged (suite string ) bool {
183209 switch strings .ToLower (suite ) {
184- case "sid" , "unstable" :
185- return false
186- case "testing" :
187- return false
188- case "bookworm" :
189- return false
190- case "trixie" :
191- return false
192- case "forky" :
193- return false
194- default :
210+ case "etch" ,
211+ "lenny" ,
212+ "squeeze" ,
213+ "wheezy" ,
214+ "jessie" ,
215+ "stretch" ,
216+ "buster" ,
217+ "bullseye" :
195218 return true
219+ default :
220+ // Default to "no workaround" for anything unknown/new (Debian >= bookworm
221+ // and derivatives)
222+ return false
196223 }
197224}
198225
@@ -244,41 +271,49 @@ func (d *DebootstrapAction) Run(context *debos.Context) error {
244271 cmdline = append (cmdline , fmt .Sprintf ("--variant=%s" , d .Variant ))
245272 }
246273
247- if shouldExcludeUsrIsMerged (d .ParentSuite ) {
248- log .Printf ("excluding usr-is-merged as package is not in parent suite %s\n " , d .ParentSuite )
249- cmdline = append (cmdline , "--exclude=usr-is-merged" )
250- }
251-
252- cmdline = append (cmdline , d .Suite )
253- cmdline = append (cmdline , context .Rootdir )
254- cmdline = append (cmdline , d .Mirror )
255-
256- if len (d .Script ) > 0 {
257- if _ , err := os .Stat (d .Script ); err != nil {
258- return fmt .Errorf ("cannot find debootstrap script %s" , d .Script )
259- }
274+ // Determine which debootstrap script to use and which suite we apply the
275+ // usr-is-merged workaround for.
276+ var scriptPath string
277+ var suiteForWorkaround string
278+
279+ if d .DebootstrapScript != "" {
280+ // Custom script specified by the user; Verify() already ensured it exists.
281+ scriptPath = d .DebootstrapScript
282+
283+ // When using a custom script we assume any distro-specific workarounds
284+ // are handled there and do not apply the usr-is-merged workaround here.
285+ suiteForWorkaround = ""
286+ } else if d .DebootstrapSuite != "" {
287+ // Explicit parent/debootstrap suite – must exist, checked in Verify().
288+ suiteForWorkaround = d .DebootstrapSuite
289+ scriptPath = getDebootstrapScriptPath (suiteForWorkaround )
260290 } else {
261- /* Auto determine debootstrap script to use from d.Suite, falling back to
262- d.ParentSuite if it doesn't exist. Finally, fallback to unstable if a
263- script for the parent suite does not exist. */
264- for _ , s := range []string {d .Suite , d .ParentSuite , "unstable" } {
265- d .Script = getDebootstrapScriptPath (s )
266- if _ , err := os .Stat (d .Script ); err == nil {
267- break
268- }
269-
270- log .Printf ("cannot find debootstrap script %s\n " , d .Script )
271-
272- /* Unstable should always be available so error out if not found */
273- if s == "unstable" {
291+ // Automatic behaviour: use suite's builtin script if available, otherwise
292+ // fall back to unstable (current behaviour), and suggest debootstrap-suite.
293+ suiteForWorkaround = d .Suite
294+ scriptPath = getDebootstrapScriptPath (suiteForWorkaround )
295+ if _ , err := os .Stat (scriptPath ); err != nil {
296+ log .Printf ("cannot find debootstrap script %s, falling back to unstable\n " , scriptPath )
297+ suiteForWorkaround = "unstable"
298+ scriptPath = getDebootstrapScriptPath (suiteForWorkaround )
299+ if _ , err := os .Stat (scriptPath ); err != nil {
274300 return errors .New ("cannot find debootstrap script for unstable" )
275301 }
302+ log .Printf ("using fallback debootstrap script %s; consider setting debootstrap-suite" , scriptPath )
276303 }
304+ }
277305
278- log .Printf ("using debootstrap script %s\n " , d .Script )
306+ // workaround for https://github.com/go-debos/debos/issues/361
307+ // Apply the workaround only for known-old suites
308+ if suiteForWorkaround != "" && shouldExcludeUsrIsMerged (suiteForWorkaround ) {
309+ log .Printf ("excluding usr-is-merged as package is not in suite %s\n " , suiteForWorkaround )
310+ cmdline = append (cmdline , "--exclude=usr-is-merged" )
279311 }
280312
281- cmdline = append (cmdline , d .Script )
313+ cmdline = append (cmdline , d .Suite )
314+ cmdline = append (cmdline , context .Rootdir )
315+ cmdline = append (cmdline , d .Mirror )
316+ cmdline = append (cmdline , scriptPath )
282317
283318 /* Make sure /etc/apt/apt.conf.d exists inside the fakemachine otherwise
284319 debootstrap prints a warning about the path not existing. */
0 commit comments