Releases: crossplane/upjet
Release list
v1.10.3
This patch release backports two bug fixes to the release-1.10 branch.
Bug Fixes
-
Prevent Terraform provider panics on cached state for missing resources (#686, backport of #685): When a Terraform state was previously cached in the tracker store with a zero-valued
RawConfig/RawPlanbut the external resource is no longer found duringObserve, these fields could remainnil. This could panic the underlying Terraform provider when it attempted to read an attribute fromRawConfigorRawPlan(for example, the Terraform AWS provider's tagging interceptor inverify.SetTagsDiff). The external client now sets theInstanceState'sRawConfigandRawPlanin this scenario. A regression test reproducing the panic conditions was added. -
Omit
XValidationfor required fields with references (#690, backport of #684): When a field is marked as required but also has a reference configured, it is satisfiable via the generated*Ref/*Selectormechanisms. Upjet now explicitly sets such fields to non-required inNewReferenceField, so noXValidationrule is emitted for them. Fixes an issue observed in crossplane-contrib/provider-upjet-gcp#952.
What's Changed
- [Backport release-1.10] Set InstanceState's RawConfig & RawPlan if Resource is not found by @ulucinar in #686
- [Backport release-1.10] fix(types): omit XValidation for required fields with references by @jonasz-lasut in #690
Full Changelog: v1.10.2...v1.10.3
v2.3.0
New Features
Conversion Webhook Decoupled from Leader Election (#678)
Setup function. Providers that set StartWebhooks: true need to update their entry point. Providers that do not use conversion webhooks are unaffected.
Conversion webhook registration was gated behind leader election through the SetupGated/gate mechanism. SetupGated stores a closure that only fires on the elected leader, so follower pods never called ctrl.NewWebhookManagedBy and their webhook servers returned 404 for every conversion request. With two replicas and --leader-election, some conversion webhook calls fail.
The fix separates webhook registration from reconciler setup:
-
controller.go.tmpl: adds SetupWebhookWithManager — a standalone function that registers the conversion webhook for a single resource kind. Removes the if o.StartWebhooks { ... } block from Setup; webhook registration is no longer the reconciler's responsibility.
-
setup.go.tmpl: adds the SetupWebhookWithManager{{ .Group }} aggregator, following the same pattern as Setup{{ .Group }} and SetupGated{{ .Group }}, so providers can register all webhooks for a group in a single call.
Providers call SetupWebhookWithManager_ once before mgr.Start() on every pod, independent of the gate and leader election. Reconciler setup remains behind the gate and runs only on the leader.
// OLD generated code (v2.2.0 and earlier) — inside Setup()
if o.StartWebhooks {
if err := ctrl.NewWebhookManagedBy(mgr, &v1beta1.MyResource{}).
Complete(); err != nil {
return errors.Wrap(err, "cannot register webhook for the kind v1beta1.MyResource")
}
}What changed
The if o.StartWebhooks { ... } block has been removed from the generated Setup() function entirely. In its place, each generated resource controller file now exposes a standalone function:
// NEW generated code (v2.3.0) — standalone function, not inside Setup()
func SetupWebhookWithManager(mgr ctrl.Manager) error {
if err := ctrl.NewWebhookManagedBy(mgr, &v1beta1.MyResource{}).
Complete(); err != nil {
return errors.Wrap(err, "cannot register webhook for the kind v1beta1.MyResource")
}
return nil
}The group-level zz_setup.go file also gains a corresponding aggregator:
func SetupWebhookWithManagerMyGroup(mgr ctrl.Manager) error {
for _, setup := range []func(ctrl.Manager) error{
myresourceSetupWebhookWithManager,
// ... all resources in this group
} {
if err := setup(mgr); err != nil {
return err
}
}
return nil
}The StartWebhooks bool field remains on tjcontroller.Options for now but has no effect on the generated code and will be removed in a future release.
Provider side:
// Webhooks are registered eagerly on all pods before mgr.Start() so that
// every replica (leader and followers alike) can serve conversion requests.
// Reconciler setup is deferred to the gate and only runs on the leader.
startWebhooks := *certsDir != ""
if startWebhooks {
kingpin.FatalIfError(clustercontroller.SetupWebhookWithManager_accesscontextmanager(mgr), "Cannot setup cluster-scoped webhooks")
kingpin.FatalIfError(namespacedcontroller.SetupWebhookWithManager_accesscontextmanager(mgr), "Cannot setup namespaced webhooks")
}MR API Lifecycle Versioning & CRD Version Management (#539, #563, #567, #585)
Upjet now includes a comprehensive framework for managing Managed Resource API versioning across CRD versions. This introduces:
- New configuration APIs (
LifecycleConfiguration, storage/hub version hooks) inpkg/config/resource.goandpkg/pipeline/for generating multi-version CRDs - A
pkg/config/conversionpackage with built-in converters (optional field, field type change) and helpers for registering conversion functions automatically - A new
cmd/schemadiffCLI tool for schema change detection, integrated with thecrddifftool for detecting breaking changes between CRD versions - Documentation guide for managing CRD versions (
docs/breaking-change-detection.md)
API Roundtrip Testing Library (#636)
A new testing library (pkg/test/roundtrip) enables API roundtrip tests for generated provider types:
- Fuzzer-based serialization roundtrip testing with configurable fuzz functions
EquateNilAndZeroValuePtrcomparison helper for comparing nil pointers and zero-value pointers
ReconciliationPolicy Support (#665, #668)
A new ReconciliationPolicy API type (apis/v1alpha1/reconciliation_policy.go) allows per-resource control over reconciliation rate limiting:
- Configurable exponential failure rate limiter with per-resource
baseDelayandmaxDelay - New
reconciliationpolicyreconciler and finalizer implementations inpkg/reconciler/reconciliationpolicy/ handler.WithDefaultRateLimiteroption to make the default rate limiter forhandler.EventHandlerconfigurable (#668)
Resource Identity Support for TF Plugin Framework (#623)
The Terraform Plugin Framework integration now supports resource identity:
- Identity is passed to the framework only when the resource supports it
Missing Resource Identitydiagnostics are now treated as resource-not-found, enabling proper observe behavior
Customizable Controller Setup Template (#655)
Providers can now override the controller setup template used by pipeline.ControllerGenerator via config.Provider. New documentation has been added for main and controller template variables (docs/controller-template-variables.md, docs/main-template-variables.md).
Provider LocalName Support (#566)
Added an optional LocalName field to ProviderRequirement. This allows explicit override of the derived provider local name in Terraform configuration — useful for providers where the resource prefix doesn't match the source path (e.g., port-labs/port-labs).
Bug Fixes
- Race condition in async MR status (#670): Fixed a race condition on MR status between async callbacks and the managed reconciler. Async Plugin SDKv2 and Framework external clients now use deep copies for
Create/Deleteoperations. - Dotted map keys with correct nesting (#635): Fixed incorrect nesting when setting dotted map keys for sensitive values.
- Panic on null prior in
proposedNewAttributes(#641): Fixed a panic in the TF Plugin Framework client when the prior state is null. - Panic on nested attributes in collection types (#606): Fixed a panic while diffing TF framework resources with nested attribute collection types.
- Nested attributes inside blocks (#558): Handle nested attributes inside Terraform blocks correctly during schema traversal.
- Reconstructed state flush after observation failures (#555, #564): Both the Framework and TF SDK external clients now flush reconstructed states for recalculation after observation failures, fixing stale state issues.
- Runtime compatibility (#602): Fixed compatibility issues with
controller-runtimeandapimachinery(required JSON tags), and bumpedcrossplane-runtimeto v2.2.0.
Security
go.opentelemetry.io/otelupdated to v1.41.0github.com/antchfx/xpathupdated to v1.3.6google.golang.org/grpcupdated to v1.79.3
Dependency & CI Updates
- Go version bumped to 1.25.8
- Migrated to
golangci-lintv2 (v2.10.1) - Updated GitHub Actions:
actions/checkout@v6,actions/cache@v5,actions/setup-go@v6,codecov/codecov-action@v6,github/codeql-action@v4,zeebe-io/backport-action@v4,fsfe/reuse-action@v6 - Added Renovate configuration for automated dependency management
- Added
test.racemake target and parallel CI job for race detection
What's Changed
- Move mergenci to emeritus maintainers by @sergenyalcin in #556
- Add doc on managing CRD versions by @jeanduplessis in #539
- ci: Bump golangci-lint version to v2.6.1 by @erhancagirici in #557
- framework-external-client: Flush reconstructed states for recalculation after Observation failures by @erhancagirici in #555
- Handle nested attributes inside blocks by @kangasta in #558
- Adding new conversion functions and handling their runtime aspects by @sergenyalcin in #563
- tfsdk external client: Flush reconstructed states for recalculation after Observation failures by @erhancagirici in #564
- Configure Renovate by @renovate[bot] in #287
- Update zeebe-io/backport-action action to v4 by @renovate[bot] in #575
- Update actions/checkout action to v6 by @renovate[bot] in #572
- Update actions/cache action to v5 by @renovate[bot] in #571
- Update actions/github-script action to v8 by @renovate[bot] in #573
- Update codecov/codecov-action action to v5 by @renovate[bot] in #574
- Update fsfe/reuse-action action to v6 by @renovate[bot] in #577
- Update github/codeql-action action to v4 by @renovate[bot] in #582
- Update actions/setup-go action to v6 by @renovate[bot] in #580
- Update dependency ubuntu to v24 by @renovate[bot] in #581
- Update golangci/golangci-lint-action action to ...
v2.2.0
New Features
- Framework Diagnostics Error Support: Added
terraform/errors.FrameworkDiagnosticsErrorto convert Terraform plugin framework diagnostic error messages into Go errors. This enhancement improves error handling and debugging capabilities when working with Terraform plugin framework resources. - Framework Resource Identity Configuration: Introduced
config.FrameworkResourceWithComputedIdentifierexternal-name configuration specifically designed for Terraform plugin framework resources with computed identifier fields. This feature includes a newconfig.ExternalName.TFPluginFrameworkOptionsstruct for grouping framework-related configuration options and ComputedIdentifierAttributes to exclude computed identifier fields during drift calculations between desired and actual states. - Struct Tag Package & InitProvider Overrides: Added comprehensive pkg/types/structtag package providing a typed struct tag model with parsing, override capabilities, and validation. This enables per-field InitProvider overrides through
config.InitProviderOverrideswith both Kubebuilder marker and struct tag overrides. JSON tag values are now validated using regex patterns to prevent invalid CRD field names, and nil values in initProvider are properly handled to avoid spurious plan diffs. - Enhanced Tag Override System: Introduced structtag.Value.OverrideFrom method for overriding struct tags from another source, along with
config.SchemaElementOption.InitProviderTagOverridesto customize generated tags for InitProvider types. This provides fine-grained control over code generation and CRD field specifications.
Bug Fixes
Critical Race Condition Fix - Conversion Webhooks
This release resolves a critical race condition in conversion path registration that was causing intermittent failures in provider packages.
Technical Details:
- Problem: A data race existed in the conversion.Convert method where multiple goroutines could simultaneously modify registered conversion paths during in-place sorting
- Impact: This race condition was observed in provider packages and could cause unexpected conversion webhook failures
- Solution: Fixed by creating a copy of registered conversion paths before performing in-place sorting, preventing concurrent modifications
This fix addresses reliability issues that users may have experienced with conversion webhooks, particularly in high-load environments or during rapid resource operations.
What's Changed
- Fix the race on the registered conversion paths in conversion.Convert by @ulucinar in #545
- Add per-field InitProvider tag & kubebuilder marker overrides by @ulucinar in #544
- linter: suppress linter false positives on switch-case by @erhancagirici in #550
- Add config.FrameworkResourceWithComputedIdentifier external-name configuration by @ulucinar in #549
- Add terraform/errors.FrameworkDiagnosticsError by @ulucinar in #551
Full Changelog: v2.1.0...v2.2.0
v1.11.0
New Features
- New External Name Configuration: Added config.FrameworkResourceWithComputedIdentifier for more flexible external name handling in Terraform provider configurations
- Enhanced Struct Tag Support: Introduced comprehensive struct tag manipulation capabilities through the new pkg/types/structtag package
- Introduce pkg/types/structtag with a typed struct tag model (Value, parsing, override, no-omit)
- Add per-field InitProvider overrides:
- config.InitProviderOverrides with kubebuilder.Options and config.TagOverrides
- Tag overrides for json and tf via structtag.Value
- Kubebuilder marker overrides via pkg/types/markers/kubebuilder.Options
- config.InitProviderOverrides with kubebuilder.Options and config.TagOverrides
- Strengthen validation of JSON tag names and tag combinations, previously there was no validation for these.
- json struct tag values are validated using the regex ^[a-zA-Z_][a-zA-Z0-9_]*$ to prevent upjet from generating invalid CRD field names.
- tf tag values are currently not validated. This is future work (we need to investigate their syntax first)
- Treat nil values in initProvider as absent when computing ignore list; avoids spurious plan diffs
Developer Experience Improvements
- Improved Error Diagnostics: Enhanced error handling and diagnostics for Terraform plugin framework integration
- Stricter Configuration Validation: Unknown struct tag options now properly trigger errors instead of being silently ignored
Technical Improvements
- Enhanced conversion path management to prevent concurrent access issues
- Strengthened validation for external name configuration options
- Improved handling of edge cases in code generation for Crossplane providers
- Better error reporting for configuration validation failures
What's Changed
- [Backport release-1.11] PR#533 PR#534 PR#538 PR#549 PR#551 by @ulucinar in #553
- [Backport release-1.11] Backport 544 to release 1.11 by @sergenyalcin in #554
Full Changelog: v1.10.0...v1.11.0
v1.10.0
Critical Race Condition Fix - Conversion Webhooks
Important Stability Improvement: This release resolves a critical race condition in conversion path registration that was causing intermittent failures in provider packages.
Technical Details:
- Problem: A data race existed in the conversion.Convert method where multiple goroutines could simultaneously modify registered conversion paths during in-place sorting
- Impact: This race condition was observed in provider packages and could cause unexpected conversion webhook failures
- Solution: Fixed by creating a copy of registered conversion paths before performing in-place sorting, preventing concurrent modifications
This fix addresses reliability issues that users may have experienced with conversion webhooks, particularly in high-load environments or during rapid resource operations.
Additional Bug Fixes
- Panic Prevention: Fixed potential panic when ts.FrameworkProvider is nil (#500)
- Wildcard Conversion: Corrected wildcard expand behavior during resource conversion (#504)
- Connection Strings: Fixed incorrectly generated connection string maps (#506)
- External Names: Removed unnecessary ID validation for resources without ID fields (#507)
- State Management: Added custom state check configuration for Terraform Plugin Framework resources (#515)
What's Changed
- Validate that
ts.FrameworkProvideris not nil to avoid panic by @nikimanoledaki in #500 - Fix wildcard expand behavior when if the field path is not found during conversion by @sergenyalcin in #504
- Fix incorrectly generated connection string map by @sergenyalcin in #506
- remove id validation from setExternalName for resources without id field by @erhancagirici in #507
- Custom state check configuration for TF plugin framework resources by @sergenyalcin in #515
- [Backport release-1.10] Fix the race on the registered conversion paths in conversion.Convert by @ulucinar in #552
New Contributors
- @nikimanoledaki made their first contribution in #500
Full Changelog: v1.9.0...v1.10.0
v2.1.0
What's new
✨ This release introduces support for for generating providers with Terraform Protocol version 6 features in their resource schemas. Resources with nested attributes and dynamic-pseudo type attributes are now can be generated. The changes are backward compatible and does not affect existing resources.
Warning
To incorporate the changes, existing providers should first upgrade the provider to adapt Upjet v2 first, referring to the upgrade guide
Fresh providers can start with the upjet-provider-template and follow provider generation guide
After upgrading your provider to Upjet v2, you can switch to this version in your provider's go.mod, configure protov6 resources and run make generate
What's Changed
- chore: update OWNERS.md file with correct email domain for maintainers by @jbw976 in #533
- docs: upjet v2 upgrade guide by @erhancagirici in #532
- Do not duplicate base package controllers in the monolithic provider by @ulucinar in #534
- Add config.Provider.ExampleManifestConfiguration to configure the example manifest generation pipeline by @ulucinar in #535
- Introduce support for generating providers with TF protov6 features by @erhancagirici in #527
- Rename examples/conversion.ConvertSingletonListToEmbeddedObject as ApplyAPIConverters by @ulucinar in #538
Full Changelog: v2.0.0...v2.1.0-rc.0
v2.0.0
We are excited to announce Upjet v2.0.0 is available. This release introduces support for generating Crossplane v2 compatible providers with namespaced MRs.
Crossplane v2 compatibility
Upjet v2 generates Crossplane v2-compatible namespaced Managed Resources (MRs) and providers.
During the transition period of the providers, Upjet continues to generate cluster-scoped MRs along with new namespace-scoped MRs.
Namespaced MR APIs
Namespaced MR Go types now embed v2.ManagedResourceSpec. Per Crossplane v2 changes, this effectively makes the generated namespaced MR API:
spec.writeConnectionSecretToRef: connection secret refs are now local references (without namespace)- remove
spec.deletionPolicyfrom namespaced MR specs, this is now expected to be configured via management policies - remove
spec.publishConnectionDetailsToas XPv2 removed support for External Secret Stores (ESS) - generate local secret refs for sensitive input parameters in
spec.forProvider, e.g.spec.forProvider.fooSecretRef. - generate optionally namespaced reference/selector fields for cross-resource references.
Directory Structure changes
To facilitate both cluster-scoped and namespace-scoped APIs at the same repository, generated providers will have apis/ internal/controller/ examples-generated/
Module changes
- upjet module is bumped to v2
- bumped crossplane-runtime to v2 and updated all the import paths
Upgrade guide
Existing providers can refere to the upgrade guide
Fresh providers can start with the upjet-provider-template and follow provider generation guide to generate a new provider.
What's Changed
- Validate that
ts.FrameworkProvideris not nil to avoid panic by @nikimanoledaki in #500 - Fix wildcard expand behavior when if the field path is not found during conversion by @sergenyalcin in #504
- Fix incorrectly generated connection string map by @sergenyalcin in #506
- remove id validation from setExternalName for resources without id field by @erhancagirici in #507
- Custom state check configuration for TF plugin framework resources by @sergenyalcin in #515
- Sanitize Identity field in InstanceDiff by @sergenyalcin in #512
- Generate crossplane v2 providers by @erhancagirici in #518
- bump upjet go module to v2 by @erhancagirici in #519
New Contributors
- @nikimanoledaki made their first contribution in #500
Full Changelog: v1.9.0...v2.0.0
v1.9.0
This release:
- Adds support for change logs feature.
- Bumps the crossplane-runtime version to the latest commit.
What's Changed
- feat(changelogs): add support for change logs in controller templates by @jbw976 in #491
- Bump crossplane-runtime dependency by @sergenyalcin in #493
Full Changelog: v1.8.0...v1.9.0
v1.8.1
This PR bumps the crossplane-runtime dependency.
What's Changed
- [Backport release-1.8] Bump crossplane-runtime dependency by @github-actions in #494
Full Changelog: v1.8.0...v1.8.1
v1.5.1
This release contains a bug fix for update reconciliations. Now, we will call runtime conversions before update calls.
What's Changed
- [Backport release-1.5] call ApplyTFConversions in Update function from terraform plugin sdk external client by @github-actions in #492
Full Changelog: v1.5.0...v1.5.1