Skip to content

Commit

Permalink
pkg/cmd/render: check if bootstrap IP is part of clusterNetwork cidr
Browse files Browse the repository at this point in the history
Signed-off-by: Sam Batschelet <[email protected]>
  • Loading branch information
hexfusion committed Feb 23, 2020
1 parent 6ff2c92 commit db60c05
Show file tree
Hide file tree
Showing 4 changed files with 77 additions and 30 deletions.
72 changes: 49 additions & 23 deletions pkg/cmd/render/render.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,10 +10,11 @@ import (
"path/filepath"
"strings"

"github.com/openshift/cluster-etcd-operator/pkg/cmd/render/options"
"github.com/openshift/cluster-etcd-operator/pkg/dnshelpers"
"github.com/openshift/cluster-etcd-operator/pkg/operator/etcd_assets"

"github.com/ghodss/yaml"
"github.com/openshift/cluster-etcd-operator/pkg/cmd/render/options"
"github.com/openshift/library-go/pkg/assets"
"github.com/spf13/cobra"
"github.com/spf13/pflag"
Expand Down Expand Up @@ -207,8 +208,9 @@ func newTemplateData(opts *renderOpts) (*TemplateData, error) {
return nil, err
}
}

templateData.setEtcdAddress()
if err := templateData.setEtcdAddress(); err != nil {
return nil, err
}

return &templateData, nil
}
Expand Down Expand Up @@ -237,47 +239,70 @@ func (r *renderOpts) Run() error {
return WriteFiles(&r.generic, &templateData.FileConfig, templateData)
}

// setBootstrapIP gets a list of IPs from local interfaces and returns the first IPv4 or IPv6 address.
func (t *TemplateData) setBootstrapIP() error {
var bootstrapIP string
ips, err := ipAddrs()
bootstrapIP, err := t.getBootstrapIP()
if err != nil {
return err
}
t.BootstrapIP = bootstrapIP
return nil
}

// getBootstrapIP gets a list of IPs from local interfaces and returns the first address that is contained
// in the ClusterCIDR[0] network. No extra checks are preformed if --bootstrap-ip is passed by flag.
func (t *TemplateData) getBootstrapIP() (string, error) {
if t.BootstrapIP != "" {
return t.BootstrapIP, nil
}
ips, err := ipAddrs()
if err != nil {
return "", err
}

for _, addr := range ips {
ip := net.ParseIP(addr)
// IPv6
if t.SingleStackIPv6 && ip.To4() == nil {
bootstrapIP = addr
break
isBootstrapIp, err := dnshelpers.IsNetworkContainIp(t.ClusterCIDR[0], addr)
if err != nil {
return "", err
}
// IPv4
if !t.SingleStackIPv6 && ip.To4() != nil {
bootstrapIP = addr
break
if isBootstrapIp {
return addr, nil
}
}

if bootstrapIP == "" {
return fmt.Errorf("no IP address found for bootstrap node")
return "", fmt.Errorf("no IP address on bootstrap node matches clusterNetwork cidr %s", t.ClusterCIDR[0])
}

func (t *TemplateData) getEscapedBootstrapIP() (string, error) {
bootstrapIP, err := t.getBootstrapIP()
if err != nil {
return "", err
}

t.BootstrapIP = bootstrapIP
return nil
isIPV4, err := dnshelpers.IsIPv4(bootstrapIP)
if err != nil {
return "", err
}
if !isIPV4 {
return "[" + bootstrapIP + "]", nil
}

return bootstrapIP, nil
}

func (t *TemplateData) setEtcdAddress() {
func (t *TemplateData) setEtcdAddress() error {
escapedBootsrapIP, err := t.getEscapedBootstrapIP()
if err != nil {
return err
}

// IPv4
allAddresses := "0.0.0.0"
localhost := "127.0.0.1"
bootstrapIP := t.BootstrapIP

// IPv6
if t.SingleStackIPv6 {
allAddresses = "::"
localhost = "[::1]"
bootstrapIP = "[" + t.BootstrapIP + "]"
}

etcdAddress := options.EtcdAddress{
Expand All @@ -286,10 +311,11 @@ func (t *TemplateData) setEtcdAddress() {
LocalHost: localhost,
ListenMetricServer: net.JoinHostPort(allAddresses, "9978"),
ListenMetricProxy: net.JoinHostPort(allAddresses, "9979"),
EscapedBootstrapIP: bootstrapIP,
EscapedBootstrapIP: escapedBootsrapIP,
}

t.ManifestConfig.EtcdAddress = etcdAddress
return nil
}

func (t *TemplateData) getClusterConfigFromFile(clusterConfigFile string) (*unstructured.Unstructured, error) {
Expand Down
11 changes: 9 additions & 2 deletions pkg/cmd/render/render_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -117,12 +117,14 @@ func TestRenderIpv4(t *testing.T) {
ClusterCIDR: []string{"10.128.0.0/14"},
ServiceCIDR: []string{"172.30.0.0/16"},
SingleStackIPv6: false,
BootstrapIP: "10.128.0.12",
}

config := &testConfig{
t: t,
clusterNetworkConfig: networkConfigIpv4,
want: want,
bootstrapIP: "10.128.0.12",
}

testRender(config)
Expand Down Expand Up @@ -159,6 +161,7 @@ func testRender(tc *testConfig) {
manifest: *options.NewManifestOptions("etcd"),
errOut: errOut,
clusterConfigFile: clusterConfigFile.Name(),
bootstrapIP: tc.bootstrapIP,
}

if err := render.Run(); err != nil {
Expand All @@ -176,12 +179,14 @@ func TestTemplateDataIpv4(t *testing.T) {
ClusterCIDR: []string{"10.128.0.0/14"},
ServiceCIDR: []string{"172.30.0.0/16"},
SingleStackIPv6: false,
BootstrapIP: "10.128.0.12",
}

config := &testConfig{
t: t,
clusterNetworkConfig: networkConfigIpv4,
want: want,
bootstrapIP: "10.128.0.12",
}
testTemplateData(config)
}
Expand All @@ -196,12 +201,14 @@ func TestTemplateDataMixed(t *testing.T) {
ClusterCIDR: []string{"10.128.10.0/14"},
ServiceCIDR: []string{"2001:db8::/32", "172.30.0.0/16"},
SingleStackIPv6: false,
BootstrapIP: "10.128.0.12",
}

config := &testConfig{
t: t,
clusterNetworkConfig: networkConfigMixedSwap,
want: want,
bootstrapIP: "10.128.0.12",
}
testTemplateData(config)
}
Expand All @@ -216,14 +223,14 @@ func TestTemplateDataSingleStack(t *testing.T) {
ClusterCIDR: []string{"10.128.0.0/14"},
ServiceCIDR: []string{"2001:db8::/32"},
SingleStackIPv6: true,
BootstrapIP: "2001:0DB8:C21A",
BootstrapIP: "fe80::d66c:724c:13d4:829c",
}

config := &testConfig{
t: t,
clusterNetworkConfig: networkConfigIPv6SingleStack,
want: want,
bootstrapIP: "2001:0DB8:C21A",
bootstrapIP: "fe80::d66c:724c:13d4:829c",
}
testTemplateData(config)
}
Expand Down
11 changes: 11 additions & 0 deletions pkg/dnshelpers/util.go
Original file line number Diff line number Diff line change
Expand Up @@ -183,3 +183,14 @@ func reverseLookupForOneIP(discoveryDomain, ipAddress string) (string, error) {
}
return selfTarget, nil
}

func IsNetworkContainIp(network, ipAddress string) (bool, error) {
_, parsedNet, err := net.ParseCIDR(network)
if err != nil {
return false, err
}
if parsedNet.Contains(net.ParseIP(ipAddress)) {
return true, nil
}
return false, nil
}
13 changes: 8 additions & 5 deletions pkg/etcdcli/etcdcli.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@ package etcdcli
import (
"context"
"fmt"
"net"
"time"

configv1informers "github.com/openshift/client-go/config/informers/externalversions/config/v1"
Expand Down Expand Up @@ -81,11 +80,15 @@ func (g *etcdClientGetter) getEtcdClient() (*clientv3.Client, error) {
klog.V(2).Infof("service/host-etcd-2 is missing annotation %s", BootstrapIPAnnotationKey)
}
if bootstrapIP != "" {
// escape if IPv6
if net.ParseIP(bootstrapIP).To4() == nil {
bootstrapIP = "[" + bootstrapIP + "]"
isIPV4, err := dnshelpers.IsIPv4(bootstrapIP)
if err != nil {
return nil, err
}
if isIPV4 {
etcdEndpoints = append(etcdEndpoints, "https://"+bootstrapIP+":2379")
} else {
etcdEndpoints = append(etcdEndpoints, "https://["+bootstrapIP+"]:2379")
}
etcdEndpoints = append(etcdEndpoints, fmt.Sprintf("https://%s:2379", bootstrapIP))
}
c, err := getEtcdClient(etcdEndpoints)
if err != nil {
Expand Down

0 comments on commit db60c05

Please sign in to comment.