github.com/didip/deis@v1.4.1/deisctl/backend/fleet/unit.go (about)

     1  package fleet
     2  
     3  import (
     4  	"fmt"
     5  	"io/ioutil"
     6  	"os"
     7  	"path"
     8  	"strconv"
     9  	"strings"
    10  
    11  	"github.com/coreos/fleet/unit"
    12  )
    13  
    14  // path hierarchy for finding systemd service templates
    15  var templatePaths = []string{
    16  	os.Getenv("DEISCTL_UNITS"),
    17  	path.Join(os.Getenv("HOME"), ".deis", "units"),
    18  	"/var/lib/deis/units",
    19  }
    20  
    21  // Units returns a list of units filtered by target
    22  func (c *FleetClient) Units(target string) (units []string, err error) {
    23  	allUnits, err := c.Fleet.Units()
    24  	if err != nil {
    25  		return
    26  	}
    27  	for _, u := range allUnits {
    28  		if strings.Contains(u.Name, target) {
    29  			units = append(units, u.Name)
    30  		}
    31  	}
    32  	if len(units) == 0 {
    33  		err = fmt.Errorf("could not find unit: %s", target)
    34  	}
    35  	return
    36  }
    37  
    38  // nextUnit returns the next unit number for a given component
    39  func (c *FleetClient) nextUnit(component string) (num int, err error) {
    40  	units, err := c.Units(component)
    41  	if err != nil {
    42  		return
    43  	}
    44  	num, err = nextUnitNum(units)
    45  	if err != nil {
    46  		return
    47  	}
    48  	return
    49  }
    50  
    51  // lastUnit returns the last unit number for a given component
    52  func (c *FleetClient) lastUnit(component string) (num int, err error) {
    53  	units, err := c.Units(component)
    54  	if err != nil {
    55  		return
    56  	}
    57  	num, err = lastUnitNum(units)
    58  	if err != nil {
    59  		return
    60  	}
    61  	return
    62  }
    63  
    64  // NewUnit takes a component type and returns a Fleet unit
    65  // that includes the relevant systemd service template
    66  func NewUnit(component string) (uf *unit.UnitFile, err error) {
    67  	template, err := readTemplate(component)
    68  	if err != nil {
    69  		return
    70  	}
    71  	uf, err = unit.NewUnitFile(string(template))
    72  	if err != nil {
    73  		return
    74  	}
    75  	return
    76  }
    77  
    78  // formatUnitName returns a properly formatted systemd service name
    79  // using the given component type and number
    80  func formatUnitName(component string, num int) (unitName string, err error) {
    81  	component = strings.TrimPrefix(component, "deis-")
    82  	if num == 0 {
    83  		return "deis-" + component + ".service", nil
    84  	}
    85  	return "deis-" + component + "@" + strconv.Itoa(num) + ".service", nil
    86  }
    87  
    88  // readTemplate returns the contents of a systemd template for the given component
    89  func readTemplate(component string) (out []byte, err error) {
    90  	templateName := "deis-" + component + ".service"
    91  	var templateFile string
    92  
    93  	// look in $DEISCTL_UNITS env var, then the local and global root paths
    94  	for _, p := range templatePaths {
    95  		if p == "" {
    96  			continue
    97  		}
    98  		filename := path.Join(p, templateName)
    99  		if _, err := os.Stat(filename); err == nil {
   100  			templateFile = filename
   101  			break
   102  		}
   103  	}
   104  
   105  	if templateFile == "" {
   106  		return nil, fmt.Errorf("Could not find unit template for %v", component)
   107  	}
   108  	out, err = ioutil.ReadFile(templateFile)
   109  	if err != nil {
   110  		return
   111  	}
   112  	return
   113  }