Merge pull request #72 from bcwaldon/unit-enable
Address unit enabling issues
This commit is contained in:
		| @@ -87,6 +87,7 @@ Arbitrary systemd units may be provided in the `coreos.units` attribute. | ||||
|  | ||||
| - **name**: String representing unit's name. Required. | ||||
| - **runtime**: Boolean indicating whether or not to persist the unit across reboots. This is analagous to the `--runtime` argument to `systemd enable`. Default value is false. | ||||
| - **enable**: Boolean indicating whether or not to handle the [Install] section of the unit file. This is similar to running `systemctl enable <name>`. Default value is false. | ||||
| - **content**: Plaintext string representing entire unit file. If no value is provided, the unit is assumed to exist already. | ||||
| - **command**: Command to execute on unit: start, stop, reload, restart, try-restart, reload-or-restart, reload-or-try-restart. Default value is restart. | ||||
|  | ||||
|   | ||||
| @@ -130,16 +130,17 @@ func Apply(cfg CloudConfig, env *Environment) error { | ||||
|  | ||||
| 	if len(cfg.Coreos.Units) > 0 { | ||||
| 		commands := make(map[string]string, 0) | ||||
|  | ||||
| 		for _, unit := range cfg.Coreos.Units { | ||||
| 			dst := system.UnitDestination(&unit, env.Root()) | ||||
| 			if unit.Content != "" { | ||||
| 				log.Printf("Writing unit %s to filesystem", unit.Name) | ||||
| 				dst, err := system.PlaceUnit(&unit, env.Root()) | ||||
| 				if err != nil { | ||||
| 				log.Printf("Writing unit %s to filesystem at path %s", unit.Name, dst) | ||||
| 				if err := system.PlaceUnit(&unit, dst); err != nil { | ||||
| 					return err | ||||
| 				} | ||||
| 				log.Printf("Placed unit %s at %s", unit.Name, dst) | ||||
| 			} | ||||
|  | ||||
| 			if unit.Enable { | ||||
| 				if unit.Group() != "network" { | ||||
| 					log.Printf("Enabling unit file %s", dst) | ||||
| 					if err := system.EnableUnitFile(dst, unit.Runtime); err != nil { | ||||
|   | ||||
| @@ -19,6 +19,7 @@ const fakeMachineID = "42000000000000000000000000000042" | ||||
|  | ||||
| type Unit struct { | ||||
| 	Name    string | ||||
| 	Enable  bool | ||||
| 	Runtime bool | ||||
| 	Content string | ||||
| 	Command string | ||||
| @@ -41,21 +42,28 @@ func (u *Unit) Group() (group string) { | ||||
|  | ||||
| type Script []byte | ||||
|  | ||||
| func PlaceUnit(u *Unit, root string) (string, error) { | ||||
| // UnitDestination builds the appropriate absolte file path for | ||||
| // the given unit. The root argument indicates the effective base | ||||
| // directory of the system (similar to a chroot). | ||||
| func UnitDestination(u *Unit, root string) string { | ||||
| 	dir := "etc" | ||||
| 	if u.Runtime { | ||||
| 		dir = "run" | ||||
| 	} | ||||
|  | ||||
| 	dst := path.Join(root, dir, "systemd", u.Group()) | ||||
| 	if _, err := os.Stat(dst); os.IsNotExist(err) { | ||||
| 		if err := os.MkdirAll(dst, os.FileMode(0755)); err != nil { | ||||
| 			return "", err | ||||
| 	return path.Join(root, dir, "systemd", u.Group(), u.Name) | ||||
| } | ||||
|  | ||||
| // PlaceUnit writes a unit file at the provided destination, creating | ||||
| // parent directories as necessary. | ||||
| func PlaceUnit(u *Unit, dst string) error { | ||||
| 	dir := filepath.Dir(dst) | ||||
| 	if _, err := os.Stat(dir); os.IsNotExist(err) { | ||||
| 		if err := os.MkdirAll(dir, os.FileMode(0755)); err != nil { | ||||
| 			return err | ||||
| 		} | ||||
| 	} | ||||
|  | ||||
| 	dst = path.Join(dst, u.Name) | ||||
|  | ||||
| 	file := File{ | ||||
| 		Path: dst, | ||||
| 		Content: u.Content, | ||||
| @@ -64,10 +72,10 @@ func PlaceUnit(u *Unit, root string) (string, error) { | ||||
|  | ||||
| 	err := WriteFile(&file) | ||||
| 	if err != nil { | ||||
| 		return "", err | ||||
| 		return err | ||||
| 	} | ||||
|  | ||||
| 	return dst, nil | ||||
| 	return nil | ||||
| } | ||||
|  | ||||
| func EnableUnitFile(file string, runtime bool) error { | ||||
|   | ||||
| @@ -26,12 +26,17 @@ Address=10.209.171.177/19 | ||||
| 	} | ||||
| 	defer syscall.Rmdir(dir) | ||||
|  | ||||
| 	if _, err := PlaceUnit(&u, dir); err != nil { | ||||
| 	dst := UnitDestination(&u, dir) | ||||
| 	expectDst := path.Join(dir, "run", "systemd", "network", "50-eth0.network") | ||||
| 	if dst != expectDst { | ||||
| 		t.Fatalf("UnitDestination returned %s, expected %s", dst, expectDst) | ||||
| 	} | ||||
|  | ||||
| 	if err := PlaceUnit(&u, dst); err != nil { | ||||
| 		t.Fatalf("PlaceUnit failed: %v", err) | ||||
| 	} | ||||
|  | ||||
| 	fullPath := path.Join(dir, "run", "systemd", "network", "50-eth0.network") | ||||
| 	fi, err := os.Stat(fullPath) | ||||
| 	fi, err := os.Stat(dst) | ||||
| 	if err != nil { | ||||
| 		t.Fatalf("Unable to stat file: %v", err) | ||||
| 	} | ||||
| @@ -40,19 +45,19 @@ Address=10.209.171.177/19 | ||||
| 		t.Errorf("File has incorrect mode: %v", fi.Mode()) | ||||
| 	} | ||||
|  | ||||
| 	contents, err := ioutil.ReadFile(fullPath) | ||||
| 	contents, err := ioutil.ReadFile(dst) | ||||
| 	if err != nil { | ||||
| 		t.Fatalf("Unable to read expected file: %v", err) | ||||
| 	} | ||||
|  | ||||
| 	expect := `[Match] | ||||
| 	expectContents := `[Match] | ||||
| Name=eth47 | ||||
|  | ||||
| [Network] | ||||
| Address=10.209.171.177/19 | ||||
| ` | ||||
| 	if string(contents) != expect { | ||||
| 		t.Fatalf("File has incorrect contents '%s'.\nExpected '%s'", string(contents), expect) | ||||
| 	if string(contents) != expectContents { | ||||
| 		t.Fatalf("File has incorrect contents '%s'.\nExpected '%s'", string(contents), expectContents) | ||||
| 	} | ||||
| } | ||||
|  | ||||
| @@ -72,12 +77,17 @@ Where=/media/state | ||||
| 	} | ||||
| 	defer syscall.Rmdir(dir) | ||||
|  | ||||
| 	if _, err := PlaceUnit(&u, dir); err != nil { | ||||
| 	dst := UnitDestination(&u, dir) | ||||
| 	expectDst := path.Join(dir, "etc", "systemd", "system", "media-state.mount") | ||||
| 	if dst != expectDst { | ||||
| 		t.Fatalf("UnitDestination returned %s, expected %s", dst, expectDst) | ||||
| 	} | ||||
|  | ||||
| 	if err := PlaceUnit(&u, dst); err != nil { | ||||
| 		t.Fatalf("PlaceUnit failed: %v", err) | ||||
| 	} | ||||
|  | ||||
| 	fullPath := path.Join(dir, "etc", "systemd", "system", "media-state.mount") | ||||
| 	fi, err := os.Stat(fullPath) | ||||
| 	fi, err := os.Stat(dst) | ||||
| 	if err != nil { | ||||
| 		t.Fatalf("Unable to stat file: %v", err) | ||||
| 	} | ||||
| @@ -86,17 +96,17 @@ Where=/media/state | ||||
| 		t.Errorf("File has incorrect mode: %v", fi.Mode()) | ||||
| 	} | ||||
|  | ||||
| 	contents, err := ioutil.ReadFile(fullPath) | ||||
| 	contents, err := ioutil.ReadFile(dst) | ||||
| 	if err != nil { | ||||
| 		t.Fatalf("Unable to read expected file: %v", err) | ||||
| 	} | ||||
|  | ||||
| 	expect := `[Mount] | ||||
| 	expectContents := `[Mount] | ||||
| What=/dev/sdb1 | ||||
| Where=/media/state | ||||
| ` | ||||
| 	if string(contents) != expect { | ||||
| 		t.Fatalf("File has incorrect contents '%s'.\nExpected '%s'", string(contents), expect) | ||||
| 	if string(contents) != expectContents { | ||||
| 		t.Fatalf("File has incorrect contents '%s'.\nExpected '%s'", string(contents), expectContents) | ||||
| 	} | ||||
| } | ||||
|  | ||||
|   | ||||
		Reference in New Issue
	
	Block a user