Skip to content

Commit

Permalink
Merge pull request #46 from funbox/develop
Browse files Browse the repository at this point in the history
Version 0.20.0
  • Loading branch information
andyone authored Jun 21, 2018
2 parents d9d187a + 452d215 commit 1133542
Show file tree
Hide file tree
Showing 10 changed files with 417 additions and 23 deletions.
2 changes: 1 addition & 1 deletion Makefile
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
################################################################################

# This Makefile generated by GoMakeGen 0.7.1 using next command:
# This Makefile generated by GoMakeGen 0.8.0 using next command:
# gomakegen .

################################################################################
Expand Down
16 changes: 12 additions & 4 deletions readme.md → README.md
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
## `init-exporter` [![Build Status](https://travis-ci.org/funbox/init-exporter.svg?branch=master)](https://travis-ci.org/funbox/init-exporter) [![Go Report Card](https://goreportcard.com/badge/github.com/funbox/init-exporter)](https://goreportcard.com/report/github.com/funbox/init-exporter) [![License](https://gh.kaos.io/mit.svg)](LICENSE)
## `init-exporter` [![Build Status](https://travis-ci.org/funbox/init-exporter.svg?branch=master)](https://travis-ci.org/funbox/init-exporter) [![Go Report Card](https://goreportcard.com/badge/github.com/funbox/init-exporter)](https://goreportcard.com/report/github.com/funbox/init-exporter) [![License](https://gh.kaos.st/mit.svg)](LICENSE)

Utility for exporting services described by Procfile to init system.
Supported init systems: upstart and systemd
Expand All @@ -23,7 +23,7 @@ Before the initial install allows git to use redirects for [pkg.re](https://gith
git config --global http.https://pkg.re.followRedirects true
```

To build the init-exporter from scratch, make sure you have a working Go 1.5+ workspace ([instructions](https://golang.org/doc/install)), then:
To build the init-exporter from scratch, make sure you have a working Go 1.8+ workspace ([instructions](https://golang.org/doc/install)), then:

```bash
go get -d github.com/funbox/init-exporter
Expand All @@ -36,14 +36,14 @@ make all
#### From ESSENTIAL KAOS Public repo for RHEL6/CentOS6

```
[sudo] yum install -y https://yum.kaos.io/6/release/x86_64/kaos-repo-8.0-0.el6.noarch.rpm
[sudo] yum install -y https://yum.kaos.st/6/release/x86_64/kaos-repo-9.1-0.el6.noarch.rpm
[sudo] yum install init-exporter
```

#### From ESSENTIAL KAOS Public repo for RHEL7/CentOS7

```
[sudo] yum install -y https://yum.kaos.io/7/release/x86_64/kaos-repo-8.0-0.el7.noarch.rpm
[sudo] yum install -y https://yum.kaos.st/7/release/x86_64/kaos-repo-9.1-0.el7.noarch.rpm
[sudo] yum install init-exporter
```

Expand All @@ -65,6 +65,14 @@ The export process can be configured through the config `/etc/init-exporter.conf
# Prefix used for exported units and helpers
prefix: fb-

[procfile]

# Enable/disable support of version 1 proc files
version1: false

# Enable/disable support of version 2 proc files
version2: true

[paths]

# Working dir
Expand Down
2 changes: 1 addition & 1 deletion cli/cli.go
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ import (
// App props
const (
APP = "init-exporter"
VER = "0.19.0"
VER = "0.20.0"
DESC = "Utility for exporting services described by Procfile to init system"
)

Expand Down
6 changes: 5 additions & 1 deletion common/init-exporter.spec
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@

Summary: Utility for exporting services described by Procfile to init system
Name: init-exporter
Version: 0.19.0
Version: 0.20.0
Release: 0%{?dist}
Group: Development/Tools
License: MIT
Expand Down Expand Up @@ -111,6 +111,10 @@ rm -rf %{buildroot}
################################################################################

%changelog
* Wed Jun 20 2018 Anton Novojilov <[email protected]> - 0.20.0-0
- Added support of resources usage limits configuration (systemd feature)
- Added support of kill mode configuration (systemd feature)

* Thu Apr 05 2018 Anton Novojilov <[email protected]> - 0.19.0-0
- Added pyenv support

Expand Down
41 changes: 41 additions & 0 deletions export/export_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -355,6 +355,7 @@ func (s *ExportSuite) TestSystemdExport(c *C) {
"[Service]",
"Type=simple",
"",
"",
"KillSignal=SIGQUIT",
"TimeoutStopSec=10",
"Restart=on-failure",
Expand All @@ -364,6 +365,7 @@ func (s *ExportSuite) TestSystemdExport(c *C) {
"LimitNOFILE=1024",
"",
"",
"",
"ExecStartPre=/bin/touch /var/log/test_application/serviceA.log",
"ExecStartPre=/bin/chown service /var/log/test_application/serviceA.log",
"ExecStartPre=/bin/chgrp service /var/log/test_application/serviceA.log",
Expand All @@ -387,6 +389,7 @@ func (s *ExportSuite) TestSystemdExport(c *C) {
"[Service]",
"Type=simple",
"",
"",
"KillSignal=SIGQUIT",
"TimeoutStopSec=10",
"Restart=on-failure",
Expand All @@ -396,6 +399,7 @@ func (s *ExportSuite) TestSystemdExport(c *C) {
"LimitNOFILE=1024",
"",
"",
"",
"ExecStartPre=/bin/touch /var/log/test_application/serviceA.log",
"ExecStartPre=/bin/chown service /var/log/test_application/serviceA.log",
"ExecStartPre=/bin/chgrp service /var/log/test_application/serviceA.log",
Expand All @@ -420,6 +424,7 @@ func (s *ExportSuite) TestSystemdExport(c *C) {
"Type=simple",
"",
"",
"",
"TimeoutStopSec=0",
"Restart=on-failure",
"",
Expand All @@ -428,6 +433,23 @@ func (s *ExportSuite) TestSystemdExport(c *C) {
"LimitNOFILE=4096",
"LimitNPROC=4096",
"",
"CPUWeight=50",
"StartupCPUWeight=50",
"CPUQuota=35%",
"MemoryLow=1G",
"MemoryHigh=4G",
"MemoryMax=8G",
"MemorySwapMax=2G",
"TasksMax=162",
"IOWeight=50",
"IODeviceWeight=/dev/sda 200",
"IOReadBandwidthMax=/dev/sda 200M",
"IOWriteBandwidthMax=/dev/sda 50M",
"IOReadIOPSMax=/dev/sda 1K",
"IOWriteIOPSMax=/dev/sda 2K",
"IPAddressAllow=127.0.0.0/8 ::1/128",
"IPAddressDeny=0.0.0.0/0 ::/0",
"",
"ExecStartPre=/bin/touch /var/log/test_application/serviceB.log",
"ExecStartPre=/bin/chown service /var/log/test_application/serviceB.log",
"ExecStartPre=/bin/chgrp service /var/log/test_application/serviceB.log",
Expand Down Expand Up @@ -512,6 +534,25 @@ func createTestApp(helperDir, targetDir string) *procfile.Application {
IsRespawnEnabled: true,
LimitFile: 4096,
LimitProc: 4096,
Resources: &procfile.Resources{
CPUWeight: 50,
StartupCPUWeight: 15,
CPUQuota: 35,
MemoryLow: "1G",
MemoryHigh: "4G",
MemoryMax: "8G",
MemorySwapMax: "2G",
TasksMax: 162,
IOWeight: 50,
StartupIOWeight: 90,
IODeviceWeight: "/dev/sda 200",
IOReadBandwidthMax: "/dev/sda 200M",
IOWriteBandwidthMax: "/dev/sda 50M",
IOReadIOPSMax: "/dev/sda 1K",
IOWriteIOPSMax: "/dev/sda 2K",
IPAddressAllow: "127.0.0.0/8 ::1/128",
IPAddressDeny: "0.0.0.0/0 ::/0",
},
},
}

Expand Down
82 changes: 80 additions & 2 deletions export/systemd.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ package export

import (
"errors"
"fmt"
"strconv"
"strings"
"time"
Expand Down Expand Up @@ -71,6 +72,7 @@ PartOf={{.Application.Name}}.service
[Service]
Type=simple
{{ if .Service.Options.IsKillModeSet }}KillMode={{.Service.Options.KillMode}}{{ end }}
{{ if .Service.Options.IsKillSignalSet }}KillSignal={{.Service.Options.KillSignal}}{{ end }}
TimeoutStopSec={{.Service.Options.KillTimeout}}
{{ if .Service.Options.IsRespawnEnabled }}Restart=on-failure{{ end }}
Expand All @@ -80,6 +82,7 @@ TimeoutStopSec={{.Service.Options.KillTimeout}}
{{ if .Service.Options.IsFileLimitSet }}LimitNOFILE={{.Service.Options.LimitFile}}{{ end }}
{{ if .Service.Options.IsProcLimitSet }}LimitNPROC={{.Service.Options.LimitProc}}{{ end }}
{{ if .Service.Options.IsResourcesSet }}{{.ResourcesAsString}}{{ end }}
ExecStartPre=/bin/touch /var/log/{{.Application.Name}}/{{.Service.Name}}.log
ExecStartPre=/bin/chown {{.Application.User}} /var/log/{{.Application.Name}}/{{.Service.Name}}.log
ExecStartPre=/bin/chgrp {{.Application.Group}} /var/log/{{.Application.Name}}/{{.Service.Name}}.log
Expand Down Expand Up @@ -119,6 +122,81 @@ func NewSystemd() *SystemdProvider {

// ////////////////////////////////////////////////////////////////////////////////// //

// ResourcesAsString return resources settings as string
func (sd *systemdServiceData) ResourcesAsString() string {
var result string

resources := sd.Service.Options.Resources

if resources.CPUWeight != 0 {
result += fmt.Sprintf("CPUWeight=%d\n", resources.CPUWeight)
}

if resources.StartupCPUWeight != 0 {
result += fmt.Sprintf("StartupCPUWeight=%d\n", resources.CPUWeight)
}

if resources.CPUQuota != 0 {
result += fmt.Sprintf("CPUQuota=%d%%\n", resources.CPUQuota)
}

if resources.MemoryLow != "" {
result += fmt.Sprintf("MemoryLow=%s\n", resources.MemoryLow)
}

if resources.MemoryHigh != "" {
result += fmt.Sprintf("MemoryHigh=%s\n", resources.MemoryHigh)
}

if resources.MemoryMax != "" {
result += fmt.Sprintf("MemoryMax=%s\n", resources.MemoryMax)
}

if resources.MemorySwapMax != "" {
result += fmt.Sprintf("MemorySwapMax=%s\n", resources.MemorySwapMax)
}

if resources.TasksMax != 0 {
result += fmt.Sprintf("TasksMax=%d\n", resources.TasksMax)
}

if resources.IOWeight != 0 {
result += fmt.Sprintf("IOWeight=%d\n", resources.IOWeight)
}

if resources.IODeviceWeight != "" {
result += fmt.Sprintf("IODeviceWeight=%s\n", resources.IODeviceWeight)
}

if resources.IOReadBandwidthMax != "" {
result += fmt.Sprintf("IOReadBandwidthMax=%s\n", resources.IOReadBandwidthMax)
}

if resources.IOWriteBandwidthMax != "" {
result += fmt.Sprintf("IOWriteBandwidthMax=%s\n", resources.IOWriteBandwidthMax)
}

if resources.IOReadIOPSMax != "" {
result += fmt.Sprintf("IOReadIOPSMax=%s\n", resources.IOReadIOPSMax)
}

if resources.IOWriteIOPSMax != "" {
result += fmt.Sprintf("IOWriteIOPSMax=%s\n", resources.IOWriteIOPSMax)
}

if resources.IPAddressAllow != "" {
result += fmt.Sprintf("IPAddressAllow=%s\n", resources.IPAddressAllow)
}

if resources.IPAddressDeny != "" {
result += fmt.Sprintf("IPAddressDeny=%s\n", resources.IPAddressDeny)
}

return result
}

// ////////////////////////////////////////////////////////////////////////////////// //

// UnitName return unit name with extension
func (sp *SystemdProvider) UnitName(name string) string {
return name + ".service"
Expand Down Expand Up @@ -174,7 +252,7 @@ func (sp *SystemdProvider) RenderAppTemplate(app *procfile.Application) (string,
// RenderServiceTemplate render unit template data with given service data and
// return service unit code
func (sp *SystemdProvider) RenderServiceTemplate(service *procfile.Service) (string, error) {
data := systemdServiceData{
data := &systemdServiceData{
Application: service.Application,
Service: service,
StartLevel: sp.renderLevel(service.Application.StartLevel),
Expand All @@ -188,7 +266,7 @@ func (sp *SystemdProvider) RenderServiceTemplate(service *procfile.Service) (str
// RenderHelperTemplate render helper template data with given service data and
// return helper script code
func (sp *SystemdProvider) RenderHelperTemplate(service *procfile.Service) (string, error) {
data := systemdServiceData{
data := &systemdServiceData{
Application: service.Application,
Service: service,
StartLevel: sp.renderLevel(service.Application.StartLevel),
Expand Down
59 changes: 59 additions & 0 deletions procfile/procfile.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ import (
"pkg.re/essentialkaos/ek.v9/fsutil"
"pkg.re/essentialkaos/ek.v9/log"
"pkg.re/essentialkaos/ek.v9/path"
"pkg.re/essentialkaos/ek.v9/sliceutil"
"pkg.re/essentialkaos/ek.v9/strutil"
)

Expand Down Expand Up @@ -61,13 +62,35 @@ type ServiceOptions struct {
LogFile string // Path to log file
KillTimeout int // Kill timeout in seconds
KillSignal string // Kill signal name
KillMode string // Kill mode (systemd only)
ReloadSignal string // Reload signal name
Count int // Exec count
RespawnInterval int // Respawn interval in seconds
RespawnCount int // Respawn count
IsRespawnEnabled bool // Respawn enabled flag
LimitProc int // Processes limit
LimitFile int // Descriptors limit
Resources *Resources // Resources limits (systemd only)
}

type Resources struct {
CPUWeight int
StartupCPUWeight int
CPUQuota int
MemoryLow string
MemoryHigh string
MemoryMax string
MemorySwapMax string
TasksMax int
IOWeight int
StartupIOWeight int
IODeviceWeight string
IOReadBandwidthMax string
IOWriteBandwidthMax string
IOReadIOPSMax string
IOWriteIOPSMax string
IPAddressAllow string
IPAddressDeny string
}

type Application struct {
Expand Down Expand Up @@ -197,6 +220,32 @@ func (so *ServiceOptions) Validate() []error {
errs.Add(fmt.Errorf("Property \"respawn:interval\" must be greater or equal 0"))
}

if so.KillMode != "" && !sliceutil.Contains([]string{"control-group", "process", "mixed", "none"}, so.KillMode) {
errs.Add(fmt.Errorf("Property \"kill_mode\" must contains 'control-group', 'process', 'mixed' or 'none'"))
}

if so.Resources != nil {
if so.Resources.CPUWeight < 0 || so.Resources.CPUWeight > 10000 {
errs.Add(fmt.Errorf("Property \"resources:cpu_weight\" must be greater or equal 0 and less or equal 10000"))
}

if so.Resources.StartupCPUWeight < 0 || so.Resources.StartupCPUWeight > 10000 {
errs.Add(fmt.Errorf("Property \"resources:startup_cpu_weight\" must be greater or equal 0 and less or equal 10000"))
}

if so.Resources.CPUQuota < 0 {
errs.Add(fmt.Errorf("Property \"resources:cpu_quota\" must be greater than 0"))
}

if so.Resources.IOWeight < 0 || so.Resources.IOWeight > 10000 {
errs.Add(fmt.Errorf("Property \"resources:io_weight\" must be greater or equal 0 and less or equal 10000"))
}

if so.Resources.StartupIOWeight < 0 || so.Resources.StartupIOWeight > 10000 {
errs.Add(fmt.Errorf("Property \"resources:startup_io_weight\" must be greater or equal 0 and less or equal 10000"))
}
}

return errs.All()
}

Expand Down Expand Up @@ -277,11 +326,21 @@ func (so *ServiceOptions) IsKillSignalSet() bool {
return so.KillSignal != ""
}

// IsKillModeSet return true if custom kill mode set
func (so *ServiceOptions) IsKillModeSet() bool {
return so.KillMode != ""
}

// IsReloadSignalSet return true if custom reload signal set
func (so *ServiceOptions) IsReloadSignalSet() bool {
return so.ReloadSignal != ""
}

// IsResourcesSet return true if resources limits are set
func (so *ServiceOptions) IsResourcesSet() bool {
return so.Resources != nil
}

// EnvString return environment variables as string
func (so *ServiceOptions) EnvString() string {
if len(so.Env) == 0 {
Expand Down
Loading

0 comments on commit 1133542

Please sign in to comment.