@@ -3,6 +3,7 @@ package manifest_test
33import (
44 "fmt"
55 "os"
6+ "path/filepath"
67 "testing"
78
89 "github.com/stretchr/testify/assert"
@@ -13,6 +14,7 @@ import (
1314 "github.com/osbuild/image-builder/pkg/arch"
1415 "github.com/osbuild/image-builder/pkg/container"
1516 "github.com/osbuild/image-builder/pkg/customizations/fsnode"
17+ "github.com/osbuild/image-builder/pkg/customizations/subscription"
1618 "github.com/osbuild/image-builder/pkg/customizations/users"
1719 "github.com/osbuild/image-builder/pkg/manifest"
1820 "github.com/osbuild/image-builder/pkg/osbuild"
@@ -409,3 +411,163 @@ func TestRawBootcPXE(t *testing.T) {
409411 assert .Contains (t , mkdirPaths , "/usr" )
410412 assert .Contains (t , mkdirPaths , "/proc" )
411413}
414+
415+ func TestRawBootcImageSerializeSubscriptionManagerCommands (t * testing.T ) {
416+ rawBootcPipeline := makeFakeRawBootcPipeline ()
417+ rawBootcPipeline .OSCustomizations .Subscription = & subscription.ImageOptions {
418+ Organization : "2040324" ,
419+ ActivationKey : "my-secret-key" ,
420+ ServerUrl : "subscription.rhsm.redhat.com" ,
421+ BaseUrl : "http://cdn.redhat.com/" ,
422+ }
423+
424+ pipeline , err := rawBootcPipeline .Serialize ()
425+ require .NoError (t , err )
426+ CheckSystemdStageOptions (t , pipeline .Stages , []string {
427+ "/usr/sbin/subscription-manager config --server.hostname 'subscription.rhsm.redhat.com'" ,
428+ `/usr/sbin/subscription-manager register --org="${ORG_ID}" --activationkey="${ACTIVATION_KEY}" --baseurl 'http://cdn.redhat.com/'` ,
429+ })
430+
431+ // registration unit in /etc, not /usr (ostree commit content)
432+ assert .Equal (t , osbuild .EtcUnitPath , registrationUnitPath (t , pipeline .Stages ))
433+ }
434+
435+ func TestRawBootcImageSerializeSubscriptionManagerInsightsCommands (t * testing.T ) {
436+ rawBootcPipeline := makeFakeRawBootcPipeline ()
437+ rawBootcPipeline .OSCustomizations .Subscription = & subscription.ImageOptions {
438+ Organization : "2040324" ,
439+ ActivationKey : "my-secret-key" ,
440+ ServerUrl : "subscription.rhsm.redhat.com" ,
441+ BaseUrl : "http://cdn.redhat.com/" ,
442+ Insights : true ,
443+ }
444+
445+ pipeline , err := rawBootcPipeline .Serialize ()
446+ require .NoError (t , err )
447+ CheckSystemdStageOptions (t , pipeline .Stages , []string {
448+ "/usr/sbin/subscription-manager config --server.hostname 'subscription.rhsm.redhat.com'" ,
449+ `/usr/sbin/subscription-manager register --org="${ORG_ID}" --activationkey="${ACTIVATION_KEY}" --baseurl 'http://cdn.redhat.com/'` ,
450+ "/usr/bin/insights-client --register" ,
451+ })
452+
453+ // InsightsOnBoot also materializes the insights-client drop-in
454+ mkdirPaths := collectMkdirPaths (pipeline .Stages )
455+ assert .Contains (t , mkdirPaths , "/etc/systemd/system/insights-client-boot.service.d" )
456+ destinationPaths := collectCopyDestinationPaths (pipeline .Stages )
457+ assert .Contains (t , destinationPaths , "tree:///etc/systemd/system/insights-client-boot.service.d/override.conf" )
458+ }
459+
460+ func TestRawBootcImageSerializeRhcInsightsCommands (t * testing.T ) {
461+ rawBootcPipeline := makeFakeRawBootcPipeline ()
462+ rawBootcPipeline .OSCustomizations .Subscription = & subscription.ImageOptions {
463+ Organization : "2040324" ,
464+ ActivationKey : "my-secret-key" ,
465+ ServerUrl : "subscription.rhsm.redhat.com" ,
466+ BaseUrl : "http://cdn.redhat.com/" ,
467+ Insights : false ,
468+ Rhc : true ,
469+ }
470+ rawBootcPipeline .OSCustomizations .PermissiveRHC = common .ToPtr (true )
471+
472+ pipeline , err := rawBootcPipeline .Serialize ()
473+ require .NoError (t , err )
474+ CheckSystemdStageOptions (t , pipeline .Stages , []string {
475+ "/usr/sbin/subscription-manager config --server.hostname 'subscription.rhsm.redhat.com'" ,
476+ `/usr/bin/rhc connect --organization="${ORG_ID}" --activation-key="${ACTIVATION_KEY}"` ,
477+ "/usr/sbin/semanage permissive --add rhcd_t" ,
478+ })
479+ }
480+
481+ func TestRawBootcImageSerializeSubscriptionEnablesService (t * testing.T ) {
482+ rawBootcPipeline := makeFakeRawBootcPipeline ()
483+ rawBootcPipeline .OSCustomizations .Subscription = & subscription.ImageOptions {
484+ Organization : "2040324" ,
485+ ActivationKey : "my-secret-key" ,
486+ }
487+
488+ pipeline , err := rawBootcPipeline .Serialize ()
489+ require .NoError (t , err )
490+
491+ stage := findStage ("org.osbuild.systemd" , pipeline .Stages )
492+ require .NotNil (t , stage )
493+ opts := stage .Options .(* osbuild.SystemdStageOptions )
494+ assert .Equal (t , []string {"osbuild-subscription-register.service" }, opts .EnabledServices )
495+ }
496+
497+ // Mirrors TestAddInlineOS: the env file must be both a copy destination and an
498+ // inline source, and is written before the blueprint's own files.
499+ func TestRawBootcImageSerializeSubscriptionEnvFile (t * testing.T ) {
500+ rawBootcPipeline := makeFakeRawBootcPipeline ()
501+
502+ require := require .New (t )
503+
504+ rawBootcPipeline .OSCustomizations .Files = createTestFilesForPipeline ()
505+ rawBootcPipeline .OSCustomizations .Subscription = & subscription.ImageOptions {
506+ Organization : "000" ,
507+ ActivationKey : "111" ,
508+ }
509+
510+ expectedPaths := []string {
511+ "tree:///etc/osbuild-subscription-register.env" , // from the subscription options
512+ "tree:///etc/test/one" , // directly from the OS customizations
513+ "tree:///etc/test/two" ,
514+ }
515+
516+ pipeline , err := rawBootcPipeline .Serialize ()
517+ require .NoError (err )
518+
519+ destinationPaths := collectCopyDestinationPaths (pipeline .Stages )
520+
521+ // The order is significant. Do not use ElementsMatch() or similar.
522+ require .Equal (expectedPaths , destinationPaths )
523+
524+ expectedContents := []string {
525+ "ORG_ID=000\n ACTIVATION_KEY=111" ,
526+ "test 1" ,
527+ "test 2" ,
528+ }
529+
530+ fileContents := manifest .GetInline (rawBootcPipeline )
531+ // These are used to define the 'sources' part of the manifest, so the
532+ // order doesn't matter
533+ require .ElementsMatch (expectedContents , fileContents )
534+ }
535+
536+ func TestRawBootcImageSerializeURIFilesError (t * testing.T ) {
537+ rawBootcPipeline := makeFakeRawBootcPipeline ()
538+
539+ localFile := filepath .Join (t .TempDir (), "local-file" )
540+ require .NoError (t , os .WriteFile (localFile , []byte ("some content" ), 0644 ))
541+ uriFile := common .Must (fsnode .NewFileForURI ("/etc/test/from-uri" , nil , nil , nil , localFile ))
542+ rawBootcPipeline .OSCustomizations .Files = []* fsnode.File {uriFile }
543+
544+ _ , err := rawBootcPipeline .Serialize ()
545+ assert .EqualError (t , err , fmt .Sprintf (
546+ "cannot create file %q from %q: files from an URI are not supported for bootc disk images yet" ,
547+ "/etc/test/from-uri" , localFile ))
548+ }
549+
550+ // registrationUnitPath returns the UnitPath of the registration unit, found by
551+ // filename because mount units share the systemd.unit.create stage type.
552+ func registrationUnitPath (t * testing.T , stages []* osbuild.Stage ) osbuild.SystemdUnitPath {
553+ t .Helper ()
554+ for _ , s := range findStages ("org.osbuild.systemd.unit.create" , stages ) {
555+ opts := s .Options .(* osbuild.SystemdUnitCreateStageOptions )
556+ if opts .Filename == "osbuild-subscription-register.service" {
557+ return opts .UnitPath
558+ }
559+ }
560+ require .Fail (t , "no osbuild-subscription-register.service unit.create stage found" )
561+ return ""
562+ }
563+
564+ func collectMkdirPaths (stages []* osbuild.Stage ) []string {
565+ mkdirPaths := make ([]string , 0 )
566+ for _ , mkdirStage := range findStages ("org.osbuild.mkdir" , stages ) {
567+ mkdirStageOptions := mkdirStage .Options .(* osbuild.MkdirStageOptions )
568+ for _ , path := range mkdirStageOptions .Paths {
569+ mkdirPaths = append (mkdirPaths , path .Path )
570+ }
571+ }
572+ return mkdirPaths
573+ }
0 commit comments