[installer] Even more rigorous migration

Due to a deficiency of cozypkg (--with-source reconciles the HelmChart,
but not the HelmRepository), we have to use workarounds to bulletproof
the latest migration, by applying directly from the assets server.

```release-note
[installer] Run 20th migration using helm charts directly from the
assets server instead of relying on cozypkg to reconcile its resources
properly.
```

Signed-off-by: Timofei Larkin <lllamnyp@gmail.com>
This commit is contained in:
Timofei Larkin
2025-10-09 17:42:16 +03:00
parent 13dccea84b
commit 43c222decf
5 changed files with 31 additions and 688 deletions

View File

@@ -54,3 +54,5 @@ kube::codegen::gen_openapi \
$CONTROLLER_GEN object:headerFile="hack/boilerplate.go.txt" paths="./api/..."
$CONTROLLER_GEN rbac:roleName=manager-role crd paths="./api/..." output:crd:artifacts:config=packages/system/cozystack-controller/crds
mv packages/system/cozystack-controller/crds/cozystack.io_cozystackresourcedefinitions.yaml \
packages/system/cozystack-resource-definition-crd/definition/cozystack.io_cozystackresourcedefinitions.yaml

View File

@@ -34,7 +34,7 @@ FROM alpine:3.22
RUN wget -O- https://github.com/cozystack/cozypkg/raw/refs/heads/main/hack/install.sh | sh -s -- -v 1.2.0
RUN apk add --no-cache make kubectl coreutils git jq
RUN apk add --no-cache make kubectl helm coreutils git jq
COPY --from=builder /src/scripts /cozystack/scripts
COPY --from=builder /src/packages/core /cozystack/packages/core

View File

@@ -1,680 +0,0 @@
---
apiVersion: apiextensions.k8s.io/v1
kind: CustomResourceDefinition
metadata:
annotations:
controller-gen.kubebuilder.io/version: v0.16.4
name: cozystackresourcedefinitions.cozystack.io
spec:
group: cozystack.io
names:
kind: CozystackResourceDefinition
listKind: CozystackResourceDefinitionList
plural: cozystackresourcedefinitions
singular: cozystackresourcedefinition
scope: Cluster
versions:
- name: v1alpha1
schema:
openAPIV3Schema:
description: CozystackResourceDefinition is the Schema for the cozystackresourcedefinitions
API
properties:
apiVersion:
description: |-
APIVersion defines the versioned schema of this representation of an object.
Servers should convert recognized schemas to the latest internal value, and
may reject unrecognized values.
More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources
type: string
kind:
description: |-
Kind is a string value representing the REST resource this object represents.
Servers may infer this from the endpoint the client submits requests to.
Cannot be updated.
In CamelCase.
More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds
type: string
metadata:
type: object
spec:
properties:
application:
description: Application configuration
properties:
kind:
description: Kind of the application, used for UI and API
type: string
openAPISchema:
description: OpenAPI schema for the application, used for API
validation
type: string
plural:
description: Plural name of the application, used for UI and API
type: string
singular:
description: Singular name of the application, used for UI and
API
type: string
required:
- kind
- openAPISchema
- plural
- singular
type: object
dashboard:
description: Dashboard configuration for this resource
properties:
category:
description: Category used to group resources in the UI (e.g.,
"Storage", "Networking")
type: string
description:
description: Short description shown in catalogs or headers (e.g.,
"S3 compatible storage")
type: string
icon:
description: Icon encoded as a string (e.g., inline SVG, base64,
or data URI)
type: string
keysOrder:
description: Order of keys in the YAML view
items:
items:
type: string
type: array
type: array
module:
description: Whether this resource is a module (tenant module)
type: boolean
name:
description: Hard-coded name used in the UI (e.g., "bucket")
type: string
plural:
description: Plural human-readable name (e.g., "Buckets")
type: string
singular:
description: Human-readable name shown in the UI (e.g., "Bucket")
type: string
singularResource:
description: Whether this resource is singular (not a collection)
in the UI
type: boolean
tabs:
description: Which tabs to show for this resource
items:
description: DashboardTab enumerates allowed UI tabs.
enum:
- workloads
- ingresses
- services
- secrets
- yaml
type: string
type: array
tags:
description: Free-form tags for search and filtering
items:
type: string
type: array
weight:
description: Order weight for sorting resources in the UI (lower
first)
type: integer
required:
- category
- plural
- singular
type: object
ingresses:
description: Ingress selectors
properties:
exclude:
description: |-
Exclude contains an array of resource selectors that target resources.
If a resource matches the selector in any of the elements in the array, it is
hidden from the user, regardless of the matches in the include array.
items:
description: |-
CozystackResourceDefinitionResourceSelector extends metav1.LabelSelector with resourceNames support.
A resource matches this selector only if it satisfies ALL criteria:
- Label selector conditions (matchExpressions and matchLabels)
- AND has a name that matches one of the names in resourceNames (if specified)
The resourceNames field supports Go templates with the following variables available:
- {{ .name }}: The name of the managing application (from apps.cozystack.io/application.name)
- {{ .kind }}: The lowercased kind of the managing application (from apps.cozystack.io/application.kind)
- {{ .namespace }}: The namespace of the resource being processed
Example YAML:
secrets:
include:
- matchExpressions:
- key: badlabel
operator: DoesNotExist
matchLabels:
goodlabel: goodvalue
resourceNames:
- "{{ .name }}-secret"
- "{{ .kind }}-{{ .name }}-tls"
- "specificname"
properties:
matchExpressions:
description: matchExpressions is a list of label selector
requirements. The requirements are ANDed.
items:
description: |-
A label selector requirement is a selector that contains values, a key, and an operator that
relates the key and values.
properties:
key:
description: key is the label key that the selector
applies to.
type: string
operator:
description: |-
operator represents a key's relationship to a set of values.
Valid operators are In, NotIn, Exists and DoesNotExist.
type: string
values:
description: |-
values is an array of string values. If the operator is In or NotIn,
the values array must be non-empty. If the operator is Exists or DoesNotExist,
the values array must be empty. This array is replaced during a strategic
merge patch.
items:
type: string
type: array
x-kubernetes-list-type: atomic
required:
- key
- operator
type: object
type: array
x-kubernetes-list-type: atomic
matchLabels:
additionalProperties:
type: string
description: |-
matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels
map is equivalent to an element of matchExpressions, whose key field is "key", the
operator is "In", and the values array contains only "value". The requirements are ANDed.
type: object
resourceNames:
description: |-
ResourceNames is a list of resource names to match
If specified, the resource must have one of these exact names to match the selector
items:
type: string
type: array
type: object
x-kubernetes-map-type: atomic
type: array
include:
description: |-
Include contains an array of resource selectors that target resources.
If a resource matches the selector in any of the elements in the array, and
matches none of the selectors in the exclude array that resource is marked
as a tenant resource and is visible to users.
items:
description: |-
CozystackResourceDefinitionResourceSelector extends metav1.LabelSelector with resourceNames support.
A resource matches this selector only if it satisfies ALL criteria:
- Label selector conditions (matchExpressions and matchLabels)
- AND has a name that matches one of the names in resourceNames (if specified)
The resourceNames field supports Go templates with the following variables available:
- {{ .name }}: The name of the managing application (from apps.cozystack.io/application.name)
- {{ .kind }}: The lowercased kind of the managing application (from apps.cozystack.io/application.kind)
- {{ .namespace }}: The namespace of the resource being processed
Example YAML:
secrets:
include:
- matchExpressions:
- key: badlabel
operator: DoesNotExist
matchLabels:
goodlabel: goodvalue
resourceNames:
- "{{ .name }}-secret"
- "{{ .kind }}-{{ .name }}-tls"
- "specificname"
properties:
matchExpressions:
description: matchExpressions is a list of label selector
requirements. The requirements are ANDed.
items:
description: |-
A label selector requirement is a selector that contains values, a key, and an operator that
relates the key and values.
properties:
key:
description: key is the label key that the selector
applies to.
type: string
operator:
description: |-
operator represents a key's relationship to a set of values.
Valid operators are In, NotIn, Exists and DoesNotExist.
type: string
values:
description: |-
values is an array of string values. If the operator is In or NotIn,
the values array must be non-empty. If the operator is Exists or DoesNotExist,
the values array must be empty. This array is replaced during a strategic
merge patch.
items:
type: string
type: array
x-kubernetes-list-type: atomic
required:
- key
- operator
type: object
type: array
x-kubernetes-list-type: atomic
matchLabels:
additionalProperties:
type: string
description: |-
matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels
map is equivalent to an element of matchExpressions, whose key field is "key", the
operator is "In", and the values array contains only "value". The requirements are ANDed.
type: object
resourceNames:
description: |-
ResourceNames is a list of resource names to match
If specified, the resource must have one of these exact names to match the selector
items:
type: string
type: array
type: object
x-kubernetes-map-type: atomic
type: array
type: object
release:
description: Release configuration
properties:
chart:
description: Helm chart configuration
properties:
name:
description: Name of the Helm chart
type: string
sourceRef:
description: Source reference for the Helm chart
properties:
kind:
default: HelmRepository
description: Kind of the source reference
type: string
name:
description: Name of the source reference
type: string
namespace:
default: cozy-public
description: Namespace of the source reference
type: string
required:
- kind
- name
- namespace
type: object
required:
- name
- sourceRef
type: object
labels:
additionalProperties:
type: string
description: Labels for the release
type: object
prefix:
description: Prefix for the release name
type: string
required:
- chart
- prefix
type: object
secrets:
description: Secret selectors
properties:
exclude:
description: |-
Exclude contains an array of resource selectors that target resources.
If a resource matches the selector in any of the elements in the array, it is
hidden from the user, regardless of the matches in the include array.
items:
description: |-
CozystackResourceDefinitionResourceSelector extends metav1.LabelSelector with resourceNames support.
A resource matches this selector only if it satisfies ALL criteria:
- Label selector conditions (matchExpressions and matchLabels)
- AND has a name that matches one of the names in resourceNames (if specified)
The resourceNames field supports Go templates with the following variables available:
- {{ .name }}: The name of the managing application (from apps.cozystack.io/application.name)
- {{ .kind }}: The lowercased kind of the managing application (from apps.cozystack.io/application.kind)
- {{ .namespace }}: The namespace of the resource being processed
Example YAML:
secrets:
include:
- matchExpressions:
- key: badlabel
operator: DoesNotExist
matchLabels:
goodlabel: goodvalue
resourceNames:
- "{{ .name }}-secret"
- "{{ .kind }}-{{ .name }}-tls"
- "specificname"
properties:
matchExpressions:
description: matchExpressions is a list of label selector
requirements. The requirements are ANDed.
items:
description: |-
A label selector requirement is a selector that contains values, a key, and an operator that
relates the key and values.
properties:
key:
description: key is the label key that the selector
applies to.
type: string
operator:
description: |-
operator represents a key's relationship to a set of values.
Valid operators are In, NotIn, Exists and DoesNotExist.
type: string
values:
description: |-
values is an array of string values. If the operator is In or NotIn,
the values array must be non-empty. If the operator is Exists or DoesNotExist,
the values array must be empty. This array is replaced during a strategic
merge patch.
items:
type: string
type: array
x-kubernetes-list-type: atomic
required:
- key
- operator
type: object
type: array
x-kubernetes-list-type: atomic
matchLabels:
additionalProperties:
type: string
description: |-
matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels
map is equivalent to an element of matchExpressions, whose key field is "key", the
operator is "In", and the values array contains only "value". The requirements are ANDed.
type: object
resourceNames:
description: |-
ResourceNames is a list of resource names to match
If specified, the resource must have one of these exact names to match the selector
items:
type: string
type: array
type: object
x-kubernetes-map-type: atomic
type: array
include:
description: |-
Include contains an array of resource selectors that target resources.
If a resource matches the selector in any of the elements in the array, and
matches none of the selectors in the exclude array that resource is marked
as a tenant resource and is visible to users.
items:
description: |-
CozystackResourceDefinitionResourceSelector extends metav1.LabelSelector with resourceNames support.
A resource matches this selector only if it satisfies ALL criteria:
- Label selector conditions (matchExpressions and matchLabels)
- AND has a name that matches one of the names in resourceNames (if specified)
The resourceNames field supports Go templates with the following variables available:
- {{ .name }}: The name of the managing application (from apps.cozystack.io/application.name)
- {{ .kind }}: The lowercased kind of the managing application (from apps.cozystack.io/application.kind)
- {{ .namespace }}: The namespace of the resource being processed
Example YAML:
secrets:
include:
- matchExpressions:
- key: badlabel
operator: DoesNotExist
matchLabels:
goodlabel: goodvalue
resourceNames:
- "{{ .name }}-secret"
- "{{ .kind }}-{{ .name }}-tls"
- "specificname"
properties:
matchExpressions:
description: matchExpressions is a list of label selector
requirements. The requirements are ANDed.
items:
description: |-
A label selector requirement is a selector that contains values, a key, and an operator that
relates the key and values.
properties:
key:
description: key is the label key that the selector
applies to.
type: string
operator:
description: |-
operator represents a key's relationship to a set of values.
Valid operators are In, NotIn, Exists and DoesNotExist.
type: string
values:
description: |-
values is an array of string values. If the operator is In or NotIn,
the values array must be non-empty. If the operator is Exists or DoesNotExist,
the values array must be empty. This array is replaced during a strategic
merge patch.
items:
type: string
type: array
x-kubernetes-list-type: atomic
required:
- key
- operator
type: object
type: array
x-kubernetes-list-type: atomic
matchLabels:
additionalProperties:
type: string
description: |-
matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels
map is equivalent to an element of matchExpressions, whose key field is "key", the
operator is "In", and the values array contains only "value". The requirements are ANDed.
type: object
resourceNames:
description: |-
ResourceNames is a list of resource names to match
If specified, the resource must have one of these exact names to match the selector
items:
type: string
type: array
type: object
x-kubernetes-map-type: atomic
type: array
type: object
services:
description: Service selectors
properties:
exclude:
description: |-
Exclude contains an array of resource selectors that target resources.
If a resource matches the selector in any of the elements in the array, it is
hidden from the user, regardless of the matches in the include array.
items:
description: |-
CozystackResourceDefinitionResourceSelector extends metav1.LabelSelector with resourceNames support.
A resource matches this selector only if it satisfies ALL criteria:
- Label selector conditions (matchExpressions and matchLabels)
- AND has a name that matches one of the names in resourceNames (if specified)
The resourceNames field supports Go templates with the following variables available:
- {{ .name }}: The name of the managing application (from apps.cozystack.io/application.name)
- {{ .kind }}: The lowercased kind of the managing application (from apps.cozystack.io/application.kind)
- {{ .namespace }}: The namespace of the resource being processed
Example YAML:
secrets:
include:
- matchExpressions:
- key: badlabel
operator: DoesNotExist
matchLabels:
goodlabel: goodvalue
resourceNames:
- "{{ .name }}-secret"
- "{{ .kind }}-{{ .name }}-tls"
- "specificname"
properties:
matchExpressions:
description: matchExpressions is a list of label selector
requirements. The requirements are ANDed.
items:
description: |-
A label selector requirement is a selector that contains values, a key, and an operator that
relates the key and values.
properties:
key:
description: key is the label key that the selector
applies to.
type: string
operator:
description: |-
operator represents a key's relationship to a set of values.
Valid operators are In, NotIn, Exists and DoesNotExist.
type: string
values:
description: |-
values is an array of string values. If the operator is In or NotIn,
the values array must be non-empty. If the operator is Exists or DoesNotExist,
the values array must be empty. This array is replaced during a strategic
merge patch.
items:
type: string
type: array
x-kubernetes-list-type: atomic
required:
- key
- operator
type: object
type: array
x-kubernetes-list-type: atomic
matchLabels:
additionalProperties:
type: string
description: |-
matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels
map is equivalent to an element of matchExpressions, whose key field is "key", the
operator is "In", and the values array contains only "value". The requirements are ANDed.
type: object
resourceNames:
description: |-
ResourceNames is a list of resource names to match
If specified, the resource must have one of these exact names to match the selector
items:
type: string
type: array
type: object
x-kubernetes-map-type: atomic
type: array
include:
description: |-
Include contains an array of resource selectors that target resources.
If a resource matches the selector in any of the elements in the array, and
matches none of the selectors in the exclude array that resource is marked
as a tenant resource and is visible to users.
items:
description: |-
CozystackResourceDefinitionResourceSelector extends metav1.LabelSelector with resourceNames support.
A resource matches this selector only if it satisfies ALL criteria:
- Label selector conditions (matchExpressions and matchLabels)
- AND has a name that matches one of the names in resourceNames (if specified)
The resourceNames field supports Go templates with the following variables available:
- {{ .name }}: The name of the managing application (from apps.cozystack.io/application.name)
- {{ .kind }}: The lowercased kind of the managing application (from apps.cozystack.io/application.kind)
- {{ .namespace }}: The namespace of the resource being processed
Example YAML:
secrets:
include:
- matchExpressions:
- key: badlabel
operator: DoesNotExist
matchLabels:
goodlabel: goodvalue
resourceNames:
- "{{ .name }}-secret"
- "{{ .kind }}-{{ .name }}-tls"
- "specificname"
properties:
matchExpressions:
description: matchExpressions is a list of label selector
requirements. The requirements are ANDed.
items:
description: |-
A label selector requirement is a selector that contains values, a key, and an operator that
relates the key and values.
properties:
key:
description: key is the label key that the selector
applies to.
type: string
operator:
description: |-
operator represents a key's relationship to a set of values.
Valid operators are In, NotIn, Exists and DoesNotExist.
type: string
values:
description: |-
values is an array of string values. If the operator is In or NotIn,
the values array must be non-empty. If the operator is Exists or DoesNotExist,
the values array must be empty. This array is replaced during a strategic
merge patch.
items:
type: string
type: array
x-kubernetes-list-type: atomic
required:
- key
- operator
type: object
type: array
x-kubernetes-list-type: atomic
matchLabels:
additionalProperties:
type: string
description: |-
matchLabels is a map of {key,value} pairs. A single {key,value} in the matchLabels
map is equivalent to an element of matchExpressions, whose key field is "key", the
operator is "In", and the values array contains only "value". The requirements are ANDed.
type: object
resourceNames:
description: |-
ResourceNames is a list of resource names to match
If specified, the resource must have one of these exact names to match the selector
items:
type: string
type: array
type: object
x-kubernetes-map-type: atomic
type: array
type: object
required:
- application
- release
type: object
type: object
served: true
storage: true

View File

@@ -39,3 +39,4 @@ webhooks:
operator: NotIn
values:
- kube-system
- default

View File

@@ -3,15 +3,35 @@
set -euo pipefail
kubectl delete ingresses.networking.k8s.io --all -n cozy-dashboard --ignore-not-found
kubectl delete crd cozystackresourcedefinitions.cozystack.io --ignore-not-found
kubectl -n cozy-system delete helmrelease cozystack-api \
|| kubectl -n cozy-system delete deployment cozystack-api --ignore-not-found # fallback to help migration progress if it failed first time
while [ $( kubectl -n cozy-system get po -l app=cozystack-api --no-headers | wc -l ) != 0 ] ;
do
echo "Waiting for Cozystack API pods to be deleted";
sleep 1
done
kubectl -n cozy-system delete helmrelease cozystack-controller \
|| kubectl -n cozy-system delete deployment cozystack-controller --ignore-not-found # same fallback
kubectl delete customresourcedefinitions.apiextensions.k8s.io cozystackresourcedefinitions.cozystack.io --ignore-not-found
while [ $( kubectl -n cozy-system get po -l app=cozystack-controller --no-headers | wc -l ) != 0 ] ;
do
echo "Waiting for Cozystack controller pods to be deleted";
sleep 1
done
kubectl delete helmrelease -n cozy-dashboard dashboard --ignore-not-found
sleep 5
cozypkg -n cozy-system -C packages/system/cozystack-resource-definition-crd apply cozystack-resource-definition-crd --plain
cozypkg -n cozy-system -C packages/system/cozystack-resource-definitions apply cozystack-resource-definitions --plain
cozypkg -n cozy-system -C packages/system/cozystack-api apply cozystack-api --plain
helm upgrade --install -n cozy-system cozystack-controller ./packages/system/cozystack-controller/ --take-ownership
sleep 5
kubectl wait deployment/cozystack-api -n cozy-system --timeout=4m --for=condition=available || exit 1
kubectl wait deployment/cozystack-controller -n cozy-system --timeout=4m --for=condition=available || exit 1
timestamp=$(date --rfc-3339=ns || date)
# Make sure webhook is upgraded first, then run migration
cozypkg -C packages/system/cozystack-controller -n cozy-system reconcile cozystack-controller --force --with-source
kubectl wait hr/cozystack-controller -n cozy-system --timeout=4m --for=condition=ready || exit 1
cozypkg -C packages/system/cozystack-api -n cozy-system reconcile cozystack-api --force --with-source
kubectl wait hr/cozystack-api -n cozy-system --timeout=4m --for=condition=ready || exit 1
kubectl get namespace -o custom-columns=NAME:.metadata.name --no-headers |
grep '^tenant-' |
while read namespace ; do