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

Secretsmanager: Implement LateInitialize of a K8s secret when AWS secret already exists #669

Merged

Conversation

MisterMX
Copy link
Collaborator

Description of your changes

Fixes #668

The controller now creates a K8s with the value from AWS if it does not already exist.

I have:

  • Read and followed Crossplane's [contribution process].
  • Run make reviewable test to ensure this PR is ready for review.

How has this code been tested

Manually

@MisterMX
Copy link
Collaborator Author

@haarchri done

@haarchri
Copy link
Member

@MisterMX sorry we merged #907 can you rebase again

@MisterMX MisterMX force-pushed the secretsmanager-lateinitialize branch from c2bbe99 to e523207 Compare November 16, 2021 11:02
@MisterMX
Copy link
Collaborator Author

@haarchri Done ;-)

Copy link
Member

@muvaf muvaf left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We haven't done late-init for an input Secret before but I think it makes sense given that it's very similar to other params except that it's stored differently. Thanks @MisterMX !

pkg/controller/secretsmanager/secret/setup.go Outdated Show resolved Hide resolved
pkg/controller/secretsmanager/secret/setup.go Outdated Show resolved Hide resolved
}

payload := map[string][]byte{}
if v, exists := parsed[awsclients.StringValue(ref.Key)]; exists {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We send the data as a string if the key is given, I'd expect the reverse of this to happen in late-init, i.e. look for a string only if the key is given. If not, then we should always treat that the whole map is requested. So, I think we should only iterate here and not account for the case where there is a key, blob in AWS is a map and user actually meant a specific key in that whole blob in AWS.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Oh in fact, it will never be non-nil anyway since we checked it in the beginning.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, I think we can go for always iterating to keep the external and local data in sync.

Though it will be overwritten in the next reconcile if a ref.Key is set (because payload will be different).

default:
return nil, errors.New("neither binarySecretRef nor stringSecretRef is given")
func (e *hooks) getPayload(ctx context.Context, cr *svcapitypes.SecretParameters) ([]byte, error) {
ref, err := getSecretRef(cr)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think it's easier to follow what's happening if we have duplication for that switch case instead of calling another function.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I would prefer to keep code encapsulated that is used more than once.

I modified the function so it will return an error in case StringSecretRef and BinarySecretRef are both set. Before that, StringSecretRef took preference over BinarySecretRef and I don't think that was intended. I also added a note to the API docs.

ref = cr.Spec.ForProvider.BinarySecretRef
default:
return nil, errors.New("neither binarySecretRef nor stringSecretRef is given")
func (e *hooks) getPayload(ctx context.Context, cr *svcapitypes.SecretParameters) ([]byte, error) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

cr seems to be used to point to the whole Secret object in this file, i.e. as in (c)ustom (r)esource. So, I'd suggest either keeping this line as is or use params as variable name when it addresses SecretParameters.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Renamed to params.

Copy link
Collaborator Author

@MisterMX MisterMX left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks @muvaf for the review. I added (most of) your requested changes and rebased on current master.

One last proposal before bumping this to v1beta1:

Currently we have a binarySecretRef and stringSecretRef next to each other. Wouldn't it be better if we'd have a single secretRef and a format property instead? This way we would be able to support different file formats, such as yaml, json etc.

}

payload := map[string][]byte{}
if v, exists := parsed[awsclients.StringValue(ref.Key)]; exists {
Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, I think we can go for always iterating to keep the external and local data in sync.

Though it will be overwritten in the next reconcile if a ref.Key is set (because payload will be different).

default:
return nil, errors.New("neither binarySecretRef nor stringSecretRef is given")
func (e *hooks) getPayload(ctx context.Context, cr *svcapitypes.SecretParameters) ([]byte, error) {
ref, err := getSecretRef(cr)
Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I would prefer to keep code encapsulated that is used more than once.

I modified the function so it will return an error in case StringSecretRef and BinarySecretRef are both set. Before that, StringSecretRef took preference over BinarySecretRef and I don't think that was intended. I also added a note to the API docs.

ref = cr.Spec.ForProvider.BinarySecretRef
default:
return nil, errors.New("neither binarySecretRef nor stringSecretRef is given")
func (e *hooks) getPayload(ctx context.Context, cr *svcapitypes.SecretParameters) ([]byte, error) {
Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Renamed to params.

@MisterMX MisterMX force-pushed the secretsmanager-lateinitialize branch from 9239fe4 to baec13f Compare February 1, 2022 12:24
The controller now creates a K8s with the value from AWS if it does not
already exist.

Signed-off-by: Maximilian Blatt <maximilian.blatt-extern@deutschebahn.com>
(external expert on behalf of DB Netz AG)
@MisterMX MisterMX force-pushed the secretsmanager-lateinitialize branch from baec13f to 26ea6cb Compare February 1, 2022 12:25
@@ -113,6 +121,79 @@ type hooks struct {
kube client.Client
}

func (e *hooks) lateInitialize(spec *svcapitypes.SecretParameters, resp *svcsdk.DescribeSecretOutput) error {
payload, err := e.getPayload(context.TODO(), spec)
if err := client.IgnoreNotFound(err); err != nil || payload == nil {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
if err := client.IgnoreNotFound(err); err != nil || payload == nil {
if err := client.IgnoreNotFound(err); err != nil || payload != nil {

I think my initial code suggestion was the opposite of what you're trying to do in that if statement, sorry about that. We should return nil in case payload is full since we don't need to take any action.

Copy link
Member

@muvaf muvaf left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm merging this to unblock #1107 before the release. I'll open a follow-up PR if my concern about payload being nil is indeed a problem. Thanks @MisterMX !!

@muvaf muvaf merged commit b4640f8 into crossplane-contrib:master Feb 8, 2022
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Secretsmanager: Implement LateInitialize of a K8s secret when AWS secret already exists
3 participants