Skip to content

Commit

Permalink
DNS v2 - add virtual ip questions (hashicorp#20245)
Browse files Browse the repository at this point in the history
  • Loading branch information
jmurret authored Jan 17, 2024
1 parent d2e991d commit 938d231
Show file tree
Hide file tree
Showing 20 changed files with 1,157 additions and 61 deletions.
4 changes: 2 additions & 2 deletions agent/agent.go
Original file line number Diff line number Diff line change
Expand Up @@ -1103,7 +1103,7 @@ func (a *Agent) listenAndServeV2DNS() error {
if a.baseDeps.UseV2Resources() {
a.catalogDataFetcher = discovery.NewV2DataFetcher(a.config)
} else {
a.catalogDataFetcher = discovery.NewV1DataFetcher(a.config)
a.catalogDataFetcher = discovery.NewV1DataFetcher(a.config, a.RPC, a.logger.Named("catalog-data-fetcher"))
}

// Generate a Query Processor with the appropriate data fetcher
Expand All @@ -1115,7 +1115,7 @@ func (a *Agent) listenAndServeV2DNS() error {
// create server
cfg := dns.Config{
AgentConfig: a.config,
EntMeta: a.AgentEnterpriseMeta(), // TODO (v2-dns): does this even work for v2 tenancy?
EntMeta: *a.AgentEnterpriseMeta(),
Logger: a.logger,
Processor: processor,
TokenFunc: a.getTokenFunc(),
Expand Down
17 changes: 12 additions & 5 deletions agent/discovery/discovery.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import (
"fmt"
"net"

"github.com/hashicorp/consul/acl"
"github.com/hashicorp/consul/agent/config"
"github.com/hashicorp/consul/agent/structs"
)
Expand All @@ -25,26 +26,28 @@ type QueryType string
const (
QueryTypeConnect QueryType = "CONNECT" // deprecated: use for V1 only
QueryTypeIngress QueryType = "INGRESS" // deprecated: use for V1 only
QueryTypeInvalid QueryType = "INVALID"
QueryTypeNode QueryType = "NODE"
QueryTypePreparedQuery QueryType = "PREPARED_QUERY" // deprecated: use for V1 only
QueryTypeService QueryType = "SERVICE"
QueryTypeVirtual QueryType = "VIRTUAL"
QueryTypeWorkload QueryType = "WORKLOAD" // V2-only
)

// Context is used to pass information about the request.
type Context struct {
Token string
DefaultPartition string
DefaultNamespace string
DefaultLocality *structs.Locality
}

// QueryTenancy is used to filter catalog data based on tenancy.
type QueryTenancy struct {
Partition string
Namespace string
SamenessGroup string
Peer string
Datacenter string
EnterpriseMeta acl.EnterpriseMeta
SamenessGroup string
Peer string
Datacenter string
}

// QueryPayload represents all information needed by the data backend
Expand Down Expand Up @@ -87,6 +90,7 @@ type Result struct {
Target string
}

// LookupType is used by the CatalogDataFetcher to properly filter endpoints.
type LookupType string

const (
Expand Down Expand Up @@ -124,10 +128,12 @@ type CatalogDataFetcher interface {
FetchPreparedQuery(ctx Context, req *QueryPayload) ([]*Result, error)
}

// QueryProcessor is used to process a Discovery Query and return the results.
type QueryProcessor struct {
dataFetcher CatalogDataFetcher
}

// NewQueryProcessor creates a new QueryProcessor.
func NewQueryProcessor(dataFetcher CatalogDataFetcher) *QueryProcessor {
return &QueryProcessor{
dataFetcher: dataFetcher,
Expand Down Expand Up @@ -163,6 +169,7 @@ func (p *QueryProcessor) QueryByName(query *Query, ctx Context) ([]*Result, erro
}
}

// QueryByIP is used to look up a service or node from an IP address.
func (p *QueryProcessor) QueryByIP(ip net.IP, ctx Context) ([]*Result, error) {
return p.dataFetcher.FetchRecordsByIp(ctx, ip)
}
190 changes: 190 additions & 0 deletions agent/discovery/mock_CatalogDataFetcher.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

51 changes: 48 additions & 3 deletions agent/discovery/query_fetcher_v1.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,11 +4,15 @@
package discovery

import (
"context"
"net"
"sync/atomic"
"time"

"github.com/hashicorp/go-hclog"

"github.com/hashicorp/consul/agent/config"
"github.com/hashicorp/consul/agent/structs"
)

const (
Expand All @@ -17,6 +21,7 @@ const (
maxRecurseRecords = 5
)

// v1DataFetcherDynamicConfig is used to store the dynamic configuration of the V1 data fetcher.
type v1DataFetcherDynamicConfig struct {
allowStale bool
maxStale time.Duration
Expand All @@ -25,16 +30,27 @@ type v1DataFetcherDynamicConfig struct {
onlyPassing bool
}

// V1DataFetcher is used to fetch data from the V1 catalog.
type V1DataFetcher struct {
dynamicConfig atomic.Value
logger hclog.Logger

rpcFunc func(ctx context.Context, method string, args interface{}, reply interface{}) error
}

func NewV1DataFetcher(config *config.RuntimeConfig) *V1DataFetcher {
f := &V1DataFetcher{}
// NewV1DataFetcher creates a new V1 data fetcher.
func NewV1DataFetcher(config *config.RuntimeConfig,
rpcFunc func(ctx context.Context, method string, args interface{}, reply interface{}) error,
logger hclog.Logger) *V1DataFetcher {
f := &V1DataFetcher{
rpcFunc: rpcFunc,
logger: logger,
}
f.LoadConfig(config)
return f
}

// LoadConfig loads the configuration for the V1 data fetcher.
func (f *V1DataFetcher) LoadConfig(config *config.RuntimeConfig) {
dynamicConfig := &v1DataFetcherDynamicConfig{
allowStale: config.DNSAllowStale,
Expand All @@ -48,26 +64,55 @@ func (f *V1DataFetcher) LoadConfig(config *config.RuntimeConfig) {

// TODO (v2-dns): Implementation of the V1 data fetcher

// FetchNodes fetches A/AAAA/CNAME
func (f *V1DataFetcher) FetchNodes(ctx Context, req *QueryPayload) ([]*Result, error) {
return nil, nil
}

// FetchEndpoints fetches records for A/AAAA/CNAME or SRV requests for services
func (f *V1DataFetcher) FetchEndpoints(ctx Context, req *QueryPayload, lookupType LookupType) ([]*Result, error) {
return nil, nil
}

// FetchVirtualIP fetches A/AAAA records for virtual IPs
func (f *V1DataFetcher) FetchVirtualIP(ctx Context, req *QueryPayload) (*Result, error) {
return nil, nil
args := structs.ServiceSpecificRequest{
// The datacenter of the request is not specified because cross-datacenter virtual IP
// queries are not supported. This guard rail is in place because virtual IPs are allocated
// within a DC, therefore their uniqueness is not guaranteed globally.
PeerName: req.Tenancy.Peer,
ServiceName: req.Name,
EnterpriseMeta: req.Tenancy.EnterpriseMeta,
QueryOptions: structs.QueryOptions{
Token: ctx.Token,
},
}

var out string
if err := f.rpcFunc(context.Background(), "Catalog.VirtualIPForService", &args, &out); err != nil {
return nil, err
}

result := &Result{
Address: out,
Type: ResultTypeVirtual,
}
return result, nil
}

// FetchRecordsByIp is used for PTR requests to look up a service/node from an IP.
func (f *V1DataFetcher) FetchRecordsByIp(ctx Context, ip net.IP) ([]*Result, error) {
return nil, nil
}

// FetchWorkload fetches a single Result associated with
// V2 Workload. V2-only.
func (f *V1DataFetcher) FetchWorkload(ctx Context, req *QueryPayload) (*Result, error) {
return nil, nil
}

// FetchPreparedQuery evaluates the results of a prepared query.
// deprecated in V2
func (f *V1DataFetcher) FetchPreparedQuery(ctx Context, req *QueryPayload) ([]*Result, error) {
return nil, nil
}
Loading

0 comments on commit 938d231

Please sign in to comment.