package v1

import (
	configv1 "github.com/openshift/api/config/v1"
	corev1 "k8s.io/api/core/v1"
	"k8s.io/apimachinery/pkg/api/resource"
	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
	runtime "k8s.io/apimachinery/pkg/runtime"
	"k8s.io/apimachinery/pkg/util/intstr"
)

// MachineConfigRoleLabelKey is metadata key in the MachineConfig. Specifies the node role that config should be applied to.
// For example: `master` or `worker`
const MachineConfigRoleLabelKey = "machineconfiguration.openshift.io/role"

// KubeletConfigRoleLabelPrefix is the label that must be present in the KubeletConfig CR
const KubeletConfigRoleLabelPrefix = "pools.operator.machineconfiguration.openshift.io/"

// +genclient
// +genclient:nonNamespaced
// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object
// +kubebuilder:object:root=true
// +kubebuilder:resource:path=controllerconfigs,scope=Cluster
// +kubebuilder:subresource:status
// +openshift:api-approved.openshift.io=https://github.com/openshift/api/pull/1453
// +openshift:file-pattern=cvoRunLevel=0000_80,operatorName=machine-config,operatorOrdering=01
// +kubebuilder:metadata:labels=openshift.io/operator-managed=

// ControllerConfig describes configuration for MachineConfigController.
// This is currently only used to drive the MachineConfig objects generated by the TemplateController.
//
// Compatibility level 1: Stable within a major release for a minimum of 12 months or 3 minor releases (whichever is longer).
// +openshift:compatibility-gen:level=1
type ControllerConfig struct {
	metav1.TypeMeta   `json:",inline"`
	metav1.ObjectMeta `json:"metadata,omitempty"`

	// TODO(jkyros): inconsistent historical generation resulted in the controllerconfig CRD being
	// generated with all fields required, while everything else was generated with optional

	// spec contains the desired controller config configuration.
	// +required
	Spec ControllerConfigSpec `json:"spec"`

	// status contains observed information about the controller config.
	// +optional
	Status ControllerConfigStatus `json:"status"`
}

// ControllerConfigSpec is the spec for ControllerConfig resource.
type ControllerConfigSpec struct {
	// clusterDNSIP is the cluster DNS IP address
	// +required
	ClusterDNSIP string `json:"clusterDNSIP"`

	// cloudProviderConfig is the configuration for the given cloud provider
	// +required
	CloudProviderConfig string `json:"cloudProviderConfig"`

	// platform is deprecated, use Infra.Status.PlatformStatus.Type instead
	// +optional
	Platform string `json:"platform,omitempty"`

	// etcdDiscoveryDomain is deprecated, use Infra.Status.EtcdDiscoveryDomain instead
	// +optional
	EtcdDiscoveryDomain string `json:"etcdDiscoveryDomain,omitempty"`

	// TODO: Use string for CA data

	// kubeAPIServerServingCAData managed Kubelet to API Server Cert... Rotated automatically
	// +required
	KubeAPIServerServingCAData []byte `json:"kubeAPIServerServingCAData"`

	// rootCAData specifies the root CA data
	// +required
	RootCAData []byte `json:"rootCAData"`

	// cloudProviderCAData specifies the cloud provider CA data
	// +required
	// +nullable
	CloudProviderCAData []byte `json:"cloudProviderCAData"`

	// additionalTrustBundle is a certificate bundle that will be added to the nodes
	// trusted certificate store.
	// +required
	// +nullable
	AdditionalTrustBundle []byte `json:"additionalTrustBundle"`

	// imageRegistryBundleUserData is Image Registry Data provided by the user
	// +listType=atomic
	// +optional
	ImageRegistryBundleUserData []ImageRegistryBundle `json:"imageRegistryBundleUserData"`

	// imageRegistryBundleData is the ImageRegistryData
	// +listType=atomic
	// +optional
	ImageRegistryBundleData []ImageRegistryBundle `json:"imageRegistryBundleData"`

	// TODO: Investigate using a ConfigMapNameReference for the PullSecret and OSImageURL

	// pullSecret is the default pull secret that needs to be installed
	// on all machines.
	// +optional
	PullSecret *corev1.ObjectReference `json:"pullSecret,omitempty"`

	// internalRegistryPullSecret is the pull secret for the internal registry, used by
	// rpm-ostree to pull images from the internal registry if present
	// +optional
	// +nullable
	InternalRegistryPullSecret []byte `json:"internalRegistryPullSecret"`

	// images is map of images that are used by the controller to render templates under ./templates/
	// +required
	Images map[string]string `json:"images"`

	// baseOSContainerImage is the new-format container image for operating system updates.
	// +required
	BaseOSContainerImage string `json:"baseOSContainerImage"`

	// baseOSExtensionsContainerImage is the matching extensions container for the new-format container
	// +optional
	BaseOSExtensionsContainerImage string `json:"baseOSExtensionsContainerImage"`

	// osImageURL is the old-format container image that contains the OS update payload.
	// +optional
	OSImageURL string `json:"osImageURL"`

	// releaseImage is the image used when installing the cluster
	// +required
	ReleaseImage string `json:"releaseImage"`

	// proxy holds the current proxy configuration for the nodes
	// +required
	// +nullable
	Proxy *configv1.ProxyStatus `json:"proxy"`

	// infra holds the infrastructure details
	// +kubebuilder:validation:EmbeddedResource
	// +required
	// +nullable
	Infra *configv1.Infrastructure `json:"infra"`

	// dns holds the cluster dns details
	// +kubebuilder:validation:EmbeddedResource
	// +required
	// +nullable
	DNS *configv1.DNS `json:"dns"`

	// ipFamilies indicates the IP families in use by the cluster network
	// +required
	IPFamilies IPFamiliesType `json:"ipFamilies"`

	// networkType holds the type of network the cluster is using
	// XXX: this is temporary and will be dropped as soon as possible in favor of a better support
	// to start network related services the proper way.
	// Nobody is also changing this once the cluster is up and running the first time, so, disallow
	// regeneration if this changes.
	// +optional
	NetworkType string `json:"networkType,omitempty"`

	// network contains additional network related information
	// +required
	// +nullable
	Network *NetworkInfo `json:"network"`
}

// ImageRegistryBundle contains information for writing image registry certificates
type ImageRegistryBundle struct {
	// file holds the name of the file where the bundle will be written to disk
	// +required
	File string `json:"file"`
	// data holds the contents of the bundle that will be written to the file location
	// +required
	Data []byte `json:"data"`
}

// IPFamiliesType indicates whether the cluster network is IPv4-only, IPv6-only, or dual-stack
type IPFamiliesType string

const (
	IPFamiliesIPv4                 IPFamiliesType = "IPv4"
	IPFamiliesIPv6                 IPFamiliesType = "IPv6"
	IPFamiliesDualStack            IPFamiliesType = "DualStack"
	IPFamiliesDualStackIPv6Primary IPFamiliesType = "DualStackIPv6Primary"
)

// Network contains network related configuration
type NetworkInfo struct {
	// mtuMigration contains the MTU migration configuration.
	// +required
	// +nullable
	MTUMigration *configv1.MTUMigration `json:"mtuMigration"`
}

// ControllerConfigStatus is the status for ControllerConfig
type ControllerConfigStatus struct {
	// observedGeneration represents the generation observed by the controller.
	// +optional
	ObservedGeneration int64 `json:"observedGeneration,omitempty"`

	// conditions represents the latest available observations of current state.
	// +listType=map
	// +listMapKey=type
	// +optional
	Conditions []ControllerConfigStatusCondition `json:"conditions"`

	// controllerCertificates represents the latest available observations of the automatically rotating certificates in the MCO.
	// +listType=atomic
	// +optional
	ControllerCertificates []ControllerCertificate `json:"controllerCertificates"`
}

// ControllerCertificate contains info about a specific cert.
type ControllerCertificate struct {
	// subject is the cert subject
	// +required
	Subject string `json:"subject"`

	// signer is the  cert Issuer
	// +required
	Signer string `json:"signer"`

	// notBefore is the lower boundary for validity
	// +optional
	NotBefore *metav1.Time `json:"notBefore,omitempty"`

	// notAfter is the upper boundary for validity
	// +optional
	NotAfter *metav1.Time `json:"notAfter,omitempty"`

	// bundleFile is the larger bundle a cert comes from
	// +required
	BundleFile string `json:"bundleFile"`
}

// ControllerConfigStatusCondition contains condition information for ControllerConfigStatus
type ControllerConfigStatusCondition struct {
	// type specifies the state of the operator's reconciliation functionality.
	// +required
	Type ControllerConfigStatusConditionType `json:"type"`

	// status of the condition, one of True, False, Unknown.
	// +required
	Status corev1.ConditionStatus `json:"status"`

	// lastTransitionTime is the time of the last update to the current status object.
	// +required
	// +nullable
	LastTransitionTime metav1.Time `json:"lastTransitionTime"`

	// reason is the reason for the condition's last transition.  Reasons are PascalCase
	// +optional
	Reason string `json:"reason,omitempty"`

	// message provides additional information about the current condition.
	// This is only to be consumed by humans.
	// +optional
	Message string `json:"message,omitempty"`
}

// ControllerConfigStatusConditionType valid conditions of a ControllerConfigStatus
type ControllerConfigStatusConditionType string

const (
	// TemplateControllerRunning means the template controller is currently running.
	TemplateControllerRunning ControllerConfigStatusConditionType = "TemplateControllerRunning"

	// TemplateControllerCompleted means the template controller has completed reconciliation.
	TemplateControllerCompleted ControllerConfigStatusConditionType = "TemplateControllerCompleted"

	// TemplateControllerFailing means the template controller is failing.
	TemplateControllerFailing ControllerConfigStatusConditionType = "TemplateControllerFailing"
)

// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object

// ControllerConfigList is a list of ControllerConfig resources
//
// Compatibility level 1: Stable within a major release for a minimum of 12 months or 3 minor releases (whichever is longer).
// +openshift:compatibility-gen:level=1
type ControllerConfigList struct {
	metav1.TypeMeta `json:",inline"`
	metav1.ListMeta `json:"metadata"`

	Items []ControllerConfig `json:"items"`
}

// +genclient
// +genclient:noStatus
// +genclient:nonNamespaced
// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object

// MachineConfig defines the configuration for a machine
//
// Compatibility level 1: Stable within a major release for a minimum of 12 months or 3 minor releases (whichever is longer).
// +kubebuilder:object:root=true
// +kubebuilder:resource:path=machineconfigs,scope=Cluster,shortName=mc
// +openshift:api-approved.openshift.io=https://github.com/openshift/api/pull/1453
// +openshift:file-pattern=cvoRunLevel=0000_80,operatorName=machine-config,operatorOrdering=01
// +kubebuilder:metadata:labels="openshift.io/operator-managed="
// +kubebuilder:printcolumn:name=GeneratedByController,JSONPath=.metadata.annotations.machineconfiguration\.openshift\.io/generated-by-controller-version,type=string,description=Version of the controller that generated the machineconfig. This will be empty if the machineconfig is not managed by a controller.
// +kubebuilder:printcolumn:name=IgnitionVersion,JSONPath=.spec.config.ignition.version,type=string,description=Version of the Ignition Config defined in the machineconfig.
// +kubebuilder:printcolumn:name=Age,JSONPath=.metadata.creationTimestamp,type=date
// +openshift:compatibility-gen:level=1
type MachineConfig struct {
	metav1.TypeMeta   `json:",inline"`
	metav1.ObjectMeta `json:"metadata,omitempty"`
	// +optional
	Spec MachineConfigSpec `json:"spec"`
}

// MachineConfigSpec is the spec for MachineConfig
type MachineConfigSpec struct {
	// osImageURL specifies the remote location that will be used to
	// fetch the OS.
	// +optional
	OSImageURL string `json:"osImageURL"`

	// baseOSExtensionsContainerImage specifies the remote location that will be used
	// to fetch the extensions container matching a new-format OS image
	// +optional
	BaseOSExtensionsContainerImage string `json:"baseOSExtensionsContainerImage"`

	// config is a Ignition Config object.
	// +optional
	Config runtime.RawExtension `json:"config,omitempty"`

	// kernelArguments contains a list of kernel arguments to be added
	// +listType=atomic
	// +nullable
	// +optional
	KernelArguments []string `json:"kernelArguments"`

	// extensions contains a list of additional features that can be enabled on host
	// +listType=atomic
	// +optional
	Extensions []string `json:"extensions"`

	// fips controls FIPS mode
	// +optional
	FIPS bool `json:"fips"`

	// kernelType contains which kernel we want to be running like default
	// (traditional), realtime, 64k-pages (aarch64 only).
	// +optional
	KernelType string `json:"kernelType"`
}

// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object

// MachineConfigList is a list of MachineConfig resources
//
// Compatibility level 1: Stable within a major release for a minimum of 12 months or 3 minor releases (whichever is longer).
// +openshift:compatibility-gen:level=1
type MachineConfigList struct {
	metav1.TypeMeta `json:",inline"`
	metav1.ListMeta `json:"metadata"`

	Items []MachineConfig `json:"items"`
}

// +genclient
// +genclient:nonNamespaced
// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object

// MachineConfigPool describes a pool of MachineConfigs.
//
// Compatibility level 1: Stable within a major release for a minimum of 12 months or 3 minor releases (whichever is longer).
// +kubebuilder:object:root=true
// +kubebuilder:resource:path=machineconfigpools,scope=Cluster,shortName=mcp
// +kubebuilder:subresource:status
// +openshift:api-approved.openshift.io=https://github.com/openshift/api/pull/1453
// +openshift:file-pattern=cvoRunLevel=0000_80,operatorName=machine-config,operatorOrdering=01
// +kubebuilder:metadata:labels="openshift.io/operator-managed="
// +kubebuilder:printcolumn:name=Config,JSONPath=.status.configuration.name,type=string
// +kubebuilder:printcolumn:name=Updated,JSONPath=.status.conditions[?(@.type=="Updated")].status,type=string,description=When all the machines in the pool are updated to the correct machine config.
// +kubebuilder:printcolumn:name=Updating,JSONPath=.status.conditions[?(@.type=="Updating")].status,type=string,description=When at least one of machine is not either not updated or is in the process of updating to the desired machine config.
// +kubebuilder:printcolumn:name=Degraded,JSONPath=.status.conditions[?(@.type=="Degraded")].status,type=string,description=When progress is blocked on updating one or more nodes or the pool configuration is failing.
// +kubebuilder:printcolumn:name=MachineCount,JSONPath=.status.machineCount,type=number,description=Total number of machines in the machine config pool
// +kubebuilder:printcolumn:name=ReadyMachineCount,JSONPath=.status.readyMachineCount,type=number,description=Total number of ready machines targeted by the pool
// +kubebuilder:printcolumn:name=UpdatedMachineCount,JSONPath=.status.updatedMachineCount,type=number,description=Total number of machines targeted by the pool that have the CurrentMachineConfig as their config
// +kubebuilder:printcolumn:name=DegradedMachineCount,JSONPath=.status.degradedMachineCount,type=number,description=Total number of machines marked degraded (or unreconcilable)
// +kubebuilder:printcolumn:name=Age,JSONPath=.metadata.creationTimestamp,type=date
// +openshift:compatibility-gen:level=1
type MachineConfigPool struct {
	metav1.TypeMeta   `json:",inline"`
	metav1.ObjectMeta `json:"metadata,omitempty"`

	// spec contains the desired machine config pool configuration.
	// +required
	Spec MachineConfigPoolSpec `json:"spec"`

	// status contains observed information about the machine config pool.
	// +optional
	Status MachineConfigPoolStatus `json:"status"`
}

// MachineConfigPoolSpec is the spec for MachineConfigPool resource.
type MachineConfigPoolSpec struct {
	// machineConfigSelector specifies a label selector for MachineConfigs.
	// Refer https://kubernetes.io/docs/concepts/overview/working-with-objects/labels/ on how label and selectors work.
	// +optional
	MachineConfigSelector *metav1.LabelSelector `json:"machineConfigSelector,omitempty"`

	// nodeSelector specifies a label selector for Machines
	// +optional
	NodeSelector *metav1.LabelSelector `json:"nodeSelector,omitempty"`

	// paused specifies whether or not changes to this machine config pool should be stopped.
	// This includes generating new desiredMachineConfig and update of machines.
	// +optional
	Paused bool `json:"paused"`

	// maxUnavailable defines either an integer number or percentage
	// of nodes in the pool that can go Unavailable during an update.
	// This includes nodes Unavailable for any reason, including user
	// initiated cordons, failing nodes, etc. The default value is 1.
	//
	// A value larger than 1 will mean multiple nodes going unavailable during
	// the update, which may affect your workload stress on the remaining nodes.
	// You cannot set this value to 0 to stop updates (it will default back to 1);
	// to stop updates, use the 'paused' property instead. Drain will respect
	// Pod Disruption Budgets (PDBs) such as etcd quorum guards, even if
	// maxUnavailable is greater than one.
	// +optional
	MaxUnavailable *intstr.IntOrString `json:"maxUnavailable,omitempty"`

	// The targeted MachineConfig object for the machine config pool.
	// +optional
	Configuration MachineConfigPoolStatusConfiguration `json:"configuration"`

	// pinnedImageSets specifies a sequence of PinnedImageSetRef objects for the
	// pool. Nodes within this pool will preload and pin images defined in the
	// PinnedImageSet. Before pulling images the MachineConfigDaemon will ensure
	// the total uncompressed size of all the images does not exceed available
	// resources. If the total size of the images exceeds the available
	// resources the controller will report a Degraded status to the
	// MachineConfigPool and not attempt to pull any images. Also to help ensure
	// the kubelet can mitigate storage risk, the pinned_image configuration and
	// subsequent service reload will happen only after all of the images have
	// been pulled for each set. Images from multiple PinnedImageSets are loaded
	// and pinned sequentially as listed. Duplicate and existing images will be
	// skipped.
	//
	// Any failure to prefetch or pin images will result in a Degraded pool.
	// Resolving these failures is the responsibility of the user. The admin
	// should be proactive in ensuring adequate storage and proper image
	// authentication exists in advance.
	// +optional
	// +listType=map
	// +listMapKey=name
	// +kubebuilder:validation:MaxItems=100
	PinnedImageSets []PinnedImageSetRef `json:"pinnedImageSets,omitempty"`

	// osImageStream specifies an OS stream to be used for the pool.
	//
	// This field can be optionally set to a known OSImageStream name to change the
	// OS and Extension images with a well-known, tested, release-provided set of images.
	// This enables a streamlined way of switching the pool's node OS to a different version
	// than the cluster default, such as transitioning to a major RHEL version.
	//
	// When set, the referenced stream overrides the cluster-wide OS
	// images for the pool with the OS and Extensions associated to stream.
	// When omitted, the pool uses the cluster-wide default OS images.
	//
	// +openshift:enable:FeatureGate=OSStreams
	// +optional
	OSImageStream OSImageStreamReference `json:"osImageStream,omitempty,omitzero"`
}

type OSImageStreamReference struct {
	// name is a required reference to an OSImageStream to be used for the pool.
	//
	// It must be a valid RFC 1123 subdomain between 1 and 253 characters in length,
	// consisting of lowercase alphanumeric characters, hyphens ('-'), and periods ('.').
	//
	// +required
	// +kubebuilder:validation:MinLength=1
	// +kubebuilder:validation:MaxLength=253
	// +kubebuilder:validation:XValidation:rule="!format.dns1123Subdomain().validate(self).hasValue()",message="a RFC 1123 subdomain must consist of lower case alphanumeric characters, '-' or '.', and must start and end with an alphanumeric character."
	Name string `json:"name,omitempty"`
}

type PinnedImageSetRef struct {
	// name is a reference to the name of a PinnedImageSet.  Must adhere to
	// RFC-1123 (https://tools.ietf.org/html/rfc1123).
	// Made up of one of more period-separated (.) segments, where each segment
	// consists of alphanumeric characters and hyphens (-), must begin and end
	// with an alphanumeric character, and is at most 63 characters in length.
	// The total length of the name must not exceed 253 characters.
	// +kubebuilder:validation:MinLength=1
	// +kubebuilder:validation:MaxLength=253
	// +kubebuilder:validation:Pattern=`^([a-zA-Z0-9]|[a-zA-Z0-9][a-zA-Z0-9\-]{0,61}[a-zA-Z0-9])(\.([a-zA-Z0-9]|[a-zA-Z0-9][a-zA-Z0-9\-]{0,61}[a-zA-Z0-9]))*$`
	// +required
	Name string `json:"name"`
}

// MachineConfigPoolStatus is the status for MachineConfigPool resource.
type MachineConfigPoolStatus struct {
	// observedGeneration represents the generation observed by the controller.
	// +optional
	ObservedGeneration int64 `json:"observedGeneration,omitempty"`

	// configuration represents the current MachineConfig object for the machine config pool.
	// +optional
	Configuration MachineConfigPoolStatusConfiguration `json:"configuration"`

	// machineCount represents the total number of machines in the machine config pool.
	// +optional
	MachineCount int32 `json:"machineCount"`

	// updatedMachineCount represents the total number of machines targeted by the pool that have the CurrentMachineConfig as their config.
	// +optional
	UpdatedMachineCount int32 `json:"updatedMachineCount"`

	// readyMachineCount represents the total number of ready machines targeted by the pool.
	// +optional
	ReadyMachineCount int32 `json:"readyMachineCount"`

	// unavailableMachineCount represents the total number of unavailable (non-ready) machines targeted by the pool.
	// A node is marked unavailable if it is in updating state or NodeReady condition is false.
	// +optional
	UnavailableMachineCount int32 `json:"unavailableMachineCount"`

	// degradedMachineCount represents the total number of machines marked degraded (or unreconcilable).
	// A node is marked degraded if applying a configuration failed..
	// +optional
	DegradedMachineCount int32 `json:"degradedMachineCount"`

	// conditions represents the latest available observations of current state.
	// +listType=atomic
	// +optional
	Conditions []MachineConfigPoolCondition `json:"conditions"`

	// certExpirys keeps track of important certificate expiration data
	// +listType=atomic
	// +optional
	CertExpirys []CertExpiry `json:"certExpirys"`

	// poolSynchronizersStatus is the status of the machines managed by the pool synchronizers.
	// +listType=map
	// +listMapKey=poolSynchronizerType
	// +optional
	PoolSynchronizersStatus []PoolSynchronizerStatus `json:"poolSynchronizersStatus,omitempty"`

	// osImageStream specifies the last updated OSImageStream for the pool.
	//
	// When omitted, the pool is using the cluster-wide default OS images.
	// +openshift:enable:FeatureGate=OSStreams
	// +optional
	OSImageStream OSImageStreamReference `json:"osImageStream,omitempty,omitzero"`
}

// +kubebuilder:validation:XValidation:rule="self.machineCount >= self.updatedMachineCount", message="machineCount must be greater than or equal to updatedMachineCount"
// +kubebuilder:validation:XValidation:rule="self.machineCount >= self.availableMachineCount", message="machineCount must be greater than or equal to availableMachineCount"
// +kubebuilder:validation:XValidation:rule="self.machineCount >= self.unavailableMachineCount", message="machineCount must be greater than or equal to unavailableMachineCount"
// +kubebuilder:validation:XValidation:rule="self.machineCount >= self.readyMachineCount", message="machineCount must be greater than or equal to readyMachineCount"
// +kubebuilder:validation:XValidation:rule="self.availableMachineCount >= self.readyMachineCount", message="availableMachineCount must be greater than or equal to readyMachineCount"
type PoolSynchronizerStatus struct {
	// poolSynchronizerType describes the type of the pool synchronizer.
	// +required
	PoolSynchronizerType PoolSynchronizerType `json:"poolSynchronizerType"`
	// machineCount is the number of machines that are managed by the node synchronizer.
	// +required
	// +kubebuilder:validation:Minimum=0
	MachineCount int64 `json:"machineCount"`
	// updatedMachineCount is the number of machines that have been updated by the node synchronizer.
	// +required
	// +kubebuilder:validation:Minimum=0
	UpdatedMachineCount int64 `json:"updatedMachineCount"`
	// readyMachineCount is the number of machines managed by the node synchronizer that are in a ready state.
	// +required
	// +kubebuilder:validation:Minimum=0
	ReadyMachineCount int64 `json:"readyMachineCount"`
	// availableMachineCount is the number of machines managed by the node synchronizer which are available.
	// +required
	// +kubebuilder:validation:Minimum=0
	AvailableMachineCount int64 `json:"availableMachineCount"`
	// unavailableMachineCount is the number of machines managed by the node synchronizer but are unavailable.
	// +required
	// +kubebuilder:validation:Minimum=0
	UnavailableMachineCount int64 `json:"unavailableMachineCount"`
	// +kubebuilder:validation:XValidation:rule="self >= oldSelf || (self == 0 && oldSelf > 0)", message="observedGeneration must not move backwards except to zero"
	// observedGeneration is the last generation change that has been applied.
	// +kubebuilder:validation:Minimum=0
	// +optional
	ObservedGeneration int64 `json:"observedGeneration,omitempty"`
}

// PoolSynchronizerType is an enum that describe the type of pool synchronizer. A pool synchronizer is a one or more controllers that
// manages the on disk state of a set of machines within a pool.
// +kubebuilder:validation:Enum:="PinnedImageSets"
// +kubebuilder:validation:MaxLength=256
type PoolSynchronizerType string

const (
	// PinnedImageSets represents a pool synchronizer for pinned image sets.
	PinnedImageSets PoolSynchronizerType = "PinnedImageSets"
)

// ceryExpiry contains the bundle name and the expiry date
type CertExpiry struct {
	// bundle is the name of the bundle in which the subject certificate resides
	// +required
	Bundle string `json:"bundle"`
	// subject is the subject of the certificate
	// +required
	Subject string `json:"subject"`
	// expiry is the date after which the certificate will no longer be valid
	// +optional
	Expiry *metav1.Time `json:"expiry"`
}

// MachineConfigPoolStatusConfiguration stores the current configuration for the pool, and
// optionally also stores the list of MachineConfig objects used to generate the configuration.
type MachineConfigPoolStatusConfiguration struct {
	corev1.ObjectReference `json:",inline"`

	// source is the list of MachineConfig objects that were used to generate the single MachineConfig object specified in `content`.
	// +listType=atomic
	// +optional
	Source []corev1.ObjectReference `json:"source,omitempty"`
}

// MachineConfigPoolCondition contains condition information for an MachineConfigPool.
type MachineConfigPoolCondition struct {
	// type of the condition, currently ('Done', 'Updating', 'Failed').
	// +optional
	Type MachineConfigPoolConditionType `json:"type"`

	// status of the condition, one of ('True', 'False', 'Unknown').
	// +optional
	Status corev1.ConditionStatus `json:"status,omitempty"`

	// lastTransitionTime is the timestamp corresponding to the last status
	// change of this condition.
	// +nullable
	// +optional
	LastTransitionTime metav1.Time `json:"lastTransitionTime"`

	// reason is a brief machine readable explanation for the condition's last
	// transition.
	// +optional
	Reason string `json:"reason"`

	// message is a human readable description of the details of the last
	// transition, complementing reason.
	// +optional
	Message string `json:"message"`
}

// MachineConfigPoolConditionType valid conditions of a MachineConfigPool
type MachineConfigPoolConditionType string

const (
	// MachineConfigPoolUpdated means MachineConfigPool is updated completely.
	// When the all the machines in the pool are updated to the correct machine config.
	MachineConfigPoolUpdated MachineConfigPoolConditionType = "Updated"

	// MachineConfigPoolUpdating means MachineConfigPool is updating.
	// When at least one of machine is not either not updated or is in the process of updating
	// to the desired machine config.
	MachineConfigPoolUpdating MachineConfigPoolConditionType = "Updating"

	// MachineConfigPoolNodeDegraded means the update for one of the machine is not progressing
	MachineConfigPoolNodeDegraded MachineConfigPoolConditionType = "NodeDegraded"

	// MachineConfigPoolRenderDegraded means the rendered configuration for the pool cannot be generated because of an error
	MachineConfigPoolRenderDegraded MachineConfigPoolConditionType = "RenderDegraded"

	// MachineConfigPoolImageBuildDegraded means the image build for the pool was not successful
	// This condition is only used when Image Mode is enabled for the pool
	MachineConfigPoolImageBuildDegraded MachineConfigPoolConditionType = "ImageBuildDegraded"

	// MachineConfigPoolPinnedImageSetsDegraded means the pinned image sets for the pool cannot be populated because of an error
	MachineConfigPoolPinnedImageSetsDegraded MachineConfigPoolConditionType = "PinnedImageSetsDegraded"

	// MachineConfigPoolSynchronizerDegraded means the pool synchronizer can not be updated because of an error
	MachineConfigPoolSynchronizerDegraded MachineConfigPoolConditionType = "PoolSynchronizerDegraded"

	// MachineConfigPoolDegraded is the overall status of the pool based, today, on whether we fail with NodeDegraded, RenderDegraded, or ImageBuildDegraded
	MachineConfigPoolDegraded MachineConfigPoolConditionType = "Degraded"

	MachineConfigPoolBuildPending MachineConfigPoolConditionType = "BuildPending"

	MachineConfigPoolBuilding MachineConfigPoolConditionType = "Building"

	MachineConfigPoolBuildSuccess MachineConfigPoolConditionType = "BuildSuccess"

	MachineConfigPoolBuildFailed MachineConfigPoolConditionType = "BuildFailed"

	MachineConfigPoolBuildInterrupted MachineConfigPoolConditionType = "BuildInterrupted"
)

// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object

// MachineConfigPoolList is a list of MachineConfigPool resources
//
// Compatibility level 1: Stable within a major release for a minimum of 12 months or 3 minor releases (whichever is longer).
// +openshift:compatibility-gen:level=1
type MachineConfigPoolList struct {
	metav1.TypeMeta `json:",inline"`
	metav1.ListMeta `json:"metadata"`

	Items []MachineConfigPool `json:"items"`
}

// +genclient
// +genclient:nonNamespaced
// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object

// KubeletConfig describes a customized Kubelet configuration.
//
// Compatibility level 1: Stable within a major release for a minimum of 12 months or 3 minor releases (whichever is longer).
// +kubebuilder:object:root=true
// +kubebuilder:resource:path=kubeletconfigs,scope=Cluster
// +kubebuilder:subresource:status
// +openshift:api-approved.openshift.io=https://github.com/openshift/api/pull/1453
// +openshift:file-pattern=cvoRunLevel=0000_80,operatorName=machine-config,operatorOrdering=01
// +kubebuilder:metadata:labels="openshift.io/operator-managed="
// +openshift:compatibility-gen:level=1
type KubeletConfig struct {
	metav1.TypeMeta   `json:",inline"`
	metav1.ObjectMeta `json:"metadata,omitempty"`

	// spec contains the desired kubelet configuration.
	// +required
	Spec KubeletConfigSpec `json:"spec"`

	// status contains observed information about the kubelet configuration.
	// +optional
	Status KubeletConfigStatus `json:"status"`
}

// KubeletConfigSpec configures the kubelet running on cluster nodes.
type KubeletConfigSpec struct {
	// autoSizingReserved controls whether system-reserved CPU and memory are automatically
	// calculated based on each node's installed capacity. When set to true, this prevents node failure
	// from resource starvation of system components (kubelet, CRI-O) without manual configuration.
	// When omitted, this means the user has no opinion and the platform is left to choose a reasonable default,
	// which is subject to change over time. The current default is true for worker nodes and false for control plane nodes.
	// When set to false, automatic resource reservation is disabled and manual settings must be configured.
	// +optional
	AutoSizingReserved *bool `json:"autoSizingReserved,omitempty"`
	// logLevel sets the kubelet log verbosity, controlling the amount of detail in kubelet logs.
	// Valid values range from 0 (minimal logging) to 10 (maximum verbosity with trace-level detail).
	// Higher log levels may impact node performance. When omitted, the platform chooses a reasonable default,
	// which is subject to change over time. The current default is 2 (standard informational logging).
	// +kubebuilder:validation:Minimum=0
	// +kubebuilder:validation:Maximum=10
	// +optional
	LogLevel *int32 `json:"logLevel,omitempty"`

	// machineConfigPoolSelector selects which pools the KubeletConfig should apply to.
	// When omitted or set to an empty selector {}, no pools are selected, which is equivalent
	// to not matching any MachineConfigPool.
	// +optional
	MachineConfigPoolSelector *metav1.LabelSelector `json:"machineConfigPoolSelector,omitempty"`
	// kubeletConfig contains upstream Kubernetes kubelet configuration fields.
	// Values are validated by the kubelet itself. Invalid values may render nodes unusable.
	// Refer to OpenShift documentation for the Kubernetes version corresponding to your
	// OpenShift release to find valid kubelet configuration options.
	// +optional
	KubeletConfig *runtime.RawExtension `json:"kubeletConfig,omitempty"`

	// tlsSecurityProfile configures TLS settings for the kubelet.
	// When omitted, the TLS configuration defaults to the value from apiservers.config.openshift.io/cluster.
	// When specified, the type field can be set to either "Old", "Intermediate", "Modern", "Custom" or omitted for backward compatibility.
	// +optional
	TLSSecurityProfile *configv1.TLSSecurityProfile `json:"tlsSecurityProfile,omitempty"`
}

// KubeletConfigStatus defines the observed state of a KubeletConfig
type KubeletConfigStatus struct {
	// observedGeneration represents the generation observed by the controller.
	// +optional
	ObservedGeneration int64 `json:"observedGeneration,omitempty"`

	// conditions represents the latest available observations of current state.
	// +optional
	// +listType=atomic
	Conditions []KubeletConfigCondition `json:"conditions"`
}

// KubeletConfigCondition defines the state of the KubeletConfig
type KubeletConfigCondition struct {
	// type specifies the state of the operator's reconciliation functionality.
	// +optional
	Type KubeletConfigStatusConditionType `json:"type"`

	// status of the condition, one of True, False, Unknown.
	// +optional
	Status corev1.ConditionStatus `json:"status,omitempty"`

	// lastTransitionTime is the time of the last update to the current status object.
	// +optional
	// +nullable
	LastTransitionTime metav1.Time `json:"lastTransitionTime"`

	// reason is the reason for the condition's last transition.  Reasons are PascalCase
	// +optional
	Reason string `json:"reason,omitempty"`

	// message provides additional information about the current condition.
	// This is only to be consumed by humans.
	// +optional
	Message string `json:"message,omitempty"`
}

// KubeletConfigStatusConditionType is the state of the operator's reconciliation functionality.
type KubeletConfigStatusConditionType string

const (
	// KubeletConfigSuccess designates a successful application of a KubeletConfig CR.
	KubeletConfigSuccess KubeletConfigStatusConditionType = "Success"

	// KubeletConfigFailure designates a failure applying a KubeletConfig CR.
	KubeletConfigFailure KubeletConfigStatusConditionType = "Failure"
)

// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object

// KubeletConfigList is a list of KubeletConfig resources
//
// Compatibility level 1: Stable within a major release for a minimum of 12 months or 3 minor releases (whichever is longer).
// +openshift:compatibility-gen:level=1
type KubeletConfigList struct {
	metav1.TypeMeta `json:",inline"`
	metav1.ListMeta `json:"metadata"`

	Items []KubeletConfig `json:"items"`
}

// +genclient
// +genclient:nonNamespaced
// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object

// ContainerRuntimeConfig describes a customized Container Runtime configuration.
//
// Compatibility level 1: Stable within a major release for a minimum of 12 months or 3 minor releases (whichever is longer).
// +kubebuilder:object:root=true
// +kubebuilder:resource:path=containerruntimeconfigs,scope=Cluster,shortName=ctrcfg
// +kubebuilder:subresource:status
// +openshift:api-approved.openshift.io=https://github.com/openshift/api/pull/1453
// +openshift:file-pattern=cvoRunLevel=0000_80,operatorName=machine-config,operatorOrdering=01
// +kubebuilder:metadata:labels="openshift.io/operator-managed="
// +openshift:compatibility-gen:level=1
type ContainerRuntimeConfig struct {
	metav1.TypeMeta   `json:",inline"`
	metav1.ObjectMeta `json:"metadata,omitempty"`

	// spec contains the desired container runtime configuration.
	// +required
	Spec ContainerRuntimeConfigSpec `json:"spec"`

	// status contains observed information about the container runtime configuration.
	// +optional
	Status ContainerRuntimeConfigStatus `json:"status"`
}

// ContainerRuntimeConfigSpec defines the desired state of ContainerRuntimeConfig
type ContainerRuntimeConfigSpec struct {
	// machineConfigPoolSelector selects which pools the ContainerRuntimeConfig shoud apply to.
	// A nil selector will result in no pools being selected.
	// +optional
	MachineConfigPoolSelector *metav1.LabelSelector `json:"machineConfigPoolSelector,omitempty"`

	// containerRuntimeConfig defines the tuneables of the container runtime.
	// +required
	ContainerRuntimeConfig *ContainerRuntimeConfiguration `json:"containerRuntimeConfig,omitempty"`
}

// ContainerRuntimeConfiguration defines the tuneables of the container runtime
type ContainerRuntimeConfiguration struct {
	// pidsLimit specifies the maximum number of processes allowed in a container
	// +optional
	PidsLimit *int64 `json:"pidsLimit,omitempty"`

	// logLevel specifies the verbosity of the logs based on the level it is set to.
	// Options are fatal, panic, error, warn, info, and debug.
	// +optional
	LogLevel string `json:"logLevel,omitempty"`

	// logSizeMax specifies the Maximum size allowed for the container log file.
	// Negative numbers indicate that no size limit is imposed.
	// If it is positive, it must be >= 8192 to match/exceed conmon's read buffer.
	// +optional
	LogSizeMax *resource.Quantity `json:"logSizeMax,omitempty"`

	// overlaySize specifies the maximum size of a container image.
	// This flag can be used to set quota on the size of container images. (default: 10GB)
	// +optional
	OverlaySize *resource.Quantity `json:"overlaySize,omitempty"`

	// defaultRuntime is the name of the OCI runtime to be used as the default for containers.
	// Allowed values are `runc` and `crun`.
	// When set to `runc`, OpenShift will use runc to execute the container
	// When set to `crun`, OpenShift will use crun to execute the container
	// When omitted, this means no opinion and the platform is left to choose a reasonable default,
	// which is subject to change over time. Currently, the default is `crun`.
	// +kubebuilder:validation:Enum=crun;runc
	// +optional
	DefaultRuntime ContainerRuntimeDefaultRuntime `json:"defaultRuntime,omitempty"`

	// additionalLayerStores configures additional read-only container image layer store locations for Open Container Initiative (OCI) images.
	//
	// Layers are checked in order: additional stores first, then the default location.
	// Stores are read-only.
	// Maximum of 5 stores allowed.
	// Each path must be unique.
	//
	// When omitted, only the default layer location is used.
	// When specified, at least one store must be provided.
	//
	// +openshift:enable:FeatureGate=AdditionalStorageConfig
	// +optional
	// +listType=atomic
	// +kubebuilder:validation:MinItems=1
	// +kubebuilder:validation:MaxItems=5
	// +kubebuilder:validation:XValidation:rule="self.all(x, self.exists_one(y, x.path == y.path))",message="additionalLayerStores must not contain duplicate paths"
	AdditionalLayerStores []AdditionalLayerStore `json:"additionalLayerStores,omitempty"`

	// additionalImageStores configures additional read-only container image store locations for Open Container Initiative (OCI) images.
	//
	// Images are checked in order: additional stores first, then the default location.
	// Stores are read-only.
	// Maximum of 10 stores allowed.
	// Each path must be unique.
	//
	// When omitted, only the default image location is used.
	// When specified, at least one store must be provided.
	//
	// +openshift:enable:FeatureGate=AdditionalStorageConfig
	// +optional
	// +listType=atomic
	// +kubebuilder:validation:MinItems=1
	// +kubebuilder:validation:MaxItems=10
	// +kubebuilder:validation:XValidation:rule="self.all(x, self.exists_one(y, x.path == y.path))",message="additionalImageStores must not contain duplicate paths"
	AdditionalImageStores []AdditionalImageStore `json:"additionalImageStores,omitempty"`

	// additionalArtifactStores configures additional read-only artifact storage locations for Open Container Initiative (OCI) artifacts.
	//
	// Artifacts are checked in order: additional stores first, then the default location (/var/lib/containers/storage/artifacts).
	// Stores are read-only.
	// Maximum of 10 stores allowed.
	// Each path must be unique.
	//
	// When omitted, only the default artifact location is used.
	// When specified, at least one store must be provided.
	//
	// +openshift:enable:FeatureGate=AdditionalStorageConfig
	// +optional
	// +listType=atomic
	// +kubebuilder:validation:MinItems=1
	// +kubebuilder:validation:MaxItems=10
	// +kubebuilder:validation:XValidation:rule="self.all(x, self.exists_one(y, x.path == y.path))",message="additionalArtifactStores must not contain duplicate paths"
	AdditionalArtifactStores []AdditionalArtifactStore `json:"additionalArtifactStores,omitempty"`
}

type ContainerRuntimeDefaultRuntime string

// These constants are used in the Machine Config Operator (MCO)
const (
	ContainerRuntimeDefaultRuntimeEmpty   = ""
	ContainerRuntimeDefaultRuntimeRunc    = "runc"
	ContainerRuntimeDefaultRuntimeCrun    = "crun"
	ContainerRuntimeDefaultRuntimeDefault = ContainerRuntimeDefaultRuntimeCrun
)

// StorePath is an absolute filesystem path used by additional container storage configurations.
// The path must be between 1 and 256 characters long, begin with a forward slash, and only contain
// the characters a-z, A-Z, 0-9, '/', '.', '_', and '-'. Consecutive forward slashes are not permitted.
// +kubebuilder:validation:MinLength=1
// +kubebuilder:validation:MaxLength=256
// +kubebuilder:validation:XValidation:rule="self.matches('^/[a-zA-Z0-9/._-]+$')",message="path must be absolute and contain only alphanumeric characters, '/', '.', '_', and '-'"
// +kubebuilder:validation:XValidation:rule="!self.contains('//')",message="path must not contain consecutive forward slashes"
type StorePath string

// AdditionalLayerStore defines a read-only storage location for Open Container Initiative (OCI) container image layers.
type AdditionalLayerStore struct {
	// path specifies the absolute location of the additional layer store.
	// The path must exist on the node before configuration is applied.
	// When a container image is requested, layers found at this location will be used instead of
	// retrieving from the registry.
	// The path is required and must be between 1 and 256 characters long, begin with a forward slash,
	// and only contain the characters a-z, A-Z, 0-9, '/', '.', '_', and '-'.
	// Consecutive forward slashes are not permitted.
	// +required
	Path StorePath `json:"path,omitempty"`
}

// AdditionalImageStore defines an additional read-only storage location for Open Container Initiative (OCI) images.
type AdditionalImageStore struct {
	// path specifies the absolute location of the additional image store.
	// The path must exist on the node before configuration is applied.
	// When a container image is requested, images found at this location will be used instead of
	// retrieving from the registry.
	// The path is required and must be between 1 and 256 characters long, begin with a forward slash,
	// and only contain the characters a-z, A-Z, 0-9, '/', '.', '_', and '-'.
	// Consecutive forward slashes are not permitted.
	// +required
	Path StorePath `json:"path,omitempty"`
}

// AdditionalArtifactStore defines an additional read-only storage location for Open Container Initiative (OCI) artifacts.
type AdditionalArtifactStore struct {
	// path specifies the absolute location of the additional artifact store.
	// The path must exist on the node before configuration is applied.
	// When an artifact is requested, artifacts found at this location will be used instead of
	// retrieving from the registry.
	// The path is required and must be between 1 and 256 characters long, begin with a forward slash,
	// and only contain the characters a-z, A-Z, 0-9, '/', '.', '_', and '-'.
	// Consecutive forward slashes are not permitted.
	// +required
	Path StorePath `json:"path,omitempty"`
}

// ContainerRuntimeConfigStatus defines the observed state of a ContainerRuntimeConfig
type ContainerRuntimeConfigStatus struct {
	// observedGeneration represents the generation observed by the controller.
	// +optional
	ObservedGeneration int64 `json:"observedGeneration,omitempty"`

	// conditions represents the latest available observations of current state.
	// +listType=atomic
	// +optional
	Conditions []ContainerRuntimeConfigCondition `json:"conditions"`
}

// ContainerRuntimeConfigCondition defines the state of the ContainerRuntimeConfig
type ContainerRuntimeConfigCondition struct {
	// type specifies the state of the operator's reconciliation functionality.
	// +optional
	Type ContainerRuntimeConfigStatusConditionType `json:"type"`

	// status of the condition, one of True, False, Unknown.
	// +optional
	Status corev1.ConditionStatus `json:"status,omitempty"`

	// lastTransitionTime is the time of the last update to the current status object.
	// +nullable
	// +optional
	LastTransitionTime metav1.Time `json:"lastTransitionTime"`

	// reason is the reason for the condition's last transition.  Reasons are PascalCase
	// +optional
	Reason string `json:"reason,omitempty"`

	// message provides additional information about the current condition.
	// This is only to be consumed by humans.
	// +optional
	Message string `json:"message,omitempty"`
}

// ContainerRuntimeConfigStatusConditionType is the state of the operator's reconciliation functionality.
type ContainerRuntimeConfigStatusConditionType string

const (
	// ContainerRuntimeConfigSuccess designates a successful application of a ContainerRuntimeConfig CR.
	ContainerRuntimeConfigSuccess ContainerRuntimeConfigStatusConditionType = "Success"

	// ContainerRuntimeConfigFailure designates a failure applying a ContainerRuntimeConfig CR.
	ContainerRuntimeConfigFailure ContainerRuntimeConfigStatusConditionType = "Failure"
)

// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object

// ContainerRuntimeConfigList is a list of ContainerRuntimeConfig resources
//
// Compatibility level 1: Stable within a major release for a minimum of 12 months or 3 minor releases (whichever is longer).
// +openshift:compatibility-gen:level=1
type ContainerRuntimeConfigList struct {
	metav1.TypeMeta `json:",inline"`
	metav1.ListMeta `json:"metadata"`

	Items []ContainerRuntimeConfig `json:"items"`
}
