feat(unit.command): Add command field to units
This commit is contained in:
		| @@ -28,9 +28,16 @@ coreos: | ||||
| Arbitrary systemd units may be provided in the `coreos.units` attribute. | ||||
| `coreos.units` is a list of objects with the following fields: | ||||
|  | ||||
| - **name**: string representing unit's name | ||||
| - **runtime**: boolean indicating whether or not to persist the unit across reboots. This is analagous to the `--runtime` flag to `systemd enable`. | ||||
| - **content**: plaintext string representing entire unit file | ||||
| - **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. | ||||
| - **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. | ||||
|  | ||||
| **NOTE:** The command field is ignored for all network, netdev, and link units. The systemd-networkd.service unit will be restarted in their place. | ||||
|  | ||||
| ##### Examples | ||||
|  | ||||
| Write a unit to disk, automatically starting it. | ||||
|  | ||||
| ``` | ||||
| #cloud-config | ||||
| @@ -53,6 +60,19 @@ coreos: | ||||
|           WantedBy=local.target | ||||
| ``` | ||||
|  | ||||
| Start the builtin `etcd` and `fleet` services: | ||||
|  | ||||
| ``` | ||||
| # cloud-config | ||||
|  | ||||
| coreos: | ||||
|     units: | ||||
|       - name: etcd.service | ||||
|         command: start | ||||
|       - name: fleet.service | ||||
|         command: start | ||||
|  | ||||
|  | ||||
| ## Cloud-Config Parameters | ||||
|  | ||||
| ### ssh_authorized_keys | ||||
|   | ||||
| @@ -114,26 +114,49 @@ 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 { | ||||
| 			log.Printf("Placing unit %s on filesystem", unit.Name) | ||||
| 			dst, err := system.PlaceUnit(&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 { | ||||
| 					return err | ||||
| 				} | ||||
| 				log.Printf("Placed unit %s at %s", unit.Name, dst) | ||||
|  | ||||
| 				if unit.Group() != "network" { | ||||
| 					log.Printf("Enabling unit file %s", dst) | ||||
| 					if err := system.EnableUnitFile(dst, unit.Runtime); err != nil { | ||||
| 						return err | ||||
| 					} | ||||
| 					log.Printf("Enabled unit %s", unit.Name) | ||||
| 				} else { | ||||
| 					log.Printf("Skipping enable for network-like unit %s", unit.Name) | ||||
| 				} | ||||
| 			} | ||||
|  | ||||
| 			if unit.Group() != "network" { | ||||
| 				command := unit.Command | ||||
| 				if command == "" { | ||||
| 					command = "restart" | ||||
| 				} | ||||
| 				commands[unit.Name] = command | ||||
| 			} else { | ||||
| 				commands["systemd-networkd.service"] = "restart" | ||||
| 			} | ||||
| 		} | ||||
|  | ||||
| 		system.DaemonReload() | ||||
|  | ||||
| 		for unit, command := range commands { | ||||
| 			log.Printf("Calling unit command '%s %s'", command, unit) | ||||
| 			res, err := system.RunUnitCommand(command, unit) | ||||
| 			if err != nil { | ||||
| 				return err | ||||
| 			} | ||||
| 			log.Printf("Placed unit %s at %s", unit.Name, dst) | ||||
|  | ||||
| 			if unit.Group() != "network" { | ||||
| 				log.Printf("Enabling unit file %s", dst) | ||||
| 				if err := system.EnableUnitFile(dst, unit.Runtime); err != nil { | ||||
| 					return err | ||||
| 				} | ||||
| 				log.Printf("Enabled unit %s", unit.Name) | ||||
| 			} else { | ||||
| 				log.Printf("Skipping enable for network-like unit %s", unit.Name) | ||||
| 			} | ||||
| 			log.Printf("Result of '%s %s': %s", command, unit, res) | ||||
| 		} | ||||
| 		system.DaemonReload() | ||||
| 		system.StartUnits(cfg.Coreos.Units) | ||||
| 	} | ||||
|  | ||||
| 	return nil | ||||
|   | ||||
| @@ -21,6 +21,7 @@ type Unit struct { | ||||
| 	Name    string | ||||
| 	Runtime bool | ||||
| 	Content string | ||||
| 	Command string | ||||
| } | ||||
|  | ||||
| func (u *Unit) Type() string { | ||||
| @@ -80,34 +81,33 @@ func EnableUnitFile(file string, runtime bool) error { | ||||
| 	return err | ||||
| } | ||||
|  | ||||
| func separateNetworkUnits(units []Unit) ([]Unit, []Unit) { | ||||
| 	networkUnits := make([]Unit, 0) | ||||
| 	nonNetworkUnits := make([]Unit, 0) | ||||
| 	for _, unit := range units { | ||||
| 		if unit.Group() == "network" { | ||||
| 			networkUnits = append(networkUnits, unit) | ||||
| 		} else { | ||||
| 			nonNetworkUnits = append(nonNetworkUnits, unit) | ||||
| 		} | ||||
| 	} | ||||
| 	return networkUnits, nonNetworkUnits | ||||
| } | ||||
|  | ||||
| func StartUnits(units []Unit) error { | ||||
| 	networkUnits, nonNetworkUnits := separateNetworkUnits(units) | ||||
| 	if len(networkUnits) > 0 { | ||||
| 		if err := RestartUnitByName("systemd-networkd.service"); err != nil { | ||||
| 			return err | ||||
| 		} | ||||
| func RunUnitCommand(command, unit string) (string, error) { | ||||
| 	conn, err := dbus.New() | ||||
| 	if err != nil { | ||||
| 		return "", err | ||||
| 	} | ||||
|  | ||||
| 	for _, unit := range nonNetworkUnits { | ||||
| 		if err := RestartUnitByName(unit.Name); err != nil { | ||||
| 			return err | ||||
| 		} | ||||
| 	var fn func(string, string) (string, error) | ||||
| 	switch command { | ||||
| 	case "start": | ||||
| 		fn = conn.StartUnit | ||||
| 	case "stop": | ||||
| 		fn = conn.StopUnit | ||||
| 	case "restart": | ||||
| 		fn = conn.RestartUnit | ||||
| 	case "reload": | ||||
| 		fn = conn.ReloadUnit | ||||
| 	case "try-restart": | ||||
| 		fn = conn.TryRestartUnit | ||||
| 	case "reload-or-restart": | ||||
| 		fn = conn.ReloadOrRestartUnit | ||||
| 	case "reload-or-try-restart": | ||||
| 		fn = conn.ReloadOrTryRestartUnit | ||||
| 	default: | ||||
| 		return "", fmt.Errorf("Unsupported systemd command %q", command) | ||||
| 	} | ||||
|  | ||||
| 	return nil | ||||
| 	return fn(unit, "replace") | ||||
| } | ||||
|  | ||||
| func DaemonReload() error { | ||||
| @@ -120,19 +120,6 @@ func DaemonReload() error { | ||||
| 	return err | ||||
| } | ||||
|  | ||||
| func RestartUnitByName(name string) error { | ||||
| 	log.Printf("Restarting unit %s", name) | ||||
| 	conn, err := dbus.New() | ||||
| 	if err != nil { | ||||
| 		return err | ||||
| 	} | ||||
|  | ||||
| 	output, err := conn.RestartUnit(name, "replace") | ||||
| 	log.Printf("Restart completed with '%s'", output) | ||||
|  | ||||
| 	return err | ||||
| } | ||||
|  | ||||
| func ExecuteScript(scriptPath string) (string, error) { | ||||
| 	props := []dbus.Property{ | ||||
| 		dbus.PropDescription("Unit generated and executed by coreos-cloudinit on behalf of user"), | ||||
|   | ||||
		Reference in New Issue
	
	Block a user