Skip to content

Commit 124d391

Browse files
committed
dbus: added new dbus methods
implemented new dbus methods: * ListUnitsFiltered * ListUnitsByPatterns * ListUnitsByNames * ListUnitFilesByPatterns refactored legacy ListUnits and ListUnitFiles functions
1 parent 1d9051f commit 124d391

File tree

2 files changed

+282
-8
lines changed

2 files changed

+282
-8
lines changed

dbus/methods.go

Lines changed: 45 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -239,12 +239,11 @@ type UnitStatus struct {
239239
JobPath dbus.ObjectPath // The job object path
240240
}
241241

242-
// ListUnits returns an array with all currently loaded units. Note that
243-
// units may be known by multiple names at the same time, and hence there might
244-
// be more unit names loaded than actual units behind them.
245-
func (c *Conn) ListUnits() ([]UnitStatus, error) {
242+
type storeFunc func(retvalues ...interface{}) error
243+
244+
func (c *Conn) listUnitsInternal(f storeFunc) ([]UnitStatus, error) {
246245
result := make([][]interface{}, 0)
247-
err := c.sysobj.Call("org.freedesktop.systemd1.Manager.ListUnits", 0).Store(&result)
246+
err := f(&result)
248247
if err != nil {
249248
return nil, err
250249
}
@@ -268,15 +267,43 @@ func (c *Conn) ListUnits() ([]UnitStatus, error) {
268267
return status, nil
269268
}
270269

270+
// ListUnits returns an array with all currently loaded units. Note that
271+
// units may be known by multiple names at the same time, and hence there might
272+
// be more unit names loaded than actual units behind them.
273+
func (c *Conn) ListUnits() ([]UnitStatus, error) {
274+
return c.listUnitsInternal(c.sysobj.Call("org.freedesktop.systemd1.Manager.ListUnits", 0).Store)
275+
}
276+
277+
// ListUnitsFiltered returns an array with units filtered by state.
278+
// It takes a list of units' statuses to filter.
279+
func (c *Conn) ListUnitsFiltered(states []string) ([]UnitStatus, error) {
280+
return c.listUnitsInternal(c.sysobj.Call("org.freedesktop.systemd1.Manager.ListUnitsFiltered", 0, states).Store)
281+
}
282+
283+
// ListUnitsByPatterns returns an array with units.
284+
// It takes a list of units' statuses and names to filter.
285+
// Note that units may be known by multiple names at the same time,
286+
// and hence there might be more unit names loaded than actual units behind them.
287+
func (c *Conn) ListUnitsByPatterns(states []string, patterns []string) ([]UnitStatus, error) {
288+
return c.listUnitsInternal(c.sysobj.Call("org.freedesktop.systemd1.Manager.ListUnitsByPatterns", 0, states, patterns).Store)
289+
}
290+
291+
// ListUnitsByNames returns an array with units. It takes a list of units'
292+
// names and returns an UnitStatus array. Comparing to ListUnitsByPatterns
293+
// method, this method returns statuses even for inactive or non-existing
294+
// units. Input array should contain exact unit names, but not patterns.
295+
func (c *Conn) ListUnitsByNames(units []string) ([]UnitStatus, error) {
296+
return c.listUnitsInternal(c.sysobj.Call("org.freedesktop.systemd1.Manager.ListUnitsByNames", 0, units).Store)
297+
}
298+
271299
type UnitFile struct {
272300
Path string
273301
Type string
274302
}
275303

276-
// ListUnitFiles returns an array of all available units on disk.
277-
func (c *Conn) ListUnitFiles() ([]UnitFile, error) {
304+
func (c *Conn) listUnitFilesInternal(f storeFunc) ([]UnitFile, error) {
278305
result := make([][]interface{}, 0)
279-
err := c.sysobj.Call("org.freedesktop.systemd1.Manager.ListUnitFiles", 0).Store(&result)
306+
err := f(&result)
280307
if err != nil {
281308
return nil, err
282309
}
@@ -300,6 +327,16 @@ func (c *Conn) ListUnitFiles() ([]UnitFile, error) {
300327
return files, nil
301328
}
302329

330+
// ListUnitFiles returns an array of all available units on disk.
331+
func (c *Conn) ListUnitFiles() ([]UnitFile, error) {
332+
return c.listUnitFilesInternal(c.sysobj.Call("org.freedesktop.systemd1.Manager.ListUnitFiles", 0).Store)
333+
}
334+
335+
// ListUnitFilesByPatterns returns an array of all available units on disk matched the patterns.
336+
func (c *Conn) ListUnitFilesByPatterns(states []string, patterns []string) ([]UnitFile, error) {
337+
return c.listUnitFilesInternal(c.sysobj.Call("org.freedesktop.systemd1.Manager.ListUnitFilesByPatterns", 0, states, patterns).Store)
338+
}
339+
303340
type LinkUnitFileChange EnableUnitFileChange
304341

305342
// LinkUnitFiles() links unit files (that are located outside of the

dbus/methods_test.go

Lines changed: 237 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ import (
1818
"fmt"
1919
"math/rand"
2020
"os"
21+
"path"
2122
"path/filepath"
2223
"reflect"
2324
"testing"
@@ -96,6 +97,7 @@ func TestStartStopUnit(t *testing.T) {
9697
for _, u := range units {
9798
if u.Name == target {
9899
unit = &u
100+
break
99101
}
100102
}
101103

@@ -122,6 +124,7 @@ func TestStartStopUnit(t *testing.T) {
122124
for _, u := range units {
123125
if u.Name == target {
124126
unit = &u
127+
break
125128
}
126129
}
127130

@@ -130,6 +133,238 @@ func TestStartStopUnit(t *testing.T) {
130133
}
131134
}
132135

136+
// Ensure that ListUnitsByNames works.
137+
func TestListUnitsByNames(t *testing.T) {
138+
target1 := "systemd-journald.service"
139+
target2 := "unexisting.service"
140+
141+
conn := setupConn(t)
142+
143+
units, err := conn.ListUnitsByNames([]string{target1, target2})
144+
145+
if err != nil {
146+
t.Fatal(err)
147+
}
148+
149+
var unit *UnitStatus
150+
for _, u := range units {
151+
if u.Name == target1 {
152+
unit = &u
153+
break
154+
}
155+
}
156+
157+
if unit == nil {
158+
t.Fatalf("%s unit not found in list", target1)
159+
}
160+
161+
if unit.ActiveState != "active" {
162+
t.Fatalf("%s unit should be active but it is %s", target1, unit.ActiveState)
163+
}
164+
165+
unit = nil
166+
for _, u := range units {
167+
if u.Name == target2 {
168+
unit = &u
169+
break
170+
}
171+
}
172+
173+
if unit == nil {
174+
t.Fatalf("Unexisting test unit not found in list")
175+
}
176+
177+
if unit.ActiveState != "inactive" {
178+
t.Fatalf("Test unit should be inactive")
179+
}
180+
}
181+
182+
// Ensure that ListUnitsByPatterns works.
183+
func TestListUnitsByPatterns(t *testing.T) {
184+
target1 := "systemd-journald.service"
185+
target2 := "unexisting.service"
186+
187+
conn := setupConn(t)
188+
189+
units, err := conn.ListUnitsByPatterns([]string{}, []string{"systemd-journald*", target2})
190+
191+
if err != nil {
192+
t.Fatal(err)
193+
}
194+
195+
var unit *UnitStatus
196+
for _, u := range units {
197+
if u.Name == target1 {
198+
unit = &u
199+
break
200+
}
201+
}
202+
203+
if unit == nil {
204+
t.Fatalf("%s unit not found in list", target1)
205+
}
206+
207+
if unit.ActiveState != "active" {
208+
t.Fatalf("Test unit should be active")
209+
}
210+
211+
unit = nil
212+
for _, u := range units {
213+
if u.Name == target2 {
214+
unit = &u
215+
break
216+
}
217+
}
218+
219+
if unit != nil {
220+
t.Fatalf("Unexisting test unit found in list")
221+
}
222+
}
223+
224+
// Ensure that ListUnitsFiltered works.
225+
func TestListUnitsFiltered(t *testing.T) {
226+
target := "systemd-journald.service"
227+
228+
conn := setupConn(t)
229+
230+
units, err := conn.ListUnitsFiltered([]string{"active"})
231+
232+
if err != nil {
233+
t.Fatal(err)
234+
}
235+
236+
var unit *UnitStatus
237+
for _, u := range units {
238+
if u.Name == target {
239+
unit = &u
240+
break
241+
}
242+
}
243+
244+
if unit == nil {
245+
t.Fatalf("%s unit not found in list", target)
246+
}
247+
248+
if unit.ActiveState != "active" {
249+
t.Fatalf("Test unit should be active")
250+
}
251+
252+
units, err = conn.ListUnitsFiltered([]string{"inactive"})
253+
254+
if err != nil {
255+
t.Fatal(err)
256+
}
257+
258+
unit = nil
259+
for _, u := range units {
260+
if u.Name == target {
261+
unit = &u
262+
break
263+
}
264+
}
265+
266+
if unit != nil {
267+
t.Fatalf("Inactive unit should not be found in list")
268+
}
269+
}
270+
271+
// Ensure that ListUnitFilesByPatterns works.
272+
func TestListUnitFilesByPatterns(t *testing.T) {
273+
target1 := "systemd-journald.service"
274+
target2 := "exit.target"
275+
276+
conn := setupConn(t)
277+
278+
units, err := conn.ListUnitFilesByPatterns([]string{"static"}, []string{"systemd-journald*", target2})
279+
280+
if err != nil {
281+
t.Fatal(err)
282+
}
283+
284+
var unit *UnitFile
285+
for _, u := range units {
286+
if path.Base(u.Path) == target1 {
287+
unit = &u
288+
break
289+
}
290+
}
291+
292+
if unit == nil {
293+
t.Fatalf("%s unit not found in list", target1)
294+
}
295+
296+
if unit.Type != "static" {
297+
t.Fatalf("Test unit file should be static")
298+
}
299+
300+
units, err = conn.ListUnitFilesByPatterns([]string{"disabled"}, []string{"systemd-journald*", target2})
301+
302+
if err != nil {
303+
t.Fatal(err)
304+
}
305+
306+
unit = nil
307+
for _, u := range units {
308+
if path.Base(u.Path) == target2 {
309+
unit = &u
310+
break
311+
}
312+
}
313+
314+
if unit == nil {
315+
t.Fatalf("%s unit not found in list", target2)
316+
}
317+
318+
if unit.Type != "disabled" {
319+
t.Fatalf("%s unit file should be disabled", target2)
320+
}
321+
}
322+
323+
func TestListUnitFiles(t *testing.T) {
324+
target1 := "systemd-journald.service"
325+
target2 := "exit.target"
326+
327+
conn := setupConn(t)
328+
329+
units, err := conn.ListUnitFiles()
330+
331+
if err != nil {
332+
t.Fatal(err)
333+
}
334+
335+
var unit *UnitFile
336+
for _, u := range units {
337+
if path.Base(u.Path) == target1 {
338+
unit = &u
339+
break
340+
}
341+
}
342+
343+
if unit == nil {
344+
t.Fatalf("%s unit not found in list", target1)
345+
}
346+
347+
if unit.Type != "static" {
348+
t.Fatalf("Test unit file should be static")
349+
}
350+
351+
unit = nil
352+
for _, u := range units {
353+
if path.Base(u.Path) == target2 {
354+
unit = &u
355+
break
356+
}
357+
}
358+
359+
if unit == nil {
360+
t.Fatalf("%s unit not found in list", target2)
361+
}
362+
363+
if unit.Type != "disabled" {
364+
t.Fatalf("%s unit file should be disabled", target2)
365+
}
366+
}
367+
133368
// Enables a unit and then immediately tears it down
134369
func TestEnableDisableUnit(t *testing.T) {
135370
target := "enable-disable.service"
@@ -302,6 +537,7 @@ func TestStartStopTransientUnit(t *testing.T) {
302537
for _, u := range units {
303538
if u.Name == target {
304539
unit = &u
540+
break
305541
}
306542
}
307543

@@ -328,6 +564,7 @@ func TestStartStopTransientUnit(t *testing.T) {
328564
for _, u := range units {
329565
if u.Name == target {
330566
unit = &u
567+
break
331568
}
332569
}
333570

0 commit comments

Comments
 (0)