systemdeps

package module
Version: v1.0.0 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Apr 21, 2019 License: MIT Imports: 8 Imported by: 0

README

systemdeps

Utility library that manages systemd service dependencies using drop-in configuration files instead of modifying the installed unit file.

Service dependencies can be stored in a JSON file so that it is similar to defining services and depends_on links in docker compose.

For example, the base services can be installed using generic Ansible roles then independently ordered per VM based on it's needs.

Optionally, can create a top-level application to manage all underlying processes using standard systemd commands: systemctl [start | stop | restart | enable | disable] application.target

References

https://www.freedesktop.org/software/systemd/man/systemd.unit.html https://www.freedesktop.org/software/systemd/man/systemd.target.html

Documentation: https://godoc.org/github.com/bisrael8191/systemdeps

Use as a library

import (
	"fmt"
    "log"
    "github.com/bisrael8191/systemdeps"
)

// Creates a top-level systemd target that controls all sub-processes
// and correctly orders all of the process dependencies.
func Example() {
    // Load JSON process dependencies 
    // (optional, can also create the Process structs manually, see systemdeps_test.go)
	processes, err := ReadDependencyFile("dependencies.json")
	if err != nil {
		log.Fatal(err)
		return
	}

	// Check process dependencies for cycles
	cycle, graph := HasCycle(processes)
	if cycle {
		fmt.Println("Cycle found between", graph.CycleStart, "and", graph.CycleEnd)
	} else {
		// No cycles found, create required drop-in files and configure systemd
		err := ConfigureSystemd("/etc/systemd/system", "my-test-app", true, processes)
		if err != nil {
			log.Fatal(err)
		}
    }
}

Run as application

Build/Install
  • Get dependencies: go get
  • Install to $GOPATH/bin: go install bin/entry.go
Run
  • Help: $GOBIN/entry -h
Usage of entry:
  -app string
        create a top-level application to manage all services
  -config string
        path of dependency file (default "dependencies.json")
  -dryrun
        don't modify system, print out modified files
  -systemdpath string
        systemd path (default "/etc/systemd/system/")
  • Test (output files without modifying systemd): $GOBIN/entry -config dependencies.json -app my-test-app -dryrun

  • Dependencies with top-level app: $GOBIN/entry -config dependencies.json -app my-test-app

  • Dependencies without top-level app: $GOBIN/entry -config dependencies.json

  • Use user-space systemd: $GOBIN/entry -config dependencies.json -app my-test-app -systemdpath ~/.config/systemd/user/

Documentation

Overview

Utility library that manages systemd service dependencies using drop-in configuration files instead of modifying the installed unit file.

Service dependencies can be stored in a JSON file so that it is similar to defining services and depends_on links in docker compose.

For example, the base services can be installed using generic Ansible roles then independently ordered per VM based on it's needs.

Optionally, can create a top-level application to manage all underlying processes using standard systemd commands:

systemctl [start | stop | restart | enable | disable] application.target

References

https://www.freedesktop.org/software/systemd/man/systemd.unit.html https://www.freedesktop.org/software/systemd/man/systemd.target.html

Example

Sample use of the systemdeps library. Creates a top-level systemd target that controls all sub-processes and correctly orders all of the process dependencies.

// Load JSON process dependencies
// (optional, can also create the Process structs manually, see systemdeps_test.go)
processes, err := ReadDependencyFile("dependencies.json")
if err != nil {
	log.Fatal(err)
	return
}

// Check process dependencies for cycles
cycle, graph := HasCycle(processes)
if cycle {
	fmt.Println("Cycle found between", graph.CycleStart, "and", graph.CycleEnd)
} else {
	// No cycles found, create required drop-in files and configure systemd
	err := ConfigureSystemd("/etc/systemd/system", "my-test-app", true, processes)
	if err != nil {
		log.Fatal(err)
	}
}
Output:

##### /etc/systemd/system/my-test-app.target #####
[Unit]
Description=My-Test-App top level service

[Install]
WantedBy=multi-user.target

##########

##### /etc/systemd/system/postgresql-example.service.d/dependencies.conf #####
[Install]
WantedBy=my-test-app.target

[Unit]
PartOf=my-test-app.target
Wants=my-test-app.target docker.service
After=my-test-app.target docker.service

##########

##### /etc/systemd/system/influxdb-example.service.d/dependencies.conf #####
[Install]
WantedBy=my-test-app.target

[Unit]
PartOf=my-test-app.target
Wants=my-test-app.target docker.service
After=my-test-app.target docker.service

##########

##### /etc/systemd/system/process1.service.d/dependencies.conf #####
[Install]
WantedBy=my-test-app.target

[Unit]
PartOf=my-test-app.target
Wants=my-test-app.target postgresql-example.service influxdb-example.service
After=my-test-app.target postgresql-example.service influxdb-example.service

##########

##### /etc/systemd/system/process2.service.d/dependencies.conf #####
[Install]
WantedBy=my-test-app.target

[Unit]
PartOf=my-test-app.target
Wants=my-test-app.target postgresql.service
After=my-test-app.target postgresql.service

##########

##### /etc/systemd/system/process3.service.d/dependencies.conf #####
[Install]
WantedBy=my-test-app.target

[Unit]
PartOf=my-test-app.target
Wants=my-test-app.target process1.service
After=my-test-app.target process1.service

##########

##### /etc/systemd/system/process4.service.d/dependencies.conf #####
[Install]
WantedBy=my-test-app.target

[Unit]
PartOf=my-test-app.target
Wants=my-test-app.target process3.service
After=my-test-app.target process3.service

##########

##### /etc/systemd/system/process5.service.d/dependencies.conf #####
[Install]
WantedBy=my-test-app.target

[Unit]
PartOf=my-test-app.target
Wants=my-test-app.target process4.service
After=my-test-app.target process4.service

##########

##### /etc/systemd/system/process6.service.d/dependencies.conf #####
[Install]
WantedBy=my-test-app.target

[Unit]
PartOf=my-test-app.target
Wants=my-test-app.target process5.service postgresql-example.service influxdb-example.service
After=my-test-app.target process5.service postgresql-example.service influxdb-example.service

##########

Index

Examples

Constants

View Source
const (
	UNSEEN = iota
	EXPLORING
	DONE
)

Used for finding cycles in DFS. Similar to the DFS Topological Sort Algorithm (https://en.wikipedia.org/wiki/Topological_sorting#Depth-first_search).

Not meant to be used directly by users.

Variables

This section is empty.

Functions

func ConfigureSystemd

func ConfigureSystemd(systemdPath string, appName string, dryRun bool, processes *Processes) error

Configure all of the systemd drop-ins based on a non-cyclic list of processes. If dry run flag is set, don't write/modify any files or make any systemd calls.

Types

type Process

type Process struct {
	Name         string   `json:"name"`
	Dependencies []string `json:"dependencies"`
}

Representation of a process and it's dependencies.

type Processes

type Processes struct {
	Processes []Process `json:"processes"`
}

List of system processes.

func ReadDependencyFile

func ReadDependencyFile(filename string) (*Processes, error)

Read a JSON file and return the Processes struct.

type SystemGraph

type SystemGraph struct {
	HasCycle   bool
	CycleStart string
	CycleEnd   string
	// contains filtered or unexported fields
}

System graph representation.

func HasCycle

func HasCycle(processes *Processes) (bool, *SystemGraph)

Check if an array of processes has any dependency cycles.

func (*SystemGraph) PrintGraph

func (g *SystemGraph) PrintGraph()

Helper function to print the structure.

type Unit

type Unit struct {
	// contains filtered or unexported fields
}

Systemd Unit directed graph structure. Unit is the vertex, requires become the edges in the graph.

func (Unit) String

func (u Unit) String() string

type UnitFile

type UnitFile struct {
	Options []*unit.UnitOption
}

Represent an entire systemd unit file.

func (*UnitFile) Bytes

func (u *UnitFile) Bytes() []byte

Output unit file as a serialized byte array.

func (*UnitFile) String

func (u *UnitFile) String() string

Output unit file as a string.

Directories

Path Synopsis

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
t or T : Toggle theme light dark auto
y or Y : Canonical URL