diff --git a/cmd/kubeadm/app/preflight/checks_test.go b/cmd/kubeadm/app/preflight/checks_test.go index 52a8bb127b4..cf93e8c1114 100644 --- a/cmd/kubeadm/app/preflight/checks_test.go +++ b/cmd/kubeadm/app/preflight/checks_test.go @@ -20,6 +20,7 @@ import ( "bytes" "fmt" "io/ioutil" + "net" "runtime" "strings" "testing" @@ -185,124 +186,228 @@ func (pfct preflightCheckTest) Check() (warning, errorList []error) { return } -func TestRunInitNodeChecks(t *testing.T) { +func TestFileExistingCheck(t *testing.T) { + f, err := os.CreateTemp("", "file-exist-check") + if err != nil { + t.Fatalf("Failed to create file: %v", err) + } + defer os.Remove(f.Name()) var tests = []struct { - name string - cfg *kubeadmapi.InitConfiguration - expected bool - isSecondaryControlPlane bool - downloadCerts bool + name string + check FileExistingCheck + expectedError bool }{ - {name: "Test valid advertised address", - cfg: &kubeadmapi.InitConfiguration{ - LocalAPIEndpoint: kubeadmapi.APIEndpoint{AdvertiseAddress: "foo"}, + { + name: "File does not exist, so it's not available", + check: FileExistingCheck{ + Path: "/does/not/exist", }, - expected: false, + expectedError: true, }, { - name: "Test CA file exists if specified", - cfg: &kubeadmapi.InitConfiguration{ - ClusterConfiguration: kubeadmapi.ClusterConfiguration{ - Etcd: kubeadmapi.Etcd{External: &kubeadmapi.ExternalEtcd{CAFile: "/foo"}}, - }, + name: "File exists and is available", + check: FileExistingCheck{ + Path: f.Name(), }, - expected: false, - }, - { - name: "Skip test CA file exists if specified/download certs", - cfg: &kubeadmapi.InitConfiguration{ - ClusterConfiguration: kubeadmapi.ClusterConfiguration{ - Etcd: kubeadmapi.Etcd{External: &kubeadmapi.ExternalEtcd{CAFile: "/foo"}}, - }, - }, - expected: true, - isSecondaryControlPlane: true, - downloadCerts: true, - }, - { - name: "Test Cert file exists if specified", - cfg: &kubeadmapi.InitConfiguration{ - ClusterConfiguration: kubeadmapi.ClusterConfiguration{ - Etcd: kubeadmapi.Etcd{External: &kubeadmapi.ExternalEtcd{CertFile: "/foo"}}, - }, - }, - expected: false, - }, - { - name: "Test Key file exists if specified", - cfg: &kubeadmapi.InitConfiguration{ - ClusterConfiguration: kubeadmapi.ClusterConfiguration{ - Etcd: kubeadmapi.Etcd{External: &kubeadmapi.ExternalEtcd{CertFile: "/foo"}}, - }, - }, - expected: false, - }, - { - name: "Test APIEndpoint exists if exists", - cfg: &kubeadmapi.InitConfiguration{ - LocalAPIEndpoint: kubeadmapi.APIEndpoint{AdvertiseAddress: "2001:1234::1:15"}, - }, - expected: false, + expectedError: false, }, } for _, rt := range tests { - // TODO: Make RunInitNodeChecks accept a ClusterConfiguration object instead of InitConfiguration - actual := RunInitNodeChecks(exec.New(), rt.cfg, sets.NewString(), rt.isSecondaryControlPlane, rt.downloadCerts) - if (actual == nil) != rt.expected { + _, output := rt.check.Check() + if (output != nil) != rt.expectedError { t.Errorf( - "failed RunInitNodeChecks:%v\n\texpected: %t\n\t actual: %t\n\t error: %v", + "Failed FileExistingCheck:%v\n\texpectedError: %t\n\t actual: %t", rt.name, - rt.expected, - (actual == nil), - actual, + rt.expectedError, + (output != nil), ) } } } -func TestRunJoinNodeChecks(t *testing.T) { +func TestFileAvailableCheck(t *testing.T) { + f, err := os.CreateTemp("", "file-avail-check") + if err != nil { + t.Fatalf("Failed to create file: %v", err) + } + defer os.Remove(f.Name()) var tests = []struct { - name string - cfg *kubeadmapi.JoinConfiguration - expected bool + name string + check FileAvailableCheck + expectedError bool }{ { - name: "Check empty JoinConfiguration", - cfg: &kubeadmapi.JoinConfiguration{}, - expected: false, + name: "The file does not exist", + check: FileAvailableCheck{ + Path: "/does/not/exist", + }, + expectedError: false, }, { - name: "Check TLS Bootstrap APIServerEndpoint IPv4 addr", - cfg: &kubeadmapi.JoinConfiguration{ - Discovery: kubeadmapi.Discovery{ - BootstrapToken: &kubeadmapi.BootstrapTokenDiscovery{ - APIServerEndpoint: "192.168.1.15", - }, - }, + name: "The file exists", + check: FileAvailableCheck{ + Path: f.Name(), }, - expected: false, - }, - { - name: "Check TLS Bootstrap APIServerEndpoint IPv6 addr", - cfg: &kubeadmapi.JoinConfiguration{ - Discovery: kubeadmapi.Discovery{ - BootstrapToken: &kubeadmapi.BootstrapTokenDiscovery{ - APIServerEndpoint: "2001:1234::1:15", - }, - }, - }, - expected: false, + expectedError: true, }, } - for _, rt := range tests { - actual := RunJoinNodeChecks(exec.New(), rt.cfg, sets.NewString()) - if (actual == nil) != rt.expected { + _, output := rt.check.Check() + if (output != nil) != rt.expectedError { t.Errorf( - "failed RunJoinNodeChecks:%v\n\texpected: %t\n\t actual: %t", + "Failed FileAvailableCheck:%v\n\texpectedError: %t\n\t actual: %t", rt.name, - rt.expected, - (actual != nil), + rt.expectedError, + (output != nil), + ) + } + } +} + +func TestFileContentCheck(t *testing.T) { + f, err := os.CreateTemp("", "file-content-check") + if err != nil { + t.Fatalf("Failed to create file: %v", err) + } + defer os.Remove(f.Name()) + var tests = []struct { + name string + check FileContentCheck + expectedError bool + }{ + { + name: "File exists and has matching content", + check: FileContentCheck{ + Path: f.Name(), + Content: []byte("Test FileContentCheck"), + }, + expectedError: false, + }, + { + name: "File exists, content is nil", + check: FileContentCheck{ + Path: f.Name(), + Content: nil, + }, + expectedError: false, + }, + { + name: "File exists but has unexpected content", + check: FileContentCheck{ + Path: f.Name(), + Content: []byte("foo"), + }, + expectedError: true, + }, + { + name: "File does not exist, content is not nil", + check: FileContentCheck{ + Path: "/does/not/exist", + Content: []byte("foo"), + }, + expectedError: true, + }, + { + name: "File dose not exist, content is nil", + check: FileContentCheck{ + Path: "/does/not/exist", + Content: nil, + }, + expectedError: true, + }, + } + if _, err = f.WriteString("Test FileContentCheck"); err != nil { + t.Fatalf("Failed to write to file: %v", err) + } + for _, rt := range tests { + _, output := rt.check.Check() + if (len(output) > 0) != rt.expectedError { + t.Errorf( + "Failed FileContentCheck:%v\n\texpectedError: %t\n\t actual: %t", + rt.name, + rt.expectedError, + (len(output) > 0), + ) + } + } +} + +func TestDirAvailableCheck(t *testing.T) { + fileDir, err := ioutil.TempDir("", "dir-avail-check") + if err != nil { + t.Fatalf("failed creating directory: %v", err) + } + defer os.RemoveAll(fileDir) + var tests = []struct { + name string + check DirAvailableCheck + expectedError bool + }{ + { + name: "Directory exists and is empty", + check: DirAvailableCheck{ + Path: fileDir, + }, + expectedError: false, + }, + { + name: "Directory exists and has something", + check: DirAvailableCheck{ + Path: os.TempDir(), // a directory was created previously in this test + }, + expectedError: true, + }, + { + name: "Directory does not exist", + check: DirAvailableCheck{ + Path: "/does/not/exist", + }, + expectedError: false, + }, + } + for _, rt := range tests { + _, output := rt.check.Check() + if (output != nil) != rt.expectedError { + t.Errorf( + "Failed DirAvailableCheck:%v\n\texpectedError: %t\n\t actual: %t", + rt.name, + rt.expectedError, + (output != nil), + ) + } + } +} + +func TestPortOpenCheck(t *testing.T) { + ln, err := net.Listen("tcp", ":0") + if err != nil { + t.Fatalf("could not listen on local network: %v", err) + } + defer ln.Close() + var tests = []struct { + name string + check PortOpenCheck + expectedError bool + }{ + { + name: "Port is available", + check: PortOpenCheck{port: 0}, + expectedError: false, + }, + { + name: "Port is not available", + check: PortOpenCheck{port: ln.Addr().(*net.TCPAddr).Port}, + expectedError: true, + }, + } + for _, rt := range tests { + _, output := rt.check.Check() + if (output != nil) != rt.expectedError { + t.Errorf( + "Failed PortOpenCheck:%v\n\texpectedError: %t\n\t actual: %t", + rt.name, + rt.expectedError, + (output != nil), ) } } @@ -650,6 +755,7 @@ func resetProxyEnv(t *testing.T) map[string]string { t.Log("Saved environment: ", savedEnv) os.Setenv("HTTP_PROXY", "http://proxy.example.com:3128") + os.Setenv("HTTPS_PROXY", "https://proxy.example.com:3128") os.Setenv("NO_PROXY", "example.com,10.0.0.0/8,2001:db8::/48") // Check if we can reliably execute tests: // ProxyFromEnvironment caches the *_proxy environment variables and