Skip to content

Commit

Permalink
stage/systemd-unit-create:add systemd-unit-create stage
Browse files Browse the repository at this point in the history
Create systemd unit using the system-unit-create stage
This new stage adds the ability to create a systemd service unit file.
It provides customization to choose the unit-type and unit-path, defaults to '/usr/lib/systemd/system/'
Filename is validated using the same rules as specified by systemd.unit(5) and they must contain the
'.service' suffix (other types of unit files are not supported). config accepts sections: `Unit`,
`Service`, `Install` and each section accepts list of options that is in accordance to systemd.service
documentation. Relavent testing is also added.

Signed-off-by: Sayan Paul <[email protected]>
  • Loading branch information
say-paul authored and bcl committed Mar 21, 2024
1 parent e069234 commit 0eb091d
Show file tree
Hide file tree
Showing 2 changed files with 131 additions and 0 deletions.
61 changes: 61 additions & 0 deletions pkg/osbuild/systemd_unit_create_stage.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
package osbuild

type serviceType string
type unitPath string

const (
Simple serviceType = "simple"
Exec serviceType = "exec"
Forking serviceType = "forking"
Oneshot serviceType = "oneshot"
Dbus serviceType = "dbus"
Notify serviceType = "notify"
NotifyReloadservice serviceType = "notify-reload"
Idle serviceType = "idle"
Etc unitPath = "etc"
Usr unitPath = "usr"
)

type Unit struct {
Description string `json:"Description,omitempty"`
DefaultDependencies bool `json:"DefaultDependencies,omitempty"`
ConditionPathExists []string `json:"ConditionPathExists,omitempty"`
ConditionPathIsDirectory []string `json:"ConditionPathIsDirectory,omitempty"`
Requires []string `json:"Requires,omitempty"`
Wants []string `json:"Wants,omitempty"`
}

type Service struct {
Type serviceType `json:"Type,omitempty"`
RemainAfterExit bool `json:"RemainAfterExit,omitempty"`
ExecStartPre []string `json:"ExecStartPre,omitempty"`
ExecStopPost []string `json:"ExecStopPost,omitempty"`
ExecStart []string `json:"ExecStart,omitempty"`
}

type Install struct {
RequiredBy []string `json:"RequiredBy,omitempty"`
WantedBy []string `json:"WantedBy,omitempty"`
}

type SystemdServiceUnit struct {
Unit *Unit `json:"Unit"`
Service *Service `json:"Service"`
Install *Install `json:"Install"`
}

type SystemdUnitCreateStageOptions struct {
Filename string `json:"filename"`
UnitType unitType `json:"unit-type,omitempty"` // unitType defined in ./systemd_unit_stage.go
UnitPath unitPath `json:"unit-path,omitempty"`
Config SystemdServiceUnit `json:"config"`
}

func (SystemdUnitCreateStageOptions) isStageOptions() {}

func NewSystemdUnitCreateStageOptions(options *SystemdUnitCreateStageOptions) *Stage {
return &Stage{
Type: "org.osbuild.systemd.unit.create",
Options: options,
}
}
70 changes: 70 additions & 0 deletions pkg/osbuild/systemd_unit_create_stage_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
package osbuild

import (
"testing"

"github.com/stretchr/testify/assert"
)

func createSystemdUnit() SystemdServiceUnit {

var unit = Unit{
Description: "Create directory and files",
ConditionPathExists: []string{"!/etc/myfile"},
ConditionPathIsDirectory: []string{"!/etc/mydir"},
Requires: []string{"dbus.service", "libvirtd.service"},
Wants: []string{"local-fs.target"},
}
var service = Service{
Type: Oneshot,
RemainAfterExit: true,
ExecStartPre: []string{"echo creating_files"},
ExecStopPost: []string{"echo done_creating_files"},
ExecStart: []string{"mkdir -p /etc/mydir", "touch /etc/myfiles"},
}

var install = Install{
RequiredBy: []string{"multi-user.target", "boot-complete.target"},
WantedBy: []string{"sshd.service"},
}

var systemdUnit = SystemdServiceUnit{
Unit: &unit,
Service: &service,
Install: &install,
}

return systemdUnit
}

func TestNewSystemdUnitCreateStage(t *testing.T) {
systemdServiceConfig := createSystemdUnit()
var options = SystemdUnitCreateStageOptions{
Filename: "create-dir-files",
Config: systemdServiceConfig,
}
expectedStage := &Stage{
Type: "org.osbuild.systemd.unit.create",
Options: &options,
}

actualStage := NewSystemdUnitCreateStageOptions(&options)
assert.Equal(t, expectedStage, actualStage)
}

func TestNewSystemdUnitCreateStageInEtc(t *testing.T) {
systemdServiceConfig := createSystemdUnit()
var options = SystemdUnitCreateStageOptions{
Filename: "create-dir-files",
Config: systemdServiceConfig,
UnitPath: Etc,
UnitType: Global,
}
expectedStage := &Stage{
Type: "org.osbuild.systemd.unit.create",
Options: &options,
}

actualStage := NewSystemdUnitCreateStageOptions(&options)
assert.Equal(t, expectedStage, actualStage)
}

0 comments on commit 0eb091d

Please sign in to comment.