Ejemplo n.º 1
0
func (_ *File) RenderLocal(t *local.LocalTarget, a, e, changes *File) error {
	dirMode := os.FileMode(0755)
	fileMode, err := fi.ParseFileMode(fi.StringValue(e.Mode), 0644)
	if err != nil {
		return fmt.Errorf("invalid file mode for %q: %q", e.Path, fi.StringValue(e.Mode))
	}

	if a != nil {
		if e.IfNotExists {
			glog.V(2).Infof("file exists and IfNotExists set; skipping %q", e.Path)
			return nil
		}
	}

	changed := false
	if e.Type == FileType_Symlink {
		if changes.Symlink != nil {
			// This will currently fail if the target already exists.
			// That's probably a good thing for now ... it is hard to know what to do here!
			glog.Infof("Creating symlink %q -> %q", e.Path, *changes.Symlink)
			err := os.Symlink(*changes.Symlink, e.Path)
			if err != nil {
				return fmt.Errorf("error creating symlink %q -> %q: %v", e.Path, *changes.Symlink, err)
			}
			changed = true
		}
	} else if e.Type == FileType_Directory {
		if a == nil {
			parent := filepath.Dir(strings.TrimSuffix(e.Path, "/"))
			err := os.MkdirAll(parent, dirMode)
			if err != nil {
				return fmt.Errorf("error creating parent directories %q: %v", parent, err)
			}

			err = os.MkdirAll(e.Path, fileMode)
			if err != nil {
				return fmt.Errorf("error creating directory %q: %v", e.Path, err)
			}
			changed = true
		}
	} else if e.Type == FileType_File {
		if changes.Contents != nil {
			err = fi.WriteFile(e.Path, e.Contents, fileMode, dirMode)
			if err != nil {
				return fmt.Errorf("error copying file %q: %v", e.Path, err)
			}
			changed = true
		}
	} else {
		return fmt.Errorf("File type=%q not valid/supported", e.Type)
	}

	if changes.Mode != nil {
		modeChanged, err := fi.EnsureFileMode(e.Path, fileMode)
		if err != nil {
			return fmt.Errorf("error changing mode on %q: %v", e.Path, err)
		}
		changed = changed || modeChanged
	}

	if changes.Owner != nil || changes.Group != nil {
		ownerChanged, err := fi.EnsureFileOwner(e.Path, fi.StringValue(e.Owner), fi.StringValue(e.Group))
		if err != nil {
			return fmt.Errorf("error changing owner/group on %q: %v", e.Path, err)
		}
		changed = changed || ownerChanged
	}

	if changed && e.OnChangeExecute != nil {
		args := e.OnChangeExecute
		human := strings.Join(args, " ")

		glog.Infof("Changed; will execute OnChangeExecute command: %q", human)

		cmd := exec.Command(args[0], args[1:]...)
		output, err := cmd.CombinedOutput()
		if err != nil {
			return fmt.Errorf("error executing command %q: %v\nOutput: %s", human, err, output)
		}
	}

	return nil
}
Ejemplo n.º 2
0
func (_ *Service) RenderLocal(t *local.LocalTarget, a, e, changes *Service) error {
	serviceName := e.Name

	action := ""

	if changes.Running != nil && fi.BoolValue(e.ManageState) {
		if fi.BoolValue(e.Running) {
			action = "restart"
		} else {
			action = "stop"
		}
	}

	if changes.Definition != nil {
		servicePath := path.Join(systemdSystemPath, serviceName)
		err := fi.WriteFile(servicePath, fi.NewStringResource(*e.Definition), 0644, 0755)
		if err != nil {
			return fmt.Errorf("error writing systemd service file: %v", err)
		}

		glog.Infof("Reloading systemd configuration")
		cmd := exec.Command("systemctl", "daemon-reload")
		output, err := cmd.CombinedOutput()
		if err != nil {
			return fmt.Errorf("error doing systemd daemon-reload: %v\nOutput: %s", err, output)
		}
	}

	// "SmartRestart" - look at the obvious dependencies in the systemd service, restart if start time older
	if fi.BoolValue(e.ManageState) && fi.BoolValue(e.SmartRestart) {
		definition := fi.StringValue(e.Definition)
		if definition == "" && a != nil {
			definition = fi.StringValue(a.Definition)
		}

		if action == "" && fi.BoolValue(e.Running) && definition != "" {
			dependencies, err := getSystemdDependencies(serviceName, definition)
			if err != nil {
				return err
			}

			var newest time.Time
			for _, dependency := range dependencies {
				stat, err := os.Stat(dependency)
				if err != nil {
					glog.Infof("Ignoring error checking service dependency %q: %v", dependency, err)
					continue
				}
				modTime := stat.ModTime()
				if newest.IsZero() || newest.Before(modTime) {
					newest = modTime
				}
			}

			if !newest.IsZero() {
				properties, err := getSystemdStatus(e.Name)
				if err != nil {
					return err
				}

				startedAt := properties["ExecMainStartTimestamp"]
				if startedAt == "" {
					glog.Warningf("service was running, but did not have ExecMainStartTimestamp: %q", serviceName)
				} else {
					startedAtTime, err := time.Parse("Mon 2006-01-02 15:04:05 MST", startedAt)
					if err != nil {
						return fmt.Errorf("unable to parse service ExecMainStartTimestamp: %q", startedAt)
					}
					if startedAtTime.Before(newest) {
						glog.V(2).Infof("will restart service %q because dependency changed after service start", serviceName)
						action = "restart"
					} else {
						glog.V(2).Infof("will not restart service %q - started after dependencies", serviceName)
					}
				}
			}
		}
	}

	if action != "" && fi.BoolValue(e.ManageState) {
		glog.Infof("Restarting service %q", serviceName)
		cmd := exec.Command("systemctl", action, serviceName)
		output, err := cmd.CombinedOutput()
		if err != nil {
			return fmt.Errorf("error doing systemd %s %s: %v\nOutput: %s", action, serviceName, err, output)
		}
	}

	return nil
}