mirror of
https://github.com/tailscale/tailscale.git
synced 2024-12-11 10:44:41 +00:00
IPN: Update ServeConfig to accept configuration for Services.
This commit updates ServeConfig to allow configuration to Services (VIPServices for now) via Serve. The scope of this commit is only adding the Services field to ServeConfig. The field doesn't actually allow packet flowing yet. The purpose of this commit is to unblock other work on k8s end. Updates #22953 Signed-off-by: KevinLiang10 <37811973+KevinLiang10@users.noreply.github.com>
This commit is contained in:
parent
8d0c690f89
commit
3f54572539
@ -1,7 +1,7 @@
|
||||
// Copyright (c) Tailscale Inc & AUTHORS
|
||||
// SPDX-License-Identifier: BSD-3-Clause
|
||||
|
||||
//go:generate go run tailscale.com/cmd/viewer -type=Prefs,ServeConfig,TCPPortHandler,HTTPHandler,WebServerConfig
|
||||
//go:generate go run tailscale.com/cmd/viewer -type=Prefs,ServeConfig,ServiceConfig,TCPPortHandler,HTTPHandler,WebServerConfig
|
||||
|
||||
// Package ipn implements the interactions between the Tailscale cloud
|
||||
// control plane and the local network stack.
|
||||
|
@ -105,6 +105,16 @@ func (src *ServeConfig) Clone() *ServeConfig {
|
||||
}
|
||||
}
|
||||
}
|
||||
if dst.Services != nil {
|
||||
dst.Services = map[string]*ServiceConfig{}
|
||||
for k, v := range src.Services {
|
||||
if v == nil {
|
||||
dst.Services[k] = nil
|
||||
} else {
|
||||
dst.Services[k] = v.Clone()
|
||||
}
|
||||
}
|
||||
}
|
||||
dst.AllowFunnel = maps.Clone(src.AllowFunnel)
|
||||
if dst.Foreground != nil {
|
||||
dst.Foreground = map[string]*ServeConfig{}
|
||||
@ -123,11 +133,50 @@ func (src *ServeConfig) Clone() *ServeConfig {
|
||||
var _ServeConfigCloneNeedsRegeneration = ServeConfig(struct {
|
||||
TCP map[uint16]*TCPPortHandler
|
||||
Web map[HostPort]*WebServerConfig
|
||||
Services map[string]*ServiceConfig
|
||||
AllowFunnel map[HostPort]bool
|
||||
Foreground map[string]*ServeConfig
|
||||
ETag string
|
||||
}{})
|
||||
|
||||
// Clone makes a deep copy of ServiceConfig.
|
||||
// The result aliases no memory with the original.
|
||||
func (src *ServiceConfig) Clone() *ServiceConfig {
|
||||
if src == nil {
|
||||
return nil
|
||||
}
|
||||
dst := new(ServiceConfig)
|
||||
*dst = *src
|
||||
if dst.TCP != nil {
|
||||
dst.TCP = map[uint16]*TCPPortHandler{}
|
||||
for k, v := range src.TCP {
|
||||
if v == nil {
|
||||
dst.TCP[k] = nil
|
||||
} else {
|
||||
dst.TCP[k] = ptr.To(*v)
|
||||
}
|
||||
}
|
||||
}
|
||||
if dst.Web != nil {
|
||||
dst.Web = map[HostPort]*WebServerConfig{}
|
||||
for k, v := range src.Web {
|
||||
if v == nil {
|
||||
dst.Web[k] = nil
|
||||
} else {
|
||||
dst.Web[k] = v.Clone()
|
||||
}
|
||||
}
|
||||
}
|
||||
return dst
|
||||
}
|
||||
|
||||
// A compilation failure here means this code must be regenerated, with the command at the top of this file.
|
||||
var _ServiceConfigCloneNeedsRegeneration = ServiceConfig(struct {
|
||||
TCP map[uint16]*TCPPortHandler
|
||||
Web map[HostPort]*WebServerConfig
|
||||
Tun bool
|
||||
}{})
|
||||
|
||||
// Clone makes a deep copy of TCPPortHandler.
|
||||
// The result aliases no memory with the original.
|
||||
func (src *TCPPortHandler) Clone() *TCPPortHandler {
|
||||
|
@ -18,7 +18,7 @@
|
||||
"tailscale.com/types/views"
|
||||
)
|
||||
|
||||
//go:generate go run tailscale.com/cmd/cloner -clonefunc=false -type=Prefs,ServeConfig,TCPPortHandler,HTTPHandler,WebServerConfig
|
||||
//go:generate go run tailscale.com/cmd/cloner -clonefunc=false -type=Prefs,ServeConfig,ServiceConfig,TCPPortHandler,HTTPHandler,WebServerConfig
|
||||
|
||||
// View returns a readonly view of Prefs.
|
||||
func (p *Prefs) View() PrefsView {
|
||||
@ -195,6 +195,12 @@ func (v ServeConfigView) Web() views.MapFn[HostPort, *WebServerConfig, WebServer
|
||||
})
|
||||
}
|
||||
|
||||
func (v ServeConfigView) Services() views.MapFn[string, *ServiceConfig, ServiceConfigView] {
|
||||
return views.MapFnOf(v.ж.Services, func(t *ServiceConfig) ServiceConfigView {
|
||||
return t.View()
|
||||
})
|
||||
}
|
||||
|
||||
func (v ServeConfigView) AllowFunnel() views.Map[HostPort, bool] {
|
||||
return views.MapOf(v.ж.AllowFunnel)
|
||||
}
|
||||
@ -210,11 +216,77 @@ func (v ServeConfigView) ETag() string { return v.ж.ETag }
|
||||
var _ServeConfigViewNeedsRegeneration = ServeConfig(struct {
|
||||
TCP map[uint16]*TCPPortHandler
|
||||
Web map[HostPort]*WebServerConfig
|
||||
Services map[string]*ServiceConfig
|
||||
AllowFunnel map[HostPort]bool
|
||||
Foreground map[string]*ServeConfig
|
||||
ETag string
|
||||
}{})
|
||||
|
||||
// View returns a readonly view of ServiceConfig.
|
||||
func (p *ServiceConfig) View() ServiceConfigView {
|
||||
return ServiceConfigView{ж: p}
|
||||
}
|
||||
|
||||
// ServiceConfigView provides a read-only view over ServiceConfig.
|
||||
//
|
||||
// Its methods should only be called if `Valid()` returns true.
|
||||
type ServiceConfigView struct {
|
||||
// ж is the underlying mutable value, named with a hard-to-type
|
||||
// character that looks pointy like a pointer.
|
||||
// It is named distinctively to make you think of how dangerous it is to escape
|
||||
// to callers. You must not let callers be able to mutate it.
|
||||
ж *ServiceConfig
|
||||
}
|
||||
|
||||
// Valid reports whether underlying value is non-nil.
|
||||
func (v ServiceConfigView) Valid() bool { return v.ж != nil }
|
||||
|
||||
// AsStruct returns a clone of the underlying value which aliases no memory with
|
||||
// the original.
|
||||
func (v ServiceConfigView) AsStruct() *ServiceConfig {
|
||||
if v.ж == nil {
|
||||
return nil
|
||||
}
|
||||
return v.ж.Clone()
|
||||
}
|
||||
|
||||
func (v ServiceConfigView) MarshalJSON() ([]byte, error) { return json.Marshal(v.ж) }
|
||||
|
||||
func (v *ServiceConfigView) UnmarshalJSON(b []byte) error {
|
||||
if v.ж != nil {
|
||||
return errors.New("already initialized")
|
||||
}
|
||||
if len(b) == 0 {
|
||||
return nil
|
||||
}
|
||||
var x ServiceConfig
|
||||
if err := json.Unmarshal(b, &x); err != nil {
|
||||
return err
|
||||
}
|
||||
v.ж = &x
|
||||
return nil
|
||||
}
|
||||
|
||||
func (v ServiceConfigView) TCP() views.MapFn[uint16, *TCPPortHandler, TCPPortHandlerView] {
|
||||
return views.MapFnOf(v.ж.TCP, func(t *TCPPortHandler) TCPPortHandlerView {
|
||||
return t.View()
|
||||
})
|
||||
}
|
||||
|
||||
func (v ServiceConfigView) Web() views.MapFn[HostPort, *WebServerConfig, WebServerConfigView] {
|
||||
return views.MapFnOf(v.ж.Web, func(t *WebServerConfig) WebServerConfigView {
|
||||
return t.View()
|
||||
})
|
||||
}
|
||||
func (v ServiceConfigView) Tun() bool { return v.ж.Tun }
|
||||
|
||||
// A compilation failure here means this code must be regenerated, with the command at the top of this file.
|
||||
var _ServiceConfigViewNeedsRegeneration = ServiceConfig(struct {
|
||||
TCP map[uint16]*TCPPortHandler
|
||||
Web map[HostPort]*WebServerConfig
|
||||
Tun bool
|
||||
}{})
|
||||
|
||||
// View returns a readonly view of TCPPortHandler.
|
||||
func (p *TCPPortHandler) View() TCPPortHandlerView {
|
||||
return TCPPortHandlerView{ж: p}
|
||||
|
21
ipn/serve.go
21
ipn/serve.go
@ -24,6 +24,23 @@ func ServeConfigKey(profileID ProfileID) StateKey {
|
||||
return StateKey("_serve/" + profileID)
|
||||
}
|
||||
|
||||
// ServiceConfig contains the config information for a single service.
|
||||
// it contains a bool to indicate if the service is in Tun mode (L3 forwarding).
|
||||
// If the service is not in Tun mode, the service is configured by the L4 forwarding
|
||||
// (TCP ports) and/or the L7 forwarding (http handlers) information.
|
||||
type ServiceConfig struct {
|
||||
// TCP are the list of TCP port numbers that tailscaled should handle for
|
||||
// the Tailscale IP addresses. (not subnet routers, etc)
|
||||
TCP map[uint16]*TCPPortHandler `json:",omitempty"`
|
||||
|
||||
// Web maps from "$SNI_NAME:$PORT" to a set of HTTP handlers
|
||||
// keyed by mount point ("/", "/foo", etc)
|
||||
Web map[HostPort]*WebServerConfig `json:",omitempty"`
|
||||
|
||||
// Tun determines if the service should be using L3 forwarding (Tun mode).
|
||||
Tun bool `json:",omitempty"`
|
||||
}
|
||||
|
||||
// ServeConfig is the JSON type stored in the StateStore for
|
||||
// StateKey "_serve/$PROFILE_ID" as returned by ServeConfigKey.
|
||||
type ServeConfig struct {
|
||||
@ -35,6 +52,10 @@ type ServeConfig struct {
|
||||
// keyed by mount point ("/", "/foo", etc)
|
||||
Web map[HostPort]*WebServerConfig `json:",omitempty"`
|
||||
|
||||
// Services maps from service name to a ServiceConfig. Which describes the
|
||||
// L3, L4, and L7 forwarding information for the service.
|
||||
Services map[string]*ServiceConfig `json:",omitempty"`
|
||||
|
||||
// AllowFunnel is the set of SNI:port values for which funnel
|
||||
// traffic is allowed, from trusted ingress peers.
|
||||
AllowFunnel map[HostPort]bool `json:",omitempty"`
|
||||
|
Loading…
Reference in New Issue
Block a user