Skip to content

Commit 0d6acfa

Browse files
✨ Cspo multiple images (#39)
* Add README Signed-off-by: Matej Feder <[email protected]> * Update osnir logic Signed-off-by: Matej Feder <[email protected]> * Fix osnir logic Update OpenStackNodeImageRelease after setting owner references Signed-off-by: Roman Hros <[email protected]> --------- Signed-off-by: Matej Feder <[email protected]> Signed-off-by: Roman Hros <[email protected]> Co-authored-by: Roman Hros <[email protected]>
1 parent 7872848 commit 0d6acfa

File tree

1 file changed

+35
-11
lines changed

1 file changed

+35
-11
lines changed

internal/controller/openstackclusterstackrelease_controller.go

Lines changed: 35 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@ import (
2222
"net/http"
2323
"os"
2424
"path/filepath"
25+
"strings"
2526
"sync"
2627
"time"
2728

@@ -34,6 +35,7 @@ import (
3435
"k8s.io/apimachinery/pkg/runtime/schema"
3536
"k8s.io/apimachinery/pkg/types"
3637
clusterv1beta1 "sigs.k8s.io/cluster-api/api/v1beta1"
38+
"sigs.k8s.io/cluster-api/util"
3739
"sigs.k8s.io/cluster-api/util/conditions"
3840
"sigs.k8s.io/cluster-api/util/patch"
3941
"sigs.k8s.io/cluster-api/util/record"
@@ -60,7 +62,6 @@ type NodeImages struct {
6062
const (
6163
metadataFileName = "metadata.yaml"
6264
nodeImagesFileName = "node-images.yaml"
63-
maxNameLength = 63
6465
waitForOpenStackNodeImageReleasesBecomeReady = 30 * time.Second
6566
reconcileOpenStackNodeImageReleases = 3 * time.Minute
6667
)
@@ -157,7 +158,18 @@ func (r *OpenStackClusterStackReleaseReconciler) Reconcile(ctx context.Context,
157158
ownerRef := generateOwnerReference(openstackclusterstackrelease)
158159

159160
for _, openStackNodeImage := range nodeImages.OpenStackNodeImages {
160-
osnirName := ensureMaxNameLength(fmt.Sprintf("%s-%s", openstackclusterstackrelease.Name, openStackNodeImage.CreateOpts.Name))
161+
// OpenStackNodeImageRelease is composed as follows:
162+
// <release tag without version>-<image name>-<node-image-version>
163+
// e.g.: `openstack-ferrol-1-27-ubuntu-capi-image-v1.27.8-v2`
164+
// This ensures that multiple versions of one ClusterStack could share images
165+
nodeImageVersion := releaseAssets.Meta.Versions.Components.NodeImage
166+
nameWithoutVersion, err := cutOpenStackClusterStackReleaseVersionFromReleaseTag(openstackclusterstackrelease.Name)
167+
if err != nil {
168+
return ctrl.Result{}, fmt.Errorf("failed to cut release tag: %w", err)
169+
}
170+
171+
osnirName := fmt.Sprintf("%s-%s-%s", nameWithoutVersion, openStackNodeImage.CreateOpts.Name, nodeImageVersion)
172+
161173
if err := r.getOrCreateOpenStackNodeImageRelease(ctx, openstackclusterstackrelease, osnirName, openStackNodeImage, ownerRef); err != nil {
162174
return ctrl.Result{}, fmt.Errorf("failed to get or create OpenStackNodeImageRelease %s/%s: %w", openstackclusterstackrelease.Namespace, osnirName, err)
163175
}
@@ -206,8 +218,19 @@ func (r *OpenStackClusterStackReleaseReconciler) getOrCreateOpenStackNodeImageRe
206218

207219
err := r.Get(ctx, types.NamespacedName{Name: osnirName, Namespace: openstackclusterstackrelease.Namespace}, openStackNodeImageRelease)
208220

209-
// Nothing to do if the object exists
221+
// Update owner references if the object exists
210222
if err == nil {
223+
// Ensure owner reference
224+
openStackNodeImageRelease.SetOwnerReferences(util.EnsureOwnerRef(openStackNodeImageRelease.GetOwnerReferences(), *ownerRef))
225+
226+
if err := r.Update(ctx, openStackNodeImageRelease); err != nil {
227+
record.Eventf(openStackNodeImageRelease,
228+
"ErrorOpenStackNodeImageRelease",
229+
"failed to update %s OpenStackNodeImageRelease: %s", osnirName, err.Error(),
230+
)
231+
return fmt.Errorf("failed to update OpenStackNodeImageRelease: %w", err)
232+
}
233+
211234
return nil
212235
}
213236

@@ -221,7 +244,7 @@ func (r *OpenStackClusterStackReleaseReconciler) getOrCreateOpenStackNodeImageRe
221244
openStackNodeImageRelease.Namespace = openstackclusterstackrelease.Namespace
222245
openStackNodeImageRelease.TypeMeta = metav1.TypeMeta{
223246
Kind: "OpenStackNodeImageRelease",
224-
APIVersion: "infrastructure.clusterstack.x-k8s.io/v1alpha1",
247+
APIVersion: apiv1alpha1.GroupVersion.String(),
225248
}
226249
openStackNodeImageRelease.SetOwnerReferences([]metav1.OwnerReference{*ownerRef})
227250
openStackNodeImageRelease.Spec.Image = openStackNodeImage
@@ -254,7 +277,7 @@ func (r *OpenStackClusterStackReleaseReconciler) getOwnedOpenStackNodeImageRelea
254277
for i := range osnir.GetOwnerReferences() {
255278
ownerRef := osnir.GetOwnerReferences()[i]
256279
if matchOwnerReference(&ownerRef, openstackclusterstackrelease) {
257-
ownedOpenStackNodeImageReleases = append(ownedOpenStackNodeImageReleases, &osnirList.Items[i])
280+
ownedOpenStackNodeImageReleases = append(ownedOpenStackNodeImageReleases, &osnir)
258281
break
259282
}
260283
}
@@ -318,13 +341,14 @@ func getNodeImagesFromLocal(localDownloadPath string) (*NodeImages, error) {
318341
return &nodeImages, nil
319342
}
320343

321-
// TODO: Ensure RFC 1123 compatibility.
322-
// RFC 1123 subdomain must consist of lower case alphanumeric characters, '-' or '.', and must start and end with an alphanumeric character (e.g. 'example.com', regex used for validation is '[a-z0-9]([-a-z0-9]*[a-z0-9])?(\\.[a-z0-9]([-a-z0-9]*[a-z0-9])?)*').
323-
func ensureMaxNameLength(base string) string {
324-
if len(base) > maxNameLength {
325-
return base[:maxNameLength]
344+
// cutOpenStackClusterStackReleaseVersionFromReleaseTag returns a release tag without version,
345+
// e.g. from `openstack-ferrol-1-27-v2` returns `openstack-ferrol-1-27`.
346+
func cutOpenStackClusterStackReleaseVersionFromReleaseTag(releaseTag string) (string, error) {
347+
v := strings.Split(releaseTag, "-")
348+
if len(v) != 5 && len(v) != 6 {
349+
return "", fmt.Errorf("invalid release tag %s", releaseTag)
326350
}
327-
return base
351+
return fmt.Sprintf("%s-%s-%s-%s", v[0], v[1], v[2], v[3]), nil
328352
}
329353

330354
// SetupWithManager sets up the controller with the Manager.

0 commit comments

Comments
 (0)