chore: use "handle-like" resource in DNSResolveCacheController
Rework (and simplify) `DNSResolveCacheController` to use `DNSUpstream` "handle-like" resources. Depends on https://github.com/cosi-project/runtime/pull/400 Signed-off-by: Dmitriy Matrenichev <dmitry.matrenichev@siderolabs.com>
This commit is contained in:
parent
013e130702
commit
afa71d6b02
Binary file not shown.
@ -93,7 +93,6 @@ message DHCP6OperatorSpec {
|
||||
// DNSResolveCacheSpec describes DNS servers status.
|
||||
message DNSResolveCacheSpec {
|
||||
string status = 1;
|
||||
repeated common.NetIP servers = 2;
|
||||
}
|
||||
|
||||
// HardwareAddrSpec describes spec for the link.
|
||||
|
4
go.mod
4
go.mod
@ -47,7 +47,7 @@ require (
|
||||
github.com/containernetworking/plugins v1.4.0
|
||||
github.com/coredns/coredns v1.11.1
|
||||
github.com/coreos/go-iptables v0.7.0
|
||||
github.com/cosi-project/runtime v0.3.20
|
||||
github.com/cosi-project/runtime v0.4.0-alpha.4
|
||||
github.com/distribution/reference v0.5.0
|
||||
github.com/docker/docker v25.0.2+incompatible
|
||||
github.com/docker/go-connections v0.5.0
|
||||
@ -235,7 +235,7 @@ require (
|
||||
github.com/gorilla/websocket v1.5.0 // indirect
|
||||
github.com/gosuri/uilive v0.0.4 // indirect
|
||||
github.com/gregjones/httpcache v0.0.0-20180305231024-9cad4c3443a7 // indirect
|
||||
github.com/grpc-ecosystem/grpc-gateway/v2 v2.18.1 // indirect
|
||||
github.com/grpc-ecosystem/grpc-gateway/v2 v2.19.0 // indirect
|
||||
github.com/hashicorp/errwrap v1.1.0 // indirect
|
||||
github.com/hashicorp/go-safetemp v1.0.0 // indirect
|
||||
github.com/hashicorp/go-version v1.6.0 // indirect
|
||||
|
8
go.sum
8
go.sum
@ -184,8 +184,8 @@ github.com/coreos/go-semver v0.3.1 h1:yi21YpKnrx1gt5R+la8n5WgS0kCrsPp33dmEyHReZr
|
||||
github.com/coreos/go-semver v0.3.1/go.mod h1:irMmmIw/7yzSRPWryHsK7EYSg09caPQL03VsM8rvUec=
|
||||
github.com/coreos/go-systemd/v22 v22.5.0 h1:RrqgGjYQKalulkV8NGVIfkXQf6YYmOyiJKk8iXXhfZs=
|
||||
github.com/coreos/go-systemd/v22 v22.5.0/go.mod h1:Y58oyj3AT4RCenI/lSvhwexgC+NSVTIJ3seZv2GcEnc=
|
||||
github.com/cosi-project/runtime v0.3.20 h1:pl8mwbHMFIRFYV8v0Glxw2ruhTXn/5ij7TSlO9nApi4=
|
||||
github.com/cosi-project/runtime v0.3.20/go.mod h1:3DQsIr7zF/bmWfHOnpHmOQ9mDukFGi8AMoHx2rNsi+s=
|
||||
github.com/cosi-project/runtime v0.4.0-alpha.4 h1:3TN+Y0NVKa/1QXqR3QTJ6ceWrcflyUeIZbQnrU2BprM=
|
||||
github.com/cosi-project/runtime v0.4.0-alpha.4/go.mod h1:JE9yuyufGRCd28AyCWFkTNf3UMiZJT722bpfPEPnsNE=
|
||||
github.com/cpuguy83/go-md2man/v2 v2.0.2/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o=
|
||||
github.com/cpuguy83/go-md2man/v2 v2.0.3 h1:qMCsGGgs+MAzDFyp9LpAe1Lqy/fY/qCovCm0qnXZOBM=
|
||||
github.com/cpuguy83/go-md2man/v2 v2.0.3/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o=
|
||||
@ -397,8 +397,8 @@ github.com/gregjones/httpcache v0.0.0-20180305231024-9cad4c3443a7 h1:pdN6V1QBWet
|
||||
github.com/gregjones/httpcache v0.0.0-20180305231024-9cad4c3443a7/go.mod h1:FecbI9+v66THATjSRHfNgh1IVFe/9kFxbXtjV0ctIMA=
|
||||
github.com/grpc-ecosystem/go-grpc-middleware v1.4.0 h1:UH//fgunKIs4JdUbpDl1VZCDaL56wXCB/5+wF6uHfaI=
|
||||
github.com/grpc-ecosystem/go-grpc-middleware v1.4.0/go.mod h1:g5qyo/la0ALbONm6Vbp88Yd8NsDy6rZz+RcrMPxvld8=
|
||||
github.com/grpc-ecosystem/grpc-gateway/v2 v2.18.1 h1:6UKoz5ujsI55KNpsJH3UwCq3T8kKbZwNZBNPuTTje8U=
|
||||
github.com/grpc-ecosystem/grpc-gateway/v2 v2.18.1/go.mod h1:YvJ2f6MplWDhfxiUC3KpyTy76kYUZA4W3pTv/wdKQ9Y=
|
||||
github.com/grpc-ecosystem/grpc-gateway/v2 v2.19.0 h1:Wqo399gCIufwto+VfwCSvsnfGpF/w5E9CNxSwbpD6No=
|
||||
github.com/grpc-ecosystem/grpc-gateway/v2 v2.19.0/go.mod h1:qmOFXW2epJhM0qSnUUYpldc7gVz2KMQwJ/QYCDIa7XU=
|
||||
github.com/hashicorp/errwrap v1.0.0/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4=
|
||||
github.com/hashicorp/errwrap v1.1.0 h1:OxrOeh75EUXMY8TBjag2fzXGZ40LB6IKw45YeGUDY2I=
|
||||
github.com/hashicorp/errwrap v1.1.0/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4=
|
||||
|
@ -6,8 +6,6 @@ github.com/Azure/azure-sdk-for-go/sdk/azidentity v1.5.1 h1:sO0/P7g68FrryJzljemN+
|
||||
github.com/Azure/azure-sdk-for-go/sdk/azidentity v1.5.1/go.mod h1:h8hyGFDsU5HMivxiS2iYFZsgDbU9OnnJ163x5UGVKYo=
|
||||
github.com/Azure/azure-sdk-for-go/sdk/internal v1.5.1 h1:6oNBlSdi1QqM1PNW7FPA6xOGA5UNsXnkaYZz9vdPGhA=
|
||||
github.com/Azure/azure-sdk-for-go/sdk/internal v1.5.1/go.mod h1:s4kgfzA0covAXNicZHDMN58jExvcng2mC/DepXiF1EI=
|
||||
github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/compute/armcompute/v5 v5.4.0 h1:QfV5XZt6iNa2aWMAt96CZEbfJ7kgG/qYIpq465Shr5E=
|
||||
github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/compute/armcompute/v5 v5.4.0/go.mod h1:uYt4CfhkJA9o0FN7jfE5minm/i4nUE4MjGUJkzB6Zs8=
|
||||
github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/compute/armcompute/v5 v5.5.0 h1:MxA59PGoCFb+vCwRQi3PhQEwHj4+r2dhuv9HG+vM7iM=
|
||||
github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/compute/armcompute/v5 v5.5.0/go.mod h1:uYt4CfhkJA9o0FN7jfE5minm/i4nUE4MjGUJkzB6Zs8=
|
||||
github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/internal/v2 v2.0.0 h1:PTFGRSlMKCQelWwxUyYVEUqseBJVemLyqWJjvMyt0do=
|
||||
@ -47,8 +45,6 @@ github.com/Azure/go-autorest/tracing v0.6.0 h1:TYi4+3m5t6K48TGI9AUdb+IzbnSxvnvUM
|
||||
github.com/Azure/go-autorest/tracing v0.6.0/go.mod h1:+vhtPC754Xsa23ID7GlGsrdKBpUA79WCAKPPZVC2DeU=
|
||||
github.com/AzureAD/microsoft-authentication-library-for-go v1.2.1 h1:DzHpqpoJVaCgOUdVHxE8QB52S6NiVdDQvGlny1qvPqA=
|
||||
github.com/AzureAD/microsoft-authentication-library-for-go v1.2.1/go.mod h1:wP83P5OoQ5p6ip3ScPr0BAq0BvuPAvacpEuSzyouqAI=
|
||||
github.com/aws/aws-sdk-go v1.50.5 h1:H2Aadcgwr7a2aqS6ZwcE+l1mA6ZrTseYCvjw2QLmxIA=
|
||||
github.com/aws/aws-sdk-go v1.50.5/go.mod h1:LF8svs817+Nz+DmiMQKTO3ubZ/6IaTpq3TjupRn3Eqk=
|
||||
github.com/aws/aws-sdk-go v1.50.8 h1:gY0WoOW+/Wz6XmYSgDH9ge3wnAevYDSQWPxxJvqAkP4=
|
||||
github.com/aws/aws-sdk-go v1.50.8/go.mod h1:LF8svs817+Nz+DmiMQKTO3ubZ/6IaTpq3TjupRn3Eqk=
|
||||
github.com/blang/semver/v4 v4.0.0 h1:1PFHFE6yCCTv8C1TeyNNarDzntLi7wMI5i/pzqYIsAM=
|
||||
|
@ -44,6 +44,10 @@ func (s *InspectServer) ControllerRuntimeDependencies(ctx context.Context, in *e
|
||||
edgeType = inspectapi.DependencyEdgeType_INPUT_WEAK
|
||||
case controller.EdgeInputDestroyReady:
|
||||
edgeType = inspectapi.DependencyEdgeType_INPUT_DESTROY_READY
|
||||
case controller.EdgeInputQPrimary,
|
||||
controller.EdgeInputQMapped,
|
||||
controller.EdgeInputQMappedDestroyReady:
|
||||
return nil, fmt.Errorf("unexpected edge type: %v", graph.Edges[i].EdgeType)
|
||||
}
|
||||
|
||||
edges = append(edges, &inspectapi.ControllerDependencyEdge{
|
||||
|
@ -9,16 +9,15 @@ import (
|
||||
"fmt"
|
||||
"time"
|
||||
|
||||
"github.com/coredns/coredns/plugin/pkg/proxy"
|
||||
"github.com/cosi-project/runtime/pkg/controller"
|
||||
"github.com/cosi-project/runtime/pkg/resource"
|
||||
"github.com/cosi-project/runtime/pkg/safe"
|
||||
"github.com/cosi-project/runtime/pkg/state"
|
||||
"github.com/siderolabs/gen/optional"
|
||||
"go.uber.org/zap"
|
||||
|
||||
"github.com/siderolabs/talos/internal/pkg/ctxutil"
|
||||
"github.com/siderolabs/talos/internal/pkg/dns"
|
||||
"github.com/siderolabs/talos/pkg/machinery/resources/config"
|
||||
"github.com/siderolabs/talos/pkg/machinery/resources/network"
|
||||
)
|
||||
|
||||
@ -36,18 +35,7 @@ func (ctrl *DNSResolveCacheController) Name() string {
|
||||
// Inputs implements controller.Controller interface.
|
||||
func (ctrl *DNSResolveCacheController) Inputs() []controller.Input {
|
||||
return []controller.Input{
|
||||
{
|
||||
Namespace: network.NamespaceName,
|
||||
Type: network.ResolverStatusType,
|
||||
ID: optional.Some(network.ResolverID),
|
||||
Kind: controller.InputWeak,
|
||||
},
|
||||
{
|
||||
Namespace: config.NamespaceName,
|
||||
Type: config.MachineConfigType,
|
||||
ID: optional.Some(config.V1Alpha1ID),
|
||||
Kind: controller.InputWeak,
|
||||
},
|
||||
safe.Input[*network.DNSUpstream](controller.InputWeak),
|
||||
}
|
||||
}
|
||||
|
||||
@ -70,22 +58,18 @@ func (ctrl *DNSResolveCacheController) Run(ctx context.Context, r controller.Run
|
||||
case <-r.EventCh():
|
||||
}
|
||||
|
||||
mc, err := safe.ReaderGetByID[*config.MachineConfig](ctx, r, config.V1Alpha1ID)
|
||||
upstreams, err := safe.ReaderListAll[*network.DNSUpstream](ctx, r)
|
||||
if err != nil {
|
||||
if state.IsNotFoundError(err) {
|
||||
continue
|
||||
}
|
||||
|
||||
return err
|
||||
return fmt.Errorf("error getting resolver status: %w", err)
|
||||
}
|
||||
|
||||
if !mc.Config().Machine().Features().LocalDNSEnabled() {
|
||||
if upstreams.Len() == 0 {
|
||||
continue
|
||||
}
|
||||
|
||||
err = func() error {
|
||||
ctrl.Logger.Info("starting dns cache resolve")
|
||||
defer ctrl.Logger.Info("stopping dns cache resolve")
|
||||
ctrl.Logger.Info("starting dns caching resolver")
|
||||
defer ctrl.Logger.Info("stopping dns caching resolver")
|
||||
|
||||
return ctrl.runServer(ctx, r)
|
||||
}()
|
||||
@ -95,10 +79,9 @@ func (ctrl *DNSResolveCacheController) Run(ctx context.Context, r controller.Run
|
||||
}
|
||||
}
|
||||
|
||||
func (ctrl *DNSResolveCacheController) writeDNSStatus(ctx context.Context, r controller.Runtime, net resource.ID, handler *dns.Handler) error {
|
||||
func (ctrl *DNSResolveCacheController) writeDNSStatus(ctx context.Context, r controller.Runtime, net resource.ID) error {
|
||||
return safe.WriterModify(ctx, r, network.NewDNSResolveCache(net), func(drc *network.DNSResolveCache) error {
|
||||
drc.TypedSpec().Status = "running"
|
||||
drc.TypedSpec().Servers = handler.ProxyList()
|
||||
|
||||
return nil
|
||||
})
|
||||
@ -140,7 +123,7 @@ func (ctrl *DNSResolveCacheController) runServer(originCtx context.Context, r co
|
||||
|
||||
runner := dns.NewRunner(dns.NewServer(opt), l)
|
||||
|
||||
err := ctrl.writeDNSStatus(ctx, r, opt.Net, handler)
|
||||
err := ctrl.writeDNSStatus(ctx, r, opt.Net)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@ -164,33 +147,31 @@ func (ctrl *DNSResolveCacheController) runServer(originCtx context.Context, r co
|
||||
|
||||
eventCh = r.EventCh()
|
||||
|
||||
mc, err := safe.ReaderGetByID[*config.MachineConfig](ctx, r, config.V1Alpha1ID)
|
||||
upstreams, err := safe.ReaderListAll[*network.DNSUpstream](ctx, r)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if !mc.Config().Machine().Features().LocalDNSEnabled() {
|
||||
return nil
|
||||
}
|
||||
|
||||
resolverStatus, err := safe.ReaderGetByID[*network.ResolverStatus](ctx, r, network.ResolverID)
|
||||
if err != nil {
|
||||
if state.IsNotFoundError(err) {
|
||||
continue
|
||||
}
|
||||
|
||||
return fmt.Errorf("error getting resolver status: %w", err)
|
||||
}
|
||||
|
||||
ctrl.Logger.Info("updating dns server nameservers", zap.Stringers("data", resolverStatus.TypedSpec().DNSServers))
|
||||
if upstreams.Len() == 0 {
|
||||
return nil
|
||||
}
|
||||
|
||||
err = handler.SetProxy(resolverStatus.TypedSpec().DNSServers)
|
||||
if err != nil {
|
||||
return fmt.Errorf("error setting dns server nameservers: %w", err)
|
||||
addrs := make([]string, 0, upstreams.Len())
|
||||
prxs := make([]*proxy.Proxy, 0, len(addrs))
|
||||
|
||||
for it := upstreams.Iterator(); it.Next(); {
|
||||
upstream := it.Value()
|
||||
|
||||
addrs = append(addrs, upstream.TypedSpec().Value.Prx.Addr())
|
||||
prxs = append(prxs, upstream.TypedSpec().Value.Prx.(*proxy.Proxy)) //nolint:forcetypeassert
|
||||
}
|
||||
|
||||
if handler.SetProxy(prxs) {
|
||||
ctrl.Logger.Info("updated dns server nameservers", zap.Strings("addrs", addrs))
|
||||
}
|
||||
|
||||
for _, n := range []string{"udp", "tcp"} {
|
||||
err = ctrl.writeDNSStatus(ctx, r, n, handler)
|
||||
err = ctrl.writeDNSStatus(ctx, r, n)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
@ -56,9 +56,10 @@ func (suite *DNSServer) TestResolving() {
|
||||
|
||||
rtestutils.AssertResources(suite.Ctx(), suite.T(), suite.State(), []resource.ID{"tcp", "udp"}, func(r *network.DNSResolveCache, assert *assert.Assertions) {
|
||||
assert.Equal("running", r.TypedSpec().Status)
|
||||
assert.Equal(dnsSlice, xslices.Map(r.TypedSpec().Servers, netip.Addr.String))
|
||||
})
|
||||
|
||||
rtestutils.AssertLength[*network.DNSUpstream](suite.Ctx(), suite.T(), suite.State(), len(dnsSlice))
|
||||
|
||||
msg := &dns.Msg{
|
||||
MsgHdr: dns.MsgHdr{
|
||||
Id: dns.Id(),
|
||||
@ -111,9 +112,9 @@ func (suite *DNSServer) TestSetupStartStop() {
|
||||
|
||||
rtestutils.AssertResources(suite.Ctx(), suite.T(), suite.State(), []resource.ID{"tcp", "udp"}, func(r *network.DNSResolveCache, assert *assert.Assertions) {
|
||||
assert.Equal("running", r.TypedSpec().Status)
|
||||
assert.Equal(dnsSlice, xslices.Map(r.TypedSpec().Servers, netip.Addr.String))
|
||||
})
|
||||
|
||||
rtestutils.AssertLength[*network.DNSUpstream](suite.Ctx(), suite.T(), suite.State(), len(dnsSlice))
|
||||
// stop dns resolver
|
||||
|
||||
cfg.Container().RawV1Alpha1().MachineConfig.MachineFeatures.LocalDNS = pointer.To(false)
|
||||
@ -123,6 +124,10 @@ func (suite *DNSServer) TestSetupStartStop() {
|
||||
ctest.AssertNoResource[*network.DNSResolveCache](suite, "tcp")
|
||||
ctest.AssertNoResource[*network.DNSResolveCache](suite, "udp")
|
||||
|
||||
for _, d := range dnsSlice {
|
||||
ctest.AssertNoResource[*network.DNSUpstream](suite, d)
|
||||
}
|
||||
|
||||
// start dns resolver again
|
||||
|
||||
cfg.Container().RawV1Alpha1().MachineConfig.MachineFeatures.LocalDNS = pointer.To(true)
|
||||
@ -131,8 +136,9 @@ func (suite *DNSServer) TestSetupStartStop() {
|
||||
|
||||
rtestutils.AssertResources(suite.Ctx(), suite.T(), suite.State(), []resource.ID{"tcp", "udp"}, func(r *network.DNSResolveCache, assert *assert.Assertions) {
|
||||
assert.Equal("running", r.TypedSpec().Status)
|
||||
assert.Equal(dnsSlice, xslices.Map(r.TypedSpec().Servers, netip.Addr.String))
|
||||
})
|
||||
|
||||
rtestutils.AssertLength[*network.DNSUpstream](suite.Ctx(), suite.T(), suite.State(), len(dnsSlice))
|
||||
}
|
||||
|
||||
func TestDNSServer(t *testing.T) {
|
||||
@ -140,6 +146,7 @@ func TestDNSServer(t *testing.T) {
|
||||
DefaultSuite: ctest.DefaultSuite{
|
||||
Timeout: 10 * time.Second,
|
||||
AfterSetup: func(suite *ctest.DefaultSuite) {
|
||||
suite.Require().NoError(suite.Runtime().RegisterController(&netctrl.DNSUpstreamController{}))
|
||||
suite.Require().NoError(suite.Runtime().RegisterController(&netctrl.DNSResolveCacheController{
|
||||
Addr: ":10700",
|
||||
Logger: zaptest.NewLogger(t),
|
||||
|
162
internal/app/machined/pkg/controllers/network/dns_upstream.go
Normal file
162
internal/app/machined/pkg/controllers/network/dns_upstream.go
Normal file
@ -0,0 +1,162 @@
|
||||
// This Source Code Form is subject to the terms of the Mozilla Public
|
||||
// License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
// file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
|
||||
package network
|
||||
|
||||
import (
|
||||
"context"
|
||||
"net"
|
||||
"time"
|
||||
|
||||
"github.com/coredns/coredns/plugin/pkg/proxy"
|
||||
"github.com/cosi-project/runtime/pkg/controller"
|
||||
"github.com/cosi-project/runtime/pkg/resource"
|
||||
"github.com/cosi-project/runtime/pkg/safe"
|
||||
"github.com/cosi-project/runtime/pkg/state"
|
||||
"github.com/siderolabs/gen/optional"
|
||||
"go.uber.org/zap"
|
||||
|
||||
"github.com/siderolabs/talos/pkg/machinery/resources/config"
|
||||
"github.com/siderolabs/talos/pkg/machinery/resources/network"
|
||||
)
|
||||
|
||||
// DNSUpstreamController is a controller that manages DNS upstreams.
|
||||
type DNSUpstreamController struct{}
|
||||
|
||||
// Name implements controller.Controller interface.
|
||||
func (ctrl *DNSUpstreamController) Name() string {
|
||||
return "network.DNSUpstreamController"
|
||||
}
|
||||
|
||||
// Inputs implements controller.Controller interface.
|
||||
func (ctrl *DNSUpstreamController) Inputs() []controller.Input {
|
||||
return []controller.Input{
|
||||
{
|
||||
Namespace: config.NamespaceName,
|
||||
Type: config.MachineConfigType,
|
||||
ID: optional.Some(config.V1Alpha1ID),
|
||||
Kind: controller.InputWeak,
|
||||
},
|
||||
{
|
||||
Namespace: network.NamespaceName,
|
||||
Type: network.ResolverStatusType,
|
||||
ID: optional.Some(network.ResolverID),
|
||||
Kind: controller.InputWeak,
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
// Outputs implements controller.Controller interface.
|
||||
func (ctrl *DNSUpstreamController) Outputs() []controller.Output {
|
||||
return []controller.Output{
|
||||
{
|
||||
Type: network.DNSUpstreamType,
|
||||
Kind: controller.OutputExclusive,
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
// Run implements controller.Controller interface.
|
||||
func (ctrl *DNSUpstreamController) Run(ctx context.Context, r controller.Runtime, l *zap.Logger) error {
|
||||
defer ctrl.cleanupUpstream(context.Background(), r, nil, l)
|
||||
|
||||
for {
|
||||
select {
|
||||
case <-ctx.Done():
|
||||
return nil
|
||||
case <-r.EventCh():
|
||||
}
|
||||
|
||||
if err := ctrl.run(ctx, r, l); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
r.ResetRestartBackoff()
|
||||
}
|
||||
}
|
||||
|
||||
func (ctrl *DNSUpstreamController) run(ctx context.Context, r controller.Runtime, l *zap.Logger) error {
|
||||
touchedIDs := map[resource.ID]struct{}{}
|
||||
|
||||
defer ctrl.cleanupUpstream(ctx, r, touchedIDs, l)
|
||||
|
||||
mc, err := safe.ReaderGetByID[*config.MachineConfig](ctx, r, config.V1Alpha1ID)
|
||||
if err != nil {
|
||||
if state.IsNotFoundError(err) {
|
||||
return nil
|
||||
}
|
||||
|
||||
return err
|
||||
}
|
||||
|
||||
if !mc.Config().Machine().Features().LocalDNSEnabled() {
|
||||
return nil
|
||||
}
|
||||
|
||||
rs, err := safe.ReaderGetByID[*network.ResolverStatus](ctx, r, network.ResolverID)
|
||||
if err != nil {
|
||||
if state.IsNotFoundError(err) {
|
||||
return nil
|
||||
}
|
||||
|
||||
return err
|
||||
}
|
||||
|
||||
for _, s := range rs.TypedSpec().DNSServers {
|
||||
remoteAddr := s.String()
|
||||
|
||||
if err = safe.WriterModify[*network.DNSUpstream](
|
||||
ctx,
|
||||
r,
|
||||
network.NewDNSUpstream(remoteAddr),
|
||||
func(u *network.DNSUpstream) error {
|
||||
touchedIDs[u.Metadata().ID()] = struct{}{}
|
||||
|
||||
if u.TypedSpec().Value.Prx != nil {
|
||||
return nil
|
||||
}
|
||||
|
||||
prx := proxy.NewProxy(remoteAddr, net.JoinHostPort(remoteAddr, "53"), "dns")
|
||||
|
||||
prx.Start(500 * time.Millisecond)
|
||||
|
||||
u.TypedSpec().Value.Prx = prx
|
||||
|
||||
l.Info("created dns upstream", zap.String("addr", remoteAddr))
|
||||
|
||||
return nil
|
||||
},
|
||||
); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (ctrl *DNSUpstreamController) cleanupUpstream(ctx context.Context, r controller.Runtime, touchedIDs map[resource.ID]struct{}, l *zap.Logger) {
|
||||
list, err := safe.ReaderListAll[*network.DNSUpstream](ctx, r)
|
||||
if err != nil {
|
||||
l.Error("error listing upstreams", zap.Error(err))
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
for it := list.Iterator(); it.Next(); {
|
||||
val := it.Value()
|
||||
md := val.Metadata()
|
||||
|
||||
if _, ok := touchedIDs[md.ID()]; !ok {
|
||||
val.TypedSpec().Value.Prx.Stop()
|
||||
|
||||
if err = r.Destroy(ctx, md); err != nil {
|
||||
l.Error("error destroying upstream", zap.Error(err), zap.String("id", md.ID()))
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
l.Info("destroyed dns upstream", zap.String("addr", md.ID()))
|
||||
}
|
||||
}
|
||||
}
|
@ -1359,8 +1359,7 @@ func LeaveEtcd(runtime.Sequence, any) (runtime.TaskExecutionFunc, string) {
|
||||
continue
|
||||
}
|
||||
|
||||
//nolint:exhaustive
|
||||
switch service.GetState() {
|
||||
switch service.GetState() { //nolint:exhaustive
|
||||
case events.StateRunning:
|
||||
fallthrough
|
||||
case events.StateStopping:
|
||||
|
@ -192,6 +192,7 @@ func (ctrl *Controller) Run(ctx context.Context, drainer *runtime.Drainer) error
|
||||
Addr: "127.0.0.1:53",
|
||||
Logger: dnsCacheLogger,
|
||||
},
|
||||
&network.DNSUpstreamController{},
|
||||
&network.EtcFileController{
|
||||
PodResolvConfPath: constants.PodResolvConfPath,
|
||||
},
|
||||
|
@ -149,6 +149,7 @@ func NewState() (*State, error) {
|
||||
&network.AddressSpec{},
|
||||
&network.DeviceConfigSpec{},
|
||||
&network.DNSResolveCache{},
|
||||
&network.DNSUpstream{},
|
||||
&network.HardwareAddr{},
|
||||
&network.HostnameStatus{},
|
||||
&network.HostnameSpec{},
|
||||
|
@ -9,8 +9,7 @@ import (
|
||||
"context"
|
||||
"errors"
|
||||
"math/rand"
|
||||
"net"
|
||||
"net/netip"
|
||||
"slices"
|
||||
"strings"
|
||||
"sync"
|
||||
"time"
|
||||
@ -20,8 +19,6 @@ import (
|
||||
"github.com/coredns/coredns/plugin/pkg/proxy"
|
||||
"github.com/coredns/coredns/request"
|
||||
"github.com/miekg/dns"
|
||||
"github.com/siderolabs/gen/pair"
|
||||
"github.com/siderolabs/gen/xslices"
|
||||
"go.uber.org/zap"
|
||||
|
||||
"github.com/siderolabs/talos/internal/pkg/utils"
|
||||
@ -96,7 +93,7 @@ func (c *Cache) ServeDNS(wr dns.ResponseWriter, msg *dns.Msg) {
|
||||
// Handler is a dns proxy selector.
|
||||
type Handler struct {
|
||||
mx sync.RWMutex
|
||||
dests []pair.Pair[netip.Addr, *proxy.Proxy]
|
||||
dests []*proxy.Proxy
|
||||
logger *zap.Logger
|
||||
}
|
||||
|
||||
@ -121,7 +118,7 @@ func (h *Handler) ServeDNS(ctx context.Context, wrt dns.ResponseWriter, msg *dns
|
||||
|
||||
h.logger.Debug("dns request", zap.Stringer("data", msg))
|
||||
|
||||
upstreams := xslices.Map(h.dests, func(h pair.Pair[netip.Addr, *proxy.Proxy]) *proxy.Proxy { return h.F2 })
|
||||
upstreams := slices.Clone(h.dests)
|
||||
|
||||
if len(upstreams) == 0 {
|
||||
emptyProxyErr := new(dns.Msg).SetRcode(req.Req, dns.RcodeServerFailure)
|
||||
@ -185,43 +182,21 @@ func (h *Handler) ServeDNS(ctx context.Context, wrt dns.ResponseWriter, msg *dns
|
||||
}
|
||||
|
||||
// SetProxy sets destination dns proxy servers.
|
||||
func (h *Handler) SetProxy(servers []netip.Addr) error {
|
||||
func (h *Handler) SetProxy(prxs []*proxy.Proxy) bool {
|
||||
h.mx.Lock()
|
||||
defer h.mx.Unlock()
|
||||
|
||||
var err error
|
||||
if slices.Equal(h.dests, prxs) {
|
||||
return false
|
||||
}
|
||||
|
||||
h.dests, err = utils.UpdatePairSet(h.dests, servers, onAdd, onRemove)
|
||||
h.dests = prxs
|
||||
|
||||
return err
|
||||
}
|
||||
|
||||
func onAdd(addr netip.Addr) (*proxy.Proxy, error) {
|
||||
dst := addr.String()
|
||||
|
||||
result := proxy.NewProxy(dst, net.JoinHostPort(dst, "53"), "dns")
|
||||
|
||||
result.Start(500 * time.Millisecond)
|
||||
|
||||
return result, nil
|
||||
}
|
||||
|
||||
func onRemove(h pair.Pair[netip.Addr, *proxy.Proxy]) error {
|
||||
h.F2.Stop()
|
||||
|
||||
return nil
|
||||
return true
|
||||
}
|
||||
|
||||
// Stop stops and clears dns proxy selector.
|
||||
func (h *Handler) Stop() { h.SetProxy(nil) } //nolint:errcheck
|
||||
|
||||
// ProxyList returns a list of destination dns proxy servers.
|
||||
func (h *Handler) ProxyList() []netip.Addr {
|
||||
h.mx.RLock()
|
||||
defer h.mx.RUnlock()
|
||||
|
||||
return xslices.Map(h.dests, func(h pair.Pair[netip.Addr, *proxy.Proxy]) netip.Addr { return h.F1 })
|
||||
}
|
||||
func (h *Handler) Stop() { h.SetProxy(nil) }
|
||||
|
||||
// ServerOptins is a Server options.
|
||||
type ServerOptins struct {
|
||||
|
@ -7,12 +7,13 @@ package dns_test
|
||||
import (
|
||||
"context"
|
||||
"errors"
|
||||
"net/netip"
|
||||
"net"
|
||||
"sync"
|
||||
"sync/atomic"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/coredns/coredns/plugin/pkg/proxy"
|
||||
dnssrv "github.com/miekg/dns"
|
||||
"github.com/siderolabs/gen/xslices"
|
||||
"github.com/siderolabs/gen/xtesting/check"
|
||||
@ -105,12 +106,18 @@ func newServer(t *testing.T, nameservers ...string) (context.Context, func()) {
|
||||
handler := dns.NewHandler(l)
|
||||
t.Cleanup(handler.Stop)
|
||||
|
||||
pxy := xslices.Map(nameservers, netip.MustParseAddr)
|
||||
pxs := xslices.Map(nameservers, func(ns string) *proxy.Proxy {
|
||||
p := proxy.NewProxy(ns, net.JoinHostPort(ns, "53"), "dns")
|
||||
p.Start(500 * time.Millisecond)
|
||||
|
||||
err := handler.SetProxy(pxy)
|
||||
require.NoError(t, err)
|
||||
t.Cleanup(func() {
|
||||
p.Stop()
|
||||
})
|
||||
|
||||
require.Equal(t, pxy, handler.ProxyList())
|
||||
return p
|
||||
})
|
||||
|
||||
handler.SetProxy(pxs)
|
||||
|
||||
runner := dns.NewRunner(dns.NewServer(dns.ServerOptins{
|
||||
Addr: ":10700",
|
||||
|
@ -7,58 +7,9 @@ package utils
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"slices"
|
||||
"sync/atomic"
|
||||
|
||||
"github.com/siderolabs/gen/pair"
|
||||
)
|
||||
|
||||
// UpdatePairSet updates a set of pairs. It removes pairs that are not in toAdd and adds pairs that are not in old.
|
||||
func UpdatePairSet[T comparable, H any](
|
||||
old []pair.Pair[T, H],
|
||||
toAdd []T,
|
||||
add func(T) (H, error),
|
||||
remove func(pair.Pair[T, H]) error,
|
||||
) ([]pair.Pair[T, H], error) {
|
||||
var err error
|
||||
|
||||
result := slices.DeleteFunc(old, func(h pair.Pair[T, H]) bool {
|
||||
if err != nil {
|
||||
return false
|
||||
}
|
||||
|
||||
if slices.Contains(toAdd, h.F1) {
|
||||
return false
|
||||
}
|
||||
|
||||
err = remove(h)
|
||||
if err != nil { //nolint:gosimple
|
||||
return false
|
||||
}
|
||||
|
||||
return true
|
||||
})
|
||||
|
||||
if err != nil {
|
||||
return result, err
|
||||
}
|
||||
|
||||
for _, val := range toAdd {
|
||||
if slices.ContainsFunc(old, func(h pair.Pair[T, H]) bool { return h.F1 == val }) {
|
||||
continue
|
||||
}
|
||||
|
||||
h, err := add(val)
|
||||
if err != nil {
|
||||
return result, err
|
||||
}
|
||||
|
||||
result = append(result, pair.MakePair(val, h))
|
||||
}
|
||||
|
||||
return result, nil
|
||||
}
|
||||
|
||||
const (
|
||||
notRunning = iota
|
||||
running
|
||||
|
@ -1,118 +0,0 @@
|
||||
// This Source Code Form is subject to the terms of the Mozilla Public
|
||||
// License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
// file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
|
||||
package utils_test
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"strconv"
|
||||
"testing"
|
||||
|
||||
"github.com/siderolabs/gen/pair"
|
||||
"github.com/siderolabs/gen/xslices"
|
||||
"github.com/siderolabs/gen/xtesting/check"
|
||||
"github.com/stretchr/testify/require"
|
||||
|
||||
"github.com/siderolabs/talos/internal/pkg/utils"
|
||||
)
|
||||
|
||||
func TestHandleSet(t *testing.T) {
|
||||
table := []struct {
|
||||
state string
|
||||
vals []int
|
||||
expected []string
|
||||
removed []string
|
||||
expectedErr check.Check
|
||||
}{
|
||||
{
|
||||
"initial state",
|
||||
[]int{1, 2, 3},
|
||||
[]string{"1", "2", "3"},
|
||||
nil,
|
||||
check.NoError(),
|
||||
},
|
||||
{
|
||||
"add and remove",
|
||||
[]int{1, 2, 4},
|
||||
[]string{"1", "2", "4"},
|
||||
[]string{"3"},
|
||||
check.NoError(),
|
||||
},
|
||||
{
|
||||
"add and remove with error",
|
||||
[]int{1, 2, 5, 42, 43},
|
||||
[]string{"1", "2", "5"},
|
||||
[]string{"4"},
|
||||
check.EqualError("42 is not allowed"),
|
||||
},
|
||||
{
|
||||
"remove all",
|
||||
[]int{},
|
||||
nil,
|
||||
[]string{"1", "2", "5"},
|
||||
check.NoError(),
|
||||
},
|
||||
{
|
||||
"start again",
|
||||
[]int{1, 2, 3, 45, 46},
|
||||
[]string{"1", "2", "3", "45", "46"},
|
||||
nil,
|
||||
check.NoError(),
|
||||
},
|
||||
{
|
||||
"remove with error",
|
||||
[]int{2, 3},
|
||||
[]string{"2", "3", "45", "46"},
|
||||
[]string{"1"},
|
||||
check.EqualError("45 is not allowed to delete"),
|
||||
},
|
||||
{
|
||||
"remove all again",
|
||||
[]int{},
|
||||
nil,
|
||||
[]string{"2", "3", "45", "46"},
|
||||
check.NoError(),
|
||||
},
|
||||
}
|
||||
|
||||
oneWithError := false
|
||||
|
||||
add := func(i int) (string, error) {
|
||||
if i == 42 {
|
||||
return "", errors.New("42 is not allowed")
|
||||
}
|
||||
|
||||
return strconv.Itoa(i), nil
|
||||
}
|
||||
|
||||
var removed []string
|
||||
|
||||
remove := func(h pair.Pair[int, string]) error {
|
||||
if h.F1 == 45 && !oneWithError {
|
||||
oneWithError = true
|
||||
|
||||
return errors.New("45 is not allowed to delete")
|
||||
}
|
||||
|
||||
removed = append(removed, h.F2)
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
var hs []pair.Pair[int, string]
|
||||
|
||||
for _, tt := range table {
|
||||
t.Run(tt.state, func(t *testing.T) {
|
||||
removed = nil
|
||||
|
||||
var err error
|
||||
hs, err = utils.UpdatePairSet(hs, tt.vals, add, remove)
|
||||
|
||||
tt.expectedErr(t, err)
|
||||
|
||||
require.Equal(t, tt.expected, xslices.Map(hs, func(h pair.Pair[int, string]) string { return h.F2 }))
|
||||
require.Equal(t, tt.removed, removed)
|
||||
})
|
||||
}
|
||||
}
|
File diff suppressed because it is too large
Load Diff
@ -729,30 +729,6 @@ func (m *DNSResolveCacheSpec) MarshalToSizedBufferVT(dAtA []byte) (int, error) {
|
||||
i -= len(m.unknownFields)
|
||||
copy(dAtA[i:], m.unknownFields)
|
||||
}
|
||||
if len(m.Servers) > 0 {
|
||||
for iNdEx := len(m.Servers) - 1; iNdEx >= 0; iNdEx-- {
|
||||
if vtmsg, ok := interface{}(m.Servers[iNdEx]).(interface {
|
||||
MarshalToSizedBufferVT([]byte) (int, error)
|
||||
}); ok {
|
||||
size, err := vtmsg.MarshalToSizedBufferVT(dAtA[:i])
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
i -= size
|
||||
i = encodeVarint(dAtA, i, uint64(size))
|
||||
} else {
|
||||
encoded, err := proto.Marshal(m.Servers[iNdEx])
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
i -= len(encoded)
|
||||
copy(dAtA[i:], encoded)
|
||||
i = encodeVarint(dAtA, i, uint64(len(encoded)))
|
||||
}
|
||||
i--
|
||||
dAtA[i] = 0x12
|
||||
}
|
||||
}
|
||||
if len(m.Status) > 0 {
|
||||
i -= len(m.Status)
|
||||
copy(dAtA[i:], m.Status)
|
||||
@ -3786,18 +3762,6 @@ func (m *DNSResolveCacheSpec) SizeVT() (n int) {
|
||||
if l > 0 {
|
||||
n += 1 + l + sov(uint64(l))
|
||||
}
|
||||
if len(m.Servers) > 0 {
|
||||
for _, e := range m.Servers {
|
||||
if size, ok := interface{}(e).(interface {
|
||||
SizeVT() int
|
||||
}); ok {
|
||||
l = size.SizeVT()
|
||||
} else {
|
||||
l = proto.Size(e)
|
||||
}
|
||||
n += 1 + l + sov(uint64(l))
|
||||
}
|
||||
}
|
||||
n += len(m.unknownFields)
|
||||
return n
|
||||
}
|
||||
@ -6508,48 +6472,6 @@ func (m *DNSResolveCacheSpec) UnmarshalVT(dAtA []byte) error {
|
||||
}
|
||||
m.Status = string(dAtA[iNdEx:postIndex])
|
||||
iNdEx = postIndex
|
||||
case 2:
|
||||
if wireType != 2 {
|
||||
return fmt.Errorf("proto: wrong wireType = %d for field Servers", wireType)
|
||||
}
|
||||
var msglen int
|
||||
for shift := uint(0); ; shift += 7 {
|
||||
if shift >= 64 {
|
||||
return ErrIntOverflow
|
||||
}
|
||||
if iNdEx >= l {
|
||||
return io.ErrUnexpectedEOF
|
||||
}
|
||||
b := dAtA[iNdEx]
|
||||
iNdEx++
|
||||
msglen |= int(b&0x7F) << shift
|
||||
if b < 0x80 {
|
||||
break
|
||||
}
|
||||
}
|
||||
if msglen < 0 {
|
||||
return ErrInvalidLength
|
||||
}
|
||||
postIndex := iNdEx + msglen
|
||||
if postIndex < 0 {
|
||||
return ErrInvalidLength
|
||||
}
|
||||
if postIndex > l {
|
||||
return io.ErrUnexpectedEOF
|
||||
}
|
||||
m.Servers = append(m.Servers, &common.NetIP{})
|
||||
if unmarshal, ok := interface{}(m.Servers[len(m.Servers)-1]).(interface {
|
||||
UnmarshalVT([]byte) error
|
||||
}); ok {
|
||||
if err := unmarshal.UnmarshalVT(dAtA[iNdEx:postIndex]); err != nil {
|
||||
return err
|
||||
}
|
||||
} else {
|
||||
if err := proto.Unmarshal(dAtA[iNdEx:postIndex], m.Servers[len(m.Servers)-1]); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
iNdEx = postIndex
|
||||
default:
|
||||
iNdEx = preIndex
|
||||
skippy, err := skip(dAtA[iNdEx:])
|
||||
|
@ -9,7 +9,7 @@ replace gopkg.in/yaml.v3 => github.com/unix4ever/yaml v0.0.0-20220527175918-f17b
|
||||
require (
|
||||
github.com/blang/semver/v4 v4.0.0
|
||||
github.com/containerd/go-cni v1.1.9
|
||||
github.com/cosi-project/runtime v0.3.20
|
||||
github.com/cosi-project/runtime v0.4.0-alpha.4
|
||||
github.com/dustin/go-humanize v1.0.1
|
||||
github.com/evanphx/json-patch v5.9.0+incompatible
|
||||
github.com/ghodss/yaml v1.0.0
|
||||
@ -43,25 +43,27 @@ require (
|
||||
github.com/gertd/go-pluralize v0.2.1 // indirect
|
||||
github.com/golang/protobuf v1.5.3 // indirect
|
||||
github.com/google/go-cmp v0.6.0 // indirect
|
||||
github.com/grpc-ecosystem/grpc-gateway/v2 v2.18.1 // indirect
|
||||
github.com/google/pprof v0.0.0-20230509042627-b1315fad0c5a // indirect
|
||||
github.com/grpc-ecosystem/grpc-gateway/v2 v2.19.0 // indirect
|
||||
github.com/hashicorp/errwrap v1.1.0 // indirect
|
||||
github.com/josharian/native v1.1.0 // indirect
|
||||
github.com/mdlayher/genetlink v1.3.2 // indirect
|
||||
github.com/mdlayher/netlink v1.7.2 // indirect
|
||||
github.com/mdlayher/socket v0.4.1 // indirect
|
||||
github.com/onsi/ginkgo/v2 v2.2.0 // indirect
|
||||
github.com/onsi/gomega v1.20.1 // indirect
|
||||
github.com/onsi/ginkgo/v2 v2.11.0 // indirect
|
||||
github.com/onsi/gomega v1.27.8 // indirect
|
||||
github.com/pkg/browser v0.0.0-20210911075715-681adbf594b8 // indirect
|
||||
github.com/pkg/errors v0.9.1 // indirect
|
||||
github.com/pmezard/go-difflib v1.0.0 // indirect
|
||||
github.com/ryanuber/go-glob v1.0.0 // indirect
|
||||
go.uber.org/multierr v1.10.0 // indirect
|
||||
go.uber.org/zap v1.26.0 // indirect
|
||||
golang.org/x/crypto v0.15.0 // indirect
|
||||
golang.org/x/net v0.18.0 // indirect
|
||||
golang.org/x/sync v0.5.0 // indirect
|
||||
golang.org/x/crypto v0.16.0 // indirect
|
||||
golang.org/x/net v0.19.0 // indirect
|
||||
golang.org/x/sync v0.6.0 // indirect
|
||||
golang.org/x/sys v0.16.0 // indirect
|
||||
golang.org/x/text v0.14.0 // indirect
|
||||
golang.org/x/time v0.5.0 // indirect
|
||||
google.golang.org/genproto/googleapis/api v0.0.0-20240102182953-50ed04b92917 // indirect
|
||||
gopkg.in/yaml.v2 v2.4.0 // indirect
|
||||
)
|
||||
|
@ -22,8 +22,8 @@ github.com/containerd/go-cni v1.1.9 h1:ORi7P1dYzCwVM6XPN4n3CbkuOx/NZ2DOqy+SHRdo9
|
||||
github.com/containerd/go-cni v1.1.9/go.mod h1:XYrZJ1d5W6E2VOvjffL3IZq0Dz6bsVlERHbekNK90PM=
|
||||
github.com/containernetworking/cni v1.1.2 h1:wtRGZVv7olUHMOqouPpn3cXJWpJgM6+EUl31EQbXALQ=
|
||||
github.com/containernetworking/cni v1.1.2/go.mod h1:sDpYKmGVENF3s6uvMvGgldDWeG8dMxakj/u+i9ht9vw=
|
||||
github.com/cosi-project/runtime v0.3.20 h1:pl8mwbHMFIRFYV8v0Glxw2ruhTXn/5ij7TSlO9nApi4=
|
||||
github.com/cosi-project/runtime v0.3.20/go.mod h1:3DQsIr7zF/bmWfHOnpHmOQ9mDukFGi8AMoHx2rNsi+s=
|
||||
github.com/cosi-project/runtime v0.4.0-alpha.4 h1:3TN+Y0NVKa/1QXqR3QTJ6ceWrcflyUeIZbQnrU2BprM=
|
||||
github.com/cosi-project/runtime v0.4.0-alpha.4/go.mod h1:JE9yuyufGRCd28AyCWFkTNf3UMiZJT722bpfPEPnsNE=
|
||||
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
|
||||
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||
@ -37,7 +37,11 @@ github.com/gertd/go-pluralize v0.2.1 h1:M3uASbVjMnTsPb0PNqg+E/24Vwigyo/tvyMTtAlL
|
||||
github.com/gertd/go-pluralize v0.2.1/go.mod h1:rbYaKDbsXxmRfr8uygAEKhOWsjyrrqrkHVpZvoOp8zk=
|
||||
github.com/ghodss/yaml v1.0.0 h1:wQHKEahhL6wmXdzwWG11gIVCkOv05bNOh+Rxn0yngAk=
|
||||
github.com/ghodss/yaml v1.0.0/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04=
|
||||
github.com/go-logr/logr v1.2.4 h1:g01GSCwiDw2xSZfjJ2/T9M+S6pFdcNtFYsp+Y43HYDQ=
|
||||
github.com/go-logr/logr v1.2.4/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A=
|
||||
github.com/go-task/slim-sprig v0.0.0-20210107165309-348f09dbbbc0/go.mod h1:fyg7847qk6SyHyPtNmDHnmrv/HOrqktSC+C9fM+CJOE=
|
||||
github.com/go-task/slim-sprig v0.0.0-20230315185526-52ccab3ef572 h1:tfuBGBXKqDEevZMzYi5KSi8KkcZtzBcTgAUUtapy0OI=
|
||||
github.com/go-task/slim-sprig v0.0.0-20230315185526-52ccab3ef572/go.mod h1:9Pwr4B2jHnOSGXyyzV8ROjYa2ojvAY6HCGYYfMoC3Ls=
|
||||
github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
|
||||
github.com/golang/protobuf v1.4.0-rc.1/go.mod h1:ceaxUfeHdC40wWswd/P6IGgMaK3YpKi5j83Wpe3EHw8=
|
||||
github.com/golang/protobuf v1.4.0-rc.1.0.20200221234624-67d41d38c208/go.mod h1:xKAWHe0F5eneWXFV3EuXVDTCmh+JuBKY0li0aMyXATA=
|
||||
@ -56,8 +60,10 @@ github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/
|
||||
github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI=
|
||||
github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY=
|
||||
github.com/google/pprof v0.0.0-20210407192527-94a9f03dee38/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE=
|
||||
github.com/grpc-ecosystem/grpc-gateway/v2 v2.18.1 h1:6UKoz5ujsI55KNpsJH3UwCq3T8kKbZwNZBNPuTTje8U=
|
||||
github.com/grpc-ecosystem/grpc-gateway/v2 v2.18.1/go.mod h1:YvJ2f6MplWDhfxiUC3KpyTy76kYUZA4W3pTv/wdKQ9Y=
|
||||
github.com/google/pprof v0.0.0-20230509042627-b1315fad0c5a h1:PEOGDI1kkyW37YqPWHLHc+D20D9+87Wt12TCcfTUo5Q=
|
||||
github.com/google/pprof v0.0.0-20230509042627-b1315fad0c5a/go.mod h1:79YE0hCXdHag9sBkw2o+N/YnZtTkXi0UT9Nnixa5eYk=
|
||||
github.com/grpc-ecosystem/grpc-gateway/v2 v2.19.0 h1:Wqo399gCIufwto+VfwCSvsnfGpF/w5E9CNxSwbpD6No=
|
||||
github.com/grpc-ecosystem/grpc-gateway/v2 v2.19.0/go.mod h1:qmOFXW2epJhM0qSnUUYpldc7gVz2KMQwJ/QYCDIa7XU=
|
||||
github.com/hashicorp/errwrap v1.0.0/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4=
|
||||
github.com/hashicorp/errwrap v1.1.0 h1:OxrOeh75EUXMY8TBjag2fzXGZ40LB6IKw45YeGUDY2I=
|
||||
github.com/hashicorp/errwrap v1.1.0/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4=
|
||||
@ -87,13 +93,13 @@ github.com/onsi/ginkgo v1.6.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+W
|
||||
github.com/onsi/ginkgo v1.12.1/go.mod h1:zj2OWP4+oCPe1qIXoGWkgMRwljMUYCdkwsT2108oapk=
|
||||
github.com/onsi/ginkgo v1.16.4/go.mod h1:dX+/inL/fNMqNlz0e9LfyB9TswhZpCVdJM/Z6Vvnwo0=
|
||||
github.com/onsi/ginkgo/v2 v2.1.3/go.mod h1:vw5CSIxN1JObi/U8gcbwft7ZxR2dgaR70JSE3/PpL4c=
|
||||
github.com/onsi/ginkgo/v2 v2.2.0 h1:3ZNA3L1c5FYDFTTxbFeVGGD8jYvjYauHD30YgLxVsNI=
|
||||
github.com/onsi/ginkgo/v2 v2.2.0/go.mod h1:MEH45j8TBi6u9BMogfbp0stKC5cdGjumZj5Y7AG4VIk=
|
||||
github.com/onsi/ginkgo/v2 v2.11.0 h1:WgqUCUt/lT6yXoQ8Wef0fsNn5cAuMK7+KT9UFRz2tcU=
|
||||
github.com/onsi/ginkgo/v2 v2.11.0/go.mod h1:ZhrRA5XmEE3x3rhlzamx/JJvujdZoJ2uvgI7kR0iZvM=
|
||||
github.com/onsi/gomega v1.7.1/go.mod h1:XdKZgCCFLUoM/7CFJVPcG8C1xQ1AJ0vpAezJrB7JYyY=
|
||||
github.com/onsi/gomega v1.10.1/go.mod h1:iN09h71vgCQne3DLsj+A5owkum+a2tYe+TOCB1ybHNo=
|
||||
github.com/onsi/gomega v1.17.0/go.mod h1:HnhC7FXeEQY45zxNK3PPoIUhzk/80Xly9PcubAlGdZY=
|
||||
github.com/onsi/gomega v1.20.1 h1:PA/3qinGoukvymdIDV8pii6tiZgC8kbmJO6Z5+b002Q=
|
||||
github.com/onsi/gomega v1.20.1/go.mod h1:DtrZpjmvpn2mPm4YWQa0/ALMDj9v4YxLgojwPeREyVo=
|
||||
github.com/onsi/gomega v1.27.8 h1:gegWiwZjBsf2DgiSbf5hpokZ98JVDMcWkUiigk6/KXc=
|
||||
github.com/onsi/gomega v1.27.8/go.mod h1:2J8vzI/s+2shY9XHRApDkdgPo1TKT7P2u6fXeJKFnNQ=
|
||||
github.com/opencontainers/runtime-spec v1.1.0 h1:HHUyrt9mwHUjtasSbXSMvs4cyFxh+Bll4AjJ9odEGpg=
|
||||
github.com/opencontainers/runtime-spec v1.1.0/go.mod h1:jwyrGlmzljRJv/Fgzds9SsS/C5hL+LL3ko9hs6T5lQ0=
|
||||
github.com/pkg/browser v0.0.0-20210911075715-681adbf594b8 h1:KoWmjvw+nsYOo29YJK9vDA65RGE3NrOnUtO7a+RF9HU=
|
||||
@ -147,8 +153,8 @@ golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPh
|
||||
golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
|
||||
golang.org/x/crypto v0.3.1-0.20221117191849-2c476679df9a/go.mod h1:hebNnKkNXi2UzZN1eVRvBB7co0a+JxK6XbPiWVs/3J4=
|
||||
golang.org/x/crypto v0.7.0/go.mod h1:pYwdfH91IfpZVANVyUOhSIPZaFoJGxTFbZhFTx+dXZU=
|
||||
golang.org/x/crypto v0.15.0 h1:frVn1TEaCEaZcn3Tmd7Y2b5KKPaZ+I32Q2OA3kYp5TA=
|
||||
golang.org/x/crypto v0.15.0/go.mod h1:4ChreQoLWfG3xLDer1WdlH5NdlQ3+mwnQq1YTKY+72g=
|
||||
golang.org/x/crypto v0.16.0 h1:mMMrFzRSCF0GvB7Ne27XVtVAaXLrPmgPC7/v0tkwHaY=
|
||||
golang.org/x/crypto v0.16.0/go.mod h1:gCAAfMLgwOJRpTjQ2zCCt2OcSfYMTeZVSRtQlPC7Nq4=
|
||||
golang.org/x/exp v0.0.0-20230224173230-c95f2b4c22f2 h1:Jvc7gsqn21cJHCmAWx0LiimpP18LZmUxkT5Mp7EZ1mI=
|
||||
golang.org/x/exp v0.0.0-20230224173230-c95f2b4c22f2/go.mod h1:CxIveKay+FTh1D0yPZemJVgC/95VzuuOLq5Qi4xnoYc=
|
||||
golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
|
||||
@ -165,15 +171,15 @@ golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug
|
||||
golang.org/x/net v0.2.0/go.mod h1:KqCZLdyyvdV855qA2rE3GC2aiw5xGR5TEjj8smXukLY=
|
||||
golang.org/x/net v0.6.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs=
|
||||
golang.org/x/net v0.8.0/go.mod h1:QVkue5JL9kW//ek3r6jTKnTFis1tRmNAW2P1shuFdJc=
|
||||
golang.org/x/net v0.18.0 h1:mIYleuAkSbHh0tCv7RvjL3F6ZVbLjq4+R7zbOn3Kokg=
|
||||
golang.org/x/net v0.18.0/go.mod h1:/czyP5RqHAH4odGYxBJ1qz0+CE5WZ+2j1YgoEo8F2jQ=
|
||||
golang.org/x/net v0.19.0 h1:zTwKpTd2XuCqf8huc7Fo2iSy+4RHPd10s4KzeTnVr1c=
|
||||
golang.org/x/net v0.19.0/go.mod h1:CfAk/cbD4CthTvqiEl8NpboMuiuOYsAr/7NOjZJtv1U=
|
||||
golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sync v0.1.0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sync v0.5.0 h1:60k92dhOjHxJkrqnwsfl8KuaHbn/5dl0lUPUklKo3qE=
|
||||
golang.org/x/sync v0.5.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk=
|
||||
golang.org/x/sync v0.6.0 h1:5BMeUDZ7vkXGfEr1x9B4bRcTH4lpkTkpdh0T/J+qjbQ=
|
||||
golang.org/x/sync v0.6.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk=
|
||||
golang.org/x/sys v0.0.0-20180909124046-d0be0721c37e/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||
golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
@ -211,11 +217,15 @@ golang.org/x/text v0.7.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8=
|
||||
golang.org/x/text v0.8.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8=
|
||||
golang.org/x/text v0.14.0 h1:ScX5w1eTa3QqT8oi6+ziP7dTV1S2+ALU0bI+0zXKWiQ=
|
||||
golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU=
|
||||
golang.org/x/time v0.5.0 h1:o7cqy6amK/52YcAKIPlM3a+Fpj35zvRj2TP+e1xFSfk=
|
||||
golang.org/x/time v0.5.0/go.mod h1:3BpzKBy/shNhVucY/MWOyx10tF3SFh9QdLuxbVysPQM=
|
||||
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
||||
golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
|
||||
golang.org/x/tools v0.0.0-20201224043029-2b0845dc783e/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA=
|
||||
golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc=
|
||||
golang.org/x/tools v0.6.0/go.mod h1:Xwgl3UAJ/d3gWutnCtw505GrjyAbvKui8lOU390QaIU=
|
||||
golang.org/x/tools v0.9.3 h1:Gn1I8+64MsuTb/HpH+LmQtNas23LhUVr3rYZ0eKuaMM=
|
||||
golang.org/x/tools v0.9.3/go.mod h1:owI94Op576fPu3cIGQeHs3joujW/2Oc6MtlxbF5dfNc=
|
||||
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||
golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||
|
@ -27,10 +27,6 @@ func (o AddressStatusSpec) DeepCopy() AddressStatusSpec {
|
||||
// DeepCopy generates a deep copy of DNSResolveCacheSpec.
|
||||
func (o DNSResolveCacheSpec) DeepCopy() DNSResolveCacheSpec {
|
||||
var cp DNSResolveCacheSpec = o
|
||||
if o.Servers != nil {
|
||||
cp.Servers = make([]netip.Addr, len(o.Servers))
|
||||
copy(cp.Servers, o.Servers)
|
||||
}
|
||||
return cp
|
||||
}
|
||||
|
||||
|
@ -5,8 +5,6 @@
|
||||
package network
|
||||
|
||||
import (
|
||||
"net/netip"
|
||||
|
||||
"github.com/cosi-project/runtime/pkg/resource"
|
||||
"github.com/cosi-project/runtime/pkg/resource/meta"
|
||||
"github.com/cosi-project/runtime/pkg/resource/protobuf"
|
||||
@ -25,8 +23,7 @@ type DNSResolveCache = typed.Resource[DNSResolveCacheSpec, DNSResolveCacheExtens
|
||||
//
|
||||
//gotagsrewrite:gen
|
||||
type DNSResolveCacheSpec struct {
|
||||
Status string `yaml:"status" protobuf:"1"`
|
||||
Servers []netip.Addr `yaml:"servers" protobuf:"2"`
|
||||
Status string `yaml:"status" protobuf:"1"`
|
||||
}
|
||||
|
||||
// NewDNSResolveCache initializes a DNSResolveCache resource.
|
||||
|
82
pkg/machinery/resources/network/dns_upstream.go
Normal file
82
pkg/machinery/resources/network/dns_upstream.go
Normal file
@ -0,0 +1,82 @@
|
||||
// This Source Code Form is subject to the terms of the Mozilla Public
|
||||
// License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||
// file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
|
||||
package network
|
||||
|
||||
import (
|
||||
"strconv"
|
||||
"time"
|
||||
|
||||
"github.com/cosi-project/runtime/pkg/resource"
|
||||
"github.com/cosi-project/runtime/pkg/resource/handle"
|
||||
"github.com/cosi-project/runtime/pkg/resource/meta"
|
||||
"github.com/cosi-project/runtime/pkg/resource/typed"
|
||||
)
|
||||
|
||||
// DNSUpstreamType is type of DNSUpstream resource.
|
||||
const DNSUpstreamType = resource.Type("DNSUpstreams.net.talos.dev")
|
||||
|
||||
// DNSUpstream resource holds DNS resolver info.
|
||||
type DNSUpstream = typed.Resource[DNSUpstreamSpec, DNSUpstreamExtension]
|
||||
|
||||
// DNSUpstreamSpec describes DNS upstreams status.
|
||||
type DNSUpstreamSpec = handle.ResourceSpec[*DNSUpstreamSpecSpec]
|
||||
|
||||
// DNSUpstreamSpecSpec describes DNS upstreams status.
|
||||
type DNSUpstreamSpecSpec struct {
|
||||
// Proxy is essentially a *proxy.Proxy interface. It's here because we don't want machinery to depend on coredns.
|
||||
// We could use a generic struct here, but without generic aliases the usage would look ugly.
|
||||
// Once generic aliases are here, redo the type above as `type DNSUpstream[P Proxy] = typed.Resource[...]`.
|
||||
Prx Proxy
|
||||
}
|
||||
|
||||
// MarshalYAML implements yaml.Marshaler interface.
|
||||
func (d *DNSUpstreamSpecSpec) MarshalYAML() (interface{}, error) {
|
||||
d.Prx.Healthcheck()
|
||||
|
||||
return map[string]string{
|
||||
"healthy": strconv.FormatBool(d.Prx.Fails() == 0),
|
||||
"addr": d.Prx.Addr(),
|
||||
}, nil
|
||||
}
|
||||
|
||||
// NewDNSUpstream initializes a DNSUpstream resource.
|
||||
func NewDNSUpstream(id resource.ID) *DNSUpstream {
|
||||
return typed.NewResource[DNSUpstreamSpec, DNSUpstreamExtension](
|
||||
resource.NewMetadata(NamespaceName, DNSUpstreamType, id, resource.VersionUndefined),
|
||||
DNSUpstreamSpec{Value: &DNSUpstreamSpecSpec{}},
|
||||
)
|
||||
}
|
||||
|
||||
// DNSUpstreamExtension provides auxiliary methods for DNSUpstream.
|
||||
type DNSUpstreamExtension struct{}
|
||||
|
||||
// ResourceDefinition implements [typed.Extension] interface.
|
||||
func (DNSUpstreamExtension) ResourceDefinition() meta.ResourceDefinitionSpec {
|
||||
return meta.ResourceDefinitionSpec{
|
||||
Type: DNSUpstreamType,
|
||||
Aliases: []resource.Type{},
|
||||
DefaultNamespace: NamespaceName,
|
||||
PrintColumns: []meta.PrintColumn{
|
||||
{
|
||||
Name: "Healthy",
|
||||
JSONPath: "{.healthy}",
|
||||
},
|
||||
{
|
||||
Name: "Address",
|
||||
JSONPath: "{.addr}",
|
||||
},
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
// Proxy is essentially a proxy.Proxy interface. It's here because we don't want machinery to depend on coredns.
|
||||
// The good thing we don't need any additional methods from coredns, so we can use a simple interface.
|
||||
type Proxy interface {
|
||||
Addr() string
|
||||
Fails() uint32
|
||||
Healthcheck()
|
||||
Stop()
|
||||
Start(duration time.Duration)
|
||||
}
|
@ -2911,7 +2911,6 @@ DNSResolveCacheSpec describes DNS servers status.
|
||||
| Field | Type | Label | Description |
|
||||
| ----- | ---- | ----- | ----------- |
|
||||
| status | [string](#string) | | |
|
||||
| servers | [common.NetIP](#common.NetIP) | repeated | |
|
||||
|
||||
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user