fix(operator): use SSA for PackageSource, separate context, unconditional creation

Switch installPlatformPackageSource to server-side apply (SSA) with
field manager, matching the pattern used in crdinstall. SSA is idempotent
and preserves metadata fields managed by other controllers.

Create PackageSource unconditionally (not only when platformSourceURL is
set), matching the previous Helm template behavior where PackageSource
was always created regardless of source URL configuration.

Use a dedicated context with its own 2-minute timeout for PackageSource
creation, separate from the platform source resource installation.

Co-Authored-By: Claude <noreply@anthropic.com>
Signed-off-by: Aleksei Sviridkin <f@lex.la>
This commit is contained in:
Aleksei Sviridkin 2026-02-19 17:54:33 +03:00
parent 8450830f06
commit 58e2b646be
No known key found for this signature in database
GPG key ID: 7988329FDF395282
2 changed files with 32 additions and 31 deletions

View file

@ -222,24 +222,28 @@ func main() {
} else {
setupLog.Info("Platform source resource installation completed successfully")
}
}
// Create platform PackageSource that references the source resource
setupLog.Info("Creating platform PackageSource", "platformSourceName", platformSourceName)
sourceType, _, err := parsePlatformSourceURL(platformSourceURL)
if err != nil {
setupLog.Error(err, "failed to parse platform source URL for PackageSource creation")
os.Exit(1)
}
// Create platform PackageSource unconditionally (it was previously created
// by a Helm template regardless of platformSourceURL). Derive sourceRefKind
// from URL when available, default to OCIRepository otherwise.
{
sourceRefKind := "OCIRepository"
if sourceType == "git" {
sourceRefKind = "GitRepository"
if platformSourceURL != "" {
sourceType, _, _ := parsePlatformSourceURL(platformSourceURL)
// Error already checked by installPlatformSourceResource above
if sourceType == "git" {
sourceRefKind = "GitRepository"
}
}
if err := installPlatformPackageSource(installCtx, directClient, platformSourceName, sourceRefKind); err != nil {
setupLog.Info("Creating platform PackageSource", "platformSourceName", platformSourceName)
psCtx, psCancel := context.WithTimeout(mgrCtx, 2*time.Minute)
defer psCancel()
if err := installPlatformPackageSource(psCtx, directClient, platformSourceName, sourceRefKind); err != nil {
setupLog.Error(err, "failed to create platform PackageSource")
os.Exit(1)
} else {
setupLog.Info("Platform PackageSource creation completed successfully")
}
setupLog.Info("Platform PackageSource creation completed successfully")
}
// Setup PackageSource reconciler
@ -663,26 +667,15 @@ func installPlatformPackageSource(ctx context.Context, k8sClient client.Client,
logger.Info("Applying platform PackageSource", "name", packageSourceName)
existing := &cozyv1alpha1.PackageSource{}
key := client.ObjectKeyFromObject(ps)
err := k8sClient.Get(ctx, key, existing)
if err != nil {
if client.IgnoreNotFound(err) == nil {
if err := k8sClient.Create(ctx, ps); err != nil {
return fmt.Errorf("failed to create PackageSource %s: %w", packageSourceName, err)
}
logger.Info("Created platform PackageSource", "name", packageSourceName)
} else {
return fmt.Errorf("failed to check if PackageSource exists: %w", err)
}
} else {
ps.SetResourceVersion(existing.GetResourceVersion())
if err := k8sClient.Update(ctx, ps); err != nil {
return fmt.Errorf("failed to update PackageSource %s: %w", packageSourceName, err)
}
logger.Info("Updated platform PackageSource", "name", packageSourceName)
patchOptions := &client.PatchOptions{
FieldManager: "cozystack-operator",
Force: func() *bool { b := true; return &b }(),
}
if err := k8sClient.Patch(ctx, ps, client.Apply, patchOptions); err != nil {
return fmt.Errorf("failed to apply PackageSource %s: %w", packageSourceName, err)
}
logger.Info("Applied platform PackageSource", "name", packageSourceName)
return nil
}

View file

@ -96,6 +96,9 @@ func TestInstallPlatformPackageSource_Updates(t *testing.T) {
ObjectMeta: metav1.ObjectMeta{
Name: "cozystack.cozystack-platform",
ResourceVersion: "1",
Labels: map[string]string{
"custom-label": "should-be-preserved",
},
},
Spec: cozyv1alpha1.PackageSourceSpec{
SourceRef: &cozyv1alpha1.PackageSourceRef{
@ -127,6 +130,11 @@ func TestInstallPlatformPackageSource_Updates(t *testing.T) {
if len(ps.Spec.Variants) != 4 {
t.Errorf("expected 4 variants after update, got %d", len(ps.Spec.Variants))
}
// Verify that labels set by other controllers are preserved (SSA does not overwrite unmanaged fields)
if ps.Labels["custom-label"] != "should-be-preserved" {
t.Errorf("expected custom-label to be preserved, got %q", ps.Labels["custom-label"])
}
}
func TestInstallPlatformPackageSource_GitRepository(t *testing.T) {