github.com/caos/orbos@v1.5.14-0.20221103111702-e6cd0cea7ad4/internal/operator/nodeagent/dep/health/dep.go (about)

     1  package health
     2  
     3  import (
     4  	"fmt"
     5  	"io/ioutil"
     6  	"os"
     7  	"path/filepath"
     8  	"regexp"
     9  	"strings"
    10  
    11  	"github.com/caos/orbos/internal/operator/nodeagent/dep"
    12  
    13  	"github.com/caos/orbos/internal/operator/common"
    14  	"github.com/caos/orbos/internal/operator/nodeagent"
    15  	"github.com/caos/orbos/internal/operator/nodeagent/dep/middleware"
    16  	"github.com/caos/orbos/mntr"
    17  )
    18  
    19  const dir string = "/lib/systemd/system"
    20  
    21  type Installer interface {
    22  	isHealth()
    23  	nodeagent.Installer
    24  }
    25  type healthDep struct {
    26  	monitor mntr.Monitor
    27  	systemd *dep.SystemD
    28  }
    29  
    30  func New(monitor mntr.Monitor, systemd *dep.SystemD) Installer {
    31  	return &healthDep{monitor: monitor, systemd: systemd}
    32  }
    33  
    34  func (healthDep) isHealth() {}
    35  
    36  func (healthDep) Is(other nodeagent.Installer) bool {
    37  	_, ok := middleware.Unwrap(other).(Installer)
    38  	return ok
    39  }
    40  
    41  func (healthDep) String() string { return "health" }
    42  
    43  func (*healthDep) Equals(other nodeagent.Installer) bool {
    44  	_, ok := other.(*healthDep)
    45  	return ok
    46  }
    47  func (*healthDep) InstalledFilter() []string { return nil }
    48  
    49  var r = regexp.MustCompile(`ExecStart=/usr/local/bin/health --listen ([^\s]+) (.*)`)
    50  
    51  func (s *healthDep) Current() (pkg common.Package, err error) {
    52  
    53  	files, _ := ioutil.ReadDir(dir)
    54  	for _, file := range files {
    55  		if !strings.HasPrefix(file.Name(), "orbos.health.") {
    56  			continue
    57  		}
    58  		content, err := ioutil.ReadFile(filepath.Join(dir, file.Name()))
    59  		if err != nil {
    60  			return pkg, err
    61  		}
    62  
    63  		if pkg.Config == nil {
    64  			pkg.Config = make(map[string]string)
    65  		}
    66  
    67  		if s.systemd.Active(file.Name()) {
    68  			http, checks := extractArguments(content)
    69  			pkg.Config[http] = unquote(checks)
    70  		}
    71  	}
    72  	return pkg, nil
    73  }
    74  
    75  func extractArguments(content []byte) (string, string) {
    76  	match := r.FindStringSubmatch(string(content))
    77  	return match[1], match[2]
    78  }
    79  
    80  func (s *healthDep) Ensure(_ common.Package, ensure common.Package, _ bool) error {
    81  
    82  	files, _ := ioutil.ReadDir(dir)
    83  	for _, file := range files {
    84  		if strings.HasPrefix(file.Name(), "orbos.health.") {
    85  			if err := s.systemd.Disable(file.Name()); err != nil {
    86  				return err
    87  			}
    88  			if err := os.Remove(filepath.Join(dir, file.Name())); err != nil {
    89  				return err
    90  			}
    91  		}
    92  	}
    93  
    94  	var i int
    95  	for location, args := range ensure.Config {
    96  		i++
    97  		svc := fmt.Sprintf("orbos.health.%d.service", i)
    98  		if err := ioutil.WriteFile(filepath.Join(dir, svc), []byte(fmt.Sprintf(`
    99  [Unit]
   100  Description=Healthchecks Proxy
   101  After=network.target
   102  
   103  [Service]
   104  Type=simple
   105  User=root
   106  ExecStart=/usr/local/bin/health --listen %s %s
   107  Restart=always
   108  MemoryLimit=20M
   109  MemoryAccounting=yes
   110  RestartSec=10
   111  CPUAccounting=yes
   112  
   113  [Install]
   114  WantedBy=multi-user.target
   115  `, location, quote(args))), 0644); err != nil {
   116  			return err
   117  		}
   118  
   119  		if err := s.systemd.Enable(svc); err != nil {
   120  			return err
   121  		}
   122  		if err := s.systemd.Start(svc); err != nil {
   123  			return err
   124  		}
   125  	}
   126  
   127  	return nil
   128  }
   129  
   130  func unquote(args string) string {
   131  	s := strings.Split(args, " ")
   132  	for idx, a := range s {
   133  		s[idx] = strings.Trim(a, `"`)
   134  	}
   135  	return strings.Join(s, " ")
   136  }
   137  
   138  func quote(args string) string {
   139  	s := strings.Split(args, " ")
   140  	for idx, a := range s {
   141  		s[idx] = fmt.Sprintf(`"%s"`, a)
   142  	}
   143  	return strings.Join(s, " ")
   144  }