debian-forge-composer/internal/distro/distro.go
Tom Gundersen 5fcdd4bea5 distro: don't use a global variable to store the distro register
Introduce a DistroRegister object. For now this does not introduce
any functional changes, as the object is always instantited to be
the same. However, in follow-up patches it will get options.

Signed-off-by: Tom Gundersen <teg@jklm.no>
2020-01-03 22:35:52 +01:00

122 lines
2.9 KiB
Go

package distro
import (
"bufio"
"errors"
"io"
"os"
"strings"
"github.com/osbuild/osbuild-composer/internal/blueprint"
"github.com/osbuild/osbuild-composer/internal/pipeline"
"github.com/osbuild/osbuild-composer/internal/rpmmd"
"github.com/osbuild/osbuild-composer/internal/distro/fedora30"
"github.com/osbuild/osbuild-composer/internal/distro/rhel82"
)
type Distro interface {
// Returns the name of the distro. This is the same name that was
// passed to New().
Name() string
// Returns a list of repositories from which this distribution gets its
// content.
Repositories(arch string) []rpmmd.RepoConfig
// Returns a sorted list of the output formats this distro supports.
ListOutputFormats() []string
// Returns the canonical filename and MIME type for a given output
// format. `outputFormat` must be one returned by
FilenameFromType(outputFormat string) (string, string, error)
// Returns an osbuild pipeline that generates an image in the given
// output format with all packages and customizations specified in the
// given blueprint.
Pipeline(b *blueprint.Blueprint, additionalRepos []rpmmd.RepoConfig, checksums map[string]string, outputArchitecture, outputFormat string) (*pipeline.Pipeline, error)
// Returns a osbuild runner that can be used on this distro.
Runner() string
}
type Registry struct {
distros map[string]Distro
}
func NewRegistry() *Registry {
distros := &Registry{
distros: make(map[string]Distro),
}
distros.register(fedora30.New())
distros.register(rhel82.New())
return distros
}
func (r *Registry) register(distro Distro) {
name := distro.Name()
if _, exists := r.distros[name]; exists {
panic("a distro with this name already exists: " + name)
}
r.distros[name] = distro
}
func (r *Registry) GetDistro(name string) Distro {
distro, ok := r.distros[name]
if !ok {
return nil
}
return distro
}
func (r *Registry) FromHost() (Distro, error) {
f, err := os.Open("/etc/os-release")
if err != nil {
return nil, err
}
defer f.Close()
osrelease, err := readOSRelease(f)
if err != nil {
return nil, err
}
name := osrelease["ID"] + "-" + osrelease["VERSION_ID"]
d := r.GetDistro(name)
if d == nil {
return nil, errors.New("unknown distro: " + name)
}
return d, nil
}
func readOSRelease(r io.Reader) (map[string]string, error) {
osrelease := make(map[string]string)
scanner := bufio.NewScanner(r)
for scanner.Scan() {
line := strings.TrimSpace(scanner.Text())
if len(line) == 0 {
continue
}
parts := strings.SplitN(line, "=", 2)
if len(parts) != 2 {
return nil, errors.New("readOSRelease: invalid input")
}
key := strings.TrimSpace(parts[0])
value := strings.TrimSpace(parts[1])
if value[0] == '"' {
if len(value) < 2 || value[len(value)-1] != '"' {
return nil, errors.New("readOSRelease: invalid input")
}
value = value[1 : len(value)-1]
}
osrelease[key] = value
}
return osrelease, nil
}