Deliverable for D3.2

server.go 3.8KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117
  1. package node
  2. import (
  3. "context"
  4. "errors"
  5. "log"
  6. "net/http"
  7. "gogs.dyne.org/DECODE/decode-prototype-da/node/api"
  8. "gogs.dyne.org/DECODE/decode-prototype-da/utils"
  9. metadataclient "gogs.dyne.org/DECODE/decode-prototype-da/client/metadata"
  10. storageclient "gogs.dyne.org/DECODE/decode-prototype-da/client/storage"
  11. "github.com/cenkalti/backoff"
  12. restful "github.com/emicklei/go-restful"
  13. restfulspec "github.com/emicklei/go-restful-openapi"
  14. )
  15. type Options struct {
  16. Binding string
  17. SwaggerUIPath string
  18. WebServicesURL string
  19. MetadataServiceAddress string
  20. StorageServiceAddress string
  21. }
  22. func Serve(options Options) error {
  23. metadataClient := metadataclient.NewMetadataApiWithBasePath(options.MetadataServiceAddress)
  24. storageClient := storageclient.NewDataApiWithBasePath(options.StorageServiceAddress)
  25. log.Printf("registering %s with metadata service %s", options.WebServicesURL, options.MetadataServiceAddress)
  26. // TODO : reuse existing token
  27. // If found then update the location by telling the metadata service where I am
  28. // The prototype will just register again
  29. token, err := registerWithMetadataService(metadataClient, options.WebServicesURL)
  30. if err != nil {
  31. return err
  32. }
  33. log.Printf("registered with metadata service : %s", token)
  34. // entitlementStore holds an in-memory cache of entitlement data
  35. entitlementStore := api.NewEntitlementStore()
  36. // metaStore holds additional information about the data stored
  37. metaStore := api.NewMetadataStore()
  38. ctx := context.Background()
  39. deviceManager := NewDeviceManager(ctx, token, metadataClient, storageClient, entitlementStore, metaStore)
  40. deviceManager.Start()
  41. // wire up the json apis
  42. restful.DefaultContainer.Add(api.NewEntitlementService(entitlementStore, metaStore, metadataClient).WebService())
  43. restful.DefaultContainer.Add(api.NewDataService(entitlementStore, storageClient, metaStore).WebService())
  44. restful.DefaultContainer.Add(api.NewDeviceService(ctx, entitlementStore, metaStore, deviceManager.Out()).WebService())
  45. config := restfulspec.Config{
  46. WebServices: restful.RegisteredWebServices(),
  47. WebServicesURL: options.WebServicesURL,
  48. APIPath: "/apidocs.json",
  49. }
  50. restful.DefaultContainer.Add(restfulspec.NewOpenAPIService(config))
  51. // add container filter to enable CORS
  52. cors := restful.CrossOriginResourceSharing{
  53. AllowedHeaders: []string{"Content-Type", "Accept"},
  54. AllowedMethods: []string{"GET", "POST", "PUT"},
  55. }
  56. // install the cors filter
  57. restful.DefaultContainer.Filter(cors.Filter)
  58. // Optionally, you can install the Swagger Service which provides a nice Web UI on your REST API
  59. // You need to download the Swagger HTML5 assets and change the FilePath location in the config below.
  60. // Open http://localhost:8080/apidocs/?url=http://localhost:8080/apidocs.json
  61. http.Handle("/apidocs/", http.StripPrefix("/apidocs/", http.FileServer(http.Dir(options.SwaggerUIPath))))
  62. log.Printf("start listening on %s", options.Binding)
  63. return http.ListenAndServe(options.Binding, nil)
  64. }
  65. // registerWithMetadataService returns the 'announce' token from the metadata service
  66. func registerWithMetadataService(client *metadataclient.MetadataApi, nodePublicAddress string) (string, error) {
  67. // parse the node's public address into its component parts
  68. ok, scheme, host, port := utils.HostAndIpToBits(nodePublicAddress)
  69. if !ok {
  70. return "", errors.New("unable to parse WEBSERVICES_URL or flag -u. Expected value : http[s]://host:port")
  71. }
  72. // register with the metadata service using an exponential backoff
  73. var token string
  74. f := func() error {
  75. log.Printf(".")
  76. response, _, err := client.RegisterLocation(metadataclient.ApiLocationRequest{
  77. IpAddress: host,
  78. Port: int32(port),
  79. Scheme: scheme,
  80. })
  81. if err != nil {
  82. return err
  83. }
  84. token = response.Uid
  85. return nil
  86. }
  87. err := backoff.Retry(f, backoff.NewExponentialBackOff())
  88. return token, err
  89. }