package apiroot import ( "net/http" "strings" "github.com/rancher/steve/pkg/schemaserver/store/empty" "github.com/rancher/steve/pkg/schemaserver/types" "github.com/rancher/wrangler/pkg/schemas" ) func Register(apiSchemas *types.APISchemas, versions, roots []string) { apiSchemas.MustAddSchema(types.APISchema{ Schema: &schemas.Schema{ ID: "apiRoot", CollectionMethods: []string{"GET"}, ResourceMethods: []string{"GET"}, ResourceFields: map[string]schemas.Field{ "apiVersion": {Type: "map[json]"}, "path": {Type: "string"}, }, }, Formatter: Formatter, Store: NewAPIRootStore(versions, roots), }) } func Formatter(apiOp *types.APIRequest, resource *types.RawResource) { data := resource.APIObject.Data() path, _ := data["path"].(string) if path == "" { return } delete(data, "path") resource.Links["root"] = apiOp.URLBuilder.RelativeToRoot(path) if data, isAPIRoot := data["apiVersion"].(map[string]interface{}); isAPIRoot { apiVersion := apiVersionFromMap(apiOp.Schemas, data) resource.Links["self"] = apiOp.URLBuilder.RelativeToRoot(apiVersion) resource.Links["schemas"] = apiOp.URLBuilder.RelativeToRoot(path) for _, schema := range apiOp.Schemas.Schemas { addCollectionLink(apiOp, schema, resource.Links) } } return } func addCollectionLink(apiOp *types.APIRequest, schema *types.APISchema, links map[string]string) { collectionLink := getSchemaCollectionLink(apiOp, schema) if collectionLink != "" { links[schema.PluralName] = collectionLink } } func getSchemaCollectionLink(apiOp *types.APIRequest, schema *types.APISchema) string { if schema != nil && contains(schema.CollectionMethods, http.MethodGet) { return apiOp.URLBuilder.Collection(schema) } return "" } type Store struct { empty.Store roots []string versions []string } func NewAPIRootStore(versions []string, roots []string) types.Store { return &Store{ roots: roots, versions: versions, } } func (a *Store) ByID(apiOp *types.APIRequest, schema *types.APISchema, id string) (types.APIObject, error) { return types.DefaultByID(a, apiOp, schema, id) } func (a *Store) List(apiOp *types.APIRequest, schema *types.APISchema) (types.APIObjectList, error) { var roots types.APIObjectList versions := a.versions for _, version := range versions { roots.Objects = append(roots.Objects, types.APIObject{ Type: "apiRoot", ID: version, Object: apiVersionToAPIRootMap(version), }) } for _, root := range a.roots { parts := strings.SplitN(root, ":", 2) if len(parts) == 2 { roots.Objects = append(roots.Objects, types.APIObject{ Type: "apiRoot", ID: parts[0], Object: map[string]interface{}{ "id": parts[0], "path": parts[1], }, }) } } return roots, nil } func apiVersionToAPIRootMap(version string) map[string]interface{} { return map[string]interface{}{ "id": version, "type": "apiRoot", "apiVersion": map[string]interface{}{ "version": version, }, "path": "/" + version, } } func apiVersionFromMap(schemas *types.APISchemas, apiVersion map[string]interface{}) string { version, _ := apiVersion["version"].(string) return version } func contains(list []string, needle string) bool { for _, v := range list { if v == needle { return true } } return false }