Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Updates #26

Merged
merged 8 commits into from
Jul 30, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ jobs:
run: |
sudo apt-get -qq update || true
sudo apt-get install -y bzr
curl -LO https://storage.googleapis.com/kubernetes-release/release/v1.17.0/bin/linux/amd64/kubectl
curl -LO "https://dl.k8s.io/release/$(curl -L -s https://dl.k8s.io/release/stable.txt)/bin/linux/amd64/kubectl"
chmod +x ./kubectl
sudo mv ./kubectl /usr/local/bin/kubectl

Expand Down
3 changes: 3 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -29,3 +29,6 @@ _testmain.go

/bin
/.go

# peer-finder
peer-finder
11 changes: 5 additions & 6 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -6,15 +6,14 @@ toolchain go1.22.2

require (
github.com/kballard/go-shellquote v0.0.0-20180428030007-95032a82bc51
k8s.io/api v0.29.2
k8s.io/apimachinery v0.29.2
k8s.io/client-go v0.29.2
k8s.io/klog/v2 v2.120.1
k8s.io/api v0.30.3
k8s.io/apimachinery v0.30.3
k8s.io/client-go v0.30.3
k8s.io/klog/v2 v2.130.1
)

require (
github.com/google/pprof v0.0.0-20221118152302-e6195bd50e26 // indirect
github.com/onsi/ginkgo/v2 v2.15.0 // indirect
github.com/onsi/gomega v1.31.1 // indirect
github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 // indirect
github.com/rogpeppe/go-internal v1.11.0 // indirect
Expand All @@ -24,7 +23,7 @@ require (
require (
github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc // indirect
github.com/emicklei/go-restful/v3 v3.11.0 // indirect
github.com/go-logr/logr v1.4.1 // indirect
github.com/go-logr/logr v1.4.2 // indirect
github.com/go-openapi/jsonpointer v0.20.0 // indirect
github.com/go-openapi/jsonreference v0.20.2 // indirect
github.com/go-openapi/swag v0.22.4 // indirect
Expand Down
20 changes: 10 additions & 10 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,8 @@ github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc h1:U9qPSI2PIWSS1
github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/emicklei/go-restful/v3 v3.11.0 h1:rAQeMHw1c7zTmncogyy8VvRZwtkmkZ4FxERmMY4rD+g=
github.com/emicklei/go-restful/v3 v3.11.0/go.mod h1:6n3XBCmQQb25CM2LCACGz8ukIrRry+4bhvbpWn3mrbc=
github.com/go-logr/logr v1.4.1 h1:pKouT5E8xu9zeFC39JXRDukb6JFQPXM5p5I91188VAQ=
github.com/go-logr/logr v1.4.1/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY=
github.com/go-logr/logr v1.4.2 h1:6pFjapn8bFcIbiKo3XT4j/BhANplGihG6tvd+8rYgrY=
github.com/go-logr/logr v1.4.2/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY=
github.com/go-openapi/jsonpointer v0.19.6/go.mod h1:osyAmYz/mB/C3I+WsTTSgw1ONzaLJoLCyoi6/zppojs=
github.com/go-openapi/jsonpointer v0.20.0 h1:ESKJdU9ASRfaPNOPRx12IUyA1vn3R9GiE3KYD14BXdQ=
github.com/go-openapi/jsonpointer v0.20.0/go.mod h1:6PGzBjjIIumbLYysB73Klnms1mwnU4G3YHOECG3CedA=
Expand Down Expand Up @@ -155,14 +155,14 @@ gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ=
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
k8s.io/api v0.29.2 h1:hBC7B9+MU+ptchxEqTNW2DkUosJpp1P+Wn6YncZ474A=
k8s.io/api v0.29.2/go.mod h1:sdIaaKuU7P44aoyyLlikSLayT6Vb7bvJNCX105xZXY0=
k8s.io/apimachinery v0.29.2 h1:EWGpfJ856oj11C52NRCHuU7rFDwxev48z+6DSlGNsV8=
k8s.io/apimachinery v0.29.2/go.mod h1:6HVkd1FwxIagpYrHSwJlQqZI3G9LfYWRPAkUvLnXTKU=
k8s.io/client-go v0.29.2 h1:FEg85el1TeZp+/vYJM7hkDlSTFZ+c5nnK44DJ4FyoRg=
k8s.io/client-go v0.29.2/go.mod h1:knlvFZE58VpqbQpJNbCbctTVXcd35mMyAAwBdpt4jrA=
k8s.io/klog/v2 v2.120.1 h1:QXU6cPEOIslTGvZaXvFWiP9VKyeet3sawzTOvdXb4Vw=
k8s.io/klog/v2 v2.120.1/go.mod h1:3Jpz1GvMt720eyJH1ckRHK1EDfpxISzJ7I9OYgaDtPE=
k8s.io/api v0.30.3 h1:ImHwK9DCsPA9uoU3rVh4QHAHHK5dTSv1nxJUapx8hoQ=
k8s.io/api v0.30.3/go.mod h1:GPc8jlzoe5JG3pb0KJCSLX5oAFIW3/qNJITlDj8BH04=
k8s.io/apimachinery v0.30.3 h1:q1laaWCmrszyQuSQCfNB8cFgCuDAoPszKY4ucAjDwHc=
k8s.io/apimachinery v0.30.3/go.mod h1:iexa2somDaxdnj7bha06bhb43Zpa6eWH8N8dbqVjTUc=
k8s.io/client-go v0.30.3 h1:bHrJu3xQZNXIi8/MoxYtZBBWQQXwy16zqJwloXXfD3k=
k8s.io/client-go v0.30.3/go.mod h1:8d4pf8vYu665/kUbsxWAQ/JDBNWqfFeZnvFiVdmx89U=
k8s.io/klog/v2 v2.130.1 h1:n9Xl7H1Xvksem4KFG4PYbdQCQxqc/tTUyrgXaOhHSzk=
k8s.io/klog/v2 v2.130.1/go.mod h1:3Jpz1GvMt720eyJH1ckRHK1EDfpxISzJ7I9OYgaDtPE=
k8s.io/kube-openapi v0.0.0-20240228011516-70dd3763d340 h1:BZqlfIlq5YbRMFko6/PM7FjZpUb45WallggurYhKGag=
k8s.io/kube-openapi v0.0.0-20240228011516-70dd3763d340/go.mod h1:yD4MZYeKMBwQKVht279WycxKyM84kkAx2DPrTXaeb98=
k8s.io/utils v0.0.0-20240102154912-e7106e64919e h1:eQ/4ljkx21sObifjzXwlPKpdGLrCfRziVtos3ofG/sQ=
Expand Down
61 changes: 43 additions & 18 deletions peer-finder.go
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,10 @@ const (
pollPeriod = 1 * time.Second
)

const (
defaultTimeout = 10 * time.Second
)

type AddressType string

const (
Expand All @@ -61,7 +65,7 @@ var (
)

var (
masterURL = flag.String("master", "", "The address of the Kubernetes API server (overrides any value in kubeconfig)")
masterURL = flag.String("master", "", "The address of the Kubernetes API server (overrides any value in kubeconfig).")
kubeconfigPath = flag.String("kubeconfig", "", "Path to kubeconfig file with authorization information (the master location is set by the master flag).")
hostsFilePath = flag.String("hosts-file", "/etc/hosts", "Path to hosts file.")
onChange = flag.String("on-change", "", "Script to run on change, must accept a new line separated list of peers via stdin.")
Expand All @@ -70,32 +74,52 @@ var (
svc = flag.String("service", "", "Governing service responsible for the DNS records of the domain this pod is in.")
namespace = flag.String("ns", "", "The namespace this pod is running in. If unspecified, the POD_NAMESPACE env var is used.")
domain = flag.String("domain", "", "The Cluster Domain which is used by the Cluster, if not set tries to determine it from /etc/resolv.conf file.")
selector = flag.String("selector", "", "The selector is used to select the pods whose ip will use to form peers")
selector = flag.String("selector", "", "The selector is used to select the pods whose ip will use to form peers.")
)

func lookupDNS(svcName string) (sets.Set[string], error) {
endpoints := sets.New[string]()
_, srvRecords, err := net.LookupSRV("", "", svcName)

ctx, cancel := context.WithTimeout(context.Background(), defaultTimeout)
defer cancel()

_, srvRecords, err := net.DefaultResolver.LookupSRV(ctx, "", "", svcName)
if err != nil {
return endpoints, err
return endpoints, fmt.Errorf("DNS lookup failed for service %s: %w", svcName, err)
}

for _, srvRecord := range srvRecords {
// The SRV records ends in a "." for the root domain
ep := fmt.Sprintf("%v", srvRecord.Target[:len(srvRecord.Target)-1])
// Trim the trailing dot
ep := strings.TrimSuffix(srvRecord.Target, ".")
endpoints.Insert(ep)
}

if endpoints.Len() == 0 {
return endpoints, fmt.Errorf("no endpoints found for service %s", svcName)
}

return endpoints, nil
}

func lookupHostIPs(hostName string) (sets.Set[string], error) {
ctx, cancel := context.WithTimeout(context.Background(), defaultTimeout)
defer cancel()

ips := sets.New[string]()
hostIPs, err := net.LookupIP(hostName)
hostIPs, err := net.DefaultResolver.LookupIP(ctx, "ip", hostName)
if err != nil {
return nil, err
return nil, fmt.Errorf("IP lookup failed for host %s: %w", hostName, err)
}

for _, hostIP := range hostIPs {
ips.Insert(hostIP.String())
}

if ips.Len() == 0 {
return nil, fmt.Errorf("no valid IP addresses found for host %s", hostName)
}

return ips, nil
}

Expand Down Expand Up @@ -124,7 +148,7 @@ func shellOut(script string, peers, hostIPs sets.Set[string], fqHostname string)

envs := sets.NewString(os.Environ()...)

envs.Insert("HOST_ADDRESS=" + info.HostAddr) // fqdn, ipv4, ipv6
envs.Insert("HOST_ADDRESS=" + info.HostAddr) // FQDN, IPv4, IPv6
envs.Insert("HOST_ADDRESS_TYPE=" + string(info.HostAddrType)) // DNS, IPv4, IPv6
// WARNING: Potentially overwrites the POD_IP from container env before passing to script in case of IPv4 or IPv6 in a dual stack cluster
envs.Insert("POD_IP=" + info.PodIP) // used for whitelist
Expand All @@ -140,12 +164,12 @@ func shellOut(script string, peers, hostIPs sets.Set[string], fqHostname string)
}

type HostInfo struct {
// fqdn, ipv4, ipv6
// FQDN, IPv4, IPv6
HostAddr string
// DNS, IPv4, IPv6
HostAddrType AddressType

// used for whitelist
// used for allowlist
// WARNING: Potentially overwrites the POD_IP from container env before passing to script in case of IPv4 or IPv6 in a dual stack cluster
PodIP string
// IPv4 or IPv6
Expand All @@ -155,11 +179,12 @@ type HostInfo struct {
func retrieveHostInfo(fqHostname string, hostIPs, peers sets.Set[string]) (*HostInfo, error) {
var info HostInfo
var err error

switch AddressType(*addrType) {
case AddressTypeDNS:
info.HostAddr = fqHostname
info.HostAddrType = AddressTypeDNS
info.PodIP = os.Getenv("POD_IP") // set using Downward api
info.PodIP = os.Getenv("POD_IP") // set using Downward API
info.PodIPType, err = IPType(info.PodIP)
if err != nil {
return nil, err
Expand Down Expand Up @@ -201,7 +226,7 @@ func retrieveHostInfo(fqHostname string, hostIPs, peers sets.Set[string]) (*Host
func IPType(s string) (AddressType, error) {
ip := net.ParseIP(s)
if ip == nil {
return "", fmt.Errorf("%s is not a valid IP", s)
return "", fmt.Errorf("%s is not a valid IP address", s)
}
if strings.ContainsRune(s, ':') {
return AddressTypeIPv6, nil
Expand Down Expand Up @@ -246,15 +271,16 @@ func main() {

// TODO: Exit if there's no on-change?
if err := run(stopCh); err != nil {
log.Error(err, "peer finder exiting")
log.Error(err, "peer finder exiting.")
}
klog.Flush()

log.Info("Block until Kubernetes sends SIGKILL")
log.Info("Block until Kubernetes sends the signal SIGKILL .")
select {}
}

func run(stopCh <-chan struct{}) error {
var domainName string
ns := *namespace
if ns == "" {
ns = os.Getenv("POD_NAMESPACE")
Expand All @@ -263,15 +289,14 @@ func run(stopCh <-chan struct{}) error {
if err != nil {
return fmt.Errorf("failed to get hostname: %s", err)
}
var domainName string

// If domain is not provided, try to get it from resolv.conf
if *domain == "" {
resolvConfBytes, err := os.ReadFile("/etc/resolv.conf")
resolvConf := string(resolvConfBytes)
if err != nil {
return fmt.Errorf("unable to read /etc/resolv.conf")
}
resolvConf := string(resolvConfBytes)

var re *regexp.Regexp
if ns == "" {
Expand Down Expand Up @@ -306,7 +331,7 @@ func run(stopCh <-chan struct{}) error {
}

if (*selector == "" && *svc == "") || domainName == "" || (*onChange == "" && *onStart == "") {
return fmt.Errorf("incomplete args, require -on-change and/or -on-start, -service and -ns or an env var for POD_NAMESPACE")
return fmt.Errorf("incomplete arguments, require -on-change and/or -on-start, -service and -ns or an environment variable named POD_NAMESPACE")
}

if *selector != "" {
Expand All @@ -324,7 +349,7 @@ func run(stopCh <-chan struct{}) error {
myName := strings.Join([]string{hostname, *svc, domainName}, ".")
hostIPs, err := lookupHostIPs(hostname)
if err != nil {
return fmt.Errorf("failed to get ips from host %v", err)
return fmt.Errorf("failed to get IP addresses from host %v", err)
}
script := *onStart
if script == "" {
Expand Down
1 change: 1 addition & 0 deletions vendor/github.com/go-logr/logr/README.md

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

Loading
Loading