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>
122 lines
2.9 KiB
Go
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
|
|
}
|