0
点赞
收藏
分享

微信扫一扫

kubectl源码分析之set serviceaccount


 欢迎关注我的公众号:

kubectl源码分析之set serviceaccount_ios


————————————————

type SetServiceAccountOptions struct {//set serviceaccount结构体
PrintFlags *genericclioptions.PrintFlags
RecordFlags *genericclioptions.RecordFlags

fileNameOptions resource.FilenameOptions
dryRun bool
shortOutput bool
all bool
output string
local bool
updatePodSpecForObject polymorphichelpers.UpdatePodSpecForObjectFunc
infos []*resource.Info
serviceAccountName string

PrintObj printers.ResourcePrinterFunc
Recorder genericclioptions.Recorder

genericclioptions.IOStreams
}

func NewSetServiceAccountOptions(streams genericclioptions.IOStreams) *SetServiceAccountOptions {
return &SetServiceAccountOptions{//初始化结构体
PrintFlags: genericclioptions.NewPrintFlags("serviceaccount updated").WithTypeSetter(scheme.Scheme),
RecordFlags: genericclioptions.NewRecordFlags(),

Recorder: genericclioptions.NoopRecorder{},

IOStreams: streams,
}
}

//创建set serviceaccount命令
func NewCmdServiceAccount(f cmdutil.Factory, streams genericclioptions.IOStreams) *cobra.Command {
o := NewSetServiceAccountOptions(streams)//初始化结构体

cmd := &cobra.Command{//创建cobra命令
Use: "serviceaccount (-f FILENAME | TYPE NAME) SERVICE_ACCOUNT",
DisableFlagsInUseLine: true,
Aliases: []string{"sa"},
Short: i18n.T("Update ServiceAccount of a resource"),
Long: serviceaccountLong,
Example: serviceaccountExample,
Run: func(cmd *cobra.Command, args []string) {
cmdutil.CheckErr(o.Complete(f, cmd, args))//准备
cmdutil.CheckErr(o.Run())//运行
},
}

o.PrintFlags.AddFlags(cmd)//设置print选项
o.RecordFlags.AddFlags(cmd)//设置record选项

usage := "identifying the resource to get from a server."
cmdutil.AddFilenameOptionFlags(cmd, &o.fileNameOptions, usage)//设置文件选项
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().BoolVar(&o.local, "local", o.local, "If true, set serviceaccount will NOT contact api-server but run locally.")//设置local选项
cmdutil.AddDryRunFlag(cmd)//设置干跑选项
cmdutil.AddIncludeUninitializedFlag(cmd)
return cmd
}

//准备
func (o *SetServiceAccountOptions) Complete(f cmdutil.Factory, cmd *cobra.Command, args []string) error {
var err error

o.RecordFlags.Complete(cmd)//record complete
o.Recorder, err = o.RecordFlags.ToRecorder()//recordflag转recorder
if err != nil {
return err
}

o.shortOutput = cmdutil.GetFlagString(cmd, "output") == "name"//判断output是否为name
o.dryRun = cmdutil.GetDryRunFlag(cmd)//设置干跑
o.output = cmdutil.GetFlagString(cmd, "output")//设置output
o.updatePodSpecForObject = polymorphichelpers.UpdatePodSpecForObjectFn//设置updatePodSpecforObject函数

if o.dryRun {
o.PrintFlags.Complete("%s (dry run)")
}
printer, err := o.PrintFlags.ToPrinter()//printflag转printer
if err != nil {
return err
}
o.PrintObj = printer.PrintObj//设置printObj函数

cmdNamespace, enforceNamespace, err := f.ToRawKubeConfigLoader().Namespace()//获取namespace和enforceNamespace
if err != nil {
return err
}
if len(args) == 0 {//如果参数为空报错
return errors.New("serviceaccount is required")
}
o.serviceAccountName = args[len(args)-1]
resources := args[:len(args)-1]
builder := f.NewBuilder().
WithScheme(scheme.Scheme, scheme.Scheme.PrioritizedVersionsAllGroups()...).
LocalParam(o.local).
ContinueOnError().
NamespaceParam(cmdNamespace).DefaultNamespace().
FilenameParam(enforceNamespace, &o.fileNameOptions).
Flatten()//构造info对象
if !o.local {
builder.ResourceTypeOrNameArgs(o.all, resources...).
Latest()
}
o.infos, err = builder.Do().Infos()//设置info对象
if err != nil {
return err
}
return nil
}

func (o *SetServiceAccountOptions) Run() error {
patchErrs := []error{}
patchFn := func(obj runtime.Object) ([]byte, error) {//创建patch,修改海曙
_, err := o.updatePodSpecForObject(obj, func(podSpec *v1.PodSpec) error {//更新pod spec
podSpec.ServiceAccountName = o.serviceAccountName//更新serviceaccountName
return nil
})
if err != nil {
return nil, err
}
// record this change (for rollout history)
if err := o.Recorder.Record(obj); err != nil {//判断是否创建change-cause注解
klog.V(4).Infof("error recording current command: %v", err)
}

return runtime.Encode(scheme.DefaultJSONEncoder(), obj)//对象转json
}

patches := CalculatePatches(o.infos, scheme.DefaultJSONEncoder(), patchFn)//计算patch
for _, patch := range patches {//遍历patch
info := patch.Info
name := info.ObjectName()
if patch.Err != nil {//patch有错误则继续
patchErrs = append(patchErrs, fmt.Errorf("error: %s %v\n", name, patch.Err))
continue
}
if o.local || o.dryRun {//local或干跑则打印对象,继续
if err := o.PrintObj(info.Object, o.Out); err != nil {
patchErrs = append(patchErrs, err)
}
continue
}
actual, err := resource.NewHelper(info.Client, info.Mapping).Patch(info.Namespace, info.Name, types.StrategicMergePatchType, patch.Patch, nil)//应用patch到服务端
if err != nil {
patchErrs = append(patchErrs, fmt.Errorf("failed to patch ServiceAccountName %v", err))
continue
}

if err := o.PrintObj(actual, o.Out); err != nil {//打印结果
patchErrs = append(patchErrs, err)
}
}
return utilerrors.NewAggregate(patchErrs)
}

举报

相关推荐

0 条评论