Skip to content

Commit

Permalink
feat: deprecate --gateway-discovery-dns-strategy make resolution to…
Browse files Browse the repository at this point in the history
… always work
  • Loading branch information
programmer04 committed Jan 27, 2025
1 parent 8e20c47 commit 385ef00
Show file tree
Hide file tree
Showing 28 changed files with 293 additions and 448 deletions.
1 change: 0 additions & 1 deletion docs/cli-arguments.md
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,6 @@
| `--enable-reverse-sync` | `bool` | Send configuration to Kong even if the configuration checksum has not changed since previous update. | `false` |
| `--feature-gates` | `list of string=bool` | A set of comma separated key=value pairs that describe feature gates for alpha/beta/experimental features. See the Feature Gates documentation for information and available options: https://github.com/Kong/kubernetes-ingress-controller/blob/main/FEATURE_GATES.md. | |
| `--gateway-api-controller-name` | `string` | The controller name to match on Gateway API resources. | `konghq.com/kic-gateway-controller` |
| `--gateway-discovery-dns-strategy` | `dns-strategy` | DNS strategy to use when creating Gateway's Admin API addresses. One of: ip, service, pod. | `"ip"` |
| `--gateway-discovery-readiness-check-interval` | `duration` | Interval of readiness checks on gateway admin API clients for discovery. | `10s` |
| `--gateway-discovery-readiness-check-timeout` | `duration` | Timeout of readiness checks on gateway admin clients. | `5s` |
| `--gateway-to-reconcile` | `namespaced-name` | Gateway namespaced name in "namespace/name" format. Makes KIC reconcile only the specified Gateway. | |
Expand Down
23 changes: 11 additions & 12 deletions internal/adminapi/client.go
Original file line number Diff line number Diff line change
Expand Up @@ -204,25 +204,24 @@ func (c *Client) PodReference() (k8stypes.NamespacedName, bool) {
}

type ClientFactory struct {
workspace string
httpClientOpts HTTPClientOpts
adminToken string
workspace string
opts ClientOpts
adminToken string
}

func NewClientFactoryForWorkspace(workspace string, httpClientOpts HTTPClientOpts, adminToken string) ClientFactory {
func NewClientFactoryForWorkspace(workspace string, httpClientOpts ClientOpts, adminToken string) ClientFactory {
return ClientFactory{
workspace: workspace,
httpClientOpts: httpClientOpts,
adminToken: adminToken,
workspace: workspace,
opts: httpClientOpts,
adminToken: adminToken,
}
}

func (cf ClientFactory) CreateAdminAPIClient(ctx context.Context, discoveredAdminAPI DiscoveredAdminAPI) (*Client, error) {
httpclient, err := MakeHTTPClient(&cf.httpClientOpts, cf.adminToken)
if err != nil {
return nil, err
}
cl, err := NewKongClientForWorkspace(ctx, discoveredAdminAPI.Address, cf.workspace, httpclient)
opts := cf.opts
opts.TLSServerName = discoveredAdminAPI.TLSServerName

cl, err := NewKongClientForWorkspace(ctx, discoveredAdminAPI.Address, cf.workspace, opts, cf.adminToken)
if err != nil {
return nil, err
}
Expand Down
2 changes: 1 addition & 1 deletion internal/adminapi/client_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ import (
)

func TestClientFactory_CreateAdminAPIClientAttachesPodReference(t *testing.T) {
factory := adminapi.NewClientFactoryForWorkspace("workspace", adminapi.HTTPClientOpts{}, "")
factory := adminapi.NewClientFactoryForWorkspace("workspace", adminapi.ClientOpts{}, "")

adminAPIHandler := mocks.NewAdminAPIHandler(t)
adminAPIServer := httptest.NewServer(adminAPIHandler)
Expand Down
80 changes: 26 additions & 54 deletions internal/adminapi/endpoints.go
Original file line number Diff line number Diff line change
Expand Up @@ -11,40 +11,36 @@ import (
k8stypes "k8s.io/apimachinery/pkg/types"
"k8s.io/apimachinery/pkg/util/sets"
"sigs.k8s.io/controller-runtime/pkg/client"

cfgtypes "github.com/kong/kubernetes-ingress-controller/v3/internal/manager/config/types"
)

// DiscoveredAdminAPI represents an Admin API discovered from a Kubernetes Service.
// For field Address use format https://<podIP>:<port>, and for field TLSServerName
// use format <podIPDashes>.<serviceName>.<namespace>.svc, where podIPDashes
// is the IP address separated by dashes instead of dots.
type DiscoveredAdminAPI struct {
// Address format is https://10.68.0.5:8444.
Address string
PodRef k8stypes.NamespacedName
// TLSServerName format is 10-68-0-5.dataplane-admin-kong-rqwr9-sc49t.default.svc.
TLSServerName string
// PodRef is the reference to the Pod with the above IP address.
PodRef k8stypes.NamespacedName
}

type Discoverer struct {
// portNames is the set of port names that Admin API Service ports will be
// matched against.
portNames sets.Set[string]

// dnsStrategy is the DNS strategy to use when resolving Admin API Service
// addresses.
dnsStrategy cfgtypes.DNSStrategy
}

func NewDiscoverer(
adminAPIPortNames sets.Set[string],
dnsStrategy cfgtypes.DNSStrategy,
) (*Discoverer, error) {
if adminAPIPortNames.Len() == 0 {
return nil, fmt.Errorf("no admin API port names provided")
}
if err := dnsStrategy.Validate(); err != nil {
return nil, fmt.Errorf("invalid dns strategy: %w", err)
}

return &Discoverer{
portNames: adminAPIPortNames,
dnsStrategy: dnsStrategy,
portNames: adminAPIPortNames,
}, nil
}

Expand Down Expand Up @@ -140,7 +136,7 @@ func (d *Discoverer) AdminAPIsFromEndpointSlice(
Namespace: endpoints.Namespace,
}

adminAPI, err := adminAPIFromEndpoint(e, p, svc, d.dnsStrategy, endpoints.AddressType)
adminAPI, err := adminAPIFromEndpoint(e, p, svc, endpoints.AddressType)
if err != nil {
return nil, err
}
Expand All @@ -154,7 +150,6 @@ func adminAPIFromEndpoint(
endpoint discoveryv1.Endpoint,
port discoveryv1.EndpointPort,
service k8stypes.NamespacedName,
dnsStrategy cfgtypes.DNSStrategy,
addressFamily discoveryv1.AddressType,
) (DiscoveredAdminAPI, error) {
podNN := k8stypes.NamespacedName{
Expand All @@ -165,49 +160,26 @@ func adminAPIFromEndpoint(
// NOTE: Endpoint's addresses are assumed to be fungible, therefore we pick
// only the first one.
// For the context please see the `Endpoint.Addresses` godoc.
eAddress := endpoint.Addresses[0]
podIPAddr := endpoint.Addresses[0]
if addressFamily == discoveryv1.AddressTypeIPv6 {
podIPAddr = fmt.Sprintf("[%s]", podIPAddr)
}
// TODO: more with ipv6

// NOTE: We assume https below because the referenced Admin API
// server will live in another Pod/elsewhere so allowing http would
// not be considered best practice.

switch dnsStrategy {
case cfgtypes.ServiceScopedPodDNSStrategy:
if service.Name == "" {
return DiscoveredAdminAPI{}, fmt.Errorf(
"service name is empty for an endpoint with TargetRef %s/%s",
endpoint.TargetRef.Namespace, endpoint.TargetRef.Name,
)
}

ipAddr := strings.ReplaceAll(eAddress, ".", "-")
address := fmt.Sprintf("%s.%s.%s.svc", ipAddr, service.Name, service.Namespace)

return DiscoveredAdminAPI{
Address: fmt.Sprintf("https://%s:%d", address, *port.Port),
PodRef: podNN,
}, nil

case cfgtypes.NamespaceScopedPodDNSStrategy:
ipAddr := strings.ReplaceAll(eAddress, ".", "-")
address := fmt.Sprintf("%s.%s.pod", ipAddr, service.Namespace)

return DiscoveredAdminAPI{
Address: fmt.Sprintf("https://%s:%d", address, *port.Port),
PodRef: podNN,
}, nil

case cfgtypes.IPDNSStrategy:
bounded := eAddress
if addressFamily == discoveryv1.AddressTypeIPv6 {
bounded = fmt.Sprintf("[%s]", bounded)
}
return DiscoveredAdminAPI{
Address: fmt.Sprintf("https://%s:%d", bounded, *port.Port),
PodRef: podNN,
}, nil

default:
return DiscoveredAdminAPI{}, fmt.Errorf("unknown dns strategy: %s", dnsStrategy)
if service.Name == "" {
return DiscoveredAdminAPI{}, fmt.Errorf(
"service name is empty for an endpoint with TargetRef %s/%s",
endpoint.TargetRef.Namespace, endpoint.TargetRef.Name,
)
}

return DiscoveredAdminAPI{
Address: fmt.Sprintf("https://%s:%d", podIPAddr, *port.Port),
TLSServerName: fmt.Sprintf("%s.%s.%s.svc", strings.ReplaceAll(podIPAddr, ".", "-"), service.Name, service.Namespace),
PodRef: podNN,
}, nil
}
Loading

0 comments on commit 385ef00

Please sign in to comment.