service.go 3.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131
  1. // Copyright © 2021-2022 Ettore Di Giacinto <[email protected]>
  2. //
  3. // This program is free software; you can redistribute it and/or modify
  4. // it under the terms of the GNU General Public License as published by
  5. // the Free Software Foundation; either version 2 of the License, or
  6. // (at your option) any later version.
  7. //
  8. // This program is distributed in the hope that it will be useful,
  9. // but WITHOUT ANY WARRANTY; without even the implied warranty of
  10. // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  11. // GNU General Public License for more details.
  12. //
  13. // You should have received a copy of the GNU General Public License along
  14. // with this program; if not, see <http://www.gnu.org/licenses/>.
  15. package service
  16. import (
  17. "fmt"
  18. "strings"
  19. "time"
  20. edgeVPNClient "github.com/mudler/edgevpn/api/client"
  21. "github.com/mudler/edgevpn/pkg/protocol"
  22. )
  23. // Client is a wrapper of an edgeVPN client
  24. // with additional metadata and syntax sugar
  25. type Client struct {
  26. serviceID string
  27. *edgeVPNClient.Client
  28. }
  29. // NewClient returns a new client with an associated service ID
  30. func NewClient(serviceID string, c *edgeVPNClient.Client) *Client {
  31. return &Client{serviceID: serviceID, Client: c}
  32. }
  33. // ListItems returns list of items associated with the serviceID and the given suffix
  34. func (c Client) ListItems(serviceID, suffix string) (strs []string, err error) {
  35. buckets, err := c.Client.GetBucketKeys(serviceID)
  36. if err != nil {
  37. return
  38. }
  39. for _, b := range buckets {
  40. if strings.HasSuffix(b, suffix) {
  41. b = strings.ReplaceAll(b, "-"+suffix, "")
  42. strs = append(strs, b)
  43. }
  44. }
  45. return
  46. }
  47. type advertizeMessage struct {
  48. Time time.Time
  49. }
  50. // Advertize advertize the given uuid to the ledger
  51. func (c Client) Advertize(uuid string) error {
  52. return c.Client.Put(c.serviceID, fmt.Sprintf("%s-uuid", uuid), advertizeMessage{Time: time.Now().UTC()})
  53. }
  54. // AdvertizingNodes returns a list of advertizing nodes
  55. func (c Client) AdvertizingNodes() (active []string, err error) {
  56. uuids, err := c.ListItems(c.serviceID, "uuid")
  57. if err != nil {
  58. return
  59. }
  60. for _, u := range uuids {
  61. var d advertizeMessage
  62. res, err := c.Client.GetBucketKey(c.serviceID, fmt.Sprintf("%s-uuid", u))
  63. if err != nil {
  64. continue
  65. }
  66. res.Unmarshal(&d)
  67. if d.Time.Add(15 * time.Minute).After(time.Now().UTC()) {
  68. active = append(active, u)
  69. }
  70. }
  71. return
  72. }
  73. // ActiveNodes returns a list of active nodes
  74. func (c Client) ActiveNodes() (active []string, err error) {
  75. res, err := c.Client.GetBucket(protocol.HealthCheckKey)
  76. if err != nil {
  77. return []string{}, err
  78. }
  79. for u, r := range res {
  80. var s string
  81. r.Unmarshal(&s)
  82. parsed, _ := time.Parse(time.RFC3339, s)
  83. if parsed.Add(15 * time.Minute).After(time.Now().UTC()) {
  84. active = append(active, u)
  85. }
  86. }
  87. return
  88. }
  89. // Clean cleans up the serviceID associated data
  90. func (c Client) Clean() error {
  91. return c.Client.DeleteBucket(c.serviceID)
  92. }
  93. func reverse(ss []string) {
  94. last := len(ss) - 1
  95. for i := 0; i < len(ss)/2; i++ {
  96. ss[i], ss[last-i] = ss[last-i], ss[i]
  97. }
  98. }
  99. // Get returns generic data from the API
  100. // e.g. get("ip", uuid)
  101. func (c Client) Get(args ...string) (string, error) {
  102. reverse(args)
  103. key := strings.Join(args, "-")
  104. var role string
  105. d, err := c.Client.GetBucketKey(c.serviceID, key)
  106. if err == nil {
  107. d.Unmarshal(&role)
  108. }
  109. return role, err
  110. }
  111. // Set generic data to the API
  112. // e.g. set("ip", uuid, "value")
  113. func (c Client) Set(thing, uuid, value string) error {
  114. return c.Client.Put(c.serviceID, fmt.Sprintf("%s-%s", uuid, thing), value)
  115. }