mirror of https://github.com/grafana/loki
Set lokistack condition failed/pending/ready based on pod status map (#53)
parent
6a12aef097
commit
7045c92086
@ -1,38 +0,0 @@ |
|||||||
package status |
|
||||||
|
|
||||||
import ( |
|
||||||
"context" |
|
||||||
|
|
||||||
lokiv1beta1 "github.com/ViaQ/loki-operator/api/v1beta1" |
|
||||||
"github.com/ViaQ/loki-operator/internal/external/k8s" |
|
||||||
"sigs.k8s.io/controller-runtime/pkg/client" |
|
||||||
|
|
||||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" |
|
||||||
) |
|
||||||
|
|
||||||
// SetDegradedCondition appends the condition Degraded to the lokistack status conditions.
|
|
||||||
func SetDegradedCondition(ctx context.Context, k k8s.Client, s *lokiv1beta1.LokiStack, msg string, reason lokiv1beta1.LokiStackConditionReason) error { |
|
||||||
reasonStr := string(reason) |
|
||||||
for _, cond := range s.Status.Conditions { |
|
||||||
if cond.Type == string(lokiv1beta1.ConditionDegraded) && cond.Reason == reasonStr { |
|
||||||
return nil |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
status := s.Status.DeepCopy() |
|
||||||
if status.Conditions == nil { |
|
||||||
status.Conditions = []metav1.Condition{} |
|
||||||
} |
|
||||||
|
|
||||||
degraded := metav1.Condition{ |
|
||||||
Type: string(lokiv1beta1.ConditionDegraded), |
|
||||||
Status: metav1.ConditionTrue, |
|
||||||
LastTransitionTime: metav1.Now(), |
|
||||||
Reason: reasonStr, |
|
||||||
Message: msg, |
|
||||||
} |
|
||||||
|
|
||||||
status.Conditions = append(status.Conditions, degraded) |
|
||||||
s.Status = *status |
|
||||||
return k.Status().Update(ctx, s, &client.UpdateOptions{}) |
|
||||||
} |
|
@ -1,53 +0,0 @@ |
|||||||
package status_test |
|
||||||
|
|
||||||
import ( |
|
||||||
"context" |
|
||||||
"testing" |
|
||||||
|
|
||||||
lokiv1beta1 "github.com/ViaQ/loki-operator/api/v1beta1" |
|
||||||
"github.com/ViaQ/loki-operator/internal/external/k8s/k8sfakes" |
|
||||||
"github.com/ViaQ/loki-operator/internal/handlers/internal/status" |
|
||||||
|
|
||||||
"github.com/stretchr/testify/require" |
|
||||||
|
|
||||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" |
|
||||||
"sigs.k8s.io/controller-runtime/pkg/client" |
|
||||||
) |
|
||||||
|
|
||||||
func TestSetDegradedCondition_WhenExisting_DoNothing(t *testing.T) { |
|
||||||
k := &k8sfakes.FakeClient{} |
|
||||||
|
|
||||||
msg := "tell me nothing" |
|
||||||
reason := lokiv1beta1.ReasonMissingObjectStorageSecret |
|
||||||
s := lokiv1beta1.LokiStack{ |
|
||||||
Status: lokiv1beta1.LokiStackStatus{ |
|
||||||
Conditions: []metav1.Condition{ |
|
||||||
{ |
|
||||||
Type: string(lokiv1beta1.ConditionDegraded), |
|
||||||
Reason: string(reason), |
|
||||||
}, |
|
||||||
}, |
|
||||||
}, |
|
||||||
} |
|
||||||
|
|
||||||
err := status.SetDegradedCondition(context.TODO(), k, &s, msg, reason) |
|
||||||
require.NoError(t, err) |
|
||||||
} |
|
||||||
|
|
||||||
func TestSetDegradedCondition_WhenNoneExisting_AppendDegradedCondition(t *testing.T) { |
|
||||||
sw := &k8sfakes.FakeStatusWriter{} |
|
||||||
k := &k8sfakes.FakeClient{} |
|
||||||
|
|
||||||
k.StatusStub = func() client.StatusWriter { return sw } |
|
||||||
|
|
||||||
msg := "tell me something" |
|
||||||
reason := lokiv1beta1.ReasonMissingObjectStorageSecret |
|
||||||
s := lokiv1beta1.LokiStack{} |
|
||||||
|
|
||||||
err := status.SetDegradedCondition(context.TODO(), k, &s, msg, reason) |
|
||||||
require.NoError(t, err) |
|
||||||
|
|
||||||
require.NotZero(t, k.StatusCallCount()) |
|
||||||
require.NotZero(t, sw.UpdateCallCount()) |
|
||||||
require.NotEmpty(t, s.Status.Conditions) |
|
||||||
} |
|
@ -0,0 +1,162 @@ |
|||||||
|
package status_test |
||||||
|
|
||||||
|
import ( |
||||||
|
"context" |
||||||
|
"testing" |
||||||
|
|
||||||
|
lokiv1beta1 "github.com/ViaQ/loki-operator/api/v1beta1" |
||||||
|
"github.com/ViaQ/loki-operator/internal/external/k8s/k8sfakes" |
||||||
|
"github.com/ViaQ/loki-operator/internal/status" |
||||||
|
"github.com/stretchr/testify/require" |
||||||
|
|
||||||
|
v1 "k8s.io/api/core/v1" |
||||||
|
apierrors "k8s.io/apimachinery/pkg/api/errors" |
||||||
|
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" |
||||||
|
"k8s.io/apimachinery/pkg/runtime/schema" |
||||||
|
"k8s.io/apimachinery/pkg/types" |
||||||
|
ctrl "sigs.k8s.io/controller-runtime" |
||||||
|
"sigs.k8s.io/controller-runtime/pkg/client" |
||||||
|
) |
||||||
|
|
||||||
|
func TestSetComponentsStatus_WhenGetLokiStackReturnsError_ReturnError(t *testing.T) { |
||||||
|
k := &k8sfakes.FakeClient{} |
||||||
|
|
||||||
|
r := ctrl.Request{ |
||||||
|
NamespacedName: types.NamespacedName{ |
||||||
|
Name: "my-stack", |
||||||
|
Namespace: "some-ns", |
||||||
|
}, |
||||||
|
} |
||||||
|
|
||||||
|
k.GetStub = func(_ context.Context, name types.NamespacedName, object client.Object) error { |
||||||
|
return apierrors.NewBadRequest("something wasn't found") |
||||||
|
} |
||||||
|
|
||||||
|
err := status.SetComponentsStatus(context.TODO(), k, r) |
||||||
|
require.Error(t, err) |
||||||
|
} |
||||||
|
|
||||||
|
func TestSetComponentsStatus_WhenGetLokiStackReturnsNotFound_DoNothing(t *testing.T) { |
||||||
|
k := &k8sfakes.FakeClient{} |
||||||
|
|
||||||
|
r := ctrl.Request{ |
||||||
|
NamespacedName: types.NamespacedName{ |
||||||
|
Name: "my-stack", |
||||||
|
Namespace: "some-ns", |
||||||
|
}, |
||||||
|
} |
||||||
|
|
||||||
|
k.GetStub = func(_ context.Context, name types.NamespacedName, object client.Object) error { |
||||||
|
return apierrors.NewNotFound(schema.GroupResource{}, "something wasn't found") |
||||||
|
} |
||||||
|
|
||||||
|
err := status.SetComponentsStatus(context.TODO(), k, r) |
||||||
|
require.NoError(t, err) |
||||||
|
} |
||||||
|
|
||||||
|
func TestSetComponentsStatus_WhenListReturnError_ReturnError(t *testing.T) { |
||||||
|
sw := &k8sfakes.FakeStatusWriter{} |
||||||
|
k := &k8sfakes.FakeClient{} |
||||||
|
|
||||||
|
k.StatusStub = func() client.StatusWriter { return sw } |
||||||
|
|
||||||
|
s := lokiv1beta1.LokiStack{ |
||||||
|
ObjectMeta: metav1.ObjectMeta{ |
||||||
|
Name: "my-stack", |
||||||
|
Namespace: "some-ns", |
||||||
|
}, |
||||||
|
} |
||||||
|
|
||||||
|
r := ctrl.Request{ |
||||||
|
NamespacedName: types.NamespacedName{ |
||||||
|
Name: "my-stack", |
||||||
|
Namespace: "some-ns", |
||||||
|
}, |
||||||
|
} |
||||||
|
|
||||||
|
k.GetStub = func(_ context.Context, name types.NamespacedName, object client.Object) error { |
||||||
|
if r.Name == name.Name && r.Namespace == name.Namespace { |
||||||
|
k.SetClientObject(object, &s) |
||||||
|
return nil |
||||||
|
} |
||||||
|
return apierrors.NewNotFound(schema.GroupResource{}, "something wasn't found") |
||||||
|
} |
||||||
|
|
||||||
|
k.ListStub = func(_ context.Context, l client.ObjectList, opts ...client.ListOption) error { |
||||||
|
return apierrors.NewNotFound(schema.GroupResource{}, "something wasn't found") |
||||||
|
} |
||||||
|
|
||||||
|
err := status.SetComponentsStatus(context.TODO(), k, r) |
||||||
|
require.Error(t, err) |
||||||
|
} |
||||||
|
|
||||||
|
func TestSetComponentsStatus_WhenPodListExisting_SetPodStatusMap(t *testing.T) { |
||||||
|
sw := &k8sfakes.FakeStatusWriter{} |
||||||
|
k := &k8sfakes.FakeClient{} |
||||||
|
|
||||||
|
k.StatusStub = func() client.StatusWriter { return sw } |
||||||
|
|
||||||
|
s := lokiv1beta1.LokiStack{ |
||||||
|
ObjectMeta: metav1.ObjectMeta{ |
||||||
|
Name: "my-stack", |
||||||
|
Namespace: "some-ns", |
||||||
|
}, |
||||||
|
} |
||||||
|
|
||||||
|
r := ctrl.Request{ |
||||||
|
NamespacedName: types.NamespacedName{ |
||||||
|
Name: "my-stack", |
||||||
|
Namespace: "some-ns", |
||||||
|
}, |
||||||
|
} |
||||||
|
|
||||||
|
k.GetStub = func(_ context.Context, name types.NamespacedName, object client.Object) error { |
||||||
|
if r.Name == name.Name && r.Namespace == name.Namespace { |
||||||
|
k.SetClientObject(object, &s) |
||||||
|
return nil |
||||||
|
} |
||||||
|
return apierrors.NewNotFound(schema.GroupResource{}, "something wasn't found") |
||||||
|
} |
||||||
|
|
||||||
|
k.ListStub = func(_ context.Context, l client.ObjectList, _ ...client.ListOption) error { |
||||||
|
pods := v1.PodList{ |
||||||
|
Items: []v1.Pod{ |
||||||
|
{ |
||||||
|
ObjectMeta: metav1.ObjectMeta{ |
||||||
|
Name: "pod-a", |
||||||
|
}, |
||||||
|
Status: v1.PodStatus{ |
||||||
|
Phase: v1.PodPending, |
||||||
|
}, |
||||||
|
}, |
||||||
|
{ |
||||||
|
ObjectMeta: metav1.ObjectMeta{ |
||||||
|
Name: "pod-b", |
||||||
|
}, |
||||||
|
Status: v1.PodStatus{ |
||||||
|
Phase: v1.PodRunning, |
||||||
|
}, |
||||||
|
}, |
||||||
|
}, |
||||||
|
} |
||||||
|
k.SetClientObjectList(l, &pods) |
||||||
|
return nil |
||||||
|
} |
||||||
|
|
||||||
|
expected := lokiv1beta1.PodStatusMap{ |
||||||
|
"Pending": []string{"pod-a"}, |
||||||
|
"Running": []string{"pod-b"}, |
||||||
|
} |
||||||
|
|
||||||
|
sw.UpdateStub = func(_ context.Context, obj client.Object, _ ...client.UpdateOption) error { |
||||||
|
stack := obj.(*lokiv1beta1.LokiStack) |
||||||
|
require.Equal(t, expected, stack.Status.Components.Compactor) |
||||||
|
return nil |
||||||
|
} |
||||||
|
|
||||||
|
err := status.SetComponentsStatus(context.TODO(), k, r) |
||||||
|
require.NoError(t, err) |
||||||
|
require.NotZero(t, k.ListCallCount()) |
||||||
|
require.NotZero(t, k.StatusCallCount()) |
||||||
|
require.NotZero(t, sw.UpdateCallCount()) |
||||||
|
} |
@ -0,0 +1,198 @@ |
|||||||
|
package status |
||||||
|
|
||||||
|
import ( |
||||||
|
"context" |
||||||
|
|
||||||
|
"github.com/ViaQ/logerr/kverrors" |
||||||
|
lokiv1beta1 "github.com/ViaQ/loki-operator/api/v1beta1" |
||||||
|
"github.com/ViaQ/loki-operator/internal/external/k8s" |
||||||
|
|
||||||
|
apierrors "k8s.io/apimachinery/pkg/api/errors" |
||||||
|
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" |
||||||
|
ctrl "sigs.k8s.io/controller-runtime" |
||||||
|
"sigs.k8s.io/controller-runtime/pkg/client" |
||||||
|
) |
||||||
|
|
||||||
|
// SetReadyCondition updates or appends the condition Ready to the lokistack status conditions.
|
||||||
|
// In addition it resets all other Status conditions to false.
|
||||||
|
func SetReadyCondition(ctx context.Context, k k8s.Client, req ctrl.Request) error { |
||||||
|
var s lokiv1beta1.LokiStack |
||||||
|
if err := k.Get(ctx, req.NamespacedName, &s); err != nil { |
||||||
|
if apierrors.IsNotFound(err) { |
||||||
|
return nil |
||||||
|
} |
||||||
|
return kverrors.Wrap(err, "failed to lookup lokistack", "name", req.NamespacedName) |
||||||
|
} |
||||||
|
|
||||||
|
for _, cond := range s.Status.Conditions { |
||||||
|
if cond.Type == string(lokiv1beta1.ConditionReady) && cond.Status == metav1.ConditionTrue { |
||||||
|
return nil |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
ready := metav1.Condition{ |
||||||
|
Type: string(lokiv1beta1.ConditionReady), |
||||||
|
Status: metav1.ConditionTrue, |
||||||
|
LastTransitionTime: metav1.Now(), |
||||||
|
Message: "All components ready", |
||||||
|
Reason: string(lokiv1beta1.ReasonReadyComponents), |
||||||
|
} |
||||||
|
|
||||||
|
index := -1 |
||||||
|
for i := range s.Status.Conditions { |
||||||
|
// Reset all other conditions first
|
||||||
|
s.Status.Conditions[i].Status = metav1.ConditionFalse |
||||||
|
s.Status.Conditions[i].LastTransitionTime = metav1.Now() |
||||||
|
|
||||||
|
// Locate existing ready condition if any
|
||||||
|
if s.Status.Conditions[i].Type == string(lokiv1beta1.ConditionReady) { |
||||||
|
index = i |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
if index == -1 { |
||||||
|
s.Status.Conditions = append(s.Status.Conditions, ready) |
||||||
|
} else { |
||||||
|
s.Status.Conditions[index] = ready |
||||||
|
} |
||||||
|
|
||||||
|
return k.Status().Update(ctx, &s, &client.UpdateOptions{}) |
||||||
|
} |
||||||
|
|
||||||
|
// SetFailedCondition updates or appends the condition Failed to the lokistack status conditions.
|
||||||
|
// In addition it resets all other Status conditions to false.
|
||||||
|
func SetFailedCondition(ctx context.Context, k k8s.Client, req ctrl.Request) error { |
||||||
|
var s lokiv1beta1.LokiStack |
||||||
|
if err := k.Get(ctx, req.NamespacedName, &s); err != nil { |
||||||
|
if apierrors.IsNotFound(err) { |
||||||
|
return nil |
||||||
|
} |
||||||
|
return kverrors.Wrap(err, "failed to lookup lokistack", "name", req.NamespacedName) |
||||||
|
} |
||||||
|
|
||||||
|
for _, cond := range s.Status.Conditions { |
||||||
|
if cond.Type == string(lokiv1beta1.ConditionFailed) && cond.Status == metav1.ConditionTrue { |
||||||
|
return nil |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
failed := metav1.Condition{ |
||||||
|
Type: string(lokiv1beta1.ConditionFailed), |
||||||
|
Status: metav1.ConditionTrue, |
||||||
|
LastTransitionTime: metav1.Now(), |
||||||
|
Message: "Some LokiStack components failed", |
||||||
|
Reason: string(lokiv1beta1.ReasonFailedComponents), |
||||||
|
} |
||||||
|
|
||||||
|
index := -1 |
||||||
|
for i := range s.Status.Conditions { |
||||||
|
// Reset all other conditions first
|
||||||
|
s.Status.Conditions[i].Status = metav1.ConditionFalse |
||||||
|
s.Status.Conditions[i].LastTransitionTime = metav1.Now() |
||||||
|
|
||||||
|
// Locate existing failed condition if any
|
||||||
|
if s.Status.Conditions[i].Type == string(lokiv1beta1.ConditionFailed) { |
||||||
|
index = i |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
if index == -1 { |
||||||
|
s.Status.Conditions = append(s.Status.Conditions, failed) |
||||||
|
} else { |
||||||
|
s.Status.Conditions[index] = failed |
||||||
|
} |
||||||
|
|
||||||
|
return k.Status().Update(ctx, &s, &client.UpdateOptions{}) |
||||||
|
} |
||||||
|
|
||||||
|
// SetPendingCondition updates or appends the condition Pending to the lokistack status conditions.
|
||||||
|
// In addition it resets all other Status conditions to false.
|
||||||
|
func SetPendingCondition(ctx context.Context, k k8s.Client, req ctrl.Request) error { |
||||||
|
var s lokiv1beta1.LokiStack |
||||||
|
if err := k.Get(ctx, req.NamespacedName, &s); err != nil { |
||||||
|
if apierrors.IsNotFound(err) { |
||||||
|
return nil |
||||||
|
} |
||||||
|
return kverrors.Wrap(err, "failed to lookup lokistack", "name", req.NamespacedName) |
||||||
|
} |
||||||
|
|
||||||
|
for _, cond := range s.Status.Conditions { |
||||||
|
if cond.Type == string(lokiv1beta1.ConditionPending) && cond.Status == metav1.ConditionTrue { |
||||||
|
return nil |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
pending := metav1.Condition{ |
||||||
|
Type: string(lokiv1beta1.ConditionPending), |
||||||
|
Status: metav1.ConditionTrue, |
||||||
|
LastTransitionTime: metav1.Now(), |
||||||
|
Message: "Some LokiStack components pending on dependendies", |
||||||
|
Reason: string(lokiv1beta1.ReasonPendingComponents), |
||||||
|
} |
||||||
|
|
||||||
|
index := -1 |
||||||
|
for i := range s.Status.Conditions { |
||||||
|
// Reset all other conditions first
|
||||||
|
s.Status.Conditions[i].Status = metav1.ConditionFalse |
||||||
|
s.Status.Conditions[i].LastTransitionTime = metav1.Now() |
||||||
|
|
||||||
|
// Locate existing pending condition if any
|
||||||
|
if s.Status.Conditions[i].Type == string(lokiv1beta1.ConditionPending) { |
||||||
|
index = i |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
if index == -1 { |
||||||
|
s.Status.Conditions = append(s.Status.Conditions, pending) |
||||||
|
} else { |
||||||
|
s.Status.Conditions[index] = pending |
||||||
|
} |
||||||
|
|
||||||
|
return k.Status().Update(ctx, &s, &client.UpdateOptions{}) |
||||||
|
} |
||||||
|
|
||||||
|
// SetDegradedCondition appends the condition Degraded to the lokistack status conditions.
|
||||||
|
func SetDegradedCondition(ctx context.Context, k k8s.Client, req ctrl.Request, msg string, reason lokiv1beta1.LokiStackConditionReason) error { |
||||||
|
var s lokiv1beta1.LokiStack |
||||||
|
if err := k.Get(ctx, req.NamespacedName, &s); err != nil { |
||||||
|
if apierrors.IsNotFound(err) { |
||||||
|
return nil |
||||||
|
} |
||||||
|
return kverrors.Wrap(err, "failed to lookup lokistack", "name", req.NamespacedName) |
||||||
|
} |
||||||
|
|
||||||
|
reasonStr := string(reason) |
||||||
|
for _, cond := range s.Status.Conditions { |
||||||
|
if cond.Type == string(lokiv1beta1.ConditionDegraded) && cond.Reason == reasonStr && cond.Status == metav1.ConditionTrue { |
||||||
|
return nil |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
degraded := metav1.Condition{ |
||||||
|
Type: string(lokiv1beta1.ConditionDegraded), |
||||||
|
Status: metav1.ConditionTrue, |
||||||
|
LastTransitionTime: metav1.Now(), |
||||||
|
Reason: reasonStr, |
||||||
|
Message: msg, |
||||||
|
} |
||||||
|
|
||||||
|
index := -1 |
||||||
|
for i := range s.Status.Conditions { |
||||||
|
// Reset all other conditions first
|
||||||
|
s.Status.Conditions[i].Status = metav1.ConditionFalse |
||||||
|
s.Status.Conditions[i].LastTransitionTime = metav1.Now() |
||||||
|
|
||||||
|
// Locate existing pending condition if any
|
||||||
|
if s.Status.Conditions[i].Type == string(lokiv1beta1.ConditionDegraded) { |
||||||
|
index = i |
||||||
|
} |
||||||
|
} |
||||||
|
|
||||||
|
if index == -1 { |
||||||
|
s.Status.Conditions = append(s.Status.Conditions, degraded) |
||||||
|
} else { |
||||||
|
s.Status.Conditions[index] = degraded |
||||||
|
} |
||||||
|
|
||||||
|
return k.Status().Update(ctx, &s, &client.UpdateOptions{}) |
||||||
|
} |
@ -0,0 +1,691 @@ |
|||||||
|
package status_test |
||||||
|
|
||||||
|
import ( |
||||||
|
"context" |
||||||
|
"testing" |
||||||
|
|
||||||
|
lokiv1beta1 "github.com/ViaQ/loki-operator/api/v1beta1" |
||||||
|
"github.com/ViaQ/loki-operator/internal/external/k8s/k8sfakes" |
||||||
|
"github.com/ViaQ/loki-operator/internal/status" |
||||||
|
|
||||||
|
"github.com/stretchr/testify/require" |
||||||
|
|
||||||
|
apierrors "k8s.io/apimachinery/pkg/api/errors" |
||||||
|
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" |
||||||
|
"k8s.io/apimachinery/pkg/runtime/schema" |
||||||
|
"k8s.io/apimachinery/pkg/types" |
||||||
|
ctrl "sigs.k8s.io/controller-runtime" |
||||||
|
"sigs.k8s.io/controller-runtime/pkg/client" |
||||||
|
) |
||||||
|
|
||||||
|
func TestSetReadyCondition_WhenGetLokiStackReturnsError_ReturnError(t *testing.T) { |
||||||
|
k := &k8sfakes.FakeClient{} |
||||||
|
|
||||||
|
r := ctrl.Request{ |
||||||
|
NamespacedName: types.NamespacedName{ |
||||||
|
Name: "my-stack", |
||||||
|
Namespace: "some-ns", |
||||||
|
}, |
||||||
|
} |
||||||
|
|
||||||
|
k.GetStub = func(_ context.Context, name types.NamespacedName, object client.Object) error { |
||||||
|
return apierrors.NewBadRequest("something wasn't found") |
||||||
|
} |
||||||
|
|
||||||
|
err := status.SetReadyCondition(context.TODO(), k, r) |
||||||
|
require.Error(t, err) |
||||||
|
} |
||||||
|
|
||||||
|
func TestSetReadyCondition_WhenGetLokiStackReturnsNotFound_DoNothing(t *testing.T) { |
||||||
|
k := &k8sfakes.FakeClient{} |
||||||
|
|
||||||
|
r := ctrl.Request{ |
||||||
|
NamespacedName: types.NamespacedName{ |
||||||
|
Name: "my-stack", |
||||||
|
Namespace: "some-ns", |
||||||
|
}, |
||||||
|
} |
||||||
|
|
||||||
|
k.GetStub = func(_ context.Context, name types.NamespacedName, object client.Object) error { |
||||||
|
return apierrors.NewNotFound(schema.GroupResource{}, "something wasn't found") |
||||||
|
} |
||||||
|
|
||||||
|
err := status.SetReadyCondition(context.TODO(), k, r) |
||||||
|
require.NoError(t, err) |
||||||
|
} |
||||||
|
|
||||||
|
func TestSetReadyCondition_WhenExisting_DoNothing(t *testing.T) { |
||||||
|
k := &k8sfakes.FakeClient{} |
||||||
|
|
||||||
|
s := lokiv1beta1.LokiStack{ |
||||||
|
ObjectMeta: metav1.ObjectMeta{ |
||||||
|
Name: "my-stack", |
||||||
|
Namespace: "some-ns", |
||||||
|
}, |
||||||
|
Status: lokiv1beta1.LokiStackStatus{ |
||||||
|
Conditions: []metav1.Condition{ |
||||||
|
{ |
||||||
|
Type: string(lokiv1beta1.ConditionReady), |
||||||
|
Status: metav1.ConditionTrue, |
||||||
|
}, |
||||||
|
}, |
||||||
|
}, |
||||||
|
} |
||||||
|
|
||||||
|
r := ctrl.Request{ |
||||||
|
NamespacedName: types.NamespacedName{ |
||||||
|
Name: "my-stack", |
||||||
|
Namespace: "some-ns", |
||||||
|
}, |
||||||
|
} |
||||||
|
|
||||||
|
k.GetStub = func(_ context.Context, name types.NamespacedName, object client.Object) error { |
||||||
|
if r.Name == name.Name && r.Namespace == name.Namespace { |
||||||
|
k.SetClientObject(object, &s) |
||||||
|
return nil |
||||||
|
} |
||||||
|
return apierrors.NewNotFound(schema.GroupResource{}, "something wasn't found") |
||||||
|
} |
||||||
|
|
||||||
|
err := status.SetReadyCondition(context.TODO(), k, r) |
||||||
|
require.NoError(t, err) |
||||||
|
require.Zero(t, k.StatusCallCount()) |
||||||
|
} |
||||||
|
|
||||||
|
func TestSetReadyCondition_WhenExisting_SetReadyConditionTrue(t *testing.T) { |
||||||
|
sw := &k8sfakes.FakeStatusWriter{} |
||||||
|
k := &k8sfakes.FakeClient{} |
||||||
|
|
||||||
|
k.StatusStub = func() client.StatusWriter { return sw } |
||||||
|
|
||||||
|
s := lokiv1beta1.LokiStack{ |
||||||
|
ObjectMeta: metav1.ObjectMeta{ |
||||||
|
Name: "my-stack", |
||||||
|
Namespace: "some-ns", |
||||||
|
}, |
||||||
|
Status: lokiv1beta1.LokiStackStatus{ |
||||||
|
Conditions: []metav1.Condition{ |
||||||
|
{ |
||||||
|
Type: string(lokiv1beta1.ConditionReady), |
||||||
|
Status: metav1.ConditionFalse, |
||||||
|
}, |
||||||
|
}, |
||||||
|
}, |
||||||
|
} |
||||||
|
|
||||||
|
r := ctrl.Request{ |
||||||
|
NamespacedName: types.NamespacedName{ |
||||||
|
Name: "my-stack", |
||||||
|
Namespace: "some-ns", |
||||||
|
}, |
||||||
|
} |
||||||
|
|
||||||
|
k.GetStub = func(_ context.Context, name types.NamespacedName, object client.Object) error { |
||||||
|
if r.Name == name.Name && r.Namespace == name.Namespace { |
||||||
|
k.SetClientObject(object, &s) |
||||||
|
return nil |
||||||
|
} |
||||||
|
return apierrors.NewNotFound(schema.GroupResource{}, "something wasn't found") |
||||||
|
} |
||||||
|
|
||||||
|
sw.UpdateStub = func(_ context.Context, obj client.Object, _ ...client.UpdateOption) error { |
||||||
|
actual := obj.(*lokiv1beta1.LokiStack) |
||||||
|
require.NotEmpty(t, actual.Status.Conditions) |
||||||
|
require.Equal(t, metav1.ConditionTrue, actual.Status.Conditions[0].Status) |
||||||
|
return nil |
||||||
|
} |
||||||
|
|
||||||
|
err := status.SetReadyCondition(context.TODO(), k, r) |
||||||
|
require.NoError(t, err) |
||||||
|
|
||||||
|
require.NotZero(t, k.StatusCallCount()) |
||||||
|
require.NotZero(t, sw.UpdateCallCount()) |
||||||
|
} |
||||||
|
|
||||||
|
func TestSetReadyCondition_WhenNoneExisting_AppendReadyCondition(t *testing.T) { |
||||||
|
sw := &k8sfakes.FakeStatusWriter{} |
||||||
|
k := &k8sfakes.FakeClient{} |
||||||
|
|
||||||
|
k.StatusStub = func() client.StatusWriter { return sw } |
||||||
|
|
||||||
|
s := lokiv1beta1.LokiStack{ |
||||||
|
ObjectMeta: metav1.ObjectMeta{ |
||||||
|
Name: "my-stack", |
||||||
|
Namespace: "some-ns", |
||||||
|
}, |
||||||
|
} |
||||||
|
|
||||||
|
r := ctrl.Request{ |
||||||
|
NamespacedName: types.NamespacedName{ |
||||||
|
Name: "my-stack", |
||||||
|
Namespace: "some-ns", |
||||||
|
}, |
||||||
|
} |
||||||
|
|
||||||
|
k.GetStub = func(_ context.Context, name types.NamespacedName, object client.Object) error { |
||||||
|
if r.Name == name.Name && r.Namespace == name.Namespace { |
||||||
|
k.SetClientObject(object, &s) |
||||||
|
return nil |
||||||
|
} |
||||||
|
return apierrors.NewNotFound(schema.GroupResource{}, "something wasn't found") |
||||||
|
} |
||||||
|
|
||||||
|
sw.UpdateStub = func(_ context.Context, obj client.Object, _ ...client.UpdateOption) error { |
||||||
|
actual := obj.(*lokiv1beta1.LokiStack) |
||||||
|
require.NotEmpty(t, actual.Status.Conditions) |
||||||
|
return nil |
||||||
|
} |
||||||
|
|
||||||
|
err := status.SetReadyCondition(context.TODO(), k, r) |
||||||
|
require.NoError(t, err) |
||||||
|
|
||||||
|
require.NotZero(t, k.StatusCallCount()) |
||||||
|
require.NotZero(t, sw.UpdateCallCount()) |
||||||
|
} |
||||||
|
|
||||||
|
func TestSetFailedCondition_WhenGetLokiStackReturnsError_ReturnError(t *testing.T) { |
||||||
|
k := &k8sfakes.FakeClient{} |
||||||
|
|
||||||
|
r := ctrl.Request{ |
||||||
|
NamespacedName: types.NamespacedName{ |
||||||
|
Name: "my-stack", |
||||||
|
Namespace: "some-ns", |
||||||
|
}, |
||||||
|
} |
||||||
|
|
||||||
|
k.GetStub = func(_ context.Context, name types.NamespacedName, object client.Object) error { |
||||||
|
return apierrors.NewBadRequest("something wasn't found") |
||||||
|
} |
||||||
|
|
||||||
|
err := status.SetFailedCondition(context.TODO(), k, r) |
||||||
|
require.Error(t, err) |
||||||
|
} |
||||||
|
|
||||||
|
func TestSetFailedCondition_WhenGetLokiStackReturnsNotFound_DoNothing(t *testing.T) { |
||||||
|
k := &k8sfakes.FakeClient{} |
||||||
|
|
||||||
|
r := ctrl.Request{ |
||||||
|
NamespacedName: types.NamespacedName{ |
||||||
|
Name: "my-stack", |
||||||
|
Namespace: "some-ns", |
||||||
|
}, |
||||||
|
} |
||||||
|
|
||||||
|
k.GetStub = func(_ context.Context, name types.NamespacedName, object client.Object) error { |
||||||
|
return apierrors.NewNotFound(schema.GroupResource{}, "something wasn't found") |
||||||
|
} |
||||||
|
|
||||||
|
err := status.SetFailedCondition(context.TODO(), k, r) |
||||||
|
require.NoError(t, err) |
||||||
|
} |
||||||
|
|
||||||
|
func TestSetFailedCondition_WhenExisting_DoNothing(t *testing.T) { |
||||||
|
k := &k8sfakes.FakeClient{} |
||||||
|
|
||||||
|
s := lokiv1beta1.LokiStack{ |
||||||
|
ObjectMeta: metav1.ObjectMeta{ |
||||||
|
Name: "my-stack", |
||||||
|
Namespace: "some-ns", |
||||||
|
}, |
||||||
|
Status: lokiv1beta1.LokiStackStatus{ |
||||||
|
Conditions: []metav1.Condition{ |
||||||
|
{ |
||||||
|
Type: string(lokiv1beta1.ConditionFailed), |
||||||
|
Status: metav1.ConditionTrue, |
||||||
|
}, |
||||||
|
}, |
||||||
|
}, |
||||||
|
} |
||||||
|
|
||||||
|
r := ctrl.Request{ |
||||||
|
NamespacedName: types.NamespacedName{ |
||||||
|
Name: "my-stack", |
||||||
|
Namespace: "some-ns", |
||||||
|
}, |
||||||
|
} |
||||||
|
|
||||||
|
k.GetStub = func(_ context.Context, name types.NamespacedName, object client.Object) error { |
||||||
|
if r.Name == name.Name && r.Namespace == name.Namespace { |
||||||
|
k.SetClientObject(object, &s) |
||||||
|
return nil |
||||||
|
} |
||||||
|
return apierrors.NewNotFound(schema.GroupResource{}, "something wasn't found") |
||||||
|
} |
||||||
|
|
||||||
|
err := status.SetFailedCondition(context.TODO(), k, r) |
||||||
|
require.NoError(t, err) |
||||||
|
require.Zero(t, k.StatusCallCount()) |
||||||
|
} |
||||||
|
|
||||||
|
func TestSetFailedCondition_WhenExisting_SetFailedConditionTrue(t *testing.T) { |
||||||
|
sw := &k8sfakes.FakeStatusWriter{} |
||||||
|
k := &k8sfakes.FakeClient{} |
||||||
|
|
||||||
|
k.StatusStub = func() client.StatusWriter { return sw } |
||||||
|
|
||||||
|
s := lokiv1beta1.LokiStack{ |
||||||
|
ObjectMeta: metav1.ObjectMeta{ |
||||||
|
Name: "my-stack", |
||||||
|
Namespace: "some-ns", |
||||||
|
}, |
||||||
|
Status: lokiv1beta1.LokiStackStatus{ |
||||||
|
Conditions: []metav1.Condition{ |
||||||
|
{ |
||||||
|
Type: string(lokiv1beta1.ConditionFailed), |
||||||
|
Status: metav1.ConditionFalse, |
||||||
|
}, |
||||||
|
}, |
||||||
|
}, |
||||||
|
} |
||||||
|
|
||||||
|
r := ctrl.Request{ |
||||||
|
NamespacedName: types.NamespacedName{ |
||||||
|
Name: "my-stack", |
||||||
|
Namespace: "some-ns", |
||||||
|
}, |
||||||
|
} |
||||||
|
|
||||||
|
k.GetStub = func(_ context.Context, name types.NamespacedName, object client.Object) error { |
||||||
|
if r.Name == name.Name && r.Namespace == name.Namespace { |
||||||
|
k.SetClientObject(object, &s) |
||||||
|
return nil |
||||||
|
} |
||||||
|
return apierrors.NewNotFound(schema.GroupResource{}, "something wasn't found") |
||||||
|
} |
||||||
|
|
||||||
|
sw.UpdateStub = func(_ context.Context, obj client.Object, _ ...client.UpdateOption) error { |
||||||
|
actual := obj.(*lokiv1beta1.LokiStack) |
||||||
|
require.NotEmpty(t, actual.Status.Conditions) |
||||||
|
require.Equal(t, metav1.ConditionTrue, actual.Status.Conditions[0].Status) |
||||||
|
return nil |
||||||
|
} |
||||||
|
|
||||||
|
err := status.SetFailedCondition(context.TODO(), k, r) |
||||||
|
require.NoError(t, err) |
||||||
|
|
||||||
|
require.NotZero(t, k.StatusCallCount()) |
||||||
|
require.NotZero(t, sw.UpdateCallCount()) |
||||||
|
} |
||||||
|
|
||||||
|
func TestSetFailedCondition_WhenNoneExisting_AppendFailedCondition(t *testing.T) { |
||||||
|
sw := &k8sfakes.FakeStatusWriter{} |
||||||
|
k := &k8sfakes.FakeClient{} |
||||||
|
|
||||||
|
k.StatusStub = func() client.StatusWriter { return sw } |
||||||
|
|
||||||
|
s := lokiv1beta1.LokiStack{ |
||||||
|
ObjectMeta: metav1.ObjectMeta{ |
||||||
|
Name: "my-stack", |
||||||
|
Namespace: "some-ns", |
||||||
|
}, |
||||||
|
} |
||||||
|
|
||||||
|
r := ctrl.Request{ |
||||||
|
NamespacedName: types.NamespacedName{ |
||||||
|
Name: "my-stack", |
||||||
|
Namespace: "some-ns", |
||||||
|
}, |
||||||
|
} |
||||||
|
|
||||||
|
k.GetStub = func(_ context.Context, name types.NamespacedName, object client.Object) error { |
||||||
|
if r.Name == name.Name && r.Namespace == name.Namespace { |
||||||
|
k.SetClientObject(object, &s) |
||||||
|
return nil |
||||||
|
} |
||||||
|
return apierrors.NewNotFound(schema.GroupResource{}, "something wasn't found") |
||||||
|
} |
||||||
|
|
||||||
|
sw.UpdateStub = func(_ context.Context, obj client.Object, _ ...client.UpdateOption) error { |
||||||
|
actual := obj.(*lokiv1beta1.LokiStack) |
||||||
|
require.NotEmpty(t, actual.Status.Conditions) |
||||||
|
return nil |
||||||
|
} |
||||||
|
|
||||||
|
err := status.SetFailedCondition(context.TODO(), k, r) |
||||||
|
require.NoError(t, err) |
||||||
|
|
||||||
|
require.NotZero(t, k.StatusCallCount()) |
||||||
|
require.NotZero(t, sw.UpdateCallCount()) |
||||||
|
} |
||||||
|
|
||||||
|
func TestSetDegradedCondition_WhenGetLokiStackReturnsError_ReturnError(t *testing.T) { |
||||||
|
k := &k8sfakes.FakeClient{} |
||||||
|
|
||||||
|
msg := "tell me nothing" |
||||||
|
reason := lokiv1beta1.ReasonMissingObjectStorageSecret |
||||||
|
|
||||||
|
r := ctrl.Request{ |
||||||
|
NamespacedName: types.NamespacedName{ |
||||||
|
Name: "my-stack", |
||||||
|
Namespace: "some-ns", |
||||||
|
}, |
||||||
|
} |
||||||
|
|
||||||
|
k.GetStub = func(_ context.Context, name types.NamespacedName, object client.Object) error { |
||||||
|
return apierrors.NewBadRequest("something wasn't found") |
||||||
|
} |
||||||
|
|
||||||
|
err := status.SetDegradedCondition(context.TODO(), k, r, msg, reason) |
||||||
|
require.Error(t, err) |
||||||
|
} |
||||||
|
|
||||||
|
func TestSetPendingCondition_WhenGetLokiStackReturnsError_ReturnError(t *testing.T) { |
||||||
|
k := &k8sfakes.FakeClient{} |
||||||
|
|
||||||
|
r := ctrl.Request{ |
||||||
|
NamespacedName: types.NamespacedName{ |
||||||
|
Name: "my-stack", |
||||||
|
Namespace: "some-ns", |
||||||
|
}, |
||||||
|
} |
||||||
|
|
||||||
|
k.GetStub = func(_ context.Context, name types.NamespacedName, object client.Object) error { |
||||||
|
return apierrors.NewBadRequest("something wasn't found") |
||||||
|
} |
||||||
|
|
||||||
|
err := status.SetPendingCondition(context.TODO(), k, r) |
||||||
|
require.Error(t, err) |
||||||
|
} |
||||||
|
|
||||||
|
func TestSetPendingCondition_WhenGetLokiStackReturnsNotFound_DoNothing(t *testing.T) { |
||||||
|
k := &k8sfakes.FakeClient{} |
||||||
|
|
||||||
|
r := ctrl.Request{ |
||||||
|
NamespacedName: types.NamespacedName{ |
||||||
|
Name: "my-stack", |
||||||
|
Namespace: "some-ns", |
||||||
|
}, |
||||||
|
} |
||||||
|
|
||||||
|
k.GetStub = func(_ context.Context, name types.NamespacedName, object client.Object) error { |
||||||
|
return apierrors.NewNotFound(schema.GroupResource{}, "something wasn't found") |
||||||
|
} |
||||||
|
|
||||||
|
err := status.SetPendingCondition(context.TODO(), k, r) |
||||||
|
require.NoError(t, err) |
||||||
|
} |
||||||
|
|
||||||
|
func TestSetPendingCondition_WhenExisting_DoNothing(t *testing.T) { |
||||||
|
k := &k8sfakes.FakeClient{} |
||||||
|
|
||||||
|
s := lokiv1beta1.LokiStack{ |
||||||
|
ObjectMeta: metav1.ObjectMeta{ |
||||||
|
Name: "my-stack", |
||||||
|
Namespace: "some-ns", |
||||||
|
}, |
||||||
|
Status: lokiv1beta1.LokiStackStatus{ |
||||||
|
Conditions: []metav1.Condition{ |
||||||
|
{ |
||||||
|
Type: string(lokiv1beta1.ConditionPending), |
||||||
|
Status: metav1.ConditionTrue, |
||||||
|
}, |
||||||
|
}, |
||||||
|
}, |
||||||
|
} |
||||||
|
|
||||||
|
r := ctrl.Request{ |
||||||
|
NamespacedName: types.NamespacedName{ |
||||||
|
Name: "my-stack", |
||||||
|
Namespace: "some-ns", |
||||||
|
}, |
||||||
|
} |
||||||
|
|
||||||
|
k.GetStub = func(_ context.Context, name types.NamespacedName, object client.Object) error { |
||||||
|
if r.Name == name.Name && r.Namespace == name.Namespace { |
||||||
|
k.SetClientObject(object, &s) |
||||||
|
return nil |
||||||
|
} |
||||||
|
return apierrors.NewNotFound(schema.GroupResource{}, "something wasn't found") |
||||||
|
} |
||||||
|
|
||||||
|
err := status.SetPendingCondition(context.TODO(), k, r) |
||||||
|
require.NoError(t, err) |
||||||
|
require.Zero(t, k.StatusCallCount()) |
||||||
|
} |
||||||
|
|
||||||
|
func TestSetPendingCondition_WhenExisting_SetPendingConditionTrue(t *testing.T) { |
||||||
|
sw := &k8sfakes.FakeStatusWriter{} |
||||||
|
k := &k8sfakes.FakeClient{} |
||||||
|
|
||||||
|
k.StatusStub = func() client.StatusWriter { return sw } |
||||||
|
|
||||||
|
s := lokiv1beta1.LokiStack{ |
||||||
|
ObjectMeta: metav1.ObjectMeta{ |
||||||
|
Name: "my-stack", |
||||||
|
Namespace: "some-ns", |
||||||
|
}, |
||||||
|
Status: lokiv1beta1.LokiStackStatus{ |
||||||
|
Conditions: []metav1.Condition{ |
||||||
|
{ |
||||||
|
Type: string(lokiv1beta1.ConditionPending), |
||||||
|
Status: metav1.ConditionFalse, |
||||||
|
}, |
||||||
|
}, |
||||||
|
}, |
||||||
|
} |
||||||
|
|
||||||
|
r := ctrl.Request{ |
||||||
|
NamespacedName: types.NamespacedName{ |
||||||
|
Name: "my-stack", |
||||||
|
Namespace: "some-ns", |
||||||
|
}, |
||||||
|
} |
||||||
|
|
||||||
|
k.GetStub = func(_ context.Context, name types.NamespacedName, object client.Object) error { |
||||||
|
if r.Name == name.Name && r.Namespace == name.Namespace { |
||||||
|
k.SetClientObject(object, &s) |
||||||
|
return nil |
||||||
|
} |
||||||
|
return apierrors.NewNotFound(schema.GroupResource{}, "something wasn't found") |
||||||
|
} |
||||||
|
|
||||||
|
sw.UpdateStub = func(_ context.Context, obj client.Object, _ ...client.UpdateOption) error { |
||||||
|
actual := obj.(*lokiv1beta1.LokiStack) |
||||||
|
require.NotEmpty(t, actual.Status.Conditions) |
||||||
|
require.Equal(t, metav1.ConditionTrue, actual.Status.Conditions[0].Status) |
||||||
|
return nil |
||||||
|
} |
||||||
|
|
||||||
|
err := status.SetPendingCondition(context.TODO(), k, r) |
||||||
|
require.NoError(t, err) |
||||||
|
require.NotZero(t, k.StatusCallCount()) |
||||||
|
require.NotZero(t, sw.UpdateCallCount()) |
||||||
|
} |
||||||
|
|
||||||
|
func TestSetPendingCondition_WhenNoneExisting_AppendPendingCondition(t *testing.T) { |
||||||
|
sw := &k8sfakes.FakeStatusWriter{} |
||||||
|
k := &k8sfakes.FakeClient{} |
||||||
|
|
||||||
|
k.StatusStub = func() client.StatusWriter { return sw } |
||||||
|
|
||||||
|
s := lokiv1beta1.LokiStack{ |
||||||
|
ObjectMeta: metav1.ObjectMeta{ |
||||||
|
Name: "my-stack", |
||||||
|
Namespace: "some-ns", |
||||||
|
}, |
||||||
|
} |
||||||
|
|
||||||
|
r := ctrl.Request{ |
||||||
|
NamespacedName: types.NamespacedName{ |
||||||
|
Name: "my-stack", |
||||||
|
Namespace: "some-ns", |
||||||
|
}, |
||||||
|
} |
||||||
|
|
||||||
|
k.GetStub = func(_ context.Context, name types.NamespacedName, object client.Object) error { |
||||||
|
if r.Name == name.Name && r.Namespace == name.Namespace { |
||||||
|
k.SetClientObject(object, &s) |
||||||
|
return nil |
||||||
|
} |
||||||
|
return apierrors.NewNotFound(schema.GroupResource{}, "something wasn't found") |
||||||
|
} |
||||||
|
|
||||||
|
sw.UpdateStub = func(_ context.Context, obj client.Object, _ ...client.UpdateOption) error { |
||||||
|
actual := obj.(*lokiv1beta1.LokiStack) |
||||||
|
require.NotEmpty(t, actual.Status.Conditions) |
||||||
|
return nil |
||||||
|
} |
||||||
|
|
||||||
|
err := status.SetPendingCondition(context.TODO(), k, r) |
||||||
|
require.NoError(t, err) |
||||||
|
|
||||||
|
require.NotZero(t, k.StatusCallCount()) |
||||||
|
require.NotZero(t, sw.UpdateCallCount()) |
||||||
|
} |
||||||
|
|
||||||
|
func TestSetDegradedCondition_WhenGetLokiStackReturnsNotFound_DoNothing(t *testing.T) { |
||||||
|
k := &k8sfakes.FakeClient{} |
||||||
|
|
||||||
|
msg := "tell me nothing" |
||||||
|
reason := lokiv1beta1.ReasonMissingObjectStorageSecret |
||||||
|
|
||||||
|
r := ctrl.Request{ |
||||||
|
NamespacedName: types.NamespacedName{ |
||||||
|
Name: "my-stack", |
||||||
|
Namespace: "some-ns", |
||||||
|
}, |
||||||
|
} |
||||||
|
|
||||||
|
k.GetStub = func(_ context.Context, name types.NamespacedName, object client.Object) error { |
||||||
|
return apierrors.NewNotFound(schema.GroupResource{}, "something wasn't found") |
||||||
|
} |
||||||
|
|
||||||
|
err := status.SetDegradedCondition(context.TODO(), k, r, msg, reason) |
||||||
|
require.NoError(t, err) |
||||||
|
} |
||||||
|
|
||||||
|
func TestSetDegradedCondition_WhenExisting_DoNothing(t *testing.T) { |
||||||
|
k := &k8sfakes.FakeClient{} |
||||||
|
|
||||||
|
msg := "tell me nothing" |
||||||
|
reason := lokiv1beta1.ReasonMissingObjectStorageSecret |
||||||
|
s := lokiv1beta1.LokiStack{ |
||||||
|
ObjectMeta: metav1.ObjectMeta{ |
||||||
|
Name: "my-stack", |
||||||
|
Namespace: "some-ns", |
||||||
|
}, |
||||||
|
Status: lokiv1beta1.LokiStackStatus{ |
||||||
|
Conditions: []metav1.Condition{ |
||||||
|
{ |
||||||
|
Type: string(lokiv1beta1.ConditionDegraded), |
||||||
|
Reason: string(reason), |
||||||
|
Status: metav1.ConditionTrue, |
||||||
|
}, |
||||||
|
}, |
||||||
|
}, |
||||||
|
} |
||||||
|
|
||||||
|
r := ctrl.Request{ |
||||||
|
NamespacedName: types.NamespacedName{ |
||||||
|
Name: "my-stack", |
||||||
|
Namespace: "some-ns", |
||||||
|
}, |
||||||
|
} |
||||||
|
|
||||||
|
k.GetStub = func(_ context.Context, name types.NamespacedName, object client.Object) error { |
||||||
|
if r.Name == name.Name && r.Namespace == name.Namespace { |
||||||
|
k.SetClientObject(object, &s) |
||||||
|
return nil |
||||||
|
} |
||||||
|
return apierrors.NewNotFound(schema.GroupResource{}, "something wasn't found") |
||||||
|
} |
||||||
|
|
||||||
|
err := status.SetDegradedCondition(context.TODO(), k, r, msg, reason) |
||||||
|
require.NoError(t, err) |
||||||
|
require.Zero(t, k.StatusCallCount()) |
||||||
|
} |
||||||
|
|
||||||
|
func TestSetDegradedCondition_WhenExisting_SetDegradedConditionTrue(t *testing.T) { |
||||||
|
sw := &k8sfakes.FakeStatusWriter{} |
||||||
|
k := &k8sfakes.FakeClient{} |
||||||
|
|
||||||
|
k.StatusStub = func() client.StatusWriter { return sw } |
||||||
|
|
||||||
|
msg := "tell me something" |
||||||
|
reason := lokiv1beta1.ReasonMissingObjectStorageSecret |
||||||
|
s := lokiv1beta1.LokiStack{ |
||||||
|
ObjectMeta: metav1.ObjectMeta{ |
||||||
|
Name: "my-stack", |
||||||
|
Namespace: "some-ns", |
||||||
|
}, |
||||||
|
Status: lokiv1beta1.LokiStackStatus{ |
||||||
|
Conditions: []metav1.Condition{ |
||||||
|
{ |
||||||
|
Type: string(lokiv1beta1.ConditionDegraded), |
||||||
|
Reason: string(reason), |
||||||
|
Status: metav1.ConditionFalse, |
||||||
|
}, |
||||||
|
}, |
||||||
|
}, |
||||||
|
} |
||||||
|
|
||||||
|
r := ctrl.Request{ |
||||||
|
NamespacedName: types.NamespacedName{ |
||||||
|
Name: "my-stack", |
||||||
|
Namespace: "some-ns", |
||||||
|
}, |
||||||
|
} |
||||||
|
|
||||||
|
k.GetStub = func(_ context.Context, name types.NamespacedName, object client.Object) error { |
||||||
|
if r.Name == name.Name && r.Namespace == name.Namespace { |
||||||
|
k.SetClientObject(object, &s) |
||||||
|
return nil |
||||||
|
} |
||||||
|
return apierrors.NewNotFound(schema.GroupResource{}, "something wasn't found") |
||||||
|
} |
||||||
|
|
||||||
|
sw.UpdateStub = func(_ context.Context, obj client.Object, _ ...client.UpdateOption) error { |
||||||
|
actual := obj.(*lokiv1beta1.LokiStack) |
||||||
|
require.NotEmpty(t, actual.Status.Conditions) |
||||||
|
require.Equal(t, metav1.ConditionTrue, actual.Status.Conditions[0].Status) |
||||||
|
return nil |
||||||
|
} |
||||||
|
|
||||||
|
err := status.SetDegradedCondition(context.TODO(), k, r, msg, reason) |
||||||
|
require.NoError(t, err) |
||||||
|
require.NotZero(t, k.StatusCallCount()) |
||||||
|
require.NotZero(t, sw.UpdateCallCount()) |
||||||
|
} |
||||||
|
|
||||||
|
func TestSetDegradedCondition_WhenNoneExisting_AppendDegradedCondition(t *testing.T) { |
||||||
|
sw := &k8sfakes.FakeStatusWriter{} |
||||||
|
k := &k8sfakes.FakeClient{} |
||||||
|
|
||||||
|
k.StatusStub = func() client.StatusWriter { return sw } |
||||||
|
|
||||||
|
msg := "tell me something" |
||||||
|
reason := lokiv1beta1.ReasonMissingObjectStorageSecret |
||||||
|
s := lokiv1beta1.LokiStack{ |
||||||
|
ObjectMeta: metav1.ObjectMeta{ |
||||||
|
Name: "my-stack", |
||||||
|
Namespace: "some-ns", |
||||||
|
}, |
||||||
|
} |
||||||
|
|
||||||
|
r := ctrl.Request{ |
||||||
|
NamespacedName: types.NamespacedName{ |
||||||
|
Name: "my-stack", |
||||||
|
Namespace: "some-ns", |
||||||
|
}, |
||||||
|
} |
||||||
|
|
||||||
|
k.GetStub = func(_ context.Context, name types.NamespacedName, object client.Object) error { |
||||||
|
if r.Name == name.Name && r.Namespace == name.Namespace { |
||||||
|
k.SetClientObject(object, &s) |
||||||
|
return nil |
||||||
|
} |
||||||
|
return apierrors.NewNotFound(schema.GroupResource{}, "something wasn't found") |
||||||
|
} |
||||||
|
|
||||||
|
sw.UpdateStub = func(_ context.Context, obj client.Object, _ ...client.UpdateOption) error { |
||||||
|
actual := obj.(*lokiv1beta1.LokiStack) |
||||||
|
require.NotEmpty(t, actual.Status.Conditions) |
||||||
|
return nil |
||||||
|
} |
||||||
|
|
||||||
|
err := status.SetDegradedCondition(context.TODO(), k, r, msg, reason) |
||||||
|
require.NoError(t, err) |
||||||
|
|
||||||
|
require.NotZero(t, k.StatusCallCount()) |
||||||
|
require.NotZero(t, sw.UpdateCallCount()) |
||||||
|
} |
@ -0,0 +1,61 @@ |
|||||||
|
package status |
||||||
|
|
||||||
|
import ( |
||||||
|
"context" |
||||||
|
|
||||||
|
"github.com/ViaQ/logerr/kverrors" |
||||||
|
lokiv1beta1 "github.com/ViaQ/loki-operator/api/v1beta1" |
||||||
|
"github.com/ViaQ/loki-operator/internal/external/k8s" |
||||||
|
|
||||||
|
corev1 "k8s.io/api/core/v1" |
||||||
|
apierrors "k8s.io/apimachinery/pkg/api/errors" |
||||||
|
ctrl "sigs.k8s.io/controller-runtime" |
||||||
|
) |
||||||
|
|
||||||
|
// Refresh executes an aggregate update of the LokiStack Status struct, i.e.
|
||||||
|
// - It recreates the Status.Components pod status map per component.
|
||||||
|
// - It sets the appropriate Status.Condition to true that matches the pod status maps.
|
||||||
|
func Refresh(ctx context.Context, k k8s.Client, req ctrl.Request) error { |
||||||
|
if err := SetComponentsStatus(ctx, k, req); err != nil { |
||||||
|
return err |
||||||
|
} |
||||||
|
|
||||||
|
var s lokiv1beta1.LokiStack |
||||||
|
if err := k.Get(ctx, req.NamespacedName, &s); err != nil { |
||||||
|
if apierrors.IsNotFound(err) { |
||||||
|
return nil |
||||||
|
} |
||||||
|
return kverrors.Wrap(err, "failed to lookup lokistack", "name", req.NamespacedName) |
||||||
|
} |
||||||
|
|
||||||
|
cs := s.Status.Components |
||||||
|
|
||||||
|
// Check for failed pods first
|
||||||
|
failed := len(cs.Compactor[corev1.PodFailed]) + |
||||||
|
len(cs.Distributor[corev1.PodFailed]) + |
||||||
|
len(cs.Ingester[corev1.PodFailed]) + |
||||||
|
len(cs.Querier[corev1.PodFailed]) + |
||||||
|
len(cs.QueryFrontend[corev1.PodFailed]) |
||||||
|
|
||||||
|
unknown := len(cs.Compactor[corev1.PodUnknown]) + |
||||||
|
len(cs.Distributor[corev1.PodUnknown]) + |
||||||
|
len(cs.Ingester[corev1.PodUnknown]) + |
||||||
|
len(cs.Querier[corev1.PodUnknown]) + |
||||||
|
len(cs.QueryFrontend[corev1.PodUnknown]) |
||||||
|
|
||||||
|
if failed != 0 || unknown != 0 { |
||||||
|
return SetFailedCondition(ctx, k, req) |
||||||
|
} |
||||||
|
|
||||||
|
// Check for pending pods
|
||||||
|
pending := len(cs.Compactor[corev1.PodPending]) + |
||||||
|
len(cs.Distributor[corev1.PodPending]) + |
||||||
|
len(cs.Ingester[corev1.PodPending]) + |
||||||
|
len(cs.Querier[corev1.PodPending]) + |
||||||
|
len(cs.QueryFrontend[corev1.PodPending]) |
||||||
|
|
||||||
|
if pending != 0 { |
||||||
|
return SetPendingCondition(ctx, k, req) |
||||||
|
} |
||||||
|
return SetReadyCondition(ctx, k, req) |
||||||
|
} |
Loading…
Reference in new issue