Skip to content

Commit

Permalink
Subcontext and mapping updates
Browse files Browse the repository at this point in the history
  • Loading branch information
ibuildthecloud committed Nov 21, 2017
1 parent 3ba704a commit 38c9c5c
Show file tree
Hide file tree
Showing 78 changed files with 1,692 additions and 994 deletions.
123 changes: 123 additions & 0 deletions api/builtin/api_root.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,123 @@
package builtin

import (
"github.com/rancher/norman/store/empty"
"github.com/rancher/norman/types"
"github.com/rancher/norman/types/convert"
)

func APIRootFormatter(apiContext *types.APIContext, resource *types.RawResource) {
path, _ := resource.Values["path"].(string)
if path == "" {
return
}

delete(resource.Values, "path")

resource.Links["root"] = apiContext.URLBuilder.RelativeToRoot(path)

data, _ := resource.Values["apiVersion"].(map[string]interface{})
apiVersion := apiVersionFromMap(apiContext.Schemas, data)

resource.Links["self"] = apiContext.URLBuilder.Version(apiVersion)

if len(apiVersion.SubContexts) > 0 {
subContextToSchema := apiContext.Schemas.SubContextSchemas()
if len(subContextToSchema) > 0 {
for _, schema := range subContextToSchema {
addCollectionLink(apiContext, schema, resource.Links)
}

for _, schema := range getNonReferencedSchemas(apiContext.Schemas.SchemasForVersion(apiVersion),
subContextToSchema) {
addCollectionLink(apiContext, schema, resource.Links)
}

return
}
}

for _, schema := range apiContext.Schemas.SchemasForVersion(apiVersion) {
addCollectionLink(apiContext, schema, resource.Links)
}

return
}

func getNonReferencedSchemas(schemas map[string]*types.Schema, subContexts map[string]*types.Schema) []*types.Schema {
var result []*types.Schema
typeNames := map[string]bool{}

for _, subContext := range subContexts {
ref := convert.ToReference(subContext.ID)
fullRef := convert.ToFullReference(subContext.Version.Path, subContext.ID)
typeNames[ref] = true
typeNames[fullRef] = true
}

outer:
for _, schema := range schemas {
for _, field := range schema.ResourceFields {
if typeNames[field.Type] {
continue outer
}
}

result = append(result, schema)
}

return result
}

func addCollectionLink(apiContext *types.APIContext, schema *types.Schema, links map[string]string) {
collectionLink := getSchemaCollectionLink(apiContext, schema, nil)
if collectionLink != "" {
links[schema.PluralName] = collectionLink
}
}

type APIRootStore struct {
empty.Store
roots []string
}

func NewAPIRootStore(roots []string) types.Store {
return &APIRootStore{roots: roots}
}

func (a *APIRootStore) ByID(apiContext *types.APIContext, schema *types.Schema, id string) (map[string]interface{}, error) {
for _, version := range apiContext.Schemas.Versions() {
if version.Path == id {
return apiVersionToAPIRootMap(version), nil
}
}
return nil, nil
}

func (a *APIRootStore) List(apiContext *types.APIContext, schema *types.Schema, opt types.QueryOptions) ([]map[string]interface{}, error) {
var roots []map[string]interface{}

for _, version := range apiContext.Schemas.Versions() {
roots = append(roots, apiVersionToAPIRootMap(version))
}

for _, root := range a.roots {
roots = append(roots, map[string]interface{}{
"path": root,
})
}

return roots, nil
}

func apiVersionToAPIRootMap(version types.APIVersion) map[string]interface{} {
return map[string]interface{}{
"type": "/v1-meta/schemas/apiRoot",
"apiVersion": map[string]interface{}{
"version": version.Version,
"group": version.Group,
"path": version.Path,
},
"path": version.Path,
}
}
109 changes: 29 additions & 80 deletions api/builtin/builtin.go → api/builtin/schema.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,16 +3,15 @@ package builtin
import (
"net/http"

"github.com/rancher/norman/store/empty"
"github.com/rancher/norman/store/schema"
"github.com/rancher/norman/types"
)

var (
Version = types.APIVersion{
Group: "io.cattle.builtin",
Version: "v3",
Path: "/v3",
Group: "meta.cattle.io",
Version: "v1",
Path: "/v1-meta",
}

Schema = types.Schema{
Expand All @@ -23,7 +22,7 @@ var (
ResourceFields: map[string]types.Field{
"collectionActions": {Type: "map[json]"},
"collectionFields": {Type: "map[json]"},
"collectionFitlers": {Type: "map[json]"},
"collectionFilters": {Type: "map[json]"},
"collectionMethods": {Type: "array[string]"},
"pluralName": {Type: "string"},
"resourceActions": {Type: "map[json]"},
Expand All @@ -41,10 +40,11 @@ var (
ResourceMethods: []string{},
CollectionMethods: []string{},
ResourceFields: map[string]types.Field{
"code": {Type: "string"},
"detail": {Type: "string"},
"message": {Type: "string"},
"status": {Type: "int"},
"code": {Type: "string"},
"detail": {Type: "string", Nullable: true},
"message": {Type: "string", Nullable: true},
"fieldName": {Type: "string", Nullable: true},
"status": {Type: "int"},
},
}

Expand Down Expand Up @@ -81,32 +81,46 @@ var (
AddSchema(&APIRoot)
)

func apiVersionFromMap(apiVersion map[string]interface{}) types.APIVersion {
func apiVersionFromMap(schemas *types.Schemas, apiVersion map[string]interface{}) types.APIVersion {
path, _ := apiVersion["path"].(string)
version, _ := apiVersion["version"].(string)
group, _ := apiVersion["group"].(string)

return types.APIVersion{
apiVersionObj := types.APIVersion{
Path: path,
Version: version,
Group: group,
}

for _, testVersion := range schemas.Versions() {
if testVersion.Equals(&apiVersionObj) {
return testVersion
}
}

return apiVersionObj
}

func SchemaFormatter(apiContext *types.APIContext, resource *types.RawResource) {
data, _ := resource.Values["version"].(map[string]interface{})
apiVersion := apiVersionFromMap(data)
apiVersion := apiVersionFromMap(apiContext.Schemas, data)

schema := apiContext.Schemas.Schema(&apiVersion, resource.ID)
collectionLink := getSchemaCollectionLink(apiContext, schema)
if schema == nil {
return
}

collectionLink := getSchemaCollectionLink(apiContext, schema, &apiVersion)
if collectionLink != "" {
resource.Links["collection"] = collectionLink
}

resource.Links["self"] = apiContext.URLBuilder.SchemaLink(schema)
}

func getSchemaCollectionLink(apiContext *types.APIContext, schema *types.Schema) string {
func getSchemaCollectionLink(apiContext *types.APIContext, schema *types.Schema, apiVersion *types.APIVersion) string {
if schema != nil && contains(schema.CollectionMethods, http.MethodGet) {
return apiContext.URLBuilder.Collection(schema)
return apiContext.URLBuilder.Collection(schema, apiVersion)
}
return ""
}
Expand All @@ -119,68 +133,3 @@ func contains(list []string, needle string) bool {
}
return false
}

func APIRootFormatter(apiContext *types.APIContext, resource *types.RawResource) {
path, _ := resource.Values["path"].(string)
if path == "" {
return
}

resource.Links["root"] = apiContext.URLBuilder.RelativeToRoot(path)

data, _ := resource.Values["apiVersion"].(map[string]interface{})
apiVersion := apiVersionFromMap(data)

for name, schema := range apiContext.Schemas.SchemasForVersion(apiVersion) {
collectionLink := getSchemaCollectionLink(apiContext, schema)
if collectionLink != "" {
resource.Links[name] = collectionLink
}
}
}

type APIRootStore struct {
empty.Store
roots []string
}

func NewAPIRootStore(roots []string) types.Store {
return &APIRootStore{roots: roots}
}

func (a *APIRootStore) ByID(apiContext *types.APIContext, schema *types.Schema, id string) (map[string]interface{}, error) {
for _, version := range apiContext.Schemas.Versions() {
if version.Path == id {
return apiVersionToAPIRootMap(version), nil
}
}
return nil, nil
}

func (a *APIRootStore) List(apiContext *types.APIContext, schema *types.Schema, opt *types.QueryOptions) ([]map[string]interface{}, error) {
roots := []map[string]interface{}{}

for _, version := range apiContext.Schemas.Versions() {
roots = append(roots, apiVersionToAPIRootMap(version))
}

for _, root := range a.roots {
roots = append(roots, map[string]interface{}{
"path": root,
})
}

return roots, nil
}

func apiVersionToAPIRootMap(version types.APIVersion) map[string]interface{} {
return map[string]interface{}{
"type": "/v3/apiRoot",
"apiVersion": map[string]interface{}{
"version": version.Version,
"group": version.Group,
"path": version.Path,
},
"path": version.Path,
}
}
25 changes: 25 additions & 0 deletions api/formatter/subcontext_filter.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
package formatter

import (
"github.com/rancher/norman/types"
"github.com/rancher/norman/types/convert"
)

func SubContextFormatter(apiContext *types.APIContext, resource *types.RawResource) {
if resource.Schema.SubContext == "" {
return
}

ref := convert.ToReference(resource.Schema.ID)
fullRef := convert.ToFullReference(resource.Schema.Version.Path, resource.Schema.ID)

outer:
for _, schema := range apiContext.Schemas.Schemas() {
for _, field := range schema.ResourceFields {
if (field.Type == ref || field.Type == fullRef) && schema.Version.SubContexts[resource.Schema.SubContext] {
resource.Links[schema.PluralName] = apiContext.URLBuilder.SubContextCollection(resource.Schema, resource.ID, schema)
continue outer
}
}
}
}
27 changes: 27 additions & 0 deletions api/handler/create.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
package handler

import (
"net/http"

"github.com/rancher/norman/types"
)

func CreateHandler(apiContext *types.APIContext) error {
var err error

data, err := ParseAndValidateBody(apiContext)
if err != nil {
return err
}

store := apiContext.Schema.Store
if store != nil {
data, err = store.Create(apiContext, apiContext.Schema, data)
if err != nil {
return err
}
}

apiContext.WriteResponse(http.StatusCreated, data)
return nil
}
2 changes: 1 addition & 1 deletion api/handlers/delete.go → api/handler/delete.go
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
package handlers
package handler

import (
"net/http"
Expand Down
6 changes: 3 additions & 3 deletions api/handlers/list.go → api/handler/list.go
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
package handlers
package handler

import (
"net/http"
Expand All @@ -19,8 +19,8 @@ func ListHandler(request *types.APIContext) error {
}

if request.ID == "" {
request.QueryOptions = parse.QueryOptions(request.Request, request.Schema)
data, err = store.List(request, request.Schema, request.QueryOptions)
opts := parse.QueryOptions(request, request.Schema)
data, err = store.List(request, request.Schema, opts)
} else if request.Link == "" {
data, err = store.ByID(request, request.Schema, request.ID)
} else {
Expand Down
Loading

0 comments on commit 38c9c5c

Please sign in to comment.