Skip to content

Conversation

@jbw976
Copy link
Member

@jbw976 jbw976 commented Dec 17, 2025

This PR adds a new guide for how to expose connection details for XRs in v2. As described in #1001, since XR/XRDs no longer have native connection details support, composition authors must manually compose a secret with their desired connection details (if they want them at all).

This is a tutorial based guide that walks through an example of composing an IAM User and two AccessKeys for that user. The composition also composes a secret that aggregates the username/password for both users into a single connection secret.

Similar to the getting started with composition guide, this connection details guide has support for function-go-templating, function-python, and function-kcl.

Support for function-patch-and-transform will be added to this guide once that function is updated with further support for composing connection details secrets - it is not possible currently and a code change is required.

Part of #1001

TODO:

  • fix all vale issues
  • run through each language example again for final quality check
  • sync to v2.x content sections after approved for master

@netlify
Copy link

netlify bot commented Dec 17, 2025

Deploy Preview for crossplane ready!

Name Link
🔨 Latest commit c1b60f1
🔍 Latest deploy log https://app.netlify.com/projects/crossplane/deploys/69446d51280ad50008ab3511
😎 Deploy Preview https://deploy-preview-1034--crossplane.netlify.app
📱 Preview on mobile
Toggle QR Code...

QR Code

Use your smartphone camera to open QR code link.
Lighthouse
Lighthouse
1 paths audited
Performance: 96 (🟢 up 1 from production)
Accessibility: 90 (🔴 down 2 from production)
Best Practices: 92 (no change from production)
SEO: 100 (no change from production)
PWA: 70 (no change from production)
View the detailed breakdown and full score reports

To edit notification comments on pull requests, go to your Netlify project configuration.

if "accesskey-0" in req.observed.resources:
accesskey0_conn = req.observed.resources["accesskey-0"].connection_details
if "username" in accesskey0_conn:
secret_data["user-0"] = base64.b64encode(accesskey0_conn["username"]).decode("utf-8")
Copy link
Member Author

Choose a reason for hiding this comment

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

feel free to offer better ways to do this in python - i'm not a python person and i landed on this solution because it was the only one i could get to work 😇

is there a better approach we could take here?

Copy link
Member

Choose a reason for hiding this comment

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

using stringData instead of data so you don't need the base64

Copy link
Member Author

Choose a reason for hiding this comment

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

i had tried that for awhile and couldn't get it to work either, but I'll definitely try it again! 🙏

Copy link
Member Author

Choose a reason for hiding this comment

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

well i'm not sure what i was doing before, but yes sir stringData does in fact work 😅

@jbw976
Copy link
Member Author

jbw976 commented Dec 17, 2025

ah, should have run vale locally before opening this PR - plenty to fix in https://github.com/crossplane/docs/actions/runs/20293960117/job/58283702650?pr=1034 😣

Copy link
Member

@haarchri haarchri left a comment

Choose a reason for hiding this comment

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

thanks for the guide - few small things

if "accesskey-0" in req.observed.resources:
accesskey0_conn = req.observed.resources["accesskey-0"].connection_details
if "username" in accesskey0_conn:
secret_data["user-0"] = base64.b64encode(accesskey0_conn["username"]).decode("utf-8")
Copy link
Member

Choose a reason for hiding this comment

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

using stringData instead of data so you don't need the base64

metadata:
namespace: default
name: my-keys
spec: {}
Copy link
Member

Choose a reason for hiding this comment

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

I would expect users to be able to provide a secret name as input. Otherwise, it’s hard to use the secret in a Deployment (for example, as an input), since it gets a random name by default. Just saying.

Copy link
Member

Choose a reason for hiding this comment

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

spec.writeConnectionSecretToRef.name

Copy link
Member Author

Choose a reason for hiding this comment

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

I was thinking it was OK because the secret gets labeled with the XR name, so it should be easy to find that way. I was trying to avoid adding more config and more logic, but I can see a case for having more control over where the secret gets created and thus easier discoverability of it to consume it.

This is also probably related to what namespace do we use when the XR is cluster scoped. I'll consider how to improve this!

Copy link
Member Author

Choose a reason for hiding this comment

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

i've included an optional .spec.writeConnectionSecretToRef.name to the XRD schema, the examples show how to use it, and the compositions use this name if it is provided.

names:
kind: UserAccessKey
plural: useraccesskeys
scope: Namespaced
Copy link
Member

Choose a reason for hiding this comment

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

Is there any difference when creating a cluster-scoped XR? Which namespace is used to create the Secret? The Crossplane default namespace?

Copy link
Member Author

Choose a reason for hiding this comment

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

very good question, that was on my TODO list to figure out later 😂 - may as well deal with it now. I have a feeling this example wouldn't work with a cluster scoped XR since the namespace for the secret isn't being provided in the composition, and Crossplane won't default it for us like it does for namespaced XRs (using the XR's namespace).

I'll dig in deeper!

Copy link
Member Author

Choose a reason for hiding this comment

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

actually, i wonder how the namespaced MRs work in a cluster scoped XR, if you don't provide the namespace for them in the composition. I assume it'd be the same problem as I expect for the secret resource, i.e. they would fail to be created because they have no namespace specified and crossplane won't default one for them 🤔

I will probably end up just including a namespaced example in this guide, as opposed to having both a cluster and namespaced example, but then have a "tip" or "note" callout box that says for cluster scoped XRs you need to be sure to set namespaces for any namespaced resources like the Secret.

Copy link
Member Author

Choose a reason for hiding this comment

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

this is what i ended up doing. the main example we are providing in this guide is namespaced and shows how to provide a name for the secret on the XR that gets plumbed via the compositions to the composed secret.

i've added a tip box that calls out how to take this information and extend it to also take in a namespace and set it on the composed resources in the cluster scoped XR scenario. I think that's a good balance here!

Copy link
Member

@ezgidemirel ezgidemirel left a comment

Choose a reason for hiding this comment

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

Much-needed guide @jbw976, thanks for preparing it!

* use stringData instead of base64 encoding ourselves for function-python
* expose a writeConnectionSecretToRef.name field for the XR so the secret
  name can be set if desired
* update all compositions to safely handle the secret name existing or not
* add note with guidance about cluster scoped XRDs and setting the namespace
  for composed resources

Signed-off-by: Jared Watts <[email protected]>
@jbw976
Copy link
Member Author

jbw976 commented Dec 18, 2025

@haarchri @ezgidemirel i pushed 95bc6b0 that incorporates all the feedback you all provided so far, take another look!

(still another commit coming to appease vale, but that shouldn't have functional differences i hope 🤪)

@jbw976
Copy link
Member Author

jbw976 commented Dec 18, 2025

Sweet, with 5be0d39 Vale is now passing again! ✅

@ezgidemirel
Copy link
Member

@haarchri @ezgidemirel i pushed 95bc6b0 that incorporates all the feedback you all provided so far, take another look!

(still another commit coming to appease vale, but that shouldn't have functional differences i hope 🤪)

Thanks @jbw976, this is much clearer now!

@jbw976
Copy link
Member Author

jbw976 commented Dec 18, 2025

Alrighty, I think this PR is all good from my side! The PR checklist is complete, Vale is happy, master has been synced to v2.1/v2.0, and I did a final quality testing run through all languages ✅

@jbw976 jbw976 merged commit 71527a1 into crossplane:master Dec 19, 2025
7 checks passed
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.

4 participants