{
  "description": "NodeHealthCheck is the Schema for the nodehealthchecks API",
  "properties": {
    "apiVersion": {
      "description": "APIVersion defines the versioned schema of this representation of an object.\nServers should convert recognized schemas to the latest internal value, and\nmay reject unrecognized values.\nMore info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources",
      "type": [
        "string",
        "null"
      ]
    },
    "kind": {
      "description": "Kind is a string value representing the REST resource this object represents.\nServers may infer this from the endpoint the client submits requests to.\nCannot be updated.\nIn CamelCase.\nMore info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds",
      "type": [
        "string",
        "null"
      ]
    },
    "metadata": {
      "type": [
        "object",
        "null"
      ]
    },
    "spec": {
      "additionalProperties": false,
      "description": "NodeHealthCheckSpec defines the desired state of NodeHealthCheck",
      "properties": {
        "escalatingRemediations": {
          "description": "EscalatingRemediations contain a list of ordered remediation templates with a timeout.\nThe remediation templates will be used one after another, until the unhealthy node\ngets healthy within the timeout of the currently processed remediation. The order of\nremediation is defined by the \"order\" field of each \"escalatingRemediation\".\n\nMutually exclusive with RemediationTemplate",
          "items": {
            "additionalProperties": false,
            "description": "EscalatingRemediation defines a remediation template with order and timeout",
            "properties": {
              "order": {
                "description": "Order defines the order for this remediation.\nRemediations with lower order will be used before remediations with higher order.\nRemediations must not have the same order.",
                "type": "integer"
              },
              "remediationTemplate": {
                "additionalProperties": false,
                "description": "RemediationTemplate is a reference to a remediation template\nprovided by a remediation provider.\n\nIf a node needs remediation the controller will create an object from this template\nand then it should be picked up by a remediation provider.",
                "properties": {
                  "apiVersion": {
                    "description": "API version of the referent.",
                    "type": [
                      "string",
                      "null"
                    ]
                  },
                  "fieldPath": {
                    "description": "If referring to a piece of an object instead of an entire object, this string\nshould contain a valid JSON/Go field access statement, such as desiredState.manifest.containers[2].\nFor example, if the object reference is to a container within a pod, this would take on a value like:\n\"spec.containers{name}\" (where \"name\" refers to the name of the container that triggered\nthe event) or if no container name is specified \"spec.containers[2]\" (container with\nindex 2 in this pod). This syntax is chosen only to have some well-defined way of\nreferencing a part of an object.",
                    "type": [
                      "string",
                      "null"
                    ]
                  },
                  "kind": {
                    "description": "Kind of the referent.\nMore info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds",
                    "type": [
                      "string",
                      "null"
                    ]
                  },
                  "name": {
                    "description": "Name of the referent.\nMore info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names",
                    "type": [
                      "string",
                      "null"
                    ]
                  },
                  "namespace": {
                    "description": "Namespace of the referent.\nMore info: https://kubernetes.io/docs/concepts/overview/working-with-objects/namespaces/",
                    "type": [
                      "string",
                      "null"
                    ]
                  },
                  "resourceVersion": {
                    "description": "Specific resourceVersion to which this reference is made, if any.\nMore info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#concurrency-control-and-consistency",
                    "type": [
                      "string",
                      "null"
                    ]
                  },
                  "uid": {
                    "description": "UID of the referent.\nMore info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#uids",
                    "type": [
                      "string",
                      "null"
                    ]
                  }
                },
                "type": "object",
                "x-kubernetes-map-type": "atomic"
              },
              "timeout": {
                "description": "Timeout defines how long NHC will wait for the node getting healthy\nbefore the next remediation (if any) will be used. When the last remediation times out,\nthe overall remediation is considered as failed.\nAs a safeguard for preventing parallel remediations, a minimum of 60s is enforced.\n\nExpects a string of decimal numbers each with optional\nfraction and a unit suffix, eg \"300ms\", \"1.5h\" or \"2h45m\".\nValid time units are \"ns\", \"us\" (or \"µs\"), \"ms\", \"s\", \"m\", \"h\".",
                "pattern": "^([0-9]+(\\.[0-9]+)?(ns|us|µs|ms|s|m|h))+$",
                "type": "string"
              }
            },
            "required": [
              "order",
              "remediationTemplate",
              "timeout"
            ],
            "type": "object"
          },
          "type": [
            "array",
            "null"
          ]
        },
        "healthyDelay": {
          "description": "HealthyDelay is the time before NHC would allow a node to be healthy again.\nA negative value means that NHC will never consider the node healthy and a manual intervention is expected",
          "pattern": "^-?([0-9]+(\\.[0-9]+)?(ns|us|µs|ms|s|m|h))+$",
          "type": [
            "string",
            "null"
          ]
        },
        "maxUnhealthy": {
          "description": "Remediation is allowed if no more than \"MaxUnhealthy\" nodes selected by \"selector\" are not healthy.\nExpects either a non-negative integer value or a percentage value.\nPercentage values must be positive whole numbers and are capped at 100%.\n0% is valid and will block all remediation.\nMaxUnhealthy should not be used with remediators that delete nodes (e.g. MachineDeletionRemediation),\nas this breaks the logic for counting healthy and unhealthy nodes.\nMinHealthy and MaxUnhealthy are configuring the same aspect,\nand they cannot be used at the same time.",
          "oneOf": [
            {
              "pattern": "^((100|[0-9]{1,2})%|[0-9]+)$",
              "type": "string"
            },
            {
              "type": "integer"
            },
            {
              "type": "null"
            }
          ],
          "x-kubernetes-int-or-string": true
        },
        "minHealthy": {
          "description": "Remediation is allowed if at least \"MinHealthy\" nodes selected by \"selector\" are healthy.\nExpects either a non-negative integer value or a percentage value.\nPercentage values must be positive whole numbers and are capped at 100%.\n100% is valid and will block all remediation.\nMinHealthy and MaxUnhealthy are configuring the same aspect,\nand they cannot be used at the same time.",
          "oneOf": [
            {
              "pattern": "^((100|[0-9]{1,2})%|[0-9]+)$",
              "type": "string"
            },
            {
              "type": "integer"
            },
            {
              "type": "null"
            }
          ],
          "x-kubernetes-int-or-string": true
        },
        "pauseRequests": {
          "description": "PauseRequests will prevent any new remediation to start, while in-flight remediations\nkeep running. Each entry is free form, and ideally represents the requested party reason\nfor this pausing - i.e:\n    \"imaginary-cluster-upgrade-manager-operator\"",
          "items": {
            "type": "string"
          },
          "type": [
            "array",
            "null"
          ]
        },
        "remediationTemplate": {
          "additionalProperties": false,
          "description": "RemediationTemplate is a reference to a remediation template\nprovided by an infrastructure provider.\n\nIf a node needs remediation the controller will create an object from this template\nand then it should be picked up by a remediation provider.\n\nMutually exclusive with EscalatingRemediations",
          "properties": {
            "apiVersion": {
              "description": "API version of the referent.",
              "type": [
                "string",
                "null"
              ]
            },
            "fieldPath": {
              "description": "If referring to a piece of an object instead of an entire object, this string\nshould contain a valid JSON/Go field access statement, such as desiredState.manifest.containers[2].\nFor example, if the object reference is to a container within a pod, this would take on a value like:\n\"spec.containers{name}\" (where \"name\" refers to the name of the container that triggered\nthe event) or if no container name is specified \"spec.containers[2]\" (container with\nindex 2 in this pod). This syntax is chosen only to have some well-defined way of\nreferencing a part of an object.",
              "type": [
                "string",
                "null"
              ]
            },
            "kind": {
              "description": "Kind of the referent.\nMore info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds",
              "type": [
                "string",
                "null"
              ]
            },
            "name": {
              "description": "Name of the referent.\nMore info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names",
              "type": [
                "string",
                "null"
              ]
            },
            "namespace": {
              "description": "Namespace of the referent.\nMore info: https://kubernetes.io/docs/concepts/overview/working-with-objects/namespaces/",
              "type": [
                "string",
                "null"
              ]
            },
            "resourceVersion": {
              "description": "Specific resourceVersion to which this reference is made, if any.\nMore info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#concurrency-control-and-consistency",
              "type": [
                "string",
                "null"
              ]
            },
            "uid": {
              "description": "UID of the referent.\nMore info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#uids",
              "type": [
                "string",
                "null"
              ]
            }
          },
          "type": [
            "object",
            "null"
          ],
          "x-kubernetes-map-type": "atomic"
        },
        "selector": {
          "additionalProperties": false,
          "description": "Label selector to match nodes whose health will be exercised.\n\nSelecting both control-plane and worker nodes in one NHC CR is\nhighly discouraged and can result in undesired behaviour.\n\nNote: mandatory now for above reason, but for backwards compatibility existing\nCRs will continue to work with an empty selector, which matches all nodes.",
          "properties": {
            "matchExpressions": {
              "description": "matchExpressions is a list of label selector requirements. The requirements are ANDed.",
              "items": {
                "additionalProperties": false,
                "description": "A label selector requirement is a selector that contains values, a key, and an operator that\nrelates the key and values.",
                "properties": {
                  "key": {
                    "description": "key is the label key that the selector applies to.",
                    "type": "string"
                  },
                  "operator": {
                    "description": "operator represents a key's relationship to a set of values.\nValid operators are In, NotIn, Exists and DoesNotExist.",
                    "type": "string"
                  },
                  "values": {
                    "description": "values is an array of string values. If the operator is In or NotIn,\nthe values array must be non-empty. If the operator is Exists or DoesNotExist,\nthe values array must be empty. This array is replaced during a strategic\nmerge patch.",
                    "items": {
                      "type": "string"
                    },
                    "type": [
                      "array",
                      "null"
                    ],
                    "x-kubernetes-list-type": "atomic"
                  }
                },
                "required": [
                  "key",
                  "operator"
                ],
                "type": "object"
              },
              "type": [
                "array",
                "null"
              ],
              "x-kubernetes-list-type": "atomic"
            },
            "matchLabels": {
              "additionalProperties": {
                "type": "string"
              },
              "description": "matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels\nmap is equivalent to an element of matchExpressions, whose key field is \"key\", the\noperator is \"In\", and the values array contains only \"value\". The requirements are ANDed.",
              "type": [
                "object",
                "null"
              ]
            }
          },
          "type": [
            "object",
            "null"
          ],
          "x-kubernetes-map-type": "atomic"
        },
        "stormCooldownDuration": {
          "description": "StormCooldownDuration defines the duration of an optional cooldown phase after a storm.\nA \"storm\" happens when the number of (un)healthy nodes exceeds the threshold defined by minHealthy or maxUnhealthy.\nSometimes this is triggered by a single root cause.\nWhen that cause is fixed, there is a risk to remediate healthy nodes:\nthe async nature of node status updates would result in only some nodes being detected as healthy by NHC in a first round of updates,\nwhich results in minHealthy or maxUnhealthy threshold being fulfilled (the storm ends) and triggering unneeded new remediation.\nThe storm cooldown phase will prevent creation of new remediation for the given duration by giving NHC some time to get the latest node statuses.\n\nExpects a string of decimal numbers each with optional fraction and a unit\nsuffix, e.g. \"300ms\", \"1.5h\" or \"2h45m\". Valid time units are \"ns\", \"us\"\n(or \"µs\"), \"ms\", \"s\", \"m\", \"h\".",
          "pattern": "^([0-9]+(\\.[0-9]+)?(ns|us|µs|ms|s|m|h))+$",
          "type": [
            "string",
            "null"
          ]
        },
        "unhealthyConditions": {
          "default": [
            {
              "duration": "300s",
              "status": "False",
              "type": "Ready"
            },
            {
              "duration": "300s",
              "status": "Unknown",
              "type": "Ready"
            }
          ],
          "description": "UnhealthyConditions contains a list of the conditions that determine\nwhether a node is considered unhealthy.  The conditions are combined in a\nlogical OR, i.e. if any of the conditions is met, the node is unhealthy.",
          "items": {
            "additionalProperties": false,
            "description": "UnhealthyCondition represents a Node condition type and value with a\nspecified duration. When the named condition has been in the given\nstatus for at least the duration value a node is considered unhealthy.",
            "properties": {
              "duration": {
                "description": "Duration of the condition specified when a node is considered unhealthy.\n\nExpects a string of decimal numbers each with optional\nfraction and a unit suffix, eg \"300ms\", \"1.5h\" or \"2h45m\".\nValid time units are \"ns\", \"us\" (or \"µs\"), \"ms\", \"s\", \"m\", \"h\".",
                "pattern": "^([0-9]+(\\.[0-9]+)?(ns|us|µs|ms|s|m|h))+$",
                "type": "string"
              },
              "status": {
                "description": "The condition status in the node's status to watch for.\nTypically False, True or Unknown.",
                "minLength": 1,
                "type": "string"
              },
              "type": {
                "description": "The condition type in the node's status to watch for.",
                "minLength": 1,
                "type": "string"
              }
            },
            "required": [
              "duration",
              "status",
              "type"
            ],
            "type": "object"
          },
          "type": [
            "array",
            "null"
          ],
          "x-kubernetes-list-map-keys": [
            "type",
            "status"
          ],
          "x-kubernetes-list-type": "map"
        }
      },
      "type": [
        "object",
        "null"
      ]
    },
    "status": {
      "additionalProperties": false,
      "description": "NodeHealthCheckStatus defines the observed state of NodeHealthCheck",
      "properties": {
        "conditions": {
          "description": "Represents the observations of a NodeHealthCheck's current state.\nKnown .status.conditions.type are: \"Disabled\"",
          "items": {
            "additionalProperties": false,
            "description": "Condition contains details for one aspect of the current state of this API Resource.",
            "properties": {
              "lastTransitionTime": {
                "description": "lastTransitionTime is the last time the condition transitioned from one status to another.\nThis should be when the underlying condition changed.  If that is not known, then using the time when the API field changed is acceptable.",
                "format": "date-time",
                "type": "string"
              },
              "message": {
                "description": "message is a human readable message indicating details about the transition.\nThis may be an empty string.",
                "maxLength": 32768,
                "type": "string"
              },
              "observedGeneration": {
                "description": "observedGeneration represents the .metadata.generation that the condition was set based upon.\nFor instance, if .metadata.generation is currently 12, but the .status.conditions[x].observedGeneration is 9, the condition is out of date\nwith respect to the current state of the instance.",
                "format": "int64",
                "minimum": 0,
                "type": [
                  "integer",
                  "null"
                ]
              },
              "reason": {
                "description": "reason contains a programmatic identifier indicating the reason for the condition's last transition.\nProducers of specific condition types may define expected values and meanings for this field,\nand whether the values are considered a guaranteed API.\nThe value should be a CamelCase string.\nThis field may not be empty.",
                "maxLength": 1024,
                "minLength": 1,
                "pattern": "^[A-Za-z]([A-Za-z0-9_,:]*[A-Za-z0-9_])?$",
                "type": "string"
              },
              "status": {
                "description": "status of the condition, one of True, False, Unknown.",
                "enum": [
                  "True",
                  "False",
                  "Unknown"
                ],
                "type": "string"
              },
              "type": {
                "description": "type of condition in CamelCase or in foo.example.com/CamelCase.",
                "maxLength": 316,
                "pattern": "^([a-z0-9]([-a-z0-9]*[a-z0-9])?(\\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*/)?(([A-Za-z0-9][-A-Za-z0-9_.]*)?[A-Za-z0-9])$",
                "type": "string"
              }
            },
            "required": [
              "lastTransitionTime",
              "message",
              "reason",
              "status",
              "type"
            ],
            "type": "object"
          },
          "type": [
            "array",
            "null"
          ],
          "x-kubernetes-list-map-keys": [
            "type"
          ],
          "x-kubernetes-list-type": "map"
        },
        "healthyNodes": {
          "description": "HealthyNodes specified the number of healthy nodes observed",
          "type": [
            "integer",
            "null"
          ]
        },
        "inFlightRemediations": {
          "additionalProperties": {
            "format": "date-time",
            "type": "string"
          },
          "description": "InFlightRemediations records the timestamp when remediation triggered per node.\nDeprecated in favour of UnhealthyNodes.",
          "type": [
            "object",
            "null"
          ]
        },
        "lastUpdateTime": {
          "description": "LastUpdateTime is the last time the status was updated.",
          "format": "date-time",
          "type": [
            "string",
            "null"
          ]
        },
        "observedNodes": {
          "description": "ObservedNodes specified the number of nodes observed by using the NHC spec.selector",
          "type": [
            "integer",
            "null"
          ]
        },
        "phase": {
          "description": "Phase represents the current phase of this Config.\nKnown phases are Disabled, Paused, Remediating and Enabled, based on:\\n\n- the status of the Disabled condition\\n\n- the value of PauseRequests\\n\n- the value of InFlightRemediations",
          "type": [
            "string",
            "null"
          ]
        },
        "reason": {
          "description": "Reason explains the current phase in more detail.",
          "type": [
            "string",
            "null"
          ]
        },
        "unhealthyNodes": {
          "description": "UnhealthyNodes tracks currently unhealthy nodes and their remediations.",
          "items": {
            "additionalProperties": false,
            "description": "UnhealthyNode defines an unhealthy node and its remediations",
            "properties": {
              "conditionsHealthyTimestamp": {
                "description": "ConditionsHealthyTimestamp is RFC 3339 date and time at which the unhealthy conditions didn't match anymore.\nThe remediation CR will be deleted at that time, but the node will still be tracked as unhealthy until all\nremediation CRs are actually deleted, when remediators finished cleanup and removed their finalizers.",
                "format": "date-time",
                "type": [
                  "string",
                  "null"
                ]
              },
              "healthyDelayed": {
                "description": "HealthyDelayed notes whether a node should be considered healthy, but isn't due to NodeHealthCheckSpec.HealthyDelay configuration.",
                "type": [
                  "boolean",
                  "null"
                ]
              },
              "name": {
                "description": "Name is the name of the unhealthy node",
                "type": "string"
              },
              "remediations": {
                "description": "Remediations tracks the remediations created for this node",
                "items": {
                  "additionalProperties": false,
                  "description": "Remediation defines a remediation which was created for a node",
                  "properties": {
                    "resource": {
                      "additionalProperties": false,
                      "description": "Resource is the reference to the remediation CR which was created",
                      "properties": {
                        "apiVersion": {
                          "description": "API version of the referent.",
                          "type": [
                            "string",
                            "null"
                          ]
                        },
                        "fieldPath": {
                          "description": "If referring to a piece of an object instead of an entire object, this string\nshould contain a valid JSON/Go field access statement, such as desiredState.manifest.containers[2].\nFor example, if the object reference is to a container within a pod, this would take on a value like:\n\"spec.containers{name}\" (where \"name\" refers to the name of the container that triggered\nthe event) or if no container name is specified \"spec.containers[2]\" (container with\nindex 2 in this pod). This syntax is chosen only to have some well-defined way of\nreferencing a part of an object.",
                          "type": [
                            "string",
                            "null"
                          ]
                        },
                        "kind": {
                          "description": "Kind of the referent.\nMore info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds",
                          "type": [
                            "string",
                            "null"
                          ]
                        },
                        "name": {
                          "description": "Name of the referent.\nMore info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names",
                          "type": [
                            "string",
                            "null"
                          ]
                        },
                        "namespace": {
                          "description": "Namespace of the referent.\nMore info: https://kubernetes.io/docs/concepts/overview/working-with-objects/namespaces/",
                          "type": [
                            "string",
                            "null"
                          ]
                        },
                        "resourceVersion": {
                          "description": "Specific resourceVersion to which this reference is made, if any.\nMore info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#concurrency-control-and-consistency",
                          "type": [
                            "string",
                            "null"
                          ]
                        },
                        "uid": {
                          "description": "UID of the referent.\nMore info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#uids",
                          "type": [
                            "string",
                            "null"
                          ]
                        }
                      },
                      "type": "object",
                      "x-kubernetes-map-type": "atomic"
                    },
                    "started": {
                      "description": "Started is the creation time of the remediation CR",
                      "format": "date-time",
                      "type": "string"
                    },
                    "templateName": {
                      "description": "TemplateName is required when using several templates of the same kind",
                      "type": [
                        "string",
                        "null"
                      ]
                    },
                    "timedOut": {
                      "description": "TimedOut is the time when the remediation timed out.\nApplicable for escalating remediations only.",
                      "format": "date-time",
                      "type": [
                        "string",
                        "null"
                      ]
                    }
                  },
                  "required": [
                    "resource",
                    "started"
                  ],
                  "type": "object"
                },
                "type": [
                  "array",
                  "null"
                ]
              }
            },
            "required": [
              "name"
            ],
            "type": "object"
          },
          "type": [
            "array",
            "null"
          ],
          "x-kubernetes-list-map-keys": [
            "name"
          ],
          "x-kubernetes-list-type": "map"
        }
      },
      "type": [
        "object",
        "null"
      ]
    }
  },
  "type": "object"
}