`TestDowngrade` E2E frequently failing
What happened?
This test is failing often:
+e2e | === RUN TestDowngrade/TestDowngrade/RequiredConfigurationIsHealthy
+e2e | pkg_test.go:495: Waiting 2m0s for Configuration.pkg.crossplane.io crossplane-e2e-depends-on-provider-nop to become HealthyPackageRevision, ActivePackageRevision...
+e2e | feature.go:361: - CONDITION: Configuration.pkg.crossplane.io crossplane-e2e-depends-on-provider-nop: Healthy=Unknown Reason=: "" (0001-01-01 00:00:00 +0000 UTC)
+e2e | feature.go:361: - CONDITION: Configuration.pkg.crossplane.io crossplane-e2e-depends-on-provider-nop: Healthy=Unknown Reason=UnknownPackageRevisionHealth: "" (2025-04-28 20:02:57 +0000 UTC)
+e2e | feature.go:361: - CONDITION: Configuration.pkg.crossplane.io crossplane-e2e-depends-on-provider-nop: Healthy=Unknown Reason=UnknownPackageRevisionHealth: cannot resolve package dependencies: missing dependencies: [crossplane-contrib/provider-nop] (2025-04-28 20:02:58 +0000 UTC)
+e2e | W0428 20:04:51.368003 3567 warnings.go:70] v1 ComponentStatus is deprecated in v1.19+
+e2e | W0428 20:05:04.120208 3567 warnings.go:70] ControllerConfig.pkg.crossplane.io/v1alpha1 is deprecated. Use DeploymentRuntimeConfig from pkg.crossplane.io/v1beta1 instead.
+e2e | pkg_test.go:495: resource did not have desired conditions: HealthyPackageRevision, ActivePackageRevision: context deadline exceeded:
https://app.buildpulse.io/@crossplane/crossplane shows it's failing ~25% of the time.
How can we reproduce it?
Run the package-dependency-upgrade E2E test a few times.
When I run the test against the https://github.com/crossplane/crossplane/pull/6407 branch it looks like the provider is installing fine but the configuration thinks the dependency isn't satisfied and never becomes healthy.
# kubectl get provider
NAME INSTALLED HEALTHY PACKAGE AGE
crossplane-contrib-provider-nop True True xpkg.crossplane.io/crossplane-contrib/provider-nop:v0.4.0 3m59s
# kubectl get configuration
NAME INSTALLED HEALTHY PACKAGE AGE
configuration-downgrade True Unknown xpkg.upbound.io/crossplane/e2e-nested-configuration:v0.2.0-d 4m5s
crossplane-e2e-depends-on-provider-nop True Unknown xpkg.crossplane.io/crossplane/e2e-depends-on-provider-nop:v0.3.1 4m
# kubectl describe configurationrevision
Name: configuration-downgrade-e9c658bec1a2
Namespace:
Labels: pkg.crossplane.io/package=configuration-downgrade
Annotations: <none>
API Version: pkg.crossplane.io/v1
Kind: ConfigurationRevision
Metadata:
Creation Timestamp: 2025-04-28T21:16:05Z
Finalizers:
revision.pkg.crossplane.io
Generation: 1
Owner References:
API Version: pkg.crossplane.io/v1
Block Owner Deletion: true
Controller: true
Kind: Configuration
Name: configuration-downgrade
UID: 04675cb5-2a5a-4213-a86e-399bc0a6c7b8
Resource Version: 782
UID: 1f97fc54-88a2-4c2e-b8b4-b7aba3b55cbf
Spec:
Desired State: Active
Ignore Crossplane Constraints: false
Image: xpkg.upbound.io/crossplane/e2e-nested-configuration:v0.2.0-d
Package Pull Policy: IfNotPresent
Revision: 1
Skip Dependency Resolution: false
Status:
Conditions:
Last Transition Time: 2025-04-28T21:16:19Z
Message: cannot resolve package dependencies: missing dependencies: [crossplane-contrib/provider-nop]
Reason: UnknownPackageRevisionHealth
Status: Unknown
Type: Healthy
Found Dependencies: 3
Installed Dependencies: 2
Events:
Type Reason Age From Message
---- ------ ---- ---- -------
Warning ResolveDependencies 6m36s (x3 over 6m37s) packages/configurationrevision.pkg.crossplane.io cannot resolve package dependencies: missing dependencies: [xpkg.crossplane.io/crossplane-contrib/provider-nop xpkg.crossplane.io/crossplane/e2e-depends-on-provider-nop]
Warning ResolveDependencies 6m32s (x2 over 6m32s) packages/configurationrevision.pkg.crossplane.io cannot resolve package dependencies: missing dependencies: [xpkg.crossplane.io/crossplane/e2e-depends-on-provider-nop]
Warning ResolveDependencies 51s (x8 over 6m24s) packages/configurationrevision.pkg.crossplane.io cannot resolve package dependencies: missing dependencies: [crossplane-contrib/provider-nop]
Name: crossplane-e2e-depends-on-provider-nop-857d0a2b3c50
Namespace:
Labels: pkg.crossplane.io/package=crossplane-e2e-depends-on-provider-nop
Annotations: <none>
API Version: pkg.crossplane.io/v1
Kind: ConfigurationRevision
Metadata:
Creation Timestamp: 2025-04-28T21:16:11Z
Finalizers:
revision.pkg.crossplane.io
Generation: 1
Owner References:
API Version: pkg.crossplane.io/v1
Block Owner Deletion: true
Controller: true
Kind: Configuration
Name: crossplane-e2e-depends-on-provider-nop
UID: b31beae8-8c42-481c-8da9-3c2ef72a0c03
Resource Version: 745
UID: b4e754f5-d907-4aa8-b45c-dc40e18e4b83
Spec:
Desired State: Active
Ignore Crossplane Constraints: false
Image: xpkg.crossplane.io/crossplane/e2e-depends-on-provider-nop:v0.3.1
Package Pull Policy: IfNotPresent
Revision: 1
Skip Dependency Resolution: false
Status:
Conditions:
Last Transition Time: 2025-04-28T21:16:13Z
Message: cannot resolve package dependencies: missing dependencies: [crossplane-contrib/provider-nop]
Reason: UnknownPackageRevisionHealth
Status: Unknown
Type: Healthy
Found Dependencies: 1
Events:
Type Reason Age From Message
---- ------ ---- ---- -------
Warning ResolveDependencies 33s (x12 over 6m30s) packages/configurationrevision.pkg.crossplane.io cannot resolve package dependencies: missing dependencies: [crossplane-contrib/provider-nop]
Here's the lock:
# kubectl get -o yaml lock lock
apiVersion: pkg.crossplane.io/v1beta1
kind: Lock
metadata:
creationTimestamp: "2025-04-28T21:15:58Z"
finalizers:
- lock.pkg.crossplane.io
generation: 4
name: lock
resourceVersion: "744"
uid: 57bd1dd2-850b-4c67-89b3-a0428e4461b4
packages:
- apiVersion: pkg.crossplane.io/v1
dependencies:
- constraints: <=v0.4.0
package: xpkg.crossplane.io/crossplane-contrib/provider-nop
type: Provider
- constraints: v0.3.1
package: xpkg.crossplane.io/crossplane/e2e-depends-on-provider-nop
type: Configuration
kind: Configuration
name: configuration-downgrade-e9c658bec1a2
source: xpkg.upbound.io/crossplane/e2e-nested-configuration
version: v0.2.0-d
- apiVersion: pkg.crossplane.io/v1
dependencies: []
kind: Provider
name: crossplane-contrib-provider-nop-a52ba8a7a054
source: xpkg.crossplane.io/crossplane-contrib/provider-nop
version: v0.4.0
- apiVersion: pkg.crossplane.io/v1
dependencies:
- apiVersion: pkg.crossplane.io/v1
constraints: =v0.3.1
kind: Provider
package: crossplane-contrib/provider-nop
kind: Configuration
name: crossplane-e2e-depends-on-provider-nop-857d0a2b3c50
source: xpkg.crossplane.io/crossplane/e2e-depends-on-provider-nop
version: v0.3.1
status:
conditions:
- lastTransitionTime: "2025-04-28T21:16:07Z"
reason: DependencyResolutionSucceeded
status: "True"
type: Resolved
Given the (almost) 100% failure rate on https://github.com/crossplane/crossplane/pull/6407 it'd appear that running with realtime compositions (or this PR specifically) breaks package dependencies somehow? I have no idea how - I wouldn't expect an interaction between the two features.
Hid the above comment because I realized I was running the test without the right -test-suite flag, so downgrades weren't enabled.
Just got this to fail locally. It looks like the provider is installed, but not in the lock...
# kubectl get provider.pkg
NAME INSTALLED HEALTHY PACKAGE AGE
crossplane-contrib-provider-nop True True xpkg.crossplane.io/crossplane-contrib/provider-nop:v0.3.1 22m
# kubectl describe provider.pkg
Name: crossplane-contrib-provider-nop
Namespace:
Labels: <none>
Annotations: <none>
API Version: pkg.crossplane.io/v1
Kind: Provider
Metadata:
Creation Timestamp: 2025-04-29T01:05:55Z
Generation: 27
Resource Version: 1102
UID: e993843b-e59b-4007-897c-3a19e1811327
Spec:
Ignore Crossplane Constraints: false
Package: xpkg.crossplane.io/crossplane-contrib/provider-nop:v0.3.1
Package Pull Policy: IfNotPresent
Revision Activation Policy: Automatic
Revision History Limit: 1
Runtime Config Ref:
API Version: pkg.crossplane.io/v1beta1
Kind: DeploymentRuntimeConfig
Name: default
Skip Dependency Resolution: false
Status:
Conditions:
Last Transition Time: 2025-04-29T01:06:05Z
Reason: HealthyPackageRevision
Status: True
Type: Healthy
Last Transition Time: 2025-04-29T01:05:56Z
Reason: ActivePackageRevision
Status: True
Type: Installed
Current Identifier: xpkg.crossplane.io/crossplane-contrib/provider-nop:v0.3.1
Current Revision: crossplane-contrib-provider-nop-761d51fed128
Events:
Type Reason Age From Message
---- ------ ---- ---- -------
Warning InstallPackageRevision 22m (x9 over 22m) packages/provider.pkg.crossplane.io current package revision health is unknown
Warning InstallPackageRevision 22m (x15 over 22m) packages/provider.pkg.crossplane.io current package revision is unhealthy
Normal InstallPackageRevision 22m packages/provider.pkg.crossplane.io Successfully installed package revision
# kubectl get -o yaml lock lock
apiVersion: pkg.crossplane.io/v1beta1
kind: Lock
metadata:
creationTimestamp: "2025-04-29T01:05:45Z"
finalizers:
- lock.pkg.crossplane.io
generation: 51
name: lock
resourceVersion: "1103"
uid: e55c9f6b-9495-49e5-9221-0ff16b52ecf3
packages:
- apiVersion: pkg.crossplane.io/v1
dependencies:
- constraints: <=v0.4.0
package: xpkg.crossplane.io/crossplane-contrib/provider-nop
type: Provider
- constraints: v0.3.1
package: xpkg.crossplane.io/crossplane/e2e-depends-on-provider-nop
type: Configuration
kind: Configuration
name: configuration-downgrade-e9c658bec1a2
source: xpkg.upbound.io/crossplane/e2e-nested-configuration
version: v0.2.0-d
- apiVersion: pkg.crossplane.io/v1
dependencies:
- apiVersion: pkg.crossplane.io/v1
constraints: =v0.3.1
kind: Provider
package: crossplane-contrib/provider-nop
kind: Configuration
name: crossplane-e2e-depends-on-provider-nop-857d0a2b3c50
source: xpkg.crossplane.io/crossplane/e2e-depends-on-provider-nop
version: v0.3.1
status:
conditions:
- lastTransitionTime: "2025-04-29T01:05:59Z"
reason: DependencyResolutionSucceeded
status: "True"
type: Resolved
This is interesting. I noticed provider-nop v0.3.1 existed and was the active revision. I edited it to add an annotation to kick off a reconcile, and it added itself to the lock.
Right after it added itself I saw this:
# kubectl get providerrevision
NAME HEALTHY REVISION IMAGE STATE DEP-FOUND DEP-INSTALLED AGE
crossplane-contrib-provider-nop-761d51fed128 True 2 crossplane-contrib/provider-nop:v0.3.1 Active 39m
crossplane-contrib-provider-nop-a52ba8a7a054 True 1 xpkg.crossplane.io/crossplane-contrib/provider-nop:v0.4.0 Inactive 39m
However soon after it's gone from the Lock again and I see this:
# kubectl get providerrevision
NAME HEALTHY REVISION IMAGE STATE DEP-FOUND DEP-INSTALLED AGE
crossplane-contrib-provider-nop-761d51fed128 True 2 xpkg.crossplane.io/crossplane-contrib/provider-nop:v0.3.1 Active 40m
crossplane-contrib-provider-nop-a52ba8a7a054 True 1 xpkg.crossplane.io/crossplane-contrib/provider-nop:v0.4.0 Inactive 40m
Note the image changed - it's now xpkg.crossplane.io/....
I added some logging:
--- a/internal/controller/pkg/revision/dependency.go
+++ b/internal/controller/pkg/revision/dependency.go
@@ -31,6 +31,7 @@ import (
"sigs.k8s.io/controller-runtime/pkg/client"
"github.com/crossplane/crossplane-runtime/pkg/errors"
+ "github.com/crossplane/crossplane-runtime/pkg/logging"
"github.com/crossplane/crossplane-runtime/pkg/resource"
pkgmetav1 "github.com/crossplane/crossplane/apis/pkg/meta/v1"
@@ -63,14 +64,16 @@ type PackageDependencyManager struct {
client client.Client
newDag dag.NewDAGFn
packageType schema.GroupVersionKind
+ log logging.Logger
}
// NewPackageDependencyManager creates a new PackageDependencyManager.
-func NewPackageDependencyManager(c client.Client, nd dag.NewDAGFn, pkgType schema.GroupVersionKind) *PackageDependencyManager {
+func NewPackageDependencyManager(c client.Client, nd dag.NewDAGFn, pkgType schema.GroupVersionKind, l logging.Logger) *PackageDependencyManager {
return &PackageDependencyManager{
client: c,
newDag: nd,
packageType: pkgType,
+ log: l,
}
}
@@ -148,6 +151,12 @@ func (m *PackageDependencyManager) Resolve(ctx context.Context, meta pkgmetav1.P
// to another registry)
for _, lp := range lock.Packages {
if self.Name == lp.Name && self.Type == lp.Type && self.Source != lp.Identifier() {
+ m.log.Debug("Package with same name and type but different source exists in lock. Removing it.",
+ "name", lp.Name,
+ "type", ptr.Deref(lp.Type, "Unknown"),
+ "old-source", lp.Identifier(),
+ "new-source", lp.Source,
+ )
if err := m.RemoveSelf(ctx, pr); err != nil {
return found, installed, invalid, err
}
...and I see this. It's repeated 31 times in total, but seems to eventually stabilize.
So it looks like at some point there's two revisions fighting to remove each other from the lock, because they think they're different sources when they're not (xpkg.crossplane.io is the default registry). Somehow this is ending up with neither revision being in the lock...
2025-04-29T02:31:15Z DEBUG crossplane Package with same name and type but different source exists in lock. Removing it. {"controller": "packages/providerrevision.pkg.crossplane.io", "name": "crossplane-contrib-provider-nop-761d51fed128", "type": "Unknown", "old-source": "crossplane-contrib/provider-nop", "new-source": "xpkg.crossplane.io/crossplane-contrib/provider-nop"}
2025-04-29T02:31:16Z DEBUG crossplane Package with same name and type but different source exists in lock. Removing it. {"controller": "packages/providerrevision.pkg.crossplane.io", "name": "crossplane-contrib-provider-nop-761d51fed128", "type": "Unknown", "old-source": "xpkg.crossplane.io/crossplane-contrib/provider-nop", "new-source": "crossplane-contrib/provider-nop"}
2025-04-29T02:31:17Z DEBUG crossplane Package with same name and type but different source exists in lock. Removing it. {"controller": "packages/providerrevision.pkg.crossplane.io", "name": "crossplane-contrib-provider-nop-761d51fed128", "type": "Unknown", "old-source": "crossplane-contrib/provider-nop", "new-source": "xpkg.crossplane.io/crossplane-contrib/provider-nop"}
2025-04-29T02:31:18Z DEBUG crossplane Package with same name and type but different source exists in lock. Removing it. {"controller": "packages/providerrevision.pkg.crossplane.io", "name": "crossplane-contrib-provider-nop-761d51fed128", "type": "Unknown", "old-source": "xpkg.crossplane.io/crossplane-contrib/provider-nop", "new-source": "crossplane-contrib/provider-nop"}
2025-04-29T02:31:19Z DEBUG crossplane Package with same name and type but different source exists in lock. Removing it. {"controller": "packages/providerrevision.pkg.crossplane.io", "name": "crossplane-contrib-provider-nop-761d51fed128", "type": "Unknown", "old-source": "crossplane-contrib/provider-nop", "new-source": "xpkg.crossplane.io/crossplane-contrib/provider-nop"}
2025-04-29T02:31:20Z DEBUG crossplane Package with same name and type but different source exists in lock. Removing it. {"controller": "packages/providerrevision.pkg.crossplane.io", "name": "crossplane-contrib-provider-nop-761d51fed128", "type": "Unknown", "old-source": "xpkg.crossplane.io/crossplane-contrib/provider-nop", "new-source": "crossplane-contrib/provider-nop"}
2025-04-29T02:31:21Z DEBUG crossplane Package with same name and type but different source exists in lock. Removing it. {"controller": "packages/providerrevision.pkg.crossplane.io", "name": "crossplane-contrib-provider-nop-761d51fed128", "type": "Unknown", "old-source": "crossplane-contrib/provider-nop", "new-source": "xpkg.crossplane.io/crossplane-contrib/provider-nop"}
The PR that introduced the different-source check: https://github.com/crossplane/crossplane/pull/5946
Not sure how this is happening...
If changing the source results in a new OCI digest (e.g crossplane-contrib/provider-nop:v0.4.0 -> xpkg.crossplane.io/crossplane-contrib/provider-nop:v0.3.1) that should result in two package revisions.
The package reconciler disables all active revisions before it sets a new revision active. So only one revision should ever be active:
https://github.com/crossplane/crossplane/blob/09e27bdb1e25c0f839a58685c2ff99768b75320d/internal/controller/pkg/manager/reconciler.go#L399-L403
The revision reconciler returns early (before it resolves dependencies) for inactive revisions:
https://github.com/crossplane/crossplane/blob/09e27bdb1e25c0f839a58685c2ff99768b75320d/internal/controller/pkg/revision/reconciler.go#L660
https://github.com/crossplane/crossplane/blob/09e27bdb1e25c0f839a58685c2ff99768b75320d/internal/controller/pkg/revision/reconciler.go#L843
Maybe there's a stale cache read going on somewhere? e.g.:
- The package reconciler doesn't see the existing active revision yet when it creates a new active one
- The revision reconciler is reconciling revisions that're actually inactive but appear active due to a stale cache read
https://github.com/crossplane/crossplane/blob/09e27bdb1e25c0f839a58685c2ff99768b75320d/test/e2e/pkg_test.go#L488-L492
https://github.com/crossplane/crossplane/blob/09e27bdb1e25c0f839a58685c2ff99768b75320d/test/e2e/manifests/pkg/dependency-upgrade/downgrade/package/crossplane.yaml#L15-L18
https://explore.ggcr.dev/fs/xpkg.crossplane.io/crossplane/e2e-depends-on-provider-nop@sha256:e19cd5c9aa6701974c56aa819a9d784290366a353976264eb053b0160ab401b3/package.yaml
It looks like the configuration the (sometimes) failing test installs:
- Depends directly on
xpkg.crossplane.io/crossplane-contrib/provider-nop <= v0.4.0 - Depends indirectly on
crossplane-contrib/provider-nop == v0.3.1
Given both dependencies are created in rapid succession (they're both dependencies of the same configuration) I could easily imagine there's some cache race going on here.
We could address the specific case this E2E test is hitting by teaching the check added in https://github.com/crossplane/crossplane/pull/5946 about the default registry, so that it knows xpkg.crossplane.io/a/b and a/b are the same package. I don't think that'd really solve the underlying bug though.
We shouldn't let two revisions fight to remove each other from the lock under any circumstance, e.g. if there was a brief window where mirror.acme.co/crossplane-contrib/provider-nop and crossplane-contrib/provider-nop` both thought they were the active package revision.
Just got this to fail locally. It looks like the provider is installed, but not in the lock...
# kubectl get provider.pkg NAME INSTALLED HEALTHY PACKAGE AGE crossplane-contrib-provider-nop True True xpkg.crossplane.io/crossplane-contrib/provider-nop:v0.3.1 22m # kubectl describe provider.pkg Name: crossplane-contrib-provider-nop Namespace: Labels: <none> Annotations: <none> API Version: pkg.crossplane.io/v1 Kind: Provider Metadata: Creation Timestamp: 2025-04-29T01:05:55Z Generation: 27 Resource Version: 1102 UID: e993843b-e59b-4007-897c-3a19e1811327 Spec: Ignore Crossplane Constraints: false Package: xpkg.crossplane.io/crossplane-contrib/provider-nop:v0.3.1 Package Pull Policy: IfNotPresent Revision Activation Policy: Automatic Revision History Limit: 1 Runtime Config Ref: API Version: pkg.crossplane.io/v1beta1 Kind: DeploymentRuntimeConfig Name: default Skip Dependency Resolution: false Status: Conditions: Last Transition Time: 2025-04-29T01:06:05Z Reason: HealthyPackageRevision Status: True Type: Healthy Last Transition Time: 2025-04-29T01:05:56Z Reason: ActivePackageRevision Status: True Type: Installed Current Identifier: xpkg.crossplane.io/crossplane-contrib/provider-nop:v0.3.1 Current Revision: crossplane-contrib-provider-nop-761d51fed128 Events: Type Reason Age From Message ---- ------ ---- ---- ------- Warning InstallPackageRevision 22m (x9 over 22m) packages/provider.pkg.crossplane.io current package revision health is unknown Warning InstallPackageRevision 22m (x15 over 22m) packages/provider.pkg.crossplane.io current package revision is unhealthy Normal InstallPackageRevision 22m packages/provider.pkg.crossplane.io Successfully installed package revisionkubectl get -o yaml lock lock
apiVersion: pkg.crossplane.io/v1beta1 kind: Lock metadata: creationTimestamp: "2025-04-29T01:05:45Z" finalizers:
- lock.pkg.crossplane.io generation: 51 name: lock resourceVersion: "1103" uid: e55c9f6b-9495-49e5-9221-0ff16b52ecf3 packages:
- apiVersion: pkg.crossplane.io/v1 dependencies:
- constraints: <=v0.4.0 package: xpkg.crossplane.io/crossplane-contrib/provider-nop type: Provider
- constraints: v0.3.1 package: xpkg.crossplane.io/crossplane/e2e-depends-on-provider-nop type: Configuration kind: Configuration name: configuration-downgrade-e9c658bec1a2 source: xpkg.upbound.io/crossplane/e2e-nested-configuration version: v0.2.0-d
- apiVersion: pkg.crossplane.io/v1 dependencies:
- apiVersion: pkg.crossplane.io/v1 constraints: =v0.3.1 kind: Provider package: crossplane-contrib/provider-nop kind: Configuration name: crossplane-e2e-depends-on-provider-nop-857d0a2b3c50 source: xpkg.crossplane.io/crossplane/e2e-depends-on-provider-nop version: v0.3.1 status: conditions:
- lastTransitionTime: "2025-04-29T01:05:59Z" reason: DependencyResolutionSucceeded status: "True" type: Resolved
I think it's related with this comment.
I think it's related with this comment.
@ezgidemirel FWIW it wasn't missing for a short period, and one of the revisions was definitely active. It was missing until I edited an annotation on the active revision to trigger a reconcile. Then the controller added it. That's in part why I opened https://github.com/crossplane/crossplane/pull/6415, to reconcile revisions when the lock changes.
(From @ezgidemirel on Slack):
one suggestion I have is to normalize packages to the repository/image-name format within the Identifier() method and ensure that this method is used consistently across all DAG-related methods, like TraceNode. I didn’t get a chance to fully test this today, but I can take care of it tomorrow if you don’t have time to look into it.
That sounds similar to what I was thinking at https://github.com/crossplane/crossplane/issues/6413.
Do you mean repository/image-name like crossplane-contrib/provider-nop, or like xpkg.upbound.io/crossplane-contrib/provider-nop (with the registry)? Only the latter (with the registry) uniquely identifies a package. I've proposed changing this in https://github.com/crossplane/crossplane/issues/6018, but today if you strip the registry then compare just repo and image name you're losing information (the registry) that uniquely identifies a package.
So unless we choose to adopt https://github.com/crossplane/crossplane/issues/6018, today it'd be safer to always include the registry, and inject the default registry when it's omitted.
The other thing to consider is that as I mentioned in https://github.com/crossplane/crossplane/issues/6413, this could fix this failing E2E but it doesn't fix the underlying bug it uncovered - that two revisions of a package can be active at the same time. At least from the reconciler's perspective.
Put otherwise, if you copy xpkg.crossplane.io/crossplane-contrib/provider-nop:v1.2.0 to internal.acme.co/crossplane-contrib/provider-nop:v1.2.0 and then upgrade your package from one to the other, the revision reconciler could still enter this state where it thinks both are active and they fight to remove each other from the lock. It's an edge case, but still a problem.
@negz at first, I thought we might not need registry information in the DAG, since installing the same package from multiple registries would lead to conflicts when acquiring CRD ownership. However, after reconsidering, I realized this approach introduces security concerns and is quite risky.
I’ve now propagated the default registry to the DAG and normalized package identifiers to the <registry>/<organization>/<repository> format, which resolved the issue in the e2e test.
That said, I encountered a problem when trying to install an image without a defined registry. The installation failed with the following log:
2025-04-30T18:42:57+03:00 DEBUG crossplane Package with same name and type but different source exists in lock. Removing it. {"controller": "packages/providerrevision.pkg.crossplane.io", "name": "crossplane-contrib-provider-nop-761d51fed128", "type": "Unknown", "old-source": "xpkg.crossplane.io/crossplane-contrib/provider-nop", "new-source": "crossplane-contrib/provider-nop"}
As you’ve noticed, there’s a conflict here. I believe we have two options:
-
Stop supporting automatic registry updates and require users to manually migrate between registries. This would involve pausing packages and performing some manual adjustments in the cluster to adopt the
<registry>/<organization>/<repository>format as the canonical identifier. -
Assume the image is uniquely identified by
<organization>/<repository>, and use the registry information only during installation and upgrades, not for ongoing identity checks.
I think the automation from merging PR #6415 erroneously closed this issue.
This is a bunch of commits I made while debugging and attempting to fix https://github.com/crossplane/crossplane/issues/6413. I don't expect any of the commits to fix that issue
I think the text of "fix https://github.com/crossplane/crossplane/issues/6413" triggered the close here, but the rest of the context is saying it's not actually fixed 😂
Crossplane does not currently have enough maintainers to address every issue and pull request. This issue has been automatically marked as stale because it has had no activity in the last 90 days. It will be closed in 14 days if no further activity occurs. Leaving a comment starting with /fresh will mark this issue as not stale.