接着是一系列的判定操作,根据当前这个storage是否有实现对应接口来判定能否提供对应服务,如 创建操作。这个结果会影响后面是否添加对应操作请求的路由
creater, isCreater := storage.(rest.Creater)然后就创建对应请求的Options,如CreateOptions。这个用于在后面创建路由时作为参数,平时使用client-go时也要传入metav1包的CreateOption,ListOption,DeleteOption等,就是这个参数了。
versionedCreateOptions, err := a.group.Creater.New(optionsExternalVersion.WithKind("CreateOptions")) if err != nil { return nil, err }下一步按照资源类型是cluster scope还是namespace scope来将支持的操作类型组成action集合,这个action集合的动作则是对应http的请求方法,如创建的
actions = appendIf(actions, action{"POST", resourcePath, resourceParams, namer, false}, isCreater)往后就是遍历action集合,为各个操作绑定路由,将其添加到路由集合中,如创建的
case "POST": // Create a resource. var handler restful.RouteFunction if isNamedCreater { handler = restfulCreateNamedResource(namedCreater, reqScope, admit) } else { handler = restfulCreateResource(creater, reqScope, admit) } handler = metrics.InstrumentRouteFunc(action.Verb, group, version, resource, subresource, requestScope, metrics.APIServerComponent, deprecated, removedRelease, handler) if enableWarningHeaders { handler = utilwarning.AddWarningsHandler(handler, warnings) } article := GetArticleForNoun(kind, " ") doc := "create" + article + kind if isSubresource { doc = "create " + subresource + " of" + article + kind } route := ws.POST(action.Path).To(handler). Doc(doc). Param(ws.QueryParameter("pretty", "If 'true', then the output is pretty printed.")). Operation("create"+namespaced+kind+strings.Title(subresource)+operationSuffix). Produces(append(storageMeta.ProducesMIMETypes(action.Verb), mediaTypes...)...). Returns(http.StatusOK, "OK", producedObject). // TODO: in some cases, the API may return a v1.Status instead of the versioned object // but currently go-restful can't handle multiple different objects being returned. Returns(http.StatusCreated, "Created", producedObject). Returns(http.StatusAccepted, "Accepted", producedObject). Reads(defaultVersionedObject). Writes(producedObject) if err := AddObjectParams(ws, route, versionedCreateOptions); err != nil { return nil, err } addParams(route, action.Params) routes = append(routes, route)最后才把这些路由添加到webservice中
for kubeVerb := range kubeVerbs { apiResource.Verbs = append(apiResource.Verbs, kubeVerb) }回头看创建POST路由时,同样按照资源是否命名空间级别的创建赌赢的handler,后面则是go-restful创建路由的代码
pod是属于命名空间级别的资源,进入restfulCreateNamedResource函数,经过三层调用到达createHandler函数,调用链如下
restfulCreateNamedResource->handlers.CreateNamedResource->createHandlercreateHandler大概逻辑如下
从请求中获取资源的namespace,name,GVK等信息
从RequestScope中获取资源的反序列化器,将body的数据反序列化为runtimeObject
执行mutating准入控制器
调用storage的create,同时传入Validate准入控制器,准备持久化到Etcd
将处理结果写到响应
代码位于/vendor/k8s.io/apiserver/pkg/endpoints/handlers/create.go
func createHandler(r rest.NamedCreater, scope *RequestScope, admit admission.Interface, includeName bool) http.HandlerFunc { return func(w http.ResponseWriter, req *http.Request) { timeout := parseTimeout(req.URL.Query().Get("timeout")) //从请求中获取资源的namespace,name,GVK等信息 namespace, name, err := scope.Namer.Name(req) gv := scope.Kind.GroupVersion() //从RequestScope中获取资源的反序列化器,将body的数据反序列化为runtimeObject decoder := scope.Serializer.DecoderToVersion(s.Serializer, scope.HubGroupVersion) body, err := limitedReadBody(req, scope.MaxRequestBodyBytes) obj, gvk, err := decoder.Decode(body, &defaultGVK, original) //调用storage的create,同时传入Validate准入控制器,准备持久化到Etcd requestFunc := func() (runtime.Object, error) { return r.Create( ctx, name, obj, rest.AdmissionToValidateObjectFunc(admit, admissionAttributes, scope), options, ) } result, err := finishRequest(timeout, func() (runtime.Object, error) { if scope.FieldManager != nil { liveObj, err := scope.Creater.New(scope.Kind) if err != nil { return nil, fmt.Errorf("failed to create new object (Create for %v): %v", scope.Kind, err) } obj = scope.FieldManager.UpdateNoErrors(liveObj, obj, managerOrUserAgent(options.FieldManager, req.UserAgent())) } //执行mutating准入控制器 if mutatingAdmission, ok := admit.(admission.MutationInterface); ok && mutatingAdmission.Handles(admission.Create) { if err := mutatingAdmission.Admit(ctx, admissionAttributes, scope); err != nil { return nil, err } } result, err := requestFunc() // If the object wasn't committed to storage because it's serialized size was too large, // it is safe to remove managedFields (which can be large) and try again. if isTooLargeError(err) { if accessor, accessorErr := meta.Accessor(obj); accessorErr == nil { accessor.SetManagedFields(nil) result, err = requestFunc() } } return result, err }) //将处理结果写到响应 //如果创建成功的结果按照请求来源时的格式序列化,写到响应体里面 transformResponseObject(ctx, scope, trace, req, w, code, outputMediaType, result) } }由此段代码可得,Mutate 准入控制器要比Validate 准入控制器先执行
继续追r.Create方法调用,r.Create==>namedCreaterAdapter.Create-->c.Creater.Create