예제 #1
0
func (chk Installed) Status() (int, string, error) {
	name := getManager()
	options := managers[name]
	cmd := exec.Command(name, options, chk.pkg)
	out, err := cmd.CombinedOutput()
	outstr := string(out)
	var msg string
	switch {
	case err == nil && (name == "rpm" || name == "pacman"):
		return errutil.Success()
	// failures due to mising package
	case name == "dpkg" && strings.Contains(outstr, "not installed"):
	case name == "pacman" && strings.Contains(outstr, "not found"):
	case name == "rpm" && strings.Contains(outstr, "not installed"):
		msg := "Package was not found:"
		msg += "\n\tPackage name: " + chk.pkg
		msg += "\n\tPackage manager: " + name
		msg += "\n\tCommand output: " + outstr
		return 1, msg, nil
	// failures that were not due to packages not being installed
	case err != nil:
		errutil.ExecError(cmd, outstr, err)
	default:
		return errutil.Success()
	}
	return 1, msg, nil
}
예제 #2
0
func (chk SystemctlUnitFileStatus) Status() (int, string, error) {
	units, statuses, err := systemdstatus.UnitFileStatuses()
	if err != nil {
		return 1, "", err
	}
	var actualStatus string
	found := false
	for _, unit := range units {
		if unit == chk.unit {
			found = true
		}
	}
	if !found {
		return 1, "Unit file could not be found: " + chk.unit, nil
	}
	for i, un := range units {
		if un == chk.unit {
			actualStatus = statuses[i]
			if actualStatus == chk.status {
				return errutil.Success()
			}
		}
	}
	msg := "Unit didn't have status"
	return errutil.GenericError(msg, chk.status, []string{actualStatus})
}
예제 #3
0
func (chk Command) Status() (int, string, error) {
	cmd := exec.Command("bash", "-c", chk.Command)
	err := cmd.Start()
	if err != nil && strings.Contains(err.Error(), "not found in $PATH") {
		return 1, "Executable not found: " + chk.Command, nil
	} else if err != nil {
		return 1, "", err
	}
	if err = cmd.Wait(); err != nil {
		var exitCode int
		// this is convoluted, but should work on Windows & Unix
		if exiterr, ok := err.(*exec.ExitError); ok {
			if status, ok := exiterr.Sys().(syscall.WaitStatus); ok {
				exitCode = status.ExitStatus()
			}
		}
		// dummy, in case the above failed. We know it's not zero!
		if exitCode == 0 {
			exitCode = 1
		}
		out, _ := cmd.CombinedOutput() // don't care if this fails
		exitMessage := "Command exited with non-zero exit code:"
		exitMessage += "\n\tCommand: " + chk.Command
		exitMessage += "\n\tExit code: " + fmt.Sprint(exitCode)
		exitMessage += "\n\tOutput: " + string(out)
		return 1, exitMessage, nil
	}
	return errutil.Success()
}
예제 #4
0
// freeMemOrSwap is an abstraction of FreeMemory and FreeSwap, which measures
// if the desired resource has a quantity free above the amount specified
func freeMemOrSwap(input string, swapOrMem string) (int, string, error) {
	amount, units, err := chkutil.SeparateByteUnits(input)
	if err != nil {
		log.WithFields(log.Fields{
			"err": err.Error(),
		}).Fatal("Couldn't separate string into a scalar and units")
	}
	var actualAmount int
	switch strings.ToLower(swapOrMem) {
	case "memory":
		actualAmount, err = memstatus.FreeMemory(units)
	case "swap":
		actualAmount, err = memstatus.FreeSwap(units)
	default:
		log.Fatalf("Invalid option passed to freeMemoOrSwap: %s", swapOrMem)
	}
	if err != nil {
		return 1, "", err
	} else if actualAmount > amount {
		return errutil.Success()
	}
	msg := "Free " + swapOrMem + " lower than defined threshold"
	actualString := fmt.Sprint(actualAmount) + units
	return errutil.GenericError(msg, input, []string{actualString})
}
예제 #5
0
// RoutingTableMatch asks: Is this value in this column of the routing table?
func RoutingTableMatch(col string, str string) (int, string, error) {
	column := RoutingTableColumn(col)
	if tabular.StrIn(str, column) {
		return errutil.Success()
	}
	return errutil.GenericError("Not found in routing table", str, column)
}
예제 #6
0
func (chk PHPConfig) Status() (int, string, error) {
	// getPHPVariable returns the value of a PHP configuration value as a string
	// or just "" if it doesn't exist
	getPHPVariable := func(name string) (val string) {
		quote := func(str string) string {
			return "\"" + str + "\""
		}
		// php -r 'echo get_cfg_var("default_mimetype");
		echo := fmt.Sprintf("echo get_cfg_var(%s);", quote(name))
		cmd := exec.Command("php", "-r", echo)
		out, err := cmd.CombinedOutput()
		if err != nil {
			errutil.ExecError(cmd, string(out), err)
		}
		return string(out)
	}
	actualValue := getPHPVariable(chk.variable)
	if actualValue == chk.value {
		return errutil.Success()
	} else if actualValue == "" {
		msg := "PHP configuration variable not set"
		return errutil.GenericError(msg, chk.value, []string{actualValue})
	}
	msg := "PHP variable did not match expected value"
	return errutil.GenericError(msg, chk.value, []string{actualValue})
}
예제 #7
0
func (chk DockerRunningAPI) Status() (int, string, error) {
	running := getRunningContainersAPI(chk.path)
	if tabular.StrContainedIn(chk.name, running) {
		return errutil.Success()
	}
	msg := "Docker container not runnning"
	return errutil.GenericError(msg, chk.name, running)
}
예제 #8
0
// ResponseMatchesGeneral is an abstraction of ResponseMatches and
// ResponseMatchesInsecure that simply varies in the security of the connection
func ResponseMatchesGeneral(urlstr string, re *regexp.Regexp, secure bool) (int, string, error) {
	body := chkutil.URLToBytes(urlstr, secure)
	if re.Match(body) {
		return errutil.Success()
	}
	msg := "Response didn't match regexp"
	return errutil.GenericError(msg, re.String(), []string{string(body)})
}
예제 #9
0
func (chk FileMatches) Status() (int, string, error) {
	if chk.re.Match(chkutil.FileToBytes(chk.path)) {
		return errutil.Success()
	}
	msg := "File does not match regexp:"
	msg += "\n\tFile: " + chk.path
	msg += "\n\tRegexp: " + chk.re.String()
	return 1, msg, nil
}
예제 #10
0
func (chk UserInGroup) Status() (int, string, error) {
	boo, err := usrstatus.UserInGroup(chk.user, chk.group)
	if err != nil {
		return 1, "", err
	} else if boo {
		return errutil.Success()
	}
	return 1, "User not found in group", nil
}
예제 #11
0
// timerCheck is pure DRY for SystemctlTimer and SystemctlTimerLoaded
func timerCheck(unit string, all bool) (int, string, error) {
	timers, err := systemdstatus.Timers(all)
	if err != nil {
		return 1, "", err
	} else if tabular.StrIn(unit, timers) {
		return errutil.Success()
	}
	return errutil.GenericError("Timer not found", unit, timers)
}
예제 #12
0
func (chk SystemctlLoaded) Status() (int, string, error) {
	boo, err := systemdstatus.ServiceLoaded(chk.service)
	if err != nil {
		return 1, "", err
	} else if boo {
		return errutil.Success()
	}
	return 1, "Service wasn't loaded: " + chk.service, nil
}
예제 #13
0
// ipCheck(int, string, error) is an abstraction of IP4 and
// IP6
func ipCheck(name string, address *net.IP, version int) (int, string, error) {
	ips := netstatus.InterfaceIPs(name)
	for _, ip := range ips {
		if ip.Equal(*address) {
			return errutil.Success()
		}
	}
	return errutil.GenericError("Interface does not have IP", address, ips)
}
예제 #14
0
func (chk SystemctlActive) Status() (int, string, error) {
	boo, err := systemdstatus.ServiceActive(chk.service)
	if err != nil {
		return 1, "", err
	} else if boo {
		return errutil.Success()
	}
	return 1, "Service wasn't active: " + chk.service, nil
}
예제 #15
0
func (chk SystemctlSockListening) Status() (int, string, error) {
	listening, err := systemdstatus.ListeningSockets()
	if err != nil {
		return 1, "", err
	}
	if tabular.StrIn(chk.path, listening) {
		return errutil.Success()
	}
	return errutil.GenericError("Socket wasn't listening", chk.path, listening)
}
예제 #16
0
func (chk DockerImage) Status() (int, string, error) {
	images, err := dockerstatus.DockerImageRepositories()
	if err != nil {
		return 1, "", err
	}
	if tabular.StrIn(chk.name, images) {
		return errutil.Success()
	}
	return errutil.GenericError("Docker image was not found", chk.name, images)
}
예제 #17
0
func (chk Permissions) Status() (int, string, error) {
	passed, err := fsstatus.FileHasPermissions(chk.expectedPerms, chk.path)
	if err != nil {
		return 1, "", err
	}
	if passed {
		return errutil.Success()
	}
	return 1, "File did not have permissions: " + chk.expectedPerms, nil
}
예제 #18
0
func (chk PortTCP) Status() (int, string, error) {
	if netstatus.PortOpen("tcp", chk.port) {
		return errutil.Success()
	}
	// convert ports to string to send to errutil.GenericError
	var strPorts []string
	for _, port := range netstatus.OpenPorts("tcp") {
		strPorts = append(strPorts, fmt.Sprint(port))
	}
	return errutil.GenericError("Port not open", fmt.Sprint(chk.port), strPorts)
}
예제 #19
0
func (chk DockerImageRegexp) Status() (int, string, error) {
	images, err := dockerstatus.DockerImageRepositories()
	if err != nil {
		return 1, "", err
	}
	if tabular.ReIn(chk.re, images) {
		return errutil.Success()
	}
	msg := "Docker image was not found."
	return errutil.GenericError(msg, chk.re.String(), images)
}
예제 #20
0
func (chk DockerRunningRegexp) Status() (int, string, error) {
	running, err := dockerstatus.RunningContainers()
	if err != nil {
		return 1, "", err
	}
	if tabular.ReIn(chk.re, running) {
		return errutil.Success()
	}
	msg := "Docker container not runnning"
	return errutil.GenericError(msg, chk.re.String(), running)
}
예제 #21
0
// isType checks if the resource at path is of the type specified by name by
// passing path to checker. Mostly used to abstract Directory, File, Symlink.
func isType(name string, checker fileCondition, path string) (int, string, error) {
	boo, err := checker(path)
	if os.IsNotExist(err) {
		return 1, "No such file or directory: " + path, nil
	} else if os.IsPermission(err) {
		return 1, "", errors.New("Insufficient Permissions to read: " + path)
	} else if boo {
		return errutil.Success()
	}
	return 1, "Is not a " + name + ": " + path, nil
}
예제 #22
0
func (chk CommandOutputMatches) Status() (int, string, error) {
	cmd := exec.Command("bash", "-c", chk.Command)
	out, err := cmd.CombinedOutput()
	if err != nil {
		errutil.ExecError(cmd, string(out), err)
	}
	if chk.re.Match(out) {
		return errutil.Success()
	}
	msg := "Command output did not match regexp"
	return errutil.GenericError(msg, chk.re.String(), []string{string(out)})
}
예제 #23
0
func (chk SwapUsage) Status() (int, string, error) {
	actualPercentUsed, err := memstatus.UsedSwap("percent")
	if err != nil {
		return 1, "", err
	}
	if actualPercentUsed < int(chk.maxPercentUsed) {
		return errutil.Success()
	}
	msg := "Swap usage above defined maximum"
	slc := []string{fmt.Sprint(actualPercentUsed)}
	return errutil.GenericError(msg, fmt.Sprint(chk.maxPercentUsed), slc)
}
예제 #24
0
func (chk InodeUsage) Status() (int, string, error) {
	actualPercentUsed, err := fsstatus.PercentInodesUsed(chk.filesystem)
	if err != nil {
		return 1, "Unexpected error", err
	}
	if actualPercentUsed < chk.maxPercentUsed {
		return errutil.Success()
	}
	msg := "More disk space used than expected"
	slc := []string{fmt.Sprint(actualPercentUsed) + "%"}
	return errutil.GenericError(msg, fmt.Sprint(chk.maxPercentUsed)+"%", slc)
}
예제 #25
0
// genericUserField constructs (int, string, error)s that check if a given field of a User
// object found by lookupUser has a given value
func genericUserField(usernameOrUID string, fieldName string, fieldValue string) (int, string, error) {
	boolean, err := userHasField(usernameOrUID, fieldName, fieldValue)
	if err != nil {
		return 1, "User does not exist: " + usernameOrUID, nil
	} else if boolean {
		return errutil.Success()
	}
	msg := "User does not have expected " + fieldName + ": "
	msg += "\nUser: "******"\nGiven: " + fieldValue
	return 1, msg, nil
}
예제 #26
0
func (chk Module) Status() (int, string, error) {
	// kernelModules returns a list of all Modules that are currently loaded
	// TODO just read from /proc/Modules
	kernelModules := func() (Modules []string) {
		cmd := exec.Command("/sbin/lsmod")
		return chkutil.CommandColumnNoHeader(0, cmd)
	}
	Modules := kernelModules()
	if tabular.StrIn(chk.name, Modules) {
		return errutil.Success()
	}
	return errutil.GenericError("Module is not loaded", chk.name, Modules)
}
예제 #27
0
func (chk GroupID) Status() (int, string, error) {
	groups, err := usrstatus.Groups()
	if err != nil {
		return 0, "", err
	}
	for _, g := range groups {
		if g.Name == chk.name {
			if g.ID == chk.id {
				return errutil.Success()
			}
			msg := "Group does not have expected ID"
			return errutil.GenericError(msg, chk.id, []int{g.ID})
		}
	}
	return groupNotFound(chk.name)
}
예제 #28
0
func (chk InterfaceExists) Status() (int, string, error) {
	// getInterfaceNames returns the names of all network interfaces
	getInterfaceNames := func() (interfaces []string) {
		for _, iface := range netstatus.GetInterfaces() {
			interfaces = append(interfaces, iface.Name)
		}
		return
	}
	interfaces := getInterfaceNames()
	for _, iface := range interfaces {
		if iface == chk.name {
			return errutil.Success()
		}
	}
	return errutil.GenericError("Interface does not exist", chk.name, interfaces)
}
예제 #29
0
func (chk Temp) Status() (int, string, error) {
	// allCoreTemps returns the Temperature of each core
	allCoreTemps := func() (Temps []int) {
		cmd := exec.Command("sensors")
		out, err := cmd.CombinedOutput()
		outstr := string(out)
		errutil.ExecError(cmd, outstr, err)
		restr := `Core\s\d+:\s+[\+\-](?P<Temp>\d+)\.*\d*°C`
		re := regexp.MustCompile(restr)
		for _, line := range regexp.MustCompile(`\n+`).Split(outstr, -1) {
			if re.MatchString(line) {
				// submatch captures only the integer part of the Temperature
				matchDict := chkutil.SubmatchMap(re, line)
				if _, ok := matchDict["Temp"]; !ok {
					log.WithFields(log.Fields{
						"regexp":    re.String(),
						"matchDict": matchDict,
						"output":    outstr,
					}).Fatal("Couldn't find any Temperatures in `sensors` output")
				}
				TempInt64, err := strconv.ParseInt(matchDict["Temp"], 10, 64)
				if err != nil {
					log.WithFields(log.Fields{
						"regexp":    re.String(),
						"matchDict": matchDict,
						"output":    outstr,
						"error":     err.Error(),
					}).Fatal("Couldn't parse integer from `sensors` output")
				}
				Temps = append(Temps, int(TempInt64))
			}
		}
		return Temps
	}
	// getCoreTemp returns an integer Temperature for a certain core
	getCoreTemp := func(core int) (Temp int) {
		Temps := allCoreTemps()
		errutil.IndexError("No such core available", core, Temps)
		return Temps[core]
	}
	Temp := getCoreTemp(0)
	if Temp < int(chk.max) {
		return errutil.Success()
	}
	msg := "Core Temp exceeds defined maximum"
	return errutil.GenericError(msg, chk.max, []string{fmt.Sprint(Temp)})
}
예제 #30
0
func (chk PacmanIgnore) Status() (int, string, error) {
	path := "/etc/pacman.conf"
	data := chkutil.FileToString(path)
	re := regexp.MustCompile(`[^#]IgnorePkg\s+=\s+.+`)
	find := re.FindString(data)
	var packages []string
	if find != "" {
		spl := strings.Split(find, " ")
		errutil.IndexError("Not enough lines in "+path, 2, spl)
		packages = spl[2:] // first two are "IgnorePkg" and "="
		if tabular.StrIn(chk.pkg, packages) {
			return errutil.Success()
		}
	}
	msg := "Couldn't find package in IgnorePkg"
	return errutil.GenericError(msg, chk.pkg, packages)
}