欢迎关注我的公众号:
目前刚开始写一个月,一共写了18篇原创文章,文章目录如下:
istio防故障利器,你知道几个,istio新手不要读,太难!
不懂envoyfilter也敢说精通istio系列-http-rbac-不要只会用AuthorizationPolicy配置权限
不懂envoyfilter也敢说精通istio系列-02-http-corsFilter-不要只会vs
不懂envoyfilter也敢说精通istio系列-03-http-csrf filter-再也不用再代码里写csrf逻辑了
不懂envoyfilter也敢说精通istio系列http-jwt_authn-不要只会RequestAuthorization
不懂envoyfilter也敢说精通istio系列-05-fault-filter-故障注入不止是vs
不懂envoyfilter也敢说精通istio系列-06-http-match-配置路由不只是vs
不懂envoyfilter也敢说精通istio系列-07-负载均衡配置不止是dr
不懂envoyfilter也敢说精通istio系列-08-连接池和断路器
不懂envoyfilter也敢说精通istio系列-09-http-route filter
不懂envoyfilter也敢说精通istio系列-network filter-redis proxy
不懂envoyfilter也敢说精通istio系列-network filter-HttpConnectionManager
不懂envoyfilter也敢说精通istio系列-ratelimit-istio ratelimit完全手册
———————————————
//创建plugin命令
func NewCmdPlugin(f cmdutil.Factory, streams genericclioptions.IOStreams) *cobra.Command {
cmd := &cobra.Command{//创建cobra命令
Use: "plugin [flags]",
DisableFlagsInUseLine: true,
Short: i18n.T("Provides utilities for interacting with plugins."),
Long: pluginLong,
Run: func(cmd *cobra.Command, args []string) {
cmdutil.DefaultSubCommandRun(streams.ErrOut)(cmd, args)
},
}
cmd.AddCommand(NewCmdPluginList(f, streams))//添加list子命令
return cmd
}
type PluginListOptions struct {//plugin list结构体
Verifier PathVerifier
NameOnly bool
PluginPaths []string
genericclioptions.IOStreams
}
//创建plugin list命令
func NewCmdPluginList(f cmdutil.Factory, streams genericclioptions.IOStreams) *cobra.Command {
o := &PluginListOptions{//初始化结构体
IOStreams: streams,
}
cmd := &cobra.Command{//创建cobra命令
Use: "list",
Short: "list all visible plugin executables on a user's PATH",
Long: pluginListLong,
Run: func(cmd *cobra.Command, args []string) {
cmdutil.CheckErr(o.Complete(cmd))//准备
cmdutil.CheckErr(o.Run())//运行
},
}
cmd.Flags().BoolVar(&o.NameOnly, "name-only", o.NameOnly, "If true, display only the binary name of each plugin, rather than its full path")//name-only选项
return cmd
}
//准备
func (o *PluginListOptions) Complete(cmd *cobra.Command) error {
o.Verifier = &CommandOverrideVerifier{//创建verifier
root: cmd.Root(),
seenPlugins: make(map[string]string, 0),
}
o.PluginPaths = filepath.SplitList(os.Getenv("PATH"))//设置path
return nil
}
//运行
func (o *PluginListOptions) Run() error {
pluginsFound := false
isFirstFile := true
pluginErrors := []error{}
pluginWarnings := 0
for _, dir := range uniquePathsList(o.PluginPaths) {//遍历path
files, err := ioutil.ReadDir(dir)//读取目录
if err != nil {
if _, ok := err.(*os.PathError); ok {
fmt.Fprintf(o.ErrOut, "Unable read directory %q from your PATH: %v. Skipping...", dir, err)
continue
}
pluginErrors = append(pluginErrors, fmt.Errorf("error: unable to read directory %q in your PATH: %v", dir, err))
continue
}
for _, f := range files {//遍历files
if f.IsDir() {//如果是目录,跳过
continue
}
if !hasValidPrefix(f.Name(), ValidPluginFilenamePrefixes) {//判断文件名称是否有有效前缀,没有跳过
continue
}
if isFirstFile {//如果是第一次,打印一句话
fmt.Fprintf(o.ErrOut, "The following compatible plugins are available:\n\n")
pluginsFound = true
isFirstFile = false
}
pluginPath := f.Name()//获取plugin名称
if !o.NameOnly {//如果非仅名称,dir+plugin名称
pluginPath = filepath.Join(dir, pluginPath)
}
fmt.Fprintf(o.Out, "%s\n", pluginPath)//打印plugin路径
if errs := o.Verifier.Verify(filepath.Join(dir, f.Name())); len(errs) != 0 {//验证plugin是否有效
for _, err := range errs {
fmt.Fprintf(o.ErrOut, " - %s\n", err)
pluginWarnings++
}
}
}
}
if !pluginsFound {//没找到,append错误
pluginErrors = append(pluginErrors, fmt.Errorf("error: unable to find any kubectl plugins in your PATH"))
}
if pluginWarnings > 0 {
if pluginWarnings == 1 {
pluginErrors = append(pluginErrors, fmt.Errorf("error: one plugin warning was found"))
} else {
pluginErrors = append(pluginErrors, fmt.Errorf("error: %v plugin warnings were found", pluginWarnings))
}
}
if len(pluginErrors) > 0 {
fmt.Fprintln(o.ErrOut)
errs := bytes.NewBuffer(nil)
for _, e := range pluginErrors {
fmt.Fprintln(errs, e)
}
return fmt.Errorf("%s", errs.String())
}
return nil
}
//验证是否有效
func (v *CommandOverrideVerifier) Verify(path string) []error {
if v.root == nil {//root不能为nil
return []error{fmt.Errorf("unable to verify path with nil root")}
}
// extract the plugin binary name
segs := strings.Split(path, "/")//用/分割
binName := segs[len(segs)-1]//获取基名
cmdPath := strings.Split(binName, "-")//用-分割
if len(cmdPath) > 1 {
// the first argument is always "kubectl" for a plugin binary
cmdPath = cmdPath[1:]//获取命令名称
}
errors := []error{}
if isExec, err := isExecutable(path); err == nil && !isExec {//判断是否可执行
errors = append(errors, fmt.Errorf("warning: %s identified as a kubectl plugin, but it is not executable", path))
} else if err != nil {
errors = append(errors, fmt.Errorf("error: unable to identify %s as an executable file: %v", path, err))
}
if existingPath, ok := v.seenPlugins[binName]; ok {//判断是否和其他的冲突
errors = append(errors, fmt.Errorf("warning: %s is overshadowed by a similarly named plugin: %s", path, existingPath))
} else {
v.seenPlugins[binName] = path
}
if cmd, _, err := v.root.Find(cmdPath); err == nil {//命令中找找,判断是否冲突
errors = append(errors, fmt.Errorf("warning: %s overwrites existing command: %q", binName, cmd.CommandPath()))
}
return errors
}
//判断是否可执行
func isExecutable(fullPath string) (bool, error) {
info, err := os.Stat(fullPath)
if err != nil {
return false, err
}
if runtime.GOOS == "windows" {//如果是windows系统判断后缀是否可执行
fileExt := strings.ToLower(filepath.Ext(fullPath))
switch fileExt {
case ".bat", ".cmd", ".com", ".exe", ".ps1":
return true, nil
}
return false, nil
}
if m := info.Mode(); !m.IsDir() && m&0111 != 0 {//linux系统判断是否有执行权限
return true, nil
}
return false, nil
}