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

Store CallerReference value for import scenarios #1261

Merged

Conversation

ezgidemirel
Copy link
Contributor

@ezgidemirel ezgidemirel commented Apr 14, 2022

Signed-off-by: ezgidemirel ezgidemirel91@gmail.com

Description of your changes

This change lateInitialize the "CallerReference" value for import scenarios.

Fixes #1260

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

  • Created a CF distribution resource with example.yaml
  • Changed spec.deletionPolicy to Orphan and deleted the managed resource
  • Imported the same resource with following manifest
apiVersion: cloudfront.aws.crossplane.io/v1alpha1
kind: Distribution
metadata:
  annotations:
    crossplane.io/external-name: <external-name>
  name: ezgi
spec:
  forProvider:
    region: us-east-1
    distributionConfig: {}
  • Updated spec.forProvider.distributionConfig.comment
  • Applied the same steps with callerReference field set

@@ -17,7 +17,9 @@ limitations under the License.
package v1alpha1

// CustomDistributionParameters includes the custom fields of Distribution.
type CustomDistributionParameters struct{}
type CustomDistributionParameters struct {
CallerReference *string `json:"callerReference,omitempty"`
Copy link
Collaborator

Choose a reason for hiding this comment

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

Should we add some documentation stating that this field is for internal use and appropriately defaulted and the +kubebuilder:validation:Optional marker for this field?

M understanding is that both for provisioning & import scenarios, users of this API will never have to supply a value, we are adding this to be able to support import scenarios. This could also be only part of the status.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I added the kubebuilder marker. As discussed offline, if callerReference field is set, I use it during preCreate.

@@ -323,9 +323,13 @@ func postUpdate(_ context.Context, cr *svcapitypes.Distribution, resp *svcsdk.Up
func preUpdate(_ context.Context, cr *svcapitypes.Distribution, udi *svcsdk.UpdateDistributionInput) error {
udi.Id = awsclients.String(meta.GetExternalName(cr))
udi.SetIfMatch(awsclients.StringValue(cr.Status.AtProvider.ETag))
udi.DistributionConfig.CallerReference = awsclients.String(string(cr.UID))
if *cr.Spec.ForProvider.CallerReference != "" { // import scenario
Copy link
Collaborator

Choose a reason for hiding this comment

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

One point to note is that because we are adding this logic to only preUpdate, we are not supporting the use case of explicitly specifying a caller reference by the user of the API, i.e., for newly provisioned CloudFront Distributions, caller ref. will always be the uid, although we have exposed an (internal) API for it. I think this is not an important use case (as long as, for instance, AWS decides to impose a (backward-incompatible) format restriction on the caller ref. string). But I think, we should at least provide field documentation mentioning this. Is it possible to introduce this field only for the status kind?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I updated preCreate function to use specified callerReference if exists. Also, extended the documentation.

Copy link
Collaborator

Choose a reason for hiding this comment

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

Thanks @ezgidemirel!

@@ -36,6 +36,11 @@ import (
// what the AWS SDK says that some of these fields are required.

func lateInitialize(dp *svcapitypes.DistributionParameters, gdo *svcsdk.GetDistributionOutput) error {
// during import scenarios, we need the original caller reference info
if gdo.Distribution != nil && gdo.Distribution.DistributionConfig != nil {
Copy link
Member

Choose a reason for hiding this comment

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

Did you consider having an Initializer like the ones we use for tagging? It'd basically populate the caller reference with UID if it's not given and then we'd be able to treat that field just like other fields in all calls since managed reconciler makes sure the initializers are called before any external operation. In fact, we could even remove its ignore statement here.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Hi @muvaf, I tried to use an Initializer which sets spec.forProvider.distributionConfig.callerReference value with UID if it's not given. But, the import scenario failed again. Setting the value in preCreate guarantees that the resource does not exist on the cloud provider.

Thanks for pointing out the ignore statement. I missed that one.

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.

Thanks @ezgidemirel ! LGTM!

@@ -85,151 +85,156 @@ func SetupDistribution(mgr ctrl.Manager, o controller.Options) error {
}

func preCreate(_ context.Context, cr *svcapitypes.Distribution, cdi *svcsdk.CreateDistributionInput) error {
cdi.DistributionConfig.CallerReference = awsclients.String(string(cr.UID))
if cr.Spec.ForProvider.DistributionConfig.CallerReference != nil && *cr.Spec.ForProvider.DistributionConfig.CallerReference != "" {
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 cr.Spec.ForProvider.DistributionConfig.CallerReference != nil && *cr.Spec.ForProvider.DistributionConfig.CallerReference != "" {
if awsclients.StringValue(cr.Spec.ForProvider.DistributionConfig.CallerReference) != "" {

Copy link
Contributor Author

Choose a reason for hiding this comment

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

done

@@ -48,6 +48,9 @@ func lateInitialize(dp *svcapitypes.DistributionParameters, gdo *svcsdk.GetDistr
in := dp.DistributionConfig
from := gdo.Distribution.DistributionConfig

// during import scenarios, we need the original caller reference info
Copy link
Member

Choose a reason for hiding this comment

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

Could you add a comment here about what we discussed offline? i.e. the caller reference is not exposed to users who would like to import the resource, hence we need to derive it from the first response from AWS if user didn't give it explicitly.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

done

Signed-off-by: ezgidemirel <ezgidemirel91@gmail.com>
@ulucinar ulucinar merged commit 9ec5e72 into crossplane-contrib:master Apr 20, 2022
@ezgidemirel ezgidemirel deleted the fix-cloudfront-update branch April 20, 2022 12:44
@muvaf
Copy link
Member

muvaf commented Apr 20, 2022

/backport

@github-actions
Copy link

Successfully created backport PR #1268 for release-0.26.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Cannot update imported Cloudfront Distribution resources
3 participants