欢迎关注我的公众号:
目前刚开始写一个月,一共写了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完全手册
————————————————
type AnnotateOptions struct {//annotate结构体
PrintFlags *genericclioptions.PrintFlags
PrintObj printers.ResourcePrinterFunc
// Filename options
resource.FilenameOptions
RecordFlags *genericclioptions.RecordFlags
// Common user flags
overwrite bool
local bool
dryrun bool
all bool
resourceVersion string
selector string
fieldSelector string
outputFormat string
// results of arg parsing
resources []string
newAnnotations map[string]string
removeAnnotations []string
Recorder genericclioptions.Recorder
namespace string
enforceNamespace bool
builder *resource.Builder
unstructuredClientForMapping func(mapping *meta.RESTMapping) (resource.RESTClient, error)
genericclioptions.IOStreams
}
func NewAnnotateOptions(ioStreams genericclioptions.IOStreams) *AnnotateOptions {
return &AnnotateOptions{//初始化结构体
PrintFlags: genericclioptions.NewPrintFlags("annotated").WithTypeSetter(scheme.Scheme),
RecordFlags: genericclioptions.NewRecordFlags(),
Recorder: genericclioptions.NoopRecorder{},
IOStreams: ioStreams,
}
}
//创建annotate命令
func NewCmdAnnotate(parent string, f cmdutil.Factory, ioStreams genericclioptions.IOStreams) *cobra.Command {
o := NewAnnotateOptions(ioStreams)// 初始化结构体
cmd := &cobra.Command{//创建cobra命令
Use: "annotate [--overwrite] (-f FILENAME | TYPE NAME) KEY_1=VAL_1 ... KEY_N=VAL_N [--resource-version=version]",
DisableFlagsInUseLine: true,
Short: i18n.T("Update the annotations on a resource"),
Long: annotateLong + "\n\n" + cmdutil.SuggestAPIResources(parent),
Example: annotateExample,
Run: func(cmd *cobra.Command, args []string) {
cmdutil.CheckErr(o.Complete(f, cmd, args))//准备
cmdutil.CheckErr(o.Validate())//校验
cmdutil.CheckErr(o.RunAnnotate())//运行
},
}
// bind flag structs
o.RecordFlags.AddFlags(cmd)//record选项
o.PrintFlags.AddFlags(cmd)//打印选项
cmdutil.AddIncludeUninitializedFlag(cmd)
cmd.Flags().BoolVar(&o.overwrite, "overwrite", o.overwrite, "If true, allow annotations to be overwritten, otherwise reject annotation updates that overwrite existing annotations.")//overwrite选项
cmd.Flags().BoolVar(&o.local, "local", o.local, "If true, annotation will NOT contact api-server but run locally.")//local选项
cmd.Flags().StringVarP(&o.selector, "selector", "l", o.selector, "Selector (label query) to filter on, not including uninitialized ones, supports '=', '==', and '!='.(e.g. -l key1=value1,key2=value2).")//selector选项
cmd.Flags().StringVar(&o.fieldSelector, "field-selector", o.fieldSelector, "Selector (field query) to filter on, supports '=', '==', and '!='.(e.g. --field-selector key1=value1,key2=value2). The server only supports a limited number of field queries per type.")//field-selector选项
cmd.Flags().BoolVar(&o.all, "all", o.all, "Select all resources, including uninitialized ones, in the namespace of the specified resource types.")//all选项
cmd.Flags().StringVar(&o.resourceVersion, "resource-version", o.resourceVersion, i18n.T("If non-empty, the annotation update will only succeed if this is the current resource-version for the object. Only valid when specifying a single resource."))//resource-version选项
usage := "identifying the resource to update the annotation"
cmdutil.AddFilenameOptionFlags(cmd, &o.FilenameOptions, usage)//文件选项
cmdutil.AddDryRunFlag(cmd)//干跑选项
return cmd
}
//准备方法
func (o *AnnotateOptions) Complete(f cmdutil.Factory, cmd *cobra.Command, args []string) error {
var err error
o.RecordFlags.Complete(cmd)//recordflag complete
o.Recorder, err = o.RecordFlags.ToRecorder()//recordflag转recorder
if err != nil {
return err
}
o.outputFormat = cmdutil.GetFlagString(cmd, "output")//设置输出格式
o.dryrun = cmdutil.GetDryRunFlag(cmd)//设置干跑
if o.dryrun {//如果是干跑,complete干跑
o.PrintFlags.Complete("%s (dry run)")
}
printer, err := o.PrintFlags.ToPrinter()//printflag转printer
if err != nil {
return err
}
o.PrintObj = func(obj runtime.Object, out io.Writer) error {//设置printObj函数
return printer.PrintObj(obj, out)
}
o.namespace, o.enforceNamespace, err = f.ToRawKubeConfigLoader().Namespace()//设置namespace和enforceNamespace
if err != nil {
return err
}
o.builder = f.NewBuilder()//设置builder
o.unstructuredClientForMapping = f.UnstructuredClientForMapping//设置unstructuredClientForMapping
// retrieves resource and annotation args from args
// also checks args to verify that all resources are specified before annotations
resources, annotationArgs, err := cmdutil.GetResourcesAndPairs(args, "annotation")//从参数里获取resources和注解参数
if err != nil {
return err
}
o.resources = resources
o.newAnnotations, o.removeAnnotations, err = parseAnnotations(annotationArgs)//解析注解参数
if err != nil {
return err
}
return nil
}
//校验
func (o AnnotateOptions) Validate() error {
if o.all && len(o.selector) > 0 {//all和selector不能同时指定
return fmt.Errorf("cannot set --all and --selector at the same time")
}
if o.all && len(o.fieldSelector) > 0 {//all和field-selector不能同时指定
return fmt.Errorf("cannot set --all and --field-selector at the same time")
}
if len(o.resources) < 1 && cmdutil.IsFilenameSliceEmpty(o.Filenames, o.Kustomize) {//文件和资源至少有一个
return fmt.Errorf("one or more resources must be specified as <resource> <name> or <resource>/<name>")
}
if len(o.newAnnotations) < 1 && len(o.removeAnnotations) < 1 {//添加注解和删除注解不能同时为空
return fmt.Errorf("at least one annotation update is required")
}
return validateAnnotations(o.removeAnnotations, o.newAnnotations)//校验注解
}
func validateAnnotations(removeAnnotations []string, newAnnotations map[string]string) error {//校验朱恩杰
var modifyRemoveBuf bytes.Buffer
for _, removeAnnotation := range removeAnnotations {//遍历要删除的注解
if _, found := newAnnotations[removeAnnotation]; found {//如果要添加的注解里有要删除的注解
if modifyRemoveBuf.Len() > 0 {
modifyRemoveBuf.WriteString(", ")
}
modifyRemoveBuf.WriteString(fmt.Sprintf(removeAnnotation))//modifyRemoveBuf添加要删除的注解
}
}
if modifyRemoveBuf.Len() > 0 {//modifyRemoveBuf不为空,报错
return fmt.Errorf("can not both modify and remove the following annotation(s) in the same command: %s", modifyRemoveBuf.String())
}
return nil
}
//运行
func (o AnnotateOptions) RunAnnotate() error {
b := o.builder.
Unstructured().
LocalParam(o.local).
ContinueOnError().
NamespaceParam(o.namespace).DefaultNamespace().
FilenameParam(o.enforceNamespace, &o.FilenameOptions).
Flatten()
if !o.local {
b = b.LabelSelectorParam(o.selector).
FieldSelectorParam(o.fieldSelector).
ResourceTypeOrNameArgs(o.all, o.resources...).
Latest()
}
r := b.Do()//用builder构造result对象
if err := r.Err(); err != nil {
return err
}
var singleItemImpliedResource bool
r.IntoSingleItemImplied(&singleItemImpliedResource)
// only apply resource version locking on a single resource.
// we must perform this check after o.builder.Do() as
// []o.resources can not accurately return the proper number
// of resources when they are not passed in "resource/name" format.
if !singleItemImpliedResource && len(o.resourceVersion) > 0 {//如果不是单对象,并且制定了resource-version报错
return fmt.Errorf("--resource-version may only be used with a single resource")
}
return r.Visit(func(info *resource.Info, err error) error {// visit result
if err != nil {
return err
}
var outputObj runtime.Object
obj := info.Object//获取info的Object
if o.dryrun || o.local {//如果是干跑或local
if err := o.updateAnnotations(obj); err != nil {//更新注解
return err
}
outputObj = obj//设置输出对象为obj
} else {
name, namespace := info.Name, info.Namespace//获取名称和名称空间
oldData, err := json.Marshal(obj)//把obj转json
if err != nil {
return err
}
if err := o.Recorder.Record(info.Object); err != nil {//判断是否创建change-cause注解
klog.V(4).Infof("error recording current command: %v", err)
}
if err := o.updateAnnotations(obj); err != nil {//更新注解
return err
}
newData, err := json.Marshal(obj)// 把更新后的对象转json
if err != nil {
return err
}
patchBytes, err := jsonpatch.CreateMergePatch(oldData, newData)//比较json创建patch
createdPatch := err == nil
if err != nil {
klog.V(2).Infof("couldn't compute patch: %v", err)
}
mapping := info.ResourceMapping()//获取mapping
client, err := o.unstructuredClientForMapping(mapping)// 获取client
if err != nil {
return err
}
helper := resource.NewHelper(client, mapping)//通过client和mapping构造helper
if createdPatch {//应用patch到服务端
outputObj, err = helper.Patch(namespace, name, types.MergePatchType, patchBytes, nil)
} else {//replacepatch到服务端
outputObj, err = helper.Replace(namespace, name, false, obj)
}
if err != nil {
return err
}
}
return o.PrintObj(outputObj, o.Out)//打印对象
})
}
//校验注解是否已经存在
func validateNoAnnotationOverwrites(accessor metav1.Object, annotations map[string]string) error {
var buf bytes.Buffer
for key := range annotations {//遍历注解
// change-cause annotation can always be overwritten
if key == polymorphichelpers.ChangeCauseAnnotation {//如果是change-cause注解则跳过
continue
}
if value, found := accessor.GetAnnotations()[key]; found {//判断注解是否存在
if buf.Len() > 0 {
buf.WriteString("; ")
}
buf.WriteString(fmt.Sprintf("'%s' already has a value (%s)", key, value))//往buf里写数据
}
}
if buf.Len() > 0 {//如果buf非空,返回错误
return fmt.Errorf("--overwrite is false but found the following declared annotation(s): %s", buf.String())
}
return nil
}
// updateAnnotations updates annotations of obj
func (o AnnotateOptions) updateAnnotations(obj runtime.Object) error {//更新注解
accessor, err := meta.Accessor(obj)//访问对象
if err != nil {
return err
}
if !o.overwrite {//如果没有指定overwrite,校验注解是否已经存在
if err := validateNoAnnotationOverwrites(accessor, o.newAnnotations); err != nil {
return err
}
}
annotations := accessor.GetAnnotations()//获取annotations
if annotations == nil {
annotations = make(map[string]string)
}
for key, value := range o.newAnnotations {//把要添加的注解加到annotations map里面
annotations[key] = value
}
for _, annotation := range o.removeAnnotations {//遍历要删除的注解
delete(annotations, annotation)//annotation map里删除注解
}
accessor.SetAnnotations(annotations)// 设置annotations
if len(o.resourceVersion) != 0 {//如果指定了resource-version设置resource-version
accessor.SetResourceVersion(o.resourceVersion)
}
return nil
}