planetscale 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (378) hide show
  1. checksums.yaml +7 -0
  2. data/.github/workflows/ci.yml +24 -0
  3. data/.github/workflows/gem-push.yml +38 -0
  4. data/.github/workflows/licensed.yml +43 -0
  5. data/.gitignore +10 -0
  6. data/.licensed.yml +9 -0
  7. data/.licenses/go/github.com/armon/circbuf.dep.yml +31 -0
  8. data/.licenses/go/github.com/gorilla/mux.dep.yml +41 -0
  9. data/.licenses/go/github.com/hashicorp/go-cleanhttp.dep.yml +375 -0
  10. data/.licenses/go/github.com/mitchellh/go-homedir.dep.yml +32 -0
  11. data/.licenses/go/github.com/pkg/errors.dep.yml +36 -0
  12. data/.licenses/go/github.com/planetscale/planetscale-go/planetscale.dep.yml +160 -0
  13. data/.licenses/go/github.com/planetscale/sql-proxy/proxy.dep.yml +180 -0
  14. data/.licenses/go/go.uber.org/atomic.dep.yml +31 -0
  15. data/.licenses/go/go.uber.org/multierr.dep.yml +30 -0
  16. data/.licenses/go/go.uber.org/zap.dep.yml +30 -0
  17. data/.licenses/go/go.uber.org/zap/buffer.dep.yml +30 -0
  18. data/.licenses/go/go.uber.org/zap/internal/bufferpool.dep.yml +30 -0
  19. data/.licenses/go/go.uber.org/zap/internal/color.dep.yml +30 -0
  20. data/.licenses/go/go.uber.org/zap/internal/exit.dep.yml +31 -0
  21. data/.licenses/go/go.uber.org/zap/zapcore.dep.yml +31 -0
  22. data/.licenses/go/golang.org/x/net/context/ctxhttp.dep.yml +63 -0
  23. data/.licenses/go/golang.org/x/oauth2.dep.yml +44 -0
  24. data/.licenses/go/golang.org/x/oauth2/internal.dep.yml +38 -0
  25. data/.ruby_version +1 -0
  26. data/Gemfile +8 -0
  27. data/LICENSE +201 -0
  28. data/README.md +88 -0
  29. data/Rakefile +10 -0
  30. data/bin/console +15 -0
  31. data/bin/setup +17 -0
  32. data/controller.go +255 -0
  33. data/go.mod +16 -0
  34. data/go.sum +428 -0
  35. data/lib/generators/planetscale/install_generator.rb +58 -0
  36. data/lib/planetscale.rb +137 -0
  37. data/lib/planetscale/version.rb +5 -0
  38. data/planetscale.gemspec +44 -0
  39. data/proxy.go +128 -0
  40. data/vendor/github.com/armon/circbuf/.gitignore +22 -0
  41. data/vendor/github.com/armon/circbuf/LICENSE +20 -0
  42. data/vendor/github.com/armon/circbuf/README.md +28 -0
  43. data/vendor/github.com/armon/circbuf/circbuf.go +92 -0
  44. data/vendor/github.com/armon/circbuf/go.mod +1 -0
  45. data/vendor/github.com/golang/protobuf/AUTHORS +3 -0
  46. data/vendor/github.com/golang/protobuf/CONTRIBUTORS +3 -0
  47. data/vendor/github.com/golang/protobuf/LICENSE +28 -0
  48. data/vendor/github.com/golang/protobuf/proto/buffer.go +324 -0
  49. data/vendor/github.com/golang/protobuf/proto/defaults.go +63 -0
  50. data/vendor/github.com/golang/protobuf/proto/deprecated.go +113 -0
  51. data/vendor/github.com/golang/protobuf/proto/discard.go +58 -0
  52. data/vendor/github.com/golang/protobuf/proto/extensions.go +356 -0
  53. data/vendor/github.com/golang/protobuf/proto/properties.go +306 -0
  54. data/vendor/github.com/golang/protobuf/proto/proto.go +167 -0
  55. data/vendor/github.com/golang/protobuf/proto/registry.go +317 -0
  56. data/vendor/github.com/golang/protobuf/proto/text_decode.go +801 -0
  57. data/vendor/github.com/golang/protobuf/proto/text_encode.go +560 -0
  58. data/vendor/github.com/golang/protobuf/proto/wire.go +78 -0
  59. data/vendor/github.com/golang/protobuf/proto/wrappers.go +34 -0
  60. data/vendor/github.com/gorilla/mux/AUTHORS +8 -0
  61. data/vendor/github.com/gorilla/mux/LICENSE +27 -0
  62. data/vendor/github.com/gorilla/mux/README.md +805 -0
  63. data/vendor/github.com/gorilla/mux/doc.go +306 -0
  64. data/vendor/github.com/gorilla/mux/go.mod +3 -0
  65. data/vendor/github.com/gorilla/mux/middleware.go +74 -0
  66. data/vendor/github.com/gorilla/mux/mux.go +606 -0
  67. data/vendor/github.com/gorilla/mux/regexp.go +388 -0
  68. data/vendor/github.com/gorilla/mux/route.go +736 -0
  69. data/vendor/github.com/gorilla/mux/test_helpers.go +19 -0
  70. data/vendor/github.com/hashicorp/go-cleanhttp/LICENSE +363 -0
  71. data/vendor/github.com/hashicorp/go-cleanhttp/README.md +30 -0
  72. data/vendor/github.com/hashicorp/go-cleanhttp/cleanhttp.go +58 -0
  73. data/vendor/github.com/hashicorp/go-cleanhttp/doc.go +20 -0
  74. data/vendor/github.com/hashicorp/go-cleanhttp/go.mod +3 -0
  75. data/vendor/github.com/hashicorp/go-cleanhttp/handlers.go +48 -0
  76. data/vendor/github.com/mitchellh/go-homedir/LICENSE +21 -0
  77. data/vendor/github.com/mitchellh/go-homedir/README.md +14 -0
  78. data/vendor/github.com/mitchellh/go-homedir/go.mod +1 -0
  79. data/vendor/github.com/mitchellh/go-homedir/homedir.go +167 -0
  80. data/vendor/github.com/pkg/errors/.gitignore +24 -0
  81. data/vendor/github.com/pkg/errors/.travis.yml +10 -0
  82. data/vendor/github.com/pkg/errors/LICENSE +23 -0
  83. data/vendor/github.com/pkg/errors/Makefile +44 -0
  84. data/vendor/github.com/pkg/errors/README.md +59 -0
  85. data/vendor/github.com/pkg/errors/appveyor.yml +32 -0
  86. data/vendor/github.com/pkg/errors/errors.go +288 -0
  87. data/vendor/github.com/pkg/errors/go113.go +38 -0
  88. data/vendor/github.com/pkg/errors/stack.go +177 -0
  89. data/vendor/github.com/planetscale/planetscale-go/planetscale/backups.go +139 -0
  90. data/vendor/github.com/planetscale/planetscale-go/planetscale/branches.go +258 -0
  91. data/vendor/github.com/planetscale/planetscale-go/planetscale/certs.go +142 -0
  92. data/vendor/github.com/planetscale/planetscale-go/planetscale/client.go +305 -0
  93. data/vendor/github.com/planetscale/planetscale-go/planetscale/databases.go +131 -0
  94. data/vendor/github.com/planetscale/planetscale-go/planetscale/deploy_requests.go +368 -0
  95. data/vendor/github.com/planetscale/planetscale-go/planetscale/organizations.go +78 -0
  96. data/vendor/github.com/planetscale/planetscale-go/planetscale/service_tokens.go +163 -0
  97. data/vendor/github.com/planetscale/sql-proxy/proxy/client.go +467 -0
  98. data/vendor/github.com/planetscale/sql-proxy/proxy/tls_cache.go +73 -0
  99. data/vendor/go.uber.org/atomic/.codecov.yml +19 -0
  100. data/vendor/go.uber.org/atomic/.gitignore +12 -0
  101. data/vendor/go.uber.org/atomic/.travis.yml +27 -0
  102. data/vendor/go.uber.org/atomic/CHANGELOG.md +76 -0
  103. data/vendor/go.uber.org/atomic/LICENSE.txt +19 -0
  104. data/vendor/go.uber.org/atomic/Makefile +78 -0
  105. data/vendor/go.uber.org/atomic/README.md +63 -0
  106. data/vendor/go.uber.org/atomic/bool.go +81 -0
  107. data/vendor/go.uber.org/atomic/bool_ext.go +53 -0
  108. data/vendor/go.uber.org/atomic/doc.go +23 -0
  109. data/vendor/go.uber.org/atomic/duration.go +82 -0
  110. data/vendor/go.uber.org/atomic/duration_ext.go +40 -0
  111. data/vendor/go.uber.org/atomic/error.go +51 -0
  112. data/vendor/go.uber.org/atomic/error_ext.go +39 -0
  113. data/vendor/go.uber.org/atomic/float64.go +76 -0
  114. data/vendor/go.uber.org/atomic/float64_ext.go +47 -0
  115. data/vendor/go.uber.org/atomic/gen.go +26 -0
  116. data/vendor/go.uber.org/atomic/go.mod +8 -0
  117. data/vendor/go.uber.org/atomic/go.sum +9 -0
  118. data/vendor/go.uber.org/atomic/int32.go +102 -0
  119. data/vendor/go.uber.org/atomic/int64.go +102 -0
  120. data/vendor/go.uber.org/atomic/nocmp.go +35 -0
  121. data/vendor/go.uber.org/atomic/string.go +54 -0
  122. data/vendor/go.uber.org/atomic/string_ext.go +43 -0
  123. data/vendor/go.uber.org/atomic/uint32.go +102 -0
  124. data/vendor/go.uber.org/atomic/uint64.go +102 -0
  125. data/vendor/go.uber.org/atomic/value.go +31 -0
  126. data/vendor/go.uber.org/multierr/.codecov.yml +15 -0
  127. data/vendor/go.uber.org/multierr/.gitignore +4 -0
  128. data/vendor/go.uber.org/multierr/.travis.yml +23 -0
  129. data/vendor/go.uber.org/multierr/CHANGELOG.md +60 -0
  130. data/vendor/go.uber.org/multierr/LICENSE.txt +19 -0
  131. data/vendor/go.uber.org/multierr/Makefile +42 -0
  132. data/vendor/go.uber.org/multierr/README.md +23 -0
  133. data/vendor/go.uber.org/multierr/error.go +449 -0
  134. data/vendor/go.uber.org/multierr/glide.yaml +8 -0
  135. data/vendor/go.uber.org/multierr/go.mod +8 -0
  136. data/vendor/go.uber.org/multierr/go.sum +11 -0
  137. data/vendor/go.uber.org/multierr/go113.go +52 -0
  138. data/vendor/go.uber.org/zap/.codecov.yml +17 -0
  139. data/vendor/go.uber.org/zap/.gitignore +32 -0
  140. data/vendor/go.uber.org/zap/.readme.tmpl +109 -0
  141. data/vendor/go.uber.org/zap/.travis.yml +23 -0
  142. data/vendor/go.uber.org/zap/CHANGELOG.md +432 -0
  143. data/vendor/go.uber.org/zap/CODE_OF_CONDUCT.md +75 -0
  144. data/vendor/go.uber.org/zap/CONTRIBUTING.md +81 -0
  145. data/vendor/go.uber.org/zap/FAQ.md +156 -0
  146. data/vendor/go.uber.org/zap/LICENSE.txt +19 -0
  147. data/vendor/go.uber.org/zap/Makefile +63 -0
  148. data/vendor/go.uber.org/zap/README.md +134 -0
  149. data/vendor/go.uber.org/zap/array.go +320 -0
  150. data/vendor/go.uber.org/zap/buffer/buffer.go +123 -0
  151. data/vendor/go.uber.org/zap/buffer/pool.go +49 -0
  152. data/vendor/go.uber.org/zap/checklicense.sh +17 -0
  153. data/vendor/go.uber.org/zap/config.go +264 -0
  154. data/vendor/go.uber.org/zap/doc.go +113 -0
  155. data/vendor/go.uber.org/zap/encoder.go +79 -0
  156. data/vendor/go.uber.org/zap/error.go +80 -0
  157. data/vendor/go.uber.org/zap/field.go +539 -0
  158. data/vendor/go.uber.org/zap/flag.go +39 -0
  159. data/vendor/go.uber.org/zap/glide.yaml +34 -0
  160. data/vendor/go.uber.org/zap/global.go +168 -0
  161. data/vendor/go.uber.org/zap/global_go112.go +26 -0
  162. data/vendor/go.uber.org/zap/global_prego112.go +26 -0
  163. data/vendor/go.uber.org/zap/go.mod +13 -0
  164. data/vendor/go.uber.org/zap/go.sum +56 -0
  165. data/vendor/go.uber.org/zap/http_handler.go +81 -0
  166. data/vendor/go.uber.org/zap/internal/bufferpool/bufferpool.go +31 -0
  167. data/vendor/go.uber.org/zap/internal/color/color.go +44 -0
  168. data/vendor/go.uber.org/zap/internal/exit/exit.go +64 -0
  169. data/vendor/go.uber.org/zap/level.go +132 -0
  170. data/vendor/go.uber.org/zap/logger.go +344 -0
  171. data/vendor/go.uber.org/zap/options.go +140 -0
  172. data/vendor/go.uber.org/zap/sink.go +161 -0
  173. data/vendor/go.uber.org/zap/stacktrace.go +85 -0
  174. data/vendor/go.uber.org/zap/sugar.go +304 -0
  175. data/vendor/go.uber.org/zap/time.go +27 -0
  176. data/vendor/go.uber.org/zap/writer.go +99 -0
  177. data/vendor/go.uber.org/zap/zapcore/console_encoder.go +161 -0
  178. data/vendor/go.uber.org/zap/zapcore/core.go +113 -0
  179. data/vendor/go.uber.org/zap/zapcore/doc.go +24 -0
  180. data/vendor/go.uber.org/zap/zapcore/encoder.go +443 -0
  181. data/vendor/go.uber.org/zap/zapcore/entry.go +264 -0
  182. data/vendor/go.uber.org/zap/zapcore/error.go +115 -0
  183. data/vendor/go.uber.org/zap/zapcore/field.go +227 -0
  184. data/vendor/go.uber.org/zap/zapcore/hook.go +68 -0
  185. data/vendor/go.uber.org/zap/zapcore/increase_level.go +66 -0
  186. data/vendor/go.uber.org/zap/zapcore/json_encoder.go +534 -0
  187. data/vendor/go.uber.org/zap/zapcore/level.go +175 -0
  188. data/vendor/go.uber.org/zap/zapcore/level_strings.go +46 -0
  189. data/vendor/go.uber.org/zap/zapcore/marshaler.go +61 -0
  190. data/vendor/go.uber.org/zap/zapcore/memory_encoder.go +179 -0
  191. data/vendor/go.uber.org/zap/zapcore/sampler.go +208 -0
  192. data/vendor/go.uber.org/zap/zapcore/tee.go +81 -0
  193. data/vendor/go.uber.org/zap/zapcore/write_syncer.go +123 -0
  194. data/vendor/golang.org/x/net/AUTHORS +3 -0
  195. data/vendor/golang.org/x/net/CONTRIBUTORS +3 -0
  196. data/vendor/golang.org/x/net/LICENSE +27 -0
  197. data/vendor/golang.org/x/net/PATENTS +22 -0
  198. data/vendor/golang.org/x/net/context/context.go +56 -0
  199. data/vendor/golang.org/x/net/context/ctxhttp/ctxhttp.go +71 -0
  200. data/vendor/golang.org/x/net/context/go17.go +73 -0
  201. data/vendor/golang.org/x/net/context/go19.go +21 -0
  202. data/vendor/golang.org/x/net/context/pre_go17.go +301 -0
  203. data/vendor/golang.org/x/net/context/pre_go19.go +110 -0
  204. data/vendor/golang.org/x/oauth2/.travis.yml +13 -0
  205. data/vendor/golang.org/x/oauth2/AUTHORS +3 -0
  206. data/vendor/golang.org/x/oauth2/CONTRIBUTING.md +26 -0
  207. data/vendor/golang.org/x/oauth2/CONTRIBUTORS +3 -0
  208. data/vendor/golang.org/x/oauth2/LICENSE +27 -0
  209. data/vendor/golang.org/x/oauth2/README.md +36 -0
  210. data/vendor/golang.org/x/oauth2/go.mod +9 -0
  211. data/vendor/golang.org/x/oauth2/go.sum +361 -0
  212. data/vendor/golang.org/x/oauth2/internal/client_appengine.go +14 -0
  213. data/vendor/golang.org/x/oauth2/internal/doc.go +6 -0
  214. data/vendor/golang.org/x/oauth2/internal/oauth2.go +37 -0
  215. data/vendor/golang.org/x/oauth2/internal/token.go +294 -0
  216. data/vendor/golang.org/x/oauth2/internal/transport.go +33 -0
  217. data/vendor/golang.org/x/oauth2/oauth2.go +381 -0
  218. data/vendor/golang.org/x/oauth2/token.go +178 -0
  219. data/vendor/golang.org/x/oauth2/transport.go +89 -0
  220. data/vendor/google.golang.org/appengine/LICENSE +202 -0
  221. data/vendor/google.golang.org/appengine/internal/api.go +678 -0
  222. data/vendor/google.golang.org/appengine/internal/api_classic.go +169 -0
  223. data/vendor/google.golang.org/appengine/internal/api_common.go +123 -0
  224. data/vendor/google.golang.org/appengine/internal/app_id.go +28 -0
  225. data/vendor/google.golang.org/appengine/internal/base/api_base.pb.go +308 -0
  226. data/vendor/google.golang.org/appengine/internal/base/api_base.proto +33 -0
  227. data/vendor/google.golang.org/appengine/internal/datastore/datastore_v3.pb.go +4367 -0
  228. data/vendor/google.golang.org/appengine/internal/datastore/datastore_v3.proto +551 -0
  229. data/vendor/google.golang.org/appengine/internal/identity.go +55 -0
  230. data/vendor/google.golang.org/appengine/internal/identity_classic.go +61 -0
  231. data/vendor/google.golang.org/appengine/internal/identity_flex.go +11 -0
  232. data/vendor/google.golang.org/appengine/internal/identity_vm.go +134 -0
  233. data/vendor/google.golang.org/appengine/internal/internal.go +110 -0
  234. data/vendor/google.golang.org/appengine/internal/log/log_service.pb.go +1313 -0
  235. data/vendor/google.golang.org/appengine/internal/log/log_service.proto +150 -0
  236. data/vendor/google.golang.org/appengine/internal/main.go +16 -0
  237. data/vendor/google.golang.org/appengine/internal/main_common.go +7 -0
  238. data/vendor/google.golang.org/appengine/internal/main_vm.go +69 -0
  239. data/vendor/google.golang.org/appengine/internal/metadata.go +60 -0
  240. data/vendor/google.golang.org/appengine/internal/net.go +56 -0
  241. data/vendor/google.golang.org/appengine/internal/regen.sh +40 -0
  242. data/vendor/google.golang.org/appengine/internal/remote_api/remote_api.pb.go +361 -0
  243. data/vendor/google.golang.org/appengine/internal/remote_api/remote_api.proto +44 -0
  244. data/vendor/google.golang.org/appengine/internal/transaction.go +115 -0
  245. data/vendor/google.golang.org/appengine/internal/urlfetch/urlfetch_service.pb.go +527 -0
  246. data/vendor/google.golang.org/appengine/internal/urlfetch/urlfetch_service.proto +64 -0
  247. data/vendor/google.golang.org/appengine/urlfetch/urlfetch.go +210 -0
  248. data/vendor/google.golang.org/protobuf/AUTHORS +3 -0
  249. data/vendor/google.golang.org/protobuf/CONTRIBUTORS +3 -0
  250. data/vendor/google.golang.org/protobuf/LICENSE +27 -0
  251. data/vendor/google.golang.org/protobuf/PATENTS +22 -0
  252. data/vendor/google.golang.org/protobuf/encoding/prototext/decode.go +773 -0
  253. data/vendor/google.golang.org/protobuf/encoding/prototext/doc.go +7 -0
  254. data/vendor/google.golang.org/protobuf/encoding/prototext/encode.go +371 -0
  255. data/vendor/google.golang.org/protobuf/encoding/protowire/wire.go +538 -0
  256. data/vendor/google.golang.org/protobuf/internal/descfmt/stringer.go +318 -0
  257. data/vendor/google.golang.org/protobuf/internal/descopts/options.go +29 -0
  258. data/vendor/google.golang.org/protobuf/internal/detrand/rand.go +69 -0
  259. data/vendor/google.golang.org/protobuf/internal/encoding/defval/default.go +213 -0
  260. data/vendor/google.golang.org/protobuf/internal/encoding/messageset/messageset.go +241 -0
  261. data/vendor/google.golang.org/protobuf/internal/encoding/tag/tag.go +207 -0
  262. data/vendor/google.golang.org/protobuf/internal/encoding/text/decode.go +665 -0
  263. data/vendor/google.golang.org/protobuf/internal/encoding/text/decode_number.go +190 -0
  264. data/vendor/google.golang.org/protobuf/internal/encoding/text/decode_string.go +161 -0
  265. data/vendor/google.golang.org/protobuf/internal/encoding/text/decode_token.go +373 -0
  266. data/vendor/google.golang.org/protobuf/internal/encoding/text/doc.go +29 -0
  267. data/vendor/google.golang.org/protobuf/internal/encoding/text/encode.go +265 -0
  268. data/vendor/google.golang.org/protobuf/internal/errors/errors.go +89 -0
  269. data/vendor/google.golang.org/protobuf/internal/errors/is_go112.go +39 -0
  270. data/vendor/google.golang.org/protobuf/internal/errors/is_go113.go +12 -0
  271. data/vendor/google.golang.org/protobuf/internal/filedesc/build.go +158 -0
  272. data/vendor/google.golang.org/protobuf/internal/filedesc/desc.go +631 -0
  273. data/vendor/google.golang.org/protobuf/internal/filedesc/desc_init.go +471 -0
  274. data/vendor/google.golang.org/protobuf/internal/filedesc/desc_lazy.go +704 -0
  275. data/vendor/google.golang.org/protobuf/internal/filedesc/desc_list.go +450 -0
  276. data/vendor/google.golang.org/protobuf/internal/filedesc/desc_list_gen.go +356 -0
  277. data/vendor/google.golang.org/protobuf/internal/filedesc/placeholder.go +107 -0
  278. data/vendor/google.golang.org/protobuf/internal/filetype/build.go +297 -0
  279. data/vendor/google.golang.org/protobuf/internal/flags/flags.go +24 -0
  280. data/vendor/google.golang.org/protobuf/internal/flags/proto_legacy_disable.go +9 -0
  281. data/vendor/google.golang.org/protobuf/internal/flags/proto_legacy_enable.go +9 -0
  282. data/vendor/google.golang.org/protobuf/internal/genid/any_gen.go +34 -0
  283. data/vendor/google.golang.org/protobuf/internal/genid/api_gen.go +106 -0
  284. data/vendor/google.golang.org/protobuf/internal/genid/descriptor_gen.go +829 -0
  285. data/vendor/google.golang.org/protobuf/internal/genid/doc.go +11 -0
  286. data/vendor/google.golang.org/protobuf/internal/genid/duration_gen.go +34 -0
  287. data/vendor/google.golang.org/protobuf/internal/genid/empty_gen.go +19 -0
  288. data/vendor/google.golang.org/protobuf/internal/genid/field_mask_gen.go +31 -0
  289. data/vendor/google.golang.org/protobuf/internal/genid/goname.go +25 -0
  290. data/vendor/google.golang.org/protobuf/internal/genid/map_entry.go +16 -0
  291. data/vendor/google.golang.org/protobuf/internal/genid/source_context_gen.go +31 -0
  292. data/vendor/google.golang.org/protobuf/internal/genid/struct_gen.go +116 -0
  293. data/vendor/google.golang.org/protobuf/internal/genid/timestamp_gen.go +34 -0
  294. data/vendor/google.golang.org/protobuf/internal/genid/type_gen.go +184 -0
  295. data/vendor/google.golang.org/protobuf/internal/genid/wrappers.go +13 -0
  296. data/vendor/google.golang.org/protobuf/internal/genid/wrappers_gen.go +175 -0
  297. data/vendor/google.golang.org/protobuf/internal/impl/api_export.go +177 -0
  298. data/vendor/google.golang.org/protobuf/internal/impl/checkinit.go +141 -0
  299. data/vendor/google.golang.org/protobuf/internal/impl/codec_extension.go +223 -0
  300. data/vendor/google.golang.org/protobuf/internal/impl/codec_field.go +830 -0
  301. data/vendor/google.golang.org/protobuf/internal/impl/codec_gen.go +5637 -0
  302. data/vendor/google.golang.org/protobuf/internal/impl/codec_map.go +388 -0
  303. data/vendor/google.golang.org/protobuf/internal/impl/codec_map_go111.go +37 -0
  304. data/vendor/google.golang.org/protobuf/internal/impl/codec_map_go112.go +11 -0
  305. data/vendor/google.golang.org/protobuf/internal/impl/codec_message.go +217 -0
  306. data/vendor/google.golang.org/protobuf/internal/impl/codec_messageset.go +123 -0
  307. data/vendor/google.golang.org/protobuf/internal/impl/codec_reflect.go +209 -0
  308. data/vendor/google.golang.org/protobuf/internal/impl/codec_tables.go +557 -0
  309. data/vendor/google.golang.org/protobuf/internal/impl/codec_unsafe.go +17 -0
  310. data/vendor/google.golang.org/protobuf/internal/impl/convert.go +496 -0
  311. data/vendor/google.golang.org/protobuf/internal/impl/convert_list.go +141 -0
  312. data/vendor/google.golang.org/protobuf/internal/impl/convert_map.go +121 -0
  313. data/vendor/google.golang.org/protobuf/internal/impl/decode.go +276 -0
  314. data/vendor/google.golang.org/protobuf/internal/impl/encode.go +201 -0
  315. data/vendor/google.golang.org/protobuf/internal/impl/enum.go +21 -0
  316. data/vendor/google.golang.org/protobuf/internal/impl/extension.go +156 -0
  317. data/vendor/google.golang.org/protobuf/internal/impl/legacy_enum.go +219 -0
  318. data/vendor/google.golang.org/protobuf/internal/impl/legacy_export.go +92 -0
  319. data/vendor/google.golang.org/protobuf/internal/impl/legacy_extension.go +176 -0
  320. data/vendor/google.golang.org/protobuf/internal/impl/legacy_file.go +81 -0
  321. data/vendor/google.golang.org/protobuf/internal/impl/legacy_message.go +558 -0
  322. data/vendor/google.golang.org/protobuf/internal/impl/merge.go +176 -0
  323. data/vendor/google.golang.org/protobuf/internal/impl/merge_gen.go +209 -0
  324. data/vendor/google.golang.org/protobuf/internal/impl/message.go +276 -0
  325. data/vendor/google.golang.org/protobuf/internal/impl/message_reflect.go +465 -0
  326. data/vendor/google.golang.org/protobuf/internal/impl/message_reflect_field.go +543 -0
  327. data/vendor/google.golang.org/protobuf/internal/impl/message_reflect_gen.go +249 -0
  328. data/vendor/google.golang.org/protobuf/internal/impl/pointer_reflect.go +178 -0
  329. data/vendor/google.golang.org/protobuf/internal/impl/pointer_unsafe.go +174 -0
  330. data/vendor/google.golang.org/protobuf/internal/impl/validate.go +576 -0
  331. data/vendor/google.golang.org/protobuf/internal/impl/weak.go +74 -0
  332. data/vendor/google.golang.org/protobuf/internal/order/order.go +89 -0
  333. data/vendor/google.golang.org/protobuf/internal/order/range.go +115 -0
  334. data/vendor/google.golang.org/protobuf/internal/pragma/pragma.go +29 -0
  335. data/vendor/google.golang.org/protobuf/internal/set/ints.go +58 -0
  336. data/vendor/google.golang.org/protobuf/internal/strs/strings.go +196 -0
  337. data/vendor/google.golang.org/protobuf/internal/strs/strings_pure.go +27 -0
  338. data/vendor/google.golang.org/protobuf/internal/strs/strings_unsafe.go +94 -0
  339. data/vendor/google.golang.org/protobuf/internal/version/version.go +79 -0
  340. data/vendor/google.golang.org/protobuf/proto/checkinit.go +71 -0
  341. data/vendor/google.golang.org/protobuf/proto/decode.go +278 -0
  342. data/vendor/google.golang.org/protobuf/proto/decode_gen.go +603 -0
  343. data/vendor/google.golang.org/protobuf/proto/doc.go +94 -0
  344. data/vendor/google.golang.org/protobuf/proto/encode.go +319 -0
  345. data/vendor/google.golang.org/protobuf/proto/encode_gen.go +97 -0
  346. data/vendor/google.golang.org/protobuf/proto/equal.go +167 -0
  347. data/vendor/google.golang.org/protobuf/proto/extension.go +92 -0
  348. data/vendor/google.golang.org/protobuf/proto/merge.go +139 -0
  349. data/vendor/google.golang.org/protobuf/proto/messageset.go +93 -0
  350. data/vendor/google.golang.org/protobuf/proto/proto.go +43 -0
  351. data/vendor/google.golang.org/protobuf/proto/proto_methods.go +19 -0
  352. data/vendor/google.golang.org/protobuf/proto/proto_reflect.go +19 -0
  353. data/vendor/google.golang.org/protobuf/proto/reset.go +43 -0
  354. data/vendor/google.golang.org/protobuf/proto/size.go +97 -0
  355. data/vendor/google.golang.org/protobuf/proto/size_gen.go +55 -0
  356. data/vendor/google.golang.org/protobuf/proto/wrappers.go +29 -0
  357. data/vendor/google.golang.org/protobuf/reflect/protodesc/desc.go +276 -0
  358. data/vendor/google.golang.org/protobuf/reflect/protodesc/desc_init.go +248 -0
  359. data/vendor/google.golang.org/protobuf/reflect/protodesc/desc_resolve.go +286 -0
  360. data/vendor/google.golang.org/protobuf/reflect/protodesc/desc_validate.go +374 -0
  361. data/vendor/google.golang.org/protobuf/reflect/protodesc/proto.go +252 -0
  362. data/vendor/google.golang.org/protobuf/reflect/protoreflect/methods.go +77 -0
  363. data/vendor/google.golang.org/protobuf/reflect/protoreflect/proto.go +504 -0
  364. data/vendor/google.golang.org/protobuf/reflect/protoreflect/source.go +128 -0
  365. data/vendor/google.golang.org/protobuf/reflect/protoreflect/source_gen.go +461 -0
  366. data/vendor/google.golang.org/protobuf/reflect/protoreflect/type.go +665 -0
  367. data/vendor/google.golang.org/protobuf/reflect/protoreflect/value.go +285 -0
  368. data/vendor/google.golang.org/protobuf/reflect/protoreflect/value_pure.go +59 -0
  369. data/vendor/google.golang.org/protobuf/reflect/protoreflect/value_union.go +411 -0
  370. data/vendor/google.golang.org/protobuf/reflect/protoreflect/value_unsafe.go +98 -0
  371. data/vendor/google.golang.org/protobuf/reflect/protoregistry/registry.go +869 -0
  372. data/vendor/google.golang.org/protobuf/runtime/protoiface/legacy.go +15 -0
  373. data/vendor/google.golang.org/protobuf/runtime/protoiface/methods.go +167 -0
  374. data/vendor/google.golang.org/protobuf/runtime/protoimpl/impl.go +44 -0
  375. data/vendor/google.golang.org/protobuf/runtime/protoimpl/version.go +56 -0
  376. data/vendor/google.golang.org/protobuf/types/descriptorpb/descriptor.pb.go +4039 -0
  377. data/vendor/modules.txt +79 -0
  378. metadata +495 -0
@@ -0,0 +1,78 @@
1
+ package planetscale
2
+
3
+ import (
4
+ "context"
5
+ "fmt"
6
+ "net/http"
7
+ "time"
8
+
9
+ "github.com/pkg/errors"
10
+ )
11
+
12
+ const organizationsAPIPath = "v1/organizations"
13
+
14
+ // GetOrganizationRequest encapsulates the request for getting a single
15
+ // organization.
16
+ type GetOrganizationRequest struct {
17
+ Organization string
18
+ }
19
+
20
+ // OrganizationsService is an interface for communicating with the PlanetScale
21
+ // Organizations API endpoints.
22
+ type OrganizationsService interface {
23
+ Get(context.Context, *GetOrganizationRequest) (*Organization, error)
24
+ List(context.Context) ([]*Organization, error)
25
+ }
26
+
27
+ // Organization represents a PlanetScale organization.
28
+ type Organization struct {
29
+ Name string `json:"name"`
30
+ CreatedAt time.Time `json:"created_at"`
31
+ UpdatedAt time.Time `json:"updated_at"`
32
+ }
33
+
34
+ type organizationsResponse struct {
35
+ Organizations []*Organization `json:"data"`
36
+ }
37
+
38
+ type organizationsService struct {
39
+ client *Client
40
+ }
41
+
42
+ var _ OrganizationsService = &organizationsService{}
43
+
44
+ func NewOrganizationsService(client *Client) *organizationsService {
45
+ return &organizationsService{
46
+ client: client,
47
+ }
48
+ }
49
+
50
+ // Get fetches a single organization by name.
51
+ func (o *organizationsService) Get(ctx context.Context, getReq *GetOrganizationRequest) (*Organization, error) {
52
+ req, err := o.client.newRequest(http.MethodGet, fmt.Sprintf("%s/%s", organizationsAPIPath, getReq.Organization), nil)
53
+ if err != nil {
54
+ return nil, errors.Wrap(err, "error creating request for get organization")
55
+ }
56
+
57
+ org := &Organization{}
58
+ if err := o.client.do(ctx, req, &org); err != nil {
59
+ return nil, err
60
+ }
61
+
62
+ return org, nil
63
+ }
64
+
65
+ // List returns all the organizations for a user.
66
+ func (o *organizationsService) List(ctx context.Context) ([]*Organization, error) {
67
+ req, err := o.client.newRequest(http.MethodGet, organizationsAPIPath, nil)
68
+ if err != nil {
69
+ return nil, errors.Wrap(err, "error creating request for list organization")
70
+ }
71
+
72
+ orgResponse := &organizationsResponse{}
73
+ if err := o.client.do(ctx, req, &orgResponse); err != nil {
74
+ return nil, err
75
+ }
76
+
77
+ return orgResponse.Organizations, nil
78
+ }
@@ -0,0 +1,163 @@
1
+ package planetscale
2
+
3
+ import (
4
+ "context"
5
+ "fmt"
6
+ "net/http"
7
+ )
8
+
9
+ var _ ServiceTokenService = &serviceTokenService{}
10
+
11
+ // ServiceTokenService is an interface for communicating with the PlanetScale
12
+ // Service Token API.
13
+ type ServiceTokenService interface {
14
+ Create(context.Context, *CreateServiceTokenRequest) (*ServiceToken, error)
15
+ List(context.Context, *ListServiceTokensRequest) ([]*ServiceToken, error)
16
+ Delete(context.Context, *DeleteServiceTokenRequest) error
17
+ GetAccess(context.Context, *GetServiceTokenAccessRequest) ([]*ServiceTokenAccess, error)
18
+ AddAccess(context.Context, *AddServiceTokenAccessRequest) ([]*ServiceTokenAccess, error)
19
+ DeleteAccess(context.Context, *DeleteServiceTokenAccessRequest) error
20
+ }
21
+
22
+ type serviceTokenService struct {
23
+ client *Client
24
+ }
25
+
26
+ func (s *serviceTokenService) Create(ctx context.Context, createReq *CreateServiceTokenRequest) (*ServiceToken, error) {
27
+ req, err := s.client.newRequest(http.MethodPost, serviceTokensAPIPath(createReq.Organization), nil)
28
+ if err != nil {
29
+ return nil, err
30
+ }
31
+
32
+ st := &ServiceToken{}
33
+ if err := s.client.do(ctx, req, &st); err != nil {
34
+ return nil, err
35
+ }
36
+
37
+ return st, nil
38
+ }
39
+
40
+ func (s *serviceTokenService) List(ctx context.Context, listReq *ListServiceTokensRequest) ([]*ServiceToken, error) {
41
+ req, err := s.client.newRequest(http.MethodGet, serviceTokensAPIPath(listReq.Organization), nil)
42
+ if err != nil {
43
+ return nil, err
44
+ }
45
+
46
+ tokenListResponse := serviceTokensResponse{}
47
+ if err := s.client.do(ctx, req, &tokenListResponse); err != nil {
48
+ return nil, err
49
+ }
50
+
51
+ return tokenListResponse.ServiceTokens, nil
52
+ }
53
+
54
+ func (s *serviceTokenService) Delete(ctx context.Context, delReq *DeleteServiceTokenRequest) error {
55
+ req, err := s.client.newRequest(http.MethodDelete, serviceTokenAPIPath(delReq.Organization, delReq.ID), nil)
56
+ if err != nil {
57
+ return err
58
+ }
59
+
60
+ err = s.client.do(ctx, req, nil)
61
+ return err
62
+ }
63
+
64
+ func (s *serviceTokenService) GetAccess(ctx context.Context, accessReq *GetServiceTokenAccessRequest) ([]*ServiceTokenAccess, error) {
65
+ req, err := s.client.newRequest(http.MethodGet, serviceTokenAccessAPIPath(accessReq.Organization, accessReq.ID), nil)
66
+ if err != nil {
67
+ return nil, err
68
+ }
69
+
70
+ tokenAccess := serviceTokenAccessResponse{}
71
+ if err := s.client.do(ctx, req, &tokenAccess); err != nil {
72
+ return nil, err
73
+ }
74
+ return tokenAccess.ServiceTokenAccesses, nil
75
+ }
76
+
77
+ func (s *serviceTokenService) AddAccess(ctx context.Context, addReq *AddServiceTokenAccessRequest) ([]*ServiceTokenAccess, error) {
78
+ req, err := s.client.newRequest(http.MethodPost, serviceTokenAccessAPIPath(addReq.Organization, addReq.ID), addReq)
79
+ if err != nil {
80
+ return nil, err
81
+ }
82
+
83
+ tokenAccess := serviceTokenAccessResponse{}
84
+ if err := s.client.do(ctx, req, &tokenAccess); err != nil {
85
+ return nil, err
86
+ }
87
+ return tokenAccess.ServiceTokenAccesses, nil
88
+ }
89
+
90
+ func (s *serviceTokenService) DeleteAccess(ctx context.Context, delReq *DeleteServiceTokenAccessRequest) error {
91
+ req, err := s.client.newRequest(http.MethodDelete, serviceTokenAccessAPIPath(delReq.Organization, delReq.ID), delReq)
92
+ if err != nil {
93
+ return err
94
+ }
95
+
96
+ err = s.client.do(ctx, req, nil)
97
+ return err
98
+ }
99
+
100
+ type CreateServiceTokenRequest struct {
101
+ Organization string `json:"-"`
102
+ }
103
+
104
+ type DeleteServiceTokenRequest struct {
105
+ Organization string `json:"-"`
106
+ ID string `json:"-"`
107
+ }
108
+
109
+ type ListServiceTokensRequest struct {
110
+ Organization string `json:"-"`
111
+ }
112
+
113
+ type GetServiceTokenAccessRequest struct {
114
+ Organization string `json:"-"`
115
+ ID string `json:"-"`
116
+ }
117
+
118
+ type AddServiceTokenAccessRequest struct {
119
+ Organization string `json:"-"`
120
+ ID string `json:"-"`
121
+ Database string `json:"database"`
122
+ Accesses []string `json:"access"`
123
+ }
124
+
125
+ type DeleteServiceTokenAccessRequest struct {
126
+ Organization string `json:"-"`
127
+ ID string `json:"-"`
128
+ Database string `json:"database"`
129
+ Accesses []string `json:"access"`
130
+ }
131
+
132
+ type ServiceToken struct {
133
+ ID string `json:"id"`
134
+ Type string `json:"type"`
135
+ Token string `json:"token"`
136
+ }
137
+
138
+ type serviceTokensResponse struct {
139
+ ServiceTokens []*ServiceToken `json:"data"`
140
+ }
141
+
142
+ type ServiceTokenAccess struct {
143
+ ID int `json:"id"`
144
+ Access string `json:"access"`
145
+ Type string `json:"type"`
146
+ Resource Database `json:"resource"`
147
+ }
148
+
149
+ type serviceTokenAccessResponse struct {
150
+ ServiceTokenAccesses []*ServiceTokenAccess `json:"data"`
151
+ }
152
+
153
+ func serviceTokenAccessAPIPath(org, id string) string {
154
+ return fmt.Sprintf("%s/%s/access", serviceTokensAPIPath(org), id)
155
+ }
156
+
157
+ func serviceTokensAPIPath(org string) string {
158
+ return fmt.Sprintf("v1/organizations/%s/service-tokens", org)
159
+ }
160
+
161
+ func serviceTokenAPIPath(org, id string) string {
162
+ return fmt.Sprintf("%s/%s", serviceTokensAPIPath(org), id)
163
+ }
@@ -0,0 +1,467 @@
1
+ package proxy
2
+
3
+ import (
4
+ "context"
5
+ "crypto/tls"
6
+ "crypto/x509"
7
+ "errors"
8
+ "fmt"
9
+ "io"
10
+ "net"
11
+ "os"
12
+ "strings"
13
+ "sync/atomic"
14
+ "time"
15
+
16
+ "go.uber.org/zap"
17
+ )
18
+
19
+ const (
20
+ keepAlivePeriod = time.Minute
21
+ )
22
+
23
+ // Cert represents the client certificate key pair in the root certiciate
24
+ // authority that the client uses to verify server certificates.
25
+
26
+ type Cert struct {
27
+ ClientCert tls.Certificate
28
+ CACert *x509.Certificate
29
+ RemoteAddr string
30
+ Ports RemotePorts
31
+ }
32
+
33
+ type RemotePorts struct {
34
+ Proxy int
35
+ MySQL int
36
+ }
37
+
38
+ // CertSource is used
39
+ type CertSource interface {
40
+ // Cert returns the required certs needed to establish a TLS connection
41
+ // from the client to the server.
42
+ Cert(ctx context.Context, org, db, branch string) (*Cert, error)
43
+ }
44
+
45
+ // Client is responsible for listening to unsecured connections over a TCP
46
+ // localhost port and tunneling them securely over a TLS connection to a remote
47
+ // database instance defined by its PlanetScale unique branch identifier.
48
+ type Client struct {
49
+ // connectionsCounter is used to enforce the optional maxConnections limit
50
+ // NOTE: don't move this field, as we need to make sure the fields are
51
+ // 64-bit aligned
52
+ connectionsCounter uint64
53
+
54
+ remoteAddr string
55
+ localAddr string
56
+ instance string
57
+ maxConnections uint64
58
+ certSource CertSource
59
+
60
+ log *zap.Logger
61
+
62
+ // configCache contains the TLS certificate chache for each indiviual
63
+ // database
64
+ configCache *tlsCache
65
+
66
+ listener net.Listener
67
+ // done is closed after a successfull net.Listen bind.
68
+ done chan struct{}
69
+ }
70
+
71
+ // Options are the options for creating a new Client.
72
+ type Options struct {
73
+ // RemoteAddr defines the server address to tunnel local connections. By
74
+ // default we connect to the remote address given by the CertSource. This
75
+ // option can be used to over write it.
76
+ RemoteAddr string
77
+
78
+ // LocalAddr defines the address to listen for new connection
79
+ LocalAddr string
80
+
81
+ // Instance defines the remote DB instance to proxy new connection
82
+ Instance string
83
+
84
+ // MaxConnections is the maximum number of connections to establish
85
+ // before refusing new connections. 0 means no limit.
86
+ MaxConnections uint64
87
+
88
+ // CertSource defines the certificate source to obtain the required TLS
89
+ // certificates for the client and the remote address of the server to
90
+ // connect.
91
+ CertSource CertSource
92
+
93
+ // Logger defines which zap.Logger to use. Use it to override the default
94
+ // Development logger . Useful for tests.
95
+ Logger *zap.Logger
96
+ }
97
+
98
+ // NewClient creates a new proxy client instance
99
+ func NewClient(opts Options) (*Client, error) {
100
+ c := &Client{
101
+ certSource: opts.CertSource,
102
+ localAddr: opts.LocalAddr,
103
+ remoteAddr: opts.RemoteAddr,
104
+ instance: opts.Instance,
105
+ configCache: newtlsCache(),
106
+ done: make(chan struct{}),
107
+ }
108
+
109
+ if opts.Logger != nil {
110
+ c.log = opts.Logger
111
+ } else {
112
+ logger, err := zap.NewDevelopment(
113
+ zap.Fields(zap.String("app", "sql-proxy-client")),
114
+ )
115
+ if err != nil {
116
+ return nil, err
117
+ }
118
+ zap.ReplaceGlobals(logger)
119
+ c.log = logger
120
+ }
121
+
122
+ // cache the certs for the given instance(s)
123
+ _, _, err := c.clientCerts(context.Background(), opts.Instance)
124
+ if err != nil {
125
+ c.log.Error("couldn't retrieve TLS certificate for the client", zap.Error(err))
126
+ }
127
+
128
+ return c, nil
129
+ }
130
+
131
+ // Conn represents a connection from a client to a specific instance.
132
+ type Conn struct {
133
+ Instance string
134
+ Conn net.Conn
135
+ }
136
+
137
+ // Run runs the proxy. It listens to the configured localhost address and
138
+ // proxies the connection over a TLS tunnel to the remote DB instance.
139
+ func (c *Client) Run(ctx context.Context) error {
140
+ c.log.Info("ready for new connections")
141
+ l, err := c.getListener()
142
+ if err != nil {
143
+ return fmt.Errorf("error net.Listen: %w", err)
144
+ }
145
+ defer c.log.Sync() // nolint: errcheck
146
+
147
+ c.listener = l
148
+ close(c.done)
149
+
150
+ return c.run(ctx, l)
151
+ }
152
+
153
+ // LocalAddr returns the address of the local listener. This is by default
154
+ // blocking and will only return if the proxy is invoked with the Run() method.
155
+ func (c *Client) LocalAddr() (net.Addr, error) {
156
+ <-c.done
157
+
158
+ if c.listener == nil {
159
+ return nil, errors.New("listener is not set")
160
+
161
+ }
162
+ return c.listener.Addr(), nil
163
+ }
164
+
165
+ func (c *Client) getListener() (net.Listener, error) {
166
+ if strings.HasPrefix(c.localAddr, "unix://") {
167
+ p := strings.TrimPrefix(c.localAddr, "unix://")
168
+ if err := os.Remove(p); err != nil && !os.IsNotExist(err) {
169
+ return nil, fmt.Errorf("failed to remove unix domain socket file %s, error: %s", p, err)
170
+ }
171
+ return net.Listen("unix", p)
172
+ }
173
+ return net.Listen("tcp", c.localAddr)
174
+ }
175
+
176
+ // run is an internal function for testing the Client proxy event loop for
177
+ // handling TCP connections
178
+ func (c *Client) run(ctx context.Context, l net.Listener) error {
179
+ connSrc := make(chan Conn, 1)
180
+ go func() {
181
+ if err := c.listen(l, connSrc); err != nil {
182
+ c.log.Error("listen to local address", zap.Error(err))
183
+ }
184
+ }()
185
+
186
+ for {
187
+ select {
188
+ case <-ctx.Done():
189
+ termTimeout := time.Second * 1
190
+ c.log.Info("received context cancellation, waiting until timeout",
191
+ zap.Duration("timeout", termTimeout))
192
+
193
+ err := c.Shutdown(termTimeout)
194
+ if err != nil {
195
+ return fmt.Errorf("error during shutdown: %v", err)
196
+ }
197
+ return nil
198
+ case conn := <-connSrc:
199
+ go func(lc Conn) {
200
+ // TODO(fatih): detach context from parent
201
+ err := c.handleConn(ctx, lc.Conn, lc.Instance)
202
+ if err != nil {
203
+ c.log.Error("error proxying conns", zap.Error(err))
204
+ }
205
+ }(conn)
206
+ }
207
+ }
208
+ }
209
+
210
+ // listen listens to the client's localAddres and sends each incoming
211
+ // connections to the given connSrc channel.
212
+ func (c *Client) listen(l net.Listener, connSrc chan<- Conn) error {
213
+ c.log.Info("listening remote DB instance",
214
+ zap.String("local_addr", c.localAddr),
215
+ zap.String("instance", c.instance),
216
+ )
217
+
218
+ for {
219
+ start := time.Now()
220
+ conn, err := l.Accept()
221
+ if err != nil {
222
+ if nerr, ok := err.(net.Error); ok && nerr.Temporary() {
223
+ d := 10*time.Millisecond - time.Since(start)
224
+ if d > 0 {
225
+ time.Sleep(d)
226
+ }
227
+ continue
228
+ }
229
+ l.Close()
230
+
231
+ return fmt.Errorf("error in accept for on %v: %w", c.localAddr, err)
232
+ }
233
+
234
+ c.log.Info("new connection", zap.String("conn_addr", l.Addr().String()))
235
+
236
+ switch clientConn := conn.(type) {
237
+ case *net.TCPConn:
238
+ clientConn.SetKeepAlive(true) //nolint: errcheck
239
+ clientConn.SetKeepAlivePeriod(1 * time.Minute) //nolint: errcheck
240
+ }
241
+
242
+ connSrc <- Conn{
243
+ Conn: conn,
244
+ Instance: c.instance,
245
+ }
246
+ }
247
+ }
248
+
249
+ func (c *Client) handleConn(ctx context.Context, conn net.Conn, instance string) error {
250
+ log := c.log.With(zap.String("instance", instance))
251
+ active := atomic.AddUint64(&c.connectionsCounter, 1)
252
+
253
+ // Deferred decrement of ConnectionsCounter upon connection closing
254
+ defer atomic.AddUint64(&c.connectionsCounter, ^uint64(0))
255
+
256
+ if c.maxConnections > 0 && active > c.maxConnections {
257
+ conn.Close()
258
+ return fmt.Errorf("too many open connections (max %d)", c.maxConnections)
259
+ }
260
+
261
+ cfg, remoteAddr, err := c.clientCerts(ctx, instance)
262
+ if err != nil {
263
+ return fmt.Errorf("couldn't retrieve certs for instance: %q: %w", instance, err)
264
+ }
265
+
266
+ // TODO(fatih): implement refreshing certs
267
+ // go p.refreshCertAfter(instance, timeToRefresh)
268
+
269
+ // overwrite the remote address if the user explicitly set it
270
+ if c.remoteAddr != "" {
271
+ remoteAddr = c.remoteAddr
272
+ }
273
+
274
+ c.log.Info("connecting to remote server", zap.String("remote_addr", remoteAddr))
275
+
276
+ var d net.Dialer
277
+ remoteConn, err := d.DialContext(ctx, "tcp", remoteAddr)
278
+ if err != nil {
279
+ conn.Close()
280
+ return fmt.Errorf("couldn't connect to %q: %v", remoteAddr, err)
281
+ }
282
+
283
+ type setKeepAliver interface {
284
+ SetKeepAlive(keepalive bool) error
285
+ SetKeepAlivePeriod(d time.Duration) error
286
+ }
287
+
288
+ if s, ok := conn.(setKeepAliver); ok {
289
+ if err := s.SetKeepAlive(true); err != nil {
290
+ log.Error("couldn't set KeepAlive to true", zap.Error(err))
291
+ } else if err := s.SetKeepAlivePeriod(keepAlivePeriod); err != nil {
292
+ log.Error("couldn't set KeepAlivePeriod", zap.Error(err), zap.Duration("keep_alive_period", keepAlivePeriod))
293
+ }
294
+ } else {
295
+ log.Warn("KeepAlive not supported: long-running tcp connections may be killed by the OS.")
296
+ }
297
+
298
+ secureConn := tls.Client(remoteConn, cfg)
299
+ if err := secureConn.Handshake(); err != nil {
300
+ secureConn.Close()
301
+ return fmt.Errorf("couldn't initiate TLS handshake to remote addr: %s", err)
302
+ }
303
+
304
+ // Hasta la vista, baby
305
+ copyThenClose(
306
+ secureConn,
307
+ conn,
308
+ "remote connection",
309
+ "local connection on "+conn.LocalAddr().String(),
310
+ )
311
+ return nil
312
+ }
313
+
314
+ // clientCerts returns the TLS configuration needed for the TLS handshake and
315
+ // connection
316
+ func (c *Client) clientCerts(ctx context.Context, instance string) (*tls.Config, string, error) {
317
+ cacheEntry, err := c.configCache.Get(instance)
318
+ if err == nil {
319
+ c.log.Info("using tls.Config from the cache", zap.String("instance", instance))
320
+ return cacheEntry.cfg, cacheEntry.remoteAddr, nil
321
+ }
322
+
323
+ if err != errConfigNotFound {
324
+ return nil, "", err // we don't handle non errConfigNotFound errors
325
+ }
326
+
327
+ s := strings.Split(instance, "/")
328
+ if len(s) != 3 {
329
+ return nil, "", fmt.Errorf("instance format is malformed, should be in form organization/dbname/branch, have: %q", instance)
330
+ }
331
+
332
+ cert, err := c.certSource.Cert(ctx, s[0], s[1], s[2])
333
+ if err != nil {
334
+ return nil, "", fmt.Errorf("couldn't retrieve certs from cert source: %s", err)
335
+ }
336
+
337
+ rootCertPool := x509.NewCertPool()
338
+ rootCertPool.AddCert(cert.CACert)
339
+
340
+ serverName := fmt.Sprintf("%s.%s.%s.%s", s[2], s[1], s[0], cert.RemoteAddr)
341
+ fullAddr := fmt.Sprintf("%s:%d", serverName, cert.Ports.Proxy)
342
+
343
+ cfg := &tls.Config{
344
+ ServerName: serverName,
345
+ Certificates: []tls.Certificate{cert.ClientCert},
346
+ RootCAs: rootCertPool,
347
+ // Set InsecureSkipVerify to skip the default validation we are
348
+ // replacing. This will not disable VerifyConnection.
349
+ InsecureSkipVerify: true,
350
+ VerifyConnection: func(cs tls.ConnectionState) error {
351
+ // For now, only verify the server's certificate chain.
352
+ // We don't know yet what the server's FQDN will be.
353
+ //
354
+ // serverName := cs.ServerName
355
+ // commonName := cs.PeerCertificates[0].Subject.CommonName
356
+ // if commonName != serverName {
357
+ // return fmt.Errorf("invalid certificate name %q, expected %q", commonName, serverName)
358
+ // }
359
+ opts := x509.VerifyOptions{
360
+ Roots: rootCertPool,
361
+ Intermediates: x509.NewCertPool(),
362
+ }
363
+ for _, cert := range cs.PeerCertificates[1:] {
364
+ opts.Intermediates.AddCert(cert)
365
+ }
366
+ _, err := cs.PeerCertificates[0].Verify(opts)
367
+ return err
368
+ },
369
+ }
370
+
371
+ c.log.Info("adding tls.Config to the cache", zap.String("instance", instance))
372
+ c.configCache.Add(instance, cfg, fullAddr)
373
+ return cfg, fullAddr, nil
374
+ }
375
+
376
+ // Shutdown waits up to a given amount of time for all active connections to
377
+ // close. Returns an error if there are still active connections after waiting
378
+ // for the whole length of the timeout.
379
+ func (c *Client) Shutdown(timeout time.Duration) error {
380
+ term, ticker := time.After(timeout), time.NewTicker(100*time.Millisecond)
381
+ defer ticker.Stop()
382
+
383
+ for {
384
+ select {
385
+ case <-ticker.C:
386
+ if atomic.LoadUint64(&c.connectionsCounter) > 0 {
387
+ continue
388
+ }
389
+ c.log.Info("no connections to wait, bailing out")
390
+ case <-term:
391
+ }
392
+ break
393
+ }
394
+
395
+ active := atomic.LoadUint64(&c.connectionsCounter)
396
+ if active == 0 {
397
+ return nil
398
+ }
399
+ return fmt.Errorf("%d active connections still exist after waiting for %v", active, timeout)
400
+ }
401
+
402
+ func copyThenClose(remote, local io.ReadWriteCloser, remoteDesc, localDesc string) {
403
+ firstErr := make(chan error, 1)
404
+
405
+ go func() {
406
+ readErr, err := myCopy(remote, local)
407
+ select {
408
+ case firstErr <- err:
409
+ if readErr && err == io.EOF {
410
+ zap.L().Info("client closed connection",
411
+ zap.String("local_desc", localDesc))
412
+ } else {
413
+ logError(localDesc, remoteDesc, readErr, err)
414
+ }
415
+ remote.Close()
416
+ local.Close()
417
+ default:
418
+ }
419
+ }()
420
+
421
+ readErr, err := myCopy(local, remote)
422
+ select {
423
+ case firstErr <- err:
424
+ if readErr && err == io.EOF {
425
+ zap.L().Info("instance closed connection",
426
+ zap.String("remote_desc", remoteDesc))
427
+ } else {
428
+ logError(remoteDesc, localDesc, readErr, err)
429
+ }
430
+ remote.Close()
431
+ local.Close()
432
+ default:
433
+ // In this case, the other goroutine exited first and already printed its
434
+ // error (and closed the things).
435
+ }
436
+ }
437
+
438
+ func logError(readDesc, writeDesc string, readErr bool, err error) {
439
+ var desc string
440
+ if readErr {
441
+ desc = "reading data from " + readDesc
442
+ } else {
443
+ desc = "writing data to " + writeDesc
444
+ }
445
+ zap.L().Error("copy error", zap.String("desc", desc), zap.Error(err))
446
+ }
447
+
448
+ // myCopy is similar to io.Copy, but reports whether the returned error was due
449
+ // to a bad read or write. The returned error will never be nil
450
+ func myCopy(dst io.Writer, src io.Reader) (readErr bool, err error) {
451
+ buf := make([]byte, 4096)
452
+ for {
453
+ n, err := src.Read(buf)
454
+ if n > 0 {
455
+ if _, werr := dst.Write(buf[:n]); werr != nil {
456
+ if err == nil {
457
+ return false, werr
458
+ }
459
+ // Read and write error; just report read error (it happened first).
460
+ return true, err
461
+ }
462
+ }
463
+ if err != nil {
464
+ return true, err
465
+ }
466
+ }
467
+ }