Drafting ctl controller
This commit is contained in:
@@ -14,7 +14,6 @@ var (
|
||||
APIVersion = "monok8s.io/v1alpha1"
|
||||
|
||||
AltPartDeviceLink = "/dev/mksaltpart"
|
||||
Annotation = "monok8s.io/annotation"
|
||||
BootStateFile = "/run/monok8s/boot-state.env"
|
||||
CatalogURL = "https://example.com/monok8s.io/v1alpha1/catalog.yaml"
|
||||
ControlAgentKey = "monok8s.io/control-agent"
|
||||
@@ -25,18 +24,20 @@ var (
|
||||
)
|
||||
|
||||
var (
|
||||
GroupVersion = schema.GroupVersion{Group: Group, Version: Version}
|
||||
SchemeBuilder = runtime.NewSchemeBuilder(addKnownTypes)
|
||||
AddToScheme = SchemeBuilder.AddToScheme
|
||||
SchemeGroupVersion = schema.GroupVersion{Group: Group, Version: Version}
|
||||
SchemeBuilder = runtime.NewSchemeBuilder(addKnownTypes)
|
||||
AddToScheme = SchemeBuilder.AddToScheme
|
||||
)
|
||||
|
||||
func addKnownTypes(scheme *runtime.Scheme) error {
|
||||
scheme.AddKnownTypes(GroupVersion,
|
||||
scheme.AddKnownTypes(SchemeGroupVersion,
|
||||
&MonoKSConfig{},
|
||||
&MonoKSConfigList{},
|
||||
&OSUpgrade{},
|
||||
&OSUpgradeList{},
|
||||
&OSUpgradeProgress{},
|
||||
&OSUpgradeProgressList{},
|
||||
)
|
||||
metav1.AddToGroupVersion(scheme, GroupVersion)
|
||||
metav1.AddToGroupVersion(scheme, SchemeGroupVersion)
|
||||
return nil
|
||||
}
|
||||
|
||||
@@ -40,7 +40,6 @@ type MonoKSConfigSpec struct {
|
||||
KubeProxyNodePortAddresses []string `json:"kubeProxyNodePortAddresses,omitempty" yaml:"kubeProxyNodePortAddresses,omitempty"`
|
||||
SubjectAltNames []string `json:"subjectAltNames,omitempty" yaml:"subjectAltNames,omitempty"`
|
||||
NodeLabels map[string]string `json:"nodeLabels,omitempty" yaml:"nodeLabels,omitempty"`
|
||||
NodeAnnotations map[string]string `json:"nodeAnnotations,omitempty" yaml:"nodeAnnotations,omitempty"`
|
||||
Network NetworkSpec `json:"network,omitempty" yaml:"network,omitempty"`
|
||||
}
|
||||
|
||||
|
||||
@@ -2,7 +2,6 @@ package v1alpha1
|
||||
|
||||
import (
|
||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
"k8s.io/apimachinery/pkg/runtime"
|
||||
)
|
||||
|
||||
type OSUpgradePhase string
|
||||
@@ -28,6 +27,7 @@ const (
|
||||
OSUpgradeProgressPhaseRejected OSUpgradeProgressPhase = "rejected"
|
||||
)
|
||||
|
||||
// +genclient
|
||||
// +kubebuilder:object:root=true
|
||||
// +kubebuilder:subresource:status
|
||||
// +kubebuilder:resource:scope=Namespaced,shortName=osu
|
||||
@@ -52,46 +52,22 @@ type OSUpgradeList struct {
|
||||
Items []OSUpgrade `json:"items" yaml:"items"`
|
||||
}
|
||||
|
||||
// OSUpgradeSpec defines the desired state of an OSUpgrade.
|
||||
type OSUpgradeSpec struct {
|
||||
// DesiredVersion is the requested target version.
|
||||
//
|
||||
// It may be either:
|
||||
// - "stable" to use the catalog's current stable version
|
||||
// - an explicit version such as "v1.35.3"
|
||||
//
|
||||
// The resolved target version is reported in status.
|
||||
// +kubebuilder:validation:MinLength=1
|
||||
DesiredVersion string `json:"desiredVersion,omitempty" yaml:"desiredVersion,omitempty"`
|
||||
|
||||
// FlashProfile controls how aggressively the image is written to disk.
|
||||
//
|
||||
// Supported values are:
|
||||
// - "fast": prioritize speed
|
||||
// - "balanced": default tradeoff between speed and system impact
|
||||
// - "safe": minimize I/O pressure on the node
|
||||
//
|
||||
// If unset, the controller should use a default profile.
|
||||
// +kubebuilder:validation:Enum=fast;balanced;safe
|
||||
// +kubebuilder:default=balanced
|
||||
FlashProfile string `json:"flashProfile,omitempty"`
|
||||
FlashProfile string `json:"flashProfile,omitempty" yaml:"flashProfile,omitempty"`
|
||||
|
||||
// Catalog specifies how available versions and images are resolved.
|
||||
//
|
||||
// This may point to a remote catalog, inline catalog data, or another source,
|
||||
// depending on the VersionCatalogSource definition.
|
||||
Catalog *VersionCatalogSource `json:"catalog,omitempty"`
|
||||
|
||||
// NodeSelector limits the upgrade to nodes whose labels match this selector.
|
||||
//
|
||||
// If unset, the upgrade applies to all eligible nodes.
|
||||
Catalog *VersionCatalogSource `json:"catalog,omitempty" yaml:"catalog,omitempty"`
|
||||
NodeSelector *metav1.LabelSelector `json:"nodeSelector,omitempty" yaml:"nodeSelector,omitempty"`
|
||||
}
|
||||
|
||||
type VersionCatalogSource struct {
|
||||
URL string `json:"url,omitempty"`
|
||||
Inline string `json:"inline,omitempty"`
|
||||
ConfigMap string `json:"configMapRef,omitempty"`
|
||||
URL string `json:"url,omitempty" yaml:"url,omitempty"`
|
||||
Inline string `json:"inline,omitempty" yaml:"inline,omitempty"`
|
||||
ConfigMap string `json:"configMapRef,omitempty" yaml:"configMapRef,omitempty"`
|
||||
}
|
||||
|
||||
type OSUpgradeStatus struct {
|
||||
@@ -100,10 +76,8 @@ type OSUpgradeStatus struct {
|
||||
ObservedGeneration int64 `json:"observedGeneration,omitempty" yaml:"observedGeneration,omitempty"`
|
||||
Summary OSUpgradeSummary `json:"summary,omitempty" yaml:"summary,omitempty"`
|
||||
Conditions []metav1.Condition `json:"conditions,omitempty" yaml:"conditions,omitempty"`
|
||||
|
||||
// Optional, useful when rejected.
|
||||
Reason string `json:"reason,omitempty" yaml:"reason,omitempty"`
|
||||
Message string `json:"message,omitempty" yaml:"message,omitempty"`
|
||||
Reason string `json:"reason,omitempty" yaml:"reason,omitempty"`
|
||||
Message string `json:"message,omitempty" yaml:"message,omitempty"`
|
||||
}
|
||||
|
||||
type OSUpgradeSummary struct {
|
||||
@@ -114,6 +88,7 @@ type OSUpgradeSummary struct {
|
||||
FailedNodes int32 `json:"failedNodes,omitempty" yaml:"failedNodes,omitempty"`
|
||||
}
|
||||
|
||||
// +genclient
|
||||
// +kubebuilder:object:root=true
|
||||
// +kubebuilder:subresource:status
|
||||
// +kubebuilder:resource:scope=Namespaced,shortName=osup
|
||||
@@ -143,56 +118,23 @@ type OSUpgradeProgressSpec struct {
|
||||
}
|
||||
|
||||
type OSUpgradeSourceRef struct {
|
||||
Name string `json:"name,omitempty" yaml:"name,omitempty"`
|
||||
Name string `json:"name,omitempty" yaml:"name,omitempty"`
|
||||
Namespace string `json:"namespace,omitempty" yaml:"namespace,omitempty"`
|
||||
}
|
||||
|
||||
type OSUpgradeProgressStatus struct {
|
||||
CurrentVersion string `json:"currentVersion,omitempty" yaml:"currentVersion,omitempty"`
|
||||
TargetVersion string `json:"targetVersion,omitempty" yaml:"targetVersion,omitempty"`
|
||||
Phase OSUpgradeProgressPhase `json:"phase,omitempty" yaml:"phase,omitempty"`
|
||||
|
||||
StartedAt *metav1.Time `json:"startedAt,omitempty" yaml:"startedAt,omitempty"`
|
||||
CompletedAt *metav1.Time `json:"completedAt,omitempty" yaml:"completedAt,omitempty"`
|
||||
LastUpdatedAt *metav1.Time `json:"lastUpdatedAt,omitempty" yaml:"lastUpdatedAt,omitempty"`
|
||||
RetryCount int32 `json:"retryCount,omitempty" yaml:"retryCount,omitempty"`
|
||||
InactivePartition string `json:"inactivePartition,omitempty" yaml:"inactivePartition,omitempty"`
|
||||
FailureReason string `json:"failureReason,omitempty" yaml:"failureReason,omitempty"`
|
||||
Message string `json:"message,omitempty" yaml:"message,omitempty"`
|
||||
|
||||
PlannedPath []string `json:"plannedPath,omitempty"`
|
||||
CurrentStep int32 `json:"currentStep,omitempty"`
|
||||
CurrentFrom string `json:"currentFrom,omitempty"`
|
||||
CurrentTo string `json:"currentTo,omitempty"`
|
||||
}
|
||||
|
||||
func (in *OSUpgrade) DeepCopyObject() runtime.Object {
|
||||
if in == nil {
|
||||
return nil
|
||||
}
|
||||
out := *in
|
||||
return &out
|
||||
}
|
||||
|
||||
func (in *OSUpgradeList) DeepCopyObject() runtime.Object {
|
||||
if in == nil {
|
||||
return nil
|
||||
}
|
||||
out := *in
|
||||
return &out
|
||||
}
|
||||
|
||||
func (in *OSUpgradeProgress) DeepCopyObject() runtime.Object {
|
||||
if in == nil {
|
||||
return nil
|
||||
}
|
||||
out := *in
|
||||
return &out
|
||||
}
|
||||
|
||||
func (in *OSUpgradeProgressList) DeepCopyObject() runtime.Object {
|
||||
if in == nil {
|
||||
return nil
|
||||
}
|
||||
out := *in
|
||||
return &out
|
||||
CurrentVersion string `json:"currentVersion,omitempty" yaml:"currentVersion,omitempty"`
|
||||
TargetVersion string `json:"targetVersion,omitempty" yaml:"targetVersion,omitempty"`
|
||||
Phase OSUpgradeProgressPhase `json:"phase,omitempty" yaml:"phase,omitempty"`
|
||||
StartedAt *metav1.Time `json:"startedAt,omitempty" yaml:"startedAt,omitempty"`
|
||||
CompletedAt *metav1.Time `json:"completedAt,omitempty" yaml:"completedAt,omitempty"`
|
||||
LastUpdatedAt *metav1.Time `json:"lastUpdatedAt,omitempty" yaml:"lastUpdatedAt,omitempty"`
|
||||
RetryCount int32 `json:"retryCount,omitempty" yaml:"retryCount,omitempty"`
|
||||
InactivePartition string `json:"inactivePartition,omitempty" yaml:"inactivePartition,omitempty"`
|
||||
FailureReason string `json:"failureReason,omitempty" yaml:"failureReason,omitempty"`
|
||||
Message string `json:"message,omitempty" yaml:"message,omitempty"`
|
||||
PlannedPath []string `json:"plannedPath,omitempty" yaml:"plannedPath,omitempty"`
|
||||
CurrentStep int32 `json:"currentStep,omitempty" yaml:"currentStep,omitempty"`
|
||||
CurrentFrom string `json:"currentFrom,omitempty" yaml:"currentFrom,omitempty"`
|
||||
CurrentTo string `json:"currentTo,omitempty" yaml:"currentTo,omitempty"`
|
||||
}
|
||||
|
||||
411
clitools/pkg/apis/monok8s/v1alpha1/zz_generated.deepcopy.go
Normal file
411
clitools/pkg/apis/monok8s/v1alpha1/zz_generated.deepcopy.go
Normal file
@@ -0,0 +1,411 @@
|
||||
//go:build !ignore_autogenerated
|
||||
|
||||
/* MIT License */
|
||||
|
||||
// Code generated by controller-gen. DO NOT EDIT.
|
||||
|
||||
package v1alpha1
|
||||
|
||||
import (
|
||||
"k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
"k8s.io/apimachinery/pkg/runtime"
|
||||
)
|
||||
|
||||
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
|
||||
func (in *MonoKSConfig) DeepCopyInto(out *MonoKSConfig) {
|
||||
*out = *in
|
||||
out.TypeMeta = in.TypeMeta
|
||||
in.ObjectMeta.DeepCopyInto(&out.ObjectMeta)
|
||||
in.Spec.DeepCopyInto(&out.Spec)
|
||||
if in.Status != nil {
|
||||
in, out := &in.Status, &out.Status
|
||||
*out = new(MonoKSConfigStatus)
|
||||
(*in).DeepCopyInto(*out)
|
||||
}
|
||||
}
|
||||
|
||||
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new MonoKSConfig.
|
||||
func (in *MonoKSConfig) DeepCopy() *MonoKSConfig {
|
||||
if in == nil {
|
||||
return nil
|
||||
}
|
||||
out := new(MonoKSConfig)
|
||||
in.DeepCopyInto(out)
|
||||
return out
|
||||
}
|
||||
|
||||
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
|
||||
func (in *MonoKSConfigList) DeepCopyInto(out *MonoKSConfigList) {
|
||||
*out = *in
|
||||
out.TypeMeta = in.TypeMeta
|
||||
in.ListMeta.DeepCopyInto(&out.ListMeta)
|
||||
if in.Items != nil {
|
||||
in, out := &in.Items, &out.Items
|
||||
*out = make([]MonoKSConfig, len(*in))
|
||||
for i := range *in {
|
||||
(*in)[i].DeepCopyInto(&(*out)[i])
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new MonoKSConfigList.
|
||||
func (in *MonoKSConfigList) DeepCopy() *MonoKSConfigList {
|
||||
if in == nil {
|
||||
return nil
|
||||
}
|
||||
out := new(MonoKSConfigList)
|
||||
in.DeepCopyInto(out)
|
||||
return out
|
||||
}
|
||||
|
||||
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
|
||||
func (in *MonoKSConfigSpec) DeepCopyInto(out *MonoKSConfigSpec) {
|
||||
*out = *in
|
||||
if in.KubeProxyNodePortAddresses != nil {
|
||||
in, out := &in.KubeProxyNodePortAddresses, &out.KubeProxyNodePortAddresses
|
||||
*out = make([]string, len(*in))
|
||||
copy(*out, *in)
|
||||
}
|
||||
if in.SubjectAltNames != nil {
|
||||
in, out := &in.SubjectAltNames, &out.SubjectAltNames
|
||||
*out = make([]string, len(*in))
|
||||
copy(*out, *in)
|
||||
}
|
||||
if in.NodeLabels != nil {
|
||||
in, out := &in.NodeLabels, &out.NodeLabels
|
||||
*out = make(map[string]string, len(*in))
|
||||
for key, val := range *in {
|
||||
(*out)[key] = val
|
||||
}
|
||||
}
|
||||
in.Network.DeepCopyInto(&out.Network)
|
||||
}
|
||||
|
||||
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new MonoKSConfigSpec.
|
||||
func (in *MonoKSConfigSpec) DeepCopy() *MonoKSConfigSpec {
|
||||
if in == nil {
|
||||
return nil
|
||||
}
|
||||
out := new(MonoKSConfigSpec)
|
||||
in.DeepCopyInto(out)
|
||||
return out
|
||||
}
|
||||
|
||||
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
|
||||
func (in *MonoKSConfigStatus) DeepCopyInto(out *MonoKSConfigStatus) {
|
||||
*out = *in
|
||||
if in.Conditions != nil {
|
||||
in, out := &in.Conditions, &out.Conditions
|
||||
*out = make([]v1.Condition, len(*in))
|
||||
for i := range *in {
|
||||
(*in)[i].DeepCopyInto(&(*out)[i])
|
||||
}
|
||||
}
|
||||
if in.AppliedSteps != nil {
|
||||
in, out := &in.AppliedSteps, &out.AppliedSteps
|
||||
*out = make([]string, len(*in))
|
||||
copy(*out, *in)
|
||||
}
|
||||
}
|
||||
|
||||
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new MonoKSConfigStatus.
|
||||
func (in *MonoKSConfigStatus) DeepCopy() *MonoKSConfigStatus {
|
||||
if in == nil {
|
||||
return nil
|
||||
}
|
||||
out := new(MonoKSConfigStatus)
|
||||
in.DeepCopyInto(out)
|
||||
return out
|
||||
}
|
||||
|
||||
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
|
||||
func (in *NetworkSpec) DeepCopyInto(out *NetworkSpec) {
|
||||
*out = *in
|
||||
if in.DNSNameservers != nil {
|
||||
in, out := &in.DNSNameservers, &out.DNSNameservers
|
||||
*out = make([]string, len(*in))
|
||||
copy(*out, *in)
|
||||
}
|
||||
if in.DNSSearchDomains != nil {
|
||||
in, out := &in.DNSSearchDomains, &out.DNSSearchDomains
|
||||
*out = make([]string, len(*in))
|
||||
copy(*out, *in)
|
||||
}
|
||||
}
|
||||
|
||||
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new NetworkSpec.
|
||||
func (in *NetworkSpec) DeepCopy() *NetworkSpec {
|
||||
if in == nil {
|
||||
return nil
|
||||
}
|
||||
out := new(NetworkSpec)
|
||||
in.DeepCopyInto(out)
|
||||
return out
|
||||
}
|
||||
|
||||
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
|
||||
func (in *OSUpgrade) DeepCopyInto(out *OSUpgrade) {
|
||||
*out = *in
|
||||
out.TypeMeta = in.TypeMeta
|
||||
in.ObjectMeta.DeepCopyInto(&out.ObjectMeta)
|
||||
in.Spec.DeepCopyInto(&out.Spec)
|
||||
if in.Status != nil {
|
||||
in, out := &in.Status, &out.Status
|
||||
*out = new(OSUpgradeStatus)
|
||||
(*in).DeepCopyInto(*out)
|
||||
}
|
||||
}
|
||||
|
||||
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new OSUpgrade.
|
||||
func (in *OSUpgrade) DeepCopy() *OSUpgrade {
|
||||
if in == nil {
|
||||
return nil
|
||||
}
|
||||
out := new(OSUpgrade)
|
||||
in.DeepCopyInto(out)
|
||||
return out
|
||||
}
|
||||
|
||||
// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object.
|
||||
func (in *OSUpgrade) DeepCopyObject() runtime.Object {
|
||||
if c := in.DeepCopy(); c != nil {
|
||||
return c
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
|
||||
func (in *OSUpgradeList) DeepCopyInto(out *OSUpgradeList) {
|
||||
*out = *in
|
||||
out.TypeMeta = in.TypeMeta
|
||||
in.ListMeta.DeepCopyInto(&out.ListMeta)
|
||||
if in.Items != nil {
|
||||
in, out := &in.Items, &out.Items
|
||||
*out = make([]OSUpgrade, len(*in))
|
||||
for i := range *in {
|
||||
(*in)[i].DeepCopyInto(&(*out)[i])
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new OSUpgradeList.
|
||||
func (in *OSUpgradeList) DeepCopy() *OSUpgradeList {
|
||||
if in == nil {
|
||||
return nil
|
||||
}
|
||||
out := new(OSUpgradeList)
|
||||
in.DeepCopyInto(out)
|
||||
return out
|
||||
}
|
||||
|
||||
// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object.
|
||||
func (in *OSUpgradeList) DeepCopyObject() runtime.Object {
|
||||
if c := in.DeepCopy(); c != nil {
|
||||
return c
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
|
||||
func (in *OSUpgradeProgress) DeepCopyInto(out *OSUpgradeProgress) {
|
||||
*out = *in
|
||||
out.TypeMeta = in.TypeMeta
|
||||
in.ObjectMeta.DeepCopyInto(&out.ObjectMeta)
|
||||
out.Spec = in.Spec
|
||||
if in.Status != nil {
|
||||
in, out := &in.Status, &out.Status
|
||||
*out = new(OSUpgradeProgressStatus)
|
||||
(*in).DeepCopyInto(*out)
|
||||
}
|
||||
}
|
||||
|
||||
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new OSUpgradeProgress.
|
||||
func (in *OSUpgradeProgress) DeepCopy() *OSUpgradeProgress {
|
||||
if in == nil {
|
||||
return nil
|
||||
}
|
||||
out := new(OSUpgradeProgress)
|
||||
in.DeepCopyInto(out)
|
||||
return out
|
||||
}
|
||||
|
||||
// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object.
|
||||
func (in *OSUpgradeProgress) DeepCopyObject() runtime.Object {
|
||||
if c := in.DeepCopy(); c != nil {
|
||||
return c
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
|
||||
func (in *OSUpgradeProgressList) DeepCopyInto(out *OSUpgradeProgressList) {
|
||||
*out = *in
|
||||
out.TypeMeta = in.TypeMeta
|
||||
in.ListMeta.DeepCopyInto(&out.ListMeta)
|
||||
if in.Items != nil {
|
||||
in, out := &in.Items, &out.Items
|
||||
*out = make([]OSUpgradeProgress, len(*in))
|
||||
for i := range *in {
|
||||
(*in)[i].DeepCopyInto(&(*out)[i])
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new OSUpgradeProgressList.
|
||||
func (in *OSUpgradeProgressList) DeepCopy() *OSUpgradeProgressList {
|
||||
if in == nil {
|
||||
return nil
|
||||
}
|
||||
out := new(OSUpgradeProgressList)
|
||||
in.DeepCopyInto(out)
|
||||
return out
|
||||
}
|
||||
|
||||
// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object.
|
||||
func (in *OSUpgradeProgressList) DeepCopyObject() runtime.Object {
|
||||
if c := in.DeepCopy(); c != nil {
|
||||
return c
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
|
||||
func (in *OSUpgradeProgressSpec) DeepCopyInto(out *OSUpgradeProgressSpec) {
|
||||
*out = *in
|
||||
out.SourceRef = in.SourceRef
|
||||
}
|
||||
|
||||
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new OSUpgradeProgressSpec.
|
||||
func (in *OSUpgradeProgressSpec) DeepCopy() *OSUpgradeProgressSpec {
|
||||
if in == nil {
|
||||
return nil
|
||||
}
|
||||
out := new(OSUpgradeProgressSpec)
|
||||
in.DeepCopyInto(out)
|
||||
return out
|
||||
}
|
||||
|
||||
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
|
||||
func (in *OSUpgradeProgressStatus) DeepCopyInto(out *OSUpgradeProgressStatus) {
|
||||
*out = *in
|
||||
if in.StartedAt != nil {
|
||||
in, out := &in.StartedAt, &out.StartedAt
|
||||
*out = (*in).DeepCopy()
|
||||
}
|
||||
if in.CompletedAt != nil {
|
||||
in, out := &in.CompletedAt, &out.CompletedAt
|
||||
*out = (*in).DeepCopy()
|
||||
}
|
||||
if in.LastUpdatedAt != nil {
|
||||
in, out := &in.LastUpdatedAt, &out.LastUpdatedAt
|
||||
*out = (*in).DeepCopy()
|
||||
}
|
||||
if in.PlannedPath != nil {
|
||||
in, out := &in.PlannedPath, &out.PlannedPath
|
||||
*out = make([]string, len(*in))
|
||||
copy(*out, *in)
|
||||
}
|
||||
}
|
||||
|
||||
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new OSUpgradeProgressStatus.
|
||||
func (in *OSUpgradeProgressStatus) DeepCopy() *OSUpgradeProgressStatus {
|
||||
if in == nil {
|
||||
return nil
|
||||
}
|
||||
out := new(OSUpgradeProgressStatus)
|
||||
in.DeepCopyInto(out)
|
||||
return out
|
||||
}
|
||||
|
||||
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
|
||||
func (in *OSUpgradeSourceRef) DeepCopyInto(out *OSUpgradeSourceRef) {
|
||||
*out = *in
|
||||
}
|
||||
|
||||
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new OSUpgradeSourceRef.
|
||||
func (in *OSUpgradeSourceRef) DeepCopy() *OSUpgradeSourceRef {
|
||||
if in == nil {
|
||||
return nil
|
||||
}
|
||||
out := new(OSUpgradeSourceRef)
|
||||
in.DeepCopyInto(out)
|
||||
return out
|
||||
}
|
||||
|
||||
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
|
||||
func (in *OSUpgradeSpec) DeepCopyInto(out *OSUpgradeSpec) {
|
||||
*out = *in
|
||||
if in.Catalog != nil {
|
||||
in, out := &in.Catalog, &out.Catalog
|
||||
*out = new(VersionCatalogSource)
|
||||
**out = **in
|
||||
}
|
||||
if in.NodeSelector != nil {
|
||||
in, out := &in.NodeSelector, &out.NodeSelector
|
||||
*out = new(v1.LabelSelector)
|
||||
(*in).DeepCopyInto(*out)
|
||||
}
|
||||
}
|
||||
|
||||
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new OSUpgradeSpec.
|
||||
func (in *OSUpgradeSpec) DeepCopy() *OSUpgradeSpec {
|
||||
if in == nil {
|
||||
return nil
|
||||
}
|
||||
out := new(OSUpgradeSpec)
|
||||
in.DeepCopyInto(out)
|
||||
return out
|
||||
}
|
||||
|
||||
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
|
||||
func (in *OSUpgradeStatus) DeepCopyInto(out *OSUpgradeStatus) {
|
||||
*out = *in
|
||||
out.Summary = in.Summary
|
||||
if in.Conditions != nil {
|
||||
in, out := &in.Conditions, &out.Conditions
|
||||
*out = make([]v1.Condition, len(*in))
|
||||
for i := range *in {
|
||||
(*in)[i].DeepCopyInto(&(*out)[i])
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new OSUpgradeStatus.
|
||||
func (in *OSUpgradeStatus) DeepCopy() *OSUpgradeStatus {
|
||||
if in == nil {
|
||||
return nil
|
||||
}
|
||||
out := new(OSUpgradeStatus)
|
||||
in.DeepCopyInto(out)
|
||||
return out
|
||||
}
|
||||
|
||||
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
|
||||
func (in *OSUpgradeSummary) DeepCopyInto(out *OSUpgradeSummary) {
|
||||
*out = *in
|
||||
}
|
||||
|
||||
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new OSUpgradeSummary.
|
||||
func (in *OSUpgradeSummary) DeepCopy() *OSUpgradeSummary {
|
||||
if in == nil {
|
||||
return nil
|
||||
}
|
||||
out := new(OSUpgradeSummary)
|
||||
in.DeepCopyInto(out)
|
||||
return out
|
||||
}
|
||||
|
||||
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
|
||||
func (in *VersionCatalogSource) DeepCopyInto(out *VersionCatalogSource) {
|
||||
*out = *in
|
||||
}
|
||||
|
||||
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new VersionCatalogSource.
|
||||
func (in *VersionCatalogSource) DeepCopy() *VersionCatalogSource {
|
||||
if in == nil {
|
||||
return nil
|
||||
}
|
||||
out := new(VersionCatalogSource)
|
||||
in.DeepCopyInto(out)
|
||||
return out
|
||||
}
|
||||
@@ -9,10 +9,7 @@ import (
|
||||
|
||||
"github.com/spf13/cobra"
|
||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
|
||||
"k8s.io/apimachinery/pkg/labels"
|
||||
"k8s.io/apimachinery/pkg/runtime"
|
||||
"k8s.io/apimachinery/pkg/runtime/schema"
|
||||
"k8s.io/apimachinery/pkg/watch"
|
||||
"k8s.io/cli-runtime/pkg/genericclioptions"
|
||||
"k8s.io/klog/v2"
|
||||
|
||||
@@ -23,18 +20,13 @@ import (
|
||||
"example.com/monok8s/pkg/templates"
|
||||
)
|
||||
|
||||
const defaultPollInterval = 15 * time.Second
|
||||
|
||||
var runtimeDefaultUnstructuredConverter = runtime.DefaultUnstructuredConverter
|
||||
|
||||
func NewCmdAgent(flags *genericclioptions.ConfigFlags) *cobra.Command {
|
||||
var namespace string
|
||||
var envFile string
|
||||
var pollInterval time.Duration
|
||||
|
||||
cmd := &cobra.Command{
|
||||
Use: "agent --env-file path",
|
||||
Short: "Watch OSUpgrade resources and process matching upgrades for this node",
|
||||
Short: "Watch OSUpgradeProgress resources for this node and process upgrades",
|
||||
RunE: func(cmd *cobra.Command, _ []string) error {
|
||||
if envFile == "" {
|
||||
return fmt.Errorf("--env-file is required")
|
||||
@@ -61,7 +53,6 @@ func NewCmdAgent(flags *genericclioptions.ConfigFlags) *cobra.Command {
|
||||
"node", cfg.Spec.NodeName,
|
||||
"namespace", namespace,
|
||||
"envFile", envFile,
|
||||
"pollInterval", pollInterval,
|
||||
)
|
||||
|
||||
clients, err := kube.NewClients(flags)
|
||||
@@ -69,13 +60,12 @@ func NewCmdAgent(flags *genericclioptions.ConfigFlags) *cobra.Command {
|
||||
return fmt.Errorf("create kube clients: %w", err)
|
||||
}
|
||||
|
||||
return runPollLoop(ctx, clients, namespace, cfg.Spec.NodeName, pollInterval)
|
||||
return runWatchLoop(ctx, clients, namespace, cfg.Spec.NodeName)
|
||||
},
|
||||
}
|
||||
|
||||
cmd.Flags().StringVar(&namespace, "namespace", "kube-system", "namespace to watch")
|
||||
cmd.Flags().StringVar(&namespace, "namespace", templates.DefaultNamespace, "namespace to watch")
|
||||
cmd.Flags().StringVar(&envFile, "env-file", "", "path to env file containing MKS_* variables")
|
||||
cmd.Flags().DurationVar(&pollInterval, "poll-interval", defaultPollInterval, "poll interval for OSUpgrade resources")
|
||||
|
||||
return cmd
|
||||
}
|
||||
@@ -94,9 +84,9 @@ func waitForControlGate(ctx context.Context, envFile string, pollInterval time.D
|
||||
for {
|
||||
_, err := os.Stat(marker)
|
||||
if err == nil {
|
||||
klog.InfoS("Control gate is present; waiting before starting poll loop", "path", marker)
|
||||
klog.InfoS("Control gate is present; waiting before starting watch loop", "path", marker)
|
||||
} else if os.IsNotExist(err) {
|
||||
klog.InfoS("Control gate not present; starting poll loop", "path", marker)
|
||||
klog.InfoS("Control gate not present; starting watch loop", "path", marker)
|
||||
return nil
|
||||
} else {
|
||||
return fmt.Errorf("stat upgrade marker %s: %w", marker, err)
|
||||
@@ -110,126 +100,181 @@ func waitForControlGate(ctx context.Context, envFile string, pollInterval time.D
|
||||
}
|
||||
}
|
||||
|
||||
func runPollLoop(ctx context.Context, clients *kube.Clients, namespace, nodeName string, interval time.Duration) error {
|
||||
gvr := schema.GroupVersionResource{
|
||||
Group: monov1alpha1.Group,
|
||||
Version: monov1alpha1.Version,
|
||||
Resource: "osupgrades",
|
||||
}
|
||||
|
||||
ticker := time.NewTicker(interval)
|
||||
defer ticker.Stop()
|
||||
func runWatchLoop(ctx context.Context, clients *kube.Clients, namespace, nodeName string) error {
|
||||
var resourceVersion string
|
||||
|
||||
for {
|
||||
if err := pollOnce(ctx, clients, gvr, namespace, nodeName); err != nil {
|
||||
klog.ErrorS(err, "poll failed", "namespace", namespace, "node", nodeName)
|
||||
if ctx.Err() != nil {
|
||||
return ctx.Err()
|
||||
}
|
||||
|
||||
select {
|
||||
case <-ctx.Done():
|
||||
return ctx.Err()
|
||||
case <-ticker.C:
|
||||
err := watchOnce(ctx, clients, namespace, nodeName, &resourceVersion)
|
||||
if err != nil {
|
||||
if ctx.Err() != nil {
|
||||
return ctx.Err()
|
||||
}
|
||||
klog.ErrorS(err, "watch failed; retrying",
|
||||
"namespace", namespace,
|
||||
"node", nodeName,
|
||||
"resourceVersion", resourceVersion,
|
||||
)
|
||||
select {
|
||||
case <-ctx.Done():
|
||||
return ctx.Err()
|
||||
case <-time.After(2 * time.Second):
|
||||
}
|
||||
continue
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func pollOnce(
|
||||
func watchOnce(
|
||||
ctx context.Context,
|
||||
clients *kube.Clients,
|
||||
gvr schema.GroupVersionResource,
|
||||
namespace string,
|
||||
nodeName string,
|
||||
resourceVersion *string,
|
||||
) error {
|
||||
list, err := clients.Dynamic.Resource(gvr).Namespace(namespace).List(ctx, metav1.ListOptions{})
|
||||
|
||||
list, err := clients.MonoKS.
|
||||
Monok8sV1alpha1().
|
||||
OSUpgradeProgresses(namespace).
|
||||
List(ctx, metav1.ListOptions{})
|
||||
if err != nil {
|
||||
return fmt.Errorf("list osupgrades: %w", err)
|
||||
}
|
||||
|
||||
klog.InfoS("agent tick", "namespace", namespace, "items", len(list.Items), "node", nodeName)
|
||||
|
||||
nodeLabels := labels.Set{
|
||||
"kubernetes.io/hostname": nodeName,
|
||||
"monok8s.io/node-name": nodeName,
|
||||
"monok8s.io/control-agent": "true",
|
||||
return fmt.Errorf("list osupgradeprogresses: %w", err)
|
||||
}
|
||||
|
||||
for i := range list.Items {
|
||||
item := &list.Items[i]
|
||||
|
||||
osu, err := decodeOSUpgrade(item)
|
||||
if err != nil {
|
||||
klog.ErrorS(err, "failed to decode osupgrade",
|
||||
"name", item.GetName(),
|
||||
"resourceVersion", item.GetResourceVersion(),
|
||||
)
|
||||
if !targetsNode(item, nodeName) {
|
||||
continue
|
||||
}
|
||||
if !shouldHandle(item) {
|
||||
continue
|
||||
}
|
||||
|
||||
if !matchesNode(osu, nodeName, nodeLabels) {
|
||||
klog.V(2).InfoS("skipping osupgrade; not targeted to this node",
|
||||
"name", osu.Name,
|
||||
"node", nodeName,
|
||||
)
|
||||
continue
|
||||
}
|
||||
|
||||
klog.InfoS("matched osupgrade",
|
||||
"name", osu.Name,
|
||||
klog.InfoS("found existing osupgradeprogress",
|
||||
"name", item.Name,
|
||||
"node", nodeName,
|
||||
"desiredVersion", osu.Spec.DesiredVersion,
|
||||
"phase", statusPhase(osu.Status),
|
||||
"resourceVersion", osu.ResourceVersion,
|
||||
"phase", progressPhase(item.Status),
|
||||
"resourceVersion", item.ResourceVersion,
|
||||
)
|
||||
|
||||
if err := osupgradeController.HandleOSUpgrade(ctx, clients, namespace, nodeName, osu); err != nil {
|
||||
klog.ErrorS(err, "failed to handle osupgrade",
|
||||
"name", osu.Name,
|
||||
if err := osupgradeController.HandleOSUpgradeProgress(ctx, clients, namespace, nodeName, item); err != nil {
|
||||
klog.ErrorS(err, "failed to handle existing osupgradeprogress",
|
||||
"name", item.Name,
|
||||
"node", nodeName,
|
||||
)
|
||||
continue
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
*resourceVersion = list.ResourceVersion
|
||||
|
||||
func decodeOSUpgrade(item *unstructured.Unstructured) (*monov1alpha1.OSUpgrade, error) {
|
||||
var osu monov1alpha1.OSUpgrade
|
||||
if err := runtimeDefaultUnstructuredConverter.FromUnstructured(item.Object, &osu); err != nil {
|
||||
return nil, fmt.Errorf("convert unstructured to OSUpgrade: %w", err)
|
||||
}
|
||||
return &osu, nil
|
||||
}
|
||||
|
||||
func matchesNode(osu *monov1alpha1.OSUpgrade, nodeName string, nodeLabels labels.Set) bool {
|
||||
if osu == nil {
|
||||
return false
|
||||
}
|
||||
|
||||
sel := osu.Spec.NodeSelector
|
||||
if sel == nil {
|
||||
// No selector means "match all nodes".
|
||||
return true
|
||||
}
|
||||
|
||||
selector, err := metav1.LabelSelectorAsSelector(sel)
|
||||
w, err := clients.MonoKS.
|
||||
Monok8sV1alpha1().
|
||||
OSUpgradeProgresses(namespace).
|
||||
Watch(ctx, metav1.ListOptions{
|
||||
ResourceVersion: *resourceVersion,
|
||||
})
|
||||
if err != nil {
|
||||
klog.ErrorS(err, "invalid node selector on osupgrade", "name", osu.Name)
|
||||
return fmt.Errorf("watch osupgradeprogresses: %w", err)
|
||||
}
|
||||
defer w.Stop()
|
||||
|
||||
klog.InfoS("watching osupgradeprogresses",
|
||||
"namespace", namespace,
|
||||
"node", nodeName,
|
||||
"resourceVersion", *resourceVersion,
|
||||
)
|
||||
|
||||
for {
|
||||
select {
|
||||
case <-ctx.Done():
|
||||
return ctx.Err()
|
||||
|
||||
case evt, ok := <-w.ResultChan():
|
||||
if !ok {
|
||||
return fmt.Errorf("watch channel closed")
|
||||
}
|
||||
|
||||
switch evt.Type {
|
||||
case watch.Bookmark:
|
||||
obj, ok := evt.Object.(*monov1alpha1.OSUpgradeProgress)
|
||||
if ok && obj != nil && obj.ResourceVersion != "" {
|
||||
*resourceVersion = obj.ResourceVersion
|
||||
}
|
||||
continue
|
||||
|
||||
case watch.Error:
|
||||
return fmt.Errorf("watch returned error event")
|
||||
}
|
||||
|
||||
osup, ok := evt.Object.(*monov1alpha1.OSUpgradeProgress)
|
||||
if !ok {
|
||||
klog.V(1).InfoS("skipping unexpected watch object type",
|
||||
"type", fmt.Sprintf("%T", evt.Object),
|
||||
)
|
||||
continue
|
||||
}
|
||||
|
||||
if osup.ResourceVersion != "" {
|
||||
*resourceVersion = osup.ResourceVersion
|
||||
}
|
||||
|
||||
if !targetsNode(osup, nodeName) {
|
||||
continue
|
||||
}
|
||||
if !shouldHandle(osup) {
|
||||
klog.V(2).InfoS("skipping osupgradeprogress due to phase",
|
||||
"name", osup.Name,
|
||||
"node", nodeName,
|
||||
"phase", progressPhase(osup.Status),
|
||||
"eventType", evt.Type,
|
||||
)
|
||||
continue
|
||||
}
|
||||
|
||||
klog.InfoS("received osupgradeprogress event",
|
||||
"name", osup.Name,
|
||||
"node", nodeName,
|
||||
"phase", progressPhase(osup.Status),
|
||||
"eventType", evt.Type,
|
||||
"resourceVersion", osup.ResourceVersion,
|
||||
)
|
||||
|
||||
if err := osupgradeController.HandleOSUpgradeProgress(ctx, clients, namespace, nodeName, osup); err != nil {
|
||||
klog.ErrorS(err, "failed to handle osupgradeprogress",
|
||||
"name", osup.Name,
|
||||
"node", nodeName,
|
||||
"eventType", evt.Type,
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func targetsNode(osup *monov1alpha1.OSUpgradeProgress, nodeName string) bool {
|
||||
if osup == nil {
|
||||
return false
|
||||
}
|
||||
return osup.Spec.NodeName == nodeName
|
||||
}
|
||||
|
||||
func shouldHandle(osup *monov1alpha1.OSUpgradeProgress) bool {
|
||||
if osup == nil {
|
||||
return false
|
||||
}
|
||||
|
||||
if selector.Empty() {
|
||||
switch osup.Status.Phase {
|
||||
case "",
|
||||
monov1alpha1.OSUpgradeProgressPhasePending:
|
||||
return true
|
||||
default:
|
||||
return false
|
||||
}
|
||||
|
||||
if selector.Matches(nodeLabels) {
|
||||
return true
|
||||
}
|
||||
|
||||
return false
|
||||
}
|
||||
|
||||
func statusPhase(st *monov1alpha1.OSUpgradeStatus) string {
|
||||
func progressPhase(st *monov1alpha1.OSUpgradeProgressStatus) string {
|
||||
if st == nil {
|
||||
return ""
|
||||
}
|
||||
|
||||
97
clitools/pkg/cmd/controller/controller.go
Normal file
97
clitools/pkg/cmd/controller/controller.go
Normal file
@@ -0,0 +1,97 @@
|
||||
package controller
|
||||
|
||||
import (
|
||||
"context"
|
||||
"net"
|
||||
"net/http"
|
||||
"os"
|
||||
"time"
|
||||
|
||||
"github.com/spf13/cobra"
|
||||
"k8s.io/cli-runtime/pkg/genericclioptions"
|
||||
"k8s.io/klog/v2"
|
||||
|
||||
mksadmission "example.com/monok8s/pkg/controller/admission"
|
||||
"example.com/monok8s/pkg/kube"
|
||||
"example.com/monok8s/pkg/templates"
|
||||
)
|
||||
|
||||
type ServerConfig struct {
|
||||
TLSCertFile string `json:"tlsCertFile,omitempty"`
|
||||
TLSPrivateKeyFile string `json:"tlsPrivateKeyFile,omitempty"`
|
||||
}
|
||||
|
||||
func NewCmdController(flags *genericclioptions.ConfigFlags) *cobra.Command {
|
||||
var namespace string = templates.DefaultNamespace
|
||||
var conf ServerConfig
|
||||
|
||||
cmd := &cobra.Command{
|
||||
Use: "controller",
|
||||
Short: "Admission controller that handles OSUpgrade resources",
|
||||
RunE: func(cmd *cobra.Command, _ []string) error {
|
||||
|
||||
ctx := cmd.Context()
|
||||
|
||||
klog.InfoS("starting controller",
|
||||
"namespace", namespace,
|
||||
)
|
||||
|
||||
clients, err := kube.NewClients(flags)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return httpListen(ctx, clients, conf)
|
||||
},
|
||||
}
|
||||
|
||||
cmd.Flags().StringVar(&namespace, "namespace", templates.DefaultNamespace, "namespace to watch")
|
||||
cmd.Flags().StringVar(&conf.TLSCertFile, "tls-cert-file", conf.TLSCertFile,
|
||||
"File containing x509 Certificate used for serving HTTPS (with intermediate certs, if any, concatenated after server cert).")
|
||||
cmd.Flags().StringVar(&conf.TLSPrivateKeyFile, "tls-private-key-file", conf.TLSPrivateKeyFile, "File containing x509 private key matching --tls-cert-file.")
|
||||
|
||||
return cmd
|
||||
}
|
||||
|
||||
func httpListen(ctx context.Context, clients *kube.Clients, conf ServerConfig) error {
|
||||
address, port := "", "8443"
|
||||
addr := net.JoinHostPort(address, port)
|
||||
|
||||
ns := os.Getenv("POD_NAMESPACE")
|
||||
nodeName := os.Getenv("NODE_NAME")
|
||||
|
||||
server := mksadmission.NewServer(ctx, clients, ns, nodeName)
|
||||
|
||||
s := &http.Server{
|
||||
Addr: addr,
|
||||
Handler: server,
|
||||
IdleTimeout: 90 * time.Second,
|
||||
ReadTimeout: 4 * 60 * time.Minute,
|
||||
WriteTimeout: 4 * 60 * time.Minute,
|
||||
MaxHeaderBytes: 1 << 20,
|
||||
}
|
||||
|
||||
if conf.TLSCertFile != "" {
|
||||
klog.InfoS("starting HTTPS server",
|
||||
"addr", addr,
|
||||
"certFile", conf.TLSCertFile,
|
||||
"keyFile", conf.TLSPrivateKeyFile,
|
||||
)
|
||||
|
||||
if err := s.ListenAndServeTLS(conf.TLSCertFile, conf.TLSPrivateKeyFile); err != nil {
|
||||
klog.ErrorS(err, "HTTPS server failed")
|
||||
os.Exit(1)
|
||||
}
|
||||
} else {
|
||||
klog.InfoS("starting HTTP server",
|
||||
"addr", addr,
|
||||
)
|
||||
|
||||
if err := s.ListenAndServe(); err != nil {
|
||||
klog.ErrorS(err, "HTTP server failed")
|
||||
os.Exit(1)
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
@@ -6,6 +6,7 @@ import (
|
||||
|
||||
agentcmd "example.com/monok8s/pkg/cmd/agent"
|
||||
checkconfigcmd "example.com/monok8s/pkg/cmd/checkconfig"
|
||||
controllercmd "example.com/monok8s/pkg/cmd/controller"
|
||||
createcmd "example.com/monok8s/pkg/cmd/create"
|
||||
initcmd "example.com/monok8s/pkg/cmd/initcmd"
|
||||
internalcmd "example.com/monok8s/pkg/cmd/internal"
|
||||
@@ -45,6 +46,7 @@ func NewRootCmd() *cobra.Command {
|
||||
checkconfigcmd.NewCmdCheckConfig(),
|
||||
createcmd.NewCmdCreate(),
|
||||
agentcmd.NewCmdAgent(flags),
|
||||
controllercmd.NewCmdController(flags),
|
||||
internalcmd.NewCmdInternal(),
|
||||
)
|
||||
return cmd
|
||||
|
||||
157
clitools/pkg/controller/admission/server.go
Normal file
157
clitools/pkg/controller/admission/server.go
Normal file
@@ -0,0 +1,157 @@
|
||||
package admission
|
||||
|
||||
import (
|
||||
"context"
|
||||
"io"
|
||||
"net/http"
|
||||
|
||||
admissionv1 "k8s.io/api/admission/v1"
|
||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
|
||||
monov1alpha1 "example.com/monok8s/pkg/apis/monok8s/v1alpha1"
|
||||
"example.com/monok8s/pkg/controller/osupgrade"
|
||||
"example.com/monok8s/pkg/kube"
|
||||
|
||||
"github.com/emicklei/go-restful/v3"
|
||||
"k8s.io/apimachinery/pkg/runtime"
|
||||
"k8s.io/apimachinery/pkg/runtime/serializer"
|
||||
"k8s.io/apiserver/pkg/server/httplog"
|
||||
"k8s.io/klog/v2"
|
||||
)
|
||||
|
||||
var (
|
||||
scheme = runtime.NewScheme()
|
||||
codecs = serializer.NewCodecFactory(scheme)
|
||||
deserializer = codecs.UniversalDeserializer()
|
||||
)
|
||||
|
||||
var statusesNoTracePred = httplog.StatusIsNot(
|
||||
http.StatusOK,
|
||||
http.StatusFound,
|
||||
http.StatusMovedPermanently,
|
||||
http.StatusTemporaryRedirect,
|
||||
http.StatusBadRequest,
|
||||
http.StatusNotFound,
|
||||
http.StatusSwitchingProtocols,
|
||||
)
|
||||
|
||||
func init() {
|
||||
_ = admissionv1.AddToScheme(scheme)
|
||||
_ = monov1alpha1.AddToScheme(scheme)
|
||||
}
|
||||
|
||||
type Server struct {
|
||||
restfulCont *restful.Container
|
||||
|
||||
ctx context.Context
|
||||
clients *kube.Clients
|
||||
namespace string
|
||||
nodeName string
|
||||
}
|
||||
|
||||
func NewServer(ctx context.Context, clients *kube.Clients, namespace, nodeName string) *Server {
|
||||
s := &Server{
|
||||
ctx: ctx,
|
||||
clients: clients,
|
||||
namespace: namespace,
|
||||
nodeName: nodeName,
|
||||
}
|
||||
s.Initialize()
|
||||
return s
|
||||
}
|
||||
|
||||
func (s *Server) ServeHTTP(w http.ResponseWriter, req *http.Request) {
|
||||
if s == nil {
|
||||
http.Error(w, "admission server is nil", http.StatusInternalServerError)
|
||||
return
|
||||
}
|
||||
if s.restfulCont == nil {
|
||||
http.Error(w, "admission server not initialized", http.StatusInternalServerError)
|
||||
return
|
||||
}
|
||||
|
||||
handler := httplog.WithLogging(s.restfulCont, statusesNoTracePred)
|
||||
handler.ServeHTTP(w, req)
|
||||
}
|
||||
|
||||
func (s *Server) Initialize() {
|
||||
s.restfulCont = restful.NewContainer()
|
||||
|
||||
ws := new(restful.WebService)
|
||||
|
||||
ws.Path("/admission").
|
||||
Consumes(restful.MIME_JSON).
|
||||
Produces(restful.MIME_JSON)
|
||||
|
||||
ws.Route(ws.POST("").To(s.triggerAdmission).
|
||||
Reads(admissionv1.AdmissionReview{}).
|
||||
Writes(admissionv1.AdmissionReview{}))
|
||||
|
||||
s.restfulCont.Add(ws)
|
||||
}
|
||||
|
||||
func (s *Server) triggerAdmission(request *restful.Request, response *restful.Response) {
|
||||
body, err := io.ReadAll(request.Request.Body)
|
||||
if err != nil {
|
||||
_ = response.WriteError(http.StatusBadRequest, err)
|
||||
return
|
||||
}
|
||||
|
||||
var reviewReq admissionv1.AdmissionReview
|
||||
if _, _, err := deserializer.Decode(body, nil, &reviewReq); err != nil {
|
||||
_ = response.WriteError(http.StatusBadRequest, err)
|
||||
return
|
||||
}
|
||||
if reviewReq.Request == nil {
|
||||
_ = response.WriteErrorString(http.StatusBadRequest, "missing admission request")
|
||||
return
|
||||
}
|
||||
|
||||
resp := admissionv1.AdmissionReview{
|
||||
TypeMeta: metav1.TypeMeta{
|
||||
Kind: "AdmissionReview",
|
||||
APIVersion: "admission.k8s.io/v1",
|
||||
},
|
||||
Response: &admissionv1.AdmissionResponse{
|
||||
UID: reviewReq.Request.UID,
|
||||
Allowed: true,
|
||||
Result: &metav1.Status{Message: "OK"},
|
||||
},
|
||||
}
|
||||
|
||||
var osu monov1alpha1.OSUpgrade
|
||||
if _, _, err := deserializer.Decode(reviewReq.Request.Object.Raw, nil, &osu); err != nil {
|
||||
klog.V(1).InfoS("Skipping non-OSUpgrade resource",
|
||||
"uid", reviewReq.Request.UID,
|
||||
"kind", reviewReq.Request.Kind.Kind,
|
||||
"operation", reviewReq.Request.Operation,
|
||||
"err", err,
|
||||
)
|
||||
_ = response.WriteEntity(resp)
|
||||
return
|
||||
}
|
||||
|
||||
klog.InfoS("Received OSUpgrade admission",
|
||||
"uid", reviewReq.Request.UID,
|
||||
"operation", reviewReq.Request.Operation,
|
||||
"name", osu.Name,
|
||||
"namespace", osu.Namespace,
|
||||
"node", s.nodeName,
|
||||
)
|
||||
|
||||
// Resolve every node name
|
||||
if err := osupgrade.EnsureOSUpgradeProgressForNode(
|
||||
s.ctx,
|
||||
s.clients,
|
||||
s.namespace,
|
||||
s.nodeName,
|
||||
&osu,
|
||||
); err != nil {
|
||||
klog.ErrorS(err, "ensure OSUpgradeProgress for node failed",
|
||||
"osupgrade", osu.Name,
|
||||
"node", s.nodeName,
|
||||
)
|
||||
}
|
||||
|
||||
_ = response.WriteEntity(resp)
|
||||
}
|
||||
@@ -41,26 +41,55 @@ func (r *UpgradeRunner) Run(fn func() error) error {
|
||||
return fn()
|
||||
}
|
||||
|
||||
func HandleOSUpgrade(ctx context.Context, clients *kube.Clients,
|
||||
namespace string, nodeName string,
|
||||
osu *monov1alpha1.OSUpgrade,
|
||||
func HandleOSUpgradeProgress(
|
||||
ctx context.Context,
|
||||
clients *kube.Clients,
|
||||
namespace string,
|
||||
nodeName string,
|
||||
osup *monov1alpha1.OSUpgradeProgress,
|
||||
) error {
|
||||
return r.Run(func() error {
|
||||
return handleOSUpgradeLocked(ctx, clients, namespace, nodeName, osu)
|
||||
return handleOSUpgradeProgressLocked(ctx, clients, namespace, nodeName, osup)
|
||||
})
|
||||
}
|
||||
|
||||
func handleOSUpgradeLocked(ctx context.Context, clients *kube.Clients,
|
||||
namespace string, nodeName string,
|
||||
osu *monov1alpha1.OSUpgrade,
|
||||
func handleOSUpgradeProgressLocked(
|
||||
ctx context.Context,
|
||||
clients *kube.Clients,
|
||||
namespace string,
|
||||
nodeName string,
|
||||
osup *monov1alpha1.OSUpgradeProgress,
|
||||
) error {
|
||||
osup, err := ensureProgressHeartbeat(ctx, clients, namespace, nodeName, osu)
|
||||
if err != nil {
|
||||
return err
|
||||
if osup == nil {
|
||||
return fmt.Errorf("osupgradeprogress is nil")
|
||||
}
|
||||
|
||||
klog.InfoS("handling osupgrade",
|
||||
"name", osu.Name,
|
||||
if osup.Spec.NodeName != nodeName {
|
||||
return nil
|
||||
}
|
||||
|
||||
if osup.Status.Phase != "" &&
|
||||
osup.Status.Phase != monov1alpha1.OSUpgradeProgressPhasePending &&
|
||||
osup.Status.Phase != monov1alpha1.OSUpgradeProgressPhaseDownloading {
|
||||
// tune this logic however you want
|
||||
return nil
|
||||
}
|
||||
|
||||
parentName := osup.Spec.SourceRef.Name
|
||||
if parentName == "" {
|
||||
return failProgress(ctx, clients, osup, "resolve parent osupgrade", fmt.Errorf("missing spec.osUpgradeName"))
|
||||
}
|
||||
|
||||
osu, err := clients.MonoKS.Monok8sV1alpha1().
|
||||
OSUpgrades(namespace).
|
||||
Get(ctx, parentName, metav1.GetOptions{})
|
||||
if err != nil {
|
||||
return failProgress(ctx, clients, osup, "resolve parent osupgrade", err)
|
||||
}
|
||||
|
||||
klog.InfoS("handling osupgradeprogress",
|
||||
"name", osup.Name,
|
||||
"osupgrade", osu.Name,
|
||||
"node", nodeName,
|
||||
"desiredVersion", osu.Spec.DesiredVersion,
|
||||
)
|
||||
|
||||
@@ -28,6 +28,33 @@ var (
|
||||
}
|
||||
)
|
||||
|
||||
func EnsureOSUpgradeProgressForNode(
|
||||
ctx context.Context,
|
||||
clients *kube.Clients,
|
||||
namespace string,
|
||||
nodeName string,
|
||||
osu *monov1alpha1.OSUpgrade,
|
||||
) error {
|
||||
if osu == nil {
|
||||
return fmt.Errorf("osupgrade is nil")
|
||||
}
|
||||
|
||||
// Keep using your existing helper if it already encapsulates
|
||||
// selector matching / parent linkage / create-or-update semantics.
|
||||
osup, err := ensureProgressHeartbeat(ctx, clients, namespace, nodeName, osu)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
klog.InfoS("ensured OSUpgradeProgress from admission",
|
||||
"osupgrade", osu.Name,
|
||||
"osupgradeProgress", osup.Name,
|
||||
"node", nodeName,
|
||||
)
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func ensureProgressHeartbeat(ctx context.Context, clients *kube.Clients,
|
||||
namespace string, nodeName string,
|
||||
osu *monov1alpha1.OSUpgrade,
|
||||
|
||||
106
clitools/pkg/generated/clientset/versioned/clientset.go
Normal file
106
clitools/pkg/generated/clientset/versioned/clientset.go
Normal file
@@ -0,0 +1,106 @@
|
||||
/* MIT License */
|
||||
|
||||
// Code generated by client-gen. DO NOT EDIT.
|
||||
|
||||
package versioned
|
||||
|
||||
import (
|
||||
fmt "fmt"
|
||||
http "net/http"
|
||||
|
||||
monok8sv1alpha1 "example.com/monok8s/pkg/generated/clientset/versioned/typed/monok8s/v1alpha1"
|
||||
discovery "k8s.io/client-go/discovery"
|
||||
rest "k8s.io/client-go/rest"
|
||||
flowcontrol "k8s.io/client-go/util/flowcontrol"
|
||||
)
|
||||
|
||||
type Interface interface {
|
||||
Discovery() discovery.DiscoveryInterface
|
||||
Monok8sV1alpha1() monok8sv1alpha1.Monok8sV1alpha1Interface
|
||||
}
|
||||
|
||||
// Clientset contains the clients for groups.
|
||||
type Clientset struct {
|
||||
*discovery.DiscoveryClient
|
||||
monok8sV1alpha1 *monok8sv1alpha1.Monok8sV1alpha1Client
|
||||
}
|
||||
|
||||
// Monok8sV1alpha1 retrieves the Monok8sV1alpha1Client
|
||||
func (c *Clientset) Monok8sV1alpha1() monok8sv1alpha1.Monok8sV1alpha1Interface {
|
||||
return c.monok8sV1alpha1
|
||||
}
|
||||
|
||||
// Discovery retrieves the DiscoveryClient
|
||||
func (c *Clientset) Discovery() discovery.DiscoveryInterface {
|
||||
if c == nil {
|
||||
return nil
|
||||
}
|
||||
return c.DiscoveryClient
|
||||
}
|
||||
|
||||
// NewForConfig creates a new Clientset for the given config.
|
||||
// If config's RateLimiter is not set and QPS and Burst are acceptable,
|
||||
// NewForConfig will generate a rate-limiter in configShallowCopy.
|
||||
// NewForConfig is equivalent to NewForConfigAndClient(c, httpClient),
|
||||
// where httpClient was generated with rest.HTTPClientFor(c).
|
||||
func NewForConfig(c *rest.Config) (*Clientset, error) {
|
||||
configShallowCopy := *c
|
||||
|
||||
if configShallowCopy.UserAgent == "" {
|
||||
configShallowCopy.UserAgent = rest.DefaultKubernetesUserAgent()
|
||||
}
|
||||
|
||||
// share the transport between all clients
|
||||
httpClient, err := rest.HTTPClientFor(&configShallowCopy)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return NewForConfigAndClient(&configShallowCopy, httpClient)
|
||||
}
|
||||
|
||||
// NewForConfigAndClient creates a new Clientset for the given config and http client.
|
||||
// Note the http client provided takes precedence over the configured transport values.
|
||||
// If config's RateLimiter is not set and QPS and Burst are acceptable,
|
||||
// NewForConfigAndClient will generate a rate-limiter in configShallowCopy.
|
||||
func NewForConfigAndClient(c *rest.Config, httpClient *http.Client) (*Clientset, error) {
|
||||
configShallowCopy := *c
|
||||
if configShallowCopy.RateLimiter == nil && configShallowCopy.QPS > 0 {
|
||||
if configShallowCopy.Burst <= 0 {
|
||||
return nil, fmt.Errorf("burst is required to be greater than 0 when RateLimiter is not set and QPS is set to greater than 0")
|
||||
}
|
||||
configShallowCopy.RateLimiter = flowcontrol.NewTokenBucketRateLimiter(configShallowCopy.QPS, configShallowCopy.Burst)
|
||||
}
|
||||
|
||||
var cs Clientset
|
||||
var err error
|
||||
cs.monok8sV1alpha1, err = monok8sv1alpha1.NewForConfigAndClient(&configShallowCopy, httpClient)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
cs.DiscoveryClient, err = discovery.NewDiscoveryClientForConfigAndClient(&configShallowCopy, httpClient)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return &cs, nil
|
||||
}
|
||||
|
||||
// NewForConfigOrDie creates a new Clientset for the given config and
|
||||
// panics if there is an error in the config.
|
||||
func NewForConfigOrDie(c *rest.Config) *Clientset {
|
||||
cs, err := NewForConfig(c)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
return cs
|
||||
}
|
||||
|
||||
// New creates a new Clientset for the given RESTClient.
|
||||
func New(c rest.Interface) *Clientset {
|
||||
var cs Clientset
|
||||
cs.monok8sV1alpha1 = monok8sv1alpha1.New(c)
|
||||
|
||||
cs.DiscoveryClient = discovery.NewDiscoveryClient(c)
|
||||
return &cs
|
||||
}
|
||||
@@ -0,0 +1,91 @@
|
||||
/* MIT License */
|
||||
|
||||
// Code generated by client-gen. DO NOT EDIT.
|
||||
|
||||
package fake
|
||||
|
||||
import (
|
||||
clientset "example.com/monok8s/pkg/generated/clientset/versioned"
|
||||
monok8sv1alpha1 "example.com/monok8s/pkg/generated/clientset/versioned/typed/monok8s/v1alpha1"
|
||||
fakemonok8sv1alpha1 "example.com/monok8s/pkg/generated/clientset/versioned/typed/monok8s/v1alpha1/fake"
|
||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
"k8s.io/apimachinery/pkg/runtime"
|
||||
"k8s.io/apimachinery/pkg/watch"
|
||||
"k8s.io/client-go/discovery"
|
||||
fakediscovery "k8s.io/client-go/discovery/fake"
|
||||
"k8s.io/client-go/testing"
|
||||
)
|
||||
|
||||
// NewSimpleClientset returns a clientset that will respond with the provided objects.
|
||||
// It's backed by a very simple object tracker that processes creates, updates and deletions as-is,
|
||||
// without applying any field management, validations and/or defaults. It shouldn't be considered a replacement
|
||||
// for a real clientset and is mostly useful in simple unit tests.
|
||||
//
|
||||
// Deprecated: NewClientset replaces this with support for field management, which significantly improves
|
||||
// server side apply testing. NewClientset is only available when apply configurations are generated (e.g.
|
||||
// via --with-applyconfig).
|
||||
func NewSimpleClientset(objects ...runtime.Object) *Clientset {
|
||||
o := testing.NewObjectTracker(scheme, codecs.UniversalDecoder())
|
||||
for _, obj := range objects {
|
||||
if err := o.Add(obj); err != nil {
|
||||
panic(err)
|
||||
}
|
||||
}
|
||||
|
||||
cs := &Clientset{tracker: o}
|
||||
cs.discovery = &fakediscovery.FakeDiscovery{Fake: &cs.Fake}
|
||||
cs.AddReactor("*", "*", testing.ObjectReaction(o))
|
||||
cs.AddWatchReactor("*", func(action testing.Action) (handled bool, ret watch.Interface, err error) {
|
||||
var opts metav1.ListOptions
|
||||
if watchAction, ok := action.(testing.WatchActionImpl); ok {
|
||||
opts = watchAction.ListOptions
|
||||
}
|
||||
gvr := action.GetResource()
|
||||
ns := action.GetNamespace()
|
||||
watch, err := o.Watch(gvr, ns, opts)
|
||||
if err != nil {
|
||||
return false, nil, err
|
||||
}
|
||||
return true, watch, nil
|
||||
})
|
||||
|
||||
return cs
|
||||
}
|
||||
|
||||
// Clientset implements clientset.Interface. Meant to be embedded into a
|
||||
// struct to get a default implementation. This makes faking out just the method
|
||||
// you want to test easier.
|
||||
type Clientset struct {
|
||||
testing.Fake
|
||||
discovery *fakediscovery.FakeDiscovery
|
||||
tracker testing.ObjectTracker
|
||||
}
|
||||
|
||||
func (c *Clientset) Discovery() discovery.DiscoveryInterface {
|
||||
return c.discovery
|
||||
}
|
||||
|
||||
func (c *Clientset) Tracker() testing.ObjectTracker {
|
||||
return c.tracker
|
||||
}
|
||||
|
||||
// IsWatchListSemanticsSupported informs the reflector that this client
|
||||
// doesn't support WatchList semantics.
|
||||
//
|
||||
// This is a synthetic method whose sole purpose is to satisfy the optional
|
||||
// interface check performed by the reflector.
|
||||
// Returning true signals that WatchList can NOT be used.
|
||||
// No additional logic is implemented here.
|
||||
func (c *Clientset) IsWatchListSemanticsUnSupported() bool {
|
||||
return true
|
||||
}
|
||||
|
||||
var (
|
||||
_ clientset.Interface = &Clientset{}
|
||||
_ testing.FakeClient = &Clientset{}
|
||||
)
|
||||
|
||||
// Monok8sV1alpha1 retrieves the Monok8sV1alpha1Client
|
||||
func (c *Clientset) Monok8sV1alpha1() monok8sv1alpha1.Monok8sV1alpha1Interface {
|
||||
return &fakemonok8sv1alpha1.FakeMonok8sV1alpha1{Fake: &c.Fake}
|
||||
}
|
||||
6
clitools/pkg/generated/clientset/versioned/fake/doc.go
Normal file
6
clitools/pkg/generated/clientset/versioned/fake/doc.go
Normal file
@@ -0,0 +1,6 @@
|
||||
/* MIT License */
|
||||
|
||||
// Code generated by client-gen. DO NOT EDIT.
|
||||
|
||||
// This package has the automatically generated fake clientset.
|
||||
package fake
|
||||
42
clitools/pkg/generated/clientset/versioned/fake/register.go
Normal file
42
clitools/pkg/generated/clientset/versioned/fake/register.go
Normal file
@@ -0,0 +1,42 @@
|
||||
/* MIT License */
|
||||
|
||||
// Code generated by client-gen. DO NOT EDIT.
|
||||
|
||||
package fake
|
||||
|
||||
import (
|
||||
monok8sv1alpha1 "example.com/monok8s/pkg/apis/monok8s/v1alpha1"
|
||||
v1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
runtime "k8s.io/apimachinery/pkg/runtime"
|
||||
schema "k8s.io/apimachinery/pkg/runtime/schema"
|
||||
serializer "k8s.io/apimachinery/pkg/runtime/serializer"
|
||||
utilruntime "k8s.io/apimachinery/pkg/util/runtime"
|
||||
)
|
||||
|
||||
var scheme = runtime.NewScheme()
|
||||
var codecs = serializer.NewCodecFactory(scheme)
|
||||
|
||||
var localSchemeBuilder = runtime.SchemeBuilder{
|
||||
monok8sv1alpha1.AddToScheme,
|
||||
}
|
||||
|
||||
// AddToScheme adds all types of this clientset into the given scheme. This allows composition
|
||||
// of clientsets, like in:
|
||||
//
|
||||
// import (
|
||||
// "k8s.io/client-go/kubernetes"
|
||||
// clientsetscheme "k8s.io/client-go/kubernetes/scheme"
|
||||
// aggregatorclientsetscheme "k8s.io/kube-aggregator/pkg/client/clientset_generated/clientset/scheme"
|
||||
// )
|
||||
//
|
||||
// kclientset, _ := kubernetes.NewForConfig(c)
|
||||
// _ = aggregatorclientsetscheme.AddToScheme(clientsetscheme.Scheme)
|
||||
//
|
||||
// After this, RawExtensions in Kubernetes types will serialize kube-aggregator types
|
||||
// correctly.
|
||||
var AddToScheme = localSchemeBuilder.AddToScheme
|
||||
|
||||
func init() {
|
||||
v1.AddToGroupVersion(scheme, schema.GroupVersion{Version: "v1"})
|
||||
utilruntime.Must(AddToScheme(scheme))
|
||||
}
|
||||
6
clitools/pkg/generated/clientset/versioned/scheme/doc.go
Normal file
6
clitools/pkg/generated/clientset/versioned/scheme/doc.go
Normal file
@@ -0,0 +1,6 @@
|
||||
/* MIT License */
|
||||
|
||||
// Code generated by client-gen. DO NOT EDIT.
|
||||
|
||||
// This package contains the scheme of the automatically generated clientset.
|
||||
package scheme
|
||||
@@ -0,0 +1,42 @@
|
||||
/* MIT License */
|
||||
|
||||
// Code generated by client-gen. DO NOT EDIT.
|
||||
|
||||
package scheme
|
||||
|
||||
import (
|
||||
monok8sv1alpha1 "example.com/monok8s/pkg/apis/monok8s/v1alpha1"
|
||||
v1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
runtime "k8s.io/apimachinery/pkg/runtime"
|
||||
schema "k8s.io/apimachinery/pkg/runtime/schema"
|
||||
serializer "k8s.io/apimachinery/pkg/runtime/serializer"
|
||||
utilruntime "k8s.io/apimachinery/pkg/util/runtime"
|
||||
)
|
||||
|
||||
var Scheme = runtime.NewScheme()
|
||||
var Codecs = serializer.NewCodecFactory(Scheme)
|
||||
var ParameterCodec = runtime.NewParameterCodec(Scheme)
|
||||
var localSchemeBuilder = runtime.SchemeBuilder{
|
||||
monok8sv1alpha1.AddToScheme,
|
||||
}
|
||||
|
||||
// AddToScheme adds all types of this clientset into the given scheme. This allows composition
|
||||
// of clientsets, like in:
|
||||
//
|
||||
// import (
|
||||
// "k8s.io/client-go/kubernetes"
|
||||
// clientsetscheme "k8s.io/client-go/kubernetes/scheme"
|
||||
// aggregatorclientsetscheme "k8s.io/kube-aggregator/pkg/client/clientset_generated/clientset/scheme"
|
||||
// )
|
||||
//
|
||||
// kclientset, _ := kubernetes.NewForConfig(c)
|
||||
// _ = aggregatorclientsetscheme.AddToScheme(clientsetscheme.Scheme)
|
||||
//
|
||||
// After this, RawExtensions in Kubernetes types will serialize kube-aggregator types
|
||||
// correctly.
|
||||
var AddToScheme = localSchemeBuilder.AddToScheme
|
||||
|
||||
func init() {
|
||||
v1.AddToGroupVersion(Scheme, schema.GroupVersion{Version: "v1"})
|
||||
utilruntime.Must(AddToScheme(Scheme))
|
||||
}
|
||||
@@ -0,0 +1,6 @@
|
||||
/* MIT License */
|
||||
|
||||
// Code generated by client-gen. DO NOT EDIT.
|
||||
|
||||
// This package has the automatically generated typed clients.
|
||||
package v1alpha1
|
||||
@@ -0,0 +1,6 @@
|
||||
/* MIT License */
|
||||
|
||||
// Code generated by client-gen. DO NOT EDIT.
|
||||
|
||||
// Package fake has the automatically generated clients.
|
||||
package fake
|
||||
@@ -0,0 +1,30 @@
|
||||
/* MIT License */
|
||||
|
||||
// Code generated by client-gen. DO NOT EDIT.
|
||||
|
||||
package fake
|
||||
|
||||
import (
|
||||
v1alpha1 "example.com/monok8s/pkg/generated/clientset/versioned/typed/monok8s/v1alpha1"
|
||||
rest "k8s.io/client-go/rest"
|
||||
testing "k8s.io/client-go/testing"
|
||||
)
|
||||
|
||||
type FakeMonok8sV1alpha1 struct {
|
||||
*testing.Fake
|
||||
}
|
||||
|
||||
func (c *FakeMonok8sV1alpha1) OSUpgrades(namespace string) v1alpha1.OSUpgradeInterface {
|
||||
return newFakeOSUpgrades(c, namespace)
|
||||
}
|
||||
|
||||
func (c *FakeMonok8sV1alpha1) OSUpgradeProgresses(namespace string) v1alpha1.OSUpgradeProgressInterface {
|
||||
return newFakeOSUpgradeProgresses(c, namespace)
|
||||
}
|
||||
|
||||
// RESTClient returns a RESTClient that is used to communicate
|
||||
// with API server by this client implementation.
|
||||
func (c *FakeMonok8sV1alpha1) RESTClient() rest.Interface {
|
||||
var ret *rest.RESTClient
|
||||
return ret
|
||||
}
|
||||
@@ -0,0 +1,36 @@
|
||||
/* MIT License */
|
||||
|
||||
// Code generated by client-gen. DO NOT EDIT.
|
||||
|
||||
package fake
|
||||
|
||||
import (
|
||||
v1alpha1 "example.com/monok8s/pkg/apis/monok8s/v1alpha1"
|
||||
monok8sv1alpha1 "example.com/monok8s/pkg/generated/clientset/versioned/typed/monok8s/v1alpha1"
|
||||
gentype "k8s.io/client-go/gentype"
|
||||
)
|
||||
|
||||
// fakeOSUpgrades implements OSUpgradeInterface
|
||||
type fakeOSUpgrades struct {
|
||||
*gentype.FakeClientWithList[*v1alpha1.OSUpgrade, *v1alpha1.OSUpgradeList]
|
||||
Fake *FakeMonok8sV1alpha1
|
||||
}
|
||||
|
||||
func newFakeOSUpgrades(fake *FakeMonok8sV1alpha1, namespace string) monok8sv1alpha1.OSUpgradeInterface {
|
||||
return &fakeOSUpgrades{
|
||||
gentype.NewFakeClientWithList[*v1alpha1.OSUpgrade, *v1alpha1.OSUpgradeList](
|
||||
fake.Fake,
|
||||
namespace,
|
||||
v1alpha1.SchemeGroupVersion.WithResource("osupgrades"),
|
||||
v1alpha1.SchemeGroupVersion.WithKind("OSUpgrade"),
|
||||
func() *v1alpha1.OSUpgrade { return &v1alpha1.OSUpgrade{} },
|
||||
func() *v1alpha1.OSUpgradeList { return &v1alpha1.OSUpgradeList{} },
|
||||
func(dst, src *v1alpha1.OSUpgradeList) { dst.ListMeta = src.ListMeta },
|
||||
func(list *v1alpha1.OSUpgradeList) []*v1alpha1.OSUpgrade { return gentype.ToPointerSlice(list.Items) },
|
||||
func(list *v1alpha1.OSUpgradeList, items []*v1alpha1.OSUpgrade) {
|
||||
list.Items = gentype.FromPointerSlice(items)
|
||||
},
|
||||
),
|
||||
fake,
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,38 @@
|
||||
/* MIT License */
|
||||
|
||||
// Code generated by client-gen. DO NOT EDIT.
|
||||
|
||||
package fake
|
||||
|
||||
import (
|
||||
v1alpha1 "example.com/monok8s/pkg/apis/monok8s/v1alpha1"
|
||||
monok8sv1alpha1 "example.com/monok8s/pkg/generated/clientset/versioned/typed/monok8s/v1alpha1"
|
||||
gentype "k8s.io/client-go/gentype"
|
||||
)
|
||||
|
||||
// fakeOSUpgradeProgresses implements OSUpgradeProgressInterface
|
||||
type fakeOSUpgradeProgresses struct {
|
||||
*gentype.FakeClientWithList[*v1alpha1.OSUpgradeProgress, *v1alpha1.OSUpgradeProgressList]
|
||||
Fake *FakeMonok8sV1alpha1
|
||||
}
|
||||
|
||||
func newFakeOSUpgradeProgresses(fake *FakeMonok8sV1alpha1, namespace string) monok8sv1alpha1.OSUpgradeProgressInterface {
|
||||
return &fakeOSUpgradeProgresses{
|
||||
gentype.NewFakeClientWithList[*v1alpha1.OSUpgradeProgress, *v1alpha1.OSUpgradeProgressList](
|
||||
fake.Fake,
|
||||
namespace,
|
||||
v1alpha1.SchemeGroupVersion.WithResource("osupgradeprogresses"),
|
||||
v1alpha1.SchemeGroupVersion.WithKind("OSUpgradeProgress"),
|
||||
func() *v1alpha1.OSUpgradeProgress { return &v1alpha1.OSUpgradeProgress{} },
|
||||
func() *v1alpha1.OSUpgradeProgressList { return &v1alpha1.OSUpgradeProgressList{} },
|
||||
func(dst, src *v1alpha1.OSUpgradeProgressList) { dst.ListMeta = src.ListMeta },
|
||||
func(list *v1alpha1.OSUpgradeProgressList) []*v1alpha1.OSUpgradeProgress {
|
||||
return gentype.ToPointerSlice(list.Items)
|
||||
},
|
||||
func(list *v1alpha1.OSUpgradeProgressList, items []*v1alpha1.OSUpgradeProgress) {
|
||||
list.Items = gentype.FromPointerSlice(items)
|
||||
},
|
||||
),
|
||||
fake,
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,9 @@
|
||||
/* MIT License */
|
||||
|
||||
// Code generated by client-gen. DO NOT EDIT.
|
||||
|
||||
package v1alpha1
|
||||
|
||||
type OSUpgradeExpansion interface{}
|
||||
|
||||
type OSUpgradeProgressExpansion interface{}
|
||||
@@ -0,0 +1,92 @@
|
||||
/* MIT License */
|
||||
|
||||
// Code generated by client-gen. DO NOT EDIT.
|
||||
|
||||
package v1alpha1
|
||||
|
||||
import (
|
||||
http "net/http"
|
||||
|
||||
monok8sv1alpha1 "example.com/monok8s/pkg/apis/monok8s/v1alpha1"
|
||||
scheme "example.com/monok8s/pkg/generated/clientset/versioned/scheme"
|
||||
rest "k8s.io/client-go/rest"
|
||||
)
|
||||
|
||||
type Monok8sV1alpha1Interface interface {
|
||||
RESTClient() rest.Interface
|
||||
OSUpgradesGetter
|
||||
OSUpgradeProgressesGetter
|
||||
}
|
||||
|
||||
// Monok8sV1alpha1Client is used to interact with features provided by the monok8s group.
|
||||
type Monok8sV1alpha1Client struct {
|
||||
restClient rest.Interface
|
||||
}
|
||||
|
||||
func (c *Monok8sV1alpha1Client) OSUpgrades(namespace string) OSUpgradeInterface {
|
||||
return newOSUpgrades(c, namespace)
|
||||
}
|
||||
|
||||
func (c *Monok8sV1alpha1Client) OSUpgradeProgresses(namespace string) OSUpgradeProgressInterface {
|
||||
return newOSUpgradeProgresses(c, namespace)
|
||||
}
|
||||
|
||||
// NewForConfig creates a new Monok8sV1alpha1Client for the given config.
|
||||
// NewForConfig is equivalent to NewForConfigAndClient(c, httpClient),
|
||||
// where httpClient was generated with rest.HTTPClientFor(c).
|
||||
func NewForConfig(c *rest.Config) (*Monok8sV1alpha1Client, error) {
|
||||
config := *c
|
||||
setConfigDefaults(&config)
|
||||
httpClient, err := rest.HTTPClientFor(&config)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return NewForConfigAndClient(&config, httpClient)
|
||||
}
|
||||
|
||||
// NewForConfigAndClient creates a new Monok8sV1alpha1Client for the given config and http client.
|
||||
// Note the http client provided takes precedence over the configured transport values.
|
||||
func NewForConfigAndClient(c *rest.Config, h *http.Client) (*Monok8sV1alpha1Client, error) {
|
||||
config := *c
|
||||
setConfigDefaults(&config)
|
||||
client, err := rest.RESTClientForConfigAndClient(&config, h)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return &Monok8sV1alpha1Client{client}, nil
|
||||
}
|
||||
|
||||
// NewForConfigOrDie creates a new Monok8sV1alpha1Client for the given config and
|
||||
// panics if there is an error in the config.
|
||||
func NewForConfigOrDie(c *rest.Config) *Monok8sV1alpha1Client {
|
||||
client, err := NewForConfig(c)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
return client
|
||||
}
|
||||
|
||||
// New creates a new Monok8sV1alpha1Client for the given RESTClient.
|
||||
func New(c rest.Interface) *Monok8sV1alpha1Client {
|
||||
return &Monok8sV1alpha1Client{c}
|
||||
}
|
||||
|
||||
func setConfigDefaults(config *rest.Config) {
|
||||
gv := monok8sv1alpha1.SchemeGroupVersion
|
||||
config.GroupVersion = &gv
|
||||
config.APIPath = "/apis"
|
||||
config.NegotiatedSerializer = rest.CodecFactoryForGeneratedClient(scheme.Scheme, scheme.Codecs).WithoutConversion()
|
||||
|
||||
if config.UserAgent == "" {
|
||||
config.UserAgent = rest.DefaultKubernetesUserAgent()
|
||||
}
|
||||
}
|
||||
|
||||
// RESTClient returns a RESTClient that is used to communicate
|
||||
// with API server by this client implementation.
|
||||
func (c *Monok8sV1alpha1Client) RESTClient() rest.Interface {
|
||||
if c == nil {
|
||||
return nil
|
||||
}
|
||||
return c.restClient
|
||||
}
|
||||
@@ -0,0 +1,56 @@
|
||||
/* MIT License */
|
||||
|
||||
// Code generated by client-gen. DO NOT EDIT.
|
||||
|
||||
package v1alpha1
|
||||
|
||||
import (
|
||||
context "context"
|
||||
|
||||
monok8sv1alpha1 "example.com/monok8s/pkg/apis/monok8s/v1alpha1"
|
||||
scheme "example.com/monok8s/pkg/generated/clientset/versioned/scheme"
|
||||
v1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
types "k8s.io/apimachinery/pkg/types"
|
||||
watch "k8s.io/apimachinery/pkg/watch"
|
||||
gentype "k8s.io/client-go/gentype"
|
||||
)
|
||||
|
||||
// OSUpgradesGetter has a method to return a OSUpgradeInterface.
|
||||
// A group's client should implement this interface.
|
||||
type OSUpgradesGetter interface {
|
||||
OSUpgrades(namespace string) OSUpgradeInterface
|
||||
}
|
||||
|
||||
// OSUpgradeInterface has methods to work with OSUpgrade resources.
|
||||
type OSUpgradeInterface interface {
|
||||
Create(ctx context.Context, oSUpgrade *monok8sv1alpha1.OSUpgrade, opts v1.CreateOptions) (*monok8sv1alpha1.OSUpgrade, error)
|
||||
Update(ctx context.Context, oSUpgrade *monok8sv1alpha1.OSUpgrade, opts v1.UpdateOptions) (*monok8sv1alpha1.OSUpgrade, error)
|
||||
// Add a +genclient:noStatus comment above the type to avoid generating UpdateStatus().
|
||||
UpdateStatus(ctx context.Context, oSUpgrade *monok8sv1alpha1.OSUpgrade, opts v1.UpdateOptions) (*monok8sv1alpha1.OSUpgrade, error)
|
||||
Delete(ctx context.Context, name string, opts v1.DeleteOptions) error
|
||||
DeleteCollection(ctx context.Context, opts v1.DeleteOptions, listOpts v1.ListOptions) error
|
||||
Get(ctx context.Context, name string, opts v1.GetOptions) (*monok8sv1alpha1.OSUpgrade, error)
|
||||
List(ctx context.Context, opts v1.ListOptions) (*monok8sv1alpha1.OSUpgradeList, error)
|
||||
Watch(ctx context.Context, opts v1.ListOptions) (watch.Interface, error)
|
||||
Patch(ctx context.Context, name string, pt types.PatchType, data []byte, opts v1.PatchOptions, subresources ...string) (result *monok8sv1alpha1.OSUpgrade, err error)
|
||||
OSUpgradeExpansion
|
||||
}
|
||||
|
||||
// oSUpgrades implements OSUpgradeInterface
|
||||
type oSUpgrades struct {
|
||||
*gentype.ClientWithList[*monok8sv1alpha1.OSUpgrade, *monok8sv1alpha1.OSUpgradeList]
|
||||
}
|
||||
|
||||
// newOSUpgrades returns a OSUpgrades
|
||||
func newOSUpgrades(c *Monok8sV1alpha1Client, namespace string) *oSUpgrades {
|
||||
return &oSUpgrades{
|
||||
gentype.NewClientWithList[*monok8sv1alpha1.OSUpgrade, *monok8sv1alpha1.OSUpgradeList](
|
||||
"osupgrades",
|
||||
c.RESTClient(),
|
||||
scheme.ParameterCodec,
|
||||
namespace,
|
||||
func() *monok8sv1alpha1.OSUpgrade { return &monok8sv1alpha1.OSUpgrade{} },
|
||||
func() *monok8sv1alpha1.OSUpgradeList { return &monok8sv1alpha1.OSUpgradeList{} },
|
||||
),
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,56 @@
|
||||
/* MIT License */
|
||||
|
||||
// Code generated by client-gen. DO NOT EDIT.
|
||||
|
||||
package v1alpha1
|
||||
|
||||
import (
|
||||
context "context"
|
||||
|
||||
monok8sv1alpha1 "example.com/monok8s/pkg/apis/monok8s/v1alpha1"
|
||||
scheme "example.com/monok8s/pkg/generated/clientset/versioned/scheme"
|
||||
v1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
types "k8s.io/apimachinery/pkg/types"
|
||||
watch "k8s.io/apimachinery/pkg/watch"
|
||||
gentype "k8s.io/client-go/gentype"
|
||||
)
|
||||
|
||||
// OSUpgradeProgressesGetter has a method to return a OSUpgradeProgressInterface.
|
||||
// A group's client should implement this interface.
|
||||
type OSUpgradeProgressesGetter interface {
|
||||
OSUpgradeProgresses(namespace string) OSUpgradeProgressInterface
|
||||
}
|
||||
|
||||
// OSUpgradeProgressInterface has methods to work with OSUpgradeProgress resources.
|
||||
type OSUpgradeProgressInterface interface {
|
||||
Create(ctx context.Context, oSUpgradeProgress *monok8sv1alpha1.OSUpgradeProgress, opts v1.CreateOptions) (*monok8sv1alpha1.OSUpgradeProgress, error)
|
||||
Update(ctx context.Context, oSUpgradeProgress *monok8sv1alpha1.OSUpgradeProgress, opts v1.UpdateOptions) (*monok8sv1alpha1.OSUpgradeProgress, error)
|
||||
// Add a +genclient:noStatus comment above the type to avoid generating UpdateStatus().
|
||||
UpdateStatus(ctx context.Context, oSUpgradeProgress *monok8sv1alpha1.OSUpgradeProgress, opts v1.UpdateOptions) (*monok8sv1alpha1.OSUpgradeProgress, error)
|
||||
Delete(ctx context.Context, name string, opts v1.DeleteOptions) error
|
||||
DeleteCollection(ctx context.Context, opts v1.DeleteOptions, listOpts v1.ListOptions) error
|
||||
Get(ctx context.Context, name string, opts v1.GetOptions) (*monok8sv1alpha1.OSUpgradeProgress, error)
|
||||
List(ctx context.Context, opts v1.ListOptions) (*monok8sv1alpha1.OSUpgradeProgressList, error)
|
||||
Watch(ctx context.Context, opts v1.ListOptions) (watch.Interface, error)
|
||||
Patch(ctx context.Context, name string, pt types.PatchType, data []byte, opts v1.PatchOptions, subresources ...string) (result *monok8sv1alpha1.OSUpgradeProgress, err error)
|
||||
OSUpgradeProgressExpansion
|
||||
}
|
||||
|
||||
// oSUpgradeProgresses implements OSUpgradeProgressInterface
|
||||
type oSUpgradeProgresses struct {
|
||||
*gentype.ClientWithList[*monok8sv1alpha1.OSUpgradeProgress, *monok8sv1alpha1.OSUpgradeProgressList]
|
||||
}
|
||||
|
||||
// newOSUpgradeProgresses returns a OSUpgradeProgresses
|
||||
func newOSUpgradeProgresses(c *Monok8sV1alpha1Client, namespace string) *oSUpgradeProgresses {
|
||||
return &oSUpgradeProgresses{
|
||||
gentype.NewClientWithList[*monok8sv1alpha1.OSUpgradeProgress, *monok8sv1alpha1.OSUpgradeProgressList](
|
||||
"osupgradeprogresses",
|
||||
c.RESTClient(),
|
||||
scheme.ParameterCodec,
|
||||
namespace,
|
||||
func() *monok8sv1alpha1.OSUpgradeProgress { return &monok8sv1alpha1.OSUpgradeProgress{} },
|
||||
func() *monok8sv1alpha1.OSUpgradeProgressList { return &monok8sv1alpha1.OSUpgradeProgressList{} },
|
||||
),
|
||||
}
|
||||
}
|
||||
249
clitools/pkg/generated/informers/externalversions/factory.go
Normal file
249
clitools/pkg/generated/informers/externalversions/factory.go
Normal file
@@ -0,0 +1,249 @@
|
||||
/* MIT License */
|
||||
|
||||
// Code generated by informer-gen. DO NOT EDIT.
|
||||
|
||||
package externalversions
|
||||
|
||||
import (
|
||||
reflect "reflect"
|
||||
sync "sync"
|
||||
time "time"
|
||||
|
||||
versioned "example.com/monok8s/pkg/generated/clientset/versioned"
|
||||
internalinterfaces "example.com/monok8s/pkg/generated/informers/externalversions/internalinterfaces"
|
||||
monok8s "example.com/monok8s/pkg/generated/informers/externalversions/monok8s"
|
||||
v1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
runtime "k8s.io/apimachinery/pkg/runtime"
|
||||
schema "k8s.io/apimachinery/pkg/runtime/schema"
|
||||
cache "k8s.io/client-go/tools/cache"
|
||||
)
|
||||
|
||||
// SharedInformerOption defines the functional option type for SharedInformerFactory.
|
||||
type SharedInformerOption func(*sharedInformerFactory) *sharedInformerFactory
|
||||
|
||||
type sharedInformerFactory struct {
|
||||
client versioned.Interface
|
||||
namespace string
|
||||
tweakListOptions internalinterfaces.TweakListOptionsFunc
|
||||
lock sync.Mutex
|
||||
defaultResync time.Duration
|
||||
customResync map[reflect.Type]time.Duration
|
||||
transform cache.TransformFunc
|
||||
|
||||
informers map[reflect.Type]cache.SharedIndexInformer
|
||||
// startedInformers is used for tracking which informers have been started.
|
||||
// This allows Start() to be called multiple times safely.
|
||||
startedInformers map[reflect.Type]bool
|
||||
// wg tracks how many goroutines were started.
|
||||
wg sync.WaitGroup
|
||||
// shuttingDown is true when Shutdown has been called. It may still be running
|
||||
// because it needs to wait for goroutines.
|
||||
shuttingDown bool
|
||||
}
|
||||
|
||||
// WithCustomResyncConfig sets a custom resync period for the specified informer types.
|
||||
func WithCustomResyncConfig(resyncConfig map[v1.Object]time.Duration) SharedInformerOption {
|
||||
return func(factory *sharedInformerFactory) *sharedInformerFactory {
|
||||
for k, v := range resyncConfig {
|
||||
factory.customResync[reflect.TypeOf(k)] = v
|
||||
}
|
||||
return factory
|
||||
}
|
||||
}
|
||||
|
||||
// WithTweakListOptions sets a custom filter on all listers of the configured SharedInformerFactory.
|
||||
func WithTweakListOptions(tweakListOptions internalinterfaces.TweakListOptionsFunc) SharedInformerOption {
|
||||
return func(factory *sharedInformerFactory) *sharedInformerFactory {
|
||||
factory.tweakListOptions = tweakListOptions
|
||||
return factory
|
||||
}
|
||||
}
|
||||
|
||||
// WithNamespace limits the SharedInformerFactory to the specified namespace.
|
||||
func WithNamespace(namespace string) SharedInformerOption {
|
||||
return func(factory *sharedInformerFactory) *sharedInformerFactory {
|
||||
factory.namespace = namespace
|
||||
return factory
|
||||
}
|
||||
}
|
||||
|
||||
// WithTransform sets a transform on all informers.
|
||||
func WithTransform(transform cache.TransformFunc) SharedInformerOption {
|
||||
return func(factory *sharedInformerFactory) *sharedInformerFactory {
|
||||
factory.transform = transform
|
||||
return factory
|
||||
}
|
||||
}
|
||||
|
||||
// NewSharedInformerFactory constructs a new instance of sharedInformerFactory for all namespaces.
|
||||
func NewSharedInformerFactory(client versioned.Interface, defaultResync time.Duration) SharedInformerFactory {
|
||||
return NewSharedInformerFactoryWithOptions(client, defaultResync)
|
||||
}
|
||||
|
||||
// NewFilteredSharedInformerFactory constructs a new instance of sharedInformerFactory.
|
||||
// Listers obtained via this SharedInformerFactory will be subject to the same filters
|
||||
// as specified here.
|
||||
//
|
||||
// Deprecated: Please use NewSharedInformerFactoryWithOptions instead
|
||||
func NewFilteredSharedInformerFactory(client versioned.Interface, defaultResync time.Duration, namespace string, tweakListOptions internalinterfaces.TweakListOptionsFunc) SharedInformerFactory {
|
||||
return NewSharedInformerFactoryWithOptions(client, defaultResync, WithNamespace(namespace), WithTweakListOptions(tweakListOptions))
|
||||
}
|
||||
|
||||
// NewSharedInformerFactoryWithOptions constructs a new instance of a SharedInformerFactory with additional options.
|
||||
func NewSharedInformerFactoryWithOptions(client versioned.Interface, defaultResync time.Duration, options ...SharedInformerOption) SharedInformerFactory {
|
||||
factory := &sharedInformerFactory{
|
||||
client: client,
|
||||
namespace: v1.NamespaceAll,
|
||||
defaultResync: defaultResync,
|
||||
informers: make(map[reflect.Type]cache.SharedIndexInformer),
|
||||
startedInformers: make(map[reflect.Type]bool),
|
||||
customResync: make(map[reflect.Type]time.Duration),
|
||||
}
|
||||
|
||||
// Apply all options
|
||||
for _, opt := range options {
|
||||
factory = opt(factory)
|
||||
}
|
||||
|
||||
return factory
|
||||
}
|
||||
|
||||
func (f *sharedInformerFactory) Start(stopCh <-chan struct{}) {
|
||||
f.lock.Lock()
|
||||
defer f.lock.Unlock()
|
||||
|
||||
if f.shuttingDown {
|
||||
return
|
||||
}
|
||||
|
||||
for informerType, informer := range f.informers {
|
||||
if !f.startedInformers[informerType] {
|
||||
f.wg.Add(1)
|
||||
// We need a new variable in each loop iteration,
|
||||
// otherwise the goroutine would use the loop variable
|
||||
// and that keeps changing.
|
||||
informer := informer
|
||||
go func() {
|
||||
defer f.wg.Done()
|
||||
informer.Run(stopCh)
|
||||
}()
|
||||
f.startedInformers[informerType] = true
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func (f *sharedInformerFactory) Shutdown() {
|
||||
f.lock.Lock()
|
||||
f.shuttingDown = true
|
||||
f.lock.Unlock()
|
||||
|
||||
// Will return immediately if there is nothing to wait for.
|
||||
f.wg.Wait()
|
||||
}
|
||||
|
||||
func (f *sharedInformerFactory) WaitForCacheSync(stopCh <-chan struct{}) map[reflect.Type]bool {
|
||||
informers := func() map[reflect.Type]cache.SharedIndexInformer {
|
||||
f.lock.Lock()
|
||||
defer f.lock.Unlock()
|
||||
|
||||
informers := map[reflect.Type]cache.SharedIndexInformer{}
|
||||
for informerType, informer := range f.informers {
|
||||
if f.startedInformers[informerType] {
|
||||
informers[informerType] = informer
|
||||
}
|
||||
}
|
||||
return informers
|
||||
}()
|
||||
|
||||
res := map[reflect.Type]bool{}
|
||||
for informType, informer := range informers {
|
||||
res[informType] = cache.WaitForCacheSync(stopCh, informer.HasSynced)
|
||||
}
|
||||
return res
|
||||
}
|
||||
|
||||
// InformerFor returns the SharedIndexInformer for obj using an internal
|
||||
// client.
|
||||
func (f *sharedInformerFactory) InformerFor(obj runtime.Object, newFunc internalinterfaces.NewInformerFunc) cache.SharedIndexInformer {
|
||||
f.lock.Lock()
|
||||
defer f.lock.Unlock()
|
||||
|
||||
informerType := reflect.TypeOf(obj)
|
||||
informer, exists := f.informers[informerType]
|
||||
if exists {
|
||||
return informer
|
||||
}
|
||||
|
||||
resyncPeriod, exists := f.customResync[informerType]
|
||||
if !exists {
|
||||
resyncPeriod = f.defaultResync
|
||||
}
|
||||
|
||||
informer = newFunc(f.client, resyncPeriod)
|
||||
informer.SetTransform(f.transform)
|
||||
f.informers[informerType] = informer
|
||||
|
||||
return informer
|
||||
}
|
||||
|
||||
// SharedInformerFactory provides shared informers for resources in all known
|
||||
// API group versions.
|
||||
//
|
||||
// It is typically used like this:
|
||||
//
|
||||
// ctx, cancel := context.WithCancel(context.Background())
|
||||
// defer cancel()
|
||||
// factory := NewSharedInformerFactory(client, resyncPeriod)
|
||||
// defer factory.WaitForStop() // Returns immediately if nothing was started.
|
||||
// genericInformer := factory.ForResource(resource)
|
||||
// typedInformer := factory.SomeAPIGroup().V1().SomeType()
|
||||
// factory.Start(ctx.Done()) // Start processing these informers.
|
||||
// synced := factory.WaitForCacheSync(ctx.Done())
|
||||
// for v, ok := range synced {
|
||||
// if !ok {
|
||||
// fmt.Fprintf(os.Stderr, "caches failed to sync: %v", v)
|
||||
// return
|
||||
// }
|
||||
// }
|
||||
//
|
||||
// // Creating informers can also be created after Start, but then
|
||||
// // Start must be called again:
|
||||
// anotherGenericInformer := factory.ForResource(resource)
|
||||
// factory.Start(ctx.Done())
|
||||
type SharedInformerFactory interface {
|
||||
internalinterfaces.SharedInformerFactory
|
||||
|
||||
// Start initializes all requested informers. They are handled in goroutines
|
||||
// which run until the stop channel gets closed.
|
||||
// Warning: Start does not block. When run in a go-routine, it will race with a later WaitForCacheSync.
|
||||
Start(stopCh <-chan struct{})
|
||||
|
||||
// Shutdown marks a factory as shutting down. At that point no new
|
||||
// informers can be started anymore and Start will return without
|
||||
// doing anything.
|
||||
//
|
||||
// In addition, Shutdown blocks until all goroutines have terminated. For that
|
||||
// to happen, the close channel(s) that they were started with must be closed,
|
||||
// either before Shutdown gets called or while it is waiting.
|
||||
//
|
||||
// Shutdown may be called multiple times, even concurrently. All such calls will
|
||||
// block until all goroutines have terminated.
|
||||
Shutdown()
|
||||
|
||||
// WaitForCacheSync blocks until all started informers' caches were synced
|
||||
// or the stop channel gets closed.
|
||||
WaitForCacheSync(stopCh <-chan struct{}) map[reflect.Type]bool
|
||||
|
||||
// ForResource gives generic access to a shared informer of the matching type.
|
||||
ForResource(resource schema.GroupVersionResource) (GenericInformer, error)
|
||||
|
||||
// InformerFor returns the SharedIndexInformer for obj using an internal
|
||||
// client.
|
||||
InformerFor(obj runtime.Object, newFunc internalinterfaces.NewInformerFunc) cache.SharedIndexInformer
|
||||
|
||||
Monok8s() monok8s.Interface
|
||||
}
|
||||
|
||||
func (f *sharedInformerFactory) Monok8s() monok8s.Interface {
|
||||
return monok8s.New(f, f.namespace, f.tweakListOptions)
|
||||
}
|
||||
50
clitools/pkg/generated/informers/externalversions/generic.go
Normal file
50
clitools/pkg/generated/informers/externalversions/generic.go
Normal file
@@ -0,0 +1,50 @@
|
||||
/* MIT License */
|
||||
|
||||
// Code generated by informer-gen. DO NOT EDIT.
|
||||
|
||||
package externalversions
|
||||
|
||||
import (
|
||||
fmt "fmt"
|
||||
|
||||
v1alpha1 "example.com/monok8s/pkg/apis/monok8s/v1alpha1"
|
||||
schema "k8s.io/apimachinery/pkg/runtime/schema"
|
||||
cache "k8s.io/client-go/tools/cache"
|
||||
)
|
||||
|
||||
// GenericInformer is type of SharedIndexInformer which will locate and delegate to other
|
||||
// sharedInformers based on type
|
||||
type GenericInformer interface {
|
||||
Informer() cache.SharedIndexInformer
|
||||
Lister() cache.GenericLister
|
||||
}
|
||||
|
||||
type genericInformer struct {
|
||||
informer cache.SharedIndexInformer
|
||||
resource schema.GroupResource
|
||||
}
|
||||
|
||||
// Informer returns the SharedIndexInformer.
|
||||
func (f *genericInformer) Informer() cache.SharedIndexInformer {
|
||||
return f.informer
|
||||
}
|
||||
|
||||
// Lister returns the GenericLister.
|
||||
func (f *genericInformer) Lister() cache.GenericLister {
|
||||
return cache.NewGenericLister(f.Informer().GetIndexer(), f.resource)
|
||||
}
|
||||
|
||||
// ForResource gives generic access to a shared informer of the matching type
|
||||
// TODO extend this to unknown resources with a client pool
|
||||
func (f *sharedInformerFactory) ForResource(resource schema.GroupVersionResource) (GenericInformer, error) {
|
||||
switch resource {
|
||||
// Group=monok8s, Version=v1alpha1
|
||||
case v1alpha1.SchemeGroupVersion.WithResource("osupgrades"):
|
||||
return &genericInformer{resource: resource.GroupResource(), informer: f.Monok8s().V1alpha1().OSUpgrades().Informer()}, nil
|
||||
case v1alpha1.SchemeGroupVersion.WithResource("osupgradeprogresses"):
|
||||
return &genericInformer{resource: resource.GroupResource(), informer: f.Monok8s().V1alpha1().OSUpgradeProgresses().Informer()}, nil
|
||||
|
||||
}
|
||||
|
||||
return nil, fmt.Errorf("no informer found for %v", resource)
|
||||
}
|
||||
@@ -0,0 +1,26 @@
|
||||
/* MIT License */
|
||||
|
||||
// Code generated by informer-gen. DO NOT EDIT.
|
||||
|
||||
package internalinterfaces
|
||||
|
||||
import (
|
||||
time "time"
|
||||
|
||||
versioned "example.com/monok8s/pkg/generated/clientset/versioned"
|
||||
v1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
runtime "k8s.io/apimachinery/pkg/runtime"
|
||||
cache "k8s.io/client-go/tools/cache"
|
||||
)
|
||||
|
||||
// NewInformerFunc takes versioned.Interface and time.Duration to return a SharedIndexInformer.
|
||||
type NewInformerFunc func(versioned.Interface, time.Duration) cache.SharedIndexInformer
|
||||
|
||||
// SharedInformerFactory a small interface to allow for adding an informer without an import cycle
|
||||
type SharedInformerFactory interface {
|
||||
Start(stopCh <-chan struct{})
|
||||
InformerFor(obj runtime.Object, newFunc NewInformerFunc) cache.SharedIndexInformer
|
||||
}
|
||||
|
||||
// TweakListOptionsFunc is a function that transforms a v1.ListOptions.
|
||||
type TweakListOptionsFunc func(*v1.ListOptions)
|
||||
@@ -0,0 +1,32 @@
|
||||
/* MIT License */
|
||||
|
||||
// Code generated by informer-gen. DO NOT EDIT.
|
||||
|
||||
package monok8s
|
||||
|
||||
import (
|
||||
internalinterfaces "example.com/monok8s/pkg/generated/informers/externalversions/internalinterfaces"
|
||||
v1alpha1 "example.com/monok8s/pkg/generated/informers/externalversions/monok8s/v1alpha1"
|
||||
)
|
||||
|
||||
// Interface provides access to each of this group's versions.
|
||||
type Interface interface {
|
||||
// V1alpha1 provides access to shared informers for resources in V1alpha1.
|
||||
V1alpha1() v1alpha1.Interface
|
||||
}
|
||||
|
||||
type group struct {
|
||||
factory internalinterfaces.SharedInformerFactory
|
||||
namespace string
|
||||
tweakListOptions internalinterfaces.TweakListOptionsFunc
|
||||
}
|
||||
|
||||
// New returns a new Interface.
|
||||
func New(f internalinterfaces.SharedInformerFactory, namespace string, tweakListOptions internalinterfaces.TweakListOptionsFunc) Interface {
|
||||
return &group{factory: f, namespace: namespace, tweakListOptions: tweakListOptions}
|
||||
}
|
||||
|
||||
// V1alpha1 returns a new v1alpha1.Interface.
|
||||
func (g *group) V1alpha1() v1alpha1.Interface {
|
||||
return v1alpha1.New(g.factory, g.namespace, g.tweakListOptions)
|
||||
}
|
||||
@@ -0,0 +1,38 @@
|
||||
/* MIT License */
|
||||
|
||||
// Code generated by informer-gen. DO NOT EDIT.
|
||||
|
||||
package v1alpha1
|
||||
|
||||
import (
|
||||
internalinterfaces "example.com/monok8s/pkg/generated/informers/externalversions/internalinterfaces"
|
||||
)
|
||||
|
||||
// Interface provides access to all the informers in this group version.
|
||||
type Interface interface {
|
||||
// OSUpgrades returns a OSUpgradeInformer.
|
||||
OSUpgrades() OSUpgradeInformer
|
||||
// OSUpgradeProgresses returns a OSUpgradeProgressInformer.
|
||||
OSUpgradeProgresses() OSUpgradeProgressInformer
|
||||
}
|
||||
|
||||
type version struct {
|
||||
factory internalinterfaces.SharedInformerFactory
|
||||
namespace string
|
||||
tweakListOptions internalinterfaces.TweakListOptionsFunc
|
||||
}
|
||||
|
||||
// New returns a new Interface.
|
||||
func New(f internalinterfaces.SharedInformerFactory, namespace string, tweakListOptions internalinterfaces.TweakListOptionsFunc) Interface {
|
||||
return &version{factory: f, namespace: namespace, tweakListOptions: tweakListOptions}
|
||||
}
|
||||
|
||||
// OSUpgrades returns a OSUpgradeInformer.
|
||||
func (v *version) OSUpgrades() OSUpgradeInformer {
|
||||
return &oSUpgradeInformer{factory: v.factory, namespace: v.namespace, tweakListOptions: v.tweakListOptions}
|
||||
}
|
||||
|
||||
// OSUpgradeProgresses returns a OSUpgradeProgressInformer.
|
||||
func (v *version) OSUpgradeProgresses() OSUpgradeProgressInformer {
|
||||
return &oSUpgradeProgressInformer{factory: v.factory, namespace: v.namespace, tweakListOptions: v.tweakListOptions}
|
||||
}
|
||||
@@ -0,0 +1,88 @@
|
||||
/* MIT License */
|
||||
|
||||
// Code generated by informer-gen. DO NOT EDIT.
|
||||
|
||||
package v1alpha1
|
||||
|
||||
import (
|
||||
context "context"
|
||||
time "time"
|
||||
|
||||
apismonok8sv1alpha1 "example.com/monok8s/pkg/apis/monok8s/v1alpha1"
|
||||
versioned "example.com/monok8s/pkg/generated/clientset/versioned"
|
||||
internalinterfaces "example.com/monok8s/pkg/generated/informers/externalversions/internalinterfaces"
|
||||
monok8sv1alpha1 "example.com/monok8s/pkg/generated/listers/monok8s/v1alpha1"
|
||||
v1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
runtime "k8s.io/apimachinery/pkg/runtime"
|
||||
watch "k8s.io/apimachinery/pkg/watch"
|
||||
cache "k8s.io/client-go/tools/cache"
|
||||
)
|
||||
|
||||
// OSUpgradeInformer provides access to a shared informer and lister for
|
||||
// OSUpgrades.
|
||||
type OSUpgradeInformer interface {
|
||||
Informer() cache.SharedIndexInformer
|
||||
Lister() monok8sv1alpha1.OSUpgradeLister
|
||||
}
|
||||
|
||||
type oSUpgradeInformer struct {
|
||||
factory internalinterfaces.SharedInformerFactory
|
||||
tweakListOptions internalinterfaces.TweakListOptionsFunc
|
||||
namespace string
|
||||
}
|
||||
|
||||
// NewOSUpgradeInformer constructs a new informer for OSUpgrade type.
|
||||
// Always prefer using an informer factory to get a shared informer instead of getting an independent
|
||||
// one. This reduces memory footprint and number of connections to the server.
|
||||
func NewOSUpgradeInformer(client versioned.Interface, namespace string, resyncPeriod time.Duration, indexers cache.Indexers) cache.SharedIndexInformer {
|
||||
return NewFilteredOSUpgradeInformer(client, namespace, resyncPeriod, indexers, nil)
|
||||
}
|
||||
|
||||
// NewFilteredOSUpgradeInformer constructs a new informer for OSUpgrade type.
|
||||
// Always prefer using an informer factory to get a shared informer instead of getting an independent
|
||||
// one. This reduces memory footprint and number of connections to the server.
|
||||
func NewFilteredOSUpgradeInformer(client versioned.Interface, namespace string, resyncPeriod time.Duration, indexers cache.Indexers, tweakListOptions internalinterfaces.TweakListOptionsFunc) cache.SharedIndexInformer {
|
||||
return cache.NewSharedIndexInformer(
|
||||
cache.ToListWatcherWithWatchListSemantics(&cache.ListWatch{
|
||||
ListFunc: func(options v1.ListOptions) (runtime.Object, error) {
|
||||
if tweakListOptions != nil {
|
||||
tweakListOptions(&options)
|
||||
}
|
||||
return client.Monok8sV1alpha1().OSUpgrades(namespace).List(context.Background(), options)
|
||||
},
|
||||
WatchFunc: func(options v1.ListOptions) (watch.Interface, error) {
|
||||
if tweakListOptions != nil {
|
||||
tweakListOptions(&options)
|
||||
}
|
||||
return client.Monok8sV1alpha1().OSUpgrades(namespace).Watch(context.Background(), options)
|
||||
},
|
||||
ListWithContextFunc: func(ctx context.Context, options v1.ListOptions) (runtime.Object, error) {
|
||||
if tweakListOptions != nil {
|
||||
tweakListOptions(&options)
|
||||
}
|
||||
return client.Monok8sV1alpha1().OSUpgrades(namespace).List(ctx, options)
|
||||
},
|
||||
WatchFuncWithContext: func(ctx context.Context, options v1.ListOptions) (watch.Interface, error) {
|
||||
if tweakListOptions != nil {
|
||||
tweakListOptions(&options)
|
||||
}
|
||||
return client.Monok8sV1alpha1().OSUpgrades(namespace).Watch(ctx, options)
|
||||
},
|
||||
}, client),
|
||||
&apismonok8sv1alpha1.OSUpgrade{},
|
||||
resyncPeriod,
|
||||
indexers,
|
||||
)
|
||||
}
|
||||
|
||||
func (f *oSUpgradeInformer) defaultInformer(client versioned.Interface, resyncPeriod time.Duration) cache.SharedIndexInformer {
|
||||
return NewFilteredOSUpgradeInformer(client, f.namespace, resyncPeriod, cache.Indexers{cache.NamespaceIndex: cache.MetaNamespaceIndexFunc}, f.tweakListOptions)
|
||||
}
|
||||
|
||||
func (f *oSUpgradeInformer) Informer() cache.SharedIndexInformer {
|
||||
return f.factory.InformerFor(&apismonok8sv1alpha1.OSUpgrade{}, f.defaultInformer)
|
||||
}
|
||||
|
||||
func (f *oSUpgradeInformer) Lister() monok8sv1alpha1.OSUpgradeLister {
|
||||
return monok8sv1alpha1.NewOSUpgradeLister(f.Informer().GetIndexer())
|
||||
}
|
||||
@@ -0,0 +1,88 @@
|
||||
/* MIT License */
|
||||
|
||||
// Code generated by informer-gen. DO NOT EDIT.
|
||||
|
||||
package v1alpha1
|
||||
|
||||
import (
|
||||
context "context"
|
||||
time "time"
|
||||
|
||||
apismonok8sv1alpha1 "example.com/monok8s/pkg/apis/monok8s/v1alpha1"
|
||||
versioned "example.com/monok8s/pkg/generated/clientset/versioned"
|
||||
internalinterfaces "example.com/monok8s/pkg/generated/informers/externalversions/internalinterfaces"
|
||||
monok8sv1alpha1 "example.com/monok8s/pkg/generated/listers/monok8s/v1alpha1"
|
||||
v1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
runtime "k8s.io/apimachinery/pkg/runtime"
|
||||
watch "k8s.io/apimachinery/pkg/watch"
|
||||
cache "k8s.io/client-go/tools/cache"
|
||||
)
|
||||
|
||||
// OSUpgradeProgressInformer provides access to a shared informer and lister for
|
||||
// OSUpgradeProgresses.
|
||||
type OSUpgradeProgressInformer interface {
|
||||
Informer() cache.SharedIndexInformer
|
||||
Lister() monok8sv1alpha1.OSUpgradeProgressLister
|
||||
}
|
||||
|
||||
type oSUpgradeProgressInformer struct {
|
||||
factory internalinterfaces.SharedInformerFactory
|
||||
tweakListOptions internalinterfaces.TweakListOptionsFunc
|
||||
namespace string
|
||||
}
|
||||
|
||||
// NewOSUpgradeProgressInformer constructs a new informer for OSUpgradeProgress type.
|
||||
// Always prefer using an informer factory to get a shared informer instead of getting an independent
|
||||
// one. This reduces memory footprint and number of connections to the server.
|
||||
func NewOSUpgradeProgressInformer(client versioned.Interface, namespace string, resyncPeriod time.Duration, indexers cache.Indexers) cache.SharedIndexInformer {
|
||||
return NewFilteredOSUpgradeProgressInformer(client, namespace, resyncPeriod, indexers, nil)
|
||||
}
|
||||
|
||||
// NewFilteredOSUpgradeProgressInformer constructs a new informer for OSUpgradeProgress type.
|
||||
// Always prefer using an informer factory to get a shared informer instead of getting an independent
|
||||
// one. This reduces memory footprint and number of connections to the server.
|
||||
func NewFilteredOSUpgradeProgressInformer(client versioned.Interface, namespace string, resyncPeriod time.Duration, indexers cache.Indexers, tweakListOptions internalinterfaces.TweakListOptionsFunc) cache.SharedIndexInformer {
|
||||
return cache.NewSharedIndexInformer(
|
||||
cache.ToListWatcherWithWatchListSemantics(&cache.ListWatch{
|
||||
ListFunc: func(options v1.ListOptions) (runtime.Object, error) {
|
||||
if tweakListOptions != nil {
|
||||
tweakListOptions(&options)
|
||||
}
|
||||
return client.Monok8sV1alpha1().OSUpgradeProgresses(namespace).List(context.Background(), options)
|
||||
},
|
||||
WatchFunc: func(options v1.ListOptions) (watch.Interface, error) {
|
||||
if tweakListOptions != nil {
|
||||
tweakListOptions(&options)
|
||||
}
|
||||
return client.Monok8sV1alpha1().OSUpgradeProgresses(namespace).Watch(context.Background(), options)
|
||||
},
|
||||
ListWithContextFunc: func(ctx context.Context, options v1.ListOptions) (runtime.Object, error) {
|
||||
if tweakListOptions != nil {
|
||||
tweakListOptions(&options)
|
||||
}
|
||||
return client.Monok8sV1alpha1().OSUpgradeProgresses(namespace).List(ctx, options)
|
||||
},
|
||||
WatchFuncWithContext: func(ctx context.Context, options v1.ListOptions) (watch.Interface, error) {
|
||||
if tweakListOptions != nil {
|
||||
tweakListOptions(&options)
|
||||
}
|
||||
return client.Monok8sV1alpha1().OSUpgradeProgresses(namespace).Watch(ctx, options)
|
||||
},
|
||||
}, client),
|
||||
&apismonok8sv1alpha1.OSUpgradeProgress{},
|
||||
resyncPeriod,
|
||||
indexers,
|
||||
)
|
||||
}
|
||||
|
||||
func (f *oSUpgradeProgressInformer) defaultInformer(client versioned.Interface, resyncPeriod time.Duration) cache.SharedIndexInformer {
|
||||
return NewFilteredOSUpgradeProgressInformer(client, f.namespace, resyncPeriod, cache.Indexers{cache.NamespaceIndex: cache.MetaNamespaceIndexFunc}, f.tweakListOptions)
|
||||
}
|
||||
|
||||
func (f *oSUpgradeProgressInformer) Informer() cache.SharedIndexInformer {
|
||||
return f.factory.InformerFor(&apismonok8sv1alpha1.OSUpgradeProgress{}, f.defaultInformer)
|
||||
}
|
||||
|
||||
func (f *oSUpgradeProgressInformer) Lister() monok8sv1alpha1.OSUpgradeProgressLister {
|
||||
return monok8sv1alpha1.NewOSUpgradeProgressLister(f.Informer().GetIndexer())
|
||||
}
|
||||
@@ -0,0 +1,21 @@
|
||||
/* MIT License */
|
||||
|
||||
// Code generated by lister-gen. DO NOT EDIT.
|
||||
|
||||
package v1alpha1
|
||||
|
||||
// OSUpgradeListerExpansion allows custom methods to be added to
|
||||
// OSUpgradeLister.
|
||||
type OSUpgradeListerExpansion interface{}
|
||||
|
||||
// OSUpgradeNamespaceListerExpansion allows custom methods to be added to
|
||||
// OSUpgradeNamespaceLister.
|
||||
type OSUpgradeNamespaceListerExpansion interface{}
|
||||
|
||||
// OSUpgradeProgressListerExpansion allows custom methods to be added to
|
||||
// OSUpgradeProgressLister.
|
||||
type OSUpgradeProgressListerExpansion interface{}
|
||||
|
||||
// OSUpgradeProgressNamespaceListerExpansion allows custom methods to be added to
|
||||
// OSUpgradeProgressNamespaceLister.
|
||||
type OSUpgradeProgressNamespaceListerExpansion interface{}
|
||||
56
clitools/pkg/generated/listers/monok8s/v1alpha1/osupgrade.go
Normal file
56
clitools/pkg/generated/listers/monok8s/v1alpha1/osupgrade.go
Normal file
@@ -0,0 +1,56 @@
|
||||
/* MIT License */
|
||||
|
||||
// Code generated by lister-gen. DO NOT EDIT.
|
||||
|
||||
package v1alpha1
|
||||
|
||||
import (
|
||||
monok8sv1alpha1 "example.com/monok8s/pkg/apis/monok8s/v1alpha1"
|
||||
labels "k8s.io/apimachinery/pkg/labels"
|
||||
listers "k8s.io/client-go/listers"
|
||||
cache "k8s.io/client-go/tools/cache"
|
||||
)
|
||||
|
||||
// OSUpgradeLister helps list OSUpgrades.
|
||||
// All objects returned here must be treated as read-only.
|
||||
type OSUpgradeLister interface {
|
||||
// List lists all OSUpgrades in the indexer.
|
||||
// Objects returned here must be treated as read-only.
|
||||
List(selector labels.Selector) (ret []*monok8sv1alpha1.OSUpgrade, err error)
|
||||
// OSUpgrades returns an object that can list and get OSUpgrades.
|
||||
OSUpgrades(namespace string) OSUpgradeNamespaceLister
|
||||
OSUpgradeListerExpansion
|
||||
}
|
||||
|
||||
// oSUpgradeLister implements the OSUpgradeLister interface.
|
||||
type oSUpgradeLister struct {
|
||||
listers.ResourceIndexer[*monok8sv1alpha1.OSUpgrade]
|
||||
}
|
||||
|
||||
// NewOSUpgradeLister returns a new OSUpgradeLister.
|
||||
func NewOSUpgradeLister(indexer cache.Indexer) OSUpgradeLister {
|
||||
return &oSUpgradeLister{listers.New[*monok8sv1alpha1.OSUpgrade](indexer, monok8sv1alpha1.Resource("osupgrade"))}
|
||||
}
|
||||
|
||||
// OSUpgrades returns an object that can list and get OSUpgrades.
|
||||
func (s *oSUpgradeLister) OSUpgrades(namespace string) OSUpgradeNamespaceLister {
|
||||
return oSUpgradeNamespaceLister{listers.NewNamespaced[*monok8sv1alpha1.OSUpgrade](s.ResourceIndexer, namespace)}
|
||||
}
|
||||
|
||||
// OSUpgradeNamespaceLister helps list and get OSUpgrades.
|
||||
// All objects returned here must be treated as read-only.
|
||||
type OSUpgradeNamespaceLister interface {
|
||||
// List lists all OSUpgrades in the indexer for a given namespace.
|
||||
// Objects returned here must be treated as read-only.
|
||||
List(selector labels.Selector) (ret []*monok8sv1alpha1.OSUpgrade, err error)
|
||||
// Get retrieves the OSUpgrade from the indexer for a given namespace and name.
|
||||
// Objects returned here must be treated as read-only.
|
||||
Get(name string) (*monok8sv1alpha1.OSUpgrade, error)
|
||||
OSUpgradeNamespaceListerExpansion
|
||||
}
|
||||
|
||||
// oSUpgradeNamespaceLister implements the OSUpgradeNamespaceLister
|
||||
// interface.
|
||||
type oSUpgradeNamespaceLister struct {
|
||||
listers.ResourceIndexer[*monok8sv1alpha1.OSUpgrade]
|
||||
}
|
||||
@@ -0,0 +1,56 @@
|
||||
/* MIT License */
|
||||
|
||||
// Code generated by lister-gen. DO NOT EDIT.
|
||||
|
||||
package v1alpha1
|
||||
|
||||
import (
|
||||
monok8sv1alpha1 "example.com/monok8s/pkg/apis/monok8s/v1alpha1"
|
||||
labels "k8s.io/apimachinery/pkg/labels"
|
||||
listers "k8s.io/client-go/listers"
|
||||
cache "k8s.io/client-go/tools/cache"
|
||||
)
|
||||
|
||||
// OSUpgradeProgressLister helps list OSUpgradeProgresses.
|
||||
// All objects returned here must be treated as read-only.
|
||||
type OSUpgradeProgressLister interface {
|
||||
// List lists all OSUpgradeProgresses in the indexer.
|
||||
// Objects returned here must be treated as read-only.
|
||||
List(selector labels.Selector) (ret []*monok8sv1alpha1.OSUpgradeProgress, err error)
|
||||
// OSUpgradeProgresses returns an object that can list and get OSUpgradeProgresses.
|
||||
OSUpgradeProgresses(namespace string) OSUpgradeProgressNamespaceLister
|
||||
OSUpgradeProgressListerExpansion
|
||||
}
|
||||
|
||||
// oSUpgradeProgressLister implements the OSUpgradeProgressLister interface.
|
||||
type oSUpgradeProgressLister struct {
|
||||
listers.ResourceIndexer[*monok8sv1alpha1.OSUpgradeProgress]
|
||||
}
|
||||
|
||||
// NewOSUpgradeProgressLister returns a new OSUpgradeProgressLister.
|
||||
func NewOSUpgradeProgressLister(indexer cache.Indexer) OSUpgradeProgressLister {
|
||||
return &oSUpgradeProgressLister{listers.New[*monok8sv1alpha1.OSUpgradeProgress](indexer, monok8sv1alpha1.Resource("osupgradeprogress"))}
|
||||
}
|
||||
|
||||
// OSUpgradeProgresses returns an object that can list and get OSUpgradeProgresses.
|
||||
func (s *oSUpgradeProgressLister) OSUpgradeProgresses(namespace string) OSUpgradeProgressNamespaceLister {
|
||||
return oSUpgradeProgressNamespaceLister{listers.NewNamespaced[*monok8sv1alpha1.OSUpgradeProgress](s.ResourceIndexer, namespace)}
|
||||
}
|
||||
|
||||
// OSUpgradeProgressNamespaceLister helps list and get OSUpgradeProgresses.
|
||||
// All objects returned here must be treated as read-only.
|
||||
type OSUpgradeProgressNamespaceLister interface {
|
||||
// List lists all OSUpgradeProgresses in the indexer for a given namespace.
|
||||
// Objects returned here must be treated as read-only.
|
||||
List(selector labels.Selector) (ret []*monok8sv1alpha1.OSUpgradeProgress, err error)
|
||||
// Get retrieves the OSUpgradeProgress from the indexer for a given namespace and name.
|
||||
// Objects returned here must be treated as read-only.
|
||||
Get(name string) (*monok8sv1alpha1.OSUpgradeProgress, error)
|
||||
OSUpgradeProgressNamespaceListerExpansion
|
||||
}
|
||||
|
||||
// oSUpgradeProgressNamespaceLister implements the OSUpgradeProgressNamespaceLister
|
||||
// interface.
|
||||
type oSUpgradeProgressNamespaceLister struct {
|
||||
listers.ResourceIndexer[*monok8sv1alpha1.OSUpgradeProgress]
|
||||
}
|
||||
@@ -3,11 +3,12 @@ package kube
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
monov1alpha1 "example.com/monok8s/pkg/apis/monok8s/v1alpha1"
|
||||
monoclientset "example.com/monok8s/pkg/generated/clientset/versioned"
|
||||
apiextensionsclientset "k8s.io/apiextensions-apiserver/pkg/client/clientset/clientset"
|
||||
utilruntime "k8s.io/apimachinery/pkg/util/runtime"
|
||||
kubernetes "k8s.io/client-go/kubernetes"
|
||||
clientgoscheme "k8s.io/client-go/kubernetes/scheme"
|
||||
monov1alpha1 "example.com/monok8s/pkg/apis/monok8s/v1alpha1"
|
||||
|
||||
"k8s.io/apimachinery/pkg/runtime"
|
||||
"k8s.io/cli-runtime/pkg/genericclioptions"
|
||||
@@ -21,6 +22,7 @@ type Clients struct {
|
||||
Dynamic dynamic.Interface
|
||||
APIExtensions apiextensionsclientset.Interface
|
||||
RESTClientGetter genericclioptions.RESTClientGetter
|
||||
MonoKS monoclientset.Interface
|
||||
}
|
||||
|
||||
func NewClients(flags *genericclioptions.ConfigFlags) (*Clients, error) {
|
||||
@@ -40,7 +42,19 @@ func NewClients(flags *genericclioptions.ConfigFlags) (*Clients, error) {
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("build apiextensions client: %w", err)
|
||||
}
|
||||
return &Clients{Config: cfg, Kubernetes: kubeClient, Dynamic: dyn, APIExtensions: ext, RESTClientGetter: flags}, nil
|
||||
mono, err := monoclientset.NewForConfig(cfg)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("build monok8s client: %w", err)
|
||||
}
|
||||
|
||||
return &Clients{
|
||||
Config: cfg,
|
||||
Kubernetes: kubeClient,
|
||||
Dynamic: dyn,
|
||||
APIExtensions: ext,
|
||||
RESTClientGetter: flags,
|
||||
MonoKS: mono,
|
||||
}, nil
|
||||
}
|
||||
|
||||
func NewClientsFromKubeconfig(kubeconfigPath string) (*Clients, error) {
|
||||
|
||||
400
clitools/pkg/node/admission.go
Normal file
400
clitools/pkg/node/admission.go
Normal file
@@ -0,0 +1,400 @@
|
||||
package node
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"reflect"
|
||||
"sort"
|
||||
"strings"
|
||||
|
||||
appsv1 "k8s.io/api/apps/v1"
|
||||
corev1 "k8s.io/api/core/v1"
|
||||
rbacv1 "k8s.io/api/rbac/v1"
|
||||
apierrors "k8s.io/apimachinery/pkg/api/errors"
|
||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
"k8s.io/apimachinery/pkg/util/intstr"
|
||||
"k8s.io/client-go/kubernetes"
|
||||
"k8s.io/klog/v2"
|
||||
|
||||
monov1alpha1 "example.com/monok8s/pkg/apis/monok8s/v1alpha1"
|
||||
"example.com/monok8s/pkg/kube"
|
||||
templates "example.com/monok8s/pkg/templates"
|
||||
)
|
||||
|
||||
func applyAdmissionControllerDeploymentResources(ctx context.Context, n *NodeContext) error {
|
||||
if strings.TrimSpace(n.Config.Spec.ClusterRole) != "control-plane" || !n.Config.Spec.EnableControlAgent {
|
||||
klog.InfoS("skipped admission controller deployment",
|
||||
"clusterRole", n.Config.Spec.ClusterRole,
|
||||
"enableControlAgent", n.Config.Spec.EnableControlAgent,
|
||||
)
|
||||
return nil
|
||||
}
|
||||
|
||||
if err := ApplyCRDs(ctx, n); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
namespace := strings.TrimSpace(n.Config.Namespace)
|
||||
if namespace == "" {
|
||||
namespace = templates.DefaultNamespace
|
||||
}
|
||||
|
||||
clients, err := kube.NewClientsFromKubeconfig(adminKubeconfigPath)
|
||||
if err != nil {
|
||||
return fmt.Errorf("build kube clients from %s: %w", adminKubeconfigPath, err)
|
||||
}
|
||||
|
||||
labels := map[string]string{
|
||||
"app.kubernetes.io/name": controlAgentName,
|
||||
"app.kubernetes.io/component": "controller",
|
||||
"app.kubernetes.io/part-of": "monok8s",
|
||||
"app.kubernetes.io/managed-by": "ctl",
|
||||
}
|
||||
|
||||
kubeClient := clients.Kubernetes
|
||||
|
||||
if err := ensureNamespace(ctx, kubeClient, namespace, labels); err != nil {
|
||||
return fmt.Errorf("ensure namespace %q: %w", namespace, err)
|
||||
}
|
||||
if err := applyAdmissionControllerServiceAccount(ctx, kubeClient, namespace, labels); err != nil {
|
||||
return fmt.Errorf("apply serviceaccount: %w", err)
|
||||
}
|
||||
if err := applyAdmissionControllerClusterRole(ctx, kubeClient, labels); err != nil {
|
||||
return fmt.Errorf("apply clusterrole: %w", err)
|
||||
}
|
||||
if err := applyAdmissionControllerClusterRoleBinding(ctx, kubeClient, namespace, labels); err != nil {
|
||||
return fmt.Errorf("apply clusterrolebinding: %w", err)
|
||||
}
|
||||
if err := applyAdmissionControllerDeployment(ctx, kubeClient, namespace, labels); err != nil {
|
||||
return fmt.Errorf("apply deployment: %w", err)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func applyAdmissionControllerServiceAccount(ctx context.Context, kubeClient kubernetes.Interface, namespace string, labels map[string]string) error {
|
||||
automount := true
|
||||
|
||||
want := &corev1.ServiceAccount{
|
||||
ObjectMeta: metav1.ObjectMeta{
|
||||
Name: controlAgentName,
|
||||
Namespace: namespace,
|
||||
Labels: labels,
|
||||
},
|
||||
AutomountServiceAccountToken: &automount,
|
||||
}
|
||||
|
||||
existing, err := kubeClient.CoreV1().ServiceAccounts(namespace).Get(ctx, controlAgentName, metav1.GetOptions{})
|
||||
if apierrors.IsNotFound(err) {
|
||||
_, err = kubeClient.CoreV1().ServiceAccounts(namespace).Create(ctx, want, metav1.CreateOptions{})
|
||||
return err
|
||||
}
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
changed := false
|
||||
if !reflect.DeepEqual(existing.Labels, want.Labels) {
|
||||
existing.Labels = want.Labels
|
||||
changed = true
|
||||
}
|
||||
if !reflect.DeepEqual(existing.AutomountServiceAccountToken, want.AutomountServiceAccountToken) {
|
||||
existing.AutomountServiceAccountToken = want.AutomountServiceAccountToken
|
||||
changed = true
|
||||
}
|
||||
|
||||
if !changed {
|
||||
return nil
|
||||
}
|
||||
|
||||
_, err = kubeClient.CoreV1().ServiceAccounts(namespace).Update(ctx, existing, metav1.UpdateOptions{})
|
||||
return err
|
||||
}
|
||||
|
||||
func applyAdmissionControllerClusterRole(ctx context.Context, kubeClient kubernetes.Interface, labels map[string]string) error {
|
||||
wantRules := []rbacv1.PolicyRule{
|
||||
{
|
||||
APIGroups: []string{monov1alpha1.Group},
|
||||
Resources: []string{"osupgrades"},
|
||||
Verbs: []string{"get", "list", "watch"},
|
||||
},
|
||||
{
|
||||
APIGroups: []string{monov1alpha1.Group},
|
||||
Resources: []string{"osupgrades/status"},
|
||||
Verbs: []string{"get", "patch", "update"},
|
||||
},
|
||||
{
|
||||
APIGroups: []string{monov1alpha1.Group},
|
||||
Resources: []string{"osupgradeprogresses"},
|
||||
Verbs: []string{"get", "list", "watch", "create", "patch", "update"},
|
||||
},
|
||||
{
|
||||
APIGroups: []string{""},
|
||||
Resources: []string{"nodes"},
|
||||
Verbs: []string{"get", "list", "watch"},
|
||||
},
|
||||
}
|
||||
|
||||
want := &rbacv1.ClusterRole{
|
||||
ObjectMeta: metav1.ObjectMeta{
|
||||
Name: controlAgentName,
|
||||
Labels: labels,
|
||||
},
|
||||
Rules: wantRules,
|
||||
}
|
||||
|
||||
existing, err := kubeClient.RbacV1().ClusterRoles().Get(ctx, controlAgentName, metav1.GetOptions{})
|
||||
if apierrors.IsNotFound(err) {
|
||||
_, err = kubeClient.RbacV1().ClusterRoles().Create(ctx, want, metav1.CreateOptions{})
|
||||
return err
|
||||
}
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
changed := false
|
||||
if !reflect.DeepEqual(existing.Labels, want.Labels) {
|
||||
existing.Labels = want.Labels
|
||||
changed = true
|
||||
}
|
||||
if !reflect.DeepEqual(existing.Rules, want.Rules) {
|
||||
existing.Rules = want.Rules
|
||||
changed = true
|
||||
}
|
||||
|
||||
if !changed {
|
||||
return nil
|
||||
}
|
||||
|
||||
_, err = kubeClient.RbacV1().ClusterRoles().Update(ctx, existing, metav1.UpdateOptions{})
|
||||
return err
|
||||
}
|
||||
|
||||
func applyAdmissionControllerClusterRoleBinding(ctx context.Context, kubeClient kubernetes.Interface, namespace string, labels map[string]string) error {
|
||||
wantSubjects := []rbacv1.Subject{
|
||||
{
|
||||
Kind: "ServiceAccount",
|
||||
Name: controlAgentName,
|
||||
Namespace: namespace,
|
||||
},
|
||||
}
|
||||
|
||||
wantRoleRef := rbacv1.RoleRef{
|
||||
APIGroup: rbacv1.GroupName,
|
||||
Kind: "ClusterRole",
|
||||
Name: controlAgentName,
|
||||
}
|
||||
|
||||
want := &rbacv1.ClusterRoleBinding{
|
||||
ObjectMeta: metav1.ObjectMeta{
|
||||
Name: controlAgentName,
|
||||
Labels: labels,
|
||||
},
|
||||
Subjects: wantSubjects,
|
||||
RoleRef: wantRoleRef,
|
||||
}
|
||||
|
||||
existing, err := kubeClient.RbacV1().ClusterRoleBindings().Get(ctx, controlAgentName, metav1.GetOptions{})
|
||||
if apierrors.IsNotFound(err) {
|
||||
_, err = kubeClient.RbacV1().ClusterRoleBindings().Create(ctx, want, metav1.CreateOptions{})
|
||||
return err
|
||||
}
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
changed := false
|
||||
if !reflect.DeepEqual(existing.Labels, want.Labels) {
|
||||
existing.Labels = want.Labels
|
||||
changed = true
|
||||
}
|
||||
if !reflect.DeepEqual(existing.Subjects, want.Subjects) {
|
||||
existing.Subjects = want.Subjects
|
||||
changed = true
|
||||
}
|
||||
if !reflect.DeepEqual(existing.RoleRef, want.RoleRef) {
|
||||
existing.RoleRef = want.RoleRef
|
||||
changed = true
|
||||
}
|
||||
|
||||
if !changed {
|
||||
return nil
|
||||
}
|
||||
|
||||
_, err = kubeClient.RbacV1().ClusterRoleBindings().Update(ctx, existing, metav1.UpdateOptions{})
|
||||
return err
|
||||
}
|
||||
|
||||
func applyAdmissionControllerDeployment(ctx context.Context, kubeClient kubernetes.Interface, namespace string, labels map[string]string) error {
|
||||
replicas := int32(1)
|
||||
|
||||
selectorLabels := map[string]string{
|
||||
"app.kubernetes.io/name": controlAgentName,
|
||||
"app.kubernetes.io/component": "controller",
|
||||
}
|
||||
|
||||
podLabels := mergeStringMaps(labels, selectorLabels)
|
||||
|
||||
runAsNonRoot := true
|
||||
allowPrivilegeEscalation := false
|
||||
|
||||
want := &appsv1.Deployment{
|
||||
ObjectMeta: metav1.ObjectMeta{
|
||||
Name: controlAgentName,
|
||||
Namespace: namespace,
|
||||
Labels: labels,
|
||||
},
|
||||
Spec: appsv1.DeploymentSpec{
|
||||
Replicas: &replicas,
|
||||
Selector: &metav1.LabelSelector{
|
||||
MatchLabels: selectorLabels,
|
||||
},
|
||||
Template: corev1.PodTemplateSpec{
|
||||
ObjectMeta: metav1.ObjectMeta{
|
||||
Labels: podLabels,
|
||||
},
|
||||
Spec: corev1.PodSpec{
|
||||
ServiceAccountName: controlAgentName,
|
||||
Containers: []corev1.Container{
|
||||
{
|
||||
Name: "controller",
|
||||
Image: controlAgentImage,
|
||||
ImagePullPolicy: corev1.PullIfNotPresent,
|
||||
Args: []string{
|
||||
"controller",
|
||||
},
|
||||
Env: []corev1.EnvVar{
|
||||
{
|
||||
Name: "POD_NAME",
|
||||
ValueFrom: &corev1.EnvVarSource{
|
||||
FieldRef: &corev1.ObjectFieldSelector{
|
||||
APIVersion: "v1",
|
||||
FieldPath: "metadata.name",
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
Name: "POD_NAMESPACE",
|
||||
ValueFrom: &corev1.EnvVarSource{
|
||||
FieldRef: &corev1.ObjectFieldSelector{
|
||||
APIVersion: "v1",
|
||||
FieldPath: "metadata.namespace",
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
Name: "NODE_NAME",
|
||||
ValueFrom: &corev1.EnvVarSource{
|
||||
FieldRef: &corev1.ObjectFieldSelector{
|
||||
APIVersion: "v1",
|
||||
FieldPath: "spec.nodeName",
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
Ports: []corev1.ContainerPort{
|
||||
{
|
||||
Name: "http",
|
||||
ContainerPort: 8080,
|
||||
Protocol: corev1.ProtocolTCP,
|
||||
},
|
||||
},
|
||||
LivenessProbe: &corev1.Probe{
|
||||
ProbeHandler: corev1.ProbeHandler{
|
||||
HTTPGet: &corev1.HTTPGetAction{
|
||||
Path: "/healthz",
|
||||
Port: intstr.FromString("http"),
|
||||
},
|
||||
},
|
||||
},
|
||||
ReadinessProbe: &corev1.Probe{
|
||||
ProbeHandler: corev1.ProbeHandler{
|
||||
HTTPGet: &corev1.HTTPGetAction{
|
||||
Path: "/readyz",
|
||||
Port: intstr.FromString("http"),
|
||||
},
|
||||
},
|
||||
},
|
||||
SecurityContext: &corev1.SecurityContext{
|
||||
RunAsNonRoot: &runAsNonRoot,
|
||||
AllowPrivilegeEscalation: &allowPrivilegeEscalation,
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
existing, err := kubeClient.AppsV1().Deployments(namespace).Get(ctx, controlAgentName, metav1.GetOptions{})
|
||||
if apierrors.IsNotFound(err) {
|
||||
_, err = kubeClient.AppsV1().Deployments(namespace).Create(ctx, want, metav1.CreateOptions{})
|
||||
return err
|
||||
}
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
changed := false
|
||||
if !reflect.DeepEqual(existing.Labels, want.Labels) {
|
||||
existing.Labels = want.Labels
|
||||
changed = true
|
||||
}
|
||||
if !reflect.DeepEqual(existing.Spec.Replicas, want.Spec.Replicas) {
|
||||
existing.Spec.Replicas = want.Spec.Replicas
|
||||
changed = true
|
||||
}
|
||||
if !reflect.DeepEqual(existing.Spec.Selector, want.Spec.Selector) {
|
||||
existing.Spec.Selector = want.Spec.Selector
|
||||
changed = true
|
||||
}
|
||||
if !reflect.DeepEqual(existing.Spec.Template.Labels, want.Spec.Template.Labels) {
|
||||
existing.Spec.Template.Labels = want.Spec.Template.Labels
|
||||
changed = true
|
||||
}
|
||||
if !reflect.DeepEqual(existing.Spec.Template.Spec.ServiceAccountName, want.Spec.Template.Spec.ServiceAccountName) {
|
||||
existing.Spec.Template.Spec.ServiceAccountName = want.Spec.Template.Spec.ServiceAccountName
|
||||
changed = true
|
||||
}
|
||||
if !reflect.DeepEqual(existing.Spec.Template.Spec.Containers, want.Spec.Template.Spec.Containers) {
|
||||
existing.Spec.Template.Spec.Containers = want.Spec.Template.Spec.Containers
|
||||
changed = true
|
||||
}
|
||||
|
||||
if !changed {
|
||||
return nil
|
||||
}
|
||||
|
||||
_, err = kubeClient.AppsV1().Deployments(namespace).Update(ctx, existing, metav1.UpdateOptions{})
|
||||
return err
|
||||
}
|
||||
|
||||
func mergeStringMaps(maps ...map[string]string) map[string]string {
|
||||
var total int
|
||||
for _, m := range maps {
|
||||
total += len(m)
|
||||
}
|
||||
if total == 0 {
|
||||
return nil
|
||||
}
|
||||
|
||||
out := make(map[string]string, total)
|
||||
for _, m := range maps {
|
||||
for k, v := range m {
|
||||
out[k] = v
|
||||
}
|
||||
}
|
||||
return out
|
||||
}
|
||||
|
||||
func sortedKeys(m map[string]string) []string {
|
||||
if len(m) == 0 {
|
||||
return nil
|
||||
}
|
||||
keys := make([]string, 0, len(m))
|
||||
for k := range m {
|
||||
keys = append(keys, k)
|
||||
}
|
||||
sort.Strings(keys)
|
||||
return keys
|
||||
}
|
||||
@@ -58,6 +58,9 @@ func ApplyControlAgentDaemonSetResources(ctx context.Context, n *NodeContext) er
|
||||
|
||||
kubeClient := clients.Kubernetes
|
||||
|
||||
if err := ensureNamespace(ctx, kubeClient, namespace, labels); err != nil {
|
||||
return fmt.Errorf("ensure namespace %q: %w", namespace, err)
|
||||
}
|
||||
if err := applyControlAgentServiceAccount(ctx, kubeClient, namespace, labels); err != nil {
|
||||
return fmt.Errorf("apply serviceaccount: %w", err)
|
||||
}
|
||||
@@ -74,6 +77,46 @@ func ApplyControlAgentDaemonSetResources(ctx context.Context, n *NodeContext) er
|
||||
return nil
|
||||
}
|
||||
|
||||
func ensureNamespace(
|
||||
ctx context.Context,
|
||||
kubeClient kubernetes.Interface,
|
||||
namespace string,
|
||||
labels map[string]string,
|
||||
) error {
|
||||
_, err := kubeClient.CoreV1().Namespaces().Get(ctx, namespace, metav1.GetOptions{})
|
||||
if err == nil {
|
||||
return nil
|
||||
}
|
||||
if !apierrors.IsNotFound(err) {
|
||||
return fmt.Errorf("get namespace: %w", err)
|
||||
}
|
||||
|
||||
ns := &corev1.Namespace{
|
||||
ObjectMeta: metav1.ObjectMeta{
|
||||
Name: namespace,
|
||||
Labels: copyStringMap(labels),
|
||||
},
|
||||
}
|
||||
|
||||
_, err = kubeClient.CoreV1().Namespaces().Create(ctx, ns, metav1.CreateOptions{})
|
||||
if err != nil && !apierrors.IsAlreadyExists(err) {
|
||||
return fmt.Errorf("create namespace: %w", err)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func copyStringMap(in map[string]string) map[string]string {
|
||||
if len(in) == 0 {
|
||||
return nil
|
||||
}
|
||||
out := make(map[string]string, len(in))
|
||||
for k, v := range in {
|
||||
out[k] = v
|
||||
}
|
||||
return out
|
||||
}
|
||||
|
||||
func applyControlAgentServiceAccount(ctx context.Context, kubeClient kubernetes.Interface, namespace string, labels map[string]string) error {
|
||||
want := &corev1.ServiceAccount{
|
||||
ObjectMeta: metav1.ObjectMeta{
|
||||
@@ -108,16 +151,6 @@ func applyControlAgentServiceAccount(ctx context.Context, kubeClient kubernetes.
|
||||
|
||||
func applyControlAgentClusterRole(ctx context.Context, kubeClient kubernetes.Interface, labels map[string]string) error {
|
||||
wantRules := []rbacv1.PolicyRule{
|
||||
{
|
||||
APIGroups: []string{monov1alpha1.Group},
|
||||
Resources: []string{"osupgrades"},
|
||||
Verbs: []string{"get", "list", "watch"},
|
||||
},
|
||||
{
|
||||
APIGroups: []string{monov1alpha1.Group},
|
||||
Resources: []string{"osupgrades/status"},
|
||||
Verbs: []string{"get", "patch", "update"},
|
||||
},
|
||||
{
|
||||
APIGroups: []string{monov1alpha1.Group},
|
||||
Resources: []string{"osupgradeprogresses"},
|
||||
|
||||
@@ -7,6 +7,7 @@ import (
|
||||
"fmt"
|
||||
"net"
|
||||
"os"
|
||||
"sort"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
@@ -464,9 +465,57 @@ func buildNodeRegistration(spec monov1alpha1.MonoKSConfigSpec) NodeRegistrationO
|
||||
)
|
||||
}
|
||||
|
||||
labels := effectiveNodeLabels(spec)
|
||||
if nodeLabels := buildNodeLabelsArg(labels); nodeLabels != "" {
|
||||
nr.KubeletExtraArgs = append(nr.KubeletExtraArgs,
|
||||
KubeadmArg{Name: "node-labels", Value: nodeLabels},
|
||||
)
|
||||
}
|
||||
|
||||
return nr
|
||||
}
|
||||
|
||||
func effectiveNodeLabels(spec monov1alpha1.MonoKSConfigSpec) map[string]string {
|
||||
if len(spec.NodeLabels) == 0 && !spec.EnableControlAgent {
|
||||
return nil
|
||||
}
|
||||
|
||||
labels := make(map[string]string, len(spec.NodeLabels)+1)
|
||||
for k, v := range spec.NodeLabels {
|
||||
labels[k] = v
|
||||
}
|
||||
|
||||
if spec.EnableControlAgent {
|
||||
labels[monov1alpha1.ControlAgentKey] = "true"
|
||||
}
|
||||
|
||||
return labels
|
||||
}
|
||||
|
||||
func buildNodeLabelsArg(labels map[string]string) string {
|
||||
if len(labels) == 0 {
|
||||
return ""
|
||||
}
|
||||
|
||||
keys := make([]string, 0, len(labels))
|
||||
for k := range labels {
|
||||
k = strings.TrimSpace(k)
|
||||
if k == "" {
|
||||
continue
|
||||
}
|
||||
keys = append(keys, k)
|
||||
}
|
||||
sort.Strings(keys)
|
||||
|
||||
parts := make([]string, 0, len(keys))
|
||||
for _, k := range keys {
|
||||
v := strings.TrimSpace(labels[k])
|
||||
parts = append(parts, k+"="+v)
|
||||
}
|
||||
|
||||
return strings.Join(parts, ",")
|
||||
}
|
||||
|
||||
func maybeAddBootstrapTaint(nr *NodeRegistrationOptions, role string) {
|
||||
if strings.TrimSpace(role) != "worker" {
|
||||
return
|
||||
|
||||
@@ -17,8 +17,8 @@ import (
|
||||
func ApplyLocalNodeMetadataIfPossible(ctx context.Context, nctx *NodeContext) error {
|
||||
spec := nctx.Config.Spec
|
||||
|
||||
if len(spec.NodeAnnotations) == 0 && len(spec.NodeLabels) == 0 {
|
||||
klog.V(4).Infof("No annotations or labels was defined")
|
||||
if len(spec.NodeLabels) == 0 {
|
||||
klog.V(4).Infof("No labels was defined")
|
||||
return nil // nothing to do
|
||||
}
|
||||
|
||||
@@ -53,9 +53,6 @@ func ApplyLocalNodeMetadataIfPossible(ctx context.Context, nctx *NodeContext) er
|
||||
if node.Labels == nil {
|
||||
node.Labels = make(map[string]string)
|
||||
}
|
||||
if node.Annotations == nil {
|
||||
node.Annotations = make(map[string]string)
|
||||
}
|
||||
|
||||
// Apply labels
|
||||
for k, v := range spec.NodeLabels {
|
||||
@@ -67,16 +64,11 @@ func ApplyLocalNodeMetadataIfPossible(ctx context.Context, nctx *NodeContext) er
|
||||
node.Labels[monov1alpah1.ControlAgentKey] = controlAgentNodeSelectorValue
|
||||
}
|
||||
|
||||
// Apply annotations
|
||||
for k, v := range spec.NodeAnnotations {
|
||||
node.Annotations[k] = v
|
||||
}
|
||||
|
||||
_, err = client.CoreV1().Nodes().Update(ctx, node, metav1.UpdateOptions{})
|
||||
if err != nil {
|
||||
return fmt.Errorf("update node metadata: %w", err)
|
||||
}
|
||||
|
||||
klog.Infof("applied labels/annotations to node %q", nodeName)
|
||||
klog.Infof("applied labels to node %q", nodeName)
|
||||
return nil
|
||||
}
|
||||
|
||||
@@ -7,7 +7,7 @@ import (
|
||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
)
|
||||
|
||||
const DefaultNamespace = "kube-system"
|
||||
const DefaultNamespace = "mono-system"
|
||||
|
||||
func DefaultMonoKSConfig(v TemplateValues) monov1alpha1.MonoKSConfig {
|
||||
return monov1alpha1.MonoKSConfig{
|
||||
@@ -51,7 +51,6 @@ func DefaultMonoKSConfig(v TemplateValues) monov1alpha1.MonoKSConfig {
|
||||
|
||||
SubjectAltNames: copyStringSlice(v.SubjectAltNames),
|
||||
NodeLabels: copyStringMap(v.NodeLabels),
|
||||
NodeAnnotations: copyStringMap(v.NodeAnnotations),
|
||||
|
||||
Network: monov1alpha1.NetworkSpec{
|
||||
Hostname: firstNonEmpty(v.Hostname, v.NodeName),
|
||||
|
||||
@@ -39,7 +39,6 @@ type TemplateValues struct {
|
||||
|
||||
SubjectAltNames []string
|
||||
NodeLabels map[string]string
|
||||
NodeAnnotations map[string]string
|
||||
}
|
||||
|
||||
func defaultTemplateValues() TemplateValues {
|
||||
@@ -78,9 +77,6 @@ func defaultTemplateValues() TemplateValues {
|
||||
NodeLabels: map[string]string{
|
||||
monov1alpha1.Label: "value",
|
||||
},
|
||||
NodeAnnotations: map[string]string{
|
||||
monov1alpha1.Annotation: "value",
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
@@ -129,9 +125,6 @@ func LoadTemplateValuesFromEnv() TemplateValues {
|
||||
if m := parseKeyValueMap(os.Getenv("MKS_NODE_LABELS")); len(m) > 0 {
|
||||
v.NodeLabels = m
|
||||
}
|
||||
if m := parseKeyValueMap(os.Getenv("MKS_NODE_ANNOTATIONS")); len(m) > 0 {
|
||||
v.NodeAnnotations = m
|
||||
}
|
||||
|
||||
return v
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user