Пример #1
0
func init() {
	kubeTestAPI := os.Getenv("KUBE_TEST_API")
	if kubeTestAPI != "" {
		testGroupVersions := strings.Split(kubeTestAPI, ",")
		for _, gvString := range testGroupVersions {
			groupVersion := unversioned.ParseGroupVersionOrDie(gvString)

			Groups[groupVersion.Group] = TestGroup{
				externalGroupVersion: groupVersion,
				internalGroupVersion: unversioned.GroupVersion{Group: groupVersion.Group},
			}
		}
	}

	if _, ok := Groups[api.SchemeGroupVersion.Group]; !ok {
		Groups[api.SchemeGroupVersion.Group] = TestGroup{
			externalGroupVersion: unversioned.GroupVersion{Group: api.SchemeGroupVersion.Group, Version: latest.GroupOrDie(api.SchemeGroupVersion.Group).GroupVersion.Version},
			internalGroupVersion: api.SchemeGroupVersion,
		}
	}
	if _, ok := Groups[extensions.SchemeGroupVersion.Group]; !ok {
		Groups[extensions.SchemeGroupVersion.Group] = TestGroup{
			externalGroupVersion: unversioned.GroupVersion{Group: extensions.SchemeGroupVersion.Group, Version: latest.GroupOrDie(extensions.SchemeGroupVersion.Group).GroupVersion.Version},
			internalGroupVersion: extensions.SchemeGroupVersion,
		}
	}

	Default = Groups[api.SchemeGroupVersion.Group]
	Extensions = Groups[extensions.SchemeGroupVersion.Group]
}
Пример #2
0
func (m *Master) thirdpartyapi(group, kind, version string) *apiserver.APIGroupVersion {
	resourceStorage := thirdpartyresourcedataetcd.NewREST(m.thirdPartyStorage, generic.UndecoratedStorage, group, kind)

	apiRoot := makeThirdPartyPath("")

	storage := map[string]rest.Storage{
		strings.ToLower(kind) + "s": resourceStorage,
	}

	serverGroupVersion := unversioned.ParseGroupVersionOrDie(latest.GroupOrDie("").GroupVersion)

	return &apiserver.APIGroupVersion{
		Root:                apiRoot,
		GroupVersion:        unversioned.GroupVersion{Group: group, Version: version},
		RequestInfoResolver: m.newRequestInfoResolver(),

		Creater:   thirdpartyresourcedata.NewObjectCreator(group, version, api.Scheme),
		Convertor: api.Scheme,
		Typer:     api.Scheme,

		Mapper:             thirdpartyresourcedata.NewMapper(latest.GroupOrDie("extensions").RESTMapper, kind, version, group),
		Codec:              thirdpartyresourcedata.NewCodec(latest.GroupOrDie("extensions").Codec, kind),
		Linker:             latest.GroupOrDie("extensions").SelfLinker,
		Storage:            storage,
		ServerGroupVersion: &serverGroupVersion,

		Context: m.requestContextMapper,

		MinRequestTimeout: m.minRequestTimeout,
	}
}
Пример #3
0
func main() {
	runtime.GOMAXPROCS(runtime.NumCPU())
	flag.Parse()

	var funcOut io.Writer
	if *functionDest == "-" {
		funcOut = os.Stdout
	} else {
		file, err := os.Create(*functionDest)
		if err != nil {
			glog.Fatalf("Couldn't open %v: %v", *functionDest, err)
		}
		defer file.Close()
		funcOut = file
	}

	data := new(bytes.Buffer)

	gv := unversioned.ParseGroupVersionOrDie(*groupVersion)

	_, err := data.WriteString(fmt.Sprintf("package %v\n", gv.Version))
	if err != nil {
		glog.Fatalf("Error while writing package line: %v", err)
	}

	versionPath := pkgPath(gv.Group, gv.Version)
	generator := kruntime.NewConversionGenerator(api.Scheme.Raw(), versionPath)
	apiShort := generator.AddImport(path.Join(pkgBase, "api"))
	generator.AddImport(path.Join(pkgBase, "api/resource"))
	// TODO(wojtek-t): Change the overwrites to a flag.
	generator.OverwritePackage(gv.Version, "")
	for _, knownType := range api.Scheme.KnownTypes(gv) {
		if knownType.PkgPath() != versionPath {
			continue
		}
		if err := generator.GenerateConversionsForType(gv, knownType); err != nil {
			glog.Errorf("Error while generating conversion functions for %v: %v", knownType, err)
		}
	}
	generator.RepackImports(sets.NewString())
	if err := generator.WriteImports(data); err != nil {
		glog.Fatalf("Error while writing imports: %v", err)
	}
	if err := generator.WriteConversionFunctions(data); err != nil {
		glog.Fatalf("Error while writing conversion functions: %v", err)
	}
	if err := generator.RegisterConversionFunctions(data, fmt.Sprintf("%s.Scheme", apiShort)); err != nil {
		glog.Fatalf("Error while writing conversion functions: %v", err)
	}

	b, err := imports.Process("", data.Bytes(), nil)
	if err != nil {
		glog.Fatalf("Error while update imports: %v", err)
	}
	if _, err := funcOut.Write(b); err != nil {
		glog.Fatalf("Error while writing out the resulting file: %v", err)
	}
}
Пример #4
0
func (m *DefaultRESTMapper) Add(scope RESTScope, kind string, gvString string, mixedCase bool) {
	gv := unversioned.ParseGroupVersionOrDie(gvString)

	plural, singular := KindToResource(kind, mixedCase)
	m.plurals[singular] = plural
	m.singulars[plural] = singular
	meta := typeMeta{APIVersion: gv.String(), Kind: kind}
	_, ok1 := m.mapping[plural]
	_, ok2 := m.mapping[strings.ToLower(plural)]
	if !ok1 && !ok2 {
		m.mapping[plural] = meta
		m.mapping[singular] = meta
		if strings.ToLower(plural) != plural {
			m.mapping[strings.ToLower(plural)] = meta
			m.mapping[strings.ToLower(singular)] = meta
		}
	}
	m.reverse[meta] = plural
	m.scopes[meta] = scope
}
Пример #5
0
// NewDefaultRESTMapper initializes a mapping between Kind and APIVersion
// to a resource name and back based on the objects in a runtime.Scheme
// and the Kubernetes API conventions. Takes a group name, a priority list of the versions
// to search when an object has no default version (set empty to return an error),
// and a function that retrieves the correct codec and metadata for a given version.
// TODO remove group when this API is fixed.  It is no longer used.
// The external API for a RESTMapper is cross-version and this is currently called using
// group/version tuples.  In the end, the structure may be easier to understand with
// a GroupRESTMapper and CrossGroupRESTMapper, but for now, this one is constructed and
// used a CrossGroupRESTMapper.
func NewDefaultRESTMapper(group string, gvStrings []string, f VersionInterfacesFunc) *DefaultRESTMapper {
	mapping := make(map[string]typeMeta)
	reverse := make(map[typeMeta]string)
	scopes := make(map[typeMeta]RESTScope)
	plurals := make(map[string]string)
	singulars := make(map[string]string)
	// TODO: verify name mappings work correctly when versions differ

	gvs := []unversioned.GroupVersion{}
	for _, gvString := range gvStrings {
		gvs = append(gvs, unversioned.ParseGroupVersionOrDie(gvString))
	}

	return &DefaultRESTMapper{
		mapping:        mapping,
		reverse:        reverse,
		scopes:         scopes,
		groupVersions:  gvs,
		plurals:        plurals,
		singulars:      singulars,
		interfacesFunc: f,
	}
}
Пример #6
0
// UpdateResource returns a function that will handle a resource update
func UpdateResource(r rest.Updater, scope RequestScope, typer runtime.ObjectTyper, admit admission.Interface) restful.RouteFunction {
	return func(req *restful.Request, res *restful.Response) {
		w := res.ResponseWriter

		// TODO: we either want to remove timeout or document it (if we document, move timeout out of this function and declare it in api_installer)
		timeout := parseTimeout(req.Request.URL.Query().Get("timeout"))

		namespace, name, err := scope.Namer.Name(req)
		if err != nil {
			errorJSON(err, scope.Codec, w)
			return
		}
		ctx := scope.ContextFunc(req)
		ctx = api.WithNamespace(ctx, namespace)

		body, err := readBody(req.Request)
		if err != nil {
			errorJSON(err, scope.Codec, w)
			return
		}

		obj := r.New()
		if err := scope.Codec.DecodeIntoWithSpecifiedVersionKind(body, obj, unversioned.ParseGroupVersionOrDie(scope.APIVersion).WithKind(scope.Kind)); err != nil {
			err = transformDecodeError(typer, err, obj, body)
			errorJSON(err, scope.Codec, w)
			return
		}

		if err := checkName(obj, name, namespace, scope.Namer); err != nil {
			errorJSON(err, scope.Codec, w)
			return
		}

		if admit != nil && admit.Handles(admission.Update) {
			userInfo, _ := api.UserFrom(ctx)

			err = admit.Admit(admission.NewAttributesRecord(obj, scope.Kind, namespace, name, scope.Resource, scope.Subresource, admission.Update, userInfo))
			if err != nil {
				errorJSON(err, scope.Codec, w)
				return
			}
		}

		wasCreated := false
		result, err := finishRequest(timeout, func() (runtime.Object, error) {
			obj, created, err := r.Update(ctx, obj)
			wasCreated = created
			return obj, err
		})
		if err != nil {
			errorJSON(err, scope.Codec, w)
			return
		}

		if err := setSelfLink(result, req, scope.Namer); err != nil {
			errorJSON(err, scope.Codec, w)
			return
		}

		status := http.StatusOK
		if wasCreated {
			status = http.StatusCreated
		}
		writeJSON(status, scope.Codec, result, w, isPrettyPrint(req.Request))
	}
}
Пример #7
0
func createHandler(r rest.NamedCreater, scope RequestScope, typer runtime.ObjectTyper, admit admission.Interface, includeName bool) restful.RouteFunction {
	return func(req *restful.Request, res *restful.Response) {
		w := res.ResponseWriter

		// TODO: we either want to remove timeout or document it (if we document, move timeout out of this function and declare it in api_installer)
		timeout := parseTimeout(req.Request.URL.Query().Get("timeout"))

		var (
			namespace, name string
			err             error
		)
		if includeName {
			namespace, name, err = scope.Namer.Name(req)
		} else {
			namespace, err = scope.Namer.Namespace(req)
		}
		if err != nil {
			errorJSON(err, scope.Codec, w)
			return
		}

		ctx := scope.ContextFunc(req)
		ctx = api.WithNamespace(ctx, namespace)

		body, err := readBody(req.Request)
		if err != nil {
			errorJSON(err, scope.Codec, w)
			return
		}

		obj := r.New()
		// TODO this cleans up with proper typing
		if err := scope.Codec.DecodeIntoWithSpecifiedVersionKind(body, obj, unversioned.ParseGroupVersionOrDie(scope.APIVersion).WithKind(scope.Kind)); err != nil {
			err = transformDecodeError(typer, err, obj, body)
			errorJSON(err, scope.Codec, w)
			return
		}

		if admit != nil && admit.Handles(admission.Create) {
			userInfo, _ := api.UserFrom(ctx)

			err = admit.Admit(admission.NewAttributesRecord(obj, scope.Kind, namespace, name, scope.Resource, scope.Subresource, admission.Create, userInfo))
			if err != nil {
				errorJSON(err, scope.Codec, w)
				return
			}
		}

		result, err := finishRequest(timeout, func() (runtime.Object, error) {
			out, err := r.Create(ctx, name, obj)
			if status, ok := out.(*unversioned.Status); ok && err == nil && status.Code == 0 {
				status.Code = http.StatusCreated
			}
			return out, err
		})
		if err != nil {
			errorJSON(err, scope.Codec, w)
			return
		}

		if err := setSelfLink(result, req, scope.Namer); err != nil {
			errorJSON(err, scope.Codec, w)
			return
		}

		write(http.StatusCreated, scope.APIVersion, scope.Codec, result, w, req.Request)
	}
}
Пример #8
0
// experimental returns the resources and codec for the experimental api
func (m *Master) experimental(c *Config) *apiserver.APIGroupVersion {
	// All resources except these are disabled by default.
	enabledResources := sets.NewString("jobs", "horizontalpodautoscalers", "ingresses")
	resourceOverrides := m.apiGroupVersionOverrides["extensions/v1beta1"].ResourceOverrides
	isEnabled := func(resource string) bool {
		// Check if the resource has been overriden.
		enabled, ok := resourceOverrides[resource]
		if !ok {
			return enabledResources.Has(resource)
		}
		return enabled
	}
	storageDecorator := c.storageDecorator()
	dbClient := func(resource string) storage.Interface {
		return c.StorageDestinations.get("extensions", resource)
	}

	storage := map[string]rest.Storage{}
	if isEnabled("horizontalpodautoscalers") {
		autoscalerStorage, autoscalerStatusStorage := horizontalpodautoscaleretcd.NewREST(dbClient("horizontalpodautoscalers"), storageDecorator)
		storage["horizontalpodautoscalers"] = autoscalerStorage
		storage["horizontalpodautoscalers/status"] = autoscalerStatusStorage
		controllerStorage := expcontrolleretcd.NewStorage(c.StorageDestinations.get("", "replicationControllers"), storageDecorator)
		storage["replicationcontrollers"] = controllerStorage.ReplicationController
		storage["replicationcontrollers/scale"] = controllerStorage.Scale
	}
	if isEnabled("thirdpartyresources") {
		thirdPartyResourceStorage := thirdpartyresourceetcd.NewREST(dbClient("thirdpartyresources"), storageDecorator)
		thirdPartyControl := ThirdPartyController{
			master: m,
			thirdPartyResourceRegistry: thirdPartyResourceStorage,
		}
		go func() {
			util.Forever(func() {
				if err := thirdPartyControl.SyncResources(); err != nil {
					glog.Warningf("third party resource sync failed: %v", err)
				}
			}, 10*time.Second)
		}()

		storage["thirdpartyresources"] = thirdPartyResourceStorage
	}

	if isEnabled("daemonsets") {
		daemonSetStorage, daemonSetStatusStorage := daemonetcd.NewREST(dbClient("daemonsets"), storageDecorator)
		storage["daemonsets"] = daemonSetStorage
		storage["daemonsets/status"] = daemonSetStatusStorage
	}
	if isEnabled("deployments") {
		deploymentStorage := deploymentetcd.NewStorage(dbClient("deployments"), storageDecorator)
		storage["deployments"] = deploymentStorage.Deployment
		storage["deployments/status"] = deploymentStorage.Status
		storage["deployments/scale"] = deploymentStorage.Scale
	}
	if isEnabled("jobs") {
		jobStorage, jobStatusStorage := jobetcd.NewREST(dbClient("jobs"), storageDecorator)
		storage["jobs"] = jobStorage
		storage["jobs/status"] = jobStatusStorage
	}
	if isEnabled("ingresses") {
		ingressStorage, ingressStatusStorage := ingressetcd.NewREST(dbClient("ingresses"), storageDecorator)
		storage["ingresses"] = ingressStorage
		storage["ingresses/status"] = ingressStatusStorage
	}

	extensionsGroup := latest.GroupOrDie("extensions")
	serverGroupVersion := unversioned.ParseGroupVersionOrDie(latest.GroupOrDie("").GroupVersion)

	return &apiserver.APIGroupVersion{
		Root:                m.apiGroupPrefix,
		RequestInfoResolver: m.newRequestInfoResolver(),

		Creater:   api.Scheme,
		Convertor: api.Scheme,
		Typer:     api.Scheme,

		Mapper:             extensionsGroup.RESTMapper,
		Codec:              extensionsGroup.Codec,
		Linker:             extensionsGroup.SelfLinker,
		Storage:            storage,
		GroupVersion:       unversioned.ParseGroupVersionOrDie(extensionsGroup.GroupVersion),
		ServerGroupVersion: &serverGroupVersion,

		Admit:   m.admissionControl,
		Context: m.requestContextMapper,

		MinRequestTimeout: m.minRequestTimeout,
	}
}
Пример #9
0
func main() {
	runtime.GOMAXPROCS(runtime.NumCPU())
	flag.Parse()

	var funcOut io.Writer
	if *functionDest == "-" {
		funcOut = os.Stdout
	} else {
		file, err := os.Create(*functionDest)
		if err != nil {
			glog.Fatalf("Couldn't open %v: %v", *functionDest, err)
		}
		defer file.Close()
		funcOut = file
	}

	data := new(bytes.Buffer)

	gv := unversioned.ParseGroupVersionOrDie(*groupVersion)

	registerTo := destScheme(gv)
	var pkgname string
	if gv.Group == "" {
		// the internal version of v1 is registered in package api
		pkgname = "api"
	} else {
		pkgname = gv.Group
	}
	if len(gv.Version) != 0 {
		pkgname = gv.Version
	}

	_, err := data.WriteString(fmt.Sprintf("package %s\n", pkgname))
	if err != nil {
		glog.Fatalf("Error while writing package line: %v", err)
	}

	versionPath := pkgPath(gv.Group, gv.Version)
	generator := kruntime.NewDeepCopyGenerator(api.Scheme.Raw(), versionPath, sets.NewString("k8s.io/kubernetes"))
	generator.AddImport(path.Join(pkgBase, "api"))

	if len(*overwrites) > 0 {
		for _, overwrite := range strings.Split(*overwrites, ",") {
			if !strings.Contains(overwrite, "=") {
				glog.Fatalf("Invalid overwrite syntax: %s", overwrite)
			}
			vals := strings.Split(overwrite, "=")
			generator.OverwritePackage(vals[0], vals[1])
		}
	}

	for _, knownType := range api.Scheme.KnownTypes(gv) {
		if knownType.PkgPath() != versionPath {
			continue
		}
		if err := generator.AddType(knownType); err != nil {
			glog.Errorf("Error while generating deep copy functions for %v: %v", knownType, err)
		}
	}
	generator.RepackImports()
	if err := generator.WriteImports(data); err != nil {
		glog.Fatalf("Error while writing imports: %v", err)
	}
	if err := generator.WriteDeepCopyFunctions(data); err != nil {
		glog.Fatalf("Error while writing deep copy functions: %v", err)
	}
	if err := generator.RegisterDeepCopyFunctions(data, registerTo); err != nil {
		glog.Fatalf("Error while registering deep copy functions: %v", err)
	}
	b, err := imports.Process("", data.Bytes(), nil)
	if err != nil {
		glog.Fatalf("Error while update imports: %v", err)
	}
	if _, err := funcOut.Write(b); err != nil {
		glog.Fatalf("Error while writing out the resulting file: %v", err)
	}
}
Пример #10
0
func (s *Scheme) EncodeToVersionStream(obj interface{}, destVersion string, stream io.Writer) error {
	obj = maybeCopy(obj)
	v, _ := EnforcePtr(obj) // maybeCopy guarantees a pointer

	// Don't encode an object defined in the unversioned package, unless if the
	// destVersion is v1, encode it to v1 for backward compatibility.
	pkg := path.Base(v.Type().PkgPath())
	if pkg == "unversioned" && destVersion != "v1" {
		// TODO: convert this to streaming too
		data, err := s.encodeUnversionedObject(obj)
		if err != nil {
			return err
		}
		_, err = stream.Write(data)
		return err
	}

	if _, registered := s.typeToGVK[v.Type()]; !registered {
		return fmt.Errorf("type %v is not registered for %q and it will be impossible to Decode it, therefore Encode will refuse to encode it.", v.Type(), destVersion)
	}

	objGVK, err := s.ObjectKind(obj)
	if err != nil {
		return err
	}

	// Perform a conversion if necessary.
	if objGVK.GroupVersion().String() != destVersion {
		objOut, err := s.NewObject(destVersion, objGVK.Kind)
		if err != nil {
			return err
		}
		flags, meta := s.generateConvertMeta(objGVK.GroupVersion(), unversioned.ParseGroupVersionOrDie(destVersion), obj)
		err = s.converter.Convert(obj, objOut, flags, meta)
		if err != nil {
			return err
		}
		obj = objOut

		// ensure the output object name comes from the destination type
		newGroupVersionKind, err := s.ObjectKind(obj)
		if err != nil {
			return err
		}
		objGVK.Kind = newGroupVersionKind.Kind
	}

	// Version and Kind should be set on the wire.
	err = s.SetVersionAndKind(destVersion, objGVK.Kind, obj)
	if err != nil {
		return err
	}

	// To add metadata, do some simple surgery on the JSON.
	encoder := json.NewEncoder(stream)
	if err := encoder.Encode(obj); err != nil {
		return err
	}

	// Version and Kind should be blank in memory. Reset them, since it's
	// possible that we modified a user object and not a copy above.
	err = s.SetVersionAndKind("", "", obj)
	if err != nil {
		return err
	}

	return nil
}