Info
什么是Info
之前我们说过,Visitor可以生成Info或处理Info。那么到底什么是Info呢?Info定义在/pkg/kubectl/resource/visitor.go中,与Visitor定义在一个文件中。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26
| type Info struct { Client RESTClient Mapping *meta.RESTMapping Namespace string Name string Source string VersionedObject interface{} runtime.Object ResourceVersion string Export bool }
|
可以看出,Info包含了REST请求需要的信息及REST的返回结果runtime.Object。
Visit()
由于Info也实现了Visit(),所以Info也可以称得上是一个Visitor。Info的Visit()方法比较简单,仅仅调用VisitorFunc,参数为自身及nil。
1 2 3
| func (i *Info) Visit(fn VisitorFunc) error { return fn(i, nil) }
|
Get()
Get()调用Helper依据Info中的信息获取obj,并更新到Info的Object字段。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
| func (i *Info) Get() (err error) { obj, err := NewHelper(i.Client, i.Mapping).Get(i.Namespace, i.Name, i.Export) if err != nil { if errors.IsNotFound(err) && len(i.Namespace) > 0 && i.Namespace != api.NamespaceDefault && i.Namespace != api.NamespaceAll { err2 := i.Client.Get().AbsPath("api", "v1", "namespaces", i.Namespace).Do().Error() if err2 != nil && errors.IsNotFound(err2) { return err2 } } return err } i.Object = obj i.ResourceVersion, _ = i.Mapping.MetadataAccessor.ResourceVersion(obj) return nil }
|
Refresh()
Refresh()把已经存在的obj更新到Info的Object。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29
| func (i *Info) Refresh(obj runtime.Object, ignoreError bool) error { name, err := i.Mapping.MetadataAccessor.Name(obj) if err != nil { if !ignoreError { return err } } else { i.Name = name } namespace, err := i.Mapping.MetadataAccessor.Namespace(obj) if err != nil { if !ignoreError { return err } } else { i.Namespace = namespace } version, err := i.Mapping.MetadataAccessor.ResourceVersion(obj) if err != nil { if !ignoreError { return err } } else { i.ResourceVersion = version } i.Object = obj return nil }
|
Result
什么是Result
之前我们提过,Builder的Do()可以返回Result。现在让我们来看看Result的定义,Result定义在/pkg/kubectl/resource/result.go中:
1 2 3 4 5 6 7 8 9 10 11 12 13
| type Result struct { err error visitor Visitor sources []Visitor singular bool ignoreErrors []utilerrors.Matcher info []*Info }
|
可以看到,Result也包含一个visitor,及一个info表示[]*Info,所以Result提供了Infos()方法来获取Visitor的结果Info数组及Object()方法来获取Visitor的结果Obj(可能为List)。
Infos()
Info()调用层层封装的visitor,然后收集所有info并返回。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22
| func (r *Result) Infos() ([]*Info, error) { if r.err != nil { return nil, r.err } if r.info != nil { return r.info, nil } infos := []*Info{} err := r.visitor.Visit(func(info *Info, err error) error { if err != nil { return err } infos = append(infos, info) return nil }) err = utilerrors.FilterOut(err, r.ignoreErrors...) r.info, r.err = infos, err return infos, err }
|
Object()
Object()先调用Infos()来获取infos,然后从每个info中提取出Object组成ObjectList返回。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36
| func (r *Result) Object() (runtime.Object, error) { infos, err := r.Infos() if err != nil { return nil, err } versions := sets.String{} objects := []runtime.Object{} for _, info := range infos { if info.Object != nil { objects = append(objects, info.Object) versions.Insert(info.ResourceVersion) } } if len(objects) == 1 { if r.singular { return objects[0], nil } if meta.IsListType(objects[0]) { return objects[0], nil } } version := "" if len(versions) == 1 { version = versions.List()[0] } return &api.List{ ListMeta: unversioned.ListMeta{ ResourceVersion: version, }, Items: objects, }, err }
|
Helper
什么是Helper
在Kubernetes中,Helper一般都提供类似驱动的功能。Kubectl的helper就是用来访问Client的驱动。一般来说,某个visitFunc函数中会调用Helper的相关成员函数来完成具体请求。
Helper定义在/pkg/kubectl/resource/helper.go中:
1 2 3 4 5 6 7 8 9 10 11 12 13
| type Helper struct { Resource string RESTClient RESTClient Versioner runtime.ResourceVersioner NamespaceScoped bool }
|
Helper实现了Get(), List(), Watch(), WatchSingle(), Delete(), Create(), Patch(), Replace()等方法,这些方法是对RESTClient的封装,所以待以后分析了RESTClient之后,这些方法的实现就很容易明白,这里就不展开了。