diff --git a/controllers/appwrapper_controller.go b/controllers/appwrapper_controller.go index 5c751e5..3cb70fe 100644 --- a/controllers/appwrapper_controller.go +++ b/controllers/appwrapper_controller.go @@ -43,14 +43,15 @@ type MachineType string // AppWrapperReconciler reconciles a AppWrapper object type AppWrapperReconciler struct { client.Client - Scheme *runtime.Scheme - Config config.InstaScaleConfiguration - kubeClient *kubernetes.Clientset - ocmClusterID string - ocmToken string - ocmConnection *ocmsdk.Connection - MachineType MachineType - machineCheck bool + Scheme *runtime.Scheme + Config config.InstaScaleConfiguration + kubeClient *kubernetes.Clientset + ocmClusterID string + ocmToken string + ocmConnection *ocmsdk.Connection + MachineType MachineType + machineCheck bool + machineNameCharacterLimit int } var ( @@ -247,6 +248,7 @@ func (r *AppWrapperReconciler) setMachineType(ctx context.Context) error { } if hypershiftEnabled { r.MachineType = MachineTypeNodePool + r.machineNameCharacterLimit = 15 } return nil } @@ -256,6 +258,7 @@ func (r *AppWrapperReconciler) SetupWithManager(ctx context.Context, mgr ctrl.Ma logger := ctrl.LoggerFrom(ctx) restConfig := mgr.GetConfig() + r.machineNameCharacterLimit = 30 var err error r.kubeClient, err = kubernetes.NewForConfig(restConfig) diff --git a/controllers/machinepools.go b/controllers/machinepools.go index db740df..7d04672 100644 --- a/controllers/machinepools.go +++ b/controllers/machinepools.go @@ -18,8 +18,8 @@ package controllers import ( "context" - "strings" + "fmt" cmv1 "github.com/openshift-online/ocm-sdk-go/clustersmgmt/v1" arbv1 "github.com/project-codeflare/multi-cluster-app-dispatcher/pkg/apis/controller/v1beta1" @@ -54,11 +54,13 @@ func (r *AppWrapperReconciler) scaleMachinePool(ctx context.Context, aw *arbv1.A }) if numberOfMachines != replicas { + label := fmt.Sprintf("%s-%s", aw.Name, aw.Namespace) + m := make(map[string]string) - m[aw.Name] = aw.Name + m[label] = label - machinePoolID := strings.ReplaceAll(aw.Name+"-"+userRequestedInstanceType, ".", "-") - createMachinePool, err := cmv1.NewMachinePool().ID(machinePoolID).InstanceType(userRequestedInstanceType).Replicas(replicas).Labels(m).Build() + machinePoolID := r.generateMachineName(ctx, aw.Name) + machinePool, err := cmv1.NewMachinePool().ID(machinePoolID).InstanceType(userRequestedInstanceType).Replicas(replicas).Labels(m).Build() if err != nil { logger.Error( err, "Error building MachinePool", @@ -68,15 +70,15 @@ func (r *AppWrapperReconciler) scaleMachinePool(ctx context.Context, aw *arbv1.A logger.Info( "Sending MachinePool creation request", "instanceType", userRequestedInstanceType, - "machinePoolName", createMachinePool.ID(), + "machinePoolName", machinePool.ID(), ) - response, err := clusterMachinePools.Add().Body(createMachinePool).SendContext(ctx) + response, err := clusterMachinePools.Add().Body(machinePool).SendContext(ctx) if err != nil { logger.Error(err, "Error creating MachinePool") } else { logger.Info( "Successfully created MachinePool", - "machinePoolName", createMachinePool.ID(), + "machinePoolName", machinePool.ID(), "response", response, ) } @@ -99,8 +101,8 @@ func (r *AppWrapperReconciler) deleteMachinePool(ctx context.Context, aw *arbv1. machinePoolsListResponse, _ := machinePoolsConnection.Send() machinePoolsList := machinePoolsListResponse.Items() machinePoolsList.Range(func(index int, item *cmv1.MachinePool) bool { - id, _ := item.GetID() - if strings.Contains(id, aw.Name) { + if hasAwLabel(item.Labels(), aw) { + id, _ := item.GetID() targetMachinePool, err := connection.ClustersMgmt().V1().Clusters().Cluster(r.ocmClusterID).MachinePools().MachinePool(id).Delete().SendContext(ctx) if err != nil { logger.Error( @@ -116,5 +118,6 @@ func (r *AppWrapperReconciler) deleteMachinePool(ctx context.Context, aw *arbv1. } return true }) + return ctrl.Result{Requeue: false}, nil } diff --git a/controllers/nodepools.go b/controllers/nodepools.go index f3fbe0f..7777f49 100644 --- a/controllers/nodepools.go +++ b/controllers/nodepools.go @@ -18,8 +18,8 @@ package controllers import ( "context" - "strings" + "fmt" cmv1 "github.com/openshift-online/ocm-sdk-go/clustersmgmt/v1" arbv1 "github.com/project-codeflare/multi-cluster-app-dispatcher/pkg/apis/controller/v1beta1" @@ -54,14 +54,16 @@ func (r *AppWrapperReconciler) scaleNodePool(ctx context.Context, aw *arbv1.AppW }) if numberOfMachines != replicas { + label := fmt.Sprintf("%s-%s", aw.Name, aw.Namespace) + m := make(map[string]string) - m[aw.Name] = aw.Name + m[label] = label + logger.Info("The instanceRequired array", "InstanceRequired", userRequestedInstanceType) - nodePoolID := strings.ReplaceAll(aw.Name+"-"+userRequestedInstanceType, ".", "-") - - createNodePool, err := cmv1.NewNodePool().AWSNodePool(cmv1.NewAWSNodePool().InstanceType(userRequestedInstanceType)).ID(nodePoolID).Replicas(replicas).Labels(m).Build() + nodePoolID := r.generateMachineName(ctx, aw.Name) + nodePool, err := cmv1.NewNodePool().AWSNodePool(cmv1.NewAWSNodePool().InstanceType(userRequestedInstanceType)).ID(nodePoolID).Replicas(replicas).Labels(m).Build() if err != nil { logger.Error( err, "Error building NodePool", @@ -71,15 +73,15 @@ func (r *AppWrapperReconciler) scaleNodePool(ctx context.Context, aw *arbv1.AppW logger.Info( "Sending NodePool creation request", "instanceType", userRequestedInstanceType, - "nodePoolName", createNodePool.ID(), + "nodePoolName", nodePool.ID(), ) - response, err := clusterNodePools.Add().Body(createNodePool).SendContext(ctx) + response, err := clusterNodePools.Add().Body(nodePool).SendContext(ctx) if err != nil { logger.Error(err, "Error creating NodePool") } else { logger.Info( "Successfully created NodePool", - "nodePoolName", createNodePool.ID(), + "nodePoolName", nodePool.ID(), "response", response, ) } @@ -102,8 +104,8 @@ func (r *AppWrapperReconciler) deleteNodePool(ctx context.Context, aw *arbv1.App nodePoolsListResponse, _ := nodePoolsConnection.Send() nodePoolsList := nodePoolsListResponse.Items() nodePoolsList.Range(func(index int, item *cmv1.NodePool) bool { - id, _ := item.GetID() - if strings.Contains(id, aw.Name) { + if hasAwLabel(item.Labels(), aw) { + id, _ := item.GetID() targetNodePool, err := connection.ClustersMgmt().V1().Clusters().Cluster(r.ocmClusterID).NodePools().NodePool(id).Delete().SendContext(ctx) if err != nil { logger.Error( diff --git a/controllers/utils.go b/controllers/utils.go index 85852df..ef5bee8 100644 --- a/controllers/utils.go +++ b/controllers/utils.go @@ -38,6 +38,28 @@ func getInstanceRequired(labels map[string]string) []string { return []string{} } +func (r *AppWrapperReconciler) generateMachineName(ctx context.Context, awName string) string { + + logger := ctrl.LoggerFrom(ctx) + const randomSuffixLength = 4 + maxBaseNameLength := r.machineNameCharacterLimit - randomSuffixLength - 1 + + // Truncate the base name if it exceeds the maximum length. + if len(awName) > maxBaseNameLength { + truncatedName := awName[:maxBaseNameLength] + + logger.Info( + "instance name exceeds character limit", + "limit", r.machineNameCharacterLimit, + "truncatedName", truncatedName, + ) + + awName = truncatedName + } + + return fmt.Sprintf("%s-%04x", awName, rand.Intn(1<<16)) +} + func resyncPeriod() func() time.Duration { return func() time.Duration { factor := rand.Float64() + 1 @@ -84,6 +106,7 @@ func contains(s []string, str string) bool { } func hasAwLabel(labels map[string]string, aw *arbv1.AppWrapper) bool { - value, ok := labels[aw.Name] - return ok && value == aw.Name + label := fmt.Sprintf("%s-%s", aw.Name, aw.Namespace) + value, ok := labels[label] + return ok && value == label }