github.com/1aal/kubeblocks@v0.0.0-20231107070852-e1c03e598921/pkg/controller/configuration/tool_image_builder.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 configuration 21 22 import ( 23 corev1 "k8s.io/api/core/v1" 24 25 appsv1alpha1 "github.com/1aal/kubeblocks/apis/apps/v1alpha1" 26 cfgcm "github.com/1aal/kubeblocks/pkg/configuration/config_manager" 27 "github.com/1aal/kubeblocks/pkg/constant" 28 "github.com/1aal/kubeblocks/pkg/controller/component" 29 "github.com/1aal/kubeblocks/pkg/controller/factory" 30 intctrlutil "github.com/1aal/kubeblocks/pkg/controllerutil" 31 viper "github.com/1aal/kubeblocks/pkg/viperx" 32 ) 33 34 const ( 35 toolsVolumeName = "kb-tools" 36 initSecRenderedToolContainerName = "init-secondary-rendered-tool" 37 38 tplRenderToolPath = "/bin/config_render" 39 ) 40 41 func buildConfigToolsContainer(cfgManagerParams *cfgcm.CfgManagerBuildParams, podSpec *corev1.PodSpec, comp *component.SynthesizedComponent) error { 42 if len(cfgManagerParams.ConfigSpecsBuildParams) == 0 { 43 return nil 44 } 45 46 // construct config manager tools volume 47 toolContainers := make([]appsv1alpha1.ToolConfig, 0) 48 toolsMap := make(map[string]cfgcm.ConfigSpecMeta) 49 for _, buildParam := range cfgManagerParams.ConfigSpecsBuildParams { 50 if buildParam.ToolsImageSpec == nil { 51 continue 52 } 53 for _, toolConfig := range buildParam.ToolsImageSpec.ToolConfigs { 54 if _, ok := toolsMap[toolConfig.Name]; !ok { 55 replaceToolsImageHolder(&toolConfig, podSpec, buildParam.ConfigSpec.VolumeName) 56 toolContainers = append(toolContainers, toolConfig) 57 toolsMap[toolConfig.Name] = buildParam 58 } 59 } 60 buildToolsVolumeMount(cfgManagerParams, podSpec, buildParam.ConfigSpec.VolumeName, buildParam.ToolsImageSpec.MountPoint) 61 } 62 63 // Ensure that the order in which iniContainers are generated does not change 64 toolContainers = checkAndInstallToolsImageVolume(toolContainers, cfgManagerParams.ConfigSpecsBuildParams) 65 if len(toolContainers) == 0 { 66 return nil 67 } 68 69 containers, err := factory.BuildCfgManagerToolsContainer(cfgManagerParams, comp, toolContainers, toolsMap) 70 if err == nil { 71 cfgManagerParams.ToolsContainers = containers 72 } 73 return err 74 } 75 76 func checkAndInstallToolsImageVolume(toolContainers []appsv1alpha1.ToolConfig, buildParams []cfgcm.ConfigSpecMeta) []appsv1alpha1.ToolConfig { 77 for _, buildParam := range buildParams { 78 if buildParam.ToolsImageSpec != nil && buildParam.ConfigSpec.LegacyRenderedConfigSpec != nil { 79 // auto install config_render tool 80 toolContainers = checkAndCreateRenderedInitContainer(toolContainers, buildParam.ToolsImageSpec.MountPoint) 81 } 82 } 83 return toolContainers 84 } 85 86 func checkAndCreateRenderedInitContainer(toolContainers []appsv1alpha1.ToolConfig, mountPoint string) []appsv1alpha1.ToolConfig { 87 kbToolsImage := viper.GetString(constant.KBToolsImage) 88 for _, container := range toolContainers { 89 if container.Name == initSecRenderedToolContainerName { 90 return nil 91 } 92 } 93 toolContainers = append(toolContainers, appsv1alpha1.ToolConfig{ 94 Name: initSecRenderedToolContainerName, 95 Image: kbToolsImage, 96 Command: []string{"cp", tplRenderToolPath, mountPoint}, 97 }) 98 return toolContainers 99 } 100 101 func replaceToolsImageHolder(toolConfig *appsv1alpha1.ToolConfig, podSpec *corev1.PodSpec, volumeName string) { 102 switch { 103 case toolConfig.Image == constant.KBToolsImagePlaceHolder: 104 toolConfig.Image = viper.GetString(constant.KBToolsImage) 105 case toolConfig.Image == "": 106 usingContainers := intctrlutil.GetPodContainerWithVolumeMount(podSpec, volumeName) 107 if len(usingContainers) != 0 { 108 toolConfig.Image = usingContainers[0].Image 109 } 110 } 111 } 112 113 func buildToolsVolumeMount(cfgManagerParams *cfgcm.CfgManagerBuildParams, podSpec *corev1.PodSpec, volumeName string, mountPoint string) { 114 if cfgcm.FindVolumeMount(cfgManagerParams.Volumes, toolsVolumeName) != nil { 115 return 116 } 117 cfgManagerParams.ScriptVolume = append(cfgManagerParams.ScriptVolume, corev1.Volume{ 118 Name: toolsVolumeName, 119 VolumeSource: corev1.VolumeSource{ 120 EmptyDir: &corev1.EmptyDirVolumeSource{}, 121 }, 122 }) 123 124 n := len(cfgManagerParams.Volumes) 125 cfgManagerParams.Volumes = append(cfgManagerParams.Volumes, corev1.VolumeMount{ 126 Name: toolsVolumeName, 127 MountPath: mountPoint, 128 }) 129 130 usingContainers := intctrlutil.GetPodContainerWithVolumeMount(podSpec, volumeName) 131 for _, container := range usingContainers { 132 container.VolumeMounts = append(container.VolumeMounts, cfgManagerParams.Volumes[n]) 133 } 134 }