Skip to content

Commit 222d07c

Browse files
Merge pull request #12 from stevendborrelli/v0.4.0
v0.4.0 release prep
2 parents aea57f7 + bc66624 commit 222d07c

8 files changed

Lines changed: 131 additions & 27 deletions

File tree

.github/ISSUE_TEMPLATE/bug_report.md

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ name: Bug Report
33
about: Help us diagnose and fix bugs in this Function
44
labels: bug
55
---
6+
67
<!--
78
Thank you for helping to improve Crossplane!
89
@@ -12,21 +13,23 @@ for questions, support, and discussion.
1213
-->
1314

1415
### What happened?
16+
1517
<!--
1618
Please let us know what behaviour you expected and how this Function diverged
1719
from that behaviour.
1820
-->
1921

20-
2122
### How can we reproduce it?
23+
2224
<!--
2325
Help us to reproduce your bug as succinctly and precisely as possible. Artifacts
2426
such as example manifests or a script that triggers the issue are highly
2527
appreciated!
2628
-->
2729

2830
### What environment did it happen in?
29-
Function version:
31+
32+
Function version:
3033

3134
<!--
3235
Include at least the version or commit of Crossplane you were running. Consider

.github/ISSUE_TEMPLATE/feature_request.md

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ name: Feature Request
33
about: Help us make this Function more useful
44
labels: enhancement
55
---
6+
67
<!--
78
Thank you for helping to improve Crossplane!
89
@@ -12,13 +13,15 @@ for questions, support, and discussion.
1213
-->
1314

1415
### What problem are you facing?
16+
1517
<!--
1618
Please tell us a little about your use case - it's okay if it's hypothetical!
1719
Leading with this context helps frame the feature request so we can ensure we
1820
implement it sensibly.
1921
-->
2022

2123
### How could this Function help solve your problem?
24+
2225
<!--
23-
Let us know how you think this Function could help with your use case.
26+
Let us know how you think this Function could help with your use case.
2427
-->

.github/PULL_REQUEST_TEMPLATE.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@ We love pull requests that fix an open issue. If yours does, use the below line
1919
to indicate which issue it fixes, for example "Fixes #500".
2020
-->
2121

22-
Fixes #
22+
Fixes #
2323

2424
I have:
2525

README.md

Lines changed: 115 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@ This repository is a template for building Crossplane Composition functions in T
2424
- [Build the Crossplane Function Package](#build-the-crossplane-function-package)
2525
- [Update the Function Package Metadata](#update-the-function-package-metadata)
2626
- [Building the Function Package](#building-the-function-package)
27+
- [Installing the Function Package Directly without a Configuration Package](#installing-the-function-package-directly-without-a-configuration-package)
2728
- [Configuration Package](#configuration-package)
2829
- [Updating the `crossplane.yaml` File](#updating-the-crossplaneyaml-file)
2930
- [Build the Configuration Package](#build-the-configuration-package)
@@ -32,6 +33,8 @@ This repository is a template for building Crossplane Composition functions in T
3233
- [Key SDK Functions](#key-sdk-functions)
3334
- [Example: Creating a Resource](#example-creating-a-resource)
3435
- [Using Kubernetes Models](#using-kubernetes-models)
36+
- [Checking Resource Conditions (SDK v0.5.0+)](#checking-resource-conditions-sdk-v050)
37+
- [Detecting Crossplane Capabilities (SDK v0.5.0+)](#detecting-crossplane-capabilities-sdk-v050)
3538
- [Testing Your Function](#testing-your-function)
3639
- [TypeScript Configuration](#typescript-configuration)
3740
- [GitHub Actions](#github-actions)
@@ -83,19 +86,19 @@ kind: Configuration
8386
metadata:
8487
name: crossplane-configuration-template-typescript
8588
spec:
86-
package: ghcr.io/crossplane/configuration-template-typescript:v0.3.0
89+
package: ghcr.io/crossplane/configuration-template-typescript:v0.4.0
8790
```
8891
8992
Once installed, confirm that the package and dependencies are installed:
9093
9194
```shell
92-
$ kubectl get pkg
95+
$ kubectl get pkg
9396
NAME INSTALLED HEALTHY PACKAGE AGE
94-
configuration.pkg.crossplane.io/crossplane-configuration-template-typescript True True ghcr.io/crossplane/configuration-template-typescript:v0.3.0 49m
97+
configuration.pkg.crossplane.io/crossplane-configuration-template-typescript True True ghcr.io/crossplane/configuration-template-typescript:v0.4.0 49m
9598

9699
NAME INSTALLED HEALTHY PACKAGE AGE
97-
function.pkg.crossplane.io/crossplane-contrib-function-auto-ready True True xpkg.upbound.io/crossplane-contrib/function-auto-ready:v0.6.0 48m
98-
function.pkg.crossplane.io/crossplane-function-template-typescript True True ghcr.io/crossplane/function-template-typescript:v0.3.0 49m
100+
function.pkg.crossplane.io/crossplane-contrib-function-auto-ready True True xpkg.upbound.io/crossplane-contrib/function-auto-ready:v0.6.1 48m
101+
function.pkg.crossplane.io/crossplane-function-template-typescript True True ghcr.io/crossplane/function-template-typescript:v0.4.0 49m
99102
```
100103

101104
### Deploy the Example Manifest
@@ -335,8 +338,8 @@ packed into a Function Package:
335338
```shell
336339
$ tree _build/docker_images
337340
_build/docker_images
338-
├── function-template-typescript-runtime-amd64-v0.3.0.tar
339-
└── function-template-typescript-runtime-arm64-v0.3.0.tar
341+
├── function-template-typescript-runtime-amd64-v0.4.0.tar
342+
└── function-template-typescript-runtime-arm64-v0.4.0.tar
340343
```
341344

342345
The Dockerfile uses a multi-stage build:
@@ -372,8 +375,8 @@ the `_build/xpkg` directory:
372375
```shell
373376
$ tree _build/xpkg
374377
_build/xpkg
375-
├── function-template-typescript-amd64-v0.3.0.xpkg
376-
└── function-template-typescript-arm64-v0.3.0.xpkg
378+
├── function-template-typescript-amd64-v0.4.0.xpkg
379+
└── function-template-typescript-arm64-v0.4.0.xpkg
377380
```
378381

379382
These packages can be pushed to any Docker Registry using `crossplane xpkg push`. Update the `XPKG_REPO` in the [env](env)
@@ -387,11 +390,36 @@ npm run function-xpkg-push
387390
npm run function-build-all
388391
```
389392

393+
### Installing the Function Package Directly without a Configuration Package
394+
395+
The Function package can be installed without the need for a Configuration package.
396+
397+
```yaml
398+
apiVersion: pkg.crossplane.io/v1
399+
kind: Function
400+
metadata:
401+
name: crossplane-function-template-typescript
402+
spec:
403+
package: ghcr.io/crossplane/function-template-typescript:v0.4.0
404+
```
405+
406+
The Function package will not install the
407+
related CompositeResourceDefinition and Composition manifests.
408+
409+
Apply the CompositeResourceDefinition and Composition manifests:
410+
411+
```shell
412+
$ kubectl apply -f package-configuration/apis/apps
413+
composition.apiextensions.crossplane.io/apps.platform.upbound.io created
414+
compositeresourcedefinition.apiextensions.crossplane.io/apps.platform.upbound.io created
415+
```
416+
390417
### Configuration Package
391418

392-
With the Function package created, the Configuration
393-
Package can be generated. This package will install the Function
394-
Package as a dependency.
419+
Crossplane configuration packages install CompositeResourceDefinition and Composition manifests. The Configuration will install Function and Provider packages as dependencies.
420+
421+
With the Function package created, the Configuration Package can be generated. We'll
422+
update the Configuration package metadata to include our function as a dependency.
395423

396424
#### Updating the `crossplane.yaml` File
397425

@@ -412,7 +440,7 @@ spec:
412440
- apiVersion: pkg.crossplane.io/v1
413441
kind: Function
414442
package: ghcr.io/crossplane/function-template-typescript
415-
version: '>=v0.3.0'
443+
version: '>=v0.4.0'
416444
```
417445
418446
A Crossplane Composition requires a `CompositeResourceDefinition` (XRD) and `Composite`. These
@@ -451,9 +479,9 @@ images and the Configuration package image:
451479
```shell
452480
$ tree _build/xpkg
453481
_build/xpkg
454-
├── configuration-template-typescript-v0.3.0.xpkg
455-
├── function-template-typescript-amd64-v0.3.0.xpkg
456-
└── function-template-typescript-arm64-v0.3.0.xpkg
482+
├── configuration-template-typescript-v0.4.0.xpkg
483+
├── function-template-typescript-amd64-v0.4.0.xpkg
484+
└── function-template-typescript-arm64-v0.4.0.xpkg
457485
```
458486

459487
Push this package to a Docker registry:
@@ -484,13 +512,26 @@ export class Function implements FunctionHandler {
484512

485513
The SDK provides helper functions for working with Crossplane resources:
486514

515+
**Resource Access:**
516+
487517
- `getObservedCompositeResource(req)` - Get the observed composite resource (XR)
488518
- `getDesiredCompositeResource(req)` - Get the desired composite resource
489519
- `getObservedComposedResources(req)` - Get observed composed resources
490520
- `getDesiredComposedResources(req)` - Get desired composed resources
491521
- `setDesiredComposedResources(rsp, resources)` - Set desired composed resources
522+
523+
**Resource Conversion:**
524+
492525
- `fromModel(model)` - Convert a Kubernetes model to a Crossplane Resource (added in SDK v0.4.0)
493526
- `Resource.fromJSON()` - Create resources from JSON (legacy method, use `fromModel` for kubernetes-models)
527+
528+
**Status and Conditions (added in SDK v0.5.0):**
529+
530+
- `getCondition(resource, type)` - Extract a status condition by type from a resource. Returns a condition object with `status` set to `"Unknown"` if the condition is not found. Useful for checking resource readiness and health.
531+
- `hasCapability(req, capability)` - Check if a specific Crossplane capability is available. Use the `Capability` enum to check for features like `CAPABILITY_REQUIRED_RESOURCES` or `CAPABILITY_REQUIRED_SCHEMAS`. This helps ensure compatibility with different Crossplane versions.
532+
533+
**Response Management:**
534+
494535
- `normal(rsp, message)` - Add a normal condition to the response
495536
- `fatal(rsp, message)` - Add a fatal condition to the response
496537
- `to(req)` - Create a minimal response from a request
@@ -552,6 +593,61 @@ desiredComposed['my-pod'] = fromModel(pod);
552593

553594
**Note**: As of SDK v0.4.0, the `fromModel` helper function provides a cleaner way to convert kubernetes-models objects to Crossplane Resources. The legacy approach using `Resource.fromJSON({ resource: pod.toJSON() })` is still supported but `fromModel` is now the recommended method.
554595

596+
### Checking Resource Conditions (SDK v0.5.0+)
597+
598+
The SDK provides the `getCondition` function to extract status conditions from resources:
599+
600+
```typescript
601+
import {
602+
getCondition,
603+
getObservedComposedResources,
604+
} from '@crossplane-org/function-sdk-typescript';
605+
606+
// Get observed composed resources
607+
const observedComposed = getObservedComposedResources(req);
608+
const observedDeployment = observedComposed['my-deployment'];
609+
610+
if (observedDeployment?.resource) {
611+
// Check if the deployment is available
612+
const availableCondition = getCondition(observedDeployment.resource, 'Available');
613+
const progressingCondition = getCondition(observedDeployment.resource, 'Progressing');
614+
615+
logger?.info(
616+
{
617+
deployment: observedDeployment.resource.metadata?.name,
618+
available: availableCondition.status, // "True", "False", or "Unknown"
619+
progressing: progressingCondition.status,
620+
},
621+
'Deployment conditions'
622+
);
623+
}
624+
```
625+
626+
The `getCondition` function returns a condition object with `status` set to `"Unknown"` if the condition type is not found, making it safe to use even when resources are newly created.
627+
628+
### Detecting Crossplane Capabilities (SDK v0.5.0+)
629+
630+
Use `hasCapability` to check what features are supported by the Crossplane version:
631+
632+
```typescript
633+
import { hasCapability, Capability } from '@crossplane-org/function-sdk-typescript';
634+
635+
// Check for specific capabilities
636+
const capabilities = {
637+
requiredResources: hasCapability(req, Capability.CAPABILITY_REQUIRED_RESOURCES),
638+
requiredSchemas: hasCapability(req, Capability.CAPABILITY_REQUIRED_SCHEMAS),
639+
};
640+
641+
logger?.info({ capabilities }, 'Crossplane capabilities detected');
642+
643+
// Conditionally enable features based on capabilities
644+
if (capabilities.requiredSchemas) {
645+
// Use schema validation features available in Crossplane 2.2.0+
646+
}
647+
```
648+
649+
This allows your function to gracefully adapt to different Crossplane versions and use features when available.
650+
555651
### Testing Your Function
556652

557653
Create YAML test cases in the [test-cases/](test-cases/) directory. Each test case defines:
@@ -648,7 +744,9 @@ Manual workflow for creating Git tags:
648744

649745
### Production Dependencies
650746

651-
- `@crossplane-org/function-sdk-typescript` - Crossplane function SDK (v0.4.0+ includes `fromModel` helper)
747+
- `@crossplane-org/function-sdk-typescript` - Crossplane function SDK
748+
- v0.4.0+: `fromModel` helper for converting kubernetes-models
749+
- v0.5.0+: `getCondition` and `hasCapability` for status checking and capability detection
652750
- `commander` - CLI argument parsing
653751
- `pino` - Structured logging
654752
- `kubernetes-models` - Type-safe Kubernetes resource models

package-configuration/apis/apps/definition.yaml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
apiVersion: apiextensions.crossplane.io/v1
1+
apiVersion: apiextensions.crossplane.io/v2
22
kind: CompositeResourceDefinition
33
metadata:
44
name: apps.platform.upbound.io

package-configuration/crossplane.yaml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -22,12 +22,12 @@ spec:
2222
- apiVersion: pkg.crossplane.io/v1
2323
kind: Function
2424
package: ghcr.io/crossplane/function-template-typescript
25-
version: ">=v0.3.0"
25+
version: ">=v0.4.0"
2626
# Automatically set ready status for resources
2727
- apiVersion: pkg.crossplane.io/v1
2828
kind: Function
2929
package: xpkg.upbound.io/crossplane-contrib/function-auto-ready
30-
version: ">=v0.6.0"
30+
version: ">=v0.6.1"
3131
# Example provider dependency
3232
# - apiVersion: pkg.crossplane.io/v1
3333
# kind: Provider

package-lock.json

Lines changed: 2 additions & 2 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "function-template-typescript",
3-
"version": "0.3.0",
3+
"version": "0.4.0",
44
"description": "Template for Crossplane function in Typescript",
55
"keywords": [
66
"crossplane",

0 commit comments

Comments
 (0)