Ce diaporama a bien été signalé.
Nous utilisons votre profil LinkedIn et vos données d’activité pour vous proposer des publicités personnalisées et pertinentes. Vous pouvez changer vos préférences de publicités à tout moment.

Slicing, Dicing, And Linting OpenAPI

2 447 vues

Publié le

Discussion on tools to work with OpenAPI

Publié dans : Technologie
  • A slide was missing fonts, here it is https://twitter.com/lestrrat/status/1066842706570371073
       Répondre 
    Voulez-vous vraiment ?  Oui  Non
    Votre message apparaîtra ici
  • Soyez le premier à aimer ceci

Slicing, Dicing, And Linting OpenAPI

  1. 1. Slicing, Dicing, and Linting OpenAPI Go Conference 2018 Autumn Nov 25, 2018 Daisuke Maki (@lestrrat) / HDE Inc.
  2. 2. • @lestrrat • Perl/Go hacker, author, father • Author of github.com/peco/peco • Organizer for builderscon
  3. 3. tl;dr • github.com/lestrrat-go/openapi • API designed for spec consumer • Safety + Predictability • Tools to work with specs
  4. 4. OpenAPI
  5. 5. Who _Knows_ OpenAPI?
  6. 6. …in its entirety?
  7. 7. Specification for REST services
  8. 8. 「んー僕もopenapiへの恨み言は、 いくらでも出てきそうだ」 「別名、SOAP 2nd generationだからなー 」 What They Are Saying “I think I can go all night with complaints about OpenAPI” “It’s also known as SOAP the Next Generation”
  9. 9. JSON or YAML
  10. 10. OpenAPI v2 OpenAPI v3
  11. 11. OpenAPI v2
  12. 12. OpenAPI v3
  13. 13. “I don’t understand any of it: We’re just pretending to understand OpenAPI"
  14. 14. My Goals • Use Cloud Endpoints (GCP) • Generate gRPC server/client • Generate ES6/Golang REST client • Write definitions in ONE file
  15. 15. Cloud Endpoints
  16. 16. gRPC …because it’s easier to write the server
  17. 17. REST Clients …because the web isn’t ready for gRPC-only
  18. 18. LB openapi endpoints-runtime use config=2018-10-01r1 fetch configuration (sidecar) HTTP2 protobuf protobuf Endpoints config generated gRPC Server generated (stub) HTTP/1.1 JSON payload (REST in Go or ES6) generated Cloud Endpoints register versioned configurations config 2018-10-01r0 config 2018-10-01r1 config 2018-10-04r0 …
  19. 19. Support
  20. 20. “I wish the ecosystem/rest of the world would support v3”
  21. 21. OpenAPI 3.0.2 OAI Specification
  22. 22. OpenAPI 2.0 Google Cloud
  23. 23. hmmm…
  24. 24. !!!! AWS
  25. 25.
  26. 26. (look at the bright side: we’re going to need tools to do v2 → v3)
  27. 27. Prior Art (1)
  28. 28. Gripes
  29. 29. Gripes • Already tried tinkering w/ it • Only generates protobuf • Does NOT check correctness
  30. 30. Prior Art (2)
  31. 31. Gripes • Where’s v3? • How do I generate custom code? • Does NOT check correctness
  32. 32. Where’s v3?
  33. 33. Sooner or later we will need to move to v3
  34. 34. github.com/go-openapi/spec3
  35. 35. hmm…
  36. 36. Ensuring Correctness
  37. 37. Remember?
  38. 38. “I don’t understand any of it: We’re just pretending to understand OpenAPI"
  39. 39. We will make mistakes surely (really horrible schemas)
  40. 40. API should defend us from making mistakes
  41. 41. everything is exported (no defense against invalid values) completely relies on encoding/json (must match how encoding/json works, not necessarily how the user wants to code)
  42. 42. required fields, but can’t tell
  43. 43. _Should_ scream FAIL spec := openapi.Swagger{ Version: “3.0.2”, // Wrong Version // Missing Info
 // Missing Paths }
  44. 44. bonus: Processing paths • Need context to process leaves • e.g. need PathItem.Path while processing Operation objects
  45. 45. paths: /pets: get: description: … operationId: findPets parameters: - name: tags in: query required: false … - name: limit in: query required: false type: integer format: int32 responses: 200: … Sample Spec Paths object PathItem object Operation object Operation object by itself does not know the HTTP verb it’s associated with
  46. 46. func processOperation(verb string, oper Operation) { … } Currying is, meh… • You have to remember what to curry • API signature is no longer standardized across methods
  47. 47. bonus: concurrent updates
  48. 48. _Should_ be safe go func() { spec.Info.Title = “foo” }() go func() { spec.Info.Title = “bar” }() • Exposing always leaves a way for users to screw up
  49. 49. Yak Shaving Time
  50. 50. github.com/lestrrat-go/openapi
  51. 51. github.com/lestrrat-go/openapi • Model: v2 usable, v3 experimental • Generation: gRPC, ES6+flow, Go generation: usable • Lint: usable
  52. 52. General Direction • Don’t allow users to screw up • Provide API to easily consume data • Provide Linting/Code Generation
  53. 53. Protection from Errors
  54. 54. // github.com/lestrrat-go/openapi type OpenAPI = Swagger type Swagger interface { … } spec := Swagger{} // Can’t do it Prohibited Direct Instantiation
  55. 55. spec, err := openapi.NewSwagger([ mandatory params ]). BasePath(…). // Optional params … Build() // Finally, build the object Object Creation via Builder
  56. 56. Object Creation API ✓ Can’t instantiate invalid objects without proper initialization ✓ Required/Optional parameters can be distinguished visually ✓ Automatic validation
  57. 57. err := openapi.MutateSwagger(spec). Info(…). // Any values that needs changing … Apply() // Finally, mutate the object Object Mutation via Mutator
  58. 58. Object Mutation API ✓ Can’t mutate objects into invalid state ✓ Consistency can be controlled across same spec tree
  59. 59. Data Access API
  60. 60. Data Traversal • OpenAPI is a tree structure • You need to traverse through the tree • … and you need to know the context of the current node
  61. 61. Iterating • Giving access to raw slices and maps could mean danger • Allow access to objects, but no mutation
  62. 62. for pIter := paths.Paths(); pIter.Next(); { pathName, pathItem := pIter.Item() for piIter := pathItem.Operations(); piIter.Next(); { oper := piIter.Item() } } Consistent Iterator API
  63. 63. Context • HTTP verb gives context to Operation object • But the data is far from the Operation object • Currying is, meh…
  64. 64. verb := oper.Verb() // NOT part of OpenAPI spec Utility Accessors ✓ Creation/Mutation API ensures consistency with context ✓ No need to curry extra parameters
  65. 65. Linting
  66. 66. Linting is a MUST • OpenAPI is too hard • Programs should tell us of inconsistencies
  67. 67. oalint go get github.com/lestrrat-go/openapi/cmd/oalint ✓ Checks for semantic errors ✓ Formats output
  68. 68. finch% git diff spec … --- a/spec/examples/v2.0/petstore-expanded.yaml +++ b/spec/examples/v2.0/petstore-expanded.yaml @@ -1,4 +1,4 @@ -swagger: "2.0" +swagger: "2.0.1" info: version: 1.0.0 title: Swagger Petstore Sample Spec
  69. 69. finch% ./oalint -file spec/examples/v2.0/petstore- expanded.yaml 2018/11/15 09:24:59 failed to parse input: failed to validate spec: failed to visit Swagger element: swagger field must be "2.0" (got "2.0.1") Catches Errors!
  70. 70. Code Generation (caveat emptor: needs polishing)
  71. 71. oagen protobuf -package myapp -output api.proto -annotate -global-option go_package=pb api.yaml Create gRPC protobuf
  72. 72. oagen rest client -target=go -directory=/path/to/myapp api.yaml Create Go REST Client
  73. 73. oagen restclient -target=es6flow -directory=/path/to/myapp api.yaml Create ES6(+flow) REST Client
  74. 74. # This does not yet exist oagen v2tov3 api.yaml (Future) v2tov3
  75. 75. Recap
  76. 76. LB openapi endpoints-runtime use config=2018-10-01r1 fetch configuration (sidecar) HTTP2 protobuf protobuf Endpoints config generated gRPC Server generated (stub) HTTP/1.1 JSON payload (REST in Go or ES6) generated Cloud Endpoints register versioned configurations config 2018-10-01r0 config 2018-10-01r1 config 2018-10-04r0 …
  77. 77. Current Status • Working gRPC/Go REST client • ES6 client should work • V3 is mostly done • v2tov3 is still in my head
  78. 78. Questions?

×