Repository: osbuild/osbuild-composer
Pull request #2598 (2022-04-28 11:25:46)

composer: add support for logrus syslog hook
Which will be used on crc in the log forwarding setup
NeededBy: COMPOSER-1285


This pull request includes:

- [ ] adequate testing for the new functionality or fixed issue
- [ ] adequate documentation informing people about the change such as
  - [ ] submit a PR for the [guides](https://github.com/osbuild/guides) repository if this PR changed any behavior described there: https://www.osbuild.org/guides/

<!--
Thanks for proposing a change to osbuild-composer!

Please don't remove the above check list. These are things that each pull
request must have before it is merged. It helps maintainers to not forget
anything.

If the reason for ticking any of the boxes is ambiguous, please add a short
note explaining why.

In addition, if this pull request fixes a downstream issue, please refer to
test/README.md and add these additional items:

- [ ] 1st commit of any `rhbz#` related PR contains bug reproducer; CI reports FAIL or
- [ ] PR contains automated tests for new functionality and
- [ ] QE has approved reproducer/new tests and
- [ ] Subsequent commits provide bug fixes without modifying the reproducer; CI reports PASS and
- [ ] QE approves this PR; RHBZ status is set to `MODIFIED + Verified=Tested`

Information regarding our GitLab pipeline (Schutzbot):

CI will not be ran automatically if WIP label is applied or the PR is in DRAFT state, instead only
a link will be provided to the pipeline which can then be triggered manually if desired. To run the
CI automatically either switch the PR to ready or apply WIP+test label.

Outside contributors need manual approval from one of the osbuild-composer maintainers.

Schutzbot will only be triggered if all Tests jobs in GitHub workflow succeed.
-->



Patch:
diff --git a/Schutzfile b/Schutzfile
index aaf743322..c07952fae 100644
--- a/Schutzfile
+++ b/Schutzfile
@@ -46,14 +46,14 @@
           {
             "title": "updates",
             "name": "updates",
-            "baseurl": "https://rpmrepo.osbuild.org/v2/mirror/public/f34/f34-x86_64-updates-released-20220330"
+            "baseurl": "https://rpmrepo.osbuild.org/v2/mirror/public/f34/f34-x86_64-updates-released-20220504"
           }
         ],
         "aarch64": [
           {
             "title": "updates",
             "name": "updates",
-            "baseurl": "https://rpmrepo.osbuild.org/v2/mirror/public/f34/f34-aarch64-updates-released-20220330"
+            "baseurl": "https://rpmrepo.osbuild.org/v2/mirror/public/f34/f34-aarch64-updates-released-20220504"
           }
         ]
       },
@@ -63,14 +63,14 @@
           {
             "title": "updates-modular",
             "name": "updates-modular",
-            "baseurl": "https://rpmrepo.osbuild.org/v2/mirror/public/f34/f34-x86_64-updates-released-modular-20220330"
+            "baseurl": "https://rpmrepo.osbuild.org/v2/mirror/public/f34/f34-x86_64-updates-released-modular-20220504"
           }
         ],
         "aarch64": [
           {
             "title": "updates-modular",
             "name": "updates-modular",
-            "baseurl": "https://rpmrepo.osbuild.org/v2/mirror/public/f34/f34-aarch64-updates-released-modular-20220330"
+            "baseurl": "https://rpmrepo.osbuild.org/v2/mirror/public/f34/f34-aarch64-updates-released-modular-20220504"
           }
         ]
       }
@@ -123,14 +123,14 @@
           {
             "title": "updates",
             "name": "updates",
-            "baseurl": "https://rpmrepo.osbuild.org/v2/mirror/public/f35/f35-x86_64-updates-released-20220330"
+            "baseurl": "https://rpmrepo.osbuild.org/v2/mirror/public/f35/f35-x86_64-updates-released-20220504"
           }
         ],
         "aarch64": [
           {
             "title": "updates",
             "name": "updates",
-            "baseurl": "https://rpmrepo.osbuild.org/v2/mirror/public/f35/f35-aarch64-updates-released-20220330"
+            "baseurl": "https://rpmrepo.osbuild.org/v2/mirror/public/f35/f35-aarch64-updates-released-20220504"
           }
         ]
       },
@@ -140,14 +140,14 @@
           {
             "title": "updates-modular",
             "name": "updates-modular",
-            "baseurl": "https://rpmrepo.osbuild.org/v2/mirror/public/f35/f35-x86_64-updates-released-modular-20220330"
+            "baseurl": "https://rpmrepo.osbuild.org/v2/mirror/public/f35/f35-x86_64-updates-released-modular-20220504"
           }
         ],
         "aarch64": [
           {
             "title": "updates-modular",
             "name": "updates-modular",
-            "baseurl": "https://rpmrepo.osbuild.org/v2/mirror/public/f35/f35-aarch64-updates-released-modular-20220330"
+            "baseurl": "https://rpmrepo.osbuild.org/v2/mirror/public/f35/f35-aarch64-updates-released-modular-20220504"
           }
         ]
       }
diff --git a/cmd/osbuild-composer/config.go b/cmd/osbuild-composer/config.go
index 19c629a4e..edbf031e2 100644
--- a/cmd/osbuild-composer/config.go
+++ b/cmd/osbuild-composer/config.go
@@ -11,11 +11,12 @@ import (
 )
 
 type ComposerConfigFile struct {
-	Koji      KojiAPIConfig   `toml:"koji"`
-	Worker    WorkerAPIConfig `toml:"worker"`
-	WeldrAPI  WeldrAPIConfig  `toml:"weldr_api"`
-	LogLevel  string          `toml:"log_level"`
-	LogFormat string          `toml:"log_format"`
+	Koji         KojiAPIConfig   `toml:"koji"`
+	Worker       WorkerAPIConfig `toml:"worker"`
+	WeldrAPI     WeldrAPIConfig  `toml:"weldr_api"`
+	SyslogServer string          `toml:"syslog_server" env:"SYSLOG_SERVER"`
+	LogLevel     string          `toml:"log_level"`
+	LogFormat    string          `toml:"log_format"`
 }
 
 type KojiAPIConfig struct {
diff --git a/cmd/osbuild-composer/main.go b/cmd/osbuild-composer/main.go
index 5a145a391..04137dc93 100644
--- a/cmd/osbuild-composer/main.go
+++ b/cmd/osbuild-composer/main.go
@@ -6,6 +6,7 @@ import (
 
 	"github.com/coreos/go-systemd/activation"
 	"github.com/sirupsen/logrus"
+	"github.com/sirupsen/logrus/hooks/syslog"
 )
 
 const (
@@ -69,6 +70,15 @@ func main() {
 		logrus.Fatal("CACHE_DIRECTORY is not set. Is the service file missing CacheDirectory=?")
 	}
 
+	if len(config.SyslogServer) > 0 {
+		hook, err := syslog.NewSyslogHook("tcp", config.SyslogServer, 0, "osbuild-composer")
+		if err != nil {
+			logrus.Fatal("Error connecting to syslog: " + err.Error())
+		}
+
+		logrus.AddHook(hook)
+	}
+
 	composer, err := NewComposer(config, stateDir, cacheDir)
 	if err != nil {
 		logrus.Fatalf("%v", err)
diff --git a/internal/boot/context-managers.go b/internal/boot/context-managers.go
index de43bc35e..88b2a1206 100644
--- a/internal/boot/context-managers.go
+++ b/internal/boot/context-managers.go
@@ -139,7 +139,7 @@ func WithBootedQemuImage(image string, ns NetNS, f func() error) error {
 				"-nographic",
 				image,
 			)
-		} else if common.CurrentArch() == "aarch64" {
+		} else if common.CurrentArch() == distro.Aarch64ArchName {
 			// This command does not use KVM as I was unable to make it work in Beaker,
 			// once we have machines that can use KVM, enable it to make it faster
 			qemuCmd = ns.NamespacedCommand(
diff --git a/internal/cloudapi/v2/handler.go b/internal/cloudapi/v2/handler.go
index 32fc09466..c610418b3 100644
--- a/internal/cloudapi/v2/handler.go
+++ b/internal/cloudapi/v2/handler.go
@@ -1010,7 +1010,8 @@ func collectRepos(irRepos, payloadRepositories []Repository, payloadPackageSets
 
 func genRepoConfig(repo Repository) (*rpmmd.RepoConfig, error) {
 	repoConfig := new(rpmmd.RepoConfig)
-	repoConfig.RHSM = repo.Rhsm
+
+	repoConfig.RHSM = repo.Rhsm != nil && *repo.Rhsm
 
 	if repo.Baseurl != nil {
 		repoConfig.BaseURL = *repo.Baseurl
diff --git a/internal/cloudapi/v2/openapi.v2.gen.go b/internal/cloudapi/v2/openapi.v2.gen.go
index 79aa77db4..7374e0a10 100644
--- a/internal/cloudapi/v2/openapi.v2.gen.go
+++ b/internal/cloudapi/v2/openapi.v2.gen.go
@@ -383,7 +383,9 @@ type Repository struct {
 	// Naming package sets for a repository assigns it to a specific part
 	// (pipeline) of the build process.
 	PackageSets *[]string `json:"package_sets,omitempty"`
-	Rhsm        bool      `json:"rhsm"`
+
+	// Determines whether a valid subscription is required to access this repository.
+	Rhsm *bool `json:"rhsm,omitempty"`
 }
 
 // Subscription defines model for Subscription.
@@ -652,105 +654,106 @@ func RegisterHandlersWithBaseURL(router EchoRouter, si ServerInterface, baseURL
 // Base64 encoded, gzipped, json marshaled Swagger object
 var swaggerSpec = []string{
 
-	"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",
+	"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",
+	"RiThZd4Nm8/ofP/xfwMAAP//XHsRRt1XAAA=",
 }
 
 // GetSwagger returns the content of the embedded swagger specification file
diff --git a/internal/cloudapi/v2/openapi.v2.yml b/internal/cloudapi/v2/openapi.v2.yml
index d639e2f8e..f25ec6d1b 100644
--- a/internal/cloudapi/v2/openapi.v2.yml
+++ b/internal/cloudapi/v2/openapi.v2.yml
@@ -652,11 +652,11 @@ components:
         - vsphere
     Repository:
       type: object
-      required:
-        - rhsm
       properties:
         rhsm:
           type: boolean
+          default: false
+          description: 'Determines whether a valid subscription is required to access this repository.'
         baseurl:
           type: string
           format: url
diff --git a/internal/distro/rhel8/distro.go b/internal/distro/rhel8/distro.go
index dd020258b..3ef926576 100644
--- a/internal/distro/rhel8/distro.go
+++ b/internal/distro/rhel8/distro.go
@@ -166,7 +166,7 @@ func (t *imageType) MIMEType() string {
 
 func (t *imageType) OSTreeRef() string {
 	if t.rpmOstree {
-		return fmt.Sprintf(ostreeRef, t.arch.name)
+		return fmt.Sprintf(ostreeRef, t.Arch().Name())
 	}
 	return ""
 }
@@ -342,7 +342,7 @@ func (t *imageType) pipeline(c *blueprint.Customizations, options distro.ImageOp
 	p := &osbuild.Pipeline{}
 	p.SetBuild(t.buildPipeline(repos, *t.arch, buildPackageSpecs), "org.osbuild.rhel82")
 
-	if t.arch.Name() == "s390x" {
+	if t.arch.Name() == distro.S390xArchName {
 		p.AddStage(osbuild.NewKernelCmdlineStage(&osbuild.KernelCmdlineStageOptions{
 			RootFsUUID: "0bd700f8-090f-4556-b797-b340297ea1bd",
 			KernelOpts: "net.ifnames=0 crashkernel=auto",
@@ -354,7 +354,7 @@ func (t *imageType) pipeline(c *blueprint.Customizations, options distro.ImageOp
 
 	if t.bootable {
 		p.AddStage(osbuild.NewFSTabStage(t.fsTabStageOptions(t.arch.uefi)))
-		if t.arch.Name() != "s390x" {
+		if t.arch.Name() != distro.S390xArchName {
 			p.AddStage(osbuild.NewGRUB2Stage(t.grub2StageOptions(t.kernelOptions, c.GetKernel(), t.arch.uefi)))
 		}
 	}
@@ -404,7 +404,7 @@ func (t *imageType) pipeline(c *blueprint.Customizations, options distro.ImageOp
 		p.AddStage(osbuild.NewFirewallStage(t.firewallStageOptions(firewall)))
 	}
 
-	if t.arch.Name() == "s390x" {
+	if t.arch.Name() == distro.S390xArchName {
 		p.AddStage(osbuild.NewZiplStage(&osbuild.ZiplStageOptions{}))
 	}
 
@@ -584,7 +584,7 @@ func qemuAssembler(format string, filename string, uefi bool, arch distro.Arch,
 			},
 		}
 	} else {
-		if arch.Name() == "ppc64le" {
+		if arch.Name() == distro.Ppc64leArchName {
 			options = osbuild.QEMUAssemblerOptions{
 				Bootloader: &osbuild.QEMUBootloader{
 					Type:     "grub2",
@@ -612,7 +612,7 @@ func qemuAssembler(format string, filename string, uefi bool, arch distro.Arch,
 					},
 				},
 			}
-		} else if arch.Name() == "s390x" {
+		} else if arch.Name() == distro.S390xArchName {
 			options = osbuild.QEMUAssemblerOptions{
 				Bootloader: &osbuild.QEMUBootloader{
 					Type: "zipl",
diff --git a/internal/distro/rhel84/distro.go b/internal/distro/rhel84/distro.go
index caeee47fb..7bf2503fd 100644
--- a/internal/distro/rhel84/distro.go
+++ b/internal/distro/rhel84/distro.go
@@ -200,7 +200,7 @@ func (t *imageType) MIMEType() string {
 
 func (t *imageType) OSTreeRef() string {
 	if t.rpmOstree {
-		return fmt.Sprintf(ostreeRef, t.arch.name)
+		return fmt.Sprintf(ostreeRef, t.Arch().Name())
 	}
 	return ""
 }
@@ -407,7 +407,7 @@ func (t *imageType) pipeline(c *blueprint.Customizations, options distro.ImageOp
 		p.SetBuild(t.buildPipeline(repos, *t.arch, buildPackageSpecs), "org.osbuild.rhel84")
 	}
 
-	if t.arch.Name() == "s390x" {
+	if t.arch.Name() == distro.S390xArchName {
 		if pt == nil {
 			panic("s390x image must have a partition table, this is a programming error")
 		}
@@ -431,7 +431,7 @@ func (t *imageType) pipeline(c *blueprint.Customizations, options distro.ImageOp
 	}
 
 	if t.bootable {
-		if t.arch.Name() != "s390x" {
+		if t.arch.Name() != distro.S390xArchName {
 			p.AddStage(osbuild.NewGRUB2Stage(t.grub2StageOptions(pt, t.kernelOptions, c.GetKernel(), packageSpecs, t.arch.uefi, t.arch.legacy)))
 		}
 	}
@@ -483,7 +483,7 @@ func (t *imageType) pipeline(c *blueprint.Customizations, options distro.ImageOp
 		p.AddStage(osbuild.NewFirewallStage(t.firewallStageOptions(firewall)))
 	}
 
-	if t.arch.Name() == "s390x" {
+	if t.arch.Name() == distro.S390xArchName {
 		p.AddStage(osbuild.NewZiplStage(&osbuild.ZiplStageOptions{}))
 	}
 
@@ -653,7 +653,7 @@ func (t *imageType) selinuxStageOptions() *osbuild.SELinuxStageOptions {
 }
 
 func defaultPartitionTable(imageSize uint64, arch distro.Arch, rng *rand.Rand) disk.PartitionTable {
-	if arch.Name() == "x86_64" {
+	if arch.Name() == distro.X86_64ArchName {
 		return disk.PartitionTable{
 			Size: imageSize,
 			UUID: "D209C89E-EA5E-4FBD-B161-B461CCE297E0",
@@ -696,7 +696,7 @@ func defaultPartitionTable(imageSize uint64, arch distro.Arch, rng *rand.Rand) d
 				},
 			},
 		}
-	} else if arch.Name() == "aarch64" {
+	} else if arch.Name() == distro.Aarch64ArchName {
 		return disk.PartitionTable{
 			Size: imageSize,
 			UUID: "D209C89E-EA5E-4FBD-B161-B461CCE297E0",
@@ -732,7 +732,7 @@ func defaultPartitionTable(imageSize uint64, arch distro.Arch, rng *rand.Rand) d
 				},
 			},
 		}
-	} else if arch.Name() == "ppc64le" {
+	} else if arch.Name() == distro.Ppc64leArchName {
 		return disk.PartitionTable{
 			Size: imageSize,
 			UUID: "0x14fc63d2",
@@ -756,7 +756,7 @@ func defaultPartitionTable(imageSize uint64, arch distro.Arch, rng *rand.Rand) d
 				},
 			},
 		}
-	} else if arch.Name() == "s390x" {
+	} else if arch.Name() == distro.S390xArchName {
 		return disk.PartitionTable{
 			Size: imageSize,
 			UUID: "0x14fc63d2",
@@ -793,12 +793,12 @@ func qemuAssembler(pt *disk.PartitionTable, format string, filename string, imag
 		options.Bootloader = &osbuild.QEMUBootloader{
 			Type: "grub2",
 		}
-	} else if arch.Name() == "ppc64le" {
+	} else if arch.Name() == distro.Ppc64leArchName {
 		options.Bootloader = &osbuild.QEMUBootloader{
 			Type:     "grub2",
 			Platform: "powerpc-ieee1275",
 		}
-	} else if arch.Name() == "s390x" {
+	} else if arch.Name() == distro.S390xArchName {
 		options.Bootloader = &osbuild.QEMUBootloader{
 			Type: "zipl",
 		}
diff --git a/internal/distro/rhel84/distro_v2.go b/internal/distro/rhel84/distro_v2.go
index 69171d39b..d6d7f86f7 100644
--- a/internal/distro/rhel84/distro_v2.go
+++ b/internal/distro/rhel84/distro_v2.go
@@ -60,7 +60,7 @@ func (t *imageTypeS2) MIMEType() string {
 
 func (t *imageTypeS2) OSTreeRef() string {
 	if t.rpmOstree {
-		return fmt.Sprintf(ostreeRef, t.arch.name)
+		return fmt.Sprintf(ostreeRef, t.Arch().Name())
 	}
 	return ""
 }
diff --git a/internal/distro/rhel85/distro.go b/internal/distro/rhel85/distro.go
index 4d901face..562972eb5 100644
--- a/internal/distro/rhel85/distro.go
+++ b/internal/distro/rhel85/distro.go
@@ -214,7 +214,7 @@ func (t *imageType) MIMEType() string {
 
 func (t *imageType) OSTreeRef() string {
 	if t.rpmOstree {
-		return fmt.Sprintf(ostreeRef, t.arch.name)
+		return fmt.Sprintf(ostreeRef, t.Arch().Name())
 	}
 	return ""
 }
diff --git a/internal/distro/rhel85/pipelines.go b/internal/distro/rhel85/pipelines.go
index 5e67e2856..ce8005f9c 100644
--- a/internal/distro/rhel85/pipelines.go
+++ b/internal/distro/rhel85/pipelines.go
@@ -62,7 +62,7 @@ func qcow2Pipelines(t *imageType, customizations *blueprint.Customizations, opti
 }
 
 func prependKernelCmdlineStage(pipeline *osbuild.Pipeline, t *imageType, pt *disk.PartitionTable) *osbuild.Pipeline {
-	if t.arch.name == distro.S390xArchName {
+	if t.Arch().Name() == distro.S390xArchName {
 		rootFs := pt.FindMountable("/")
 		if rootFs == nil {
 			panic("s390x image must have a root filesystem, this is a programming error")
@@ -1461,9 +1461,9 @@ func simplifiedInstallerEFIBootTreePipeline(installDevice, kernelVer, arch strin
 
 	var architectures []string
 
-	if arch == "x86_64" {
+	if arch == distro.X86_64ArchName {
 		architectures = []string{"IA32", "X64"}
-	} else if arch == "aarch64" {
+	} else if arch == distro.Aarch64ArchName {
 		architectures = []string{"AA64"}
 	} else {
 		panic("unsupported architecture")
@@ -1705,7 +1705,7 @@ func qemuPipeline(inputPipelineName, inputFilename, outputFilename string, forma
 }
 
 func bootloaderConfigStage(t *imageType, partitionTable *disk.PartitionTable, kernel *blueprint.KernelCustomization, kernelVer string, install, greenboot bool) *osbuild.Stage {
-	if t.arch.name == distro.S390xArchName {
+	if t.Arch().Name() == distro.S390xArchName {
 		return osbuild.NewZiplStage(new(osbuild.ZiplStageOptions))
 	}
 
diff --git a/internal/distro/rhel86/distro.go b/internal/distro/rhel86/distro.go
index f405186aa..7703fd1c1 100644
--- a/internal/distro/rhel86/distro.go
+++ b/internal/distro/rhel86/distro.go
@@ -278,7 +278,7 @@ func (t *imageType) MIMEType() string {
 func (t *imageType) OSTreeRef() string {
 	d := t.arch.distro
 	if t.rpmOstree {
-		return fmt.Sprintf(d.ostreeRefTmpl, t.arch.name)
+		return fmt.Sprintf(d.ostreeRefTmpl, t.Arch().Name())
 	}
 	return ""
 }
diff --git a/internal/distro/rhel86/pipelines.go b/internal/distro/rhel86/pipelines.go
index e74fc4e49..5bc6d2ac3 100644
--- a/internal/distro/rhel86/pipelines.go
+++ b/internal/distro/rhel86/pipelines.go
@@ -41,7 +41,7 @@ func qcow2Pipelines(t *imageType, customizations *blueprint.Customizations, opti
 }
 
 func prependKernelCmdlineStage(pipeline *osbuild.Pipeline, t *imageType, pt *disk.PartitionTable) *osbuild.Pipeline {
-	if t.arch.name == distro.S390xArchName {
+	if t.Arch().Name() == distro.S390xArchName {
 		rootFs := pt.FindMountable("/")
 		if rootFs == nil {
 			panic("s390x image must have a root filesystem, this is a programming error")
@@ -238,7 +238,7 @@ func edgeInstallerPipelines(t *imageType, customizations *blueprint.Customizatio
 	pipelines = append(pipelines, *buildPipeline(repos, packageSetSpecs[buildPkgsKey], t.arch.distro.runner))
 	installerPackages := packageSetSpecs[installerPkgsKey]
 	d := t.arch.distro
-	archName := t.arch.name
+	archName := t.Arch().Name()
 	kernelVer := rpmmd.GetVerStrFromPackageSpecListPanic(installerPackages, "kernel")
 	ostreeRepoPath := "/ostree/repo"
 	payloadStages := ostreePayloadStages(options, ostreeRepoPath)
@@ -285,7 +285,7 @@ func imageInstallerPipelines(t *imageType, customizations *blueprint.Customizati
 	if err != nil {
 		return nil, err
 	}
-	archName := t.arch.name
+	archName := t.Arch().Name()
 	d := t.arch.distro
 	pipelines = append(pipelines, *anacondaTreePipeline(repos, installerPackages, kernelVer, archName, d.product, d.osVersion, "BaseOS", true))
 	isolabel := fmt.Sprintf(d.isolabelTmpl, archName)
@@ -741,7 +741,7 @@ func edgeSimplifiedInstallerPipelines(t *imageType, customizations *blueprint.Cu
 
 	// create boot ISO with raw image
 	d := t.arch.distro
-	archName := t.arch.name
+	archName := t.Arch().Name()
 	installerTreePipeline := simplifiedInstallerTreePipeline(repos, installerPackages, kernelVer, archName, d.product, d.osVersion, "edge", customizations.GetFDO())
 	isolabel := fmt.Sprintf(d.isolabelTmpl, archName)
 	efibootTreePipeline := simplifiedInstallerEFIBootTreePipeline(installDevice, kernelVer, archName, d.vendor, d.product, d.osVersion, isolabel, customizations.GetFDO())
@@ -1100,7 +1100,7 @@ func qemuPipeline(inputPipelineName, inputFilename, outputFilename string, forma
 }
 
 func bootloaderConfigStage(t *imageType, partitionTable disk.PartitionTable, kernel *blueprint.KernelCustomization, kernelVer string, install, greenboot bool) *osbuild.Stage {
-	if t.arch.name == distro.S390xArchName {
+	if t.Arch().Name() == distro.S390xArchName {
 		return osbuild.NewZiplStage(new(osbuild.ZiplStageOptions))
 	}
 
diff --git a/internal/distro/rhel86/stage_options.go b/internal/distro/rhel86/stage_options.go
index 911dbcab7..ae18c51de 100644
--- a/internal/distro/rhel86/stage_options.go
+++ b/internal/distro/rhel86/stage_options.go
@@ -209,9 +209,9 @@ func bootISOMonoStageOptions(kernelVer, arch, vendor, product, osVersion, isolab
 func grubISOStageOptions(installDevice, kernelVer, arch, vendor, product, osVersion, isolabel string, fdo *blueprint.FDOCustomization) *osbuild.GrubISOStageOptions {
 	var architectures []string
 
-	if arch == "x86_64" {
+	if arch == distro.X86_64ArchName {
 		architectures = []string{"IA32", "X64"}
-	} else if arch == "aarch64" {
+	} else if arch == distro.Aarch64ArchName {
 		architectures = []string{"AA64"}
 	} else {
 		panic("unsupported architecture")
diff --git a/internal/distro/rhel90/distro.go b/internal/distro/rhel90/distro.go
index c998d1994..c98b6c3ea 100644
--- a/internal/distro/rhel90/distro.go
+++ b/internal/distro/rhel90/distro.go
@@ -278,7 +278,7 @@ func (t *imageType) MIMEType() string {
 func (t *imageType) OSTreeRef() string {
 	d := t.arch.distro
 	if t.rpmOstree {
-		return fmt.Sprintf(d.ostreeRefTmpl, t.arch.name)
+		return fmt.Sprintf(d.ostreeRefTmpl, t.Arch().Name())
 	}
 	return ""
 }
diff --git a/internal/distro/rhel90/pipelines.go b/internal/distro/rhel90/pipelines.go
index fb90c86d8..faa9dfcdb 100644
--- a/internal/distro/rhel90/pipelines.go
+++ b/internal/distro/rhel90/pipelines.go
@@ -230,7 +230,7 @@ func edgeInstallerPipelines(t *imageType, customizations *blueprint.Customizatio
 	pipelines = append(pipelines, *buildPipeline(repos, packageSetSpecs[buildPkgsKey], t.arch.distro.runner))
 	installerPackages := packageSetSpecs[installerPkgsKey]
 	d := t.arch.distro
-	archName := t.arch.name
+	archName := t.Arch().Name()
 	kernelVer := rpmmd.GetVerStrFromPackageSpecListPanic(installerPackages, "kernel")
 	ostreeRepoPath := "/ostree/repo"
 	payloadStages := ostreePayloadStages(options, ostreeRepoPath)
@@ -277,7 +277,7 @@ func imageInstallerPipelines(t *imageType, customizations *blueprint.Customizati
 	if err != nil {
 		return nil, err
 	}
-	archName := t.arch.name
+	archName := t.Arch().Name()
 	d := t.arch.distro
 	pipelines = append(pipelines, *anacondaTreePipeline(repos, installerPackages, kernelVer, archName, d.product, d.osVersion, "BaseOS", true))
 	isolabel := fmt.Sprintf(d.isolabelTmpl, archName)
@@ -738,7 +738,7 @@ func edgeSimplifiedInstallerPipelines(t *imageType, customizations *blueprint.Cu
 
 	// create boot ISO with raw image
 	d := t.arch.distro
-	archName := t.arch.name
+	archName := t.Arch().Name()
 	installerTreePipeline := simplifiedInstallerTreePipeline(repos, installerPackages, kernelVer, archName, d.product, d.osVersion, "edge", customizations.GetFDO())
 	isolabel := fmt.Sprintf(d.isolabelTmpl, archName)
 	efibootTreePipeline := simplifiedInstallerEFIBootTreePipeline(installDevice, kernelVer, archName, d.vendor, d.product, d.osVersion, isolabel, customizations.GetFDO())
@@ -1092,7 +1092,7 @@ func qemuPipeline(inputPipelineName, inputFilename, outputFilename string, forma
 }
 
 func bootloaderConfigStage(t *imageType, partitionTable disk.PartitionTable, kernelVer string, install, greenboot bool) *osbuild.Stage {
-	if t.arch.name == distro.S390xArchName {
+	if t.Arch().Name() == distro.S390xArchName {
 		return osbuild.NewZiplStage(new(osbuild.ZiplStageOptions))
 	}
 
diff --git a/internal/distro/rhel90/stage_options.go b/internal/distro/rhel90/stage_options.go
index cb33cc793..b9604d105 100644
--- a/internal/distro/rhel90/stage_options.go
+++ b/internal/distro/rhel90/stage_options.go
@@ -209,9 +209,9 @@ func bootISOMonoStageOptions(kernelVer, arch, vendor, product, osVersion, isolab
 func grubISOStageOptions(installDevice, kernelVer, arch, vendor, product, osVersion, isolabel string, fdo *blueprint.FDOCustomization) *osbuild.GrubISOStageOptions {
 	var architectures []string
 
-	if arch == "x86_64" {
+	if arch == distro.X86_64ArchName {
 		architectures = []string{"X64"}
-	} else if arch == "aarch64" {
+	} else if arch == distro.Aarch64ArchName {
 		architectures = []string{"AA64"}
 	} else {
 		panic("unsupported architecture")
diff --git a/internal/distro/rhel90beta/distro.go b/internal/distro/rhel90beta/distro.go
index abb0dadbb..3e7a28538 100644
--- a/internal/distro/rhel90beta/distro.go
+++ b/internal/distro/rhel90beta/distro.go
@@ -223,7 +223,7 @@ func (t *imageType) MIMEType() string {
 
 func (t *imageType) OSTreeRef() string {
 	if t.rpmOstree {
-		return fmt.Sprintf(ostreeRef, t.arch.name)
+		return fmt.Sprintf(ostreeRef, t.Arch().Name())
 	}
 	return ""
 }
diff --git a/internal/distro/rhel90beta/pipelines.go b/internal/distro/rhel90beta/pipelines.go
index d73351b09..5eea71473 100644
--- a/internal/distro/rhel90beta/pipelines.go
+++ b/internal/distro/rhel90beta/pipelines.go
@@ -1097,7 +1097,7 @@ func qemuPipeline(inputPipelineName, inputFilename, outputFilename string, forma
 }
 
 func bootloaderConfigStage(t *imageType, partitionTable *disk.PartitionTable, kernel *blueprint.KernelCustomization, kernelVer string) *osbuild.Stage {
-	if t.arch.name == distro.S390xArchName {
+	if t.Arch().Name() == distro.S390xArchName {
 		return osbuild.NewZiplStage(new(osbuild.ZiplStageOptions))
 	}
 
diff --git a/templates/composer.yml b/templates/composer.yml
index a6b0e670d..5d1e4bf71 100644
--- a/templates/composer.yml
+++ b/templates/composer.yml
@@ -94,6 +94,8 @@ objects:
             value: "${PGSSLMODE}"
           - name: PGMAXCONNS
             value: "${PGMAXCONNS}"
+          - name: SYSLOG_SERVER
+            value: "localhost:5140"
           ports:
           - name: composer-api
             protocol: TCP
@@ -109,6 +111,32 @@ objects:
             mountPath: "/var/lib/osbuild-composer"
           - name: cache-directory
             mountPath: "/var/cache/osbuild-composer"
+        - image: "fluentd-hec:1.2.13"
+          name: fluentd-sidecar
+          resources:
+            requests:
+              cpu: "${CPU_REQUEST}"
+              memory: "${MEMORY_REQUEST}"
+            limits:
+              cpu: "${CPU_REQUEST}"
+              memory: "${MEMORY_LIMIT}"
+          env:
+            - name: SPLUNK_HEC_TOKEN
+              valueFrom:
+                secretKeyRef:
+                  name: splunk
+                  key: token
+                  optional: false
+            - name: SPLUNK_HEC_URL
+              valueFrom:
+                secretKeyRef:
+                  name: splunk
+                  key: url
+                  optional: false
+          volumeMounts:
+            - name: fluentd-config
+              mountPath: /fluentd/etc
+              readOnly: true
         volumes:
         - name: composer-config
           configMap:
@@ -158,7 +186,7 @@ objects:
   metadata:
     name: image-builder
   imagePullSecrets:
-  - name: quay-cloudservices-pull
+  - name: default-dockercfg-8bg88
 
 - apiVersion: v1
   kind: Service
@@ -224,7 +252,30 @@ objects:
       jwt_keys_urls = ["${RH_SSO_BASE_URL}/protocol/openid-connect/certs", "${MAS_SSO_BASE_URL}/protocol/openid-connect/certs"]
       jwt_acl_file = "${COMPOSER_CONFIG_DIR}/acl.yml"
       jwt_tenant_provider_fields = ["rh-org-id", "account_id"]
+- apiVersion: v1
+  kind: ConfigMap
+  metadata:
+    name: fluentd-config
+  data:
+    fluent.conf: |
+      <source>
+        @type syslog
+        port 5140
+        bind 127.0.0.1
+        <transport tcp>
+        </transport>
+        tag osbuild-composer
+        <parse>
+          time_format %Y-%m-%dT%H:%M:%SZ
+        </parse>
+      </source>
 
+      <match **>
+        @type splunk_hec
+        hec_host "#{ENV['SPLUNK_HEC_URL']}"
+        hec_port 8088
+        hec_token "#{ENV['SPLUNK_HEC_TOKEN']}"
+      </match>
 - apiVersion: batch/v1
   kind: CronJob
   metadata:
diff --git a/vendor/github.com/sirupsen/logrus/hooks/syslog/README.md b/vendor/github.com/sirupsen/logrus/hooks/syslog/README.md
new file mode 100644
index 000000000..1bbc0f72d
--- /dev/null
+++ b/vendor/github.com/sirupsen/logrus/hooks/syslog/README.md
@@ -0,0 +1,39 @@
+# Syslog Hooks for Logrus <img src="http://i.imgur.com/hTeVwmJ.png" width="40" height="40" alt=":walrus:" class="emoji" title=":walrus:"/>
+
+## Usage
+
+```go
+import (
+  "log/syslog"
+  "github.com/sirupsen/logrus"
+  lSyslog "github.com/sirupsen/logrus/hooks/syslog"
+)
+
+func main() {
+  log       := logrus.New()
+  hook, err := lSyslog.NewSyslogHook("udp", "localhost:514", syslog.LOG_INFO, "")
+
+  if err == nil {
+    log.Hooks.Add(hook)
+  }
+}
+```
+
+If you want to connect to local syslog (Ex. "/dev/log" or "/var/run/syslog" or "/var/run/log"). Just assign empty string to the first two parameters of `NewSyslogHook`. It should look like the following.
+
+```go
+import (
+  "log/syslog"
+  "github.com/sirupsen/logrus"
+  lSyslog "github.com/sirupsen/logrus/hooks/syslog"
+)
+
+func main() {
+  log       := logrus.New()
+  hook, err := lSyslog.NewSyslogHook("", "", syslog.LOG_INFO, "")
+
+  if err == nil {
+    log.Hooks.Add(hook)
+  }
+}
+```
diff --git a/vendor/github.com/sirupsen/logrus/hooks/syslog/syslog.go b/vendor/github.com/sirupsen/logrus/hooks/syslog/syslog.go
new file mode 100644
index 000000000..02b8df380
--- /dev/null
+++ b/vendor/github.com/sirupsen/logrus/hooks/syslog/syslog.go
@@ -0,0 +1,55 @@
+// +build !windows,!nacl,!plan9
+
+package syslog
+
+import (
+	"fmt"
+	"log/syslog"
+	"os"
+
+	"github.com/sirupsen/logrus"
+)
+
+// SyslogHook to send logs via syslog.
+type SyslogHook struct {
+	Writer        *syslog.Writer
+	SyslogNetwork string
+	SyslogRaddr   string
+}
+
+// Creates a hook to be added to an instance of logger. This is called with
+// `hook, err := NewSyslogHook("udp", "localhost:514", syslog.LOG_DEBUG, "")`
+// `if err == nil { log.Hooks.Add(hook) }`
+func NewSyslogHook(network, raddr string, priority syslog.Priority, tag string) (*SyslogHook, error) {
+	w, err := syslog.Dial(network, raddr, priority, tag)
+	return &SyslogHook{w, network, raddr}, err
+}
+
+func (hook *SyslogHook) Fire(entry *logrus.Entry) error {
+	line, err := entry.String()
+	if err != nil {
+		fmt.Fprintf(os.Stderr, "Unable to read entry, %v", err)
+		return err
+	}
+
+	switch entry.Level {
+	case logrus.PanicLevel:
+		return hook.Writer.Crit(line)
+	case logrus.FatalLevel:
+		return hook.Writer.Crit(line)
+	case logrus.ErrorLevel:
+		return hook.Writer.Err(line)
+	case logrus.WarnLevel:
+		return hook.Writer.Warning(line)
+	case logrus.InfoLevel:
+		return hook.Writer.Info(line)
+	case logrus.DebugLevel, logrus.TraceLevel:
+		return hook.Writer.Debug(line)
+	default:
+		return nil
+	}
+}
+
+func (hook *SyslogHook) Levels() []logrus.Level {
+	return logrus.AllLevels
+}
diff --git a/vendor/modules.txt b/vendor/modules.txt
index 0fb784ee8..5707ec4e2 100644
--- a/vendor/modules.txt
+++ b/vendor/modules.txt
@@ -338,6 +338,7 @@ github.com/segmentio/ksuid
 # github.com/sirupsen/logrus v1.8.1
 ## explicit
 github.com/sirupsen/logrus
+github.com/sirupsen/logrus/hooks/syslog
 # github.com/sony/gobreaker v0.4.2-0.20210216022020-dd874f9dd33b
 github.com/sony/gobreaker
 # github.com/spf13/cobra v1.4.0


Test patch:
diff --git a/cmd/osbuild-image-tests/main_test.go b/cmd/osbuild-image-tests/main_test.go
index c02af51fe..e3936e2f7 100644
--- a/cmd/osbuild-image-tests/main_test.go
+++ b/cmd/osbuild-image-tests/main_test.go
@@ -30,6 +30,7 @@ import (
 	"github.com/osbuild/osbuild-composer/internal/boot/openstacktest"
 	"github.com/osbuild/osbuild-composer/internal/boot/vmwaretest"
 	"github.com/osbuild/osbuild-composer/internal/common"
+	"github.com/osbuild/osbuild-composer/internal/distro"
 	"github.com/osbuild/osbuild-composer/internal/test"
 	"github.com/osbuild/osbuild-composer/internal/upload/vmware"
 )
@@ -392,7 +393,7 @@ func testBootUsingOpenStack(t *testing.T, imagePath string) {
 	currentArch := common.CurrentArch()
 
 	// skip on aarch64 because we don't have aarch64 openstack or kvm machines
-	if currentArch == "aarch64" {
+	if currentArch == distro.Aarch64ArchName {
 		t.Skip("Openstack boot test is skipped on aarch64.")
 		// if no credentials are given, fall back to qemu
 	} else if (creds == gophercloud.AuthOptions{}) {
diff --git a/internal/cloudapi/v2/v2_internal_test.go b/internal/cloudapi/v2/v2_internal_test.go
index ea8731c2c..2bb22afa9 100644
--- a/internal/cloudapi/v2/v2_internal_test.go
+++ b/internal/cloudapi/v2/v2_internal_test.go
@@ -134,7 +134,7 @@ func TestRepoConfigConversion(t *testing.T) {
 				IgnoreSsl:   common.BoolToPtr(false),
 				Metalink:    nil,
 				Mirrorlist:  nil,
-				Rhsm:        false,
+				Rhsm:        common.BoolToPtr(false),
 				PackageSets: nil,
 			},
 			repoConfig: rpmmd.RepoConfig{
@@ -158,7 +158,7 @@ func TestRepoConfigConversion(t *testing.T) {
 				IgnoreSsl:   common.BoolToPtr(true),
 				Metalink:    common.StringToPtr("http://example.org/metalink"),
 				Mirrorlist:  common.StringToPtr("http://example.org/mirrorlist"),
-				Rhsm:        false,
+				Rhsm:        common.BoolToPtr(false),
 				PackageSets: nil,
 			},
 			repoConfig: rpmmd.RepoConfig{
@@ -182,7 +182,7 @@ func TestRepoConfigConversion(t *testing.T) {
 				IgnoreSsl:   common.BoolToPtr(true),
 				Metalink:    common.StringToPtr("http://example.org/metalink"),
 				Mirrorlist:  common.StringToPtr("http://example.org/mirrorlist"),
-				Rhsm:        false,
+				Rhsm:        common.BoolToPtr(false),
 				PackageSets: nil,
 			},
 			repoConfig: rpmmd.RepoConfig{
@@ -206,7 +206,7 @@ func TestRepoConfigConversion(t *testing.T) {
 				IgnoreSsl:   common.BoolToPtr(true),
 				Metalink:    common.StringToPtr("http://example.org/metalink"),
 				Mirrorlist:  nil,
-				Rhsm:        true,
+				Rhsm:        common.BoolToPtr(true),
 				PackageSets: nil,
 			},
 			repoConfig: rpmmd.RepoConfig{
@@ -243,7 +243,7 @@ func TestRepoConfigConversion(t *testing.T) {
 				IgnoreSsl:   nil,
 				Metalink:    nil,
 				Mirrorlist:  nil,
-				Rhsm:        true,
+				Rhsm:        common.BoolToPtr(true),
 				PackageSets: nil,
 			},
 			err: HTTPError(ErrorInvalidRepository).Error(),
@@ -258,7 +258,7 @@ func TestRepoConfigConversion(t *testing.T) {
 				IgnoreSsl:   common.BoolToPtr(true),
 				Metalink:    common.StringToPtr("http://example.org/metalink"),
 				Mirrorlist:  nil,
-				Rhsm:        true,
+				Rhsm:        common.BoolToPtr(true),
 				PackageSets: nil,
 			},
 			err: HTTPError(ErrorNoGPGKey).Error(),
diff --git a/internal/distro/rhel84/distro_test.go b/internal/distro/rhel84/distro_test.go
index 474d002c5..afe9da809 100644
--- a/internal/distro/rhel84/distro_test.go
+++ b/internal/distro/rhel84/distro_test.go
@@ -220,7 +220,7 @@ func TestImageType_Name(t *testing.T) {
 	for _, dist := range rhelFamilyDistros {
 		t.Run(dist.name, func(t *testing.T) {
 			for _, mapping := range imgMap {
-				if mapping.arch == "s390x" && dist.name == "centos" {
+				if mapping.arch == distro.S390xArchName && dist.name == "centos" {
 					continue
 				}
 				arch, err := dist.distro.GetArch(mapping.arch)
@@ -443,7 +443,7 @@ func TestDistro_ManifestError(t *testing.T) {
 	for _, archName := range r8distro.ListArches() {
 		arch, _ := r8distro.GetArch(archName)
 		for _, imgTypeName := range arch.ListImageTypes() {
-			if archName == "s390x" && imgTypeName == "tar" {
+			if archName == distro.S390xArchName && imgTypeName == "tar" {
 				// broken arch-imgType combination; see
 				// https://github.com/osbuild/osbuild-composer/issues/1220
 				continue
@@ -514,7 +514,7 @@ func TestArchitecture_ListImageTypes(t *testing.T) {
 	for _, dist := range rhelFamilyDistros {
 		t.Run(dist.name, func(t *testing.T) {
 			for _, mapping := range imgMap {
-				if mapping.arch == "s390x" && dist.name == "centos" {
+				if mapping.arch == distro.S390xArchName && dist.name == "centos" {
 					continue
 				}
 				arch, err := dist.distro.GetArch(mapping.arch)
@@ -623,7 +623,7 @@ func TestDistro_CustomFileSystemManifestError(t *testing.T) {
 			for _, archName := range d.ListArches() {
 				arch, _ := d.GetArch(archName)
 				for _, imgTypeName := range arch.ListImageTypes() {
-					if (archName == "s390x" && imgTypeName == "tar") || imgTypeName == "rhel-edge-installer" {
+					if (archName == distro.S390xArchName && imgTypeName == "tar") || imgTypeName == "rhel-edge-installer" {
 						continue
 					}
 					imgType, _ := arch.GetImageType(imgTypeName)
@@ -660,7 +660,7 @@ func TestDistro_TestRootMountPoint(t *testing.T) {
 			for _, archName := range d.ListArches() {
 				arch, _ := d.GetArch(archName)
 				for _, imgTypeName := range arch.ListImageTypes() {
-					if (archName == "s390x" && imgTypeName == "tar") || imgTypeName == "rhel-edge-installer" {
+					if (archName == distro.S390xArchName && imgTypeName == "tar") || imgTypeName == "rhel-edge-installer" {
 						continue
 					}
 					imgType, _ := arch.GetImageType(imgTypeName)
diff --git a/internal/distro/rhel85/distro_test.go b/internal/distro/rhel85/distro_test.go
index c142cfc74..b67b5a812 100644
--- a/internal/distro/rhel85/distro_test.go
+++ b/internal/distro/rhel85/distro_test.go
@@ -317,7 +317,7 @@ func TestImageType_Name(t *testing.T) {
 	for _, dist := range rhelFamilyDistros {
 		t.Run(dist.name, func(t *testing.T) {
 			for _, mapping := range imgMap {
-				if mapping.arch == "s390x" && dist.name == "centos" {
+				if mapping.arch == distro.S390xArchName && dist.name == "centos" {
 					continue
 				}
 				arch, err := dist.distro.GetArch(mapping.arch)
diff --git a/internal/distro/rhel86/distro_test.go b/internal/distro/rhel86/distro_test.go
index b09876e32..47697d955 100644
--- a/internal/distro/rhel86/distro_test.go
+++ b/internal/distro/rhel86/distro_test.go
@@ -335,7 +335,7 @@ func TestImageType_Name(t *testing.T) {
 	for _, dist := range rhelFamilyDistros {
 		t.Run(dist.name, func(t *testing.T) {
 			for _, mapping := range imgMap {
-				if mapping.arch == "s390x" && dist.name == "centos" {
+				if mapping.arch == distro.S390xArchName && dist.name == "centos" {
 					continue
 				}
 				arch, err := dist.distro.GetArch(mapping.arch)
diff --git a/internal/distro/rhel90/distro_test.go b/internal/distro/rhel90/distro_test.go
index 141d915f4..e27c71a05 100644
--- a/internal/distro/rhel90/distro_test.go
+++ b/internal/distro/rhel90/distro_test.go
@@ -318,7 +318,7 @@ func TestImageType_Name(t *testing.T) {
 	for _, dist := range rhelFamilyDistros {
 		t.Run(dist.name, func(t *testing.T) {
 			for _, mapping := range imgMap {
-				if mapping.arch == "s390x" && dist.name == "centos" {
+				if mapping.arch == distro.S390xArchName && dist.name == "centos" {
 					continue
 				}
 				arch, err := dist.distro.GetArch(mapping.arch)
diff --git a/internal/distro/rhel90beta/distro_test.go b/internal/distro/rhel90beta/distro_test.go
index ee70eb4dd..f4bc7767c 100644
--- a/internal/distro/rhel90beta/distro_test.go
+++ b/internal/distro/rhel90beta/distro_test.go
@@ -308,7 +308,7 @@ func TestImageType_Name(t *testing.T) {
 	for _, dist := range rhelFamilyDistros {
 		t.Run(dist.name, func(t *testing.T) {
 			for _, mapping := range imgMap {
-				if mapping.arch == "s390x" && dist.name == "centos" {
+				if mapping.arch == distro.S390xArchName && dist.name == "centos" {
 					continue
 				}
 				arch, err := dist.distro.GetArch(mapping.arch)