121 lines
3.5 KiB
Go
121 lines
3.5 KiB
Go
package distros
|
|
|
|
import (
|
|
"encoding/json"
|
|
"errors"
|
|
"fmt"
|
|
"io"
|
|
"net/http"
|
|
"strings"
|
|
|
|
"github.com/rs/zerolog/log"
|
|
"libguestfs.org/guestfs"
|
|
|
|
"git.csclub.uwaterloo.ca/cloud/cloudbuild/pkg/config"
|
|
)
|
|
|
|
type UbuntuTemplateManager struct {
|
|
TemplateManager
|
|
}
|
|
|
|
// NewUbuntuTemplateManager returns a UbuntuTemplateManager with the given
|
|
// config values.
|
|
func NewUbuntuTemplateManager(cfg *config.Config) *UbuntuTemplateManager {
|
|
logger := log.With().Str("distro", "ubuntu").Logger()
|
|
// The child embeds the parent, and the parent has a reference to the child
|
|
ubuntuTemplateManager := UbuntuTemplateManager{
|
|
TemplateManager{
|
|
cfg: cfg,
|
|
logger: &logger,
|
|
impl: nil,
|
|
},
|
|
}
|
|
ubuntuTemplateManager.TemplateManager.impl = &ubuntuTemplateManager
|
|
return &ubuntuTemplateManager
|
|
}
|
|
|
|
type UbuntuVersions struct {
|
|
Products map[string]struct {
|
|
Arch string `json:"arch"`
|
|
Release string `json:"release"`
|
|
ReleaseTitle string `json:"release_title"`
|
|
Version string `json:"version"`
|
|
} `json:"products"`
|
|
}
|
|
|
|
// GetLatestVersion returns the version and codename of the latest Ubuntu release.
|
|
// e.g. version = 22.04, codename = jammy
|
|
func (mgr *UbuntuTemplateManager) GetLatestVersion() (version string, codename string, err error) {
|
|
resp, err := http.Get("https://cloud-images.ubuntu.com/releases/streams/v1/com.ubuntu.cloud:released:download.json")
|
|
if err != nil {
|
|
return
|
|
}
|
|
defer resp.Body.Close()
|
|
buf, err := io.ReadAll(resp.Body)
|
|
if err != nil {
|
|
return
|
|
}
|
|
var data UbuntuVersions
|
|
if err = json.Unmarshal(buf, &data); err != nil {
|
|
return
|
|
}
|
|
for _, val := range data.Products {
|
|
if val.Arch == "amd64" && strings.HasSuffix(val.ReleaseTitle, "LTS") && val.Version > version {
|
|
version = val.Version
|
|
codename = val.Release
|
|
}
|
|
}
|
|
if version == "" {
|
|
err = errors.New("Could not find latest LTS version of Ubuntu")
|
|
}
|
|
return
|
|
}
|
|
|
|
// DownloadTemplate downloads the cloud image for the given Ubuntu codename,
|
|
// and returns the filename to which it was written.
|
|
func (mgr *UbuntuTemplateManager) DownloadTemplate(version, codename string) (path string, err error) {
|
|
filename := fmt.Sprintf("%s-server-cloudimg-amd64.img", codename)
|
|
url := fmt.Sprintf("https://cloud-images.ubuntu.com/%s/current/%s", codename, filename)
|
|
return mgr.DownloadTemplateGeneric(filename, url)
|
|
}
|
|
|
|
func (mgr *UbuntuTemplateManager) addUbuntuCloudInitSnippet(handle *guestfs.Guestfs) error {
|
|
path := "/etc/cloud/cloud.cfg.d/99_csclub_misc.cfg"
|
|
mgr.logger.Debug().Msg("Writing to " + path)
|
|
return handle.Write(path, getResource("ubuntu-cloud-init"))
|
|
}
|
|
|
|
func (mgr *UbuntuTemplateManager) disableNoisyMotdMessages(handle *guestfs.Guestfs) {
|
|
log := mgr.logger
|
|
// Setting these files to non-executable (chmod a-x) disables them
|
|
filesToDisable := []string{
|
|
"00-header",
|
|
"10-help-text",
|
|
"50-landscape-sysinfo",
|
|
//"50-motd-news",
|
|
"88-esm-announce",
|
|
}
|
|
for _, filename := range filesToDisable {
|
|
path := "/etc/update-motd.d/" + filename
|
|
log.Debug().Msg("Disabling " + path)
|
|
if err := handle.Chmod(0644, path); err != nil {
|
|
log.Warn().Err(err).Msg("Could not disable " + path)
|
|
}
|
|
}
|
|
}
|
|
|
|
func (mgr *UbuntuTemplateManager) CommandToUpdatePackageCache() []string {
|
|
return debianCommandToUpdatePackageCache()
|
|
}
|
|
|
|
func (mgr *UbuntuTemplateManager) PerformDistroSpecificModifications(handle *guestfs.Guestfs) (err error) {
|
|
if err = mgr.replaceDebianMirrorUrls(handle); err != nil {
|
|
return
|
|
}
|
|
if err = mgr.addUbuntuCloudInitSnippet(handle); err != nil {
|
|
return
|
|
}
|
|
mgr.disableNoisyMotdMessages(handle)
|
|
return
|
|
}
|