mirror of
https://github.com/clastix/kamaji.git
synced 2026-02-14 18:10:03 +00:00
Compare commits
3 Commits
edge-26.2.
...
master
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
830d56dac1 | ||
|
|
a9c2c0de89 | ||
|
|
b40428825d |
7
Makefile
7
Makefile
@@ -236,7 +236,12 @@ metallb:
|
||||
kubectl apply -f "https://raw.githubusercontent.com/metallb/metallb/$$(curl "https://api.github.com/repos/metallb/metallb/releases/latest" | jq -r ".tag_name")/config/manifests/metallb-native.yaml"
|
||||
kubectl wait pods -n metallb-system -l app=metallb,component=controller --for=condition=Ready --timeout=10m
|
||||
kubectl wait pods -n metallb-system -l app=metallb,component=speaker --for=condition=Ready --timeout=2m
|
||||
cat hack/metallb.yaml | sed -E "s|172.19|$$(docker network inspect -f '{{range .IPAM.Config}}{{.Gateway}}{{end}}' kind | sed -E 's|^([0-9]+\.[0-9]+)\..*$$|\1|g')|g" | kubectl apply -f -
|
||||
@IPV4_PREFIX=$$(docker network inspect kind \
|
||||
-f '{{range .IPAM.Config}}{{println .Subnet " " .Gateway}}{{end}}' \
|
||||
| grep -v ':' \
|
||||
| awk '{print $$2}' \
|
||||
| sed -E 's|^([0-9]+\.[0-9]+)\..*$$|\1|'); \
|
||||
sed -E "s|172\.19|$$IPV4_PREFIX|g" hack/metallb.yaml | kubectl apply -f -
|
||||
|
||||
cert-manager:
|
||||
$(HELM) repo add jetstack https://charts.jetstack.io
|
||||
|
||||
@@ -90,6 +90,9 @@ type SecretReference struct {
|
||||
|
||||
// DataStoreStatus defines the observed state of DataStore.
|
||||
type DataStoreStatus struct {
|
||||
// ObservedGeneration represents the .metadata.generation that was last reconciled.
|
||||
// +optional
|
||||
ObservedGeneration int64 `json:"observedGeneration,omitempty"`
|
||||
// List of the Tenant Control Planes, namespaced named, using this data store.
|
||||
UsedBy []string `json:"usedBy,omitempty"`
|
||||
}
|
||||
|
||||
@@ -66,6 +66,9 @@ type KubeconfigGeneratorStatusError struct {
|
||||
|
||||
// KubeconfigGeneratorStatus defines the observed state of KubeconfigGenerator.
|
||||
type KubeconfigGeneratorStatus struct {
|
||||
// ObservedGeneration represents the .metadata.generation that was last reconciled.
|
||||
// +optional
|
||||
ObservedGeneration int64 `json:"observedGeneration,omitempty"`
|
||||
// Resources is the sum of targeted TenantControlPlane objects.
|
||||
//+kubebuilder:default=0
|
||||
Resources int `json:"resources"`
|
||||
|
||||
@@ -10,7 +10,6 @@ import (
|
||||
"strconv"
|
||||
"strings"
|
||||
|
||||
"github.com/pkg/errors"
|
||||
corev1 "k8s.io/api/core/v1"
|
||||
"k8s.io/apimachinery/pkg/types"
|
||||
"sigs.k8s.io/controller-runtime/pkg/client"
|
||||
@@ -27,12 +26,12 @@ func (in *TenantControlPlane) AssignedControlPlaneAddress() (string, int32, erro
|
||||
|
||||
address, portString, err := net.SplitHostPort(in.Status.ControlPlaneEndpoint)
|
||||
if err != nil {
|
||||
return "", 0, errors.Wrap(err, "cannot split host port from Tenant Control Plane endpoint")
|
||||
return "", 0, fmt.Errorf("cannot split host port from Tenant Control Plane endpoint: %w", err)
|
||||
}
|
||||
|
||||
port, err := strconv.Atoi(portString)
|
||||
if err != nil {
|
||||
return "", 0, errors.Wrap(err, "cannot convert Tenant Control Plane port from endpoint")
|
||||
return "", 0, fmt.Errorf("cannot convert Tenant Control Plane port from endpoint: %w", err)
|
||||
}
|
||||
|
||||
return address, int32(port), nil
|
||||
@@ -47,7 +46,7 @@ func (in *TenantControlPlane) DeclaredControlPlaneAddress(ctx context.Context, c
|
||||
svc := &corev1.Service{}
|
||||
err := client.Get(ctx, types.NamespacedName{Namespace: in.GetNamespace(), Name: in.GetName()}, svc)
|
||||
if err != nil {
|
||||
return "", errors.Wrap(err, "cannot retrieve Service for the TenantControlPlane")
|
||||
return "", fmt.Errorf("cannot retrieve Service for the TenantControlPlane: %w", err)
|
||||
}
|
||||
|
||||
switch {
|
||||
|
||||
@@ -162,6 +162,9 @@ type AddonsStatus struct {
|
||||
|
||||
// TenantControlPlaneStatus defines the observed state of TenantControlPlane.
|
||||
type TenantControlPlaneStatus struct {
|
||||
// ObservedGeneration represents the .metadata.generation that was last reconciled.
|
||||
// +optional
|
||||
ObservedGeneration int64 `json:"observedGeneration,omitempty"`
|
||||
// Storage Status contains information about Kubernetes storage system
|
||||
Storage StorageStatus `json:"storage,omitempty"`
|
||||
// Certificates contains information about the different certificates
|
||||
|
||||
@@ -275,6 +275,10 @@ versions:
|
||||
status:
|
||||
description: DataStoreStatus defines the observed state of DataStore.
|
||||
properties:
|
||||
observedGeneration:
|
||||
description: ObservedGeneration represents the .metadata.generation that was last reconciled.
|
||||
format: int64
|
||||
type: integer
|
||||
usedBy:
|
||||
description: List of the Tenant Control Planes, namespaced named, using this data store.
|
||||
items:
|
||||
|
||||
@@ -199,6 +199,10 @@ versions:
|
||||
- resource
|
||||
type: object
|
||||
type: array
|
||||
observedGeneration:
|
||||
description: ObservedGeneration represents the .metadata.generation that was last reconciled.
|
||||
format: int64
|
||||
type: integer
|
||||
resources:
|
||||
default: 0
|
||||
description: Resources is the sum of targeted TenantControlPlane objects.
|
||||
|
||||
@@ -8788,6 +8788,10 @@ versions:
|
||||
type: string
|
||||
type: object
|
||||
type: object
|
||||
observedGeneration:
|
||||
description: ObservedGeneration represents the .metadata.generation that was last reconciled.
|
||||
format: int64
|
||||
type: integer
|
||||
storage:
|
||||
description: Storage Status contains information about Kubernetes storage system
|
||||
properties:
|
||||
|
||||
@@ -284,6 +284,10 @@ spec:
|
||||
status:
|
||||
description: DataStoreStatus defines the observed state of DataStore.
|
||||
properties:
|
||||
observedGeneration:
|
||||
description: ObservedGeneration represents the .metadata.generation that was last reconciled.
|
||||
format: int64
|
||||
type: integer
|
||||
usedBy:
|
||||
description: List of the Tenant Control Planes, namespaced named, using this data store.
|
||||
items:
|
||||
|
||||
@@ -207,6 +207,10 @@ spec:
|
||||
- resource
|
||||
type: object
|
||||
type: array
|
||||
observedGeneration:
|
||||
description: ObservedGeneration represents the .metadata.generation that was last reconciled.
|
||||
format: int64
|
||||
type: integer
|
||||
resources:
|
||||
default: 0
|
||||
description: Resources is the sum of targeted TenantControlPlane objects.
|
||||
|
||||
@@ -8796,6 +8796,10 @@ spec:
|
||||
type: string
|
||||
type: object
|
||||
type: object
|
||||
observedGeneration:
|
||||
description: ObservedGeneration represents the .metadata.generation that was last reconciled.
|
||||
format: int64
|
||||
type: integer
|
||||
storage:
|
||||
description: Storage Status contains information about Kubernetes storage system
|
||||
properties:
|
||||
|
||||
@@ -4,7 +4,8 @@
|
||||
package utils
|
||||
|
||||
import (
|
||||
"github.com/pkg/errors"
|
||||
"fmt"
|
||||
|
||||
"k8s.io/client-go/kubernetes"
|
||||
"k8s.io/client-go/rest"
|
||||
)
|
||||
@@ -12,12 +13,12 @@ import (
|
||||
func KubernetesVersion(config *rest.Config) (string, error) {
|
||||
cs, csErr := kubernetes.NewForConfig(config)
|
||||
if csErr != nil {
|
||||
return "", errors.Wrap(csErr, "cannot create kubernetes clientset")
|
||||
return "", fmt.Errorf("cannot create kubernetes clientset: %w", csErr)
|
||||
}
|
||||
|
||||
sv, svErr := cs.ServerVersion()
|
||||
if svErr != nil {
|
||||
return "", errors.Wrap(svErr, "cannot get Kubernetes version")
|
||||
return "", fmt.Errorf("cannot get Kubernetes version: %w", svErr)
|
||||
}
|
||||
|
||||
return sv.GitVersion, nil
|
||||
|
||||
@@ -9,7 +9,6 @@ import (
|
||||
"fmt"
|
||||
"time"
|
||||
|
||||
"github.com/pkg/errors"
|
||||
corev1 "k8s.io/api/core/v1"
|
||||
k8serrors "k8s.io/apimachinery/pkg/api/errors"
|
||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
@@ -168,7 +167,7 @@ func (s *CertificateLifecycle) extractCertificateFromKubeconfig(secret corev1.Se
|
||||
|
||||
crt, err := crypto.ParseCertificateBytes(kc.AuthInfos[0].AuthInfo.ClientCertificateData)
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "cannot parse kubeconfig certificate bytes")
|
||||
return nil, fmt.Errorf("cannot parse kubeconfig certificate bytes: %w", err)
|
||||
}
|
||||
|
||||
return crt, nil
|
||||
|
||||
@@ -5,8 +5,8 @@ package controllers
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
|
||||
"github.com/pkg/errors"
|
||||
k8serrors "k8s.io/apimachinery/pkg/api/errors"
|
||||
"k8s.io/apimachinery/pkg/fields"
|
||||
k8stypes "k8s.io/apimachinery/pkg/types"
|
||||
@@ -65,7 +65,7 @@ func (r *DataStore) Reconcile(ctx context.Context, request reconcile.Request) (r
|
||||
if lErr := r.Client.List(ctx, &tcpList, client.MatchingFieldsSelector{
|
||||
Selector: fields.OneTermEqualSelector(kamajiv1alpha1.TenantControlPlaneUsedDataStoreKey, ds.GetName()),
|
||||
}); lErr != nil {
|
||||
return errors.Wrap(lErr, "cannot retrieve list of the Tenant Control Plane using the following instance")
|
||||
return fmt.Errorf("cannot retrieve list of the Tenant Control Plane using the following instance: %w", lErr)
|
||||
}
|
||||
// Updating the status with the list of Tenant Control Plane using the following Data Source
|
||||
tcpSets := sets.NewString()
|
||||
@@ -73,10 +73,11 @@ func (r *DataStore) Reconcile(ctx context.Context, request reconcile.Request) (r
|
||||
tcpSets.Insert(getNamespacedName(tcp.GetNamespace(), tcp.GetName()).String())
|
||||
}
|
||||
|
||||
ds.Status.ObservedGeneration = ds.Generation
|
||||
ds.Status.UsedBy = tcpSets.List()
|
||||
|
||||
if sErr := r.Client.Status().Update(ctx, &ds); sErr != nil {
|
||||
return errors.Wrap(sErr, "cannot update the status for the given instance")
|
||||
return fmt.Errorf("cannot update the status for the given instance: %w", sErr)
|
||||
}
|
||||
|
||||
return nil
|
||||
|
||||
@@ -12,7 +12,6 @@ import (
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/pkg/errors"
|
||||
corev1 "k8s.io/api/core/v1"
|
||||
apierrors "k8s.io/apimachinery/pkg/api/errors"
|
||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
@@ -88,6 +87,7 @@ func (r *KubeconfigGeneratorReconciler) Reconcile(ctx context.Context, req ctrl.
|
||||
}
|
||||
|
||||
generator.Status = status
|
||||
generator.Status.ObservedGeneration = generator.Generation
|
||||
|
||||
if statusErr := r.Client.Status().Update(ctx, &generator); statusErr != nil {
|
||||
logger.Error(statusErr, "cannot update resource status")
|
||||
@@ -103,12 +103,12 @@ func (r *KubeconfigGeneratorReconciler) Reconcile(ctx context.Context, req ctrl.
|
||||
func (r *KubeconfigGeneratorReconciler) handle(ctx context.Context, generator *kamajiv1alpha1.KubeconfigGenerator) (kamajiv1alpha1.KubeconfigGeneratorStatus, error) {
|
||||
nsSelector, nsErr := metav1.LabelSelectorAsSelector(&generator.Spec.NamespaceSelector)
|
||||
if nsErr != nil {
|
||||
return kamajiv1alpha1.KubeconfigGeneratorStatus{}, errors.Wrap(nsErr, "NamespaceSelector contains an error")
|
||||
return kamajiv1alpha1.KubeconfigGeneratorStatus{}, fmt.Errorf("NamespaceSelector contains an error: %w", nsErr)
|
||||
}
|
||||
|
||||
var namespaceList corev1.NamespaceList
|
||||
if err := r.Client.List(ctx, &namespaceList, &client.ListOptions{LabelSelector: nsSelector}); err != nil {
|
||||
return kamajiv1alpha1.KubeconfigGeneratorStatus{}, errors.Wrap(err, "cannot filter Namespace objects using provided selector")
|
||||
return kamajiv1alpha1.KubeconfigGeneratorStatus{}, fmt.Errorf("cannot filter Namespace objects using provided selector: %w", err)
|
||||
}
|
||||
|
||||
var targets []kamajiv1alpha1.TenantControlPlane
|
||||
@@ -116,12 +116,12 @@ func (r *KubeconfigGeneratorReconciler) handle(ctx context.Context, generator *k
|
||||
for _, ns := range namespaceList.Items {
|
||||
tcpSelector, tcpErr := metav1.LabelSelectorAsSelector(&generator.Spec.TenantControlPlaneSelector)
|
||||
if tcpErr != nil {
|
||||
return kamajiv1alpha1.KubeconfigGeneratorStatus{}, errors.Wrap(tcpErr, "TenantControlPlaneSelector contains an error")
|
||||
return kamajiv1alpha1.KubeconfigGeneratorStatus{}, fmt.Errorf("TenantControlPlaneSelector contains an error: %w", tcpErr)
|
||||
}
|
||||
|
||||
var tcpList kamajiv1alpha1.TenantControlPlaneList
|
||||
if err := r.Client.List(ctx, &tcpList, &client.ListOptions{Namespace: ns.GetName(), LabelSelector: tcpSelector}); err != nil {
|
||||
return kamajiv1alpha1.KubeconfigGeneratorStatus{}, errors.Wrap(err, "cannot filter TenantControlPlane objects using provided selector")
|
||||
return kamajiv1alpha1.KubeconfigGeneratorStatus{}, fmt.Errorf("cannot filter TenantControlPlane objects using provided selector: %w", err)
|
||||
}
|
||||
|
||||
targets = append(targets, tcpList.Items...)
|
||||
@@ -290,17 +290,17 @@ func (r *KubeconfigGeneratorReconciler) generate(ctx context.Context, generator
|
||||
|
||||
var caSecret corev1.Secret
|
||||
if caErr := r.Client.Get(ctx, types.NamespacedName{Namespace: tcp.Namespace, Name: tcp.Status.Certificates.CA.SecretName}, &caSecret); caErr != nil {
|
||||
return errors.Wrap(caErr, "cannot retrieve Certificate Authority")
|
||||
return fmt.Errorf("cannot retrieve Certificate Authority: %w", caErr)
|
||||
}
|
||||
|
||||
caCert, crtErr := crypto.ParseCertificateBytes(caSecret.Data[kubeadmconstants.CACertName])
|
||||
if crtErr != nil {
|
||||
return errors.Wrap(crtErr, "cannot parse Certificate Authority certificate")
|
||||
return fmt.Errorf("cannot parse Certificate Authority certificate: %w", crtErr)
|
||||
}
|
||||
|
||||
caKey, keyErr := crypto.ParsePrivateKeyBytes(caSecret.Data[kubeadmconstants.CAKeyName])
|
||||
if keyErr != nil {
|
||||
return errors.Wrap(keyErr, "cannot parse Certificate Authority key")
|
||||
return fmt.Errorf("cannot parse Certificate Authority key: %w", keyErr)
|
||||
}
|
||||
|
||||
clientCert, clientKey, err := pkiutil.NewCertAndKey(caCert, caKey, &clientCertConfig)
|
||||
@@ -312,7 +312,7 @@ func (r *KubeconfigGeneratorReconciler) generate(ctx context.Context, generator
|
||||
tmpl.AuthInfos[name].AuthInfo.ClientCertificateData = pkiutil.EncodeCertPEM(clientCert)
|
||||
tmpl.AuthInfos[name].AuthInfo.ClientKeyData, err = keyutil.MarshalPrivateKeyToPEM(clientKey)
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "cannot marshal private key to PEM")
|
||||
return fmt.Errorf("cannot marshal private key to PEM: %w", err)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -341,7 +341,7 @@ func (r *KubeconfigGeneratorReconciler) generate(ctx context.Context, generator
|
||||
|
||||
secret.Data["value"], err = utilities.EncodeToYaml(tmpl)
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "cannot encode generated Kubeconfig to YAML")
|
||||
return fmt.Errorf("cannot encode generated Kubeconfig to YAML: %w", err)
|
||||
}
|
||||
|
||||
if utilities.IsRotationRequested(secret) {
|
||||
@@ -355,7 +355,7 @@ func (r *KubeconfigGeneratorReconciler) generate(ctx context.Context, generator
|
||||
return ctrl.SetControllerReference(tcp, secret, r.Client.Scheme())
|
||||
})
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "cannot create or update generated Kubeconfig")
|
||||
return fmt.Errorf("cannot create or update generated Kubeconfig: %w", err)
|
||||
}
|
||||
|
||||
return nil
|
||||
|
||||
@@ -5,9 +5,9 @@ package controllers
|
||||
|
||||
import (
|
||||
"context"
|
||||
"errors"
|
||||
|
||||
"github.com/go-logr/logr"
|
||||
"github.com/pkg/errors"
|
||||
appsv1 "k8s.io/api/apps/v1"
|
||||
corev1 "k8s.io/api/core/v1"
|
||||
rbacv1 "k8s.io/api/rbac/v1"
|
||||
|
||||
@@ -3,8 +3,6 @@
|
||||
|
||||
package errors
|
||||
|
||||
import (
|
||||
"github.com/pkg/errors"
|
||||
)
|
||||
import "errors"
|
||||
|
||||
var ErrPausedReconciliation = errors.New("paused reconciliation, no further actions")
|
||||
|
||||
@@ -5,9 +5,9 @@ package controllers
|
||||
|
||||
import (
|
||||
"context"
|
||||
"errors"
|
||||
|
||||
"github.com/go-logr/logr"
|
||||
"github.com/pkg/errors"
|
||||
appsv1 "k8s.io/api/apps/v1"
|
||||
corev1 "k8s.io/api/core/v1"
|
||||
v1 "k8s.io/api/rbac/v1"
|
||||
|
||||
@@ -5,9 +5,9 @@ package controllers
|
||||
|
||||
import (
|
||||
"context"
|
||||
"errors"
|
||||
|
||||
"github.com/go-logr/logr"
|
||||
"github.com/pkg/errors"
|
||||
"k8s.io/utils/ptr"
|
||||
controllerruntime "sigs.k8s.io/controller-runtime"
|
||||
"sigs.k8s.io/controller-runtime/pkg/builder"
|
||||
|
||||
@@ -5,9 +5,9 @@ package controllers
|
||||
|
||||
import (
|
||||
"context"
|
||||
"errors"
|
||||
|
||||
"github.com/go-logr/logr"
|
||||
"github.com/pkg/errors"
|
||||
appsv1 "k8s.io/api/apps/v1"
|
||||
corev1 "k8s.io/api/core/v1"
|
||||
rbacv1 "k8s.io/api/rbac/v1"
|
||||
|
||||
@@ -5,11 +5,11 @@ package controllers
|
||||
|
||||
import (
|
||||
"context"
|
||||
"errors"
|
||||
"fmt"
|
||||
"time"
|
||||
|
||||
"github.com/go-logr/logr"
|
||||
"github.com/pkg/errors"
|
||||
admissionregistrationv1 "k8s.io/api/admissionregistration/v1"
|
||||
apierrors "k8s.io/apimachinery/pkg/api/errors"
|
||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
|
||||
@@ -5,11 +5,11 @@ package controllers
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"time"
|
||||
|
||||
"github.com/clastix/kamaji-telemetry/api"
|
||||
telemetry "github.com/clastix/kamaji-telemetry/pkg/client"
|
||||
"github.com/pkg/errors"
|
||||
corev1 "k8s.io/api/core/v1"
|
||||
"k8s.io/apimachinery/pkg/types"
|
||||
"k8s.io/utils/ptr"
|
||||
@@ -31,7 +31,7 @@ type TelemetryController struct {
|
||||
func (m *TelemetryController) retrieveControllerUID(ctx context.Context) (string, error) {
|
||||
var defaultSvc corev1.Service
|
||||
if err := m.Client.Get(ctx, types.NamespacedName{Name: "kubernetes", Namespace: "default"}, &defaultSvc); err != nil {
|
||||
return "", errors.Wrap(err, "cannot start the telemetry controller")
|
||||
return "", fmt.Errorf("cannot start the telemetry controller: %w", err)
|
||||
}
|
||||
|
||||
return string(defaultSvc.UID), nil
|
||||
|
||||
@@ -5,12 +5,12 @@ package controllers
|
||||
|
||||
import (
|
||||
"context"
|
||||
"errors"
|
||||
"fmt"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/juju/mutex/v2"
|
||||
"github.com/pkg/errors"
|
||||
appsv1 "k8s.io/api/apps/v1"
|
||||
batchv1 "k8s.io/api/batch/v1"
|
||||
corev1 "k8s.io/api/core/v1"
|
||||
@@ -18,6 +18,7 @@ import (
|
||||
k8serrors "k8s.io/apimachinery/pkg/api/errors"
|
||||
k8stypes "k8s.io/apimachinery/pkg/types"
|
||||
"k8s.io/client-go/discovery"
|
||||
"k8s.io/client-go/util/retry"
|
||||
"k8s.io/client-go/util/workqueue"
|
||||
"k8s.io/utils/clock"
|
||||
ctrl "sigs.k8s.io/controller-runtime"
|
||||
@@ -115,11 +116,11 @@ func (r *TenantControlPlaneReconciler) Reconcile(ctx context.Context, req ctrl.R
|
||||
releaser, err := mutex.Acquire(r.mutexSpec(tenantControlPlane))
|
||||
if err != nil {
|
||||
switch {
|
||||
case errors.As(err, &mutex.ErrTimeout):
|
||||
case errors.Is(err, mutex.ErrTimeout):
|
||||
log.Info("acquire timed out, current process is blocked by another reconciliation")
|
||||
|
||||
return ctrl.Result{RequeueAfter: time.Second}, nil
|
||||
case errors.As(err, &mutex.ErrCancelled):
|
||||
case errors.Is(err, mutex.ErrCancelled):
|
||||
log.Info("acquire cancelled")
|
||||
|
||||
return ctrl.Result{RequeueAfter: time.Second}, nil
|
||||
@@ -260,6 +261,23 @@ func (r *TenantControlPlaneReconciler) Reconcile(ctx context.Context, req ctrl.R
|
||||
|
||||
log.Info(fmt.Sprintf("%s has been reconciled", tenantControlPlane.GetName()))
|
||||
|
||||
// Set ObservedGeneration only on successful reconciliation completion.
|
||||
// This follows Cluster API conventions where ObservedGeneration indicates
|
||||
// the controller has fully processed the given generation.
|
||||
if err := retry.RetryOnConflict(retry.DefaultRetry, func() error {
|
||||
if getErr := r.Client.Get(ctx, req.NamespacedName, tenantControlPlane); getErr != nil {
|
||||
return getErr
|
||||
}
|
||||
|
||||
tenantControlPlane.Status.ObservedGeneration = tenantControlPlane.Generation
|
||||
|
||||
return r.Client.Status().Update(ctx, tenantControlPlane)
|
||||
}); err != nil {
|
||||
log.Error(err, "failed to update ObservedGeneration")
|
||||
|
||||
return ctrl.Result{}, err
|
||||
}
|
||||
|
||||
return ctrl.Result{}, nil
|
||||
}
|
||||
|
||||
@@ -379,7 +397,7 @@ func (r *TenantControlPlaneReconciler) dataStore(ctx context.Context, tenantCont
|
||||
|
||||
var ds kamajiv1alpha1.DataStore
|
||||
if err := r.Client.Get(ctx, k8stypes.NamespacedName{Name: tenantControlPlane.Spec.DataStore}, &ds); err != nil {
|
||||
return nil, errors.Wrap(err, "cannot retrieve *kamajiv1alpha.DataStore object")
|
||||
return nil, fmt.Errorf("cannot retrieve *kamajiv1alpha.DataStore object: %w", err)
|
||||
}
|
||||
|
||||
return &ds, nil
|
||||
@@ -391,7 +409,7 @@ func (r *TenantControlPlaneReconciler) dataStoreOverride(ctx context.Context, te
|
||||
for _, dso := range tenantControlPlane.Spec.DataStoreOverrides {
|
||||
var ds kamajiv1alpha1.DataStore
|
||||
if err := r.Client.Get(ctx, k8stypes.NamespacedName{Name: dso.DataStore}, &ds); err != nil {
|
||||
return nil, errors.Wrap(err, "cannot retrieve *kamajiv1alpha.DataStore object")
|
||||
return nil, fmt.Errorf("cannot retrieve *kamajiv1alpha.DataStore object: %w", err)
|
||||
}
|
||||
if ds.Spec.Driver != kamajiv1alpha1.EtcdDriver {
|
||||
return nil, errors.New("DataStoreOverrides can only use ETCD driver")
|
||||
|
||||
@@ -27982,6 +27982,15 @@ DataStoreStatus defines the observed state of DataStore.
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody><tr>
|
||||
<td><b>observedGeneration</b></td>
|
||||
<td>integer</td>
|
||||
<td>
|
||||
ObservedGeneration represents the .metadata.generation that was last reconciled.<br/>
|
||||
<br/>
|
||||
<i>Format</i>: int64<br/>
|
||||
</td>
|
||||
<td>false</td>
|
||||
</tr><tr>
|
||||
<td><b>usedBy</b></td>
|
||||
<td>[]string</td>
|
||||
<td>
|
||||
@@ -28365,6 +28374,15 @@ In case of a different value compared to Resources, check the field errors.<br/>
|
||||
Errors is the list of failed kubeconfig generations.<br/>
|
||||
</td>
|
||||
<td>false</td>
|
||||
</tr><tr>
|
||||
<td><b>observedGeneration</b></td>
|
||||
<td>integer</td>
|
||||
<td>
|
||||
ObservedGeneration represents the .metadata.generation that was last reconciled.<br/>
|
||||
<br/>
|
||||
<i>Format</i>: int64<br/>
|
||||
</td>
|
||||
<td>false</td>
|
||||
</tr></tbody>
|
||||
</table>
|
||||
|
||||
@@ -42555,6 +42573,15 @@ that are necessary to run a kubernetes control plane<br/>
|
||||
Kubernetes contains information about the reconciliation of the required Kubernetes resources deployed in the admin cluster<br/>
|
||||
</td>
|
||||
<td>false</td>
|
||||
</tr><tr>
|
||||
<td><b>observedGeneration</b></td>
|
||||
<td>integer</td>
|
||||
<td>
|
||||
ObservedGeneration represents the .metadata.generation that was last reconciled.<br/>
|
||||
<br/>
|
||||
<i>Format</i>: int64<br/>
|
||||
</td>
|
||||
<td>false</td>
|
||||
</tr><tr>
|
||||
<td><b><a href="#tenantcontrolplanestatusstorage">storage</a></b></td>
|
||||
<td>object</td>
|
||||
|
||||
@@ -5,10 +5,12 @@ package e2e
|
||||
|
||||
import (
|
||||
"context"
|
||||
"time"
|
||||
|
||||
. "github.com/onsi/ginkgo/v2"
|
||||
. "github.com/onsi/gomega"
|
||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
"k8s.io/apimachinery/pkg/types"
|
||||
pointer "k8s.io/utils/ptr"
|
||||
|
||||
kamajiv1alpha1 "github.com/clastix/kamaji/api/v1alpha1"
|
||||
@@ -59,5 +61,15 @@ var _ = Describe("Deploy a TenantControlPlane resource", func() {
|
||||
// Check if TenantControlPlane resource has been created
|
||||
It("Should be Ready", func() {
|
||||
StatusMustEqualTo(tcp, kamajiv1alpha1.VersionReady)
|
||||
// ObservedGeneration is set at the end of successful reconciliation,
|
||||
// after status becomes Ready, so we need to wait for it.
|
||||
Eventually(func() int64 {
|
||||
if err := k8sClient.Get(context.Background(), types.NamespacedName{Name: tcp.GetName(), Namespace: tcp.GetNamespace()}, tcp); err != nil {
|
||||
return -1
|
||||
}
|
||||
|
||||
return tcp.Status.ObservedGeneration
|
||||
}, 30*time.Second, time.Second).Should(Equal(tcp.Generation),
|
||||
"ObservedGeneration should equal Generation after successful reconciliation")
|
||||
})
|
||||
})
|
||||
|
||||
2
go.mod
2
go.mod
@@ -18,7 +18,6 @@ require (
|
||||
github.com/nats-io/nats.go v1.48.0
|
||||
github.com/onsi/ginkgo/v2 v2.28.1
|
||||
github.com/onsi/gomega v1.39.1
|
||||
github.com/pkg/errors v0.9.1
|
||||
github.com/prometheus/client_golang v1.23.2
|
||||
github.com/prometheus/client_model v0.6.2
|
||||
github.com/spf13/cobra v1.10.2
|
||||
@@ -124,6 +123,7 @@ require (
|
||||
github.com/opencontainers/image-spec v1.1.1 // indirect
|
||||
github.com/pelletier/go-toml/v2 v2.2.4 // indirect
|
||||
github.com/peterbourgon/diskv v2.0.1+incompatible // indirect
|
||||
github.com/pkg/errors v0.9.1 // indirect
|
||||
github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 // indirect
|
||||
github.com/power-devops/perfstat v0.0.0-20210106213030-5aafc221ea8c // indirect
|
||||
github.com/prometheus/common v0.66.1 // indirect
|
||||
|
||||
@@ -12,7 +12,6 @@ import (
|
||||
"strconv"
|
||||
"strings"
|
||||
|
||||
"github.com/pkg/errors"
|
||||
appsv1 "k8s.io/api/apps/v1"
|
||||
corev1 "k8s.io/api/core/v1"
|
||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
@@ -1022,7 +1021,7 @@ func (d Deployment) templateLabels(ctx context.Context, tenantControlPlane *kama
|
||||
func (d Deployment) secretHashValue(ctx context.Context, client client.Client, namespace, name string) (string, error) {
|
||||
secret := &corev1.Secret{}
|
||||
if err := client.Get(ctx, types.NamespacedName{Namespace: namespace, Name: name}, secret); err != nil {
|
||||
return "", errors.Wrap(err, "cannot retrieve *corev1.Secret for resource version retrieval")
|
||||
return "", fmt.Errorf("cannot retrieve *corev1.Secret for resource version retrieval: %w", err)
|
||||
}
|
||||
|
||||
return d.hashValue(*secret), nil
|
||||
|
||||
@@ -17,7 +17,6 @@ import (
|
||||
"net"
|
||||
"time"
|
||||
|
||||
"github.com/pkg/errors"
|
||||
"k8s.io/apimachinery/pkg/util/sets"
|
||||
)
|
||||
|
||||
@@ -93,7 +92,7 @@ func GenerateCertificatePrivateKeyPair(template *x509.Certificate, caCertificate
|
||||
|
||||
caPrivKeyBytes, err := ParsePrivateKeyBytes(caPrivateKey)
|
||||
if err != nil {
|
||||
return nil, nil, errors.Wrap(err, "provided CA private key for certificate generation cannot be parsed")
|
||||
return nil, nil, fmt.Errorf("provided CA private key for certificate generation cannot be parsed: %w", err)
|
||||
}
|
||||
|
||||
return generateCertificateKeyPairBytes(template, caCertBytes, caPrivKeyBytes)
|
||||
@@ -108,7 +107,7 @@ func ParseCertificateBytes(content []byte) (*x509.Certificate, error) {
|
||||
|
||||
crt, err := x509.ParseCertificate(pemContent.Bytes)
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "cannot parse x509 Certificate")
|
||||
return nil, fmt.Errorf("cannot parse x509 Certificate: %w", err)
|
||||
}
|
||||
|
||||
return crt, nil
|
||||
@@ -124,7 +123,7 @@ func ParsePrivateKeyBytes(content []byte) (crypto.Signer, error) {
|
||||
if pemContent.Type == "EC PRIVATE KEY" {
|
||||
privateKey, err := x509.ParseECPrivateKey(pemContent.Bytes)
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "cannot parse EC Private Key")
|
||||
return nil, fmt.Errorf("cannot parse EC Private Key: %w", err)
|
||||
}
|
||||
|
||||
return privateKey, nil
|
||||
@@ -132,7 +131,7 @@ func ParsePrivateKeyBytes(content []byte) (crypto.Signer, error) {
|
||||
|
||||
privateKey, err := x509.ParsePKCS1PrivateKey(pemContent.Bytes)
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "cannot parse PKCS1 Private Key")
|
||||
return nil, fmt.Errorf("cannot parse PKCS1 Private Key: %w", err)
|
||||
}
|
||||
|
||||
return privateKey, nil
|
||||
@@ -209,12 +208,12 @@ func VerifyCertificate(cert, ca []byte, usages ...x509.ExtKeyUsage) (bool, error
|
||||
func generateCertificateKeyPairBytes(template *x509.Certificate, caCert *x509.Certificate, caKey crypto.Signer) (*bytes.Buffer, *bytes.Buffer, error) {
|
||||
certPrivKey, err := rsa.GenerateKey(cryptorand.Reader, 2048)
|
||||
if err != nil {
|
||||
return nil, nil, errors.Wrap(err, "cannot generate an RSA key")
|
||||
return nil, nil, fmt.Errorf("cannot generate an RSA key: %w", err)
|
||||
}
|
||||
|
||||
certBytes, err := x509.CreateCertificate(cryptorand.Reader, template, caCert, &certPrivKey.PublicKey, caKey)
|
||||
if err != nil {
|
||||
return nil, nil, errors.Wrap(err, "cannot create the certificate")
|
||||
return nil, nil, fmt.Errorf("cannot create the certificate: %w", err)
|
||||
}
|
||||
|
||||
certPEM := &bytes.Buffer{}
|
||||
@@ -223,7 +222,7 @@ func generateCertificateKeyPairBytes(template *x509.Certificate, caCert *x509.Ce
|
||||
Headers: nil,
|
||||
Bytes: certBytes,
|
||||
}); err != nil {
|
||||
return nil, nil, errors.Wrap(err, "cannot encode the generate certificate bytes")
|
||||
return nil, nil, fmt.Errorf("cannot encode the generate certificate bytes: %w", err)
|
||||
}
|
||||
|
||||
certPrivKeyPEM := &bytes.Buffer{}
|
||||
@@ -232,7 +231,7 @@ func generateCertificateKeyPairBytes(template *x509.Certificate, caCert *x509.Ce
|
||||
Headers: nil,
|
||||
Bytes: x509.MarshalPKCS1PrivateKey(certPrivKey),
|
||||
}); err != nil {
|
||||
return nil, nil, errors.Wrap(err, "cannot encode private key")
|
||||
return nil, nil, fmt.Errorf("cannot encode private key: %w", err)
|
||||
}
|
||||
|
||||
return certPEM, certPrivKeyPEM, nil
|
||||
|
||||
@@ -7,7 +7,6 @@ import (
|
||||
"context"
|
||||
"fmt"
|
||||
|
||||
"github.com/pkg/errors"
|
||||
"sigs.k8s.io/controller-runtime/pkg/client"
|
||||
|
||||
kamajiv1alpha1 "github.com/clastix/kamaji/api/v1alpha1"
|
||||
@@ -16,7 +15,7 @@ import (
|
||||
func NewStorageConnection(ctx context.Context, client client.Client, ds kamajiv1alpha1.DataStore) (Connection, error) {
|
||||
cc, err := NewConnectionConfig(ctx, client, ds)
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "unable to create connection config object")
|
||||
return nil, fmt.Errorf("unable to create connection config object: %w", err)
|
||||
}
|
||||
|
||||
switch ds.Spec.Driver {
|
||||
|
||||
@@ -11,7 +11,6 @@ import (
|
||||
"net"
|
||||
"strconv"
|
||||
|
||||
"github.com/pkg/errors"
|
||||
"sigs.k8s.io/controller-runtime/pkg/client"
|
||||
|
||||
kamajiv1alpha1 "github.com/clastix/kamaji/api/v1alpha1"
|
||||
@@ -67,7 +66,7 @@ func NewConnectionConfig(ctx context.Context, client client.Client, ds kamajiv1a
|
||||
|
||||
certificate, err := tls.X509KeyPair(crt, key)
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "cannot retrieve x.509 key pair from the Kine Secret")
|
||||
return nil, fmt.Errorf("cannot retrieve x.509 key pair from the Kine Secret: %w", err)
|
||||
}
|
||||
|
||||
tlsConfig.Certificates = []tls.Certificate{certificate}
|
||||
@@ -93,12 +92,12 @@ func NewConnectionConfig(ctx context.Context, client client.Client, ds kamajiv1a
|
||||
for _, ep := range ds.Spec.Endpoints {
|
||||
host, stringPort, err := net.SplitHostPort(ep)
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "cannot retrieve host-port pair from DataStore endpoints")
|
||||
return nil, fmt.Errorf("cannot retrieve host-port pair from DataStore endpoints: %w", err)
|
||||
}
|
||||
|
||||
port, err := strconv.Atoi(stringPort)
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "cannot convert port from string for the given DataStore")
|
||||
return nil, fmt.Errorf("cannot convert port from string for the given DataStore: %w", err)
|
||||
}
|
||||
|
||||
eps = append(eps, ConnectionEndpoint{
|
||||
|
||||
@@ -3,48 +3,48 @@
|
||||
|
||||
package errors
|
||||
|
||||
import "github.com/pkg/errors"
|
||||
import "fmt"
|
||||
|
||||
func NewCreateUserError(err error) error {
|
||||
return errors.Wrap(err, "cannot create user")
|
||||
return fmt.Errorf("cannot create user: %w", err)
|
||||
}
|
||||
|
||||
func NewGrantPrivilegesError(err error) error {
|
||||
return errors.Wrap(err, "cannot grant privileges")
|
||||
return fmt.Errorf("cannot grant privileges: %w", err)
|
||||
}
|
||||
|
||||
func NewCheckUserExistsError(err error) error {
|
||||
return errors.Wrap(err, "cannot check if user exists")
|
||||
return fmt.Errorf("cannot check if user exists: %w", err)
|
||||
}
|
||||
|
||||
func NewCheckGrantExistsError(err error) error {
|
||||
return errors.Wrap(err, "cannot check if grant exists")
|
||||
return fmt.Errorf("cannot check if grant exists: %w", err)
|
||||
}
|
||||
|
||||
func NewDeleteUserError(err error) error {
|
||||
return errors.Wrap(err, "cannot delete user")
|
||||
return fmt.Errorf("cannot delete user: %w", err)
|
||||
}
|
||||
|
||||
func NewCannotDeleteDatabaseError(err error) error {
|
||||
return errors.Wrap(err, "cannot delete database")
|
||||
return fmt.Errorf("cannot delete database: %w", err)
|
||||
}
|
||||
|
||||
func NewCheckDatabaseExistError(err error) error {
|
||||
return errors.Wrap(err, "cannot check if database exists")
|
||||
return fmt.Errorf("cannot check if database exists: %w", err)
|
||||
}
|
||||
|
||||
func NewRevokePrivilegesError(err error) error {
|
||||
return errors.Wrap(err, "cannot revoke privileges")
|
||||
return fmt.Errorf("cannot revoke privileges: %w", err)
|
||||
}
|
||||
|
||||
func NewCloseConnectionError(err error) error {
|
||||
return errors.Wrap(err, "cannot close connection")
|
||||
return fmt.Errorf("cannot close connection: %w", err)
|
||||
}
|
||||
|
||||
func NewCheckConnectionError(err error) error {
|
||||
return errors.Wrap(err, "cannot check connection")
|
||||
return fmt.Errorf("cannot check connection: %w", err)
|
||||
}
|
||||
|
||||
func NewCreateDBError(err error) error {
|
||||
return errors.Wrap(err, "cannot create database")
|
||||
return fmt.Errorf("cannot create database: %w", err)
|
||||
}
|
||||
|
||||
@@ -7,13 +7,12 @@ import (
|
||||
"context"
|
||||
"fmt"
|
||||
|
||||
goerrors "github.com/pkg/errors"
|
||||
"go.etcd.io/etcd/api/v3/authpb"
|
||||
"go.etcd.io/etcd/api/v3/v3rpc/rpctypes"
|
||||
etcdclient "go.etcd.io/etcd/client/v3"
|
||||
|
||||
kamajiv1alpha1 "github.com/clastix/kamaji/api/v1alpha1"
|
||||
"github.com/clastix/kamaji/internal/datastore/errors"
|
||||
dserrors "github.com/clastix/kamaji/internal/datastore/errors"
|
||||
)
|
||||
|
||||
func NewETCDConnection(config ConnectionConfig) (Connection, error) {
|
||||
@@ -44,7 +43,7 @@ type EtcdClient struct {
|
||||
|
||||
func (e *EtcdClient) CreateUser(ctx context.Context, user, password string) error {
|
||||
if _, err := e.Client.Auth.UserAddWithOptions(ctx, user, password, &etcdclient.UserAddOptions{NoPassword: true}); err != nil {
|
||||
return errors.NewCreateUserError(err)
|
||||
return dserrors.NewCreateUserError(err)
|
||||
}
|
||||
|
||||
return nil
|
||||
@@ -56,18 +55,18 @@ func (e *EtcdClient) CreateDB(context.Context, string) error {
|
||||
|
||||
func (e *EtcdClient) GrantPrivileges(ctx context.Context, user, dbName string) error {
|
||||
if _, err := e.Client.Auth.RoleAdd(ctx, dbName); err != nil {
|
||||
return errors.NewGrantPrivilegesError(err)
|
||||
return dserrors.NewGrantPrivilegesError(err)
|
||||
}
|
||||
|
||||
permission := etcdclient.PermissionType(authpb.READWRITE)
|
||||
key := e.buildKey(dbName)
|
||||
|
||||
if _, err := e.Client.RoleGrantPermission(ctx, dbName, key, etcdclient.GetPrefixRangeEnd(key), permission); err != nil {
|
||||
return errors.NewGrantPrivilegesError(err)
|
||||
return dserrors.NewGrantPrivilegesError(err)
|
||||
}
|
||||
|
||||
if _, err := e.Client.UserGrantRole(ctx, user, dbName); err != nil {
|
||||
return errors.NewGrantPrivilegesError(err)
|
||||
return dserrors.NewGrantPrivilegesError(err)
|
||||
}
|
||||
|
||||
return nil
|
||||
@@ -75,11 +74,15 @@ func (e *EtcdClient) GrantPrivileges(ctx context.Context, user, dbName string) e
|
||||
|
||||
func (e *EtcdClient) UserExists(ctx context.Context, user string) (bool, error) {
|
||||
if _, err := e.Client.UserGet(ctx, user); err != nil {
|
||||
if goerrors.As(err, &rpctypes.ErrGRPCUserNotFound) {
|
||||
// Convert gRPC error to comparable EtcdError using rpctypes.Error(),
|
||||
// then compare against the client-side error constant.
|
||||
// The == comparison is correct here as rpctypes.Error() normalizes
|
||||
// gRPC status errors to comparable EtcdError struct values.
|
||||
if rpctypes.Error(err) == rpctypes.ErrUserNotFound { //nolint:errorlint
|
||||
return false, nil
|
||||
}
|
||||
|
||||
return false, errors.NewCheckUserExistsError(err)
|
||||
return false, dserrors.NewCheckUserExistsError(err)
|
||||
}
|
||||
|
||||
return true, nil
|
||||
@@ -92,16 +95,20 @@ func (e *EtcdClient) DBExists(context.Context, string) (bool, error) {
|
||||
func (e *EtcdClient) GrantPrivilegesExists(ctx context.Context, username, dbName string) (bool, error) {
|
||||
_, err := e.Client.RoleGet(ctx, dbName)
|
||||
if err != nil {
|
||||
if goerrors.As(err, &rpctypes.ErrGRPCRoleNotFound) {
|
||||
// Convert gRPC error to comparable EtcdError using rpctypes.Error(),
|
||||
// then compare against the client-side error constant.
|
||||
// The == comparison is correct here as rpctypes.Error() normalizes
|
||||
// gRPC status errors to comparable EtcdError struct values.
|
||||
if rpctypes.Error(err) == rpctypes.ErrRoleNotFound { //nolint:errorlint
|
||||
return false, nil
|
||||
}
|
||||
|
||||
return false, errors.NewCheckGrantExistsError(err)
|
||||
return false, dserrors.NewCheckGrantExistsError(err)
|
||||
}
|
||||
|
||||
user, err := e.Client.UserGet(ctx, username)
|
||||
if err != nil {
|
||||
return false, errors.NewCheckGrantExistsError(err)
|
||||
return false, dserrors.NewCheckGrantExistsError(err)
|
||||
}
|
||||
|
||||
for _, i := range user.Roles {
|
||||
@@ -115,7 +122,7 @@ func (e *EtcdClient) GrantPrivilegesExists(ctx context.Context, username, dbName
|
||||
|
||||
func (e *EtcdClient) DeleteUser(ctx context.Context, user string) error {
|
||||
if _, err := e.Client.Auth.UserDelete(ctx, user); err != nil {
|
||||
return errors.NewDeleteUserError(err)
|
||||
return dserrors.NewDeleteUserError(err)
|
||||
}
|
||||
|
||||
return nil
|
||||
@@ -124,7 +131,7 @@ func (e *EtcdClient) DeleteUser(ctx context.Context, user string) error {
|
||||
func (e *EtcdClient) DeleteDB(ctx context.Context, dbName string) error {
|
||||
prefix := e.buildKey(dbName)
|
||||
if _, err := e.Client.Delete(ctx, prefix, etcdclient.WithPrefix()); err != nil {
|
||||
return errors.NewCannotDeleteDatabaseError(err)
|
||||
return dserrors.NewCannotDeleteDatabaseError(err)
|
||||
}
|
||||
|
||||
return nil
|
||||
@@ -132,7 +139,7 @@ func (e *EtcdClient) DeleteDB(ctx context.Context, dbName string) error {
|
||||
|
||||
func (e *EtcdClient) RevokePrivileges(ctx context.Context, _, dbName string) error {
|
||||
if _, err := e.Client.Auth.RoleDelete(ctx, dbName); err != nil {
|
||||
return errors.NewRevokePrivilegesError(err)
|
||||
return dserrors.NewRevokePrivilegesError(err)
|
||||
}
|
||||
|
||||
return nil
|
||||
@@ -146,7 +153,7 @@ func (e *EtcdClient) GetConnectionString() string {
|
||||
|
||||
func (e *EtcdClient) Close() error {
|
||||
if err := e.Client.Close(); err != nil {
|
||||
return errors.NewCloseConnectionError(err)
|
||||
return dserrors.NewCloseConnectionError(err)
|
||||
}
|
||||
|
||||
return nil
|
||||
@@ -154,7 +161,7 @@ func (e *EtcdClient) Close() error {
|
||||
|
||||
func (e *EtcdClient) Check(ctx context.Context) error {
|
||||
if _, err := e.Client.AuthStatus(ctx); err != nil {
|
||||
return errors.NewCheckConnectionError(err)
|
||||
return dserrors.NewCheckConnectionError(err)
|
||||
}
|
||||
|
||||
return nil
|
||||
|
||||
@@ -5,11 +5,11 @@ package datastore
|
||||
|
||||
import (
|
||||
"context"
|
||||
"errors"
|
||||
"fmt"
|
||||
"strings"
|
||||
|
||||
"github.com/nats-io/nats.go"
|
||||
"github.com/pkg/errors"
|
||||
|
||||
kamajiv1alpha1 "github.com/clastix/kamaji/api/v1alpha1"
|
||||
)
|
||||
@@ -73,7 +73,7 @@ func (nc *NATSConnection) CreateUser(_ context.Context, _, _ string) error {
|
||||
func (nc *NATSConnection) CreateDB(_ context.Context, dbName string) error {
|
||||
_, err := nc.js.CreateKeyValue(&nats.KeyValueConfig{Bucket: dbName})
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "unable to create the datastore")
|
||||
return fmt.Errorf("unable to create the datastore: %w", err)
|
||||
}
|
||||
|
||||
return nil
|
||||
|
||||
@@ -10,7 +10,6 @@ import (
|
||||
"strings"
|
||||
|
||||
"github.com/go-pg/pg/v10"
|
||||
goerrors "github.com/pkg/errors"
|
||||
|
||||
kamajiv1alpha1 "github.com/clastix/kamaji/api/v1alpha1"
|
||||
"github.com/clastix/kamaji/internal/datastore/errors"
|
||||
@@ -236,7 +235,7 @@ func (r *PostgreSQLConnection) DeleteUser(ctx context.Context, user string) erro
|
||||
|
||||
func (r *PostgreSQLConnection) DeleteDB(ctx context.Context, dbName string) error {
|
||||
if err := r.GrantPrivileges(ctx, r.rootUser, dbName); err != nil {
|
||||
return errors.NewCannotDeleteDatabaseError(goerrors.Wrap(err, "cannot grant privileges to root user"))
|
||||
return errors.NewCannotDeleteDatabaseError(fmt.Errorf("cannot grant privileges to root user: %w", err))
|
||||
}
|
||||
|
||||
if _, err := r.db.ExecContext(ctx, fmt.Sprintf(postgresqlDropDBStatement, dbName)); err != nil {
|
||||
|
||||
@@ -3,15 +3,21 @@
|
||||
|
||||
package errors
|
||||
|
||||
import "github.com/pkg/errors"
|
||||
import "errors"
|
||||
|
||||
func ShouldReconcileErrorBeIgnored(err error) bool {
|
||||
var (
|
||||
nonExposedLBErr NonExposedLoadBalancerError
|
||||
missingValidIPErr MissingValidIPError
|
||||
migrationErr MigrationInProcessError
|
||||
)
|
||||
|
||||
switch {
|
||||
case errors.As(err, &NonExposedLoadBalancerError{}):
|
||||
case errors.As(err, &nonExposedLBErr):
|
||||
return true
|
||||
case errors.As(err, &MissingValidIPError{}):
|
||||
case errors.As(err, &missingValidIPErr):
|
||||
return true
|
||||
case errors.As(err, &MigrationInProcessError{}):
|
||||
case errors.As(err, &migrationErr):
|
||||
return true
|
||||
default:
|
||||
return false
|
||||
|
||||
@@ -4,7 +4,8 @@
|
||||
package kubeadm
|
||||
|
||||
import (
|
||||
"github.com/pkg/errors"
|
||||
"fmt"
|
||||
|
||||
corev1 "k8s.io/api/core/v1"
|
||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
"k8s.io/client-go/kubernetes"
|
||||
@@ -20,19 +21,19 @@ func BootstrapToken(client kubernetes.Interface, config *Configuration) error {
|
||||
initConfiguration := config.InitConfiguration
|
||||
|
||||
if err := node.UpdateOrCreateTokens(client, false, initConfiguration.BootstrapTokens); err != nil {
|
||||
return errors.Wrap(err, "error updating or creating token")
|
||||
return fmt.Errorf("error updating or creating token: %w", err)
|
||||
}
|
||||
|
||||
if err := node.AllowBootstrapTokensToGetNodes(client); err != nil {
|
||||
return errors.Wrap(err, "error allowing bootstrap tokens to get Nodes")
|
||||
return fmt.Errorf("error allowing bootstrap tokens to get Nodes: %w", err)
|
||||
}
|
||||
|
||||
if err := node.AllowBootstrapTokensToPostCSRs(client); err != nil {
|
||||
return errors.Wrap(err, "error allowing bootstrap tokens to post CSRs")
|
||||
return fmt.Errorf("error allowing bootstrap tokens to post CSRs: %w", err)
|
||||
}
|
||||
|
||||
if err := node.AutoApproveNodeBootstrapTokens(client); err != nil {
|
||||
return errors.Wrap(err, "error auto-approving node bootstrap tokens")
|
||||
return fmt.Errorf("error auto-approving node bootstrap tokens: %w", err)
|
||||
}
|
||||
|
||||
if err := node.AutoApproveNodeCertificateRotation(client); err != nil {
|
||||
@@ -66,7 +67,7 @@ func BootstrapToken(client kubernetes.Interface, config *Configuration) error {
|
||||
}
|
||||
|
||||
if err := clusterinfo.CreateClusterInfoRBACRules(client); err != nil {
|
||||
return errors.Wrap(err, "error creating clusterinfo RBAC rules")
|
||||
return fmt.Errorf("error creating clusterinfo RBAC rules: %w", err)
|
||||
}
|
||||
|
||||
return nil
|
||||
|
||||
@@ -8,7 +8,6 @@ import (
|
||||
|
||||
"github.com/blang/semver"
|
||||
jsonpatchv5 "github.com/evanphx/json-patch/v5"
|
||||
"github.com/pkg/errors"
|
||||
corev1 "k8s.io/api/core/v1"
|
||||
rbacv1 "k8s.io/api/rbac/v1"
|
||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
@@ -67,7 +66,7 @@ func UploadKubeletConfig(client kubernetes.Interface, config *Configuration, pat
|
||||
}
|
||||
|
||||
if err = createConfigMapRBACRules(client, configMapName); err != nil {
|
||||
return nil, errors.Wrap(err, "error creating kubelet configuration configmap RBAC rules")
|
||||
return nil, fmt.Errorf("error creating kubelet configuration configmap RBAC rules: %w", err)
|
||||
}
|
||||
|
||||
return nil, nil
|
||||
@@ -98,15 +97,15 @@ func getKubeletConfigmapContent(kubeletConfiguration KubeletConfiguration, patch
|
||||
if len(patch) > 0 {
|
||||
kubeletConfig, patchErr := utilities.EncodeToJSON(&kc)
|
||||
if patchErr != nil {
|
||||
return nil, errors.Wrapf(patchErr, "unable to encode KubeletConfiguration to JSON for JSON patching")
|
||||
return nil, fmt.Errorf("unable to encode KubeletConfiguration to JSON for JSON patching: %w", patchErr)
|
||||
}
|
||||
|
||||
if kubeletConfig, patchErr = patch.Apply(kubeletConfig); patchErr != nil {
|
||||
return nil, errors.Wrapf(patchErr, "unable to apply JSON patching to KubeletConfiguration")
|
||||
return nil, fmt.Errorf("unable to apply JSON patching to KubeletConfiguration: %w", patchErr)
|
||||
}
|
||||
|
||||
if patchErr = utilities.DecodeFromJSON(string(kubeletConfig), &kc); patchErr != nil {
|
||||
return nil, errors.Wrapf(patchErr, "unable to decode JSON to KubeletConfiguration")
|
||||
return nil, fmt.Errorf("unable to decode JSON to KubeletConfiguration: %w", patchErr)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -159,7 +158,7 @@ func createConfigMapRBACRules(client kubernetes.Interface, configMapName string)
|
||||
func generateKubeletConfigMapName(version string) (string, error) {
|
||||
parsedVersion, err := semver.ParseTolerant(version)
|
||||
if err != nil {
|
||||
return "", errors.Wrapf(err, "failed to parse kubernetes version %q", version)
|
||||
return "", fmt.Errorf("failed to parse kubernetes version %q: %w", version, err)
|
||||
}
|
||||
|
||||
majorMinor := semver.Version{Major: parsedVersion.Major, Minor: parsedVersion.Minor}
|
||||
|
||||
@@ -6,8 +6,8 @@ package addons
|
||||
import (
|
||||
"bytes"
|
||||
"context"
|
||||
"fmt"
|
||||
|
||||
"github.com/pkg/errors"
|
||||
"github.com/prometheus/client_golang/prometheus"
|
||||
appsv1 "k8s.io/api/apps/v1"
|
||||
corev1 "k8s.io/api/core/v1"
|
||||
@@ -219,7 +219,7 @@ func (c *CoreDNS) UpdateTenantControlPlaneStatus(_ context.Context, tcp *kamajiv
|
||||
func (c *CoreDNS) decodeManifests(ctx context.Context, tcp *kamajiv1alpha1.TenantControlPlane) error {
|
||||
tcpClient, config, err := resources.GetKubeadmManifestDeps(ctx, c.Client, tcp)
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "unable to create manifests dependencies")
|
||||
return fmt.Errorf("unable to create manifests dependencies: %w", err)
|
||||
}
|
||||
|
||||
// If CoreDNS addon is enabled and with an override, adding these to the kubeadm init configuration
|
||||
@@ -235,38 +235,38 @@ func (c *CoreDNS) decodeManifests(ctx context.Context, tcp *kamajiv1alpha1.Tenan
|
||||
|
||||
manifests, err := kubeadm.AddCoreDNS(tcpClient, config)
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "unable to generate manifests")
|
||||
return fmt.Errorf("unable to generate manifests: %w", err)
|
||||
}
|
||||
|
||||
parts := bytes.Split(manifests, []byte("---"))
|
||||
|
||||
if err = utilities.DecodeFromYAML(string(parts[1]), c.deployment); err != nil {
|
||||
return errors.Wrap(err, "unable to decode Deployment manifest")
|
||||
return fmt.Errorf("unable to decode Deployment manifest: %w", err)
|
||||
}
|
||||
addons_utils.SetKamajiManagedLabels(c.deployment)
|
||||
|
||||
if err = utilities.DecodeFromYAML(string(parts[2]), c.configMap); err != nil {
|
||||
return errors.Wrap(err, "unable to decode ConfigMap manifest")
|
||||
return fmt.Errorf("unable to decode ConfigMap manifest: %w", err)
|
||||
}
|
||||
addons_utils.SetKamajiManagedLabels(c.configMap)
|
||||
|
||||
if err = utilities.DecodeFromYAML(string(parts[3]), c.service); err != nil {
|
||||
return errors.Wrap(err, "unable to decode Service manifest")
|
||||
return fmt.Errorf("unable to decode Service manifest: %w", err)
|
||||
}
|
||||
addons_utils.SetKamajiManagedLabels(c.service)
|
||||
|
||||
if err = utilities.DecodeFromYAML(string(parts[4]), c.clusterRole); err != nil {
|
||||
return errors.Wrap(err, "unable to decode ClusterRole manifest")
|
||||
return fmt.Errorf("unable to decode ClusterRole manifest: %w", err)
|
||||
}
|
||||
addons_utils.SetKamajiManagedLabels(c.clusterRole)
|
||||
|
||||
if err = utilities.DecodeFromYAML(string(parts[5]), c.clusterRoleBinding); err != nil {
|
||||
return errors.Wrap(err, "unable to decode ClusterRoleBinding manifest")
|
||||
return fmt.Errorf("unable to decode ClusterRoleBinding manifest: %w", err)
|
||||
}
|
||||
addons_utils.SetKamajiManagedLabels(c.clusterRoleBinding)
|
||||
|
||||
if err = utilities.DecodeFromYAML(string(parts[6]), c.serviceAccount); err != nil {
|
||||
return errors.Wrap(err, "unable to decode ServiceAccount manifest")
|
||||
return fmt.Errorf("unable to decode ServiceAccount manifest: %w", err)
|
||||
}
|
||||
addons_utils.SetKamajiManagedLabels(c.serviceAccount)
|
||||
|
||||
|
||||
@@ -6,8 +6,8 @@ package addons
|
||||
import (
|
||||
"bytes"
|
||||
"context"
|
||||
"fmt"
|
||||
|
||||
"github.com/pkg/errors"
|
||||
"github.com/prometheus/client_golang/prometheus"
|
||||
appsv1 "k8s.io/api/apps/v1"
|
||||
corev1 "k8s.io/api/core/v1"
|
||||
@@ -321,7 +321,7 @@ func (k *KubeProxy) mutateDaemonSet(ctx context.Context, tenantClient client.Cli
|
||||
func (k *KubeProxy) decodeManifests(ctx context.Context, tcp *kamajiv1alpha1.TenantControlPlane) error {
|
||||
tcpClient, config, err := resources.GetKubeadmManifestDeps(ctx, k.Client, tcp)
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "unable to create manifests dependencies")
|
||||
return fmt.Errorf("unable to create manifests dependencies: %w", err)
|
||||
}
|
||||
// If the kube-proxy addon has overrides, adding it to the kubeadm parameters
|
||||
config.Parameters.KubeProxyOptions = &kubeadm.AddonOptions{}
|
||||
@@ -340,38 +340,38 @@ func (k *KubeProxy) decodeManifests(ctx context.Context, tcp *kamajiv1alpha1.Ten
|
||||
|
||||
manifests, err := kubeadm.AddKubeProxy(tcpClient, config)
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "unable to generate manifests")
|
||||
return fmt.Errorf("unable to generate manifests: %w", err)
|
||||
}
|
||||
|
||||
parts := bytes.Split(manifests, []byte("---"))
|
||||
|
||||
if err = utilities.DecodeFromYAML(string(parts[1]), k.serviceAccount); err != nil {
|
||||
return errors.Wrap(err, "unable to decode ServiceAccount manifest")
|
||||
return fmt.Errorf("unable to decode ServiceAccount manifest: %w", err)
|
||||
}
|
||||
addon_utils.SetKamajiManagedLabels(k.serviceAccount)
|
||||
|
||||
if err = utilities.DecodeFromYAML(string(parts[2]), k.clusterRoleBinding); err != nil {
|
||||
return errors.Wrap(err, "unable to decode ClusterRoleBinding manifest")
|
||||
return fmt.Errorf("unable to decode ClusterRoleBinding manifest: %w", err)
|
||||
}
|
||||
addon_utils.SetKamajiManagedLabels(k.clusterRoleBinding)
|
||||
|
||||
if err = utilities.DecodeFromYAML(string(parts[3]), k.role); err != nil {
|
||||
return errors.Wrap(err, "unable to decode Role manifest")
|
||||
return fmt.Errorf("unable to decode Role manifest: %w", err)
|
||||
}
|
||||
addon_utils.SetKamajiManagedLabels(k.role)
|
||||
|
||||
if err = utilities.DecodeFromYAML(string(parts[4]), k.roleBinding); err != nil {
|
||||
return errors.Wrap(err, "unable to decode RoleBinding manifest")
|
||||
return fmt.Errorf("unable to decode RoleBinding manifest: %w", err)
|
||||
}
|
||||
addon_utils.SetKamajiManagedLabels(k.roleBinding)
|
||||
|
||||
if err = utilities.DecodeFromYAML(string(parts[5]), k.configMap); err != nil {
|
||||
return errors.Wrap(err, "unable to decode ConfigMap manifest")
|
||||
return fmt.Errorf("unable to decode ConfigMap manifest: %w", err)
|
||||
}
|
||||
addon_utils.SetKamajiManagedLabels(k.configMap)
|
||||
|
||||
if err = utilities.DecodeFromYAML(string(parts[6]), k.daemonSet); err != nil {
|
||||
return errors.Wrap(err, "unable to decode DaemonSet manifest")
|
||||
return fmt.Errorf("unable to decode DaemonSet manifest: %w", err)
|
||||
}
|
||||
addon_utils.SetKamajiManagedLabels(k.daemonSet)
|
||||
|
||||
|
||||
@@ -5,8 +5,8 @@ package datastore
|
||||
|
||||
import (
|
||||
"context"
|
||||
"errors"
|
||||
|
||||
"github.com/pkg/errors"
|
||||
"github.com/prometheus/client_golang/prometheus"
|
||||
"k8s.io/apimachinery/pkg/util/sets"
|
||||
"sigs.k8s.io/controller-runtime/pkg/controller/controllerutil"
|
||||
|
||||
@@ -5,8 +5,8 @@ package datastore
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
|
||||
"github.com/pkg/errors"
|
||||
"github.com/prometheus/client_golang/prometheus"
|
||||
corev1 "k8s.io/api/core/v1"
|
||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
@@ -192,7 +192,7 @@ func (r *Setup) UpdateTenantControlPlaneStatus(_ context.Context, tenantControlP
|
||||
func (r *Setup) createDB(ctx context.Context, _ *kamajiv1alpha1.TenantControlPlane) (controllerutil.OperationResult, error) {
|
||||
exists, err := r.Connection.DBExists(ctx, r.resource.schema)
|
||||
if err != nil {
|
||||
return controllerutil.OperationResultNone, errors.Wrap(err, "unable to check if datastore exists")
|
||||
return controllerutil.OperationResultNone, fmt.Errorf("unable to check if datastore exists: %w", err)
|
||||
}
|
||||
|
||||
if exists {
|
||||
@@ -200,7 +200,7 @@ func (r *Setup) createDB(ctx context.Context, _ *kamajiv1alpha1.TenantControlPla
|
||||
}
|
||||
|
||||
if err := r.Connection.CreateDB(ctx, r.resource.schema); err != nil {
|
||||
return controllerutil.OperationResultNone, errors.Wrap(err, "unable to create the datastore")
|
||||
return controllerutil.OperationResultNone, fmt.Errorf("unable to create the datastore: %w", err)
|
||||
}
|
||||
|
||||
return controllerutil.OperationResultCreated, nil
|
||||
@@ -209,7 +209,7 @@ func (r *Setup) createDB(ctx context.Context, _ *kamajiv1alpha1.TenantControlPla
|
||||
func (r *Setup) deleteDB(ctx context.Context, _ *kamajiv1alpha1.TenantControlPlane) error {
|
||||
exists, err := r.Connection.DBExists(ctx, r.resource.schema)
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "unable to check if datastore exists")
|
||||
return fmt.Errorf("unable to check if datastore exists: %w", err)
|
||||
}
|
||||
|
||||
if !exists {
|
||||
@@ -217,7 +217,7 @@ func (r *Setup) deleteDB(ctx context.Context, _ *kamajiv1alpha1.TenantControlPla
|
||||
}
|
||||
|
||||
if err := r.Connection.DeleteDB(ctx, r.resource.schema); err != nil {
|
||||
return errors.Wrap(err, "unable to delete the datastore")
|
||||
return fmt.Errorf("unable to delete the datastore: %w", err)
|
||||
}
|
||||
|
||||
return nil
|
||||
@@ -226,7 +226,7 @@ func (r *Setup) deleteDB(ctx context.Context, _ *kamajiv1alpha1.TenantControlPla
|
||||
func (r *Setup) createUser(ctx context.Context, _ *kamajiv1alpha1.TenantControlPlane) (controllerutil.OperationResult, error) {
|
||||
exists, err := r.Connection.UserExists(ctx, r.resource.user)
|
||||
if err != nil {
|
||||
return controllerutil.OperationResultNone, errors.Wrap(err, "unable to check if user exists")
|
||||
return controllerutil.OperationResultNone, fmt.Errorf("unable to check if user exists: %w", err)
|
||||
}
|
||||
|
||||
if exists {
|
||||
@@ -234,7 +234,7 @@ func (r *Setup) createUser(ctx context.Context, _ *kamajiv1alpha1.TenantControlP
|
||||
}
|
||||
|
||||
if err := r.Connection.CreateUser(ctx, r.resource.user, r.resource.password); err != nil {
|
||||
return controllerutil.OperationResultNone, errors.Wrap(err, "unable to create the user")
|
||||
return controllerutil.OperationResultNone, fmt.Errorf("unable to create the user: %w", err)
|
||||
}
|
||||
|
||||
return controllerutil.OperationResultCreated, nil
|
||||
@@ -243,7 +243,7 @@ func (r *Setup) createUser(ctx context.Context, _ *kamajiv1alpha1.TenantControlP
|
||||
func (r *Setup) deleteUser(ctx context.Context, _ *kamajiv1alpha1.TenantControlPlane) error {
|
||||
exists, err := r.Connection.UserExists(ctx, r.resource.user)
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "unable to check if user exists")
|
||||
return fmt.Errorf("unable to check if user exists: %w", err)
|
||||
}
|
||||
|
||||
if !exists {
|
||||
@@ -251,7 +251,7 @@ func (r *Setup) deleteUser(ctx context.Context, _ *kamajiv1alpha1.TenantControlP
|
||||
}
|
||||
|
||||
if err := r.Connection.DeleteUser(ctx, r.resource.user); err != nil {
|
||||
return errors.Wrap(err, "unable to remove the user")
|
||||
return fmt.Errorf("unable to remove the user: %w", err)
|
||||
}
|
||||
|
||||
return nil
|
||||
@@ -260,7 +260,7 @@ func (r *Setup) deleteUser(ctx context.Context, _ *kamajiv1alpha1.TenantControlP
|
||||
func (r *Setup) createGrantPrivileges(ctx context.Context, _ *kamajiv1alpha1.TenantControlPlane) (controllerutil.OperationResult, error) {
|
||||
exists, err := r.Connection.GrantPrivilegesExists(ctx, r.resource.user, r.resource.schema)
|
||||
if err != nil {
|
||||
return controllerutil.OperationResultNone, errors.Wrap(err, "unable to check if privileges exist")
|
||||
return controllerutil.OperationResultNone, fmt.Errorf("unable to check if privileges exist: %w", err)
|
||||
}
|
||||
|
||||
if exists {
|
||||
@@ -268,7 +268,7 @@ func (r *Setup) createGrantPrivileges(ctx context.Context, _ *kamajiv1alpha1.Ten
|
||||
}
|
||||
|
||||
if err := r.Connection.GrantPrivileges(ctx, r.resource.user, r.resource.schema); err != nil {
|
||||
return controllerutil.OperationResultNone, errors.Wrap(err, "unable to grant privileges")
|
||||
return controllerutil.OperationResultNone, fmt.Errorf("unable to grant privileges: %w", err)
|
||||
}
|
||||
|
||||
return controllerutil.OperationResultCreated, nil
|
||||
@@ -277,7 +277,7 @@ func (r *Setup) createGrantPrivileges(ctx context.Context, _ *kamajiv1alpha1.Ten
|
||||
func (r *Setup) revokeGrantPrivileges(ctx context.Context, _ *kamajiv1alpha1.TenantControlPlane) error {
|
||||
exists, err := r.Connection.GrantPrivilegesExists(ctx, r.resource.user, r.resource.schema)
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "unable to check if privileges exist")
|
||||
return fmt.Errorf("unable to check if privileges exist: %w", err)
|
||||
}
|
||||
|
||||
if !exists {
|
||||
@@ -285,7 +285,7 @@ func (r *Setup) revokeGrantPrivileges(ctx context.Context, _ *kamajiv1alpha1.Ten
|
||||
}
|
||||
|
||||
if err := r.Connection.RevokePrivileges(ctx, r.resource.user, r.resource.schema); err != nil {
|
||||
return errors.Wrap(err, "unable to revoke privileges")
|
||||
return fmt.Errorf("unable to revoke privileges: %w", err)
|
||||
}
|
||||
|
||||
return nil
|
||||
|
||||
@@ -5,9 +5,9 @@ package datastore
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
|
||||
"github.com/google/uuid"
|
||||
"github.com/pkg/errors"
|
||||
"github.com/prometheus/client_golang/prometheus"
|
||||
corev1 "k8s.io/api/core/v1"
|
||||
kubeerrors "k8s.io/apimachinery/pkg/api/errors"
|
||||
@@ -82,7 +82,7 @@ func (r *Config) Delete(ctx context.Context, _ *kamajiv1alpha1.TenantControlPlan
|
||||
return nil
|
||||
}
|
||||
|
||||
return errors.Wrap(err, "cannot retrieve the DataStore Secret for removal")
|
||||
return fmt.Errorf("cannot retrieve the DataStore Secret for removal: %w", err)
|
||||
}
|
||||
|
||||
secret.SetFinalizers(nil)
|
||||
@@ -92,7 +92,7 @@ func (r *Config) Delete(ctx context.Context, _ *kamajiv1alpha1.TenantControlPlan
|
||||
return nil
|
||||
}
|
||||
|
||||
return errors.Wrap(err, "cannot remove DataStore Secret finalizers")
|
||||
return fmt.Errorf("cannot remove DataStore Secret finalizers: %w", err)
|
||||
}
|
||||
|
||||
return nil
|
||||
@@ -138,12 +138,12 @@ func (r *Config) mutate(ctx context.Context, tenantControlPlane *kamajiv1alpha1.
|
||||
// set username and password to the basicAuth values of the NATS datastore
|
||||
u, err := r.DataStore.Spec.BasicAuth.Username.GetContent(ctx, r.Client)
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "failed to retrieve the username for the NATS datastore")
|
||||
return fmt.Errorf("failed to retrieve the username for the NATS datastore: %w", err)
|
||||
}
|
||||
|
||||
p, err := r.DataStore.Spec.BasicAuth.Password.GetContent(ctx, r.Client)
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "failed to retrieve the password for the NATS datastore")
|
||||
return fmt.Errorf("failed to retrieve the password for the NATS datastore: %w", err)
|
||||
}
|
||||
|
||||
username = u
|
||||
|
||||
@@ -11,7 +11,6 @@ import (
|
||||
"time"
|
||||
|
||||
jsonpatchv5 "github.com/evanphx/json-patch/v5"
|
||||
"github.com/pkg/errors"
|
||||
"github.com/prometheus/client_golang/prometheus"
|
||||
corev1 "k8s.io/api/core/v1"
|
||||
rbacv1 "k8s.io/api/rbac/v1"
|
||||
@@ -158,10 +157,10 @@ func (r *KubeadmPhase) GetKubeadmFunction(ctx context.Context, tcp *kamajiv1alph
|
||||
if len(tcp.Spec.Kubernetes.Kubelet.ConfigurationJSONPatches) > 0 {
|
||||
jsonP, patchErr := tcp.Spec.Kubernetes.Kubelet.ConfigurationJSONPatches.ToJSON()
|
||||
if patchErr != nil {
|
||||
return nil, errors.Wrap(patchErr, "cannot encode JSON Patches to JSON")
|
||||
return nil, fmt.Errorf("cannot encode JSON Patches to JSON: %w", patchErr)
|
||||
}
|
||||
if patch, patchErr = jsonpatchv5.DecodePatch(jsonP); patchErr != nil {
|
||||
return nil, errors.Wrap(patchErr, "cannot decode JSON Patches")
|
||||
return nil, fmt.Errorf("cannot decode JSON Patches: %w", patchErr)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -7,7 +7,6 @@ import (
|
||||
"context"
|
||||
"fmt"
|
||||
|
||||
"github.com/pkg/errors"
|
||||
"github.com/prometheus/client_golang/prometheus"
|
||||
"k8s.io/apimachinery/pkg/util/version"
|
||||
"k8s.io/kubernetes/cmd/kubeadm/app/phases/upgrade"
|
||||
@@ -75,7 +74,7 @@ func (k *KubernetesUpgrade) CreateOrUpdate(ctx context.Context, tenantControlPla
|
||||
// Checking if the upgrade is allowed, or not
|
||||
clientSet, err := utilities.GetTenantClientSet(ctx, k.Client, tenantControlPlane)
|
||||
if err != nil {
|
||||
return controllerutil.OperationResultNone, errors.Wrap(err, "cannot create REST client required for Kubernetes upgrade plan")
|
||||
return controllerutil.OperationResultNone, fmt.Errorf("cannot create REST client required for Kubernetes upgrade plan: %w", err)
|
||||
}
|
||||
|
||||
var coreDNSVersion string
|
||||
@@ -86,7 +85,7 @@ func (k *KubernetesUpgrade) CreateOrUpdate(ctx context.Context, tenantControlPla
|
||||
versionGetter := kamajiupgrade.NewKamajiKubeVersionGetter(clientSet, tenantControlPlane.Status.Kubernetes.Version.Version, coreDNSVersion, tenantControlPlane.Status.Kubernetes.Version.Status)
|
||||
|
||||
if _, err = upgrade.GetAvailableUpgrades(versionGetter, false, false, &printers.Discard{}); err != nil {
|
||||
return controllerutil.OperationResultNone, errors.Wrap(err, "cannot retrieve available Upgrades for Kubernetes upgrade plan")
|
||||
return controllerutil.OperationResultNone, fmt.Errorf("cannot retrieve available Upgrades for Kubernetes upgrade plan: %w", err)
|
||||
}
|
||||
|
||||
if err = k.isUpgradable(); err != nil {
|
||||
@@ -123,12 +122,12 @@ func (k *KubernetesUpgrade) UpdateTenantControlPlaneStatus(_ context.Context, te
|
||||
func (k *KubernetesUpgrade) isUpgradable() error {
|
||||
newK8sVersion, err := version.ParseSemantic(k.upgrade.After.KubeVersion)
|
||||
if err != nil {
|
||||
return errors.Wrap(err, fmt.Sprintf("unable to parse normalized version %q as a semantic version", k.upgrade.After.KubeVersion))
|
||||
return fmt.Errorf("unable to parse normalized version %q as a semantic version: %w", k.upgrade.After.KubeVersion, err)
|
||||
}
|
||||
|
||||
oldK8sVersion, err := version.ParseSemantic(k.upgrade.Before.KubeVersion)
|
||||
if err != nil {
|
||||
return errors.Wrap(err, fmt.Sprintf("unable to parse normalized version %q as a semantic version", k.upgrade.After.KubeVersion))
|
||||
return fmt.Errorf("unable to parse normalized version %q as a semantic version: %w", k.upgrade.After.KubeVersion, err)
|
||||
}
|
||||
|
||||
if newK8sVersion.Minor() < oldK8sVersion.Minor() {
|
||||
|
||||
@@ -5,9 +5,9 @@ package resources
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
|
||||
"github.com/go-logr/logr"
|
||||
"github.com/pkg/errors"
|
||||
corev1 "k8s.io/api/core/v1"
|
||||
k8serrors "k8s.io/apimachinery/pkg/api/errors"
|
||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
@@ -25,17 +25,17 @@ import (
|
||||
func GetKubeadmManifestDeps(ctx context.Context, client client.Client, tenantControlPlane *kamajiv1alpha1.TenantControlPlane) (*clientset.Clientset, *kubeadm.Configuration, error) {
|
||||
config, err := getStoredKubeadmConfiguration(ctx, client, "", tenantControlPlane)
|
||||
if err != nil {
|
||||
return nil, nil, errors.Wrap(err, "cannot retrieve kubeadm configuration")
|
||||
return nil, nil, fmt.Errorf("cannot retrieve kubeadm configuration: %w", err)
|
||||
}
|
||||
|
||||
kubeconfig, err := utilities.GetTenantKubeconfig(ctx, client, tenantControlPlane)
|
||||
if err != nil {
|
||||
return nil, nil, errors.Wrap(err, "cannot retrieve kubeconfig configuration")
|
||||
return nil, nil, fmt.Errorf("cannot retrieve kubeconfig configuration: %w", err)
|
||||
}
|
||||
|
||||
address, _, err := tenantControlPlane.AssignedControlPlaneAddress()
|
||||
if err != nil {
|
||||
return nil, nil, errors.Wrap(err, "cannot retrieve Tenant Control Plane address")
|
||||
return nil, nil, fmt.Errorf("cannot retrieve Tenant Control Plane address: %w", err)
|
||||
}
|
||||
|
||||
config.Kubeconfig = *kubeconfig
|
||||
@@ -80,7 +80,7 @@ func GetKubeadmManifestDeps(ctx context.Context, client client.Client, tenantCon
|
||||
|
||||
tenantClient, err := utilities.GetTenantClientSet(ctx, client, tenantControlPlane)
|
||||
if err != nil {
|
||||
return nil, nil, errors.Wrap(err, "cannot generate tenant client")
|
||||
return nil, nil, fmt.Errorf("cannot generate tenant client: %w", err)
|
||||
}
|
||||
|
||||
return tenantClient, config, nil
|
||||
|
||||
@@ -7,7 +7,6 @@ import (
|
||||
"fmt"
|
||||
"runtime"
|
||||
|
||||
"github.com/pkg/errors"
|
||||
versionutil "k8s.io/apimachinery/pkg/util/version"
|
||||
apimachineryversion "k8s.io/apimachinery/pkg/version"
|
||||
"k8s.io/client-go/kubernetes"
|
||||
@@ -63,7 +62,7 @@ func (k kamajiKubeVersionGetter) KubeadmVersion() (string, *versionutil.Version,
|
||||
|
||||
kubeadmVersion, err := versionutil.ParseSemantic(kubeadmVersionInfo.String())
|
||||
if err != nil {
|
||||
return "", nil, errors.Wrap(err, "Couldn't parse kubeadm version")
|
||||
return "", nil, fmt.Errorf("couldn't parse kubeadm version: %w", err)
|
||||
}
|
||||
|
||||
return kubeadmVersionInfo.String(), kubeadmVersion, nil
|
||||
|
||||
@@ -9,7 +9,6 @@ import (
|
||||
"net/http"
|
||||
"strings"
|
||||
|
||||
"github.com/pkg/errors"
|
||||
"gomodules.xyz/jsonpatch/v2"
|
||||
admissionv1 "k8s.io/api/admission/v1"
|
||||
"k8s.io/apimachinery/pkg/runtime"
|
||||
@@ -34,11 +33,11 @@ func (h handlersChainer) Handler(object runtime.Object, routeHandlers ...handler
|
||||
// When deleting the OldObject struct field contains the object being deleted:
|
||||
// https://github.com/kubernetes/kubernetes/pull/76346
|
||||
if err := h.decoder.DecodeRaw(req.OldObject, decodedObj); err != nil {
|
||||
return admission.Errored(http.StatusInternalServerError, errors.Wrap(err, fmt.Sprintf("unable to decode deleted object into %T", object)))
|
||||
return admission.Errored(http.StatusInternalServerError, fmt.Errorf("unable to decode deleted object into %T: %w", object, err))
|
||||
}
|
||||
default:
|
||||
if err := h.decoder.Decode(req, decodedObj); err != nil {
|
||||
return admission.Errored(http.StatusInternalServerError, errors.Wrap(err, fmt.Sprintf("unable to decode into %T", object)))
|
||||
return admission.Errored(http.StatusInternalServerError, fmt.Errorf("unable to decode into %T: %w", object, err))
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -70,7 +69,7 @@ func (h handlersChainer) Handler(object runtime.Object, routeHandlers ...handler
|
||||
}
|
||||
case admissionv1.Update:
|
||||
if err := h.decoder.DecodeRaw(req.OldObject, oldDecodedObj); err != nil {
|
||||
return admission.Errored(http.StatusInternalServerError, errors.Wrap(err, fmt.Sprintf("unable to decode old object into %T", object)))
|
||||
return admission.Errored(http.StatusInternalServerError, fmt.Errorf("unable to decode old object into %T: %w", object, err))
|
||||
}
|
||||
|
||||
for _, routeHandler := range routeHandlers {
|
||||
|
||||
@@ -8,7 +8,6 @@ import (
|
||||
"fmt"
|
||||
"strings"
|
||||
|
||||
"github.com/pkg/errors"
|
||||
"gomodules.xyz/jsonpatch/v2"
|
||||
corev1 "k8s.io/api/core/v1"
|
||||
"k8s.io/apimachinery/pkg/fields"
|
||||
@@ -39,7 +38,7 @@ func (d DataStoreSecretValidation) OnUpdate(object runtime.Object, _ runtime.Obj
|
||||
dsList := &kamajiv1alpha1.DataStoreList{}
|
||||
|
||||
if err := d.Client.List(ctx, dsList, client.MatchingFieldsSelector{Selector: fields.OneTermEqualSelector(kamajiv1alpha1.DatastoreUsedSecretNamespacedNameKey, fmt.Sprintf("%s/%s", secret.GetNamespace(), secret.GetName()))}); err != nil {
|
||||
return nil, errors.Wrap(err, "cannot list Tenant Control Plane using the provided Secret")
|
||||
return nil, fmt.Errorf("cannot list Tenant Control Plane using the provided Secret: %w", err)
|
||||
}
|
||||
|
||||
if len(dsList.Items) > 0 {
|
||||
|
||||
@@ -7,7 +7,6 @@ import (
|
||||
"context"
|
||||
"fmt"
|
||||
|
||||
"github.com/pkg/errors"
|
||||
"gomodules.xyz/jsonpatch/v2"
|
||||
corev1 "k8s.io/api/core/v1"
|
||||
k8serrors "k8s.io/apimachinery/pkg/api/errors"
|
||||
@@ -38,7 +37,7 @@ func (d DataStoreValidation) OnDelete(object runtime.Object) AdmissionResponse {
|
||||
|
||||
tcpList := &kamajiv1alpha1.TenantControlPlaneList{}
|
||||
if err := d.Client.List(ctx, tcpList, client.MatchingFieldsSelector{Selector: fields.OneTermEqualSelector(kamajiv1alpha1.TenantControlPlaneUsedDataStoreKey, ds.GetName())}); err != nil {
|
||||
return nil, errors.Wrap(err, "cannot retrieve TenantControlPlane list used by the DataStore")
|
||||
return nil, fmt.Errorf("cannot retrieve TenantControlPlane list used by the DataStore: %w", err)
|
||||
}
|
||||
|
||||
if len(tcpList.Items) > 0 {
|
||||
|
||||
@@ -5,9 +5,9 @@ package handlers
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"net"
|
||||
|
||||
"github.com/pkg/errors"
|
||||
"gomodules.xyz/jsonpatch/v2"
|
||||
"k8s.io/apimachinery/pkg/runtime"
|
||||
pointer "k8s.io/utils/ptr"
|
||||
@@ -31,7 +31,7 @@ func (t TenantControlPlaneDefaults) OnCreate(object runtime.Object) AdmissionRes
|
||||
if len(defaulted.Spec.NetworkProfile.DNSServiceIPs) == 0 {
|
||||
ip, _, err := net.ParseCIDR(defaulted.Spec.NetworkProfile.ServiceCIDR)
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "cannot define resulting DNS Service IP")
|
||||
return nil, fmt.Errorf("cannot define resulting DNS Service IP: %w", err)
|
||||
}
|
||||
switch {
|
||||
case ip.To4() != nil:
|
||||
@@ -45,7 +45,7 @@ func (t TenantControlPlaneDefaults) OnCreate(object runtime.Object) AdmissionRes
|
||||
|
||||
operations, err := utils.JSONPatch(original, defaulted)
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "cannot create patch responses upon Tenant Control Plane creation")
|
||||
return nil, fmt.Errorf("cannot create patch responses upon Tenant Control Plane creation: %w", err)
|
||||
}
|
||||
|
||||
return operations, nil
|
||||
|
||||
@@ -5,9 +5,9 @@ package handlers
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
|
||||
"github.com/google/go-cmp/cmp"
|
||||
"github.com/pkg/errors"
|
||||
"gomodules.xyz/jsonpatch/v2"
|
||||
appsv1 "k8s.io/api/apps/v1"
|
||||
k8serrors "k8s.io/apimachinery/pkg/api/errors"
|
||||
@@ -103,7 +103,7 @@ func (t TenantControlPlaneDeployment) OnUpdate(newObject runtime.Object, oldObje
|
||||
}
|
||||
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "the resulting Deployment will generate a configuration error, cannot proceed")
|
||||
return nil, fmt.Errorf("the resulting Deployment will generate a configuration error, cannot proceed: %w", err)
|
||||
}
|
||||
|
||||
return nil, nil
|
||||
|
||||
@@ -9,7 +9,6 @@ import (
|
||||
"strings"
|
||||
|
||||
"github.com/blang/semver"
|
||||
"github.com/pkg/errors"
|
||||
"gomodules.xyz/jsonpatch/v2"
|
||||
"k8s.io/apimachinery/pkg/runtime"
|
||||
"sigs.k8s.io/controller-runtime/pkg/webhook/admission"
|
||||
@@ -27,14 +26,14 @@ func (t TenantControlPlaneVersion) OnCreate(object runtime.Object) AdmissionResp
|
||||
|
||||
ver, err := semver.New(t.normalizeKubernetesVersion(tcp.Spec.Kubernetes.Version))
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "unable to parse the desired Kubernetes version")
|
||||
return nil, fmt.Errorf("unable to parse the desired Kubernetes version: %w", err)
|
||||
}
|
||||
// No need to check if the patch version
|
||||
ver.Patch = 0
|
||||
|
||||
supportedVer, supportedErr := semver.Make(t.normalizeKubernetesVersion(upgrade.KubeadmVersion))
|
||||
if supportedErr != nil {
|
||||
return nil, errors.Wrap(supportedErr, "unable to parse the Kamaji supported Kubernetes version")
|
||||
return nil, fmt.Errorf("unable to parse the Kamaji supported Kubernetes version: %w", supportedErr)
|
||||
}
|
||||
|
||||
if ver.GT(supportedVer) {
|
||||
@@ -67,21 +66,21 @@ func (t TenantControlPlaneVersion) OnUpdate(object runtime.Object, oldObject run
|
||||
|
||||
oldVer, oldErr := semver.Make(t.normalizeKubernetesVersion(oldTCP.Spec.Kubernetes.Version))
|
||||
if oldErr != nil {
|
||||
return nil, errors.Wrap(oldErr, "unable to parse the previous Kubernetes version")
|
||||
return nil, fmt.Errorf("unable to parse the previous Kubernetes version: %w", oldErr)
|
||||
}
|
||||
// No need to check if the patch version
|
||||
oldVer.Patch = 0
|
||||
|
||||
newVer, newErr := semver.New(t.normalizeKubernetesVersion(newTCP.Spec.Kubernetes.Version))
|
||||
if newErr != nil {
|
||||
return nil, errors.Wrap(newErr, "unable to parse the desired Kubernetes version")
|
||||
return nil, fmt.Errorf("unable to parse the desired Kubernetes version: %w", newErr)
|
||||
}
|
||||
// No need to check if the patch version
|
||||
newVer.Patch = 0
|
||||
|
||||
supportedVer, supportedErr := semver.Make(t.normalizeKubernetesVersion(upgrade.KubeadmVersion))
|
||||
if supportedErr != nil {
|
||||
return nil, errors.Wrap(supportedErr, "unable to parse the Kamaji supported Kubernetes version")
|
||||
return nil, fmt.Errorf("unable to parse the Kamaji supported Kubernetes version: %w", supportedErr)
|
||||
}
|
||||
|
||||
switch {
|
||||
|
||||
@@ -4,8 +4,9 @@
|
||||
package utils
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
json "github.com/json-iterator/go"
|
||||
"github.com/pkg/errors"
|
||||
"gomodules.xyz/jsonpatch/v2"
|
||||
"sigs.k8s.io/controller-runtime/pkg/client"
|
||||
)
|
||||
@@ -13,12 +14,12 @@ import (
|
||||
func JSONPatch(original, modified client.Object) ([]jsonpatch.Operation, error) {
|
||||
originalJSON, err := json.Marshal(original)
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "cannot marshal original object")
|
||||
return nil, fmt.Errorf("cannot marshal original object: %w", err)
|
||||
}
|
||||
|
||||
modifiedJSON, err := json.Marshal(modified)
|
||||
if err != nil {
|
||||
return nil, errors.Wrap(err, "cannot marshal modified object")
|
||||
return nil, fmt.Errorf("cannot marshal modified object: %w", err)
|
||||
}
|
||||
|
||||
return jsonpatch.CreatePatch(originalJSON, modifiedJSON)
|
||||
|
||||
Reference in New Issue
Block a user