istio

Форк
0
/
pluginutil.go 
144 строки · 3.6 Кб
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 util
16

17
import (
18
	"context"
19
	"encoding/json"
20
	"fmt"
21
	"os"
22

23
	"github.com/fsnotify/fsnotify"
24

25
	"istio.io/istio/pkg/file"
26
	"istio.io/istio/pkg/log"
27
)
28

29
type Watcher struct {
30
	watcher *fsnotify.Watcher
31
	Events  chan struct{}
32
	Errors  chan error
33
}
34

35
// Waits until a file is modified (returns nil), the context is cancelled (returns context error), or returns error
36
func (w *Watcher) Wait(ctx context.Context) error {
37
	select {
38
	case <-w.Events:
39
		return nil
40
	case err := <-w.Errors:
41
		return err
42
	case <-ctx.Done():
43
		return ctx.Err()
44
	}
45
}
46

47
func (w *Watcher) Close() {
48
	_ = w.watcher.Close()
49
}
50

51
// Creates a file watcher that watches for any changes to the directory
52
func CreateFileWatcher(paths ...string) (*Watcher, error) {
53
	watcher, err := fsnotify.NewWatcher()
54
	if err != nil {
55
		return nil, fmt.Errorf("watcher create: %v", err)
56
	}
57

58
	fileModified, errChan := make(chan struct{}), make(chan error)
59
	go watchFiles(watcher, fileModified, errChan)
60

61
	for _, path := range paths {
62
		if !file.Exists(path) {
63
			log.Infof("file watcher skipping watch on non-existent path: %v", path)
64
			continue
65
		}
66
		if err := watcher.Add(path); err != nil {
67
			if closeErr := watcher.Close(); closeErr != nil {
68
				err = fmt.Errorf("%s: %w", closeErr.Error(), err)
69
			}
70
			return nil, err
71
		}
72
	}
73

74
	return &Watcher{
75
		watcher: watcher,
76
		Events:  fileModified,
77
		Errors:  errChan,
78
	}, nil
79
}
80

81
func watchFiles(watcher *fsnotify.Watcher, fileModified chan struct{}, errChan chan error) {
82
	for {
83
		select {
84
		case event, ok := <-watcher.Events:
85
			if !ok {
86
				return
87
			}
88
			if event.Op&(fsnotify.Create|fsnotify.Write|fsnotify.Remove) != 0 {
89
				log.Infof("file modified: %v", event.Name)
90
				fileModified <- struct{}{}
91
			}
92
		case err, ok := <-watcher.Errors:
93
			if !ok {
94
				return
95
			}
96
			errChan <- err
97
		}
98
	}
99
}
100

101
// Read CNI config from file and return the unmarshalled JSON as a map
102
func ReadCNIConfigMap(path string) (map[string]any, error) {
103
	cniConfig, err := os.ReadFile(path)
104
	if err != nil {
105
		return nil, err
106
	}
107

108
	var cniConfigMap map[string]any
109
	if err = json.Unmarshal(cniConfig, &cniConfigMap); err != nil {
110
		return nil, fmt.Errorf("%s: %w", path, err)
111
	}
112

113
	return cniConfigMap, nil
114
}
115

116
// Given an unmarshalled CNI config JSON map, return the plugin list asserted as a []interface{}
117
func GetPlugins(cniConfigMap map[string]any) (plugins []any, err error) {
118
	plugins, ok := cniConfigMap["plugins"].([]any)
119
	if !ok {
120
		err = fmt.Errorf("error reading plugin list from CNI config")
121
		return
122
	}
123
	return
124
}
125

126
// Given the raw plugin interface, return the plugin asserted as a map[string]interface{}
127
func GetPlugin(rawPlugin any) (plugin map[string]any, err error) {
128
	plugin, ok := rawPlugin.(map[string]any)
129
	if !ok {
130
		err = fmt.Errorf("error reading plugin from CNI config plugin list")
131
		return
132
	}
133
	return
134
}
135

136
// Marshal the CNI config map and append a new line
137
func MarshalCNIConfig(cniConfigMap map[string]any) ([]byte, error) {
138
	cniConfig, err := json.MarshalIndent(cniConfigMap, "", "  ")
139
	if err != nil {
140
		return nil, err
141
	}
142
	cniConfig = append(cniConfig, "\n"...)
143
	return cniConfig, nil
144
}
145

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

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

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

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