119 lines
2.6 KiB
Go
119 lines
2.6 KiB
Go
package budget
|
|
|
|
import (
|
|
"fmt"
|
|
"io"
|
|
"strings"
|
|
)
|
|
|
|
type application struct {
|
|
config config
|
|
paths paths
|
|
ctl unitCtl
|
|
run func(...string) error
|
|
out io.Writer
|
|
}
|
|
|
|
func (a application) apply() error {
|
|
files, err := a.config.render()
|
|
if err != nil {
|
|
return err
|
|
}
|
|
if err := writeFiles(a.paths, files); err != nil {
|
|
return err
|
|
}
|
|
if err := a.run("daemon-reload"); err != nil {
|
|
return err
|
|
}
|
|
units, err := a.ctl.Units()
|
|
if err != nil {
|
|
return err
|
|
}
|
|
for _, unit := range units {
|
|
name := a.config.activeProfile(unit)
|
|
if name == "" || unit.Active != "active" {
|
|
continue
|
|
}
|
|
values, err := a.config.properties(name)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
if err := a.ctl.Set(unit.Name, values); err != nil {
|
|
return err
|
|
}
|
|
}
|
|
if err := a.run("enable", "budget.service"); err != nil {
|
|
return err
|
|
}
|
|
if err := a.run("restart", "budget.service"); err != nil {
|
|
return err
|
|
}
|
|
_, err = fmt.Fprintf(a.out, "Applied %d resource configuration files\n", len(files))
|
|
return err
|
|
}
|
|
|
|
func selectUnits(c config, units []unit, target string) []string {
|
|
selected := map[string]bool{}
|
|
if strings.HasSuffix(target, ".slice") || strings.HasSuffix(target, ".scope") || strings.HasSuffix(target, ".service") {
|
|
selected[target] = true
|
|
} else {
|
|
for _, unit := range units {
|
|
if unit.Active == "active" && appMatches(target, unit.Name) {
|
|
selected[unit.Name] = true
|
|
}
|
|
}
|
|
if _, shared := c.Shared[target]; shared {
|
|
selected[c.sharedSlice()] = true
|
|
}
|
|
}
|
|
return keys(selected)
|
|
}
|
|
|
|
func (a application) override(name, target string) error {
|
|
values, err := a.config.properties(name)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
units, err := a.ctl.Units()
|
|
if err != nil {
|
|
return err
|
|
}
|
|
selected := selectUnits(a.config, units, target)
|
|
if len(selected) == 0 {
|
|
return fmt.Errorf("no running unit matches %s", target)
|
|
}
|
|
all := map[string]bool{}
|
|
for _, name := range selected {
|
|
all[name] = true
|
|
}
|
|
for _, unit := range selected {
|
|
if !strings.HasSuffix(unit, ".slice") {
|
|
continue
|
|
}
|
|
group, err := a.ctl.Group(unit)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
for _, child := range units {
|
|
if child.Active != "active" || all[child.Name] || (!strings.HasSuffix(child.Name, ".scope") && !strings.HasSuffix(child.Name, ".service")) {
|
|
continue
|
|
}
|
|
childGroup, err := a.ctl.Group(child.Name)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
if strings.HasPrefix(childGroup, group+"/") {
|
|
all[child.Name] = true
|
|
}
|
|
}
|
|
}
|
|
for _, unit := range keys(all) {
|
|
if err := a.ctl.Set(unit, values); err != nil {
|
|
return err
|
|
}
|
|
if _, err := fmt.Fprintf(a.out, "%s: %s\n", unit, name); err != nil {
|
|
return err
|
|
}
|
|
}
|
|
return nil
|
|
}
|