openapi.go 3.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129
  1. /*
  2. Copyright 2017 The Kubernetes Authors.
  3. Licensed under the Apache License, Version 2.0 (the "License");
  4. you may not use this file except in compliance with the License.
  5. You may obtain a copy of the License at
  6. http://www.apache.org/licenses/LICENSE-2.0
  7. Unless required by applicable law or agreed to in writing, software
  8. distributed under the License is distributed on an "AS IS" BASIS,
  9. WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  10. See the License for the specific language governing permissions and
  11. limitations under the License.
  12. */
  13. package openapi
  14. import (
  15. openapi_v2 "github.com/googleapis/gnostic/OpenAPIv2"
  16. "k8s.io/apimachinery/pkg/runtime/schema"
  17. "k8s.io/kube-openapi/pkg/util/proto"
  18. )
  19. // Resources interface describe a resources provider, that can give you
  20. // resource based on group-version-kind.
  21. type Resources interface {
  22. LookupResource(gvk schema.GroupVersionKind) proto.Schema
  23. }
  24. // groupVersionKindExtensionKey is the key used to lookup the
  25. // GroupVersionKind value for an object definition from the
  26. // definition's "extensions" map.
  27. const groupVersionKindExtensionKey = "x-kubernetes-group-version-kind"
  28. // document is an implementation of `Resources`. It looks for
  29. // resources in an openapi Schema.
  30. type document struct {
  31. // Maps gvk to model name
  32. resources map[schema.GroupVersionKind]string
  33. models proto.Models
  34. }
  35. var _ Resources = &document{}
  36. // NewOpenAPIData creates a new `Resources` out of the openapi document
  37. func NewOpenAPIData(doc *openapi_v2.Document) (Resources, error) {
  38. models, err := proto.NewOpenAPIData(doc)
  39. if err != nil {
  40. return nil, err
  41. }
  42. resources := map[schema.GroupVersionKind]string{}
  43. for _, modelName := range models.ListModels() {
  44. model := models.LookupModel(modelName)
  45. if model == nil {
  46. panic("ListModels returns a model that can't be looked-up.")
  47. }
  48. gvkList := parseGroupVersionKind(model)
  49. for _, gvk := range gvkList {
  50. if len(gvk.Kind) > 0 {
  51. resources[gvk] = modelName
  52. }
  53. }
  54. }
  55. return &document{
  56. resources: resources,
  57. models: models,
  58. }, nil
  59. }
  60. func (d *document) LookupResource(gvk schema.GroupVersionKind) proto.Schema {
  61. modelName, found := d.resources[gvk]
  62. if !found {
  63. return nil
  64. }
  65. return d.models.LookupModel(modelName)
  66. }
  67. // Get and parse GroupVersionKind from the extension. Returns empty if it doesn't have one.
  68. func parseGroupVersionKind(s proto.Schema) []schema.GroupVersionKind {
  69. extensions := s.GetExtensions()
  70. gvkListResult := []schema.GroupVersionKind{}
  71. // Get the extensions
  72. gvkExtension, ok := extensions[groupVersionKindExtensionKey]
  73. if !ok {
  74. return []schema.GroupVersionKind{}
  75. }
  76. // gvk extension must be a list of at least 1 element.
  77. gvkList, ok := gvkExtension.([]interface{})
  78. if !ok {
  79. return []schema.GroupVersionKind{}
  80. }
  81. for _, gvk := range gvkList {
  82. // gvk extension list must be a map with group, version, and
  83. // kind fields
  84. gvkMap, ok := gvk.(map[interface{}]interface{})
  85. if !ok {
  86. continue
  87. }
  88. group, ok := gvkMap["group"].(string)
  89. if !ok {
  90. continue
  91. }
  92. version, ok := gvkMap["version"].(string)
  93. if !ok {
  94. continue
  95. }
  96. kind, ok := gvkMap["kind"].(string)
  97. if !ok {
  98. continue
  99. }
  100. gvkListResult = append(gvkListResult, schema.GroupVersionKind{
  101. Group: group,
  102. Version: version,
  103. Kind: kind,
  104. })
  105. }
  106. return gvkListResult
  107. }