// Visitor lets clients walk a list of resources.type Visitor interface{Visit(VisitorFunc)error}// VisitorFunc implements the Visitor interface for a matching function.// If there was a problem walking a list of resources, the incoming error// will describe the problem and the function can decide how to handle that error.// A nil returned indicates to accept an error to continue loops even when errors happen.// This is useful for ignoring certain kinds of errors or aggregating errors in some way.type VisitorFunc func(*Info,error)error
// Visit in a FileVisitor is just taking care of opening/closing filesfunc(v *FileVisitor)Visit(fn VisitorFunc)error{var f *os.File
if v.Path == constSTDINstr {
f = os.Stdin
}else{var err error
f, err = os.Open(v.Path)if err !=nil{return err
}defer f.Close()}// TODO: Consider adding a flag to force to UTF16, apparently some// Windows tools don't write the BOM
utf16bom := unicode.BOMOverride(unicode.UTF8.NewDecoder())
v.StreamVisitor.Reader = transform.NewReader(f, utf16bom)return v.StreamVisitor.Visit(fn)}
func(o *FilenameOptions)validate()[]error{var errs []erroriflen(o.Filenames)>0&&len(o.Kustomize)>0{
errs =append(errs, fmt.Errorf("only one of -f or -k can be specified"))}iflen(o.Kustomize)>0&& o.Recursive {
errs =append(errs, fmt.Errorf("the -k flag can't be used with -f or -R"))}return errs
}
-k代表使用 Kustomize配置
如果 -f -k都存在报错 only one of -f or -k can be specified
kubectl create -f rule.yaml -k rule.yaml
error: only one of -f or -k can be specified
-k不支持递归 -R
kubectl create -k rule.yaml -R
error: the -k flag can't be used with -f or -R
调用path解析文件
recursive := filenameOptions.Recursive
paths := filenameOptions.Filenames
for_, s :=range paths {switch{case s =="-":
b.Stdin()case strings.Index(s,"http://")==0|| strings.Index(s,"https://")==0:
url, err := url.Parse(s)if err !=nil{
b.errs =append(b.errs, fmt.Errorf("the URL passed to filename %q is not valid: %v", s, err))continue}
b.URL(defaultHttpGetAttempts, url)default:if!recursive {
b.singleItemImplied =true}
b.Path(recursive, s)}}
func(v *StreamVisitor)Visit(fn VisitorFunc)error{
d := yaml.NewYAMLOrJSONDecoder(v.Reader,4096)for{
ext := runtime.RawExtension{}if err := d.Decode(&ext); err !=nil{if err == io.EOF {returnnil}return fmt.Errorf("error parsing %s: %v", v.Source, err)}// TODO: This needs to be able to handle object in other encodings and schemas.
ext.Raw = bytes.TrimSpace(ext.Raw)iflen(ext.Raw)==0|| bytes.Equal(ext.Raw,[]byte("null")){continue}if err :=ValidateSchema(ext.Raw, v.Schema); err !=nil{return fmt.Errorf("error validating %q: %v", v.Source, err)}
info, err := v.infoForData(ext.Raw, v.Source)if err !=nil{if fnErr :=fn(info, err); fnErr !=nil{return fnErr
}continue}if err :=fn(info,nil); err !=nil{return err
}}}
用jsonYamlDecoder解析文件
ValidateSchema会解析文件中的字段进行校验,比如我们把spec故意写成aspec
kubectl apply -f rule.yaml
error: error validating "rule.yaml": error validating data: [ValidationError(PrometheusRule): unknown field "aspec"in com.coreos.monitoring.v1.PrometheusRule, ValidationError(PrometheusRule): missing required field "spec"in com.coreos.monitoring.v1.PrometheusRule];if you choose to ignore these errors, turn validation off with --validate=false
// Object interface must be supported by all API types registered with Scheme. Since objects in a scheme are// expected to be serialized to the wire, the interface an Object must provide to the Scheme allows// serializers to set the kind, version, and group the object is represented as. An Object may choose// to return a no-op ObjectKindAccessor in cases where it is not expected to be serialized.type Object interface{GetObjectKind() schema.ObjectKind
DeepCopyObject() Object
}
作用
Kubernetes 对象 是持久化的实体
Kubernetes 使用这些实体去表示整个集群的状态。特别地,它们描述了如下信息:
哪些容器化应用在运行(以及在哪些节点上)
可以被应用使用的资源
关于应用运行时表现的策略,比如重启策略、升级策略,以及容错策略
操作 Kubernetes 对象,无论是创建、修改,或者删除, 需要使用 Kubernetes API
funcRequireNamespace(namespace string) VisitorFunc {returnfunc(info *Info, err error)error{if err !=nil{return err
}if!info.Namespaced(){returnnil}iflen(info.Namespace)==0{
info.Namespace = namespace
UpdateObjectNamespace(info,nil)returnnil}if info.Namespace != namespace {return fmt.Errorf("the namespace from the provided object %q does not match the namespace %q. You must pass '--namespace=%s' to perform this operation.", info.Namespace, namespace, info.Namespace)}returnnil}}
创建带装饰器的visitor DecoratedVisitor
if b.continueOnError {
r.visitor =NewDecoratedVisitor(ContinueOnErrorVisitor{r.visitor}, helpers...)}else{
r.visitor =NewDecoratedVisitor(r.visitor, helpers...)}