mirror of
https://github.com/clastix/kamaji.git
synced 2026-08-26 00:47:20 +00:00
feat: addons
This commit is contained in:
committed by
Gonzalo Gabriel Jiménez Fuentes
parent
1d64932265
commit
258b1ff48f
@@ -0,0 +1,6 @@
|
||||
package api
|
||||
|
||||
type KubeadmConfigResourceVersionDependant interface {
|
||||
GetKubeadmConfigResourceVersion() string
|
||||
SetKubeadmConfigResourceVersion(string)
|
||||
}
|
||||
@@ -90,6 +90,20 @@ type ServiceSpec struct {
|
||||
ServiceType ServiceType `json:"serviceType"`
|
||||
}
|
||||
|
||||
// AddonSpec defines the spec for every addon.
|
||||
type AddonSpec struct {
|
||||
// +kubebuilder:default=true
|
||||
Enabled *bool `json:"enabled,omitempty"`
|
||||
}
|
||||
|
||||
// AddonsSpec defines the enabled addons and their features.
|
||||
type AddonsSpec struct {
|
||||
// +kubebuilder:default={enabled: true}
|
||||
CoreDNS AddonSpec `json:"coreDNS,omitempty"`
|
||||
// +kubebuilder:default={enabled: true}
|
||||
KubeProxy AddonSpec `json:"kubeProxy,omitempty"`
|
||||
}
|
||||
|
||||
// TenantControlPlaneSpec defines the desired state of TenantControlPlane.
|
||||
type TenantControlPlaneSpec struct {
|
||||
ControlPlane ControlPlane `json:"controlPlane"`
|
||||
@@ -99,6 +113,10 @@ type TenantControlPlaneSpec struct {
|
||||
|
||||
// NetworkProfile specifies how the network is
|
||||
NetworkProfile NetworkProfileSpec `json:"networkProfile,omitempty"`
|
||||
|
||||
// Addons contain which addons are enabled
|
||||
// +kubebuilder:default={coreDNS: {enabled: true}, kubeProxy: {enabled: true}}
|
||||
Addons AddonsSpec `json:"addons,omitempty"`
|
||||
}
|
||||
|
||||
// ETCDAPIServerCertificate defines the observed state of ETCD Certificate for API server.
|
||||
@@ -179,15 +197,42 @@ type KubeadmPhaseStatus struct {
|
||||
LastUpdate metav1.Time `json:"lastUpdate,omitempty"`
|
||||
}
|
||||
|
||||
func (d KubeadmPhaseStatus) GetKubeadmConfigResourceVersion() string {
|
||||
return d.KubeadmConfigResourceVersion
|
||||
}
|
||||
|
||||
func (d *KubeadmPhaseStatus) SetKubeadmConfigResourceVersion(rv string) {
|
||||
d.KubeadmConfigResourceVersion = rv
|
||||
}
|
||||
|
||||
// KubeadmPhasesStatus contains the status of the different kubeadm phases action.
|
||||
type KubeadmPhasesStatus struct {
|
||||
UploadConfigKubeadm KubeadmPhaseStatus `json:"uploadConfigKubeadm"`
|
||||
UploadConfigKubelet KubeadmPhaseStatus `json:"uploadConfigKubelet"`
|
||||
AddonCoreDNS KubeadmPhaseStatus `json:"addonCoreDNS"`
|
||||
AddonKubeProxy KubeadmPhaseStatus `json:"addonKubeProxy"`
|
||||
BootstrapToken KubeadmPhaseStatus `json:"bootstrapToken"`
|
||||
}
|
||||
|
||||
// AddonStatus defines the observed state of an Addon.
|
||||
type AddonStatus struct {
|
||||
Enabled bool `json:"enabled"`
|
||||
KubeadmConfigResourceVersion string `json:"kubeadmConfigResourceVersion,omitempty"`
|
||||
LastUpdate metav1.Time `json:"lastUpdate,omitempty"`
|
||||
}
|
||||
|
||||
func (d AddonStatus) GetKubeadmConfigResourceVersion() string {
|
||||
return d.KubeadmConfigResourceVersion
|
||||
}
|
||||
|
||||
func (d *AddonStatus) SetKubeadmConfigResourceVersion(rv string) {
|
||||
d.KubeadmConfigResourceVersion = rv
|
||||
}
|
||||
|
||||
// AddonsStatus defines the observed state of the different Addons.
|
||||
type AddonsStatus struct {
|
||||
CoreDNS AddonStatus `json:"coreDNS,omitempty"`
|
||||
KubeProxy AddonStatus `json:"kubeProxy,omitempty"`
|
||||
}
|
||||
|
||||
// TenantControlPlaneStatus defines the observed state of TenantControlPlane.
|
||||
type TenantControlPlaneStatus struct {
|
||||
// Storage Status contains information about Kubernetes storage system
|
||||
@@ -205,6 +250,8 @@ type TenantControlPlaneStatus struct {
|
||||
KubeadmPhase KubeadmPhasesStatus `json:"kubeadmPhase,omitempty"`
|
||||
// ControlPlaneEndpoint contains the status of the kubernetes control plane
|
||||
ControlPlaneEndpoint string `json:"controlPlaneEndpoint,omitempty"`
|
||||
// Addons contains the status of the different Addons
|
||||
Addons AddonsStatus `json:"addons,omitempty"`
|
||||
}
|
||||
|
||||
// KubernetesStatus defines the status of the resources deployed in the management cluster,
|
||||
|
||||
@@ -57,6 +57,76 @@ func (in *AdditionalMetadata) DeepCopy() *AdditionalMetadata {
|
||||
return out
|
||||
}
|
||||
|
||||
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
|
||||
func (in *AddonSpec) DeepCopyInto(out *AddonSpec) {
|
||||
*out = *in
|
||||
if in.Enabled != nil {
|
||||
in, out := &in.Enabled, &out.Enabled
|
||||
*out = new(bool)
|
||||
**out = **in
|
||||
}
|
||||
}
|
||||
|
||||
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new AddonSpec.
|
||||
func (in *AddonSpec) DeepCopy() *AddonSpec {
|
||||
if in == nil {
|
||||
return nil
|
||||
}
|
||||
out := new(AddonSpec)
|
||||
in.DeepCopyInto(out)
|
||||
return out
|
||||
}
|
||||
|
||||
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
|
||||
func (in *AddonStatus) DeepCopyInto(out *AddonStatus) {
|
||||
*out = *in
|
||||
in.LastUpdate.DeepCopyInto(&out.LastUpdate)
|
||||
}
|
||||
|
||||
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new AddonStatus.
|
||||
func (in *AddonStatus) DeepCopy() *AddonStatus {
|
||||
if in == nil {
|
||||
return nil
|
||||
}
|
||||
out := new(AddonStatus)
|
||||
in.DeepCopyInto(out)
|
||||
return out
|
||||
}
|
||||
|
||||
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
|
||||
func (in *AddonsSpec) DeepCopyInto(out *AddonsSpec) {
|
||||
*out = *in
|
||||
in.CoreDNS.DeepCopyInto(&out.CoreDNS)
|
||||
in.KubeProxy.DeepCopyInto(&out.KubeProxy)
|
||||
}
|
||||
|
||||
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new AddonsSpec.
|
||||
func (in *AddonsSpec) DeepCopy() *AddonsSpec {
|
||||
if in == nil {
|
||||
return nil
|
||||
}
|
||||
out := new(AddonsSpec)
|
||||
in.DeepCopyInto(out)
|
||||
return out
|
||||
}
|
||||
|
||||
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
|
||||
func (in *AddonsStatus) DeepCopyInto(out *AddonsStatus) {
|
||||
*out = *in
|
||||
in.CoreDNS.DeepCopyInto(&out.CoreDNS)
|
||||
in.KubeProxy.DeepCopyInto(&out.KubeProxy)
|
||||
}
|
||||
|
||||
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new AddonsStatus.
|
||||
func (in *AddonsStatus) DeepCopy() *AddonsStatus {
|
||||
if in == nil {
|
||||
return nil
|
||||
}
|
||||
out := new(AddonsStatus)
|
||||
in.DeepCopyInto(out)
|
||||
return out
|
||||
}
|
||||
|
||||
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
|
||||
func (in AdmissionControllers) DeepCopyInto(out *AdmissionControllers) {
|
||||
{
|
||||
@@ -255,8 +325,6 @@ func (in *KubeadmPhasesStatus) DeepCopyInto(out *KubeadmPhasesStatus) {
|
||||
*out = *in
|
||||
in.UploadConfigKubeadm.DeepCopyInto(&out.UploadConfigKubeadm)
|
||||
in.UploadConfigKubelet.DeepCopyInto(&out.UploadConfigKubelet)
|
||||
in.AddonCoreDNS.DeepCopyInto(&out.AddonCoreDNS)
|
||||
in.AddonKubeProxy.DeepCopyInto(&out.AddonKubeProxy)
|
||||
in.BootstrapToken.DeepCopyInto(&out.BootstrapToken)
|
||||
}
|
||||
|
||||
@@ -564,6 +632,7 @@ func (in *TenantControlPlaneSpec) DeepCopyInto(out *TenantControlPlaneSpec) {
|
||||
in.ControlPlane.DeepCopyInto(&out.ControlPlane)
|
||||
in.Kubernetes.DeepCopyInto(&out.Kubernetes)
|
||||
in.NetworkProfile.DeepCopyInto(&out.NetworkProfile)
|
||||
in.Addons.DeepCopyInto(&out.Addons)
|
||||
}
|
||||
|
||||
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new TenantControlPlaneSpec.
|
||||
@@ -585,6 +654,7 @@ func (in *TenantControlPlaneStatus) DeepCopyInto(out *TenantControlPlaneStatus)
|
||||
in.Kubernetes.DeepCopyInto(&out.Kubernetes)
|
||||
in.KubeadmConfig.DeepCopyInto(&out.KubeadmConfig)
|
||||
in.KubeadmPhase.DeepCopyInto(&out.KubeadmPhase)
|
||||
in.Addons.DeepCopyInto(&out.Addons)
|
||||
}
|
||||
|
||||
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new TenantControlPlaneStatus.
|
||||
|
||||
@@ -60,6 +60,33 @@ spec:
|
||||
spec:
|
||||
description: TenantControlPlaneSpec defines the desired state of TenantControlPlane.
|
||||
properties:
|
||||
addons:
|
||||
default:
|
||||
coreDNS:
|
||||
enabled: true
|
||||
kubeProxy:
|
||||
enabled: true
|
||||
description: Addons contain which addons are enabled
|
||||
properties:
|
||||
coreDNS:
|
||||
default:
|
||||
enabled: true
|
||||
description: AddonSpec defines the spec for every addon.
|
||||
properties:
|
||||
enabled:
|
||||
default: true
|
||||
type: boolean
|
||||
type: object
|
||||
kubeProxy:
|
||||
default:
|
||||
enabled: true
|
||||
description: AddonSpec defines the spec for every addon.
|
||||
properties:
|
||||
enabled:
|
||||
default: true
|
||||
type: boolean
|
||||
type: object
|
||||
type: object
|
||||
controlPlane:
|
||||
description: ControlPlane defines how the Tenant Control Plane Kubernetes
|
||||
resources must be created in the Admin Cluster, such as the number
|
||||
@@ -278,6 +305,36 @@ spec:
|
||||
status:
|
||||
description: TenantControlPlaneStatus defines the observed state of TenantControlPlane.
|
||||
properties:
|
||||
addons:
|
||||
description: Addons contains the status of the different Addons
|
||||
properties:
|
||||
coreDNS:
|
||||
description: AddonStatus defines the observed state of an Addon.
|
||||
properties:
|
||||
enabled:
|
||||
type: boolean
|
||||
kubeadmConfigResourceVersion:
|
||||
type: string
|
||||
lastUpdate:
|
||||
format: date-time
|
||||
type: string
|
||||
required:
|
||||
- enabled
|
||||
type: object
|
||||
kubeProxy:
|
||||
description: AddonStatus defines the observed state of an Addon.
|
||||
properties:
|
||||
enabled:
|
||||
type: boolean
|
||||
kubeadmConfigResourceVersion:
|
||||
type: string
|
||||
lastUpdate:
|
||||
format: date-time
|
||||
type: string
|
||||
required:
|
||||
- enabled
|
||||
type: object
|
||||
type: object
|
||||
certificates:
|
||||
description: Certificates contains information about the different
|
||||
certificates that are necessary to run a kubernetes control plane
|
||||
@@ -370,26 +427,6 @@ spec:
|
||||
description: KubeadmPhase contains the status of the kubeadm phases
|
||||
action
|
||||
properties:
|
||||
addonCoreDNS:
|
||||
description: KubeadmPhasesStatus contains the status of of a kubeadm
|
||||
phase action.
|
||||
properties:
|
||||
kubeadmConfigResourceVersion:
|
||||
type: string
|
||||
lastUpdate:
|
||||
format: date-time
|
||||
type: string
|
||||
type: object
|
||||
addonKubeProxy:
|
||||
description: KubeadmPhasesStatus contains the status of of a kubeadm
|
||||
phase action.
|
||||
properties:
|
||||
kubeadmConfigResourceVersion:
|
||||
type: string
|
||||
lastUpdate:
|
||||
format: date-time
|
||||
type: string
|
||||
type: object
|
||||
bootstrapToken:
|
||||
description: KubeadmPhasesStatus contains the status of of a kubeadm
|
||||
phase action.
|
||||
@@ -421,8 +458,6 @@ spec:
|
||||
type: string
|
||||
type: object
|
||||
required:
|
||||
- addonCoreDNS
|
||||
- addonKubeProxy
|
||||
- bootstrapToken
|
||||
- uploadConfigKubeadm
|
||||
- uploadConfigKubelet
|
||||
|
||||
+57
-20
@@ -60,6 +60,33 @@ spec:
|
||||
spec:
|
||||
description: TenantControlPlaneSpec defines the desired state of TenantControlPlane.
|
||||
properties:
|
||||
addons:
|
||||
default:
|
||||
coreDNS:
|
||||
enabled: true
|
||||
kubeProxy:
|
||||
enabled: true
|
||||
description: Addons contain which addons are enabled
|
||||
properties:
|
||||
coreDNS:
|
||||
default:
|
||||
enabled: true
|
||||
description: AddonSpec defines the spec for every addon.
|
||||
properties:
|
||||
enabled:
|
||||
default: true
|
||||
type: boolean
|
||||
type: object
|
||||
kubeProxy:
|
||||
default:
|
||||
enabled: true
|
||||
description: AddonSpec defines the spec for every addon.
|
||||
properties:
|
||||
enabled:
|
||||
default: true
|
||||
type: boolean
|
||||
type: object
|
||||
type: object
|
||||
controlPlane:
|
||||
description: ControlPlane defines how the Tenant Control Plane Kubernetes resources must be created in the Admin Cluster, such as the number of Pod replicas, the Service resource, or the Ingress.
|
||||
properties:
|
||||
@@ -257,6 +284,36 @@ spec:
|
||||
status:
|
||||
description: TenantControlPlaneStatus defines the observed state of TenantControlPlane.
|
||||
properties:
|
||||
addons:
|
||||
description: Addons contains the status of the different Addons
|
||||
properties:
|
||||
coreDNS:
|
||||
description: AddonStatus defines the observed state of an Addon.
|
||||
properties:
|
||||
enabled:
|
||||
type: boolean
|
||||
kubeadmConfigResourceVersion:
|
||||
type: string
|
||||
lastUpdate:
|
||||
format: date-time
|
||||
type: string
|
||||
required:
|
||||
- enabled
|
||||
type: object
|
||||
kubeProxy:
|
||||
description: AddonStatus defines the observed state of an Addon.
|
||||
properties:
|
||||
enabled:
|
||||
type: boolean
|
||||
kubeadmConfigResourceVersion:
|
||||
type: string
|
||||
lastUpdate:
|
||||
format: date-time
|
||||
type: string
|
||||
required:
|
||||
- enabled
|
||||
type: object
|
||||
type: object
|
||||
certificates:
|
||||
description: Certificates contains information about the different certificates that are necessary to run a kubernetes control plane
|
||||
properties:
|
||||
@@ -343,24 +400,6 @@ spec:
|
||||
kubeadmPhase:
|
||||
description: KubeadmPhase contains the status of the kubeadm phases action
|
||||
properties:
|
||||
addonCoreDNS:
|
||||
description: KubeadmPhasesStatus contains the status of of a kubeadm phase action.
|
||||
properties:
|
||||
kubeadmConfigResourceVersion:
|
||||
type: string
|
||||
lastUpdate:
|
||||
format: date-time
|
||||
type: string
|
||||
type: object
|
||||
addonKubeProxy:
|
||||
description: KubeadmPhasesStatus contains the status of of a kubeadm phase action.
|
||||
properties:
|
||||
kubeadmConfigResourceVersion:
|
||||
type: string
|
||||
lastUpdate:
|
||||
format: date-time
|
||||
type: string
|
||||
type: object
|
||||
bootstrapToken:
|
||||
description: KubeadmPhasesStatus contains the status of of a kubeadm phase action.
|
||||
properties:
|
||||
@@ -389,8 +428,6 @@ spec:
|
||||
type: string
|
||||
type: object
|
||||
required:
|
||||
- addonCoreDNS
|
||||
- addonKubeProxy
|
||||
- bootstrapToken
|
||||
- uploadConfigKubeadm
|
||||
- uploadConfigKubelet
|
||||
|
||||
@@ -46,3 +46,8 @@ spec:
|
||||
podCidr: "10.244.0.0/16"
|
||||
dnsServiceIPs:
|
||||
- "10.96.0.10"
|
||||
addons:
|
||||
coreDNS:
|
||||
enabled: true
|
||||
kubeProxy:
|
||||
enabled: true
|
||||
|
||||
@@ -224,35 +224,35 @@ func (r *TenantControlPlaneReconciler) Reconcile(ctx context.Context, req ctrl.R
|
||||
&resources.KubernetesIngressResource{
|
||||
Client: r.Client,
|
||||
},
|
||||
&resources.KubeadmPhaseResource{
|
||||
Name: "upload-config-kubeadm",
|
||||
Client: r.Client,
|
||||
Log: log,
|
||||
KubeadmPhase: resources.PhaseUploadConfigKubeadm,
|
||||
&resources.KubeadmPhase{
|
||||
Name: "upload-config-kubeadm",
|
||||
Client: r.Client,
|
||||
Log: log,
|
||||
Phase: resources.PhaseUploadConfigKubeadm,
|
||||
},
|
||||
&resources.KubeadmPhaseResource{
|
||||
Name: "upload-config-kubelet",
|
||||
Client: r.Client,
|
||||
Log: log,
|
||||
KubeadmPhase: resources.PhaseUploadConfigKubelet,
|
||||
&resources.KubeadmPhase{
|
||||
Name: "upload-config-kubelet",
|
||||
Client: r.Client,
|
||||
Log: log,
|
||||
Phase: resources.PhaseUploadConfigKubelet,
|
||||
},
|
||||
&resources.KubeadmPhaseResource{
|
||||
Name: "addon-coredns",
|
||||
Client: r.Client,
|
||||
Log: log,
|
||||
KubeadmPhase: resources.PhaseAddonCoreDNS,
|
||||
&resources.KubeadmPhase{
|
||||
Name: "bootstrap-token",
|
||||
Client: r.Client,
|
||||
Log: log,
|
||||
Phase: resources.PhaseBootstrapToken,
|
||||
},
|
||||
&resources.KubeadmPhaseResource{
|
||||
Name: "addon-kubeproxy",
|
||||
&resources.KubeadmAddonResource{
|
||||
Name: "coredns",
|
||||
Client: r.Client,
|
||||
Log: log,
|
||||
KubeadmPhase: resources.PhaseAddonKubeProxy,
|
||||
KubeadmAddon: resources.AddonCoreDNS,
|
||||
},
|
||||
&resources.KubeadmPhaseResource{
|
||||
Name: "bootstrap-token",
|
||||
&resources.KubeadmAddonResource{
|
||||
Name: "kubeproxy",
|
||||
Client: r.Client,
|
||||
Log: log,
|
||||
KubeadmPhase: resources.PhaseBootstrapToken,
|
||||
KubeadmAddon: resources.AddonKubeProxy,
|
||||
},
|
||||
}
|
||||
|
||||
|
||||
+166
-2
@@ -4,12 +4,14 @@
|
||||
package kubeadm
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"time"
|
||||
|
||||
"github.com/pkg/errors"
|
||||
appsv1 "k8s.io/api/apps/v1"
|
||||
corev1 "k8s.io/api/core/v1"
|
||||
k8serrors "k8s.io/apimachinery/pkg/api/errors"
|
||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
"k8s.io/client-go/kubernetes"
|
||||
clientcmdapi "k8s.io/client-go/tools/clientcmd/api/v1"
|
||||
@@ -22,11 +24,84 @@ import (
|
||||
"k8s.io/utils/pointer"
|
||||
)
|
||||
|
||||
func CoreDNSAddon(client kubernetes.Interface, config *Configuration) error {
|
||||
const (
|
||||
kubeSystemNamespace = "kube-system"
|
||||
kubeProxyName = "kube-proxy"
|
||||
coreDNSName = "coredns"
|
||||
kubeDNSName = "kube-dns"
|
||||
)
|
||||
|
||||
func AddCoreDNS(client kubernetes.Interface, config *Configuration) error {
|
||||
return dns.EnsureDNSAddon(&config.InitConfiguration.ClusterConfiguration, client)
|
||||
}
|
||||
|
||||
func KubeProxyAddon(client kubernetes.Interface, config *Configuration) error {
|
||||
func RemoveCoreDNSAddon(ctx context.Context, client kubernetes.Interface) error {
|
||||
var result error
|
||||
|
||||
if err := removeCoreDNSService(ctx, client); err != nil {
|
||||
if !k8serrors.IsNotFound(err) {
|
||||
return err
|
||||
}
|
||||
result = err
|
||||
}
|
||||
|
||||
if err := removeCoreDNSDeployment(ctx, client); err != nil {
|
||||
if !k8serrors.IsNotFound(err) {
|
||||
return err
|
||||
}
|
||||
result = err
|
||||
}
|
||||
|
||||
if err := removeCoreDNSConfigMap(ctx, client); err != nil {
|
||||
if !k8serrors.IsNotFound(err) {
|
||||
return err
|
||||
}
|
||||
result = err
|
||||
}
|
||||
|
||||
return result
|
||||
}
|
||||
|
||||
func removeCoreDNSService(ctx context.Context, client kubernetes.Interface) error {
|
||||
name, _ := getCoreDNSServiceName(ctx)
|
||||
opts := metav1.DeleteOptions{}
|
||||
|
||||
return client.CoreV1().Services(kubeSystemNamespace).Delete(ctx, name, opts)
|
||||
}
|
||||
|
||||
func removeCoreDNSDeployment(ctx context.Context, client kubernetes.Interface) error {
|
||||
name, _ := getCoreDNSDeploymentName(ctx)
|
||||
opts := metav1.DeleteOptions{}
|
||||
|
||||
return client.AppsV1().Deployments(kubeSystemNamespace).Delete(ctx, name, opts)
|
||||
}
|
||||
|
||||
func removeCoreDNSConfigMap(ctx context.Context, client kubernetes.Interface) error {
|
||||
name, _ := getCoreDNSConfigMapName(ctx)
|
||||
opts := metav1.DeleteOptions{}
|
||||
|
||||
return client.CoreV1().ConfigMaps(kubeSystemNamespace).Delete(ctx, name, opts)
|
||||
}
|
||||
|
||||
func getCoreDNSServiceName(ctx context.Context) (string, error) {
|
||||
// TODO: Currently, DNS is installed using kubeadm phases, therefore we know the name.
|
||||
// Implement a method for future approaches
|
||||
return kubeDNSName, nil
|
||||
}
|
||||
|
||||
func getCoreDNSDeploymentName(ctx context.Context) (string, error) {
|
||||
// TODO: Currently, DNS is installed using kubeadm phases, therefore we know the name.
|
||||
// Implement a method for future approaches
|
||||
return coreDNSName, nil
|
||||
}
|
||||
|
||||
func getCoreDNSConfigMapName(ctx context.Context) (string, error) {
|
||||
// TODO: Currently, DNS is installed using kubeadm phases, therefore we know the name.
|
||||
// Implement a method for future approaches
|
||||
return coreDNSName, nil
|
||||
}
|
||||
|
||||
func AddKubeProxy(client kubernetes.Interface, config *Configuration) error {
|
||||
if err := proxy.CreateServiceAccount(client); err != nil {
|
||||
return errors.Wrap(err, "error when creating kube-proxy service account")
|
||||
}
|
||||
@@ -46,6 +121,95 @@ func KubeProxyAddon(client kubernetes.Interface, config *Configuration) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func RemoveKubeProxy(ctx context.Context, client kubernetes.Interface) error {
|
||||
var result error
|
||||
|
||||
if err := removeKubeProxyDaemonSet(ctx, client); err != nil {
|
||||
if !k8serrors.IsNotFound(err) {
|
||||
return err
|
||||
}
|
||||
result = err
|
||||
}
|
||||
|
||||
if err := removeKubeProxyConfigMap(ctx, client); err != nil {
|
||||
if !k8serrors.IsNotFound(err) {
|
||||
return err
|
||||
}
|
||||
result = err
|
||||
}
|
||||
|
||||
if err := removeKubeProxyRBAC(ctx, client); err != nil {
|
||||
if !k8serrors.IsNotFound(err) {
|
||||
return err
|
||||
}
|
||||
result = err
|
||||
}
|
||||
|
||||
return result
|
||||
}
|
||||
|
||||
func removeKubeProxyDaemonSet(ctx context.Context, client kubernetes.Interface) error {
|
||||
name, _ := getKubeProxyDaemonSetName(ctx)
|
||||
opts := metav1.DeleteOptions{}
|
||||
|
||||
return client.AppsV1().DaemonSets(kubeSystemNamespace).Delete(ctx, name, opts)
|
||||
}
|
||||
|
||||
func removeKubeProxyConfigMap(ctx context.Context, client kubernetes.Interface) error {
|
||||
name, _ := getKubeProxyConfigMapName(ctx)
|
||||
opts := metav1.DeleteOptions{}
|
||||
|
||||
return client.CoreV1().ConfigMaps(kubeSystemNamespace).Delete(ctx, name, opts)
|
||||
}
|
||||
|
||||
func removeKubeProxyRBAC(ctx context.Context, client kubernetes.Interface) error {
|
||||
// TODO: Currently, kube-proxy is installed using kubeadm phases, therefore, name is the same.
|
||||
name, _ := getKubeProxyRBACName(ctx)
|
||||
opts := metav1.DeleteOptions{}
|
||||
var result error
|
||||
|
||||
if err := client.RbacV1().RoleBindings(kubeSystemNamespace).Delete(ctx, name, opts); err != nil {
|
||||
if !k8serrors.IsNotFound(err) {
|
||||
return err
|
||||
}
|
||||
result = err
|
||||
}
|
||||
|
||||
if err := client.RbacV1().Roles(kubeSystemNamespace).Delete(ctx, name, opts); err != nil {
|
||||
if !k8serrors.IsNotFound(err) {
|
||||
return err
|
||||
}
|
||||
result = err
|
||||
}
|
||||
|
||||
if err := client.CoreV1().ServiceAccounts(kubeSystemNamespace).Delete(ctx, name, opts); err != nil {
|
||||
if !k8serrors.IsNotFound(err) {
|
||||
return err
|
||||
}
|
||||
result = err
|
||||
}
|
||||
|
||||
return result
|
||||
}
|
||||
|
||||
func getKubeProxyRBACName(ctx context.Context) (string, error) {
|
||||
// TODO: Currently, kube-proxy is installed using kubeadm phases, therefore we know the name.
|
||||
// Implement a method for future approaches
|
||||
return kubeProxyName, nil
|
||||
}
|
||||
|
||||
func getKubeProxyDaemonSetName(ctx context.Context) (string, error) {
|
||||
// TODO: Currently, kube-proxy is installed using kubeadm phases, therefore we know the name.
|
||||
// Implement a method for future approaches
|
||||
return kubeProxyName, nil
|
||||
}
|
||||
|
||||
func getKubeProxyConfigMapName(ctx context.Context) (string, error) {
|
||||
// TODO: Currently, kube-proxy is installed using kubeadm phases, therefore we know the name.
|
||||
// Implement a method for future approaches
|
||||
return kubeProxyName, nil
|
||||
}
|
||||
|
||||
func createKubeProxyConfigMap(client kubernetes.Interface, config *Configuration) error {
|
||||
configConf, err := getKubeproxyConfigmapContent(config)
|
||||
if err != nil {
|
||||
|
||||
@@ -37,7 +37,7 @@ func (r *APIServerCertificate) ShouldCleanup(plane *kamajiv1alpha1.TenantControl
|
||||
return false
|
||||
}
|
||||
|
||||
func (r *APIServerCertificate) CleanUp(ctx context.Context) (bool, error) {
|
||||
func (r *APIServerCertificate) CleanUp(ctx context.Context, tenantControlPlane *kamajiv1alpha1.TenantControlPlane) (bool, error) {
|
||||
return false, nil
|
||||
}
|
||||
|
||||
|
||||
@@ -37,7 +37,7 @@ func (r *APIServerKubeletClientCertificate) ShouldCleanup(plane *kamajiv1alpha1.
|
||||
return false
|
||||
}
|
||||
|
||||
func (r *APIServerKubeletClientCertificate) CleanUp(ctx context.Context) (bool, error) {
|
||||
func (r *APIServerKubeletClientCertificate) CleanUp(ctx context.Context, tenantControlPlane *kamajiv1alpha1.TenantControlPlane) (bool, error) {
|
||||
return false, nil
|
||||
}
|
||||
|
||||
|
||||
@@ -36,7 +36,7 @@ func (r *CACertificate) ShouldCleanup(plane *kamajiv1alpha1.TenantControlPlane)
|
||||
return false
|
||||
}
|
||||
|
||||
func (r *CACertificate) CleanUp(ctx context.Context) (bool, error) {
|
||||
func (r *CACertificate) CleanUp(ctx context.Context, tenantControlPlane *kamajiv1alpha1.TenantControlPlane) (bool, error) {
|
||||
return false, nil
|
||||
}
|
||||
|
||||
|
||||
@@ -4,5 +4,6 @@
|
||||
package resources
|
||||
|
||||
const (
|
||||
defaultIngressPort = 443
|
||||
kubeconfigAdminKeyName = "admin.conf"
|
||||
defaultIngressPort = 443
|
||||
)
|
||||
|
||||
@@ -43,7 +43,7 @@ func (r *ETCDCACertificatesResource) ShouldCleanup(plane *kamajiv1alpha1.TenantC
|
||||
return false
|
||||
}
|
||||
|
||||
func (r *ETCDCACertificatesResource) CleanUp(ctx context.Context) (bool, error) {
|
||||
func (r *ETCDCACertificatesResource) CleanUp(ctx context.Context, tenantControlPlane *kamajiv1alpha1.TenantControlPlane) (bool, error) {
|
||||
return false, nil
|
||||
}
|
||||
|
||||
|
||||
@@ -40,7 +40,7 @@ func (r *ETCDCertificatesResource) ShouldCleanup(plane *kamajiv1alpha1.TenantCon
|
||||
return false
|
||||
}
|
||||
|
||||
func (r *ETCDCertificatesResource) CleanUp(ctx context.Context) (bool, error) {
|
||||
func (r *ETCDCertificatesResource) CleanUp(ctx context.Context, tenantControlPlane *kamajiv1alpha1.TenantControlPlane) (bool, error) {
|
||||
return false, nil
|
||||
}
|
||||
|
||||
|
||||
@@ -52,7 +52,7 @@ func (r *ETCDSetupResource) ShouldCleanup(plane *kamajiv1alpha1.TenantControlPla
|
||||
return false
|
||||
}
|
||||
|
||||
func (r *ETCDSetupResource) CleanUp(ctx context.Context) (bool, error) {
|
||||
func (r *ETCDSetupResource) CleanUp(ctx context.Context, tenantControlPlane *kamajiv1alpha1.TenantControlPlane) (bool, error) {
|
||||
return false, nil
|
||||
}
|
||||
|
||||
|
||||
@@ -37,7 +37,7 @@ func (r *FrontProxyClientCertificate) ShouldCleanup(plane *kamajiv1alpha1.Tenant
|
||||
return false
|
||||
}
|
||||
|
||||
func (r *FrontProxyClientCertificate) CleanUp(ctx context.Context) (bool, error) {
|
||||
func (r *FrontProxyClientCertificate) CleanUp(ctx context.Context, tenantControlPlane *kamajiv1alpha1.TenantControlPlane) (bool, error) {
|
||||
return false, nil
|
||||
}
|
||||
|
||||
|
||||
@@ -36,7 +36,7 @@ func (r *FrontProxyCACertificate) ShouldCleanup(plane *kamajiv1alpha1.TenantCont
|
||||
return false
|
||||
}
|
||||
|
||||
func (r *FrontProxyCACertificate) CleanUp(ctx context.Context) (bool, error) {
|
||||
func (r *FrontProxyCACertificate) CleanUp(ctx context.Context, tenantControlPlane *kamajiv1alpha1.TenantControlPlane) (bool, error) {
|
||||
return false, nil
|
||||
}
|
||||
|
||||
|
||||
@@ -48,7 +48,7 @@ func (r *KubernetesDeploymentResource) ShouldCleanup(plane *kamajiv1alpha1.Tenan
|
||||
return false
|
||||
}
|
||||
|
||||
func (r *KubernetesDeploymentResource) CleanUp(ctx context.Context) (bool, error) {
|
||||
func (r *KubernetesDeploymentResource) CleanUp(ctx context.Context, tenantControlPlane *kamajiv1alpha1.TenantControlPlane) (bool, error) {
|
||||
return false, nil
|
||||
}
|
||||
|
||||
|
||||
@@ -33,7 +33,7 @@ func (r *KubernetesIngressResource) ShouldCleanup(tenantControlPlane *kamajiv1al
|
||||
return !tenantControlPlane.Spec.ControlPlane.Ingress.Enabled
|
||||
}
|
||||
|
||||
func (r *KubernetesIngressResource) CleanUp(ctx context.Context) (bool, error) {
|
||||
func (r *KubernetesIngressResource) CleanUp(ctx context.Context, tenantControlPlane *kamajiv1alpha1.TenantControlPlane) (bool, error) {
|
||||
if err := r.Client.Delete(ctx, r.resource); err != nil {
|
||||
if !k8serrors.IsNotFound(err) {
|
||||
return false, err
|
||||
|
||||
@@ -34,7 +34,7 @@ func (r *KubernetesServiceResource) ShouldCleanup(plane *kamajiv1alpha1.TenantCo
|
||||
return false
|
||||
}
|
||||
|
||||
func (r *KubernetesServiceResource) CleanUp(ctx context.Context) (bool, error) {
|
||||
func (r *KubernetesServiceResource) CleanUp(ctx context.Context, tenantControlPlane *kamajiv1alpha1.TenantControlPlane) (bool, error) {
|
||||
return false, nil
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,185 @@
|
||||
// Copyright 2022 Clastix Labs
|
||||
// SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
package resources
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
|
||||
"github.com/go-logr/logr"
|
||||
k8serrors "k8s.io/apimachinery/pkg/api/errors"
|
||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
clientset "k8s.io/client-go/kubernetes"
|
||||
"sigs.k8s.io/controller-runtime/pkg/client"
|
||||
"sigs.k8s.io/controller-runtime/pkg/controller/controllerutil"
|
||||
|
||||
kamajiapi "github.com/clastix/kamaji/api"
|
||||
kamajiv1alpha1 "github.com/clastix/kamaji/api/v1alpha1"
|
||||
"github.com/clastix/kamaji/internal/kubeadm"
|
||||
)
|
||||
|
||||
type KubeadmAddon int
|
||||
|
||||
const (
|
||||
AddonCoreDNS KubeadmAddon = iota
|
||||
AddonKubeProxy
|
||||
)
|
||||
|
||||
func (d KubeadmAddon) String() string {
|
||||
return [...]string{"PhaseAddonCoreDNS", "PhaseAddonKubeProxy"}[d]
|
||||
}
|
||||
|
||||
type KubeadmAddonResource struct {
|
||||
Client client.Client
|
||||
Log logr.Logger
|
||||
Name string
|
||||
KubeadmAddon KubeadmAddon
|
||||
kubeadmConfigResourceVersion string
|
||||
}
|
||||
|
||||
func (r *KubeadmAddonResource) isStatusEqual(tenantControlPlane *kamajiv1alpha1.TenantControlPlane) bool {
|
||||
addonSpec, err := r.getSpec(tenantControlPlane)
|
||||
if err != nil {
|
||||
return false
|
||||
}
|
||||
|
||||
i, err := r.GetStatus(tenantControlPlane)
|
||||
if err != nil {
|
||||
return false
|
||||
}
|
||||
|
||||
addonStatus, ok := i.(*kamajiv1alpha1.AddonStatus)
|
||||
if !ok {
|
||||
return false
|
||||
}
|
||||
|
||||
return *addonSpec.Enabled == addonStatus.Enabled
|
||||
}
|
||||
|
||||
func (r *KubeadmAddonResource) SetKubeadmConfigResourceVersion(rv string) {
|
||||
r.kubeadmConfigResourceVersion = rv
|
||||
}
|
||||
|
||||
func (r *KubeadmAddonResource) ShouldStatusBeUpdated(ctx context.Context, tenantControlPlane *kamajiv1alpha1.TenantControlPlane) bool {
|
||||
return !r.isStatusEqual(tenantControlPlane)
|
||||
}
|
||||
|
||||
func (r *KubeadmAddonResource) ShouldCleanup(tenantControlPlane *kamajiv1alpha1.TenantControlPlane) bool {
|
||||
spec, err := r.getSpec(tenantControlPlane)
|
||||
if err != nil {
|
||||
return false
|
||||
}
|
||||
|
||||
return !*spec.Enabled
|
||||
}
|
||||
|
||||
func (r *KubeadmAddonResource) CleanUp(ctx context.Context, tenantControlPlane *kamajiv1alpha1.TenantControlPlane) (bool, error) {
|
||||
client, err := GetRESTClient(ctx, r, tenantControlPlane)
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
|
||||
fun, err := r.getRemoveAddonFunction()
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
|
||||
if err := fun(ctx, client); err != nil {
|
||||
if !k8serrors.IsNotFound(err) {
|
||||
return false, err
|
||||
}
|
||||
|
||||
return false, nil
|
||||
}
|
||||
|
||||
return true, nil
|
||||
}
|
||||
|
||||
func (r *KubeadmAddonResource) Define(ctx context.Context, tenantControlPlane *kamajiv1alpha1.TenantControlPlane) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (r *KubeadmAddonResource) GetKubeadmFunction() (func(clientset.Interface, *kubeadm.Configuration) error, error) {
|
||||
switch r.KubeadmAddon {
|
||||
case AddonCoreDNS:
|
||||
return kubeadm.AddCoreDNS, nil
|
||||
case AddonKubeProxy:
|
||||
return kubeadm.AddKubeProxy, nil
|
||||
|
||||
default:
|
||||
return nil, fmt.Errorf("no available functionality for phase %s", r.KubeadmAddon)
|
||||
}
|
||||
}
|
||||
|
||||
func (r *KubeadmAddonResource) getRemoveAddonFunction() (func(context.Context, clientset.Interface) error, error) {
|
||||
switch r.KubeadmAddon {
|
||||
case AddonCoreDNS:
|
||||
return kubeadm.RemoveCoreDNSAddon, nil
|
||||
case AddonKubeProxy:
|
||||
return kubeadm.RemoveKubeProxy, nil
|
||||
default:
|
||||
return nil, fmt.Errorf("no available functionality for removing addon %s", r.KubeadmAddon)
|
||||
}
|
||||
}
|
||||
|
||||
func (r *KubeadmAddonResource) GetClient() client.Client {
|
||||
return r.Client
|
||||
}
|
||||
|
||||
func (r *KubeadmAddonResource) GetTmpDirectory() string {
|
||||
return ""
|
||||
}
|
||||
|
||||
func (r *KubeadmAddonResource) GetName() string {
|
||||
return r.Name
|
||||
}
|
||||
|
||||
func (r *KubeadmAddonResource) UpdateTenantControlPlaneStatus(ctx context.Context, tenantControlPlane *kamajiv1alpha1.TenantControlPlane) error {
|
||||
i, err := r.GetStatus(tenantControlPlane)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
addonSpec, err := r.getSpec(tenantControlPlane)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
status, ok := i.(*kamajiv1alpha1.AddonStatus)
|
||||
if !ok {
|
||||
return fmt.Errorf("error addon status")
|
||||
}
|
||||
|
||||
status.Enabled = *addonSpec.Enabled
|
||||
status.LastUpdate = metav1.Now()
|
||||
status.KubeadmConfigResourceVersion = r.kubeadmConfigResourceVersion
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (r *KubeadmAddonResource) GetStatus(tenantControlPlane *kamajiv1alpha1.TenantControlPlane) (kamajiapi.KubeadmConfigResourceVersionDependant, error) {
|
||||
switch r.KubeadmAddon {
|
||||
case AddonCoreDNS:
|
||||
return &tenantControlPlane.Status.Addons.CoreDNS, nil
|
||||
case AddonKubeProxy:
|
||||
return &tenantControlPlane.Status.Addons.KubeProxy, nil
|
||||
default:
|
||||
return nil, fmt.Errorf("%s has no addon status", r.KubeadmAddon)
|
||||
}
|
||||
}
|
||||
|
||||
func (r *KubeadmAddonResource) getSpec(tenantControlPlane *kamajiv1alpha1.TenantControlPlane) (*kamajiv1alpha1.AddonSpec, error) {
|
||||
switch r.KubeadmAddon {
|
||||
case AddonCoreDNS:
|
||||
return &tenantControlPlane.Spec.Addons.CoreDNS, nil
|
||||
case AddonKubeProxy:
|
||||
return &tenantControlPlane.Spec.Addons.KubeProxy, nil
|
||||
default:
|
||||
return nil, fmt.Errorf("%s has no spec", r.KubeadmAddon)
|
||||
}
|
||||
}
|
||||
|
||||
func (r *KubeadmAddonResource) CreateOrUpdate(ctx context.Context, tenantControlPlane *kamajiv1alpha1.TenantControlPlane) (controllerutil.OperationResult, error) {
|
||||
return KubeadmPhaseCreate(ctx, r, tenantControlPlane)
|
||||
}
|
||||
@@ -51,7 +51,7 @@ func (r *KubeadmConfigResource) ShouldCleanup(plane *kamajiv1alpha1.TenantContro
|
||||
return false
|
||||
}
|
||||
|
||||
func (r *KubeadmConfigResource) CleanUp(ctx context.Context) (bool, error) {
|
||||
func (r *KubeadmConfigResource) CleanUp(ctx context.Context, tenantControlPlane *kamajiv1alpha1.TenantControlPlane) (bool, error) {
|
||||
return false, nil
|
||||
}
|
||||
|
||||
|
||||
@@ -6,86 +6,81 @@ package resources
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"time"
|
||||
|
||||
"github.com/go-logr/logr"
|
||||
corev1 "k8s.io/api/core/v1"
|
||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
k8stypes "k8s.io/apimachinery/pkg/types"
|
||||
clientset "k8s.io/client-go/kubernetes"
|
||||
restclient "k8s.io/client-go/rest"
|
||||
bootstraptokenv1 "k8s.io/kubernetes/cmd/kubeadm/app/apis/bootstraptoken/v1"
|
||||
"sigs.k8s.io/controller-runtime/pkg/client"
|
||||
"sigs.k8s.io/controller-runtime/pkg/controller/controllerutil"
|
||||
|
||||
kamajiapi "github.com/clastix/kamaji/api"
|
||||
kamajiv1alpha1 "github.com/clastix/kamaji/api/v1alpha1"
|
||||
"github.com/clastix/kamaji/internal/kubeadm"
|
||||
kubeconfigutil "github.com/clastix/kamaji/internal/kubeconfig"
|
||||
)
|
||||
|
||||
type kubeadmPhase int
|
||||
|
||||
const kubeadmPhaseTimeout = 10 // seconds
|
||||
|
||||
type KubeadmPhase int
|
||||
|
||||
const (
|
||||
PhaseUploadConfigKubeadm KubeadmPhase = iota
|
||||
PhaseUploadConfigKubeadm kubeadmPhase = iota
|
||||
PhaseUploadConfigKubelet
|
||||
PhaseAddonCoreDNS
|
||||
PhaseAddonKubeProxy
|
||||
PhaseBootstrapToken
|
||||
)
|
||||
|
||||
func (d KubeadmPhase) String() string {
|
||||
func (d kubeadmPhase) String() string {
|
||||
return [...]string{"PhaseUploadConfigKubeadm", "PhaseUploadConfigKubelet", "PhaseAddonCoreDNS", "PhaseAddonKubeProxy", "PhaseBootstrapToken"}[d]
|
||||
}
|
||||
|
||||
const (
|
||||
kubeconfigAdminKeyName = "admin.conf"
|
||||
)
|
||||
|
||||
type KubeadmPhaseResource struct {
|
||||
type KubeadmPhase struct {
|
||||
Client client.Client
|
||||
Log logr.Logger
|
||||
Name string
|
||||
KubeadmPhase KubeadmPhase
|
||||
Phase kubeadmPhase
|
||||
kubeadmConfigResourceVersion string
|
||||
}
|
||||
|
||||
func (r *KubeadmPhaseResource) isStatusEqual(tenantControlPlane *kamajiv1alpha1.TenantControlPlane) bool {
|
||||
status, err := r.getStatus(tenantControlPlane)
|
||||
func (r *KubeadmPhase) isStatusEqual(tenantControlPlane *kamajiv1alpha1.TenantControlPlane) bool {
|
||||
i, err := r.GetStatus(tenantControlPlane)
|
||||
if err != nil {
|
||||
return true
|
||||
}
|
||||
|
||||
status, ok := i.(*kamajiv1alpha1.KubeadmPhaseStatus)
|
||||
if !ok {
|
||||
return false
|
||||
}
|
||||
|
||||
return status.KubeadmConfigResourceVersion == r.kubeadmConfigResourceVersion
|
||||
}
|
||||
|
||||
func (r *KubeadmPhaseResource) ShouldStatusBeUpdated(ctx context.Context, tenantControlPlane *kamajiv1alpha1.TenantControlPlane) bool {
|
||||
func (r *KubeadmPhase) SetKubeadmConfigResourceVersion(rv string) {
|
||||
r.kubeadmConfigResourceVersion = rv
|
||||
}
|
||||
|
||||
func (r *KubeadmPhase) ShouldStatusBeUpdated(ctx context.Context, tenantControlPlane *kamajiv1alpha1.TenantControlPlane) bool {
|
||||
return !r.isStatusEqual(tenantControlPlane)
|
||||
}
|
||||
|
||||
func (r *KubeadmPhaseResource) ShouldCleanup(plane *kamajiv1alpha1.TenantControlPlane) bool {
|
||||
func (r *KubeadmPhase) ShouldCleanup(tenantControlPlane *kamajiv1alpha1.TenantControlPlane) bool {
|
||||
return false
|
||||
}
|
||||
|
||||
func (r *KubeadmPhaseResource) CleanUp(ctx context.Context) (bool, error) {
|
||||
func (r *KubeadmPhase) CleanUp(ctx context.Context, tenantControlPlane *kamajiv1alpha1.TenantControlPlane) (bool, error) {
|
||||
return false, nil
|
||||
}
|
||||
|
||||
func (r *KubeadmPhaseResource) Define(ctx context.Context, tenantControlPlane *kamajiv1alpha1.TenantControlPlane) error {
|
||||
func (r *KubeadmPhase) Define(ctx context.Context, tenantControlPlane *kamajiv1alpha1.TenantControlPlane) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (r *KubeadmPhaseResource) getKubeadmPhaseFunction() (func(clientset.Interface, *kubeadm.Configuration) error, error) {
|
||||
switch r.KubeadmPhase {
|
||||
func (r *KubeadmPhase) GetKubeadmFunction() (func(clientset.Interface, *kubeadm.Configuration) error, error) {
|
||||
switch r.Phase {
|
||||
case PhaseUploadConfigKubeadm:
|
||||
return kubeadm.UploadKubeadmConfig, nil
|
||||
case PhaseUploadConfigKubelet:
|
||||
return kubeadm.UploadKubeletConfig, nil
|
||||
case PhaseAddonCoreDNS:
|
||||
return kubeadm.CoreDNSAddon, nil
|
||||
case PhaseAddonKubeProxy:
|
||||
return kubeadm.KubeProxyAddon, nil
|
||||
case PhaseBootstrapToken:
|
||||
return func(client clientset.Interface, config *kubeadm.Configuration) error {
|
||||
bootstrapTokensEnrichment(config.InitConfiguration.BootstrapTokens)
|
||||
@@ -93,7 +88,7 @@ func (r *KubeadmPhaseResource) getKubeadmPhaseFunction() (func(clientset.Interfa
|
||||
return kubeadm.BootstrapToken(client, config)
|
||||
}, nil
|
||||
default:
|
||||
return nil, fmt.Errorf("no available functionality for phase %s", r.KubeadmPhase)
|
||||
return nil, fmt.Errorf("no available functionality for phase %s", r.Phase)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -117,155 +112,48 @@ func enrichBootstrapToken(bootstrapToken *bootstraptokenv1.BootstrapToken) {
|
||||
}
|
||||
}
|
||||
|
||||
func (r *KubeadmPhaseResource) GetClient() client.Client {
|
||||
func (r *KubeadmPhase) GetClient() client.Client {
|
||||
return r.Client
|
||||
}
|
||||
|
||||
func (r *KubeadmPhaseResource) GetTmpDirectory() string {
|
||||
func (r *KubeadmPhase) GetTmpDirectory() string {
|
||||
return ""
|
||||
}
|
||||
|
||||
func (r *KubeadmPhaseResource) GetName() string {
|
||||
func (r *KubeadmPhase) GetName() string {
|
||||
return r.Name
|
||||
}
|
||||
|
||||
func (r *KubeadmPhaseResource) UpdateTenantControlPlaneStatus(ctx context.Context, tenantControlPlane *kamajiv1alpha1.TenantControlPlane) error {
|
||||
status, err := r.getStatus(tenantControlPlane)
|
||||
func (r *KubeadmPhase) UpdateTenantControlPlaneStatus(ctx context.Context, tenantControlPlane *kamajiv1alpha1.TenantControlPlane) error {
|
||||
i, err := r.GetStatus(tenantControlPlane)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
status.LastUpdate = metav1.Now()
|
||||
status.KubeadmConfigResourceVersion = r.kubeadmConfigResourceVersion
|
||||
kubeadmStatus, ok := i.(*kamajiv1alpha1.KubeadmPhaseStatus)
|
||||
if !ok {
|
||||
return fmt.Errorf("error status kubeadm phase")
|
||||
}
|
||||
|
||||
kubeadmStatus.LastUpdate = metav1.Now()
|
||||
kubeadmStatus.KubeadmConfigResourceVersion = r.kubeadmConfigResourceVersion
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (r *KubeadmPhaseResource) getStatus(tenantControlPlane *kamajiv1alpha1.TenantControlPlane) (*kamajiv1alpha1.KubeadmPhaseStatus, error) {
|
||||
switch r.KubeadmPhase {
|
||||
func (r *KubeadmPhase) GetStatus(tenantControlPlane *kamajiv1alpha1.TenantControlPlane) (kamajiapi.KubeadmConfigResourceVersionDependant, error) {
|
||||
switch r.Phase {
|
||||
case PhaseUploadConfigKubeadm:
|
||||
return &tenantControlPlane.Status.KubeadmPhase.UploadConfigKubeadm, nil
|
||||
case PhaseUploadConfigKubelet:
|
||||
return &tenantControlPlane.Status.KubeadmPhase.UploadConfigKubelet, nil
|
||||
case PhaseAddonCoreDNS:
|
||||
return &tenantControlPlane.Status.KubeadmPhase.AddonCoreDNS, nil
|
||||
case PhaseAddonKubeProxy:
|
||||
return &tenantControlPlane.Status.KubeadmPhase.AddonKubeProxy, nil
|
||||
case PhaseBootstrapToken:
|
||||
return &tenantControlPlane.Status.KubeadmPhase.BootstrapToken, nil
|
||||
default:
|
||||
return nil, fmt.Errorf("%s is not a right kubeadm phase", r.KubeadmPhase)
|
||||
return nil, fmt.Errorf("%s is not a right kubeadm phase", r.Phase)
|
||||
}
|
||||
}
|
||||
|
||||
func (r *KubeadmPhaseResource) CreateOrUpdate(ctx context.Context, tenantControlPlane *kamajiv1alpha1.TenantControlPlane) (controllerutil.OperationResult, error) {
|
||||
return r.reconcile(ctx, tenantControlPlane)
|
||||
}
|
||||
|
||||
func (r *KubeadmPhaseResource) reconcile(ctx context.Context, tenantControlPlane *kamajiv1alpha1.TenantControlPlane) (controllerutil.OperationResult, error) {
|
||||
config, resourceVersion, err := getKubeadmConfiguration(ctx, r, tenantControlPlane)
|
||||
if err != nil {
|
||||
return controllerutil.OperationResultNone, err
|
||||
}
|
||||
|
||||
kubeconfig, err := r.getKubeconfig(ctx, tenantControlPlane)
|
||||
if err != nil {
|
||||
return controllerutil.OperationResultNone, err
|
||||
}
|
||||
|
||||
config.Kubeconfig = *kubeconfig
|
||||
config.Parameters = kubeadm.Parameters{
|
||||
TenantControlPlaneName: tenantControlPlane.GetName(),
|
||||
TenantDNSServiceIPs: tenantControlPlane.Spec.NetworkProfile.DNSServiceIPs,
|
||||
TenantControlPlaneVersion: tenantControlPlane.Spec.Kubernetes.Version,
|
||||
TenantControlPlanePodCIDR: tenantControlPlane.Spec.NetworkProfile.PodCIDR,
|
||||
TenantControlPlaneAddress: tenantControlPlane.Spec.NetworkProfile.Address,
|
||||
TenantControlPlanePort: tenantControlPlane.Spec.NetworkProfile.Port,
|
||||
TenantControlPlaneCGroupDriver: tenantControlPlane.Spec.Kubernetes.Kubelet.CGroupFS.String(),
|
||||
}
|
||||
|
||||
status, err := r.getStatus(tenantControlPlane)
|
||||
if err != nil {
|
||||
return controllerutil.OperationResultNone, err
|
||||
}
|
||||
|
||||
if resourceVersion == status.KubeadmConfigResourceVersion {
|
||||
r.kubeadmConfigResourceVersion = resourceVersion
|
||||
|
||||
return controllerutil.OperationResultNone, nil
|
||||
}
|
||||
|
||||
client, err := r.getRESTClient(ctx, tenantControlPlane)
|
||||
if err != nil {
|
||||
return controllerutil.OperationResultNone, err
|
||||
}
|
||||
|
||||
fun, err := r.getKubeadmPhaseFunction()
|
||||
if err != nil {
|
||||
return controllerutil.OperationResultNone, err
|
||||
}
|
||||
if err = fun(client, config); err != nil {
|
||||
return controllerutil.OperationResultNone, err
|
||||
}
|
||||
|
||||
r.kubeadmConfigResourceVersion = resourceVersion
|
||||
|
||||
if status.LastUpdate.IsZero() {
|
||||
return controllerutil.OperationResultCreated, nil
|
||||
}
|
||||
|
||||
return controllerutil.OperationResultUpdated, nil
|
||||
}
|
||||
|
||||
func (r *KubeadmPhaseResource) getKubeconfigSecret(ctx context.Context, tenantControlPlane *kamajiv1alpha1.TenantControlPlane) (*corev1.Secret, error) {
|
||||
kubeconfigSecretName := tenantControlPlane.Status.KubeConfig.Admin.SecretName
|
||||
namespacedName := k8stypes.NamespacedName{Namespace: tenantControlPlane.GetNamespace(), Name: kubeconfigSecretName}
|
||||
secret := &corev1.Secret{}
|
||||
if err := r.Client.Get(ctx, namespacedName, secret); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return secret, nil
|
||||
}
|
||||
|
||||
func (r *KubeadmPhaseResource) getKubeconfig(ctx context.Context, tenantControlPlane *kamajiv1alpha1.TenantControlPlane) (*kubeconfigutil.Kubeconfig, error) {
|
||||
secretKubeconfig, err := r.getKubeconfigSecret(ctx, tenantControlPlane)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
bytes, ok := secretKubeconfig.Data[kubeconfigAdminKeyName]
|
||||
if !ok {
|
||||
return nil, fmt.Errorf("%s is not into kubeconfig secret", kubeconfigAdminKeyName)
|
||||
}
|
||||
|
||||
return kubeconfigutil.GetKubeconfigFromBytes(bytes)
|
||||
}
|
||||
|
||||
func (r *KubeadmPhaseResource) getRESTClient(ctx context.Context, tenantControlPlane *kamajiv1alpha1.TenantControlPlane) (*clientset.Clientset, error) {
|
||||
config, err := r.getRESTClientConfig(ctx, tenantControlPlane)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return clientset.NewForConfig(config)
|
||||
}
|
||||
|
||||
func (r *KubeadmPhaseResource) getRESTClientConfig(ctx context.Context, tenantControlPlane *kamajiv1alpha1.TenantControlPlane) (*restclient.Config, error) {
|
||||
kubeconfig, err := r.getKubeconfig(ctx, tenantControlPlane)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
config := &restclient.Config{
|
||||
Host: fmt.Sprintf("https://%s:%d", getTenantControllerInternalFQDN(*tenantControlPlane), tenantControlPlane.Spec.NetworkProfile.Port),
|
||||
TLSClientConfig: restclient.TLSClientConfig{
|
||||
CAData: kubeconfig.Clusters[0].Cluster.CertificateAuthorityData,
|
||||
CertData: kubeconfig.AuthInfos[0].AuthInfo.ClientCertificateData,
|
||||
KeyData: kubeconfig.AuthInfos[0].AuthInfo.ClientKeyData,
|
||||
},
|
||||
Timeout: time.Second * kubeadmPhaseTimeout,
|
||||
}
|
||||
|
||||
return config, nil
|
||||
func (r *KubeadmPhase) CreateOrUpdate(ctx context.Context, tenantControlPlane *kamajiv1alpha1.TenantControlPlane) (controllerutil.OperationResult, error) {
|
||||
return KubeadmPhaseCreate(ctx, r, tenantControlPlane)
|
||||
}
|
||||
|
||||
@@ -48,7 +48,7 @@ func (k *KubernetesUpgrade) ShouldCleanup(*kamajiv1alpha1.TenantControlPlane) bo
|
||||
return false
|
||||
}
|
||||
|
||||
func (k *KubernetesUpgrade) CleanUp(context.Context) (bool, error) {
|
||||
func (k *KubernetesUpgrade) CleanUp(context.Context, *kamajiv1alpha1.TenantControlPlane) (bool, error) {
|
||||
return false, nil
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,126 @@
|
||||
package resources
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"time"
|
||||
|
||||
corev1 "k8s.io/api/core/v1"
|
||||
k8stypes "k8s.io/apimachinery/pkg/types"
|
||||
clientset "k8s.io/client-go/kubernetes"
|
||||
restclient "k8s.io/client-go/rest"
|
||||
"sigs.k8s.io/controller-runtime/pkg/controller/controllerutil"
|
||||
|
||||
kamajiv1alpha1 "github.com/clastix/kamaji/api/v1alpha1"
|
||||
"github.com/clastix/kamaji/internal/kubeadm"
|
||||
kubeconfigutil "github.com/clastix/kamaji/internal/kubeconfig"
|
||||
)
|
||||
|
||||
func KubeadmPhaseCreate(ctx context.Context, r KubeadmPhaseResource, tenantControlPlane *kamajiv1alpha1.TenantControlPlane) (controllerutil.OperationResult, error) {
|
||||
config, resourceVersion, err := getKubeadmConfiguration(ctx, r, tenantControlPlane)
|
||||
if err != nil {
|
||||
return controllerutil.OperationResultNone, err
|
||||
}
|
||||
|
||||
kubeconfig, err := getKubeconfig(ctx, r, tenantControlPlane)
|
||||
if err != nil {
|
||||
return controllerutil.OperationResultNone, err
|
||||
}
|
||||
|
||||
config.Kubeconfig = *kubeconfig
|
||||
config.Parameters = kubeadm.Parameters{
|
||||
TenantControlPlaneName: tenantControlPlane.GetName(),
|
||||
TenantDNSServiceIPs: tenantControlPlane.Spec.NetworkProfile.DNSServiceIPs,
|
||||
TenantControlPlaneVersion: tenantControlPlane.Spec.Kubernetes.Version,
|
||||
TenantControlPlanePodCIDR: tenantControlPlane.Spec.NetworkProfile.PodCIDR,
|
||||
TenantControlPlaneAddress: tenantControlPlane.Spec.NetworkProfile.Address,
|
||||
TenantControlPlanePort: tenantControlPlane.Spec.NetworkProfile.Port,
|
||||
TenantControlPlaneCGroupDriver: tenantControlPlane.Spec.Kubernetes.Kubelet.CGroupFS.String(),
|
||||
}
|
||||
|
||||
status, err := r.GetStatus(tenantControlPlane)
|
||||
if err != nil {
|
||||
return controllerutil.OperationResultNone, err
|
||||
}
|
||||
|
||||
storedResourceVersion := status.GetKubeadmConfigResourceVersion()
|
||||
if resourceVersion == storedResourceVersion {
|
||||
r.SetKubeadmConfigResourceVersion(resourceVersion)
|
||||
|
||||
return controllerutil.OperationResultNone, nil
|
||||
}
|
||||
|
||||
client, err := GetRESTClient(ctx, r, tenantControlPlane)
|
||||
if err != nil {
|
||||
return controllerutil.OperationResultNone, err
|
||||
}
|
||||
|
||||
fun, err := r.GetKubeadmFunction()
|
||||
if err != nil {
|
||||
return controllerutil.OperationResultNone, err
|
||||
}
|
||||
if err = fun(client, config); err != nil {
|
||||
return controllerutil.OperationResultNone, err
|
||||
}
|
||||
|
||||
r.SetKubeadmConfigResourceVersion(resourceVersion)
|
||||
|
||||
if storedResourceVersion == "" {
|
||||
return controllerutil.OperationResultCreated, nil
|
||||
}
|
||||
|
||||
return controllerutil.OperationResultUpdated, nil
|
||||
}
|
||||
|
||||
func getKubeconfigSecret(ctx context.Context, r KubeadmPhaseResource, tenantControlPlane *kamajiv1alpha1.TenantControlPlane) (*corev1.Secret, error) {
|
||||
kubeconfigSecretName := tenantControlPlane.Status.KubeConfig.Admin.SecretName
|
||||
namespacedName := k8stypes.NamespacedName{Namespace: tenantControlPlane.GetNamespace(), Name: kubeconfigSecretName}
|
||||
secret := &corev1.Secret{}
|
||||
if err := r.GetClient().Get(ctx, namespacedName, secret); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return secret, nil
|
||||
}
|
||||
|
||||
func getKubeconfig(ctx context.Context, r KubeadmPhaseResource, tenantControlPlane *kamajiv1alpha1.TenantControlPlane) (*kubeconfigutil.Kubeconfig, error) {
|
||||
secretKubeconfig, err := getKubeconfigSecret(ctx, r, tenantControlPlane)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
bytes, ok := secretKubeconfig.Data[kubeconfigAdminKeyName]
|
||||
if !ok {
|
||||
return nil, fmt.Errorf("%s is not into kubeconfig secret", kubeconfigAdminKeyName)
|
||||
}
|
||||
|
||||
return kubeconfigutil.GetKubeconfigFromBytes(bytes)
|
||||
}
|
||||
|
||||
func GetRESTClient(ctx context.Context, r KubeadmPhaseResource, tenantControlPlane *kamajiv1alpha1.TenantControlPlane) (*clientset.Clientset, error) {
|
||||
config, err := getRESTClientConfig(ctx, r, tenantControlPlane)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return clientset.NewForConfig(config)
|
||||
}
|
||||
|
||||
func getRESTClientConfig(ctx context.Context, r KubeadmPhaseResource, tenantControlPlane *kamajiv1alpha1.TenantControlPlane) (*restclient.Config, error) {
|
||||
kubeconfig, err := getKubeconfig(ctx, r, tenantControlPlane)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
config := &restclient.Config{
|
||||
Host: fmt.Sprintf("https://%s:%d", getTenantControllerInternalFQDN(*tenantControlPlane), tenantControlPlane.Spec.NetworkProfile.Port),
|
||||
TLSClientConfig: restclient.TLSClientConfig{
|
||||
CAData: kubeconfig.Clusters[0].Cluster.CertificateAuthorityData,
|
||||
CertData: kubeconfig.AuthInfos[0].AuthInfo.ClientCertificateData,
|
||||
KeyData: kubeconfig.AuthInfos[0].AuthInfo.ClientKeyData,
|
||||
},
|
||||
Timeout: time.Second * kubeadmPhaseTimeout,
|
||||
}
|
||||
|
||||
return config, nil
|
||||
}
|
||||
@@ -47,7 +47,7 @@ func (r *KubeconfigResource) ShouldCleanup(plane *kamajiv1alpha1.TenantControlPl
|
||||
return false
|
||||
}
|
||||
|
||||
func (r *KubeconfigResource) CleanUp(ctx context.Context) (bool, error) {
|
||||
func (r *KubeconfigResource) CleanUp(ctx context.Context, tenantControlPlane *kamajiv1alpha1.TenantControlPlane) (bool, error) {
|
||||
return false, nil
|
||||
}
|
||||
|
||||
|
||||
@@ -8,9 +8,11 @@ import (
|
||||
|
||||
corev1 "k8s.io/api/core/v1"
|
||||
k8stypes "k8s.io/apimachinery/pkg/types"
|
||||
clientset "k8s.io/client-go/kubernetes"
|
||||
"sigs.k8s.io/controller-runtime/pkg/client"
|
||||
"sigs.k8s.io/controller-runtime/pkg/controller/controllerutil"
|
||||
|
||||
kamajiapi "github.com/clastix/kamaji/api"
|
||||
kamajiv1alpha1 "github.com/clastix/kamaji/api/v1alpha1"
|
||||
"github.com/clastix/kamaji/internal/kubeadm"
|
||||
)
|
||||
@@ -18,7 +20,7 @@ import (
|
||||
type Resource interface {
|
||||
Define(context.Context, *kamajiv1alpha1.TenantControlPlane) error
|
||||
ShouldCleanup(*kamajiv1alpha1.TenantControlPlane) bool
|
||||
CleanUp(context.Context) (bool, error)
|
||||
CleanUp(context.Context, *kamajiv1alpha1.TenantControlPlane) (bool, error)
|
||||
CreateOrUpdate(context.Context, *kamajiv1alpha1.TenantControlPlane) (controllerutil.OperationResult, error)
|
||||
GetName() string
|
||||
ShouldStatusBeUpdated(context.Context, *kamajiv1alpha1.TenantControlPlane) bool
|
||||
@@ -35,6 +37,14 @@ type KubeadmResource interface {
|
||||
GetTmpDirectory() string
|
||||
}
|
||||
|
||||
type KubeadmPhaseResource interface {
|
||||
KubeadmResource
|
||||
GetClient() client.Client
|
||||
GetKubeadmFunction() (func(clientset.Interface, *kubeadm.Configuration) error, error)
|
||||
GetStatus(*kamajiv1alpha1.TenantControlPlane) (kamajiapi.KubeadmConfigResourceVersionDependant, error)
|
||||
SetKubeadmConfigResourceVersion(string)
|
||||
}
|
||||
|
||||
type HandlerConfig struct {
|
||||
Resource Resource
|
||||
TenantControlPlane *kamajiv1alpha1.TenantControlPlane
|
||||
@@ -50,7 +60,7 @@ func Handle(ctx context.Context, resource Resource, tenantControlPlane *kamajiv1
|
||||
return createOrUpdate(ctx, resource, tenantControlPlane)
|
||||
}
|
||||
|
||||
cleanUp, err := resource.CleanUp(ctx)
|
||||
cleanUp, err := resource.CleanUp(ctx, tenantControlPlane)
|
||||
if err != nil {
|
||||
return controllerutil.OperationResultNone, err
|
||||
}
|
||||
|
||||
@@ -36,7 +36,7 @@ func (r *SACertificate) ShouldCleanup(plane *kamajiv1alpha1.TenantControlPlane)
|
||||
return false
|
||||
}
|
||||
|
||||
func (r *SACertificate) CleanUp(ctx context.Context) (bool, error) {
|
||||
func (r *SACertificate) CleanUp(ctx context.Context, tenantControlPlane *kamajiv1alpha1.TenantControlPlane) (bool, error) {
|
||||
return false, nil
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user