Compare commits

..

No commits in common. "main" and "v0.0.2" have entirely different histories.
main ... v0.0.2

4 changed files with 19 additions and 74 deletions

View File

@ -1,21 +0,0 @@
MIT License
Copyright (c) 2022 Justin Hawkins
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.

View File

@ -1,41 +1,31 @@
# unitard - automatically deploy a systemd unit file from your application # unitard - automatically deploy a systemd unit file from your application
[![Go Reference](https://pkg.go.dev/badge/github.com/tardisx/unitard.svg)](https://pkg.go.dev/github.com/tardisx/unitard)
## Synopsis ## Synopsis
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?

View File

@ -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

View File

@ -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)
} }