k8s1.11命令行——实现源码导读之kubectl patch更新资源对象
这一讲我们来看kubectl patch更新资源对象命令,它的实现在NewCmdPatch方法中获取PatchOptions中保存的命令行输入的kubectl patch 后面跟的参数(如--all-namespace,--output,--patch等)构建cmd patch命令,注册patch命令的实现方法给patch命令添加相应的参数来控制patch命令的操作func New...
·
这一讲我们来看kubectl patch更新资源对象命令,它的实现在NewCmdPatch方法中
- 获取PatchOptions中保存的命令行输入的kubectl patch 后面跟的参数(如--all-namespace,--output,--patch等)
- 构建cmd patch命令,注册patch命令的实现方法
- 给patch命令添加相应的参数来控制patch命令的操作
func NewCmdPatch(f cmdutil.Factory, ioStreams genericclioptions.IOStreams) *cobra.Command {
o := NewPatchOptions(ioStreams)
// 构建cmd patch命令
cmd := &cobra.Command{
Use: "patch (-f FILENAME | TYPE NAME) -p PATCH",
DisableFlagsInUseLine: true,
Short: i18n.T("Update field(s) of a resource using strategic merge patch"),
Long: patchLong,
Example: patchExample,
// 代码实际运行部分
Run: func(cmd *cobra.Command, args []string) {
cmdutil.CheckErr(o.Complete(f, cmd, args))
cmdutil.CheckErr(o.Validate())
// patch请求的具体实现方法
cmdutil.CheckErr(o.RunPatch())
},
}
o.RecordFlags.AddFlags(cmd)
o.PrintFlags.AddFlags(cmd)
// 参数flag提供修饰符来控制动作命令的操作,即给命令添加参数,这些参数都保存在PatchOptions中
cmd.Flags().StringVarP(&o.Patch, "patch", "p", "", "The patch to be applied to the resource JSON file.")
cmd.MarkFlagRequired("patch")
cmd.Flags().StringVar(&o.PatchType, "type", "strategic", fmt.Sprintf("The type of patch being provided; one of %v", sets.StringKeySet(patchTypes).List()))
cmdutil.AddDryRunFlag(cmd)
cmdutil.AddFilenameOptionFlags(cmd, &o.FilenameOptions, "identifying the resource to update")
cmd.Flags().BoolVar(&o.Local, "local", o.Local, "If true, patch will operate on the content of the file, not the server-side resource.")
return cmd
}
下面来看Patch命令具体的实现函数RunPatch,RunPatch函数首先从命令行中读取输入的patch类型和patchBytes补丁内容,然后同get命令一样构建Builder-Visitor资源对象访问机制,代码实现如下:
//获取patch的类型
patchType := types.StrategicMergePatchType
if len(o.PatchType) != 0 {
patchType = patchTypes[strings.ToLower(o.PatchType)]
}
//获取patchBytes补丁内容
patchBytes, err := yaml.ToJSON([]byte(o.Patch))
if err != nil {
return fmt.Errorf("unable to parse %q: %v", o.Patch, err)
}
//构建Builder,Visitor
r := o.builder.
Unstructured().
ContinueOnError().
NamespaceParam(o.namespace).DefaultNamespace().
FilenameParam(o.enforceNamespace, &o.FilenameOptions).
ResourceTypeOrNameArgs(false, o.args...).
Flatten().
Do()
err = r.Err()
if err != nil {
return err
}
其中,Builder-Visitor已经在上一讲做过详细介绍,有兴趣可以移步k8s1.11命令行——实现源码导读之kubectl get获取资源对象。
通过上述步骤,我们构建了访问要patch的资源对象的访问器(Visitor),通过回调函数Visit要获取资源并执行patch请求,整个过程如下:
- 获取资源对象的名字,命名空间以及映射器mapping
- 由资源映射器mapping和客户端client构建helper(Helper提供了检索或改变RESTful资源的方法)
- 调用helper的Patch方法通过向apiServer发送patch请求更新资源对象并返回
- 检查源对象info.Object和更新后的对象patchedObj是否一致
- 如果记录Recorder进行了更改,计算和创建另外一个patch(Recorder在注释中记录了runtime.Object更改的原因)
- 使用更新后的对象patchedObj更新源对象info.Object
- 打印输出
代码实现如下:
helper.go中的Patch方法:
func (m *Helper) Patch(namespace, name string, pt types.PatchType, data []byte) (runtime.Object, error) {
return m.RESTClient.Patch(pt).
NamespaceIfScoped(namespace, m.NamespaceScoped).
Resource(m.Resource).
Name(name).
Body(data).
Do().
Get()
}
更多推荐
已为社区贡献4条内容
所有评论(0)