kubectl源码分析之set selector
欢迎关注我的公众号:
目前刚开始写一个月,一共写了18篇原创文章,文章目录如下:
istio多集群探秘,部署了50次多集群后我得出的结论
istio多集群链路追踪,附实操视频
istio防故障利器,你知道几个,istio新手不要读,太难!
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完全手册
加qq交流群,请联系:
——————————————————————————————————————————————-
type SetSelectorOptions struct {//set selector结构体
// Bound
ResourceBuilderFlags *genericclioptions.ResourceBuilderFlags
PrintFlags *genericclioptions.PrintFlags
RecordFlags *genericclioptions.RecordFlags
dryrun bool
// set by args
resources []string
selector *metav1.LabelSelector
// computed
WriteToServer bool
PrintObj printers.ResourcePrinterFunc
Recorder genericclioptions.Recorder
ResourceFinder genericclioptions.ResourceFinder
// set at initialization
genericclioptions.IOStreams
}
func NewSelectorOptions(streams genericclioptions.IOStreams) *SetSelectorOptions {
return &SetSelectorOptions{//初始化结构体
ResourceBuilderFlags: genericclioptions.NewResourceBuilderFlags().
WithScheme(scheme.Scheme).
WithAll(false).
WithLocal(false).
WithLatest(),
PrintFlags: genericclioptions.NewPrintFlags("selector updated").WithTypeSetter(scheme.Scheme),
RecordFlags: genericclioptions.NewRecordFlags(),
Recorder: genericclioptions.NoopRecorder{},
IOStreams: streams,
}
}
//创建set selector命令
func NewCmdSelector(f cmdutil.Factory, streams genericclioptions.IOStreams) *cobra.Command {
o := NewSelectorOptions(streams)//初始化结构体
cmd := &cobra.Command{//创建cobra命令
Use: "selector (-f FILENAME | TYPE NAME) EXPRESSIONS [--resource-version=version]",
DisableFlagsInUseLine: true,
Short: i18n.T("Set the selector on a resource"),
Long: fmt.Sprintf(selectorLong, validation.LabelValueMaxLength),
Example: selectorExample,
Run: func(cmd *cobra.Command, args []string) {
cmdutil.CheckErr(o.Complete(f, cmd, args))//准备
cmdutil.CheckErr(o.Validate())//校验
cmdutil.CheckErr(o.RunSelector())//运行
},
}
o.ResourceBuilderFlags.AddFlags(cmd.Flags())//构造资源flag
o.PrintFlags.AddFlags(cmd)//设置打印flag
o.RecordFlags.AddFlags(cmd)//设置record选项
cmd.Flags().String("resource-version", "", "If non-empty, the selectors update will only succeed if this is the current resource-version for the object. Only valid when specifying a single resource.")//设置resource version选项
cmdutil.AddDryRunFlag(cmd)//设置干跑选项
return cmd
}
//准备函数
func (o *SetSelectorOptions) Complete(f cmdutil.Factory, cmd *cobra.Command, args []string) error {
var err error
o.RecordFlags.Complete(cmd)//record flag complete
o.Recorder, err = o.RecordFlags.ToRecorder()//record flag转recorder
if err != nil {
return err
}
o.dryrun = cmdutil.GetDryRunFlag(cmd)//设置干跑
o.resources, o.selector, err = getResourcesAndSelector(args)//设置resource和selector
if err != nil {
return err
}
o.ResourceFinder = o.ResourceBuilderFlags.ToBuilder(f, o.resources)//设置resorucebuilder
o.WriteToServer = !(*o.ResourceBuilderFlags.Local || o.dryrun)//判断是否写到服务器
if o.dryrun {
o.PrintFlags.Complete("%s (dry run)")
}
printer, err := o.PrintFlags.ToPrinter()//打印选项转printer
if err != nil {
return err
}
o.PrintObj = printer.PrintObj//设置printObj函数
return err
}
func (o *SetSelectorOptions) Validate() error {
if o.selector == nil {//selector不能为空
return fmt.Errorf("one selector is required")
}
return nil
}
//运行
func (o *SetSelectorOptions) RunSelector() error {
r := o.ResourceFinder.Do()//从builder获取result
return r.Visit(func(info *resource.Info, err error) error {//访问result
patch := &Patch{Info: info}//构造patch
CalculatePatch(patch, scheme.DefaultJSONEncoder(), func(obj runtime.Object) ([]byte, error) {//计算patch
selectErr := updateSelectorForObject(info.Object, *o.selector)//更新对象selector
if selectErr != nil {
return nil, selectErr
}
// record this change (for rollout history)
if err := o.Recorder.Record(patch.Info.Object); err != nil {//判断是否更新change-cause注解
klog.V(4).Infof("error recording current command: %v", err)
}
return runtime.Encode(scheme.DefaultJSONEncoder(), info.Object)//obj转json
})
if patch.Err != nil {
return patch.Err
}
if !o.WriteToServer {//如果不写到服务器则打印
return o.PrintObj(info.Object, o.Out)
}
actual, err := resource.NewHelper(info.Client, info.Mapping).Patch(info.Namespace, info.Name, types.StrategicMergePatchType, patch.Patch, nil)//应用patch到服务器
if err != nil {
return err
}
return o.PrintObj(actual, o.Out)//打印对象
})
}
//更新对象selector
func updateSelectorForObject(obj runtime.Object, selector metav1.LabelSelector) error {
copyOldSelector := func() (map[string]string, error) {//获取selector
if len(selector.MatchExpressions) > 0 {//不支持matchExpression
return nil, fmt.Errorf("match expression %v not supported on this object", selector.MatchExpressions)
}
dst := make(map[string]string)
for label, value := range selector.MatchLabels {//遍历matchLabels
dst[label] = value//设置labels map
}
return dst, nil//返回labels map
}
var err error
switch t := obj.(type) {//判断对象
case *v1.Service://如果是service
t.Spec.Selector, err = copyOldSelector()//设置selector
default:
err = fmt.Errorf("setting a selector is only supported for Services")
}
return err
}
还没有评论,来说两句吧...