unit: refactor config

- Seperate the config from Destination()
- Add YAML tags for the fields
This commit is contained in:
Alex Crawford 2014-09-21 19:22:38 -07:00
parent 667dbd8fb7
commit 1fbbaaec19
11 changed files with 95 additions and 76 deletions

34
config/unit.go Normal file
View File

@ -0,0 +1,34 @@
package config
import (
"path/filepath"
"strings"
)
type Unit struct {
Name string `yaml:"name"`
Mask bool `yaml:"mask"`
Enable bool `yaml:"enable"`
Runtime bool `yaml:"runtime"`
Content string `yaml:"content"`
Command string `yaml:"command"`
// For drop-in units, a cloudinit.conf is generated.
// This is currently unbound in YAML (and hence unsettable in cloud-config files)
// until the correct behaviour for multiple drop-in units is determined.
DropIn bool `yaml:"-"`
}
func (u *Unit) Type() string {
ext := filepath.Ext(u.Name)
return strings.TrimLeft(ext, ".")
}
func (u *Unit) Group() string {
switch u.Type() {
case "network", "netdev", "link":
return "network"
default:
return "system"
}
}

View File

@ -35,7 +35,7 @@ type CloudConfig struct {
Fleet config.Fleet
OEM config.OEM
Update config.Update
Units []system.Unit
Units []config.Unit
}
WriteFiles []system.File `yaml:"write_files"`
Hostname string
@ -231,6 +231,11 @@ func Apply(cfg CloudConfig, env *Environment) error {
}
}
var units []system.Unit
for _, u := range cfg.Coreos.Units {
units = append(units, system.Unit{u})
}
for _, ccu := range []CloudConfigUnit{
system.Etcd{cfg.Coreos.Etcd},
system.Fleet{cfg.Coreos.Fleet},
@ -240,7 +245,7 @@ func Apply(cfg CloudConfig, env *Environment) error {
if err != nil {
return err
}
cfg.Coreos.Units = append(cfg.Coreos.Units, u...)
units = append(units, u...)
}
wroteEnvironment := false
@ -291,7 +296,7 @@ func Apply(cfg CloudConfig, env *Environment) error {
}
um := system.NewUnitManager(env.Root())
return processUnits(cfg.Coreos.Units, env.Root(), um)
return processUnits(units, env.Root(), um)
}

View File

@ -5,6 +5,7 @@ import (
"strings"
"testing"
"github.com/coreos/coreos-cloudinit/config"
"github.com/coreos/coreos-cloudinit/system"
)
@ -401,10 +402,10 @@ func (tum *TestUnitManager) UnmaskUnit(unit *system.Unit) error {
func TestProcessUnits(t *testing.T) {
tum := &TestUnitManager{}
units := []system.Unit{
system.Unit{
system.Unit{config.Unit{
Name: "foo",
Mask: true,
},
}},
}
if err := processUnits(units, "", tum); err != nil {
t.Fatalf("unexpected error calling processUnits: %v", err)
@ -415,9 +416,9 @@ func TestProcessUnits(t *testing.T) {
tum = &TestUnitManager{}
units = []system.Unit{
system.Unit{
system.Unit{config.Unit{
Name: "bar.network",
},
}},
}
if err := processUnits(units, "", tum); err != nil {
t.Fatalf("unexpected error calling processUnits: %v", err)
@ -428,10 +429,10 @@ func TestProcessUnits(t *testing.T) {
tum = &TestUnitManager{}
units = []system.Unit{
system.Unit{
system.Unit{config.Unit{
Name: "baz.service",
Content: "[Service]\nExecStart=/bin/true",
},
}},
}
if err := processUnits(units, "", tum); err != nil {
t.Fatalf("unexpected error calling processUnits: %v", err)
@ -442,10 +443,10 @@ func TestProcessUnits(t *testing.T) {
tum = &TestUnitManager{}
units = []system.Unit{
system.Unit{
system.Unit{config.Unit{
Name: "locksmithd.service",
Runtime: true,
},
}},
}
if err := processUnits(units, "", tum); err != nil {
t.Fatalf("unexpected error calling processUnits: %v", err)
@ -456,10 +457,10 @@ func TestProcessUnits(t *testing.T) {
tum = &TestUnitManager{}
units = []system.Unit{
system.Unit{
system.Unit{config.Unit{
Name: "woof",
Enable: true,
},
}},
}
if err := processUnits(units, "", tum); err != nil {
t.Fatalf("unexpected error calling processUnits: %v", err)

View File

@ -16,10 +16,10 @@ func (ee Etcd) Units() ([]Unit, error) {
if content == "" {
return nil, nil
}
return []Unit{{
return []Unit{{config.Unit{
Name: "etcd.service",
Runtime: true,
DropIn: true,
Content: content,
}}, nil
}}}, nil
}

View File

@ -21,7 +21,7 @@ func TestEtcdUnits(t *testing.T) {
Discovery: "http://disco.example.com/foobar",
PeerBindAddr: "127.0.0.1:7002",
},
[]Unit{{
[]Unit{{config.Unit{
Name: "etcd.service",
Runtime: true,
DropIn: true,
@ -29,7 +29,7 @@ func TestEtcdUnits(t *testing.T) {
Environment="ETCD_DISCOVERY=http://disco.example.com/foobar"
Environment="ETCD_PEER_BIND_ADDR=127.0.0.1:7002"
`,
}},
}}},
},
{
config.Etcd{
@ -37,7 +37,7 @@ Environment="ETCD_PEER_BIND_ADDR=127.0.0.1:7002"
Discovery: "http://disco.example.com/foobar",
PeerBindAddr: "127.0.0.1:7002",
},
[]Unit{{
[]Unit{{config.Unit{
Name: "etcd.service",
Runtime: true,
DropIn: true,
@ -46,7 +46,7 @@ Environment="ETCD_DISCOVERY=http://disco.example.com/foobar"
Environment="ETCD_NAME=node001"
Environment="ETCD_PEER_BIND_ADDR=127.0.0.1:7002"
`,
}},
}}},
},
} {
units, err := Etcd{tt.config}.Units()

View File

@ -17,10 +17,10 @@ func (fe Fleet) Units() ([]Unit, error) {
if content == "" {
return nil, nil
}
return []Unit{{
return []Unit{{config.Unit{
Name: "fleet.service",
Runtime: true,
DropIn: true,
Content: content,
}}, nil
}}}, nil
}

View File

@ -20,14 +20,14 @@ func TestFleetUnits(t *testing.T) {
config.Fleet{
PublicIP: "12.34.56.78",
},
[]Unit{{
[]Unit{{config.Unit{
Name: "fleet.service",
Content: `[Service]
Environment="FLEET_PUBLIC_IP=12.34.56.78"
`,
Runtime: true,
DropIn: true,
}},
}}},
},
} {
units, err := Fleet{tt.config}.Units()

View File

@ -5,10 +5,12 @@ import (
"os"
"path"
"testing"
"github.com/coreos/coreos-cloudinit/config"
)
func TestPlaceNetworkUnit(t *testing.T) {
u := Unit{
u := Unit{config.Unit{
Name: "50-eth0.network",
Runtime: true,
Content: `[Match]
@ -17,7 +19,7 @@ Name=eth47
[Network]
Address=10.209.171.177/19
`,
}
}}
dir, err := ioutil.TempDir(os.TempDir(), "coreos-cloudinit-")
if err != nil {
@ -66,10 +68,10 @@ func TestUnitDestination(t *testing.T) {
dir := "/some/dir"
name := "foobar.service"
u := Unit{
u := Unit{config.Unit{
Name: name,
DropIn: false,
}
}}
dst := u.Destination(dir)
expectDst := path.Join(dir, "etc", "systemd", "system", "foobar.service")
@ -87,14 +89,14 @@ func TestUnitDestination(t *testing.T) {
}
func TestPlaceMountUnit(t *testing.T) {
u := Unit{
u := Unit{config.Unit{
Name: "media-state.mount",
Runtime: false,
Content: `[Mount]
What=/dev/sdb1
Where=/media/state
`,
}
}}
dir, err := ioutil.TempDir(os.TempDir(), "coreos-cloudinit-")
if err != nil {
@ -162,7 +164,7 @@ func TestMaskUnit(t *testing.T) {
sd := &systemd{dir}
// Ensure mask works with units that do not currently exist
uf := &Unit{Name: "foo.service"}
uf := &Unit{config.Unit{Name: "foo.service"}}
if err := sd.MaskUnit(uf); err != nil {
t.Fatalf("Unable to mask new unit: %v", err)
}
@ -176,7 +178,7 @@ func TestMaskUnit(t *testing.T) {
}
// Ensure mask works with unit files that already exist
ub := &Unit{Name: "bar.service"}
ub := &Unit{config.Unit{Name: "bar.service"}}
barPath := path.Join(dir, "etc", "systemd", "system", "bar.service")
if _, err := os.Create(barPath); err != nil {
t.Fatalf("Error creating new unit file: %v", err)
@ -202,12 +204,12 @@ func TestUnmaskUnit(t *testing.T) {
sd := &systemd{dir}
nilUnit := &Unit{Name: "null.service"}
nilUnit := &Unit{config.Unit{Name: "null.service"}}
if err := sd.UnmaskUnit(nilUnit); err != nil {
t.Errorf("unexpected error from unmasking nonexistent unit: %v", err)
}
uf := &Unit{Name: "foo.service", Content: "[Service]\nExecStart=/bin/true"}
uf := &Unit{config.Unit{Name: "foo.service", Content: "[Service]\nExecStart=/bin/true"}}
dst := uf.Destination(dir)
if err := os.MkdirAll(path.Dir(dst), os.FileMode(0755)); err != nil {
t.Fatalf("Unable to create unit directory: %v", err)
@ -227,7 +229,7 @@ func TestUnmaskUnit(t *testing.T) {
t.Errorf("unmask of non-empty unit mutated unit contents unexpectedly")
}
ub := &Unit{Name: "bar.service"}
ub := &Unit{config.Unit{Name: "bar.service"}}
dst = ub.Destination(dir)
if err := os.Symlink("/dev/null", dst); err != nil {
t.Fatalf("Unable to create masked unit: %v", err)

View File

@ -3,8 +3,8 @@ package system
import (
"fmt"
"path"
"path/filepath"
"strings"
"github.com/coreos/coreos-cloudinit/config"
)
// Name for drop-in service configuration files created by cloudconfig
@ -19,33 +19,10 @@ type UnitManager interface {
UnmaskUnit(unit *Unit) error
}
// Unit is a top-level structure which embeds its underlying configuration,
// config.Unit, and provides the system-specific Destination().
type Unit struct {
Name string
Mask bool
Enable bool
Runtime bool
Content string
Command string
// For drop-in units, a cloudinit.conf is generated.
// This is currently unbound in YAML (and hence unsettable in cloud-config files)
// until the correct behaviour for multiple drop-in units is determined.
DropIn bool `yaml:"-"`
}
func (u *Unit) Type() string {
ext := filepath.Ext(u.Name)
return strings.TrimLeft(ext, ".")
}
func (u *Unit) Group() (group string) {
t := u.Type()
if t == "network" || t == "netdev" || t == "link" {
group = "network"
} else {
group = "system"
}
return
config.Unit
}
type Script []byte

View File

@ -103,12 +103,12 @@ func (uc Update) File() (*File, error) {
func (uc Update) Units() ([]Unit, error) {
var units []Unit
if uc.Config.RebootStrategy != "" {
ls := &Unit{
ls := &Unit{config.Unit{
Name: locksmithUnit,
Command: "restart",
Mask: false,
Runtime: true,
}
}}
if uc.Config.RebootStrategy == "off" {
ls.Command = "stop"
@ -118,10 +118,10 @@ func (uc Update) Units() ([]Unit, error) {
}
if uc.Config.Group != "" || uc.Config.Server != "" {
ue := Unit{
ue := Unit{config.Unit{
Name: updateEngineUnit,
Command: "restart",
}
}}
units = append(units, ue)
}

View File

@ -27,43 +27,43 @@ func TestUpdateUnits(t *testing.T) {
},
{
config: config.Update{Group: "master", Server: "http://foo.com"},
units: []Unit{{
units: []Unit{{config.Unit{
Name: "update-engine.service",
Command: "restart",
}},
}}},
},
{
config: config.Update{RebootStrategy: "best-effort"},
units: []Unit{{
units: []Unit{{config.Unit{
Name: "locksmithd.service",
Command: "restart",
Runtime: true,
}},
}}},
},
{
config: config.Update{RebootStrategy: "etcd-lock"},
units: []Unit{{
units: []Unit{{config.Unit{
Name: "locksmithd.service",
Command: "restart",
Runtime: true,
}},
}}},
},
{
config: config.Update{RebootStrategy: "reboot"},
units: []Unit{{
units: []Unit{{config.Unit{
Name: "locksmithd.service",
Command: "restart",
Runtime: true,
}},
}}},
},
{
config: config.Update{RebootStrategy: "off"},
units: []Unit{{
units: []Unit{{config.Unit{
Name: "locksmithd.service",
Command: "stop",
Runtime: true,
Mask: true,
}},
}}},
},
} {
units, err := Update{tt.config, testReadConfig("")}.Units()