github.com/alibaba/sealer@v0.8.6-0.20220430115802-37a2bdaa8173/build/buildimage/utils.go (about) 1 // Copyright © 2021 Alibaba Group Holding Ltd. 2 // 3 // Licensed under the Apache License, Version 2.0 (the "License"); 4 // you may not use this file except in compliance with the License. 5 // You may obtain a copy of the License at 6 // 7 // http://www.apache.org/licenses/LICENSE-2.0 8 // 9 // Unless required by applicable law or agreed to in writing, software 10 // distributed under the License is distributed on an "AS IS" BASIS, 11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 // See the License for the specific language governing permissions and 13 // limitations under the License. 14 15 package buildimage 16 17 import ( 18 "fmt" 19 "io/fs" 20 "path/filepath" 21 "strings" 22 23 "github.com/alibaba/sealer/build/buildinstruction" 24 "github.com/alibaba/sealer/common" 25 "github.com/alibaba/sealer/logger" 26 v1 "github.com/alibaba/sealer/types/api/v1" 27 v2 "github.com/alibaba/sealer/types/api/v2" 28 "github.com/alibaba/sealer/utils" 29 "github.com/alibaba/sealer/utils/mount" 30 "helm.sh/helm/v3/pkg/chartutil" 31 32 "github.com/alibaba/sealer/pkg/parser" 33 "sigs.k8s.io/yaml" 34 ) 35 36 // initImageSpec init default Image metadata 37 func initImageSpec(kubefile string) (*v1.Image, error) { 38 kubeFile, err := utils.ReadAll(kubefile) 39 if err != nil { 40 return nil, fmt.Errorf("failed to load kubefile: %v", err) 41 } 42 43 rawImage, err := parser.NewParse().Parse(kubeFile) 44 if err != nil { 45 return nil, err 46 } 47 48 layer0 := rawImage.Spec.Layers[0] 49 if layer0.Type != common.FROMCOMMAND { 50 return nil, fmt.Errorf("first line of kubefile must start with %s", common.FROMCOMMAND) 51 } 52 53 return rawImage, nil 54 } 55 56 func setClusterFileToImage(cluster *v2.Cluster, image *v1.Image) error { 57 clusterData, err := yaml.Marshal(cluster) 58 if err != nil { 59 return err 60 } 61 62 if image.Annotations == nil { 63 image.Annotations = make(map[string]string) 64 } 65 image.Annotations[common.ImageAnnotationForClusterfile] = string(clusterData) 66 return nil 67 } 68 69 func getKubeVersion(rootfs string) string { 70 chartsPath := filepath.Join(rootfs, "charts") 71 if !utils.IsExist(chartsPath) { 72 return "" 73 } 74 return readCharts(chartsPath) 75 } 76 77 func readCharts(chartsPath string) string { 78 var kv string 79 err := filepath.Walk(chartsPath, func(path string, f fs.FileInfo, err error) error { 80 if kv != "" { 81 return nil 82 } 83 if f.IsDir() || f.Name() != "Chart.yaml" { 84 return nil 85 } 86 meta, walkErr := chartutil.LoadChartfile(path) 87 if walkErr != nil { 88 return walkErr 89 } 90 if meta.KubeVersion != "" { 91 kv = meta.KubeVersion 92 } 93 return nil 94 }) 95 96 if err != nil { 97 return "" 98 } 99 return kv 100 } 101 102 func FormatImages(images []string) (res []string) { 103 for _, ima := range utils.RemoveDuplicate(images) { 104 if ima == "" { 105 continue 106 } 107 if strings.HasPrefix(ima, "#") { 108 continue 109 } 110 res = append(res, trimQuotes(strings.TrimSpace(ima))) 111 } 112 return 113 } 114 115 func trimQuotes(s string) string { 116 if len(s) >= 2 { 117 if c := s[len(s)-1]; s[0] == c && (c == '"' || c == '\'') { 118 return s[1 : len(s)-1] 119 } 120 } 121 return s 122 } 123 124 // GetLayerMountInfo to get rootfs mount info.if not mounted will mount it via base layers. 125 //1, already mount: runtime docker registry mount info,just get related mount info. 126 //2, already mount: if exec build cmd failed and return ,need to collect related old mount info 127 //3, new mount: just mount and return related info. 128 func GetLayerMountInfo(baseLayers []v1.Layer) (mount.Service, error) { 129 var filterArgs = "tmp" 130 mountInfos := mount.GetBuildMountInfo(filterArgs) 131 lowerLayers := buildinstruction.GetBaseLayersPath(baseLayers) 132 for _, info := range mountInfos { 133 // if info.Lowers equal lowerLayers,means image already mounted. 134 if strings.Join(lowerLayers, ":") == strings.Join(info.Lowers, ":") { 135 logger.Info("get mount dir :%s success ", info.Target) 136 //nolint 137 return mount.NewMountService(info.Target, info.Upper, info.Lowers) 138 } 139 } 140 141 return mountRootfs(lowerLayers) 142 } 143 144 func mountRootfs(res []string) (mount.Service, error) { 145 mounter, err := mount.NewMountService("", "", res) 146 if err != nil { 147 return nil, err 148 } 149 150 err = mounter.TempMount() 151 if err != nil { 152 return nil, err 153 } 154 return mounter, nil 155 }