cloudbuild/pkg/distros/almalinux.go

140 lines
3.9 KiB
Go

package distros
import (
"errors"
"fmt"
"math"
"net/http"
"regexp"
"strconv"
"github.com/rs/zerolog/log"
"golang.org/x/net/html"
"libguestfs.org/guestfs"
"git.csclub.uwaterloo.ca/cloud/cloudbuild/pkg/config"
)
// TODO: reduce code duplication with FedoraTemplateManager
type AlmaLinuxTemplateManager struct {
TemplateManager
}
// NewAlmaLinuxTemplateManager returns a AlmaLinuxTemplateManager with the given
// config values.
func NewAlmaLinuxTemplateManager(cfg *config.Config) *AlmaLinuxTemplateManager {
logger := log.With().Str("distro", "almalinux").Logger()
almaLinuxTemplateManager := AlmaLinuxTemplateManager{
TemplateManager{
cfg: cfg,
logger: &logger,
impl: nil,
},
}
almaLinuxTemplateManager.TemplateManager.impl = &almaLinuxTemplateManager
return &almaLinuxTemplateManager
}
var floatNumberSlashPattern *regexp.Regexp = regexp.MustCompile("^\\d+(\\.\\d)?/$")
func getMaxFloatVersionFromHtml(node *html.Node, maxVersion *float64) {
if isHyperlink(node) {
text := node.FirstChild.Data
if numberSlashPattern.FindString(text) != "" {
version, _ := strconv.ParseFloat(text[:len(text)-1], 64)
if version > *maxVersion {
*maxVersion = version
}
}
return
}
for c := node.FirstChild; c != nil; c = c.NextSibling {
getMaxFloatVersionFromHtml(c, maxVersion)
}
}
func (mgr *AlmaLinuxTemplateManager) GetLatestVersion() (version string, codename string, err error) {
resp, err := http.Get("https://mirror.csclub.uwaterloo.ca/almalinux/")
if err != nil {
return
}
defer resp.Body.Close()
node, err := html.Parse(resp.Body)
if err != nil {
return
}
var floatVersion float64
getMaxFloatVersionFromHtml(node, &floatVersion)
if floatVersion == 0 {
err = errors.New("Could not determine latest AlmaLinux version from HTML")
} else {
version = strconv.FormatFloat(floatVersion, 'f', -1, 64)
// AlmaLinux doesn't have codenames, only numbered versions
codename = version
}
return
}
func (mgr *AlmaLinuxTemplateManager) DownloadTemplate(codename string) (path string, err error) {
// TODO: REMOVE THIS
//if true {
// return "AlmaLinux-9-GenericCloud-latest.x86_64.qcow2", nil
//}
version := codename
floatVersion, err := strconv.ParseFloat(version, 64)
if err != nil {
return
}
majorVersion := int(math.Floor(floatVersion))
filename := fmt.Sprintf("AlmaLinux-%d-GenericCloud-latest.x86_64.qcow2", majorVersion)
url := fmt.Sprintf("https://mirror.csclub.uwaterloo.ca/almalinux/%s/cloud/x86_64/images/%s", version, filename)
return mgr.DownloadTemplateGeneric(filename, url)
}
func (mgr *AlmaLinuxTemplateManager) GetIpv6ScriptsTemplateData() map[string]string {
return map[string]string{
"networkService": "NetworkManager.service",
"networkTarget": "network-online.target",
}
}
func (mgr *AlmaLinuxTemplateManager) addCloudInitSnippet(handle *guestfs.Guestfs) error {
path := "/etc/cloud/cloud.cfg.d/99_csclub.cfg"
mgr.logger.Debug().Msg("Writing to " + path)
return handle.Write(path, getResource("fedora-cloud-init"))
}
func (mgr *AlmaLinuxTemplateManager) HasSELinuxEnabled() bool {
return true
}
var almaLinuxYumRepoBaseUrlPattern *regexp.Regexp = regexp.MustCompile(
"^(?P<scheme>https?://)[A-Za-z0-9./-]+(?P<path>/almalinux/\\$releasever/[A-Za-z0-9./$-]+)$",
)
func (mgr *AlmaLinuxTemplateManager) transformAlmaLinuxYumRepoBaseUrl(url string) string {
submatches := almaLinuxYumRepoBaseUrlPattern.FindStringSubmatch(url)
if submatches != nil {
scheme, path := submatches[1], submatches[2]
url = scheme + mgr.cfg.MirrorHost + path
}
return url
}
func (mgr *AlmaLinuxTemplateManager) PerformDistroSpecificModifications(handle *guestfs.Guestfs) (err error) {
if err = mgr.setChronyOptions(handle, "/etc/chrony.conf"); err != nil {
return
}
if err = mgr.setNetworkManagerOptions(handle); err != nil {
return
}
if err = mgr.addCloudInitSnippet(handle); err != nil {
return
}
if err = mgr.replaceYumRepoMirrorUrls(handle, mgr.transformAlmaLinuxYumRepoBaseUrl); err != nil {
return
}
return
}