k8s.io/kube-openapi@v0.0.0-20240228011516-70dd3763d340/pkg/validation/spec/gnostic.go (about) 1 /* 2 Copyright 2022 The Kubernetes Authors. 3 4 Licensed under the Apache License, Version 2.0 (the "License"); 5 you may not use this file except in compliance with the License. 6 You may obtain a copy of the License at 7 8 http://www.apache.org/licenses/LICENSE-2.0 9 10 Unless required by applicable law or agreed to in writing, software 11 distributed under the License is distributed on an "AS IS" BASIS, 12 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 See the License for the specific language governing permissions and 14 limitations under the License. 15 */ 16 17 package spec 18 19 import ( 20 "errors" 21 "strconv" 22 23 "github.com/go-openapi/jsonreference" 24 openapi_v2 "github.com/google/gnostic-models/openapiv2" 25 ) 26 27 // Interfaces 28 type GnosticCommonValidations interface { 29 GetMaximum() float64 30 GetExclusiveMaximum() bool 31 GetMinimum() float64 32 GetExclusiveMinimum() bool 33 GetMaxLength() int64 34 GetMinLength() int64 35 GetPattern() string 36 GetMaxItems() int64 37 GetMinItems() int64 38 GetUniqueItems() bool 39 GetMultipleOf() float64 40 GetEnum() []*openapi_v2.Any 41 } 42 43 func (k *CommonValidations) FromGnostic(g GnosticCommonValidations) error { 44 if g == nil { 45 return nil 46 } 47 48 max := g.GetMaximum() 49 if max != 0 { 50 k.Maximum = &max 51 } 52 53 k.ExclusiveMaximum = g.GetExclusiveMaximum() 54 55 min := g.GetMinimum() 56 if min != 0 { 57 k.Minimum = &min 58 } 59 60 k.ExclusiveMinimum = g.GetExclusiveMinimum() 61 62 maxLen := g.GetMaxLength() 63 if maxLen != 0 { 64 k.MaxLength = &maxLen 65 } 66 67 minLen := g.GetMinLength() 68 if minLen != 0 { 69 k.MinLength = &minLen 70 } 71 72 k.Pattern = g.GetPattern() 73 74 maxItems := g.GetMaxItems() 75 if maxItems != 0 { 76 k.MaxItems = &maxItems 77 } 78 79 minItems := g.GetMinItems() 80 if minItems != 0 { 81 k.MinItems = &minItems 82 } 83 84 k.UniqueItems = g.GetUniqueItems() 85 86 multOf := g.GetMultipleOf() 87 if multOf != 0 { 88 k.MultipleOf = &multOf 89 } 90 91 enums := g.GetEnum() 92 93 if enums != nil { 94 k.Enum = make([]interface{}, len(enums)) 95 for i, v := range enums { 96 if v == nil { 97 continue 98 } 99 100 var convert interface{} 101 if err := v.ToRawInfo().Decode(&convert); err != nil { 102 return err 103 } else { 104 k.Enum[i] = convert 105 } 106 } 107 } 108 109 return nil 110 } 111 112 type GnosticSimpleSchema interface { 113 GetType() string 114 GetFormat() string 115 GetItems() *openapi_v2.PrimitivesItems 116 GetCollectionFormat() string 117 GetDefault() *openapi_v2.Any 118 } 119 120 func (k *SimpleSchema) FromGnostic(g GnosticSimpleSchema) error { 121 if g == nil { 122 return nil 123 } 124 125 k.Type = g.GetType() 126 k.Format = g.GetFormat() 127 k.CollectionFormat = g.GetCollectionFormat() 128 129 items := g.GetItems() 130 if items != nil { 131 k.Items = &Items{} 132 if err := k.Items.FromGnostic(items); err != nil { 133 return err 134 } 135 } 136 137 def := g.GetDefault() 138 if def != nil { 139 var convert interface{} 140 if err := def.ToRawInfo().Decode(&convert); err != nil { 141 return err 142 } else { 143 k.Default = convert 144 } 145 } 146 147 return nil 148 } 149 150 func (k *Items) FromGnostic(g *openapi_v2.PrimitivesItems) error { 151 if g == nil { 152 return nil 153 } 154 155 if err := k.SimpleSchema.FromGnostic(g); err != nil { 156 return err 157 } 158 159 if err := k.CommonValidations.FromGnostic(g); err != nil { 160 return err 161 } 162 163 if err := k.VendorExtensible.FromGnostic(g.VendorExtension); err != nil { 164 return err 165 } 166 167 return nil 168 } 169 170 func (k *VendorExtensible) FromGnostic(g []*openapi_v2.NamedAny) error { 171 if len(g) == 0 { 172 return nil 173 } 174 175 k.Extensions = make(Extensions, len(g)) 176 for _, v := range g { 177 if v == nil { 178 continue 179 } 180 181 if v.Value == nil { 182 k.Extensions[v.Name] = nil 183 continue 184 } 185 186 var iface interface{} 187 if err := v.Value.ToRawInfo().Decode(&iface); err != nil { 188 return err 189 } else { 190 k.Extensions[v.Name] = iface 191 } 192 } 193 return nil 194 } 195 196 func (k *Refable) FromGnostic(g string) error { 197 return k.Ref.FromGnostic(g) 198 } 199 200 func (k *Ref) FromGnostic(g string) error { 201 if g == "" { 202 return nil 203 } 204 205 ref, err := jsonreference.New(g) 206 if err != nil { 207 return err 208 } 209 210 *k = Ref{ 211 Ref: ref, 212 } 213 214 return nil 215 } 216 217 // Converts a gnostic v2 Document to a kube-openapi Swagger Document 218 // 219 // Caveats: 220 // 221 // - gnostic v2 documents treats zero as unspecified for numerical fields of 222 // CommonValidations fields such as Maximum, Minimum, MaximumItems, etc. 223 // There will always be data loss if one of the values of these fields is set to zero. 224 // 225 // Returns: 226 // 227 // - `ok`: `false` if a value was present in the gnostic document which cannot be 228 // roundtripped into kube-openapi types. In these instances, `ok` is set to 229 // `false` and the value is skipped. 230 // 231 // - `err`: an unexpected error occurred in the conversion from the gnostic type 232 // to kube-openapi type. 233 func (k *Swagger) FromGnostic(g *openapi_v2.Document) (ok bool, err error) { 234 ok = true 235 if g == nil { 236 return true, nil 237 } 238 239 if err := k.VendorExtensible.FromGnostic(g.VendorExtension); err != nil { 240 return false, err 241 } 242 243 if nok, err := k.SwaggerProps.FromGnostic(g); err != nil { 244 return false, err 245 } else if !nok { 246 ok = false 247 } 248 249 return ok, nil 250 } 251 252 func (k *SwaggerProps) FromGnostic(g *openapi_v2.Document) (ok bool, err error) { 253 if g == nil { 254 return true, nil 255 } 256 257 ok = true 258 259 // openapi_v2.Document does not support "ID" field, so it will not be 260 // included 261 k.Consumes = g.Consumes 262 k.Produces = g.Produces 263 k.Schemes = g.Schemes 264 k.Swagger = g.Swagger 265 266 if g.Info != nil { 267 k.Info = &Info{} 268 if nok, err := k.Info.FromGnostic(g.Info); err != nil { 269 return false, err 270 } else if !nok { 271 ok = false 272 } 273 } 274 275 k.Host = g.Host 276 k.BasePath = g.BasePath 277 278 if g.Paths != nil { 279 k.Paths = &Paths{} 280 if nok, err := k.Paths.FromGnostic(g.Paths); err != nil { 281 return false, err 282 } else if !nok { 283 ok = false 284 } 285 } 286 287 if g.Definitions != nil { 288 k.Definitions = make(Definitions, len(g.Definitions.AdditionalProperties)) 289 for _, v := range g.Definitions.AdditionalProperties { 290 if v == nil { 291 continue 292 } 293 converted := Schema{} 294 if nok, err := converted.FromGnostic(v.Value); err != nil { 295 return false, err 296 } else if !nok { 297 ok = false 298 } 299 k.Definitions[v.Name] = converted 300 301 } 302 } 303 304 if g.Parameters != nil { 305 k.Parameters = make( 306 map[string]Parameter, 307 len(g.Parameters.AdditionalProperties)) 308 for _, v := range g.Parameters.AdditionalProperties { 309 if v == nil { 310 continue 311 } 312 p := Parameter{} 313 if nok, err := p.FromGnostic(v.Value); err != nil { 314 return false, err 315 } else if !nok { 316 ok = false 317 } 318 319 k.Parameters[v.Name] = p 320 } 321 } 322 323 if g.Responses != nil { 324 k.Responses = make( 325 map[string]Response, 326 len(g.Responses.AdditionalProperties)) 327 328 for _, v := range g.Responses.AdditionalProperties { 329 if v == nil { 330 continue 331 } 332 p := Response{} 333 if nok, err := p.FromGnostic(v.Value); err != nil { 334 return false, err 335 } else if !nok { 336 ok = false 337 } 338 339 k.Responses[v.Name] = p 340 } 341 } 342 343 if g.SecurityDefinitions != nil { 344 k.SecurityDefinitions = make(SecurityDefinitions) 345 if err := k.SecurityDefinitions.FromGnostic(g.SecurityDefinitions); err != nil { 346 return false, err 347 } 348 } 349 350 if g.Security != nil { 351 k.Security = make([]map[string][]string, len(g.Security)) 352 for i, v := range g.Security { 353 if v == nil || v.AdditionalProperties == nil { 354 continue 355 } 356 357 k.Security[i] = make(map[string][]string, len(v.AdditionalProperties)) 358 converted := k.Security[i] 359 for _, p := range v.AdditionalProperties { 360 if p == nil { 361 continue 362 } 363 if p.Value != nil { 364 converted[p.Name] = p.Value.Value 365 } else { 366 converted[p.Name] = nil 367 } 368 } 369 } 370 } 371 372 if g.Tags != nil { 373 k.Tags = make([]Tag, len(g.Tags)) 374 for i, v := range g.Tags { 375 if v == nil { 376 continue 377 } else if nok, err := k.Tags[i].FromGnostic(v); err != nil { 378 return false, err 379 } else if !nok { 380 ok = false 381 } 382 } 383 } 384 385 if g.ExternalDocs != nil { 386 k.ExternalDocs = &ExternalDocumentation{} 387 if nok, err := k.ExternalDocs.FromGnostic(g.ExternalDocs); err != nil { 388 return false, err 389 } else if !nok { 390 ok = false 391 } 392 } 393 394 return ok, nil 395 } 396 397 // Info 398 399 func (k *Info) FromGnostic(g *openapi_v2.Info) (ok bool, err error) { 400 ok = true 401 if g == nil { 402 return true, nil 403 } 404 405 if err := k.VendorExtensible.FromGnostic(g.VendorExtension); err != nil { 406 return false, err 407 } 408 409 if nok, err := k.InfoProps.FromGnostic(g); err != nil { 410 return false, err 411 } else if !nok { 412 ok = false 413 } 414 415 return ok, nil 416 } 417 418 func (k *InfoProps) FromGnostic(g *openapi_v2.Info) (ok bool, err error) { 419 if g == nil { 420 return true, nil 421 } 422 423 ok = true 424 425 k.Description = g.Description 426 k.Title = g.Title 427 k.TermsOfService = g.TermsOfService 428 429 if g.Contact != nil { 430 k.Contact = &ContactInfo{} 431 432 if nok, err := k.Contact.FromGnostic(g.Contact); err != nil { 433 return false, err 434 } else if !nok { 435 ok = false 436 } 437 } 438 439 if g.License != nil { 440 k.License = &License{} 441 if nok, err := k.License.FromGnostic(g.License); err != nil { 442 return false, err 443 } else if !nok { 444 ok = false 445 } 446 } 447 448 k.Version = g.Version 449 return ok, nil 450 } 451 452 func (k *License) FromGnostic(g *openapi_v2.License) (ok bool, err error) { 453 if g == nil { 454 return true, nil 455 } 456 457 ok = true 458 459 k.Name = g.Name 460 k.URL = g.Url 461 462 // License does not embed to VendorExtensible! 463 // data loss from g.VendorExtension 464 if len(g.VendorExtension) != 0 { 465 ok = false 466 } 467 468 return ok, nil 469 } 470 471 func (k *ContactInfo) FromGnostic(g *openapi_v2.Contact) (ok bool, err error) { 472 if g == nil { 473 return true, nil 474 } 475 476 ok = true 477 478 k.Name = g.Name 479 k.URL = g.Url 480 k.Email = g.Email 481 482 // ContactInfo does not embed to VendorExtensible! 483 // data loss from g.VendorExtension 484 if len(g.VendorExtension) != 0 { 485 ok = false 486 } 487 488 return ok, nil 489 } 490 491 // Paths 492 493 func (k *Paths) FromGnostic(g *openapi_v2.Paths) (ok bool, err error) { 494 if g == nil { 495 return true, nil 496 } 497 498 ok = true 499 500 if g.Path != nil { 501 k.Paths = make(map[string]PathItem, len(g.Path)) 502 for _, v := range g.Path { 503 if v == nil { 504 continue 505 } 506 507 converted := PathItem{} 508 if nok, err := converted.FromGnostic(v.Value); err != nil { 509 return false, err 510 } else if !nok { 511 ok = false 512 } 513 514 k.Paths[v.Name] = converted 515 } 516 } 517 518 if err := k.VendorExtensible.FromGnostic(g.VendorExtension); err != nil { 519 return false, err 520 } 521 return ok, nil 522 } 523 524 func (k *PathItem) FromGnostic(g *openapi_v2.PathItem) (ok bool, err error) { 525 if g == nil { 526 return true, nil 527 } 528 ok = true 529 530 if nok, err := k.PathItemProps.FromGnostic(g); err != nil { 531 return false, err 532 } else if !nok { 533 ok = false 534 } 535 536 if err := k.Refable.FromGnostic(g.XRef); err != nil { 537 return false, err 538 } 539 540 if err := k.VendorExtensible.FromGnostic(g.VendorExtension); err != nil { 541 return false, err 542 } 543 return ok, nil 544 } 545 546 func (k *PathItemProps) FromGnostic(g *openapi_v2.PathItem) (ok bool, err error) { 547 if g == nil { 548 return true, nil 549 } 550 ok = true 551 if g.Get != nil { 552 k.Get = &Operation{} 553 if nok, err := k.Get.FromGnostic(g.Get); err != nil { 554 return false, err 555 } else if !nok { 556 ok = false 557 } 558 } 559 560 if g.Put != nil { 561 k.Put = &Operation{} 562 if nok, err := k.Put.FromGnostic(g.Put); err != nil { 563 return false, err 564 } else if !nok { 565 ok = false 566 } 567 } 568 569 if g.Post != nil { 570 k.Post = &Operation{} 571 if nok, err := k.Post.FromGnostic(g.Post); err != nil { 572 return false, err 573 } else if !nok { 574 ok = false 575 } 576 } 577 578 if g.Delete != nil { 579 k.Delete = &Operation{} 580 if nok, err := k.Delete.FromGnostic(g.Delete); err != nil { 581 return false, err 582 } else if !nok { 583 ok = false 584 } 585 } 586 587 if g.Options != nil { 588 k.Options = &Operation{} 589 if nok, err := k.Options.FromGnostic(g.Options); err != nil { 590 return false, err 591 } else if !nok { 592 ok = false 593 } 594 } 595 596 if g.Head != nil { 597 k.Head = &Operation{} 598 if nok, err := k.Head.FromGnostic(g.Head); err != nil { 599 return false, err 600 } else if !nok { 601 ok = false 602 } 603 } 604 605 if g.Patch != nil { 606 k.Patch = &Operation{} 607 if nok, err := k.Patch.FromGnostic(g.Patch); err != nil { 608 return false, err 609 } else if !nok { 610 ok = false 611 } 612 } 613 614 if g.Parameters != nil { 615 k.Parameters = make([]Parameter, len(g.Parameters)) 616 for i, v := range g.Parameters { 617 if v == nil { 618 continue 619 } else if nok, err := k.Parameters[i].FromGnosticParametersItem(v); err != nil { 620 return false, err 621 } else if !nok { 622 ok = false 623 } 624 } 625 } 626 627 return ok, nil 628 } 629 630 func (k *Operation) FromGnostic(g *openapi_v2.Operation) (ok bool, err error) { 631 if g == nil { 632 return true, nil 633 } 634 635 ok = true 636 637 if err := k.VendorExtensible.FromGnostic(g.VendorExtension); err != nil { 638 return false, err 639 } 640 641 if nok, err := k.OperationProps.FromGnostic(g); err != nil { 642 return false, err 643 } else if !nok { 644 ok = false 645 } 646 647 return ok, nil 648 } 649 650 func (k *OperationProps) FromGnostic(g *openapi_v2.Operation) (ok bool, err error) { 651 if g == nil { 652 return true, nil 653 } 654 655 ok = true 656 657 k.Description = g.Description 658 k.Consumes = g.Consumes 659 k.Produces = g.Produces 660 k.Schemes = g.Schemes 661 k.Tags = g.Tags 662 k.Summary = g.Summary 663 664 if g.ExternalDocs != nil { 665 k.ExternalDocs = &ExternalDocumentation{} 666 if nok, err := k.ExternalDocs.FromGnostic(g.ExternalDocs); err != nil { 667 return false, err 668 } else if !nok { 669 ok = false 670 } 671 } 672 673 k.ID = g.OperationId 674 k.Deprecated = g.Deprecated 675 676 if g.Security != nil { 677 k.Security = make([]map[string][]string, len(g.Security)) 678 for i, v := range g.Security { 679 if v == nil || v.AdditionalProperties == nil { 680 continue 681 } 682 683 k.Security[i] = make(map[string][]string, len(v.AdditionalProperties)) 684 converted := k.Security[i] 685 for _, p := range v.AdditionalProperties { 686 if p == nil { 687 continue 688 } 689 690 if p.Value != nil { 691 converted[p.Name] = p.Value.Value 692 } else { 693 converted[p.Name] = nil 694 } 695 } 696 } 697 } 698 699 if g.Parameters != nil { 700 k.Parameters = make([]Parameter, len(g.Parameters)) 701 for i, v := range g.Parameters { 702 if v == nil { 703 continue 704 } else if nok, err := k.Parameters[i].FromGnosticParametersItem(v); err != nil { 705 return false, err 706 } else if !nok { 707 ok = false 708 } 709 } 710 } 711 712 if g.Responses != nil { 713 k.Responses = &Responses{} 714 if nok, err := k.Responses.FromGnostic(g.Responses); err != nil { 715 return false, err 716 } else if !nok { 717 ok = false 718 } 719 } 720 721 return ok, nil 722 } 723 724 // Responses 725 726 func (k *Responses) FromGnostic(g *openapi_v2.Responses) (ok bool, err error) { 727 if g == nil { 728 return true, nil 729 } 730 ok = true 731 if err := k.VendorExtensible.FromGnostic(g.VendorExtension); err != nil { 732 return false, err 733 } 734 735 if nok, err := k.ResponsesProps.FromGnostic(g); err != nil { 736 return false, err 737 } else if !nok { 738 ok = false 739 } 740 741 return ok, nil 742 } 743 744 func (k *ResponsesProps) FromGnostic(g *openapi_v2.Responses) (ok bool, err error) { 745 if g == nil { 746 return true, nil 747 } else if g.ResponseCode == nil { 748 return ok, nil 749 } 750 751 ok = true 752 for _, v := range g.ResponseCode { 753 if v == nil { 754 continue 755 } 756 if v.Name == "default" { 757 k.Default = &Response{} 758 if nok, err := k.Default.FromGnosticResponseValue(v.Value); err != nil { 759 return false, err 760 } else if !nok { 761 ok = false 762 } 763 } else if nk, err := strconv.Atoi(v.Name); err != nil { 764 // This should actually never fail, unless gnostic struct was 765 // manually/purposefully tampered with at runtime. 766 // Gnostic's ParseDocument validates that all StatusCodeResponses 767 // keys adhere to the following regex ^([0-9]{3})$|^(default)$ 768 ok = false 769 } else { 770 if k.StatusCodeResponses == nil { 771 k.StatusCodeResponses = map[int]Response{} 772 } 773 774 res := Response{} 775 if nok, err := res.FromGnosticResponseValue(v.Value); err != nil { 776 return false, err 777 } else if !nok { 778 ok = false 779 } 780 k.StatusCodeResponses[nk] = res 781 } 782 } 783 784 return ok, nil 785 } 786 787 func (k *Response) FromGnostic(g *openapi_v2.Response) (ok bool, err error) { 788 if g == nil { 789 return true, nil 790 } 791 ok = true 792 // Refable case handled in FromGnosticResponseValue 793 794 if err := k.VendorExtensible.FromGnostic(g.VendorExtension); err != nil { 795 return false, err 796 } 797 798 if nok, err := k.ResponseProps.FromGnostic(g); err != nil { 799 return false, err 800 } else if !nok { 801 ok = false 802 } 803 804 return ok, nil 805 } 806 807 func (k *Response) FromGnosticResponseValue(g *openapi_v2.ResponseValue) (ok bool, err error) { 808 ok = true 809 if ref := g.GetJsonReference(); ref != nil { 810 k.Description = ref.Description 811 812 if err := k.Refable.FromGnostic(ref.XRef); err != nil { 813 return false, err 814 } 815 } else if nok, err := k.FromGnostic(g.GetResponse()); err != nil { 816 return false, err 817 } else if !nok { 818 ok = false 819 } 820 821 return ok, nil 822 } 823 824 func (k *ResponseProps) FromGnostic(g *openapi_v2.Response) (ok bool, err error) { 825 if g == nil { 826 return true, nil 827 } 828 ok = true 829 k.Description = g.Description 830 831 if g.Schema != nil { 832 k.Schema = &Schema{} 833 if nok, err := k.Schema.FromGnosticSchemaItem(g.Schema); err != nil { 834 return false, err 835 } else if !nok { 836 ok = false 837 } 838 } 839 840 if g.Headers != nil { 841 k.Headers = make(map[string]Header, len(g.Headers.AdditionalProperties)) 842 for _, v := range g.Headers.AdditionalProperties { 843 if v == nil { 844 continue 845 } 846 847 converted := Header{} 848 if err := converted.FromGnostic(v.GetValue()); err != nil { 849 return false, err 850 } 851 852 k.Headers[v.Name] = converted 853 } 854 } 855 856 if g.Examples != nil { 857 k.Examples = make(map[string]interface{}, len(g.Examples.AdditionalProperties)) 858 for _, v := range g.Examples.AdditionalProperties { 859 if v == nil { 860 continue 861 } else if v.Value == nil { 862 k.Examples[v.Name] = nil 863 continue 864 } 865 866 var iface interface{} 867 if err := v.Value.ToRawInfo().Decode(&iface); err != nil { 868 return false, err 869 } else { 870 k.Examples[v.Name] = iface 871 } 872 } 873 } 874 875 return ok, nil 876 } 877 878 // Header 879 880 func (k *Header) FromGnostic(g *openapi_v2.Header) (err error) { 881 if g == nil { 882 return nil 883 } 884 885 if err := k.CommonValidations.FromGnostic(g); err != nil { 886 return err 887 } 888 889 if err := k.VendorExtensible.FromGnostic(g.VendorExtension); err != nil { 890 return err 891 } 892 893 if err := k.SimpleSchema.FromGnostic(g); err != nil { 894 return err 895 } 896 897 if err := k.HeaderProps.FromGnostic(g); err != nil { 898 return err 899 } 900 901 return nil 902 } 903 904 func (k *HeaderProps) FromGnostic(g *openapi_v2.Header) error { 905 if g == nil { 906 return nil 907 } 908 909 // All other fields of openapi_v2.Header are handled by 910 // the embeded fields, commonvalidations, etc. 911 k.Description = g.Description 912 return nil 913 } 914 915 // Parameters 916 917 func (k *Parameter) FromGnostic(g *openapi_v2.Parameter) (ok bool, err error) { 918 if g == nil { 919 return true, nil 920 } 921 ok = true 922 switch p := g.Oneof.(type) { 923 case *openapi_v2.Parameter_BodyParameter: 924 if nok, err := k.ParamProps.FromGnostic(p.BodyParameter); err != nil { 925 return false, err 926 } else if !nok { 927 ok = false 928 } 929 930 if err := k.VendorExtensible.FromGnostic(p.BodyParameter.GetVendorExtension()); err != nil { 931 return false, err 932 } 933 934 return ok, nil 935 case *openapi_v2.Parameter_NonBodyParameter: 936 switch nb := g.GetNonBodyParameter().Oneof.(type) { 937 case *openapi_v2.NonBodyParameter_HeaderParameterSubSchema: 938 if nok, err := k.ParamProps.FromGnostic(nb.HeaderParameterSubSchema); err != nil { 939 return false, err 940 } else if !nok { 941 ok = false 942 } 943 944 if err := k.SimpleSchema.FromGnostic(nb.HeaderParameterSubSchema); err != nil { 945 return false, err 946 } 947 948 if err := k.CommonValidations.FromGnostic(nb.HeaderParameterSubSchema); err != nil { 949 return false, err 950 } 951 952 if err := k.VendorExtensible.FromGnostic(nb.HeaderParameterSubSchema.GetVendorExtension()); err != nil { 953 return false, err 954 } 955 956 return ok, nil 957 case *openapi_v2.NonBodyParameter_FormDataParameterSubSchema: 958 if nok, err := k.ParamProps.FromGnostic(nb.FormDataParameterSubSchema); err != nil { 959 return false, err 960 } else if !nok { 961 ok = false 962 } 963 964 if err := k.SimpleSchema.FromGnostic(nb.FormDataParameterSubSchema); err != nil { 965 return false, err 966 } 967 968 if err := k.CommonValidations.FromGnostic(nb.FormDataParameterSubSchema); err != nil { 969 return false, err 970 } 971 972 if err := k.VendorExtensible.FromGnostic(nb.FormDataParameterSubSchema.GetVendorExtension()); err != nil { 973 return false, err 974 } 975 976 return ok, nil 977 case *openapi_v2.NonBodyParameter_QueryParameterSubSchema: 978 if nok, err := k.ParamProps.FromGnostic(nb.QueryParameterSubSchema); err != nil { 979 return false, err 980 } else if !nok { 981 ok = false 982 } 983 984 if err := k.SimpleSchema.FromGnostic(nb.QueryParameterSubSchema); err != nil { 985 return false, err 986 } 987 988 if err := k.CommonValidations.FromGnostic(nb.QueryParameterSubSchema); err != nil { 989 return false, err 990 } 991 992 if err := k.VendorExtensible.FromGnostic(nb.QueryParameterSubSchema.GetVendorExtension()); err != nil { 993 return false, err 994 } 995 996 return ok, nil 997 case *openapi_v2.NonBodyParameter_PathParameterSubSchema: 998 if nok, err := k.ParamProps.FromGnostic(nb.PathParameterSubSchema); err != nil { 999 return false, err 1000 } else if !nok { 1001 ok = false 1002 } 1003 1004 if err := k.SimpleSchema.FromGnostic(nb.PathParameterSubSchema); err != nil { 1005 return false, err 1006 } 1007 1008 if err := k.CommonValidations.FromGnostic(nb.PathParameterSubSchema); err != nil { 1009 return false, err 1010 } 1011 1012 if err := k.VendorExtensible.FromGnostic(nb.PathParameterSubSchema.GetVendorExtension()); err != nil { 1013 return false, err 1014 } 1015 1016 return ok, nil 1017 default: 1018 return false, errors.New("unrecognized nonbody type for Parameter") 1019 } 1020 default: 1021 return false, errors.New("unrecognized type for Parameter") 1022 } 1023 } 1024 1025 type GnosticCommonParamProps interface { 1026 GetName() string 1027 GetRequired() bool 1028 GetIn() string 1029 GetDescription() string 1030 } 1031 1032 type GnosticCommonParamPropsBodyParameter interface { 1033 GetSchema() *openapi_v2.Schema 1034 } 1035 1036 type GnosticCommonParamPropsFormData interface { 1037 GetAllowEmptyValue() bool 1038 } 1039 1040 func (k *ParamProps) FromGnostic(g GnosticCommonParamProps) (ok bool, err error) { 1041 ok = true 1042 k.Description = g.GetDescription() 1043 k.In = g.GetIn() 1044 k.Name = g.GetName() 1045 k.Required = g.GetRequired() 1046 1047 if formDataParameter, success := g.(GnosticCommonParamPropsFormData); success { 1048 k.AllowEmptyValue = formDataParameter.GetAllowEmptyValue() 1049 } 1050 1051 if bodyParameter, success := g.(GnosticCommonParamPropsBodyParameter); success { 1052 if bodyParameter.GetSchema() != nil { 1053 k.Schema = &Schema{} 1054 if nok, err := k.Schema.FromGnostic(bodyParameter.GetSchema()); err != nil { 1055 return false, err 1056 } else if !nok { 1057 ok = false 1058 } 1059 } 1060 } 1061 1062 return ok, nil 1063 } 1064 1065 // PB types use a different structure than we do for "refable". For PB, there is 1066 // a wrappign oneof type that could be a ref or the type 1067 func (k *Parameter) FromGnosticParametersItem(g *openapi_v2.ParametersItem) (ok bool, err error) { 1068 if g == nil { 1069 return true, nil 1070 } 1071 1072 ok = true 1073 if ref := g.GetJsonReference(); ref != nil { 1074 k.Description = ref.Description 1075 1076 if err := k.Refable.FromGnostic(ref.XRef); err != nil { 1077 return false, err 1078 } 1079 } else if nok, err := k.FromGnostic(g.GetParameter()); err != nil { 1080 return false, err 1081 } else if !nok { 1082 ok = false 1083 } 1084 1085 return ok, nil 1086 } 1087 1088 // Schema 1089 1090 func (k *Schema) FromGnostic(g *openapi_v2.Schema) (ok bool, err error) { 1091 if g == nil { 1092 return true, nil 1093 } 1094 ok = true 1095 1096 if err := k.VendorExtensible.FromGnostic(g.VendorExtension); err != nil { 1097 return false, err 1098 } 1099 1100 // SwaggerSchemaProps 1101 k.Discriminator = g.Discriminator 1102 k.ReadOnly = g.ReadOnly 1103 k.Description = g.Description 1104 if g.ExternalDocs != nil { 1105 k.ExternalDocs = &ExternalDocumentation{} 1106 if nok, err := k.ExternalDocs.FromGnostic(g.ExternalDocs); err != nil { 1107 return false, err 1108 } else if !nok { 1109 ok = false 1110 } 1111 } 1112 1113 if g.Example != nil { 1114 if err := g.Example.ToRawInfo().Decode(&k.Example); err != nil { 1115 return false, err 1116 } 1117 } 1118 1119 // SchemaProps 1120 if err := k.Ref.FromGnostic(g.XRef); err != nil { 1121 return false, err 1122 } 1123 k.Type = g.Type.GetValue() 1124 k.Format = g.GetFormat() 1125 k.Title = g.GetTitle() 1126 1127 // These below fields are not available in gnostic types, so will never 1128 // be populated. This means roundtrips which make use of these 1129 // (non-official, kube-only) fields will lose information. 1130 // 1131 // Schema.ID is not available in official spec 1132 // Schema.$schema 1133 // Schema.Nullable - in openapiv3, not v2 1134 // Schema.AnyOf - in openapiv3, not v2 1135 // Schema.OneOf - in openapiv3, not v2 1136 // Schema.Not - in openapiv3, not v2 1137 // Schema.PatternProperties - in openapiv3, not v2 1138 // Schema.Dependencies - in openapiv3, not v2 1139 // Schema.AdditionalItems 1140 // Schema.Definitions - not part of spec 1141 // Schema.ExtraProps - gnostic parser rejects any keys it does not recognize 1142 1143 if g.GetDefault() != nil { 1144 if err := g.GetDefault().ToRawInfo().Decode(&k.Default); err != nil { 1145 return false, err 1146 } 1147 } 1148 1149 // These conditionals (!= 0) follow gnostic's logic for ToRawInfo 1150 // The keys in gnostic source are only included if nonzero. 1151 1152 if g.Maximum != 0.0 { 1153 k.Maximum = &g.Maximum 1154 } 1155 1156 if g.Minimum != 0.0 { 1157 k.Minimum = &g.Minimum 1158 } 1159 1160 k.ExclusiveMaximum = g.ExclusiveMaximum 1161 k.ExclusiveMinimum = g.ExclusiveMinimum 1162 1163 if g.MaxLength != 0 { 1164 k.MaxLength = &g.MaxLength 1165 } 1166 1167 if g.MinLength != 0 { 1168 k.MinLength = &g.MinLength 1169 } 1170 1171 k.Pattern = g.GetPattern() 1172 1173 if g.MaxItems != 0 { 1174 k.MaxItems = &g.MaxItems 1175 } 1176 1177 if g.MinItems != 0 { 1178 k.MinItems = &g.MinItems 1179 } 1180 k.UniqueItems = g.UniqueItems 1181 1182 if g.MultipleOf != 0 { 1183 k.MultipleOf = &g.MultipleOf 1184 } 1185 1186 for _, v := range g.GetEnum() { 1187 if v == nil { 1188 continue 1189 } 1190 1191 var convert interface{} 1192 if err := v.ToRawInfo().Decode(&convert); err != nil { 1193 return false, err 1194 } 1195 k.Enum = append(k.Enum, convert) 1196 } 1197 1198 if g.MaxProperties != 0 { 1199 k.MaxProperties = &g.MaxProperties 1200 } 1201 1202 if g.MinProperties != 0 { 1203 k.MinProperties = &g.MinProperties 1204 } 1205 1206 k.Required = g.Required 1207 1208 if g.GetItems() != nil { 1209 k.Items = &SchemaOrArray{} 1210 for _, v := range g.Items.GetSchema() { 1211 if v == nil { 1212 continue 1213 } 1214 1215 schema := Schema{} 1216 if nok, err := schema.FromGnostic(v); err != nil { 1217 return false, err 1218 } else if !nok { 1219 ok = false 1220 } 1221 k.Items.Schemas = append(k.Items.Schemas, schema) 1222 } 1223 1224 if len(k.Items.Schemas) == 1 { 1225 k.Items.Schema = &k.Items.Schemas[0] 1226 k.Items.Schemas = nil 1227 } 1228 } 1229 1230 for i, v := range g.GetAllOf() { 1231 if v == nil { 1232 continue 1233 } 1234 1235 k.AllOf = append(k.AllOf, Schema{}) 1236 if nok, err := k.AllOf[i].FromGnostic(v); err != nil { 1237 return false, err 1238 } else if !nok { 1239 ok = false 1240 } 1241 } 1242 1243 if g.Properties != nil { 1244 k.Properties = make(map[string]Schema) 1245 for _, namedSchema := range g.Properties.AdditionalProperties { 1246 if namedSchema == nil { 1247 continue 1248 } 1249 val := &Schema{} 1250 if nok, err := val.FromGnostic(namedSchema.Value); err != nil { 1251 return false, err 1252 } else if !nok { 1253 ok = false 1254 } 1255 1256 k.Properties[namedSchema.Name] = *val 1257 } 1258 } 1259 1260 if g.AdditionalProperties != nil { 1261 k.AdditionalProperties = &SchemaOrBool{} 1262 if g.AdditionalProperties.GetSchema() == nil { 1263 k.AdditionalProperties.Allows = g.AdditionalProperties.GetBoolean() 1264 } else { 1265 k.AdditionalProperties.Schema = &Schema{} 1266 k.AdditionalProperties.Allows = true 1267 1268 if nok, err := k.AdditionalProperties.Schema.FromGnostic(g.AdditionalProperties.GetSchema()); err != nil { 1269 return false, err 1270 } else if !nok { 1271 ok = false 1272 } 1273 } 1274 } 1275 1276 return ok, nil 1277 } 1278 1279 func (k *Schema) FromGnosticSchemaItem(g *openapi_v2.SchemaItem) (ok bool, err error) { 1280 if g == nil { 1281 return true, nil 1282 } 1283 ok = true 1284 1285 switch p := g.Oneof.(type) { 1286 case *openapi_v2.SchemaItem_FileSchema: 1287 fileSchema := p.FileSchema 1288 1289 if err := k.VendorExtensible.FromGnostic(fileSchema.VendorExtension); err != nil { 1290 return false, err 1291 } 1292 1293 k.Format = fileSchema.Format 1294 k.Title = fileSchema.Title 1295 k.Description = fileSchema.Description 1296 k.Required = fileSchema.Required 1297 k.Type = []string{fileSchema.Type} 1298 k.ReadOnly = fileSchema.ReadOnly 1299 1300 if fileSchema.ExternalDocs != nil { 1301 k.ExternalDocs = &ExternalDocumentation{} 1302 if nok, err := k.ExternalDocs.FromGnostic(fileSchema.ExternalDocs); err != nil { 1303 return false, err 1304 } else if !nok { 1305 ok = false 1306 } 1307 } 1308 1309 if fileSchema.Example != nil { 1310 if err := fileSchema.Example.ToRawInfo().Decode(&k.Example); err != nil { 1311 return false, err 1312 } 1313 } 1314 1315 if fileSchema.Default != nil { 1316 if err := fileSchema.Default.ToRawInfo().Decode(&k.Default); err != nil { 1317 return false, err 1318 } 1319 } 1320 1321 case *openapi_v2.SchemaItem_Schema: 1322 schema := p.Schema 1323 1324 if nok, err := k.FromGnostic(schema); err != nil { 1325 return false, err 1326 } else if !nok { 1327 ok = false 1328 } 1329 default: 1330 return false, errors.New("unrecognized type for SchemaItem") 1331 } 1332 1333 return ok, nil 1334 } 1335 1336 // SecurityDefinitions 1337 1338 func (k SecurityDefinitions) FromGnostic(g *openapi_v2.SecurityDefinitions) error { 1339 for _, v := range g.GetAdditionalProperties() { 1340 if v == nil { 1341 continue 1342 } 1343 secScheme := &SecurityScheme{} 1344 if err := secScheme.FromGnostic(v.Value); err != nil { 1345 return err 1346 } 1347 k[v.Name] = secScheme 1348 } 1349 1350 return nil 1351 } 1352 1353 type GnosticCommonSecurityDefinition interface { 1354 GetType() string 1355 GetDescription() string 1356 } 1357 1358 func (k *SecuritySchemeProps) FromGnostic(g GnosticCommonSecurityDefinition) error { 1359 k.Type = g.GetType() 1360 k.Description = g.GetDescription() 1361 1362 if hasName, success := g.(interface{ GetName() string }); success { 1363 k.Name = hasName.GetName() 1364 } 1365 1366 if hasIn, success := g.(interface{ GetIn() string }); success { 1367 k.In = hasIn.GetIn() 1368 } 1369 1370 if hasFlow, success := g.(interface{ GetFlow() string }); success { 1371 k.Flow = hasFlow.GetFlow() 1372 } 1373 1374 if hasAuthURL, success := g.(interface{ GetAuthorizationUrl() string }); success { 1375 k.AuthorizationURL = hasAuthURL.GetAuthorizationUrl() 1376 } 1377 1378 if hasTokenURL, success := g.(interface{ GetTokenUrl() string }); success { 1379 k.TokenURL = hasTokenURL.GetTokenUrl() 1380 } 1381 1382 if hasScopes, success := g.(interface { 1383 GetScopes() *openapi_v2.Oauth2Scopes 1384 }); success { 1385 scopes := hasScopes.GetScopes() 1386 if scopes != nil { 1387 k.Scopes = make(map[string]string, len(scopes.AdditionalProperties)) 1388 for _, v := range scopes.AdditionalProperties { 1389 if v == nil { 1390 continue 1391 } 1392 1393 k.Scopes[v.Name] = v.Value 1394 } 1395 } 1396 } 1397 1398 return nil 1399 } 1400 1401 func (k *SecurityScheme) FromGnostic(g *openapi_v2.SecurityDefinitionsItem) error { 1402 if g == nil { 1403 return nil 1404 } 1405 1406 switch s := g.Oneof.(type) { 1407 case *openapi_v2.SecurityDefinitionsItem_ApiKeySecurity: 1408 if err := k.SecuritySchemeProps.FromGnostic(s.ApiKeySecurity); err != nil { 1409 return err 1410 } 1411 if err := k.VendorExtensible.FromGnostic(s.ApiKeySecurity.VendorExtension); err != nil { 1412 return err 1413 } 1414 return nil 1415 case *openapi_v2.SecurityDefinitionsItem_BasicAuthenticationSecurity: 1416 if err := k.SecuritySchemeProps.FromGnostic(s.BasicAuthenticationSecurity); err != nil { 1417 return err 1418 } 1419 if err := k.VendorExtensible.FromGnostic(s.BasicAuthenticationSecurity.VendorExtension); err != nil { 1420 return err 1421 } 1422 return nil 1423 case *openapi_v2.SecurityDefinitionsItem_Oauth2AccessCodeSecurity: 1424 if err := k.SecuritySchemeProps.FromGnostic(s.Oauth2AccessCodeSecurity); err != nil { 1425 return err 1426 } 1427 if err := k.VendorExtensible.FromGnostic(s.Oauth2AccessCodeSecurity.VendorExtension); err != nil { 1428 return err 1429 } 1430 return nil 1431 case *openapi_v2.SecurityDefinitionsItem_Oauth2ApplicationSecurity: 1432 if err := k.SecuritySchemeProps.FromGnostic(s.Oauth2ApplicationSecurity); err != nil { 1433 return err 1434 } 1435 if err := k.VendorExtensible.FromGnostic(s.Oauth2ApplicationSecurity.VendorExtension); err != nil { 1436 return err 1437 } 1438 return nil 1439 case *openapi_v2.SecurityDefinitionsItem_Oauth2ImplicitSecurity: 1440 if err := k.SecuritySchemeProps.FromGnostic(s.Oauth2ImplicitSecurity); err != nil { 1441 return err 1442 } 1443 if err := k.VendorExtensible.FromGnostic(s.Oauth2ImplicitSecurity.VendorExtension); err != nil { 1444 return err 1445 } 1446 return nil 1447 case *openapi_v2.SecurityDefinitionsItem_Oauth2PasswordSecurity: 1448 if err := k.SecuritySchemeProps.FromGnostic(s.Oauth2PasswordSecurity); err != nil { 1449 return err 1450 } 1451 if err := k.VendorExtensible.FromGnostic(s.Oauth2PasswordSecurity.VendorExtension); err != nil { 1452 return err 1453 } 1454 return nil 1455 default: 1456 return errors.New("unrecognized SecurityDefinitionsItem") 1457 } 1458 } 1459 1460 // Tag 1461 1462 func (k *Tag) FromGnostic(g *openapi_v2.Tag) (ok bool, err error) { 1463 if g == nil { 1464 return true, nil 1465 } 1466 1467 ok = true 1468 1469 if nok, err := k.TagProps.FromGnostic(g); err != nil { 1470 return false, err 1471 } else if !nok { 1472 ok = false 1473 } 1474 1475 if err := k.VendorExtensible.FromGnostic(g.VendorExtension); err != nil { 1476 return false, err 1477 } 1478 return ok, nil 1479 } 1480 1481 func (k *TagProps) FromGnostic(g *openapi_v2.Tag) (ok bool, err error) { 1482 if g == nil { 1483 return true, nil 1484 } 1485 ok = true 1486 k.Description = g.Description 1487 k.Name = g.Name 1488 1489 if g.ExternalDocs != nil { 1490 k.ExternalDocs = &ExternalDocumentation{} 1491 if nok, err := k.ExternalDocs.FromGnostic(g.ExternalDocs); err != nil { 1492 return false, err 1493 } else if !nok { 1494 ok = false 1495 } 1496 } 1497 1498 return ok, nil 1499 } 1500 1501 // ExternalDocumentation 1502 1503 func (k *ExternalDocumentation) FromGnostic(g *openapi_v2.ExternalDocs) (ok bool, err error) { 1504 if g == nil { 1505 return true, nil 1506 } 1507 ok = true 1508 k.Description = g.Description 1509 k.URL = g.Url 1510 1511 // data loss! g.VendorExtension 1512 if len(g.VendorExtension) != 0 { 1513 ok = false 1514 } 1515 1516 return ok, nil 1517 }