istio

Форк
0
/
renderer.go 
182 строки · 5.0 Кб
1
// Copyright Istio Authors
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 helm
16

17
import (
18
	"fmt"
19
	"io/fs"
20
	"os"
21
	"path/filepath"
22
	"strings"
23

24
	"helm.sh/helm/v3/pkg/chart"
25
	"helm.sh/helm/v3/pkg/chart/loader"
26
	"k8s.io/apimachinery/pkg/version"
27

28
	"istio.io/istio/manifests"
29
	"istio.io/istio/operator/pkg/util"
30
)
31

32
const (
33
	// DefaultProfileFilename is the name of the default profile yaml file.
34
	DefaultProfileFilename = "default.yaml"
35
	ChartsSubdirName       = "charts"
36
	profilesRoot           = "profiles"
37
)
38

39
// Renderer is a helm template renderer for a fs.FS.
40
type Renderer struct {
41
	namespace     string
42
	componentName string
43
	chart         *chart.Chart
44
	started       bool
45
	files         fs.FS
46
	dir           string
47
	// Kubernetes cluster version
48
	version *version.Info
49
}
50

51
// NewFileTemplateRenderer creates a TemplateRenderer with the given parameters and returns a pointer to it.
52
// helmChartDirPath must be an absolute file path to the root of the helm charts.
53
func NewGenericRenderer(files fs.FS, dir, componentName, namespace string, version *version.Info) *Renderer {
54
	return &Renderer{
55
		namespace:     namespace,
56
		componentName: componentName,
57
		dir:           dir,
58
		files:         files,
59
		version:       version,
60
	}
61
}
62

63
// Run implements the TemplateRenderer interface.
64
func (h *Renderer) Run() error {
65
	if err := h.loadChart(); err != nil {
66
		return err
67
	}
68

69
	h.started = true
70
	return nil
71
}
72

73
// RenderManifest renders the current helm templates with the current values and returns the resulting YAML manifest string.
74
func (h *Renderer) RenderManifest(values string) (string, error) {
75
	if !h.started {
76
		return "", fmt.Errorf("fileTemplateRenderer for %s not started in renderChart", h.componentName)
77
	}
78
	return renderChart(h.namespace, values, h.chart, nil, h.version)
79
}
80

81
// RenderManifestFiltered filters templates to render using the supplied filter function.
82
func (h *Renderer) RenderManifestFiltered(values string, filter TemplateFilterFunc) (string, error) {
83
	if !h.started {
84
		return "", fmt.Errorf("fileTemplateRenderer for %s not started in renderChart", h.componentName)
85
	}
86
	return renderChart(h.namespace, values, h.chart, filter, h.version)
87
}
88

89
func GetFilesRecursive(f fs.FS, root string) ([]string, error) {
90
	res := []string{}
91
	err := fs.WalkDir(f, root, func(path string, d fs.DirEntry, err error) error {
92
		if err != nil {
93
			return err
94
		}
95
		if d.IsDir() {
96
			return nil
97
		}
98
		res = append(res, path)
99
		return nil
100
	})
101
	return res, err
102
}
103

104
// loadChart implements the TemplateRenderer interface.
105
func (h *Renderer) loadChart() error {
106
	fnames, err := GetFilesRecursive(h.files, h.dir)
107
	if err != nil {
108
		if os.IsNotExist(err) {
109
			return fmt.Errorf("component %q does not exist", h.componentName)
110
		}
111
		return fmt.Errorf("list files: %v", err)
112
	}
113
	var bfs []*loader.BufferedFile
114
	for _, fname := range fnames {
115
		b, err := fs.ReadFile(h.files, fname)
116
		if err != nil {
117
			return fmt.Errorf("read file: %v", err)
118
		}
119
		// Helm expects unix / separator, but on windows this will be \
120
		name := strings.ReplaceAll(stripPrefix(fname, h.dir), string(filepath.Separator), "/")
121
		bf := &loader.BufferedFile{
122
			Name: name,
123
			Data: b,
124
		}
125
		bfs = append(bfs, bf)
126
		scope.Debugf("Chart loaded: %s", bf.Name)
127
	}
128

129
	h.chart, err = loader.LoadFiles(bfs)
130
	if err != nil {
131
		return fmt.Errorf("load files: %v", err)
132
	}
133
	return nil
134
}
135

136
func builtinProfileToFilename(name string) string {
137
	if name == "" {
138
		return DefaultProfileFilename
139
	}
140
	return name + ".yaml"
141
}
142

143
func LoadValues(profileName string, chartsDir string) (string, error) {
144
	path := strings.Join([]string{profilesRoot, builtinProfileToFilename(profileName)}, "/")
145
	by, err := fs.ReadFile(manifests.BuiltinOrDir(chartsDir), path)
146
	if err != nil {
147
		return "", err
148
	}
149
	return string(by), nil
150
}
151

152
func readProfiles(chartsDir string) (map[string]bool, error) {
153
	profiles := map[string]bool{}
154
	f := manifests.BuiltinOrDir(chartsDir)
155
	dir, err := fs.ReadDir(f, profilesRoot)
156
	if err != nil {
157
		return nil, err
158
	}
159
	for _, f := range dir {
160
		trimmedString := strings.TrimSuffix(f.Name(), ".yaml")
161
		if f.Name() != trimmedString {
162
			profiles[trimmedString] = true
163
		}
164
	}
165
	return profiles, nil
166
}
167

168
// stripPrefix removes the given prefix from prefix.
169
func stripPrefix(path, prefix string) string {
170
	pl := len(strings.Split(prefix, "/"))
171
	pv := strings.Split(path, "/")
172
	return strings.Join(pv[pl:], "/")
173
}
174

175
// list all the profiles.
176
func ListProfiles(charts string) ([]string, error) {
177
	profiles, err := readProfiles(charts)
178
	if err != nil {
179
		return nil, err
180
	}
181
	return util.StringBoolMapToSlice(profiles), nil
182
}
183

Использование cookies

Мы используем файлы cookie в соответствии с Политикой конфиденциальности и Политикой использования cookies.

Нажимая кнопку «Принимаю», Вы даете АО «СберТех» согласие на обработку Ваших персональных данных в целях совершенствования нашего веб-сайта и Сервиса GitVerse, а также повышения удобства их использования.

Запретить использование cookies Вы можете самостоятельно в настройках Вашего браузера.