Compare commits

...

75 Commits

Author SHA1 Message Date
dependabot[bot] d68b141c66
build(deps): bump golang.org/x/text from 0.15.0 to 0.16.0 (#301) 2024-06-15 14:20:25 -05:00
dependabot[bot] 732283d1c5
build(deps): bump github.com/docker/docker from 26.1.3+incompatible to 26.1.4+incompatible in the patches group (#300)
* build(deps): bump github.com/docker/docker in the patches group

Bumps the patches group with 1 update: [github.com/docker/docker](https://github.com/docker/docker).


Updates `github.com/docker/docker` from 26.1.3+incompatible to 26.1.4+incompatible
- [Release notes](https://github.com/docker/docker/releases)
- [Commits](https://github.com/docker/docker/compare/v26.1.3...v26.1.4)

---
updated-dependencies:
- dependency-name: github.com/docker/docker
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: patches
...

Signed-off-by: dependabot[bot] <support@github.com>

* Bump to Go 1.22.4

---------

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: Geoff Bourne <itzgeoff@gmail.com>
2024-06-15 14:04:35 -05:00
dependabot[bot] ff1709ef3b
build(deps): bump github.com/docker/docker from 26.1.1+incompatible to 26.1.2+incompatible in the patches group (#292)
* build(deps): bump github.com/docker/docker in the patches group

Bumps the patches group with 1 update: [github.com/docker/docker](https://github.com/docker/docker).


Updates `github.com/docker/docker` from 26.1.1+incompatible to 26.1.2+incompatible
- [Release notes](https://github.com/docker/docker/releases)
- [Commits](https://github.com/docker/docker/compare/v26.1.1...v26.1.2)

---
updated-dependencies:
- dependency-name: github.com/docker/docker
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: patches
...

Signed-off-by: dependabot[bot] <support@github.com>

* Bump to Go 1.22.3

---------

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: Geoff Bourne <itzgeoff@gmail.com>
2024-05-24 21:30:30 -05:00
dependabot[bot] 28a78380d0
build(deps): bump github.com/docker/docker from 26.1.1+incompatible to 26.1.3+incompatible in the patches group across 1 directory (#293)
* build(deps): bump github.com/docker/docker

Bumps the patches group with 1 update in the / directory: [github.com/docker/docker](https://github.com/docker/docker).


Updates `github.com/docker/docker` from 26.1.1+incompatible to 26.1.3+incompatible
- [Release notes](https://github.com/docker/docker/releases)
- [Commits](https://github.com/docker/docker/compare/v26.1.1...v26.1.3)

---
updated-dependencies:
- dependency-name: github.com/docker/docker
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: patches
...

Signed-off-by: dependabot[bot] <support@github.com>

* Bump to Go 1.22.3

---------

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: Geoff Bourne <itzgeoff@gmail.com>
2024-05-24 21:15:10 -05:00
dependabot[bot] e17d5d6188
build(deps): bump github.com/docker/docker in the patches group (#289) 2024-05-06 08:05:34 -05:00
dependabot[bot] 5f79ad653e
build(deps): bump golang.org/x/text from 0.14.0 to 0.15.0 (#290) 2024-05-06 07:28:35 -05:00
Ambrose Chua f34b6e85b0
Prevent crash due to large memory allocation (#291) 2024-05-05 21:10:23 -05:00
dependabot[bot] 09ed21d467
build(deps): bump github.com/docker/docker (#288) 2024-04-29 07:42:23 -05:00
dependabot[bot] c4d2918053
build(deps): bump github.com/docker/docker from 26.0.0+incompatible to 26.0.2+incompatible (#284)
* build(deps): bump github.com/docker/docker

Bumps [github.com/docker/docker](https://github.com/docker/docker) from 26.0.0+incompatible to 26.0.2+incompatible.
- [Release notes](https://github.com/docker/docker/releases)
- [Commits](https://github.com/docker/docker/compare/v26.0.0...v26.0.2)

---
updated-dependencies:
- dependency-name: github.com/docker/docker
  dependency-type: direct:production
...

Signed-off-by: dependabot[bot] <support@github.com>

* Add toolchain to go.mod

* Bump to go 1.22.2

---------

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: Geoff Bourne <itzgeoff@gmail.com>
2024-04-18 19:02:12 -05:00
dependabot[bot] 392c64f7fb
build(deps): bump github.com/docker/docker (#281)
Bumps [github.com/docker/docker](https://github.com/docker/docker) from 25.0.5+incompatible to 26.0.0+incompatible.
- [Release notes](https://github.com/docker/docker/releases)
- [Commits](https://github.com/docker/docker/compare/v25.0.5...v26.0.0)

---
updated-dependencies:
- dependency-name: github.com/docker/docker
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-03-24 20:55:24 -05:00
dependabot[bot] e15c0d8110
build(deps): bump github.com/docker/docker (#280) 2024-03-20 16:13:55 -05:00
dependabot[bot] 3cc4f3c861
build(deps): bump the patches group with 1 update (#276) 2024-03-17 22:09:52 -05:00
dependabot[bot] e441a72d90
build(deps): bump google.golang.org/protobuf from 1.32.0 to 1.33.0 (#275)
Bumps google.golang.org/protobuf from 1.32.0 to 1.33.0.

---
updated-dependencies:
- dependency-name: google.golang.org/protobuf
  dependency-type: indirect
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-03-16 14:30:15 -05:00
dependabot[bot] 8ca88f416e
build(deps): bump the patches group with 1 update (#274) 2024-03-11 08:20:48 -05:00
dependabot[bot] b762c1b04e
build(deps): bump github.com/stretchr/testify from 1.8.4 to 1.9.0 (#273) 2024-03-04 07:58:53 -06:00
dependabot[bot] 705ffbf093
build(deps): bump golang.ngrok.com/ngrok from 1.8.1 to 1.9.0 (#272) 2024-03-03 18:11:53 -06:00
Stein van Broekhoven 5dc576fc2e
auto scale up and down with many named backends in k8s (#270) 2024-02-19 09:54:24 -06:00
dependabot[bot] 555033b54d
build(deps): bump the patches group with 1 update (#266) 2024-02-18 19:48:55 -06:00
dependabot[bot] f85b23b271
build(deps): bump the patches group with 1 update (#265) 2024-02-12 12:21:58 -06:00
dependabot[bot] fad894e773
build(deps): bump the patches group with 1 update (#263) 2024-02-04 19:44:16 -06:00
dependabot[bot] 1d6df79ba3
build(deps): bump golang.ngrok.com/ngrok from 1.7.0 to 1.8.0 (#264)
Bumps [golang.ngrok.com/ngrok](https://github.com/ngrok/ngrok-go) from 1.7.0 to 1.8.0.
- [Release notes](https://github.com/ngrok/ngrok-go/releases)
- [Changelog](https://github.com/ngrok/ngrok-go/blob/main/CHANGELOG.md)
- [Commits](https://github.com/ngrok/ngrok-go/compare/v1.7.0...v1.8.0)

---
updated-dependencies:
- dependency-name: golang.ngrok.com/ngrok
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2024-02-04 18:50:05 -06:00
Geoff Bourne b2153f89cb
Corrected addresses used in PROXY header (#262) 2024-02-03 19:37:44 -06:00
dependabot[bot] 51b8d44c77
build(deps): bump github.com/docker/docker (#260) 2024-01-30 08:17:23 -06:00
dependabot[bot] ac3e315a1f
build(deps): bump golang.ngrok.com/ngrok from 1.5.1 to 1.7.0 (#253) 2023-12-25 07:18:54 -07:00
dependabot[bot] f9572965f9
build(deps): bump github.com/itzg/go-flagsfiller from 1.13.1 to 1.14.0 (#251) 2023-12-24 20:01:20 -07:00
dependabot[bot] ffacdb5155
build(deps): bump golang.org/x/text from 0.13.0 to 0.14.0 (#246)
Bumps [golang.org/x/text](https://github.com/golang/text) from 0.13.0 to 0.14.0.
- [Release notes](https://github.com/golang/text/releases)
- [Commits](https://github.com/golang/text/compare/v0.13.0...v0.14.0)

---
updated-dependencies:
- dependency-name: golang.org/x/text
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-11-07 21:49:49 -06:00
dependabot[bot] 952e298c87 build(deps): bump the patches group with 1 update
Bumps the patches group with 1 update: [github.com/gorilla/mux](https://github.com/gorilla/mux).

- [Release notes](https://github.com/gorilla/mux/releases)
- [Commits](https://github.com/gorilla/mux/compare/v1.8.0...v1.8.1)

---
updated-dependencies:
- dependency-name: github.com/gorilla/mux
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: patches
...

Signed-off-by: dependabot[bot] <support@github.com>
2023-11-06 08:58:28 -06:00
dependabot[bot] aa4b27c8f5
build(deps): bump the patches group with 2 updates (#244)
Bumps the patches group with 2 updates: [k8s.io/api](https://github.com/kubernetes/api) and [k8s.io/client-go](https://github.com/kubernetes/client-go).


Updates `k8s.io/api` from 0.28.2 to 0.28.3
- [Commits](https://github.com/kubernetes/api/compare/v0.28.2...v0.28.3)

Updates `k8s.io/client-go` from 0.28.2 to 0.28.3
- [Changelog](https://github.com/kubernetes/client-go/blob/master/CHANGELOG.md)
- [Commits](https://github.com/kubernetes/client-go/compare/v0.28.2...v0.28.3)

---
updated-dependencies:
- dependency-name: k8s.io/api
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: patches
- dependency-name: k8s.io/client-go
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: patches
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-11-03 15:45:03 -05:00
dependabot[bot] a96cde55d5
build(deps): bump github.com/docker/docker (#243)
Bumps [github.com/docker/docker](https://github.com/docker/docker) from 24.0.6+incompatible to 24.0.7+incompatible.
- [Release notes](https://github.com/docker/docker/releases)
- [Commits](https://github.com/docker/docker/compare/v24.0.6...v24.0.7)

---
updated-dependencies:
- dependency-name: github.com/docker/docker
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-10-29 22:00:38 -05:00
Geoff Bourne 4f54002231
Allow for MAPPING to be declared with newline delimited entries (#241) 2023-10-28 16:54:46 -05:00
dependabot[bot] ccc0b6f9f4
build(deps): bump golang.ngrok.com/ngrok from 1.4.1 to 1.5.1 (#238)
Bumps [golang.ngrok.com/ngrok](https://github.com/ngrok/ngrok-go) from 1.4.1 to 1.5.1.
- [Release notes](https://github.com/ngrok/ngrok-go/releases)
- [Changelog](https://github.com/ngrok/ngrok-go/blob/main/CHANGELOG.md)
- [Commits](https://github.com/ngrok/ngrok-go/compare/v1.4.1...v1.5.1)

---
updated-dependencies:
- dependency-name: golang.ngrok.com/ngrok
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-10-22 20:33:31 -05:00
dependabot[bot] 1e1428c6bd
build(deps): bump golang.org/x/net from 0.13.0 to 0.17.0 (#236) 2023-10-14 17:27:10 -05:00
Geoff Bourne 2cbb998aff
build: use common workflows (#235)
* build(deps): bump docker/setup-buildx-action from 2 to 3

Bumps [docker/setup-buildx-action](https://github.com/docker/setup-buildx-action) from 2 to 3.
- [Release notes](https://github.com/docker/setup-buildx-action/releases)
- [Commits](https://github.com/docker/setup-buildx-action/compare/v2...v3)

---
updated-dependencies:
- dependency-name: docker/setup-buildx-action
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>

* build(deps): bump goreleaser/goreleaser-action from 4 to 5

Bumps [goreleaser/goreleaser-action](https://github.com/goreleaser/goreleaser-action) from 4 to 5.
- [Release notes](https://github.com/goreleaser/goreleaser-action/releases)
- [Commits](https://github.com/goreleaser/goreleaser-action/compare/v4...v5)

---
updated-dependencies:
- dependency-name: goreleaser/goreleaser-action
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>

* build(deps): bump docker/login-action from 2 to 3

Bumps [docker/login-action](https://github.com/docker/login-action) from 2 to 3.
- [Release notes](https://github.com/docker/login-action/releases)
- [Commits](https://github.com/docker/login-action/compare/v2...v3)

---
updated-dependencies:
- dependency-name: docker/login-action
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>

* build(deps): bump k8s.io/apimachinery from 0.28.1 to 0.28.2

Bumps [k8s.io/apimachinery](https://github.com/kubernetes/apimachinery) from 0.28.1 to 0.28.2.
- [Commits](https://github.com/kubernetes/apimachinery/compare/v0.28.1...v0.28.2)

---
updated-dependencies:
- dependency-name: k8s.io/apimachinery
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>

* build(deps): bump golang.ngrok.com/ngrok from 1.4.0 to 1.4.1

Bumps [golang.ngrok.com/ngrok](https://github.com/ngrok/ngrok-go) from 1.4.0 to 1.4.1.
- [Release notes](https://github.com/ngrok/ngrok-go/releases)
- [Changelog](https://github.com/ngrok/ngrok-go/blob/main/CHANGELOG.md)
- [Commits](https://github.com/ngrok/ngrok-go/compare/v1.4.0...v1.4.1)

---
updated-dependencies:
- dependency-name: golang.ngrok.com/ngrok
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>

* build: use common workflows

* build(deps): upgrade k8s

---------

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-09-23 18:44:30 -05:00
dependabot[bot] 5fb718df2d
build(deps): bump actions/checkout from 3 to 4 (#226) 2023-09-11 22:09:09 -05:00
dependabot[bot] 35aaae5bcb
build(deps): bump github.com/docker/docker (#225) 2023-09-11 07:18:41 -05:00
Geoff Bourne a73a1689c9
deps: upgrade k8s and others (#224) 2023-09-09 14:11:44 -05:00
dependabot[bot] b4b97f51df
build(deps): bump github.com/stretchr/testify from 1.8.2 to 1.8.4 (#200)
Bumps [github.com/stretchr/testify](https://github.com/stretchr/testify) from 1.8.2 to 1.8.4.
- [Release notes](https://github.com/stretchr/testify/releases)
- [Commits](https://github.com/stretchr/testify/compare/v1.8.2...v1.8.4)

---
updated-dependencies:
- dependency-name: github.com/stretchr/testify
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-09-09 13:35:24 -05:00
dependabot[bot] 84907ef8cd
build(deps): bump github.com/docker/docker (#215)
Bumps [github.com/docker/docker](https://github.com/docker/docker) from 24.0.2+incompatible to 24.0.5+incompatible.
- [Release notes](https://github.com/docker/docker/releases)
- [Commits](https://github.com/docker/docker/compare/v24.0.2...v24.0.5)

---
updated-dependencies:
- dependency-name: github.com/docker/docker
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-09-09 13:31:17 -05:00
Geoff Bourne 33f393f1b9
ci: fix goreleaser `--rm-dist` deprecation (#223) 2023-09-09 13:30:53 -05:00
Geoff Bourne afdca5646e
Added ngrok support (#222) 2023-09-09 12:06:59 -05:00
dependabot[bot] 25601c65a6
build(deps): bump github.com/sirupsen/logrus from 1.9.2 to 1.9.3 (#210) 2023-07-16 20:28:12 -05:00
dependabot[bot] 4435b7cb55
build(deps): bump golang.org/x/text from 0.9.0 to 0.11.0 (#209) 2023-07-09 21:36:13 -05:00
dependabot[bot] ff7ef24f4c
build(deps): bump github.com/itzg/go-flagsfiller from 1.11.0 to 1.12.0 (#202)
Bumps [github.com/itzg/go-flagsfiller](https://github.com/itzg/go-flagsfiller) from 1.11.0 to 1.12.0.
- [Release notes](https://github.com/itzg/go-flagsfiller/releases)
- [Commits](https://github.com/itzg/go-flagsfiller/compare/v1.11.0...v1.12.0)

---
updated-dependencies:
- dependency-name: github.com/itzg/go-flagsfiller
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-06-11 20:20:24 -05:00
dependabot[bot] 302b68400b
build(deps): bump github.com/docker/docker (#201) 2023-06-05 10:10:36 -05:00
dependabot[bot] f6dc9cd03a
build(deps): bump github.com/sirupsen/logrus from 1.9.0 to 1.9.2 (#198) 2023-05-29 08:54:08 -05:00
dependabot[bot] 88d2e8a013
build(deps): bump github.com/itzg/go-flagsfiller from 1.9.2 to 1.11.0 (#199) 2023-05-29 08:21:48 -05:00
dependabot[bot] 7f4a6843ea
build(deps): bump github.com/docker/distribution (#187) 2023-05-25 06:59:25 -05:00
Geoff Bourne 1803ecfe04
Fixed Go version for test build (#197) 2023-05-24 22:28:41 -05:00
dependabot[bot] 8fab072e18
build(deps): bump golang.org/x/text from 0.8.0 to 0.9.0 (#181) 2023-05-24 22:22:16 -05:00
dependabot[bot] c046edec8b
build(deps): bump github.com/docker/docker (#191) 2023-05-24 22:21:31 -05:00
Lilly Tempest c548fda65e
Support TCP Shield host enrinchment (#195) 2023-05-24 21:28:38 -05:00
Geoff Bourne 059ee78c5c
Simplify PR github action (#196) 2023-05-24 21:27:44 -05:00
Lilly Tempest de655ee432
Add documentation for routes config file (#194) 2023-05-24 08:24:39 -05:00
dependabot[bot] 087a325720
build(deps): bump github.com/docker/docker (#184)
Bumps [github.com/docker/docker](https://github.com/docker/docker) from 23.0.1+incompatible to 23.0.4+incompatible.
- [Release notes](https://github.com/docker/docker/releases)
- [Commits](https://github.com/docker/docker/compare/v23.0.1...v23.0.4)

---
updated-dependencies:
- dependency-name: github.com/docker/docker
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-04-23 21:51:25 -05:00
dependabot[bot] 426aebeadb
build(deps): bump github.com/itzg/go-flagsfiller from 1.9.1 to 1.9.2 (#178) 2023-04-09 22:14:29 -05:00
dependabot[bot] ae24356102
build(deps): bump github.com/pires/go-proxyproto from 0.6.2 to 0.7.0 (#175) 2023-03-20 14:35:16 -05:00
dependabot[bot] 80a9d38471
build(deps): bump actions/setup-go from 3 to 4 (#171) 2023-03-20 07:32:24 -05:00
dependabot[bot] a3cd1598bf
build(deps): bump golang.org/x/crypto (#165)
Bumps [golang.org/x/crypto](https://github.com/golang/crypto) from 0.0.0-20210915214749-c084706c2272 to 0.1.0.
- [Release notes](https://github.com/golang/crypto/releases)
- [Commits](https://github.com/golang/crypto/commits/v0.1.0)

---
updated-dependencies:
- dependency-name: golang.org/x/crypto
  dependency-type: indirect
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2023-03-06 12:22:44 -06:00
dependabot[bot] a1067acfa1
build(deps): bump golang.org/x/text from 0.7.0 to 0.8.0 (#167) 2023-03-05 22:25:34 -06:00
dependabot[bot] e39d4049eb
build(deps): bump github.com/stretchr/testify from 1.8.1 to 1.8.2 (#166) 2023-02-26 19:42:23 -06:00
dependabot[bot] da057f5b34
build(deps): bump golang.org/x/net (#164) 2023-02-24 20:59:56 -06:00
dependabot[bot] 1f8236ad92
build(deps): bump github.com/docker/docker (#162) 2023-02-14 07:22:23 -06:00
dependabot[bot] 7fb3cbd7bf
build(deps): bump golang.org/x/text from 0.6.0 to 0.7.0 (#163) 2023-02-13 08:38:17 -06:00
dependabot[bot] dc5e5cac31
build(deps): bump github.com/docker/docker (#160) 2023-02-06 07:21:21 -06:00
dependabot[bot] 137bd9c8ec
build(deps): bump docker/build-push-action from 3.2.0 to 3.3.0 (#155) 2023-01-15 19:02:30 -06:00
dependabot[bot] 4d93eeaa0d
build(deps): bump golang.org/x/text from 0.5.0 to 0.6.0 (#154) 2023-01-08 20:54:54 -06:00
dependabot[bot] 28695b3bba
build(deps): bump github.com/docker/docker (#151)
Bumps [github.com/docker/docker](https://github.com/docker/docker) from 20.10.21+incompatible to 20.10.22+incompatible.
- [Release notes](https://github.com/docker/docker/releases)
- [Commits](https://github.com/docker/docker/compare/v20.10.21...v20.10.22)

---
updated-dependencies:
- dependency-name: github.com/docker/docker
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2022-12-19 20:28:04 -06:00
dependabot[bot] 730a8d3d89
build(deps): bump goreleaser/goreleaser-action from 3 to 4 (#150) 2022-12-18 19:32:08 -06:00
Lasse15 787ab54ca4
Persistent routes from REST API (#145) 2022-12-05 07:58:13 -06:00
dependabot[bot] e1bb4980bb
build(deps): bump golang.org/x/text from 0.4.0 to 0.5.0 (#146)
Bumps [golang.org/x/text](https://github.com/golang/text) from 0.4.0 to 0.5.0.
- [Release notes](https://github.com/golang/text/releases)
- [Commits](https://github.com/golang/text/compare/v0.4.0...v0.5.0)

---
updated-dependencies:
- dependency-name: golang.org/x/text
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2022-12-04 20:00:04 -06:00
n1xx1 c2b23d40c7
Enable network filtering for docker swarm discovery (#143) 2022-11-17 08:38:44 -06:00
dependabot[bot] 298ea8eef9
build(deps): bump github.com/docker/docker (#138) 2022-10-30 22:04:42 -05:00
dependabot[bot] 7117562215
build(deps): bump github.com/stretchr/testify from 1.8.0 to 1.8.1 (#137) 2022-10-30 19:33:03 -05:00
dependabot[bot] 085bb6e133
build(deps): bump github.com/docker/docker (#134) 2022-10-24 12:52:21 -05:00
Geoff Bourne a7229355bf
Route to k8s service port minecraft or mc-router (#135) 2022-10-23 22:18:10 -05:00
20 changed files with 1092 additions and 1080 deletions

View File

@ -5,7 +5,20 @@ updates:
directory: "/"
schedule:
interval: "weekly"
groups:
updates:
patterns:
- "*"
update-types:
- patch
- minor
- package-ecosystem: "gomod"
directory: "/"
schedule:
interval: "weekly"
interval: "weekly"
groups:
patches:
patterns:
- "*"
update-types:
- patch

View File

@ -1,56 +0,0 @@
name: Validate PR
on:
pull_request:
branches: [ master ]
types: [assigned, opened, synchronize, labeled]
env:
IMAGE_TO_TEST: itzg/mc-router:test-${{ github.repository_owner }}-${{ github.run_id }}
jobs:
test:
runs-on: ubuntu-20.04
steps:
- uses: actions/checkout@v3
- name: Setup Docker Buildx
uses: docker/setup-buildx-action@v2
- name: Build
uses: docker/build-push-action@v3.2.0
with:
tags: ${{ env.IMAGE_TO_TEST }}
load: true
cache-from: type=gha
target: builder
- name: Run tests
run: |
docker run --rm --entrypoint go ${{ env.IMAGE_TO_TEST }} test ./...
- name: Gather Docker metadata
if: contains(github.event.pull_request.labels.*.name, 'ci/push-image')
id: meta
uses: docker/metadata-action@v4
with:
images: |
itzg/mc-router
- name: Login to DockerHub
if: contains(github.event.pull_request.labels.*.name, 'ci/push-image')
uses: docker/login-action@v2
with:
username: ${{ secrets.DOCKERHUB_USERNAME }}
password: ${{ secrets.DOCKERHUB_TOKEN }}
- name: Push
if: contains(github.event.pull_request.labels.*.name, 'ci/push-image')
uses: docker/build-push-action@v3.2.0
with:
tags: ${{ steps.meta.outputs.tags }}
pull: true
push: true
cache-from: type=gha
labels: ${{ steps.meta.outputs.labels }}

View File

@ -8,35 +8,9 @@ on:
jobs:
release:
runs-on: ubuntu-20.04
env:
DOCKER_CLI_EXPERIMENTAL: "enabled"
steps:
- name: Checkout
uses: actions/checkout@v3
with:
fetch-depth: 0
- name: Set up Go
uses: actions/setup-go@v3
with:
go-version: 1.18
- name: Setup docker buildx
uses: docker/setup-buildx-action@v2
with:
install: true
- name: Docker login
uses: docker/login-action@v2
with:
username: ${{ secrets.DOCKERHUB_USERNAME }}
password: ${{ secrets.DOCKERHUB_TOKEN }}
- name: Run GoReleaser
uses: goreleaser/goreleaser-action@v3
with:
version: latest
args: release --rm-dist
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
uses: itzg/github-workflows/.github/workflows/go-with-releaser-image.yml@main
with:
go-version: "1.22.4"
secrets:
image-registry-username: ${{ secrets.DOCKERHUB_USERNAME }}
image-registry-password: ${{ secrets.DOCKERHUB_TOKEN }}

View File

@ -1,28 +1,14 @@
name: test
name: Test
on:
push:
branches:
- master
pull_request:
branches: [ master ]
jobs:
build:
runs-on: ubuntu-20.04
steps:
- name: Checkout
uses: actions/checkout@v3
- name: Set up Go
uses: actions/setup-go@v3
with:
go-version: 1.17
- name: Test
run: go test ./...
- name: Run GoReleaser Snapshot
uses: goreleaser/goreleaser-action@v3
with:
version: latest
args: build --snapshot --rm-dist
uses: itzg/github-workflows/.github/workflows/go-test.yml@main
with:
go-version: "1.22.4"

View File

@ -1,4 +1,4 @@
FROM golang:1.17 as builder
FROM golang:1.20 as builder
WORKDIR /build
@ -6,7 +6,7 @@ COPY go.mod go.sum ./
RUN go mod download
COPY . .
RUN CGO_ENABLED=0 go build ./cmd/mc-router
RUN CGO_ENABLED=0 go build -buildvcs=false ./cmd/mc-router
FROM scratch
ENTRYPOINT ["/mc-router"]

273
README.md
View File

@ -7,116 +7,132 @@
Routes Minecraft client connections to backend servers based upon the requested server address.
# Usage
## Usage
```text
-api-binding host:port
The host:port bound for servicing API requests (env API_BINDING)
The host:port bound for servicing API requests (env API_BINDING)
-auto-scale-up
Increase Kubernetes StatefulSet Replicas (only) from 0 to 1 on respective backend servers when accessed (env AUTO_SCALE_UP)
Increase Kubernetes StatefulSet Replicas (only) from 0 to 1 on respective backend servers when accessed (env AUTO_SCALE_UP)
-connection-rate-limit int
Max number of connections to allow per second (env CONNECTION_RATE_LIMIT) (default 1)
Max number of connections to allow per second (env CONNECTION_RATE_LIMIT) (default 1)
-cpu-profile string
Enables CPU profiling and writes to given path (env CPU_PROFILE)
Enables CPU profiling and writes to given path (env CPU_PROFILE)
-debug
Enable debug logs (env DEBUG)
-in-kube-cluster
Use in-cluster Kubernetes config (env IN_KUBE_CLUSTER)
-kube-config string
The path to a Kubernetes configuration file (env KUBE_CONFIG)
Enable debug logs (env DEBUG)
-default string
host:port of a default Minecraft server to use when mapping not found (env DEFAULT)
-docker-refresh-interval int
Refresh interval in seconds for the Docker Swarm integration (env DOCKER_REFRESH_INTERVAL) (default 15)
-docker-timeout int
Timeout configuration in seconds for the Docker Swarm integration (env DOCKER_TIMEOUT)
-in-docker-swarm
Use in-swarm Docker config (env IN_DOCKER_SWARM)
-docker-timeout
Timeout configuration in seconds for the Docker Swarm integration (env DOCKER_TIMEOUT) (default 0)
-docker-refresh-interval
Refresh interval in seconds for the Docker Swarm integration (env DOCKER_REFRESH_INTERVAL) (default 15)
-mapping string
Comma-separated mappings of externalHostname=host:port (env MAPPING)
Use in-swarm Docker config (env IN_DOCKER_SWARM)
-in-kube-cluster
Use in-cluster Kubernetes config (env IN_KUBE_CLUSTER)
-kube-config string
The path to a Kubernetes configuration file (env KUBE_CONFIG)
-mapping value
Comma-separated or repeated mappings of externalHostname=host:port (env MAPPING)
-metrics-backend string
Backend to use for metrics exposure/publishing: discard,expvar,influxdb (env METRICS_BACKEND) (default "discard")
Backend to use for metrics exposure/publishing: discard,expvar,influxdb (env METRICS_BACKEND) (default "discard")
-metrics-backend-config-influxdb-addr string
(env METRICS_BACKEND_CONFIG_INFLUXDB_ADDR)
(env METRICS_BACKEND_CONFIG_INFLUXDB_ADDR)
-metrics-backend-config-influxdb-database string
(env METRICS_BACKEND_CONFIG_INFLUXDB_DATABASE)
(env METRICS_BACKEND_CONFIG_INFLUXDB_DATABASE)
-metrics-backend-config-influxdb-interval duration
(env METRICS_BACKEND_CONFIG_INFLUXDB_INTERVAL) (default 1m0s)
(env METRICS_BACKEND_CONFIG_INFLUXDB_INTERVAL) (default 1m0s)
-metrics-backend-config-influxdb-password string
(env METRICS_BACKEND_CONFIG_INFLUXDB_PASSWORD)
(env METRICS_BACKEND_CONFIG_INFLUXDB_PASSWORD)
-metrics-backend-config-influxdb-retention-policy string
(env METRICS_BACKEND_CONFIG_INFLUXDB_RETENTION_POLICY)
(env METRICS_BACKEND_CONFIG_INFLUXDB_RETENTION_POLICY)
-metrics-backend-config-influxdb-tags value
any extra tags to be included with all reported metrics (env METRICS_BACKEND_CONFIG_INFLUXDB_TAGS)
any extra tags to be included with all reported metrics (env METRICS_BACKEND_CONFIG_INFLUXDB_TAGS)
-metrics-backend-config-influxdb-username string
(env METRICS_BACKEND_CONFIG_INFLUXDB_USERNAME)
(env METRICS_BACKEND_CONFIG_INFLUXDB_USERNAME)
-ngrok-token string
If set, an ngrok tunnel will be established. It is HIGHLY recommended to pass as an environment variable. (env NGROK_TOKEN)
-port port
The port bound to listen for Minecraft client connections (env PORT) (default 25565)
The port bound to listen for Minecraft client connections (env PORT) (default 25565)
-routes-config string
Name or full path to routes config file (env ROUTES_CONFIG)
-simplify-srv
Simplify fully qualified SRV records for mapping (env SIMPLIFY_SRV)
-use-proxy-protocol
Send PROXY protocol to backend servers (env USE_PROXY_PROTOCOL)
-version
Output version and exit (env VERSION)
Output version and exit (env VERSION)
```
# REST API
* `GET /routes` (with `Accept: application/json`)
Retrieves the currently configured routes
* `POST /routes` (with `Content-Type: application/json`)
Registers a route given a JSON body structured like:
```json
{
"serverAddress": "CLIENT REQUESTED SERVER ADDRESS",
"backend": "HOST:PORT"
}
```
* `POST /defaultRoute` (with `Content-Type: application/json`)
Registers a default route to the given backend. JSON body is structured as:
```json
{
"backend": "HOST:PORT"
}
```
* `DELETE /routes/{serverAddress}`
Deletes an existing route for the given `serverAddress`
# Docker Multi-Architecture Image
## Docker Multi-Architecture Image
The [multi-architecture image published at Docker Hub](https://hub.docker.com/repository/docker/itzg/mc-router) supports amd64, arm64, and arm32v6 (i.e. RaspberryPi).
# Docker Compose Usage
## Docker Compose Usage
The following diagram shows how [the example docker-compose.yml](docs/docker-compose.yml)
configures two Minecraft server services named `vanilla` and `forge`, which also become the internal
network aliases. _Notice those services don't need their ports exposed since the internal
networking allows for the inter-container access._
The diagram below shows how this `docker-compose.yml` configures two Minecraft server services named `vanilla` and `forge`, which also become the internal network aliases. _Notice those services don't need their ports exposed since the internal networking allows for the inter-container access._
The `router` service is only one of the services that needs to exposed on the external
network. The `--mapping` declares how the hostname users will enter into their Minecraft client
will map to the internal services.
```yaml
version: "3.8"
services:
vanilla:
image: itzg/minecraft-server
environment:
EULA: "TRUE"
forge:
image: itzg/minecraft-server
environment:
EULA: "TRUE"
TYPE: FORGE
router:
image: ${MC_ROUTER_IMAGE:-itzg/mc-router}
depends_on:
- forge
- vanilla
environment:
MAPPING: |
vanilla.example.com=vanilla:25565
forge.example.com=forge:25565
ports:
- "25565:25565"
```
The `router` service is only one of the services that needs to exposed on the external network. The `MAPPING` declares how the hostname users will enter into their Minecraft client will map to the internal services.
![](docs/compose-diagram.png)
To test out this example, I added these two entries to my "hosts" file:
To test out this example, add these two entries to my "hosts" file:
```
127.0.0.1 vanilla.example.com
127.0.0.1 forge.example.com
```
# Kubernetes Usage
## Routing Configuration
## Using Kubernetes Service auto-discovery
The routing configuration allows routing via a config file rather than a command.
You need to set `-routes-config` or `ROUTES_CONFIG` env variable.
The following shows a JSON file for routes config, where `default-server` can also be `null` or omitted:
When running `mc-router` as a Kubernetes Pod and you pass the `--in-kube-cluster` command-line argument, then
it will automatically watch for any services annotated with
- `mc-router.itzg.me/externalServerName` : The value of the annotation will be registered as the external hostname Minecraft clients would used to connect to the
routed service. The service's clusterIP and target port are used as the routed backend. You can use more hostnames by splitting them with comma.
- `mc-router.itzg.me/defaultServer` : The service's clusterIP and target port are used as the default if
no other `externalServiceName` annotations applies.
```json
{
"default-server": "vanilla:25565",
"mappings": {
"vanilla.example.com": "vanilla:25565",
"forge.example.com": "forge:25565"
}
}
```
## Kubernetes Usage
### Using Kubernetes Service auto-discovery
When running `mc-router` as a Kubernetes Pod and you pass the `--in-kube-cluster` command-line argument, then it will automatically watch for any services annotated with
- `mc-router.itzg.me/externalServerName` : The value of the annotation will be registered as the external hostname Minecraft clients would used to connect to the routed service. The service's clusterIP and target port are used as the routed backend. You can use more hostnames by splitting them with comma.
- `mc-router.itzg.me/defaultServer` : The service's clusterIP and target port are used as the default if no other `externalServiceName` annotations applies.
For example, start `mc-router`'s container spec with
@ -148,7 +164,9 @@ metadata:
"mc-router.itzg.me/externalServerName": "external.host.name,other.host.name"
```
## Example Kubernetes deployment
mc-router will pick the service port named either `minecraft` or `mc-router`. If neither port names exist, it will use port value 25565.
### Example Kubernetes deployment
[This example deployment](docs/k8s-example-auto.yaml)
* Declares an `mc-router` service that exposes a node port 25565
@ -163,12 +181,12 @@ kubectl apply -f https://raw.githubusercontent.com/itzg/mc-router/master/docs/k8
![](docs/example-deployment-auto.drawio.png)
#### Notes
##### Notes
* This deployment assumes two persistent volume claims: `mc-stable` and `mc-snapshot`
* I extended the allowed node port range by adding `--service-node-port-range=25000-32767`
to `/etc/kubernetes/manifests/kube-apiserver.yaml`
#### Auto Scale Up
##### Auto Scale Up
The `-auto-scale-up` flag argument makes the router "wake up" any stopped backend servers, by changing `replicas: 0` to `replicas: 1`.
@ -191,9 +209,9 @@ rules:
verbs: ["watch","list","get","update"]
```
# Docker Swarm Usage
## Docker Swarm Usage
## Using Docker Swarm Service auto-discovery
### Using Docker Swarm Service auto-discovery
When running `mc-router` in a Docker Swarm environment you can pass the `--in-docker-swarm`
command-line argument and it will poll the Docker API periodically to find all the running
@ -207,23 +225,108 @@ label on the service. These are the labels scanned:
The default value is 25565.
- `mc-router.default`: Set this to a truthy value to make this server the deafult backend.
Please note that `mc-router.host` is still required to be set.
- `mc-router.network`: Specify the network you are using for the router if multiple are
present in the service. You can either use the network ID, it's full name or an alias.
## Example Docker Swarm deployment
### Example Docker Swarm deployment
Refer to [this example docker-compose.yml](docs/swarm.docker-compose.yml) to see how to
configure two different Minecraft servers and a `mc-router` instance. Notice how you don't
have to expose the Minecraft instances ports, but all the containers are required to be in
the same network.
# Development
## REST API
## Building locally with Docker
* `GET /routes` (with `Accept: application/json`)
Retrieves the currently configured routes
* `POST /routes` (with `Content-Type: application/json`)
Registers a route given a JSON body structured like:
```json
{
"serverAddress": "CLIENT REQUESTED SERVER ADDRESS",
"backend": "HOST:PORT"
}
```
* `POST /defaultRoute` (with `Content-Type: application/json`)
Registers a default route to the given backend. JSON body is structured as:
```json
{
"backend": "HOST:PORT"
}
```
* `DELETE /routes/{serverAddress}`
Deletes an existing route for the given `serverAddress`
## ngrok
mc-router has built-in support to run as an [ngrok agent](https://ngrok.com/docs/secure-tunnels/ngrok-agent/). To enable this support, pass [an ngrok authtoken](https://ngrok.com/docs/secure-tunnels/ngrok-agent/tunnel-authtokens/#per-agent-authtokens) to the command-line argument or environment variable, [shown above](#usage).
### Ngrok Quick Start
Create/access an ngrok account and [allocate an agent authtoken from the dashboard](https://dashboard.ngrok.com/tunnels/authtokens).
In a new directory, create a file called `.env` with the allocated token
```dotenv
NGROK_TOKEN=...
```
In the same directory, create the following compose file:
```yaml
version: "3.8"
services:
mc:
image: itzg/minecraft-server
environment:
EULA: true
volumes:
- mc-data:/data
# No port mapping since mc-router connects over compose network
router:
image: itzg/mc-router
environment:
DEFAULT: mc:25565
NGROK_TOKEN: ${NGROK_TOKEN}
# No port mapping needed since it routes through ngrok tunnel
volumes:
mc-data: {}
```
Start the compose project:
```shell
docker compose up -d
```
Grab the mc-router logs using:
```shell
docker compose logs router
```
From those logs, locate the `ngrokUrl` parameter from the "Listening" info log message, such as `tcp://8.tcp.ngrok.io:99999`.
In the Minecraft client, the server address will be the part after the "tcp://" prefix, such as `8.tcp.ngrok.io:99999`.
## Development
### Building locally with Docker
```bash
docker build -t mc-router .
```
## Build locally without Docker
### Build locally without Docker
After [installing Go](https://go.dev/doc/install) and doing a `go mod download` to install all required prerequisites, just like the [Dockerfile](Dockerfile) does, you can:
@ -232,7 +335,7 @@ make test # go test -v ./...
go build ./cmd/mc-router/
```
## Skaffold
### Skaffold
For "in-cluster development" it's convenient to use https://skaffold.dev. Any changes to Go source code
will trigger a go build, new container image pushed to registry with a new tag, and refresh in Kubernetes
@ -246,7 +349,7 @@ then add the _Artifact Registry Reader_ Role to the _Compute Engine default serv
then use e.g. `gcloud auth configure-docker europe-docker.pkg.dev` or equivalent one time (to create a `~/.docker/config.json`),
and then use e.g. `--default-repo=europe-docker.pkg.dev/YOUR-PROJECT/YOUR-ARTIFACT-REGISTRY` option for `skaffold dev`.
## Performing snapshot release with Docker
### Performing snapshot release with Docker
```bash
docker run -it --rm \
@ -256,6 +359,6 @@ docker run -it --rm \
release --snapshot --rm-dist
```
# Related Projects
## Related Projects
* https://github.com/haveachin/infrared

View File

@ -8,7 +8,6 @@ import (
"os/signal"
"runtime/pprof"
"strconv"
"strings"
"syscall"
"time"
@ -30,22 +29,25 @@ type MetricsBackendConfig struct {
}
type Config struct {
Port int `default:"25565" usage:"The [port] bound to listen for Minecraft client connections"`
Mapping []string `usage:"Comma-separated or repeated mappings of externalHostname=host:port"`
ApiBinding string `usage:"The [host:port] bound for servicing API requests"`
Version bool `usage:"Output version and exit"`
CpuProfile string `usage:"Enables CPU profiling and writes to given path"`
Debug bool `usage:"Enable debug logs"`
ConnectionRateLimit int `default:"1" usage:"Max number of connections to allow per second"`
InKubeCluster bool `usage:"Use in-cluster Kubernetes config"`
KubeConfig string `usage:"The path to a Kubernetes configuration file"`
AutoScaleUp bool `usage:"Increase Kubernetes StatefulSet Replicas (only) from 0 to 1 on respective backend servers when accessed"`
InDockerSwarm bool `usage:"Use in-swarm Docker config"`
DockerTimeout int `default:"0" usage:"Timeout configuration in seconds for the Docker Swarm integration"`
DockerRefreshInterval int `default:"15" usage:"Refresh interval in seconds for the Docker Swarm integration"`
MetricsBackend string `default:"discard" usage:"Backend to use for metrics exposure/publishing: discard,expvar,influxdb"`
UseProxyProtocol bool `default:"false" usage:"Send PROXY protocol to backend servers"`
Port int `default:"25565" usage:"The [port] bound to listen for Minecraft client connections"`
Default string `usage:"host:port of a default Minecraft server to use when mapping not found"`
Mapping map[string]string `usage:"Comma or newline delimited or repeated mappings of externalHostname=host:port"`
ApiBinding string `usage:"The [host:port] bound for servicing API requests"`
Version bool `usage:"Output version and exit"`
CpuProfile string `usage:"Enables CPU profiling and writes to given path"`
Debug bool `usage:"Enable debug logs"`
ConnectionRateLimit int `default:"1" usage:"Max number of connections to allow per second"`
InKubeCluster bool `usage:"Use in-cluster Kubernetes config"`
KubeConfig string `usage:"The path to a Kubernetes configuration file"`
AutoScaleUp bool `usage:"Increase Kubernetes StatefulSet Replicas (only) from 0 to 1 on respective backend servers when accessed"`
InDockerSwarm bool `usage:"Use in-swarm Docker config"`
DockerTimeout int `default:"0" usage:"Timeout configuration in seconds for the Docker Swarm integration"`
DockerRefreshInterval int `default:"15" usage:"Refresh interval in seconds for the Docker Swarm integration"`
MetricsBackend string `default:"discard" usage:"Backend to use for metrics exposure/publishing: discard,expvar,influxdb"`
UseProxyProtocol bool `default:"false" usage:"Send PROXY protocol to backend servers"`
MetricsBackendConfig MetricsBackendConfig
RoutesConfig string `usage:"Name or full path to routes config file"`
NgrokToken string `usage:"If set, an ngrok tunnel will be established. It is HIGHLY recommended to pass as an environment variable."`
SimplifySRV bool `default:"false" usage:"Simplify fully qualified SRV records for mapping"`
}
@ -100,12 +102,25 @@ func main() {
c := make(chan os.Signal, 1)
signal.Notify(c, syscall.SIGINT, syscall.SIGTERM)
server.Routes.RegisterAll(parseMappings(config.Mapping))
if config.RoutesConfig != "" {
err := server.RoutesConfig.ReadRoutesConfig(config.RoutesConfig)
if err != nil {
logrus.WithError(err).Error("Unable to load routes from config file")
}
}
server.Routes.RegisterAll(config.Mapping)
if config.Default != "" {
server.Routes.SetDefaultRoute(config.Default)
}
if config.ConnectionRateLimit < 1 {
config.ConnectionRateLimit = 1
}
connector := server.NewConnector(metricsBuilder.BuildConnectorMetrics(), config.UseProxyProtocol)
if config.NgrokToken != "" {
connector.UseNgrok(config.NgrokToken)
}
err = connector.StartAcceptingConnections(ctx,
net.JoinHostPort("", strconv.Itoa(config.Port)),
config.ConnectionRateLimit,
@ -157,17 +172,3 @@ func main() {
connector.WaitForConnections()
logrus.Info("Stopped")
}
func parseMappings(vals []string) map[string]string {
result := make(map[string]string)
for _, part := range vals {
keyValue := strings.Split(part, "=")
if len(keyValue) == 2 {
result[keyValue[0]] = keyValue[1]
} else {
logrus.WithField("part", part).Fatal("Invalid part of mapping")
}
}
return result
}

1
docs/.gitignore vendored Normal file
View File

@ -0,0 +1 @@
.env

View File

@ -1,5 +1,3 @@
version: '3.4'
services:
vanilla:
image: itzg/minecraft-server
@ -18,9 +16,12 @@ services:
environment:
# enable API
API_BINDING: ":25564"
DEBUG: true
MAPPING: |
vanilla.example.com=vanilla:25565
forge.example.com=forge:25565
ports:
- 25565:25565
- "25565:25565"
# bind the API port to only loopback to avoid external exposure
- 127.0.0.1:25564:25564
command: --mapping=vanilla.example.com=vanilla:25565,forge.example.com=forge:25565
- "127.0.0.1:25564:25564"

278
docs/k8s-autoscale.yaml Normal file
View File

@ -0,0 +1,278 @@
# This YAML is an example and is not intended to be directly applied.
# It consists of 3 parts
# 1. the mc-router with service account an service
# 2. the shutdown cronjob with service account
# 3. the actual server with service and storage
# part 3 is the only part you need to replicate for the number of servers you want
# mc-router
---
apiVersion: v1
kind: ServiceAccount
metadata:
name: mc-router
---
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
name: services-watcher
rules:
- apiGroups: [""]
resources: ["services"]
verbs: ["watch","list"]
- apiGroups: ["apps"]
resources: ["statefulsets", "statefulsets/scale"]
verbs: ["watch","list","get","update"]
---
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
name: mc-router-services-watcher
subjects:
- kind: ServiceAccount
name: mc-router
namespace: default
roleRef:
kind: ClusterRole
name: services-watcher
apiGroup: rbac.authorization.k8s.io
# Use whatever tcp ingress method you want I just used a node port here for simplicity
---
apiVersion: v1
kind: Service
metadata:
name: mc-router
spec:
type: NodePort
externalIPs:
- 192.168.1.100
ports:
- targetPort: web
name: web
port: 8080
nodePort: 30001
- targetPort: proxy
name: proxy
port: 25565
nodePort: 30000
selector:
run: mc-router
---
apiVersion: apps/v1
kind: Deployment
metadata:
labels:
run: mc-router
name: mc-router
spec:
selector:
matchLabels:
run: mc-router
strategy:
type: Recreate
template:
metadata:
labels:
run: mc-router
spec:
serviceAccountName: mc-router
containers:
- image: aapjeisbaas/mc-router:latest
imagePullPolicy: Always
name: mc-router
args: ["--api-binding", ":8080", "--in-kube-cluster","--auto-scale-up", "--debug"]
env:
- name: AUTO_SCALE_UP
value: "true"
ports:
- name: proxy
containerPort: 25565
- name: web
containerPort: 8080
resources:
requests:
memory: 50Mi
cpu: "100m"
limits:
memory: 100Mi
cpu: "250m"
# Cron job for stopping empty servers
---
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
name: mc-shutdown
rules:
- apiGroups: ["apps"]
resources: ["statefulsets", "statefulsets/scale"]
verbs: ["list","get","update", "patch"]
- apiGroups: [""]
resources: ["pods", "pods/log"]
verbs: ["get", "list"]
- apiGroups: [""]
resources: ["pods/exec"]
verbs: ["create"]
---
kind: ClusterRoleBinding
apiVersion: rbac.authorization.k8s.io/v1
metadata:
name: mc-shutdown
subjects:
- kind: ServiceAccount
name: mc-shutdown
namespace: default
roleRef:
kind: ClusterRole
name: mc-shutdown
apiGroup: "rbac.authorization.k8s.io"
---
apiVersion: v1
kind: ServiceAccount
metadata:
name: mc-shutdown
---
apiVersion: batch/v1
kind: CronJob
metadata:
name: mc-shutdown
spec:
schedule: "*/5 * * * *"
concurrencyPolicy: Forbid
jobTemplate:
spec:
template:
spec:
serviceAccountName: mc-shutdown
restartPolicy: OnFailure
containers:
- name: shutdown
image: bitnami/kubectl:latest
imagePullPolicy: IfNotPresent
command:
- /bin/bash
- -c
- source shutdown-script.sh
volumeMounts:
- name: shutdown-script
mountPath: /shutdown-script.sh
subPath: shutdown-script.sh
readOnly: true
volumes:
- name: shutdown-script
configMap:
name: shutdown-script
items:
- key: shutdown-script.sh
path: shutdown-script.sh
# uses container label containertype=minecraft-server to find running servers
# TODO: get ownerReferences link to StatefulSet/name from pod metadate instead of sed string manipulation
---
apiVersion: v1
kind: ConfigMap
metadata:
name: shutdown-script
data:
shutdown-script.sh: |
#!/bin/bash
MC_PODS=$(kubectl get pods -l containertype=minecraft-server -o=jsonpath="{range .items[*]}{.metadata.name},"| sed 's/,/\n/g')
for p in $MC_PODS; do
echo "found minecraft pod $p, sleeping 120 seconds to prevent shutdown before login"
sleep 120
deployment=$(echo $p |sed 's/-0//g')
# check online player count in the mc server
if [[ $(kubectl exec -i $p -- /usr/local/bin/mc-monitor status) == *"online=0"* ]] ;then
kubectl scale statefulset $deployment --replicas=0
fi
done
# The actual minecraft servers, services and storage, repeat this block for as many servers as you want
# make sure you have the label containertype=minecraft-server this is used to find running servers
---
apiVersion: apps/v1
kind: StatefulSet
metadata:
name: minecraft-servername-deployment
labels:
app: minecraft-servername-container
spec:
serviceName: minecraft-servername-deployment
selector:
matchLabels:
app: minecraft-servername-container
replicas: 0
template:
metadata:
labels:
app: minecraft-servername-container
containertype: minecraft-server
spec:
containers:
- name: minecraft-servername-deployment
image: itzg/minecraft-server:latest
imagePullPolicy: IfNotPresent
resources:
limits:
memory: "2048Mi"
env:
# Use secret in real usage
- name: EULA
value: "true"
# let the JVM figure out mem management
- name: "MEMORY"
value: ""
- name: JVM_XX_OPTS
value: "-XX:MaxRAMPercentage=75"
ports:
- containerPort: 25565
name: main
readinessProbe:
exec:
command: [ "/usr/local/bin/mc-monitor", "status", "--host", "localhost" ]
# Give it i + p * f seconds to be ready, so 120 seconds
initialDelaySeconds: 20
periodSeconds: 5
failureThreshold: 20
# Monitor ongoing liveness
livenessProbe:
exec:
command: ["/usr/local/bin/mc-monitor", "status", "--host", "localhost"]
initialDelaySeconds: 120
periodSeconds: 60
volumeMounts:
- name: mc-data
mountPath: /data
volumes:
- name: mc-data
persistentVolumeClaim:
claimName: minecraft-servername-pvc
readOnly: false
---
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: minecraft-servername-pvc
namespace: default
spec:
accessModes:
- ReadWriteMany
resources:
requests:
storage: 20Gi
---
apiVersion: v1
kind: Service
metadata:
name: minecraft-servername-deployment
namespace: default
annotations:
"mc-router.itzg.me/externalServerName": "your-awesome-server.public-domain.com"
spec:
ports:
- port: 25565
selector:
app: minecraft-servername-container

View File

@ -0,0 +1,19 @@
version: "3.8"
services:
mc:
image: itzg/minecraft-server
environment:
EULA: true
volumes:
- mc-data:/data
# No port mapping since mc-router connects over compose network
router:
image: itzg/mc-router
environment:
DEFAULT: mc:25565
NGROK_TOKEN: ${NGROK_TOKEN}
# No port mapping needed since it routes through ngrok tunnel
volumes:
mc-data: {}

View File

@ -23,6 +23,7 @@ services:
replicas: 1
labels:
- "mc-router.host=foo.host.name,bar.host.name"
- "mc-router.network=minecraft" # not required in this case
volumes:
- mcfoobardata:/data
networks:
@ -39,6 +40,9 @@ services:
replicas: 1
labels:
- "mc-router.host=baz.host.name"
- "mc-router.network=minecraft" # required since we are exposing a port
ports:
- "25575:25575" # RCON
volumes:
- mcbazdata:/data
networks:

102
go.mod
View File

@ -1,68 +1,98 @@
module github.com/itzg/mc-router
go 1.17
go 1.21
toolchain go1.22.4
require (
github.com/go-kit/kit v0.12.0
github.com/gorilla/mux v1.8.0
github.com/influxdata/influxdb1-client v0.0.0-20200827194710-b269163b24ab
github.com/itzg/go-flagsfiller v1.9.1
github.com/go-kit/kit v0.13.0
github.com/gorilla/mux v1.8.1
github.com/influxdata/influxdb1-client v0.0.0-20220302092344-a9ab5670611c
github.com/itzg/go-flagsfiller v1.14.0
github.com/juju/ratelimit v1.0.2
github.com/pires/go-proxyproto v0.6.2
github.com/pires/go-proxyproto v0.7.0
github.com/pkg/errors v0.9.1
github.com/sirupsen/logrus v1.9.0
github.com/stretchr/testify v1.8.0
golang.org/x/text v0.4.0
k8s.io/api v0.18.5
k8s.io/apimachinery v0.18.5
k8s.io/client-go v0.18.5
github.com/sirupsen/logrus v1.9.3
github.com/stretchr/testify v1.9.0
golang.ngrok.com/ngrok v1.9.1
golang.org/x/text v0.16.0
k8s.io/api v0.28.3
k8s.io/apimachinery v0.28.3
k8s.io/client-go v0.28.3
)
require (
github.com/containerd/log v0.1.0 // indirect
github.com/distribution/reference v0.5.0 // indirect
github.com/emicklei/go-restful/v3 v3.9.0 // indirect
github.com/felixge/httpsnoop v1.0.4 // indirect
github.com/go-logr/logr v1.4.1 // indirect
github.com/go-logr/stdr v1.2.2 // indirect
github.com/go-openapi/jsonpointer v0.19.6 // indirect
github.com/go-openapi/jsonreference v0.20.2 // indirect
github.com/go-openapi/swag v0.22.3 // indirect
github.com/go-stack/stack v1.8.1 // indirect
github.com/google/gnostic-models v0.6.8 // indirect
github.com/inconshreveable/log15 v3.0.0-testing.3+incompatible // indirect
github.com/inconshreveable/log15/v3 v3.0.0-testing.5 // indirect
github.com/josharian/intern v1.0.0 // indirect
github.com/jpillora/backoff v1.0.0 // indirect
github.com/mailru/easyjson v0.7.7 // indirect
github.com/mattn/go-colorable v0.1.13 // indirect
github.com/mattn/go-isatty v0.0.16 // indirect
github.com/moby/docker-image-spec v1.3.1 // indirect
github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 // indirect
go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.47.0 // indirect
go.opentelemetry.io/otel v1.22.0 // indirect
go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.22.0 // indirect
go.opentelemetry.io/otel/metric v1.22.0 // indirect
go.opentelemetry.io/otel/sdk v1.22.0 // indirect
go.opentelemetry.io/otel/trace v1.22.0 // indirect
go.uber.org/multierr v1.11.0 // indirect
golang.ngrok.com/muxado/v2 v2.0.0 // indirect
golang.org/x/sync v0.7.0 // indirect
k8s.io/klog/v2 v2.100.1 // indirect
k8s.io/kube-openapi v0.0.0-20230717233707-2695361300d9 // indirect
sigs.k8s.io/json v0.0.0-20221116044647-bc3834ca7abd // indirect
sigs.k8s.io/structured-merge-diff/v4 v4.2.3 // indirect
)
require (
github.com/Microsoft/go-winio v0.5.2 // indirect
github.com/VividCortex/gohistogram v1.0.0 // indirect
github.com/davecgh/go-spew v1.1.1 // indirect
github.com/docker/distribution v2.8.1+incompatible // indirect
github.com/docker/docker v20.10.19+incompatible
github.com/docker/docker v26.1.4+incompatible
github.com/docker/go-connections v0.4.0 // indirect
github.com/docker/go-units v0.4.0 // indirect
github.com/go-kit/log v0.2.0 // indirect
github.com/go-logfmt/logfmt v0.5.1 // indirect
github.com/gogo/protobuf v1.3.2 // indirect
github.com/golang/protobuf v1.5.2 // indirect
github.com/google/go-cmp v0.5.6 // indirect
github.com/google/gofuzz v1.1.0 // indirect
github.com/google/uuid v1.1.2 // indirect
github.com/googleapis/gnostic v0.2.0 // indirect
github.com/hashicorp/golang-lru v0.5.4 // indirect
github.com/iancoleman/strcase v0.2.0 // indirect
github.com/golang/protobuf v1.5.3 // indirect
github.com/google/go-cmp v0.6.0 // indirect
github.com/google/gofuzz v1.2.0 // indirect
github.com/google/uuid v1.3.0 // indirect
github.com/iancoleman/strcase v0.3.0 // indirect
github.com/imdario/mergo v0.3.7 // indirect
github.com/json-iterator/go v1.1.12 // indirect
github.com/kr/text v0.2.0 // indirect
github.com/moby/term v0.0.0-20210619224110-3f7ff695adc6 // indirect
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect
github.com/modern-go/reflect2 v1.0.2 // indirect
github.com/morikuni/aec v1.0.0 // indirect
github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e // indirect
github.com/opencontainers/go-digest v1.0.0 // indirect
github.com/opencontainers/image-spec v1.0.2 // indirect
github.com/pmezard/go-difflib v1.0.0 // indirect
github.com/spf13/pflag v1.0.5 // indirect
golang.org/x/crypto v0.0.0-20210915214749-c084706c2272 // indirect
golang.org/x/net v0.0.0-20210917221730-978cfadd31cf // indirect
golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45 // indirect
golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f // indirect
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1 // indirect
golang.org/x/time v0.0.0-20210723032227-1f47c861a9ac // indirect
google.golang.org/appengine v1.6.6 // indirect
google.golang.org/protobuf v1.27.1 // indirect
gopkg.in/check.v1 v1.0.0-20200227125254-8fa46927fb4f // indirect
golang.org/x/net v0.23.0 // indirect
golang.org/x/oauth2 v0.8.0 // indirect
golang.org/x/sys v0.18.0 // indirect
golang.org/x/term v0.18.0 // indirect
golang.org/x/time v0.3.0 // indirect
google.golang.org/appengine v1.6.7 // indirect
google.golang.org/protobuf v1.33.0 // indirect
gopkg.in/inf.v0 v0.9.1 // indirect
gopkg.in/yaml.v2 v2.4.0 // indirect
gopkg.in/yaml.v3 v3.0.1 // indirect
gotest.tools/v3 v3.3.0 // indirect
k8s.io/klog v1.0.0 // indirect
k8s.io/utils v0.0.0-20200324210504-a9aa75ae1b89 // indirect
sigs.k8s.io/structured-merge-diff/v3 v3.0.0 // indirect
sigs.k8s.io/yaml v1.2.0 // indirect
k8s.io/utils v0.0.0-20230406110748-d93618cff8a2 // indirect
sigs.k8s.io/yaml v1.3.0 // indirect
)

937
go.sum

File diff suppressed because it is too large Load Diff

View File

@ -160,6 +160,12 @@ func ReadFrame(reader io.Reader, addr net.Addr) (*Frame, error) {
if err != nil {
return nil, err
}
// Limit frame length to 2^21 - 1
if frame.Length > 2097151 {
return nil, errors.Errorf("frame length %d too large", frame.Length)
}
logrus.
WithField("client", addr).
WithField("length", frame.Length).

View File

@ -3,9 +3,10 @@ package server
import (
"bytes"
"context"
"golang.ngrok.com/ngrok"
"golang.ngrok.com/ngrok/config"
"io"
"net"
"strconv"
"sync"
"sync/atomic"
"time"
@ -46,16 +47,32 @@ type Connector struct {
activeConnections int32
connectionsCond *sync.Cond
ngrokToken string
}
func (c *Connector) StartAcceptingConnections(ctx context.Context, listenAddress string, connRateLimit int) error {
ln, err := net.Listen("tcp", listenAddress)
if err != nil {
logrus.WithError(err).Fatal("Unable to start listening")
return err
var ln net.Listener
var err error
if c.ngrokToken != "" {
ngrokTun, err := ngrok.Listen(ctx,
config.TCPEndpoint(),
ngrok.WithAuthtoken(c.ngrokToken),
)
if err != nil {
logrus.WithError(err).Fatal("Unable to start ngrok tunnel")
return err
}
ln = ngrokTun
logrus.WithField("ngrokUrl", ngrokTun.URL()).Info("Listening for Minecraft client connections via ngrok tunnel")
} else {
ln, err = net.Listen("tcp", listenAddress)
if err != nil {
logrus.WithError(err).Fatal("Unable to start listening")
return err
}
logrus.WithField("listenAddress", listenAddress).Info("Listening for Minecraft client connections")
}
logrus.WithField("listenAddress", listenAddress).Info("Listening for Minecraft client connections")
go c.acceptConnections(ctx, ln, connRateLimit)
@ -230,21 +247,29 @@ func (c *Connector) findAndConnectBackend(ctx context.Context, frontendConn net.
// PROXY protocol implementation
if c.sendProxyProto {
remoteHostStr, _, _ := net.SplitHostPort(backendHostPort)
sourceAddrStr, sourcePortStr, _ := net.SplitHostPort(clientAddr.String())
sourcePort, _ := strconv.Atoi(sourcePortStr)
// Determine transport protocol for the PROXY header by "analyzing" the frontend connection's address
transportProtocol := proxyproto.TCPv4
ourHostIpPart, _, err := net.SplitHostPort(frontendConn.LocalAddr().String())
if err != nil {
logrus.
WithError(err).
WithField("localAddr", frontendConn.LocalAddr()).
Error("Failed to extract host part of our address")
_ = backendConn.Close()
return
}
ourFrontendIp := net.ParseIP(ourHostIpPart)
if ourFrontendIp.To4() == nil {
transportProtocol = proxyproto.TCPv6
}
header := &proxyproto.Header{
Version: 2,
Command: proxyproto.PROXY,
TransportProtocol: proxyproto.TCPv4,
SourceAddr: &net.TCPAddr{
IP: net.ParseIP(sourceAddrStr),
Port: sourcePort,
},
DestinationAddr: &net.TCPAddr{
IP: net.ParseIP(remoteHostStr),
},
TransportProtocol: transportProtocol,
SourceAddr: clientAddr,
DestinationAddr: frontendConn.LocalAddr(), // our end of the client's connection
}
_, err = header.WriteTo(backendConn)
@ -322,3 +347,7 @@ func (c *Connector) pumpFrames(incoming io.Reader, outgoing io.Writer, errors ch
errors <- io.EOF
}
}
func (c *Connector) UseNgrok(token string) {
c.ngrokToken = token
}

View File

@ -37,6 +37,7 @@ const (
DockerRouterLabelHost = "mc-router.host"
DockerRouterLabelPort = "mc-router.port"
DockerRouterLabelDefault = "mc-router.default"
DockerRouterLabelNetwork = "mc-router.network"
)
func (w *dockerWatcherImpl) makeWakerFunc(service *routableService) func(ctx context.Context) error {
@ -179,7 +180,7 @@ func (w *dockerWatcherImpl) listServices(ctx context.Context) ([]*routableServic
continue
}
data, ok := w.parseServiceData(&service)
data, ok := w.parseServiceData(&service, networkMap)
if !ok {
continue
}
@ -201,21 +202,46 @@ func (w *dockerWatcherImpl) listServices(ctx context.Context) ([]*routableServic
return result, nil
}
type parsedDockerServiceData struct {
hosts []string
port uint64
def *bool
ip string
func dockerCheckNetworkName(id string, name string, networkMap map[string]*dockertypes.NetworkResource, networkAliases map[string][]string) (bool, error) {
// we allow to specify the id instead
if id == name {
return true, nil
}
if network := networkMap[id]; network != nil {
if network.Name == name {
return true, nil
}
aliases := networkAliases[id]
for _, alias := range aliases {
if alias == name {
return true, nil
}
}
return false, nil
}
return false, fmt.Errorf("network not found %s", id)
}
func (w *dockerWatcherImpl) parseServiceData(service *swarm.Service) (data parsedDockerServiceData, ok bool) {
ok = true
type parsedDockerServiceData struct {
hosts []string
port uint64
def *bool
network *string
ip string
}
func (w *dockerWatcherImpl) parseServiceData(service *swarm.Service, networkMap map[string]*dockertypes.NetworkResource) (data parsedDockerServiceData, ok bool) {
networkAliases := map[string][]string{}
for _, network := range service.Spec.TaskTemplate.Networks {
networkAliases[network.Target] = network.Aliases
}
for key, value := range service.Spec.Labels {
if key == DockerRouterLabelHost {
if data.hosts != nil {
logrus.WithFields(logrus.Fields{"serviceId": service.ID, "serviceName": service.Spec.Name}).
Warnf("ignoring service with duplicate %s", DockerRouterLabelHost)
ok = false
return
}
data.hosts = strings.Split(value, ",")
@ -224,7 +250,6 @@ func (w *dockerWatcherImpl) parseServiceData(service *swarm.Service) (data parse
if data.port != 0 {
logrus.WithFields(logrus.Fields{"serviceId": service.ID, "serviceName": service.Spec.Name}).
Warnf("ignoring service with duplicate %s", DockerRouterLabelPort)
ok = false
return
}
var err error
@ -233,7 +258,6 @@ func (w *dockerWatcherImpl) parseServiceData(service *swarm.Service) (data parse
logrus.WithFields(logrus.Fields{"serviceId": service.ID, "serviceName": service.Spec.Name}).
WithError(err).
Warnf("ignoring service with invalid %s", DockerRouterLabelPort)
ok = false
return
}
}
@ -241,7 +265,6 @@ func (w *dockerWatcherImpl) parseServiceData(service *swarm.Service) (data parse
if data.def != nil {
logrus.WithFields(logrus.Fields{"serviceId": service.ID, "serviceName": service.Spec.Name}).
Warnf("ignoring service with duplicate %s", DockerRouterLabelDefault)
ok = false
return
}
data.def = new(bool)
@ -249,19 +272,58 @@ func (w *dockerWatcherImpl) parseServiceData(service *swarm.Service) (data parse
lowerValue := strings.TrimSpace(strings.ToLower(value))
*data.def = lowerValue != "" && lowerValue != "0" && lowerValue != "false" && lowerValue != "no"
}
if key == DockerRouterLabelNetwork {
if data.network != nil {
logrus.WithFields(logrus.Fields{"serviceId": service.ID, "serviceName": service.Spec.Name}).
Warnf("ignoring service with duplicate %s", DockerRouterLabelNetwork)
return
}
data.network = new(string)
*data.network = value
}
}
// probably not minecraft related
if len(data.hosts) == 0 {
ok = false
return
}
if len(service.Endpoint.VirtualIPs) == 0 {
logrus.WithFields(logrus.Fields{"serviceId": service.ID, "serviceName": service.Spec.Name}).
Warnf("ignoring service, no VirtualIPs found")
return
}
if data.port == 0 {
data.port = 25565
}
virtualIP := service.Endpoint.VirtualIPs[0]
vipIndex := -1
if data.network != nil {
for i, vip := range service.Endpoint.VirtualIPs {
if ok, err := dockerCheckNetworkName(vip.NetworkID, *data.network, networkMap, networkAliases); ok {
vipIndex = i
break
} else if err != nil {
// we intentionally ignore name check errors
logrus.WithFields(logrus.Fields{"serviceId": service.ID, "serviceName": service.Spec.Name}).
Debugf("%v", err)
}
}
if vipIndex == -1 {
logrus.WithFields(logrus.Fields{"serviceId": service.ID, "serviceName": service.Spec.Name}).
Warnf("ignoring service, network %s not found", *data.network)
return
}
} else {
// if network isn't specified assume it's the first one
vipIndex = 0
}
virtualIP := service.Endpoint.VirtualIPs[vipIndex]
ip, _, _ := net.ParseCIDR(virtualIP.Addr)
data.ip = ip.String()
ok = true
return
}

View File

@ -232,7 +232,7 @@ func (w *k8sWatcherImpl) buildDetails(service *core.Service, externalServiceName
clusterIp := service.Spec.ClusterIP
port := "25565"
for _, p := range service.Spec.Ports {
if p.Name == "mc-router" {
if p.Name == "mc-router" || p.Name == "minecraft" {
port = strconv.Itoa(int(p.Port))
}
}

View File

@ -4,6 +4,7 @@ import (
"context"
"encoding/json"
"net/http"
"regexp"
"strings"
"sync"
@ -11,6 +12,8 @@ import (
"github.com/sirupsen/logrus"
)
var tcpShieldPattern = regexp.MustCompile("///.*")
func init() {
apiRoutes.Path("/routes").Methods("GET").
Headers("Accept", "application/json").
@ -37,6 +40,7 @@ func routesListHandler(writer http.ResponseWriter, request *http.Request) {
func routesDeleteHandler(writer http.ResponseWriter, request *http.Request) {
serverAddress := mux.Vars(request)["serverAddress"]
RoutesConfig.DeleteMapping(serverAddress)
if serverAddress != "" {
if Routes.DeleteMapping(serverAddress) {
writer.WriteHeader(http.StatusOK)
@ -63,6 +67,7 @@ func routesCreateHandler(writer http.ResponseWriter, request *http.Request) {
}
Routes.CreateMapping(definition.ServerAddress, definition.Backend, func(ctx context.Context) error { return nil })
RoutesConfig.AddMapping(definition.ServerAddress, definition.Backend)
writer.WriteHeader(http.StatusCreated)
}
@ -82,6 +87,7 @@ func routesSetDefault(writer http.ResponseWriter, request *http.Request) {
}
Routes.SetDefaultRoute(body.Backend)
RoutesConfig.SetDefaultRoute(body.Backend)
writer.WriteHeader(http.StatusOK)
}
@ -174,6 +180,9 @@ func (r *routesImpl) FindBackendForServerAddress(ctx context.Context, serverAddr
// trim the root zone indicator, see https://en.wikipedia.org/wiki/Fully_qualified_domain_name
strings.TrimSuffix(addressParts[0], "."))
// Strip suffix of TCP Shield
address = tcpShieldPattern.ReplaceAllString(address, "")
if r.mappings != nil {
if mapping, exists := r.mappings[address]; exists {
return mapping.backend, address, mapping.waker

173
server/routes_config.go Normal file
View File

@ -0,0 +1,173 @@
package server
import (
"encoding/json"
"github.com/pkg/errors"
"github.com/sirupsen/logrus"
"io/fs"
"os"
"sync"
)
type IRoutesConfig interface {
ReadRoutesConfig(routesConfig string)
AddMapping(serverAddress string, backend string)
DeleteMapping(serverAddress string)
SetDefaultRoute(backend string)
}
var RoutesConfig = &routesConfigImpl{}
type routesConfigImpl struct {
sync.RWMutex
fileName string
}
type routesConfigStructure struct {
DefaultServer string `json:"default-server"`
Mappings map[string]string `json:"mappings"`
}
func (r *routesConfigImpl) ReadRoutesConfig(routesConfig string) error {
r.fileName = routesConfig
logrus.WithField("routesConfig", r.fileName).Info("Loading routes config file")
config, readErr := r.readRoutesConfigFile()
if readErr != nil {
if errors.Is(readErr, fs.ErrNotExist) {
logrus.WithField("routesConfig", r.fileName).Info("Routes config file doses not exist, skipping reading it")
// File doesn't exist -> ignore it
return nil
}
return errors.Wrap(readErr, "Could not load the routes config file")
}
Routes.RegisterAll(config.Mappings)
Routes.SetDefaultRoute(config.DefaultServer)
return nil
}
func (r *routesConfigImpl) AddMapping(serverAddress string, backend string) {
if !r.isRoutesConfigEnabled() {
return
}
config, readErr := r.readRoutesConfigFile()
if readErr != nil && !errors.Is(readErr, fs.ErrNotExist) {
logrus.WithError(readErr).Error("Could not read the routes config file")
return
}
if config.Mappings == nil {
config.Mappings = make(map[string]string)
}
config.Mappings[serverAddress] = backend
writeErr := r.writeRoutesConfigFile(config)
if writeErr != nil {
logrus.WithError(writeErr).Error("Could not write to the routes config file")
return
}
logrus.WithFields(logrus.Fields{
"serverAddress": serverAddress,
"backend": backend,
}).Info("Added route to routes config")
return
}
func (r *routesConfigImpl) SetDefaultRoute(backend string) {
if !r.isRoutesConfigEnabled() {
return
}
config, readErr := r.readRoutesConfigFile()
if readErr != nil && !errors.Is(readErr, fs.ErrNotExist) {
logrus.WithError(readErr).Error("Could not read the routes config file")
return
}
config.DefaultServer = backend
writeErr := r.writeRoutesConfigFile(config)
if writeErr != nil {
logrus.WithError(writeErr).Error("Could not write to the routes config file")
return
}
logrus.WithFields(logrus.Fields{
"backend": backend,
}).Info("Set default route in routes config")
return
}
func (r *routesConfigImpl) DeleteMapping(serverAddress string) {
if !r.isRoutesConfigEnabled() {
return
}
config, readErr := r.readRoutesConfigFile()
if readErr != nil && !errors.Is(readErr, fs.ErrNotExist) {
logrus.WithError(readErr).Error("Could not read the routes config file")
return
}
delete(config.Mappings, serverAddress)
writeErr := r.writeRoutesConfigFile(config)
if writeErr != nil {
logrus.WithError(writeErr).Error("Could not write to the routes config file")
return
}
logrus.WithField("serverAddress", serverAddress).Info("Deleted route in routes config")
return
}
func (r *routesConfigImpl) isRoutesConfigEnabled() bool {
return r.fileName != ""
}
func (r *routesConfigImpl) readRoutesConfigFile() (routesConfigStructure, error) {
r.RLock()
defer r.RUnlock()
config := routesConfigStructure{
"",
make(map[string]string),
}
file, fileErr := os.ReadFile(r.fileName)
if fileErr != nil {
return config, errors.Wrap(fileErr, "Could not load the routes config file")
}
parseErr := json.Unmarshal(file, &config)
if parseErr != nil {
return config, errors.Wrap(parseErr, "Could not parse the json routes config file")
}
return config, nil
}
func (r *routesConfigImpl) writeRoutesConfigFile(config routesConfigStructure) error {
r.Lock()
defer r.Unlock()
newFileContent, parseErr := json.Marshal(config)
if parseErr != nil {
return errors.Wrap(parseErr, "Could not parse the routes to json")
}
fileErr := os.WriteFile(r.fileName, newFileContent, 0664)
if fileErr != nil {
return errors.Wrap(fileErr, "Could not write to the routes config file")
}
return nil
}