Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Ensure OBJ key secret is in sync with bucket #191

Merged
merged 42 commits into from
Mar 21, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
42 commits
Select commit Hold shift + click to select a range
0e35d4d
chore: migrate from kuttl to chainsaw
eddycharly Mar 8, 2024
efc0e7d
Merge branch 'main' into chainsaw-4
eddycharly Mar 8, 2024
1eb410f
Merge branch 'main' into chainsaw-4
eddycharly Mar 8, 2024
0f59073
set bucket name based on namespace
eljohnson92 Mar 11, 2024
cbabe4d
fix object store bucket listing logic
eljohnson92 Mar 11, 2024
d923729
migrate vpc test from kuttl to chainsaw and remove all kuttl related …
eljohnson92 Mar 11, 2024
2b5e183
Merge branch 'main' into chainsaw-4
eljohnson92 Mar 11, 2024
28b5465
remove bucket .spec.label
Mar 11, 2024
b9158b1
add key ID fields to OBJ status
Mar 11, 2024
03871e2
use key ID fields
Mar 11, 2024
dad0792
update tests
Mar 11, 2024
cb16bae
ensure key IDs are not nil
Mar 11, 2024
45a146b
add Testing doc
eljohnson92 Mar 11, 2024
9a9c6dc
remove unneeded env variables from tests
eljohnson92 Mar 11, 2024
67ce856
prefer status.accessKeyRefs
Mar 12, 2024
da0f7b6
Merge branch 'main' into chainsaw-4
eljohnson92 Mar 12, 2024
1f81fa2
Merge branch 'chainsaw-4' into fixup-obj-bucket
Mar 12, 2024
678163d
Merge branch 'main' into fixup-obj-bucket
Mar 12, 2024
3850ea1
use CreateOrPatch for OBJ access key secret
Mar 12, 2024
76d6756
Merge branch 'main' into fixup-obj-bucket
Mar 12, 2024
ca3f516
fix label
Mar 12, 2024
d915a23
Ensure OBJ key secrets are re-created on delete
Mar 13, 2024
1df4760
Merge branch 'main' into obj-guard-secret
Mar 14, 2024
36f43a9
obj controller watch owned
Mar 14, 2024
9090849
fix lint
Mar 14, 2024
ab74f0f
trigger e2e
Mar 14, 2024
1c61ec4
Merge branch 'main' into obj-guard-secret
Mar 14, 2024
da6c388
fix
Mar 14, 2024
4e53e05
unnest conditionals
Mar 14, 2024
9b37d2f
update tests
Mar 14, 2024
c034bee
Merge branch 'main' into obj-guard-secret
Mar 18, 2024
b36745e
add some test coverage
Mar 18, 2024
9c0157c
fix lint errors
Mar 19, 2024
d722883
more testing
Mar 20, 2024
e374de2
Merge branch 'main' into obj-guard-secret
Mar 20, 2024
ccc6194
fix missing import
Mar 20, 2024
773dde9
fix lint errors
Mar 20, 2024
40671bd
fix test
Mar 20, 2024
9276a06
enhance controller tests
Mar 20, 2024
02a2303
address lints
Mar 20, 2024
d359d21
cleanup
Mar 21, 2024
2253658
test adding finalizer
Mar 21, 2024
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
1 change: 1 addition & 0 deletions Tiltfile
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@ k8s_resource(
"linodeclustertemplates.infrastructure.cluster.x-k8s.io:customresourcedefinition",
"linodemachinetemplates.infrastructure.cluster.x-k8s.io:customresourcedefinition",
"linodevpcs.infrastructure.cluster.x-k8s.io:customresourcedefinition",
"linodeobjectstoragebuckets.infrastructure.cluster.x-k8s.io:customresourcedefinition",
"capl-controller-manager:serviceaccount",
"capl-leader-election-role:role",
"capl-manager-role:clusterrole",
Expand Down
1 change: 1 addition & 0 deletions cloud/scope/client.go
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ import (
type LinodeObjectStorageClient interface {
GetObjectStorageBucket(ctx context.Context, cluster, label string) (*linodego.ObjectStorageBucket, error)
CreateObjectStorageBucket(ctx context.Context, opts linodego.ObjectStorageBucketCreateOptions) (*linodego.ObjectStorageBucket, error)
GetObjectStorageKey(ctx context.Context, keyID int) (*linodego.ObjectStorageKey, error)
CreateObjectStorageKey(ctx context.Context, opts linodego.ObjectStorageKeyCreateOptions) (*linodego.ObjectStorageKey, error)
DeleteObjectStorageKey(ctx context.Context, keyID int) error
}
Expand Down
71 changes: 48 additions & 23 deletions cloud/scope/object_storage_bucket.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,10 @@
"github.com/go-logr/logr"
"github.com/linode/linodego"
corev1 "k8s.io/api/core/v1"
apierrors "k8s.io/apimachinery/pkg/api/errors"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"sigs.k8s.io/cluster-api/util/patch"
"sigs.k8s.io/controller-runtime/pkg/client"
"sigs.k8s.io/controller-runtime/pkg/controller/controllerutil"

infrav1alpha1 "github.com/linode/cluster-api-provider-linode/api/v1alpha1"
Expand All @@ -23,11 +25,11 @@
}

type ObjectStorageBucketScope struct {
client k8sClient
Bucket *infrav1alpha1.LinodeObjectStorageBucket
Logger logr.Logger
LinodeClient LinodeObjectStorageClient
BucketPatchHelper *patch.Helper
Client k8sClient
Bucket *infrav1alpha1.LinodeObjectStorageBucket
Logger logr.Logger
LinodeClient LinodeObjectStorageClient
PatchHelper *patch.Helper
}

const AccessKeyNameTemplate = "%s-access-keys"
Expand Down Expand Up @@ -65,23 +67,23 @@
return nil, fmt.Errorf("failed to create linode client: %w", err)
}

bucketPatchHelper, err := patch.NewHelper(params.Bucket, params.Client)
patchHelper, err := patch.NewHelper(params.Bucket, params.Client)
if err != nil {
return nil, fmt.Errorf("failed to init patch helper: %w", err)
}

return &ObjectStorageBucketScope{
client: params.Client,
Bucket: params.Bucket,
Logger: *params.Logger,
LinodeClient: linodeClient,
BucketPatchHelper: bucketPatchHelper,
Client: params.Client,
Bucket: params.Bucket,
Logger: *params.Logger,
LinodeClient: linodeClient,
PatchHelper: patchHelper,
}, nil
}

// PatchObject persists the object storage bucket configuration and status.
func (s *ObjectStorageBucketScope) PatchObject(ctx context.Context) error {
return s.BucketPatchHelper.Patch(ctx, s.Bucket)
return s.PatchHelper.Patch(ctx, s.Bucket)
}

// Close closes the current scope persisting the object storage bucket configuration and status.
Expand All @@ -99,8 +101,17 @@
return nil
}

// ApplyAccessKeySecret applies a Secret containing keys created for accessing the bucket.
func (s *ObjectStorageBucketScope) ApplyAccessKeySecret(ctx context.Context, keys [NumAccessKeys]linodego.ObjectStorageKey, secretName string) error {
// GenerateKeySecret returns a secret suitable for submission to the Kubernetes API.
// The secret is expected to contain keys for accessing the bucket, as well as owner and controller references.
func (s *ObjectStorageBucketScope) GenerateKeySecret(ctx context.Context, keys [NumAccessKeys]*linodego.ObjectStorageKey) (*corev1.Secret, error) {
for _, key := range keys {
if key == nil {
return nil, errors.New("expected two non-nil object storage keys")
}
}

secretName := fmt.Sprintf(AccessKeyNameTemplate, s.Bucket.Name)

secret := &corev1.Secret{
ObjectMeta: metav1.ObjectMeta{
Name: secretName,
Expand All @@ -112,20 +123,34 @@
},
}

if err := controllerutil.SetOwnerReference(s.Bucket, secret, s.client.Scheme()); err != nil {
return fmt.Errorf("could not set owner ref on access key secret %s: %w", secretName, err)
scheme := s.Client.Scheme()
if err := controllerutil.SetOwnerReference(s.Bucket, secret, scheme); err != nil {
return nil, fmt.Errorf("could not set owner ref on access key secret %s: %w", secretName, err)
}

result, err := controllerutil.CreateOrPatch(ctx, s.client, secret, func() error { return nil })
if err != nil {
return fmt.Errorf("could not create/patch access key secret %s: %w", secretName, err)
if err := controllerutil.SetControllerReference(s.Bucket, secret, scheme); err != nil {
return nil, fmt.Errorf("could not set controller ref on access key secret %s: %w", secretName, err)

Check warning on line 131 in cloud/scope/object_storage_bucket.go

View check run for this annotation

Codecov / codecov/patch

cloud/scope/object_storage_bucket.go#L131

Added line #L131 was not covered by tests
}

s.Logger.Info(fmt.Sprintf("Secret %s was %s with new access keys", secret.Name, result))
return secret, nil
}

return nil
func (s *ObjectStorageBucketScope) ShouldInitKeys() bool {
return s.Bucket.Status.LastKeyGeneration == nil
}

func (s *ObjectStorageBucketScope) ShouldRotateKeys() bool {
return *s.Bucket.Spec.KeyGeneration != *s.Bucket.Status.LastKeyGeneration
return s.Bucket.Status.LastKeyGeneration != nil &&
*s.Bucket.Spec.KeyGeneration != *s.Bucket.Status.LastKeyGeneration
}

func (s *ObjectStorageBucketScope) ShouldRestoreKeySecret(ctx context.Context) (bool, error) {
if s.Bucket.Status.KeySecretName == nil {
return false, nil
}

secret := &corev1.Secret{}
key := client.ObjectKey{Namespace: s.Bucket.Namespace, Name: *s.Bucket.Status.KeySecretName}
err := s.Client.Get(ctx, key, secret)

return apierrors.IsNotFound(err), client.IgnoreNotFound(err)
}
Loading