feat(dns): serve machine IP at /.uncloud-verify to verify Caddy reachability

This commit is contained in:
Pavel Sviderski
2025-02-25 17:36:44 +10:00
parent 0ea997e826
commit d0fd9db258
2 changed files with 57 additions and 8 deletions
+54 -7
View File
@@ -11,6 +11,7 @@ import (
"github.com/caddyserver/caddy/v2/modules/caddyhttp/reverseproxy" "github.com/caddyserver/caddy/v2/modules/caddyhttp/reverseproxy"
"log/slog" "log/slog"
"net" "net"
"net/http"
"os" "os"
"path/filepath" "path/filepath"
"strconv" "strconv"
@@ -20,17 +21,21 @@ import (
"uncloud/internal/machine/store" "uncloud/internal/machine/store"
) )
const CaddyGroup = "uncloud" const (
CaddyGroup = "uncloud"
VerifyPath = "/.uncloud-verify"
)
// Controller monitors container changes in the cluster store and generates a configuration file for Caddy reverse // Controller monitors container changes in the cluster store and generates a configuration file for Caddy reverse
// proxy. The generated Caddyfile allows Caddy to route external traffic to service containers across the internal // proxy. The generated Caddyfile allows Caddy to route external traffic to service containers across the internal
// network. // network.
type Controller struct { type Controller struct {
store *store.Store store *store.Store
path string path string
verifyResponse string
} }
func NewController(store *store.Store, path string) (*Controller, error) { func NewController(store *store.Store, path string, verifyResponse string) (*Controller, error) {
dir := filepath.Dir(path) dir := filepath.Dir(path)
if err := os.MkdirAll(dir, 0750); err != nil { if err := os.MkdirAll(dir, 0750); err != nil {
return nil, fmt.Errorf("create parent directory for Caddy configuration '%s': %w", dir, err) return nil, fmt.Errorf("create parent directory for Caddy configuration '%s': %w", dir, err)
@@ -40,8 +45,9 @@ func NewController(store *store.Store, path string) (*Controller, error) {
} }
return &Controller{ return &Controller{
store: store, store: store,
path: path, path: path,
verifyResponse: verifyResponse,
}, nil }, nil
} }
@@ -144,7 +150,11 @@ func (c *Controller) generateConfig(containers []api.Container) error {
servers := make(map[string]*caddyhttp.Server) servers := make(map[string]*caddyhttp.Server)
servers["http"] = &caddyhttp.Server{ servers["http"] = &caddyhttp.Server{
Listen: []string{fmt.Sprintf(":%d", caddyhttp.DefaultHTTPPort)}, Listen: []string{fmt.Sprintf(":%d", caddyhttp.DefaultHTTPPort)},
Routes: hostUpstreamsToRoutes(httpHostUpstreams, &warnings), Routes: append(
hostUpstreamsToRoutes(httpHostUpstreams, &warnings),
// Add a route to respond with a static verification response at the /.uncloud-verify path.
verificationRoute(c.verifyResponse, &warnings),
),
} }
servers["https"] = &caddyhttp.Server{ servers["https"] = &caddyhttp.Server{
Listen: []string{fmt.Sprintf(":%d", caddyhttp.DefaultHTTPSPort)}, Listen: []string{fmt.Sprintf(":%d", caddyhttp.DefaultHTTPSPort)},
@@ -211,3 +221,40 @@ func hostUpstreamsToRoutes(hostUpstreams map[string][]string, warnings *[]caddyc
} }
return routes return routes
} }
// verificationRoute returns a Caddy route that responds with the given static response at the /.uncloud-verify path.
func verificationRoute(response string, warnings *[]caddyconfig.Warning) caddyhttp.Route {
// Return the following route:
// {
// "match": [
// {
// "path": [
// "/.uncloud-verify"
// ]
// }
// ],
// "handle": [
// {
// "handler": "static_response",
// "body": "<response>",
// "status_code": 200
// }
// ]
// }
staticResponse := caddyhttp.StaticResponse{
StatusCode: caddyhttp.WeakString(strconv.Itoa(http.StatusOK)),
Body: response,
}
return caddyhttp.Route{
MatcherSetsRaw: caddyhttp.RawMatcherSets{
{
"path": caddyconfig.JSON(caddyhttp.MatchPath{VerifyPath}, warnings),
},
},
HandlersRaw: []json.RawMessage{
caddyconfig.JSONModuleObject(staticResponse, "handler", "static_response", warnings),
},
}
}
+3 -1
View File
@@ -357,7 +357,9 @@ func (m *Machine) Run(ctx context.Context) error {
), ),
) )
caddyfileCtrl, err := caddyfile.NewController(m.store, m.config.CaddyfilePath) // Create a new Caddyfile controller for managing the Caddy reverse proxy configuration.
// It will also serve the current machine ID at /.uncloud-verify to verify Caddy reachability.
caddyfileCtrl, err := caddyfile.NewController(m.store, m.config.CaddyfilePath, m.state.ID)
if err != nil { if err != nil {
return fmt.Errorf("create Caddyfile controller: %w", err) return fmt.Errorf("create Caddyfile controller: %w", err)
} }