debian-forge-composer/cmd/osbuild-composer/main.go
Brian C. Lane ea05f400e6 cloudapi: Listen on /run/cloudapi/api.socket
Add a local socket for communicating with the cloudapi. It is started by
osbuild-composer.socket and is located at /run/cloudapi/api.socket

cloudapi requests can be passed to it using curl like this:

curl -k --unix-socket /run/cloudapi/api.socket --header 'Content-Type: application/json' \
--data request.json http://localhost/api/image-builder-composer/v2/compose

A simple request.json looks like this:

{
  "distribution": "fedora-38",
  "image_request":
    {
      "architecture": "x86_64",
      "image_type": "guest-image",
      "upload_options": {},
      "repositories": [
          {
            "name": "fedora",
            "metalink": "https://mirrors.fedoraproject.org/metalink?repo=fedora-38&arch=x86_64",
            "check_gpg": false
          },
          {
            "name": "updates",
            "metalink": "https://mirrors.fedoraproject.org/metalink?repo=updates-released-f38&arch=x86_64",
            "check_gpg": false
          }
      ]
    }
}
2024-01-15 11:48:35 +01:00

152 lines
4.2 KiB
Go

package main
import (
"context"
"flag"
"os"
"github.com/coreos/go-systemd/activation"
slogger "github.com/osbuild/osbuild-composer/pkg/splunk_logger"
"github.com/sirupsen/logrus"
)
const (
configFile = "/etc/osbuild-composer/osbuild-composer.toml"
ServerKeyFile = "/etc/osbuild-composer/composer-key.pem"
ServerCertFile = "/etc/osbuild-composer/composer-crt.pem"
)
var repositoryConfigs = []string{
"/etc/osbuild-composer",
"/usr/share/osbuild-composer",
}
func main() {
var verbose bool
flag.BoolVar(&verbose, "verbose", false, "Print access log")
flag.Parse()
if !verbose {
logrus.Print("verbose flag is provided for backward compatibility only, current behavior is always printing the access log")
}
config, err := LoadConfig(configFile)
if err != nil {
logrus.Fatalf("Error loading configuration: %v", err)
}
logrus.SetOutput(os.Stdout)
logLevel, err := logrus.ParseLevel(config.LogLevel)
logrus.SetReportCaller(true)
if err == nil {
logrus.SetLevel(logLevel)
} else {
logrus.Info("Failed to load loglevel from config:", err)
}
switch config.LogFormat {
case "text":
logrus.SetFormatter(&logrus.TextFormatter{})
case "json":
logrus.SetFormatter(&logrus.JSONFormatter{})
default:
logrus.Infof("Failed to set logging format from config, '%s' is not a valid option", config.LogFormat)
}
logrus.Info("Loaded configuration:")
err = DumpConfig(*config, logrus.StandardLogger().WriterLevel(logrus.InfoLevel))
if err != nil {
logrus.Fatalf("Error printing configuration: %v", err)
}
if config.SplunkHost != "" {
hook, err := slogger.NewSplunkHook(context.Background(), config.SplunkHost, config.SplunkPort, config.SplunkToken, "osbuild-composer")
if err != nil {
panic(err)
}
logrus.AddHook(hook)
}
stateDir, ok := os.LookupEnv("STATE_DIRECTORY")
if !ok {
logrus.Fatal("STATE_DIRECTORY is not set. Is the service file missing StateDirectory=?")
}
cacheDir, ok := os.LookupEnv("CACHE_DIRECTORY")
if !ok {
logrus.Fatal("CACHE_DIRECTORY is not set. Is the service file missing CacheDirectory=?")
}
composer, err := NewComposer(config, stateDir, cacheDir)
if err != nil {
logrus.Fatalf("%v", err)
}
listeners, err := activation.ListenersWithNames()
if err != nil {
logrus.Fatalf("Could not get listening sockets: " + err.Error())
}
if l, exists := listeners["osbuild-composer.socket"]; exists {
if len(l) != 2 {
logrus.Fatal("The osbuild-composer.socket unit is misconfigured. It should contain two sockets.")
}
err = composer.InitWeldr(repositoryConfigs, l[0], config.weldrDistrosImageTypeDenyList())
if err != nil {
logrus.Fatalf("Error initializing weldr API: %v", err)
}
// Start cloudapi using the 2nd socket and no certs
err = composer.InitAPI(ServerCertFile, ServerKeyFile, false, false, false, l[1])
if err != nil {
logrus.Fatalf("Error initializing Cloud API using local socket: %v", err)
}
}
if l, exists := listeners["osbuild-local-worker.socket"]; exists {
if len(l) != 1 {
logrus.Fatal("The osbuild-local-worker.socket unit is misconfigured. It should contain only one socket.")
}
composer.InitLocalWorker(l[0])
}
if l, exists := listeners["osbuild-composer-prometheus.socket"]; exists {
if len(l) != 1 {
logrus.Warn("The osbuild-composer-prometheus.socket unit is misconfigured. It should contain only one socket.")
}
composer.InitMetricsAPI(l[0])
}
if l, exists := listeners["osbuild-composer-api.socket"]; exists {
if len(l) != 1 {
logrus.Fatal("The osbuild-composer-api.socket unit is misconfigured. It should contain only one socket.")
}
err = composer.InitAPI(ServerCertFile, ServerKeyFile, config.Koji.EnableTLS, config.Koji.EnableMTLS, config.Koji.EnableJWT, l[0])
if err != nil {
logrus.Fatalf("Error initializing koji API: %v", err)
}
}
if l, exists := listeners["osbuild-remote-worker.socket"]; exists {
if len(l) != 1 {
logrus.Fatal("The osbuild-remote-worker.socket unit is misconfigured. It should contain only one socket.")
}
err = composer.InitRemoteWorkers(ServerCertFile, ServerKeyFile, config.Worker.EnableTLS, config.Worker.EnableMTLS, config.Worker.EnableJWT, l[0])
if err != nil {
logrus.Fatalf("Error initializing worker API: %v", err)
}
}
err = composer.Start()
if err != nil {
logrus.Fatalf("%v", err)
}
}