github.com/1aal/kubeblocks@v0.0.0-20231107070852-e1c03e598921/pkg/controllerutil/volume_util.go (about)

     1  /*
     2  Copyright (C) 2022-2023 ApeCloud Co., Ltd
     3  
     4  This file is part of KubeBlocks project
     5  
     6  This program is free software: you can redistribute it and/or modify
     7  it under the terms of the GNU Affero General Public License as published by
     8  the Free Software Foundation, either version 3 of the License, or
     9  (at your option) any later version.
    10  
    11  This program is distributed in the hope that it will be useful
    12  but WITHOUT ANY WARRANTY; without even the implied warranty of
    13  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    14  GNU Affero General Public License for more details.
    15  
    16  You should have received a copy of the GNU Affero General Public License
    17  along with this program.  If not, see <http://www.gnu.org/licenses/>.
    18  */
    19  
    20  package controllerutil
    21  
    22  import (
    23  	"fmt"
    24  	"sort"
    25  
    26  	"golang.org/x/exp/maps"
    27  	corev1 "k8s.io/api/core/v1"
    28  
    29  	appsv1alpha1 "github.com/1aal/kubeblocks/apis/apps/v1alpha1"
    30  )
    31  
    32  type createVolumeFn func(volumeName string) corev1.Volume
    33  type updateVolumeFn func(*corev1.Volume) error
    34  
    35  func findVolumeWithVolumeName(volumes []corev1.Volume, volumeName string) int {
    36  	for index, itr := range volumes {
    37  		if itr.Name == volumeName {
    38  			return index
    39  		}
    40  	}
    41  	return -1
    42  }
    43  
    44  func CreateOrUpdateVolume(volumes []corev1.Volume, volumeName string, createFn createVolumeFn, updateFn updateVolumeFn) ([]corev1.Volume, error) {
    45  	// for update volume
    46  	if existIndex := findVolumeWithVolumeName(volumes, volumeName); existIndex >= 0 {
    47  		if updateFn == nil {
    48  			return volumes, nil
    49  		}
    50  		if err := updateFn(&volumes[existIndex]); err != nil {
    51  			return volumes, err
    52  		}
    53  		return volumes, nil
    54  	}
    55  
    56  	// for create volume
    57  	return append(volumes, createFn(volumeName)), nil
    58  }
    59  
    60  func CreateOrUpdatePodVolumes(podSpec *corev1.PodSpec, volumes map[string]appsv1alpha1.ComponentTemplateSpec) error {
    61  	var (
    62  		err        error
    63  		podVolumes = podSpec.Volumes
    64  	)
    65  	// sort the volumes
    66  	volumeKeys := maps.Keys(volumes)
    67  	sort.Strings(volumeKeys)
    68  	// Update PodTemplate Volumes
    69  	for _, cmName := range volumeKeys {
    70  		templateSpec := volumes[cmName]
    71  		if templateSpec.VolumeName == "" {
    72  			continue
    73  		}
    74  		if podVolumes, err = CreateOrUpdateVolume(podVolumes, templateSpec.VolumeName, func(volumeName string) corev1.Volume {
    75  			return corev1.Volume{
    76  				Name: volumeName,
    77  				VolumeSource: corev1.VolumeSource{
    78  					ConfigMap: &corev1.ConfigMapVolumeSource{
    79  						LocalObjectReference: corev1.LocalObjectReference{Name: cmName},
    80  						DefaultMode:          templateSpec.DefaultMode,
    81  					},
    82  				},
    83  			}
    84  		}, func(volume *corev1.Volume) error {
    85  			configMap := volume.ConfigMap
    86  			if configMap == nil {
    87  				return fmt.Errorf("mount volume[%s] requires a ConfigMap: [%+v]", volume.Name, volume)
    88  			}
    89  			configMap.Name = cmName
    90  			return nil
    91  		}); err != nil {
    92  			return err
    93  		}
    94  	}
    95  	podSpec.Volumes = podVolumes
    96  	return nil
    97  }