mirror of
https://github.com/lxc/distrobuilder.git
synced 2026-02-05 15:46:17 +01:00
183 lines
4.6 KiB
Go
183 lines
4.6 KiB
Go
package generators
|
|
|
|
import (
|
|
"fmt"
|
|
"os"
|
|
"path/filepath"
|
|
"slices"
|
|
"strings"
|
|
|
|
"github.com/lxc/incus/v6/shared/api"
|
|
incus "github.com/lxc/incus/v6/shared/util"
|
|
|
|
"github.com/lxc/distrobuilder/image"
|
|
"github.com/lxc/distrobuilder/shared"
|
|
)
|
|
|
|
type cloudInit struct {
|
|
common
|
|
}
|
|
|
|
// RunLXC disables cloud-init.
|
|
func (g *cloudInit) RunLXC(img *image.LXCImage, target shared.DefinitionTargetLXC) error {
|
|
// With OpenRC:
|
|
// Remove all symlinks to /etc/init.d/cloud-{init-local,config,init,final} in /etc/runlevels/*
|
|
fullPath := filepath.Join(g.sourceDir, "etc", "runlevels")
|
|
|
|
if incus.PathExists(fullPath) {
|
|
err := filepath.Walk(fullPath, func(path string, info os.FileInfo, err error) error {
|
|
if info.IsDir() {
|
|
return nil
|
|
}
|
|
|
|
if slices.Contains([]string{"cloud-init-local", "cloud-config", "cloud-init", "cloud-final"}, info.Name()) {
|
|
err := os.Remove(path)
|
|
if err != nil {
|
|
return fmt.Errorf("Failed to remove file %q: %w", path, err)
|
|
}
|
|
}
|
|
|
|
return nil
|
|
})
|
|
if err != nil {
|
|
return fmt.Errorf("Failed to walk file tree %q: %w", fullPath, err)
|
|
}
|
|
}
|
|
|
|
// With systemd:
|
|
path := filepath.Join(g.sourceDir, "/etc/cloud")
|
|
|
|
if !incus.PathExists(path) {
|
|
err := os.MkdirAll(path, 0o755)
|
|
if err != nil {
|
|
return fmt.Errorf("Failed to create directory %q: %w", path, err)
|
|
}
|
|
}
|
|
|
|
// Create file /etc/cloud/cloud-init.disabled
|
|
path = filepath.Join(g.sourceDir, "/etc/cloud/cloud-init.disabled")
|
|
|
|
f, err := os.Create(path)
|
|
if err != nil {
|
|
return fmt.Errorf("Failed to create file %q: %w", path, err)
|
|
}
|
|
|
|
defer f.Close()
|
|
|
|
return nil
|
|
}
|
|
|
|
// RunIncus creates cloud-init template files.
|
|
func (g *cloudInit) RunIncus(img *image.IncusImage, target shared.DefinitionTargetIncus) error {
|
|
templateDir := filepath.Join(g.cacheDir, "templates")
|
|
|
|
err := os.MkdirAll(templateDir, 0o755)
|
|
if err != nil {
|
|
return fmt.Errorf("Failed to create directory %q: %w", templateDir, err)
|
|
}
|
|
|
|
var content string
|
|
properties := make(map[string]string)
|
|
|
|
switch g.defFile.Name {
|
|
case "user-data":
|
|
content = `{%- if config_get("cloud-init.user-data", properties.default) == properties.default -%}
|
|
{{ config_get("user.user-data", properties.default) }}
|
|
{%- else -%}
|
|
{{- config_get("cloud-init.user-data", properties.default) }}
|
|
{%- endif %}
|
|
`
|
|
properties["default"] = `#cloud-config
|
|
{}`
|
|
case "meta-data":
|
|
content = `instance-id: {{ container.name }}
|
|
local-hostname: {{ container.name }}
|
|
{{ config_get("user.meta-data", "") }}
|
|
`
|
|
case "vendor-data":
|
|
content = `{%- if config_get("cloud-init.vendor-data", properties.default) == properties.default -%}
|
|
{{ config_get("user.vendor-data", properties.default) }}
|
|
{%- else -%}
|
|
{{- config_get("cloud-init.vendor-data", properties.default) }}
|
|
{%- endif %}
|
|
`
|
|
properties["default"] = `#cloud-config
|
|
{}`
|
|
case "network-config":
|
|
defaultValue := `version: 1
|
|
config:
|
|
- type: physical
|
|
name: {% if instance.type == "virtual-machine" %}enp5s0{% else %}eth0{% endif %}
|
|
subnets:
|
|
- type: dhcp
|
|
control: auto`
|
|
|
|
// Use the provided content as the new default value
|
|
if g.defFile.Content != "" {
|
|
defaultValue = g.defFile.Content
|
|
}
|
|
|
|
content = fmt.Sprintf(`{%%- if config_get("cloud-init.network-config", "") == "" -%%}
|
|
{%%- if config_get("user.network-config", "") == "" -%%}
|
|
%s
|
|
{%%- else -%%}
|
|
{{- config_get("user.network-config", "") -}}
|
|
{%%- endif -%%}
|
|
{%%- else -%%}
|
|
{{- config_get("cloud-init.network-config", "") -}}
|
|
{%%- endif %%}
|
|
`, defaultValue)
|
|
default:
|
|
return fmt.Errorf("Unknown cloud-init configuration: %s", g.defFile.Name)
|
|
}
|
|
|
|
template := fmt.Sprintf("cloud-init-%s.tpl", g.defFile.Name)
|
|
path := filepath.Join(templateDir, template)
|
|
|
|
file, err := os.Create(path)
|
|
if err != nil {
|
|
return fmt.Errorf("Failed to create file %q: %w", path, err)
|
|
}
|
|
|
|
defer file.Close()
|
|
|
|
// Use the provided content as the new default value
|
|
if g.defFile.Name != "network-config" && g.defFile.Content != "" {
|
|
properties["default"] = g.defFile.Content
|
|
}
|
|
|
|
// Append final new line if missing
|
|
if !strings.HasSuffix(content, "\n") {
|
|
content += "\n"
|
|
}
|
|
|
|
_, err = file.WriteString(content)
|
|
if err != nil {
|
|
return fmt.Errorf("Failed to write to content to %s template: %w", g.defFile.Name, err)
|
|
}
|
|
|
|
if len(g.defFile.Template.Properties) > 0 {
|
|
properties = g.defFile.Template.Properties
|
|
}
|
|
|
|
targetPath := filepath.Join("/var/lib/cloud/seed/nocloud-net", g.defFile.Name)
|
|
|
|
if g.defFile.Path != "" {
|
|
targetPath = g.defFile.Path
|
|
}
|
|
|
|
// Add to Incus templates
|
|
img.Metadata.Templates[targetPath] = &api.ImageMetadataTemplate{
|
|
Template: template,
|
|
Properties: properties,
|
|
When: []string{"create", "copy"},
|
|
}
|
|
|
|
return nil
|
|
}
|
|
|
|
// Run does nothing.
|
|
func (g *cloudInit) Run() error {
|
|
return nil
|
|
}
|