Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 7 additions & 1 deletion internal/authentication/tokengetter.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,12 @@ package authentication

import (
"context"
"fmt"
"sync"
"time"

authenticationv1 "k8s.io/api/authentication/v1"
"k8s.io/apimachinery/pkg/api/errors"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/types"
corev1 "k8s.io/client-go/kubernetes/typed/core/v1"
Expand Down Expand Up @@ -66,7 +68,7 @@ func (t *TokenGetter) Get(ctx context.Context, key types.NamespacedName) (string
var err error
token, err = t.getToken(ctx, key)
if err != nil {
return "", err
return "", fmt.Errorf("authentication error: %w", err)
}
t.mu.Lock()
t.tokens[key] = token
Expand All @@ -86,6 +88,10 @@ func (t *TokenGetter) getToken(ctx context.Context, key types.NamespacedName) (*
Spec: authenticationv1.TokenRequestSpec{ExpirationSeconds: ptr.To(int64(t.expirationDuration / time.Second))},
}, metav1.CreateOptions{})
if err != nil {
if errors.IsNotFound(err) {
// return nil, &ServiceAccountNotFoundError{ServiceAccountName: key.Name, ServiceAccountNamespace: key.Namespace, Err: err}
return nil, fmt.Errorf("service account \"%s\" not found in namespace \"%s\"", key.Name, key.Namespace)
}
return nil, err
}
return &req.Status, nil
Expand Down
6 changes: 4 additions & 2 deletions internal/authentication/tokengetter_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -71,14 +71,16 @@ func TestTokenGetterGet(t *testing.T) {
{"Testing token that expired 10 seconds ago", "test-service-account-3",
"test-namespace-3", "test-token-3", "failed to get token"},
{"Testing error when getting token from fake client", "test-service-account-4",
"test-namespace-4", "error when fetching token", "error when fetching token"},
"test-namespace-4", "error when fetching token", "authentication error: error when fetching token"},
{"Testing service account not found", "missing-sa",
"test-namespace-5", "", "authentication error: service account \"missing-sa\" not found in namespace \"test-namespace-5\""},
}

for _, tc := range tests {
got, err := tg.Get(context.Background(), types.NamespacedName{Namespace: tc.namespace, Name: tc.serviceAccountName})
if err != nil {
t.Logf("%s: expected: %v, got: %v", tc.testName, tc.want, err)
assert.EqualError(t, err, tc.errorMsg)
assert.EqualError(t, err, tc.errorMsg, "Error message should match expected output")
} else {
t.Logf("%s: expected: %v, got: %v", tc.testName, tc.want, got)
assert.Equal(t, tc.want, got, tc.errorMsg)
Expand Down
2 changes: 1 addition & 1 deletion internal/controllers/clusterextension_controller.go
Original file line number Diff line number Diff line change
Expand Up @@ -207,7 +207,7 @@ func (r *ClusterExtensionReconciler) reconcile(ctx context.Context, ext *ocv1.Cl
if err != nil {
setInstallStatus(ext, nil)
setInstalledStatusConditionUnknown(ext, err.Error())
setStatusProgressing(ext, errors.New("retrying to get installed bundle"))
setStatusProgressing(ext, fmt.Errorf("error getting installed bundle: %w", err))
return ctrl.Result{}, err
}

Expand Down
51 changes: 51 additions & 0 deletions internal/controllers/clusterextension_controller_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -332,6 +332,57 @@ func TestClusterExtensionResolutionAndUnpackSuccessfulApplierFails(t *testing.T)
require.NoError(t, cl.DeleteAllOf(ctx, &ocv1.ClusterExtension{}))
}

func TestClusterExtensionServiceAccountNotFound(t *testing.T) {
cl, reconciler := newClientAndReconciler(t)
reconciler.InstalledBundleGetter = &MockInstalledBundleGetter{
err: errors.New("authentication error: service account \"missing-sa\" not found in namespace \"default\""),
}

ctx := context.Background()
extKey := types.NamespacedName{Name: fmt.Sprintf("cluster-extension-test-%s", rand.String(8))}

t.Log("Given a cluster extension with a missing service account")
clusterExtension := &ocv1.ClusterExtension{
ObjectMeta: metav1.ObjectMeta{Name: extKey.Name},
Spec: ocv1.ClusterExtensionSpec{
Source: ocv1.SourceConfig{
SourceType: "Catalog",
Catalog: &ocv1.CatalogSource{
PackageName: "test-package",
},
},
Namespace: "default",
ServiceAccount: ocv1.ServiceAccountReference{
Name: "missing-sa",
},
},
}

require.NoError(t, cl.Create(ctx, clusterExtension))

t.Log("When reconciling the cluster extension")
res, err := reconciler.Reconcile(ctx, ctrl.Request{NamespacedName: extKey})

require.Equal(t, ctrl.Result{}, res)
require.Error(t, err)
t.Log("By fetching updated cluster extension after reconcile")
require.NoError(t, cl.Get(ctx, extKey, clusterExtension))

t.Log("By checking the status conditions")
installedCond := apimeta.FindStatusCondition(clusterExtension.Status.Conditions, ocv1.TypeInstalled)
require.NotNil(t, installedCond)
require.Equal(t, metav1.ConditionUnknown, installedCond.Status)
require.Contains(t, installedCond.Message, fmt.Sprintf("service account %q not found in namespace %q",
"missing-sa", "default"))

progressingCond := apimeta.FindStatusCondition(clusterExtension.Status.Conditions, ocv1.TypeProgressing)
require.NotNil(t, progressingCond)
require.Equal(t, metav1.ConditionTrue, progressingCond.Status)
require.Equal(t, ocv1.ReasonRetrying, progressingCond.Reason)
require.Contains(t, progressingCond.Message, "error getting installed bundle: authentication error: service account \"missing-sa\" not found in namespace \"default\"")
require.NoError(t, cl.DeleteAllOf(ctx, &ocv1.ClusterExtension{}))
}

func TestClusterExtensionApplierFailsWithBundleInstalled(t *testing.T) {
cl, reconciler := newClientAndReconciler(t)
reconciler.Unpacker = &MockUnpacker{
Expand Down
4 changes: 4 additions & 0 deletions internal/controllers/suite_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -74,13 +74,17 @@ func newClient(t *testing.T) client.Client {

type MockInstalledBundleGetter struct {
bundle *controllers.InstalledBundle
err error
}

func (m *MockInstalledBundleGetter) SetBundle(bundle *controllers.InstalledBundle) {
m.bundle = bundle
}

func (m *MockInstalledBundleGetter) GetInstalledBundle(ctx context.Context, ext *ocv1.ClusterExtension) (*controllers.InstalledBundle, error) {
if m.err != nil {
return m.bundle, m.err
}
return m.bundle, nil
}

Expand Down
Loading