rules

package
v0.0.0-...-d41f2af Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Jan 9, 2023 License: Apache-2.0 Imports: 11 Imported by: 0

Documentation

Index

Constants

This section is empty.

Variables

View Source
var IngressNeedsAnnotation = engine.NewRule(
	func(old runtime.Object, new runtime.Object, ctx *engine.RuleHandlerContext) {
		ingress := new.(*networkingv1.Ingress)
		logger := log.WithFields(log.Fields{"name": ingress.Name, "namespace": ingress.Namespace, "rule": "IngressNeedsAnnotation"})
		annotation := ingress.GetAnnotations()
		hasAnnotation := false
		for key := range annotation {
			if strings.HasPrefix(key, prefix) {
				logger.Debugf("Checking annotation %s", key)
				hasAnnotation = true
				break
			}
		}
		if !hasAnnotation {
			ctx.Alertf(new, "You don't have any alerts set up for your ingress: %s.%s. You may want to check https://github.com/uswitch/heimdall for more info.", ingress.Namespace, ingress.Name)
		}
	}, engine.WantIngress)
View Source
var RequireCronJobHistoryLimits = engine.NewRule(
	func(old runtime.Object, new runtime.Object, ctx *engine.RuleHandlerContext) {
		job := new.(*batchv1.CronJob)
		logger := log.WithFields(log.Fields{"rule": "RequireCronJobHistoryLimits", "namespace": job.GetNamespace(), "name": job.GetName()})

		logger.Debugf("checking for history limit requirement")

		messages := make([]string, 0)
		if job.Spec.SuccessfulJobsHistoryLimit == nil {
			message := fmt.Sprintf("CronJob `%s/%s` doesn't specify `.spec.successfulJobsHistoryLimit`. Must be 10 or under.", job.GetNamespace(), job.GetName())
			messages = append(messages, message)
		} else {
			if *job.Spec.SuccessfulJobsHistoryLimit > 10 {
				message := fmt.Sprintf("CronJob `%s/%s` `.spec.succcessfulJobsHistoryLimit` is too high: `%d`. Must be 10 or under.", job.GetNamespace(), job.GetName(), *job.Spec.SuccessfulJobsHistoryLimit)
				messages = append(messages, message)
			}
		}

		if job.Spec.FailedJobsHistoryLimit == nil {
			message := fmt.Sprintf("CronJob `%s/%s` doesn't specify `.spec.failedJobsHistoryLimit`. Must be 10 or under.", job.GetNamespace(), job.GetName())
			messages = append(messages, message)
		} else {
			if *job.Spec.FailedJobsHistoryLimit > 10 {
				message := fmt.Sprintf("CronJob `%s/%s` `.spec.failedJobsHistoryLimit` is too high: `%d`. Must be 10 or under.", job.GetNamespace(), job.GetName(), *job.Spec.FailedJobsHistoryLimit)
				messages = append(messages, message)
			}
		}

		for _, msg := range messages {
			ctx.Alert(job, msg)
		}
	},
	engine.WantCronJobs,
)
View Source
var ResourceAnnotationRule = engine.NewRule(
	func(old runtime.Object, new runtime.Object, ctx *engine.RuleHandlerContext) {
		deployment := new.(*appsv1.Deployment)
		logger := log.WithFields(log.Fields{"rule": "ResourceAnnotationRule", "name": deployment.Name, "namespace": deployment.Namespace})

		newInViolation := containersInViolation(deployment)

		if old == nil || !reflect.DeepEqual(containersInViolation(old.(*appsv1.Deployment)), newInViolation) {
			if len(newInViolation) == 0 {
				if old != nil {
					ctx.Alertf(new, "Thanks for sorting your resource requests and limits on %s.%s!", deployment.ObjectMeta.Namespace, podNameForDeployment(deployment))
				}
			} else {
				ctx.Alertf(new, "Please add resource requests and limits to the containers (%s) part of %s.%s", strings.Join(newInViolation, ", "), deployment.ObjectMeta.Namespace, podNameForDeployment(deployment))
			}
		} else {
			logger.Debugf("ResourceAnnotationRule: %s.%s hadn't changed", deployment.ObjectMeta.Namespace, podNameForDeployment(deployment))
		}
	},
	engine.WantDeployments,
)
View Source
var ScrapeNeedsPortsRule = engine.NewRule(
	func(old runtime.Object, new runtime.Object, ctx *engine.RuleHandlerContext) {
		deployment := new.(*appsv1.Deployment)
		logger := log.WithFields(log.Fields{"name": deployment.Name, "namespace": deployment.Namespace, "rule": "ScrapeNeedsPortsRule"})

		if old == nil || validScrapeAndPorts(old.(*appsv1.Deployment)) != validScrapeAndPorts(deployment) {
			podName := podNameForDeployment(deployment)

			if validScrapeAndPorts(deployment) {
				if old != nil {
					ctx.Alertf(new, "Thanks for sorting the ports for scraping on %s.%s", deployment.ObjectMeta.Namespace, podName)
				}
			} else {
				ctx.Alertf(new, "%s.%s wants to be scraped so it needs to expose some ports", deployment.ObjectMeta.Namespace, podName)
			}
		} else {
			logger.Debugf("ScrapeNeedsPortsRule: %s.%s hadn't changed", deployment.ObjectMeta.Namespace, podNameForDeployment(deployment))
		}
	},
	engine.WantDeployments,
)
View Source
var UnsuccessfulExitRule = engine.NewRule(
	func(old runtime.Object, newObj runtime.Object, ctx *engine.RuleHandlerContext) {
		pod := newObj.(*v1.Pod)

		logger := log.WithFields(log.Fields{"name": pod.Name, "namespace": pod.Namespace, "rule": "UnsuccessfulExitRule"})

		for _, c := range pod.Status.ContainerStatuses {
			logger = logger.WithFields(log.Fields{"container.name": c.Name, "container.id": c.ContainerID})
			contx := context.Background()
			if c.State.Terminated != nil {
				switch exitCode := c.State.Terminated.ExitCode; exitCode {
				case 0:
					break
				case 143:
					break
				case 137:
					ctx.Alertf(newObj, "Pod `%s.%s` (container: `%s`) was killed by a SIGKILL. Please make sure you gracefully shut down in time or extend `terminationGracePeriodSeconds` on your pod.", pod.ObjectMeta.Namespace, pod.ObjectMeta.Name, c.Name)
				default:
					tailLines := int64(20)
					opts := &v1.PodLogOptions{
						Container: c.Name,
						Follow:    false,
						Previous:  false,
						TailLines: &tailLines,
					}
					message := fmt.Sprintf("Pod `%s.%s` (container: `%s`) has failed with exit code: `%d`", pod.ObjectMeta.Namespace, pod.ObjectMeta.Name, c.Name, c.State.Terminated.ExitCode)

					result := ctx.Client().CoreV1().Pods(pod.Namespace).GetLogs(pod.Name, opts).Do(contx)
					if result.Error() != nil {
						logger.Errorf("error retrieving pod logs: %s", result.Error())
						ctx.Alert(newObj, message)
						return
					}

					bytes, err := result.Raw()
					if err != nil {
						logger.Errorf("error retrieving pod logs: %s", err.Error())
						ctx.Alert(newObj, message)
						return
					}

					logger.Debugf("log: \"%s\"", string(bytes))
					ctx.Alertf(newObj, "%s\n\n```%s```", message, string(bytes))
				}
			}
		}
	},
	engine.WantPods,
)

Functions

This section is empty.

Types

This section is empty.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL