Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 7 additions & 1 deletion dbus/methods.go
Original file line number Diff line number Diff line change
Expand Up @@ -194,7 +194,13 @@ func (c *Conn) StartTransientUnit(name string, mode string, properties []Propert
// unique. mode is the same as in StartUnitContext, properties contains properties
// of the unit.
func (c *Conn) StartTransientUnitContext(ctx context.Context, name string, mode string, properties []Property, ch chan<- string) (int, error) {
return c.startJob(ctx, ch, "org.freedesktop.systemd1.Manager.StartTransientUnit", name, mode, properties, make([]PropertyCollection, 0))
return c.StartTransientUnitAux(ctx, name, mode, properties, make([]PropertyCollection, 0), ch)
}

// StartTransientUnitAux is the same as StartTransientUnitContext but allows passing
// auxiliary units in the aux parameter.
func (c *Conn) StartTransientUnitAux(ctx context.Context, name string, mode string, properties []Property, aux []PropertyCollection, ch chan<- string) (int, error) {
return c.startJob(ctx, ch, "org.freedesktop.systemd1.Manager.StartTransientUnit", name, mode, properties, aux)
}

// Deprecated: use [KillUnitWithTarget] instead.
Expand Down
91 changes: 91 additions & 0 deletions dbus/methods_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -128,6 +128,28 @@ func runStartTrUnit(t *testing.T, conn *Conn, trTarget TrUnitProp) error {
return nil
}

func runStartTrUnitWithAux(t *testing.T, conn *Conn, trTarget TrUnitProp, trAux TrUnitProp) error {
reschan := make(chan string)
_, err := conn.StartTransientUnitAux(
context.TODO(), // Switch to t.Context once go < 1.24 is not supported.
trTarget.name,
"replace",
trTarget.props,
[]PropertyCollection{{Name: trAux.name, Properties: trAux.props}},
reschan,
)
if err != nil {
return err
}

job := <-reschan
if job != "done" {
return fmt.Errorf("Job is not done: %s", job)
}

return nil
}

func runStopUnit(t *testing.T, conn *Conn, trTarget TrUnitProp) error {
reschan := make(chan string)
_, err := conn.StopUnit(trTarget.name, "replace", reschan)
Expand Down Expand Up @@ -850,6 +872,11 @@ func TestSetUnitProperties(t *testing.T) {
}
}

type TrUnitSocketListenProp struct {
Type string
Address string
}

// Ensure that oneshot transient unit starting and stopping works.
func TestStartStopTransientUnitAll(t *testing.T) {
testCases := []struct {
Expand Down Expand Up @@ -991,6 +1018,29 @@ func TestStartStopTransientUnitAll(t *testing.T) {
},
checkFunc: checkTransientUnitConflicts,
},
{
trTarget: TrUnitProp{
name: "testing-aux-unit.socket",
props: []Property{
{
Name: "Listen",
Value: dbus.MakeVariant([]TrUnitSocketListenProp{
{
Type: "Stream",
Address: path.Join(t.TempDir(), "go-systemd-test.sock"),
},
}),
},
},
},
trDep: TrUnitProp{
name: "testing-aux-unit.service",
props: []Property{
PropExecStart([]string{"/bin/sleep", "400"}, false),
},
},
checkFunc: checkTransientUnitAux,
},
}

for i, tt := range testCases {
Expand Down Expand Up @@ -1332,6 +1382,47 @@ func checkTransientUnitConflicts(t *testing.T, trTarget TrUnitProp, trDep TrUnit
return nil
}

func checkTransientUnitAux(t *testing.T, trTarget TrUnitProp, trDep TrUnitProp) error {
conn := setupConn(t)

// Start the target unit with dep as auxiliary unit
err := runStartTrUnitWithAux(t, conn, trTarget, trDep)
if err != nil {
return err
}

target := getUnitStatusSingle(conn, trTarget.name)
if target == nil || target.ActiveState != "active" {
return fmt.Errorf("Test unit %s not active, should be active", trTarget.name)
}

aux := getUnitStatusSingle(conn, trDep.name)
if aux == nil {
return fmt.Errorf("Test unit %s not found", trDep.name)
}

if aux.ActiveState == "active" {
return fmt.Errorf("Test unit %s active, should be inactive", trDep.name)
}

err = runStopUnit(t, conn, trTarget)
if err != nil {
return err
}

target = getUnitStatusSingle(conn, trTarget.name)
if target != nil {
return fmt.Errorf("Test unit %s found in list, should be stopped", trTarget.name)
}

aux = getUnitStatusSingle(conn, trDep.name)
if aux != nil {
return fmt.Errorf("Test unit %s found in list, should be stopped", trTarget.name)
}

return nil
}

func runSleep(t *testing.T) uint32 {
cmd := exec.Command("/bin/sleep", "400")
err := cmd.Start()
Expand Down