Compare commits
No commits in common. "main" and "v0.0.4" have entirely different histories.
36
README.md
36
README.md
@ -7,35 +7,27 @@
|
|||||||
import "github.com/tardisx/unitard"
|
import "github.com/tardisx/unitard"
|
||||||
|
|
||||||
func main() {
|
func main() {
|
||||||
appName := "coolapp"
|
appName := "coolapp"
|
||||||
if deploy {
|
if deploy {
|
||||||
// error checking ignored for this example
|
unit, _ := unitard.NewUnit(appName)
|
||||||
unit, _ := unitard.NewUnit(appName)
|
unit.Deploy()
|
||||||
unit.Deploy()
|
os.Exit(0)
|
||||||
os.Exit(0)
|
}
|
||||||
}
|
// rest of your application here
|
||||||
// rest of your application here
|
|
||||||
}
|
}
|
||||||
|
|
||||||
## What it does
|
## What it does
|
||||||
|
|
||||||
This package provides a simple interface to automatically creating and enabling a
|
`Deploy()` automatically creates a systemd unit file, reloads the systemd daemon
|
||||||
systemd "user unit" service, as part of your single-binary deployment.
|
so it can use it, enables the unit (so it starts on boot) and starts the service
|
||||||
|
|
||||||
The `Deploy()` function creates the systemd unit file, reloads the systemd daemon
|
|
||||||
so it reads it, enables the unit (to start on boot) and starts the service
|
|
||||||
running.
|
running.
|
||||||
|
|
||||||
Copy your executable to "somewhere" on your target system, run it with `-deploy`
|
This means you can have a single binary deployment. Copy your executable to "somewhere"
|
||||||
(or however you have enabled the call to `Deploy()`) and your application starts
|
on your target system, run it with `-deploy` (or however you have enabled the call to `Deploy()`)
|
||||||
running in the background and will restart on boot.
|
and your application starts running in the background, and will restart on boot.
|
||||||
|
|
||||||
There is also an `Undeploy()` func, which you should of course provide as an option
|
There is also an `Undeploy()` func, which you should of course
|
||||||
to your users. It stops the running service, removes the unit file and reloads the
|
provide as an option to your users. It stops the running service, removes the unit file and restarts systemd.
|
||||||
systemd daemon.
|
|
||||||
|
|
||||||
While it does shell out to call the `systemctl` tool, this does mean this package
|
|
||||||
adds no new non-core dependencies to your project.
|
|
||||||
|
|
||||||
## What's with the name?
|
## What's with the name?
|
||||||
|
|
||||||
|
@ -5,7 +5,7 @@ Description={{ .description }}
|
|||||||
|
|
||||||
[Service]
|
[Service]
|
||||||
WorkingDirectory={{ .workingDirectory }}
|
WorkingDirectory={{ .workingDirectory }}
|
||||||
ExecStart={{ .execStart }} {{ .execStartArgs }}
|
ExecStart={{ .execStart }}
|
||||||
|
|
||||||
[Install]
|
[Install]
|
||||||
WantedBy=default.target
|
WantedBy=default.target
|
32
unitard.go
32
unitard.go
@ -4,7 +4,6 @@ package unitard
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"embed"
|
"embed"
|
||||||
"errors"
|
|
||||||
"fmt"
|
"fmt"
|
||||||
"io"
|
"io"
|
||||||
"os"
|
"os"
|
||||||
@ -22,31 +21,12 @@ type Unit struct {
|
|||||||
name string
|
name string
|
||||||
binary string
|
binary string
|
||||||
binaryPath string
|
binaryPath string
|
||||||
binaryArgs string
|
|
||||||
|
|
||||||
systemCtlPath string // path to systemctl command
|
systemCtlPath string // path to systemctl command
|
||||||
unitFilePath string
|
unitFilePath string
|
||||||
}
|
}
|
||||||
|
|
||||||
type UnitOpts interface {
|
type UnitOpts interface{}
|
||||||
Apply(u *Unit) error
|
|
||||||
}
|
|
||||||
|
|
||||||
// OptProgramArgs allows you to add an arguments to the invocation of the program
|
|
||||||
type OptProgramArgs struct {
|
|
||||||
Args string // Program args
|
|
||||||
}
|
|
||||||
|
|
||||||
func (o OptProgramArgs) Apply(u *Unit) error {
|
|
||||||
if o.Args == "" {
|
|
||||||
return errors.New("can't set an empty args option")
|
|
||||||
}
|
|
||||||
if u.binaryArgs != "" {
|
|
||||||
return errors.New("args were already set - use OptProgramArgs only once")
|
|
||||||
}
|
|
||||||
u.binaryArgs = o.Args
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// NewUnit creates a new systemd unit representation, with a particular name.
|
// NewUnit creates a new systemd unit representation, with a particular name.
|
||||||
// No changes will be made to the system configuration until Deploy or Undeploy
|
// No changes will be made to the system configuration until Deploy or Undeploy
|
||||||
@ -66,11 +46,8 @@ func NewUnit(unitName string, unitOpts ...UnitOpts) (Unit, error) {
|
|||||||
binaryPath: path,
|
binaryPath: path,
|
||||||
}
|
}
|
||||||
|
|
||||||
for _, opt := range unitOpts {
|
if len(unitOpts) > 0 {
|
||||||
err := opt.Apply(&u)
|
return Unit{}, fmt.Errorf("sorry, UnitOpts are not yet supported")
|
||||||
if err != nil {
|
|
||||||
return Unit{}, fmt.Errorf("bad option: %s", err)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
err := u.setupEnvironment()
|
err := u.setupEnvironment()
|
||||||
@ -120,7 +97,6 @@ func (u Unit) writeTemplate(f io.Writer) error {
|
|||||||
data := map[string]string{
|
data := map[string]string{
|
||||||
"description": u.name,
|
"description": u.name,
|
||||||
"execStart": u.binary,
|
"execStart": u.binary,
|
||||||
"execStartArgs": u.binaryArgs,
|
|
||||||
"workingDirectory": u.binaryPath,
|
"workingDirectory": u.binaryPath,
|
||||||
}
|
}
|
||||||
err = t.ExecuteTemplate(f, "basic.service", data)
|
err = t.ExecuteTemplate(f, "basic.service", data)
|
||||||
@ -237,7 +213,7 @@ func (u *Unit) setupEnvironment() error {
|
|||||||
"user",
|
"user",
|
||||||
)
|
)
|
||||||
|
|
||||||
err = os.MkdirAll(unitFileDirectory, 0700)
|
err = os.MkdirAll(unitFileDirectory, 0777)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("cannot create the user systemd path '%s': %s", unitFileDirectory, err)
|
return fmt.Errorf("cannot create the user systemd path '%s': %s", unitFileDirectory, err)
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user