fix(installer): move PackageSource creation from Helm template to operator

Replace the Helm hook approach with programmatic PackageSource creation
in the operator startup sequence. Helm hooks are unsuitable for persistent
resources like PackageSource because before-hook-creation policy causes
cascade deletion of owned ArtifactGenerators during upgrades.

The operator now creates the platform PackageSource after installing CRDs
and the Flux source resource, using the same create-or-update pattern as
installPlatformSourceResource(). The sourceRef.kind is derived from the
platform source URL (OCIRepository for oci://, GitRepository for git).

Also fix stale comment in e2e test referencing deleted crds/ directory.

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:38:23 +03:00
parent 668ddc552e
commit 655133b81c
4 changed files with 127 additions and 63 deletions

View File

@@ -42,20 +42,17 @@ manifests:
# Talos variant (default)
helm template installer packages/core/installer -n cozy-system \
--show-only templates/cozystack-operator.yaml \
--show-only templates/packagesource.yaml \
> _out/assets/cozystack-operator-talos.yaml
# Generic Kubernetes variant (k3s, kubeadm, RKE2)
helm template installer packages/core/installer -n cozy-system \
--set cozystackOperator.variant=generic \
--set cozystack.apiServerHost=REPLACE_ME \
--show-only templates/cozystack-operator.yaml \
--show-only templates/packagesource.yaml \
> _out/assets/cozystack-operator-generic.yaml
# Hosted variant (managed Kubernetes)
helm template installer packages/core/installer -n cozy-system \
--set cozystackOperator.variant=hosted \
--show-only templates/cozystack-operator.yaml \
--show-only templates/packagesource.yaml \
> _out/assets/cozystack-operator-hosted.yaml
cozypkg:

View File

@@ -222,6 +222,20 @@ 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, _, _ := parsePlatformSourceURL(platformSourceURL)
sourceRefKind := "OCIRepository"
if sourceType == "git" {
sourceRefKind = "GitRepository"
}
if err := installPlatformPackageSource(installCtx, directClient, platformSourceName, sourceRefKind); err != nil {
setupLog.Error(err, "failed to create platform PackageSource")
os.Exit(1)
} else {
setupLog.Info("Platform PackageSource creation completed successfully")
}
}
// Setup PackageSource reconciler
@@ -552,3 +566,115 @@ func generateGitRepository(name, repoURL string, refMap map[string]string) (*sou
return obj, nil
}
// installPlatformPackageSource creates the platform PackageSource resource
// that references the Flux source resource (OCIRepository or GitRepository).
func installPlatformPackageSource(ctx context.Context, k8sClient client.Client, platformSourceName, sourceRefKind string) error {
logger := log.FromContext(ctx)
packageSourceName := "cozystack." + platformSourceName
ps := &cozyv1alpha1.PackageSource{
TypeMeta: metav1.TypeMeta{
APIVersion: cozyv1alpha1.GroupVersion.String(),
Kind: "PackageSource",
},
ObjectMeta: metav1.ObjectMeta{
Name: packageSourceName,
Annotations: map[string]string{
"operator.cozystack.io/skip-cozystack-values": "true",
},
},
Spec: cozyv1alpha1.PackageSourceSpec{
SourceRef: &cozyv1alpha1.PackageSourceRef{
Kind: sourceRefKind,
Name: platformSourceName,
Namespace: "cozy-system",
Path: "/",
},
Variants: []cozyv1alpha1.Variant{
{
Name: "default",
Components: []cozyv1alpha1.Component{
{
Name: "platform",
Path: "core/platform",
Install: &cozyv1alpha1.ComponentInstall{
Namespace: "cozy-system",
ReleaseName: "cozystack-platform",
},
ValuesFiles: []string{"values.yaml"},
},
},
},
{
Name: "isp-full",
Components: []cozyv1alpha1.Component{
{
Name: "platform",
Path: "core/platform",
Install: &cozyv1alpha1.ComponentInstall{
Namespace: "cozy-system",
ReleaseName: "cozystack-platform",
},
ValuesFiles: []string{"values.yaml", "values-isp-full.yaml"},
},
},
},
{
Name: "isp-hosted",
Components: []cozyv1alpha1.Component{
{
Name: "platform",
Path: "core/platform",
Install: &cozyv1alpha1.ComponentInstall{
Namespace: "cozy-system",
ReleaseName: "cozystack-platform",
},
ValuesFiles: []string{"values.yaml", "values-isp-hosted.yaml"},
},
},
},
{
Name: "isp-full-generic",
Components: []cozyv1alpha1.Component{
{
Name: "platform",
Path: "core/platform",
Install: &cozyv1alpha1.ComponentInstall{
Namespace: "cozy-system",
ReleaseName: "cozystack-platform",
},
ValuesFiles: []string{"values.yaml", "values-isp-full-generic.yaml"},
},
},
},
},
},
}
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)
}
return nil
}

View File

@@ -8,7 +8,7 @@
}
@test "Install Cozystack" {
# Install cozy-installer chart (CRDs from crds/ are applied automatically)
# Install cozy-installer chart (operator installs CRDs on startup via --install-crds)
helm upgrade installer packages/core/installer \
--install \
--namespace cozy-system \

View File

@@ -1,59 +0,0 @@
{{- $validVariants := list "talos" "generic" "hosted" -}}
{{- if not (has .Values.cozystackOperator.variant $validVariants) -}}
{{- fail (printf "Invalid cozystackOperator.variant %q: must be one of talos, generic, hosted" .Values.cozystackOperator.variant) -}}
{{- end -}}
---
apiVersion: cozystack.io/v1alpha1
kind: PackageSource
metadata:
name: cozystack.cozystack-platform
annotations:
"helm.sh/hook": post-install,post-upgrade
"helm.sh/hook-delete-policy": before-hook-creation
operator.cozystack.io/skip-cozystack-values: "true"
spec:
sourceRef:
kind: OCIRepository
name: cozystack-platform
namespace: cozy-system
path: /
variants:
- name: default
components:
- install:
namespace: cozy-system
releaseName: cozystack-platform
name: platform
path: core/platform
valuesFiles:
- values.yaml
- name: isp-full
components:
- install:
namespace: cozy-system
releaseName: cozystack-platform
name: platform
path: core/platform
valuesFiles:
- values.yaml
- values-isp-full.yaml
- name: isp-hosted
components:
- install:
namespace: cozy-system
releaseName: cozystack-platform
name: platform
path: core/platform
valuesFiles:
- values.yaml
- values-isp-hosted.yaml
- name: isp-full-generic
components:
- install:
namespace: cozy-system
releaseName: cozystack-platform
name: platform
path: core/platform
valuesFiles:
- values.yaml
- values-isp-full-generic.yaml