*
* Copyright (c) 2025 Bocloud Technologies Co., Ltd.
* installer is licensed under Mulan PSL v2.
* You can use this software according to the terms and conditions of the Mulan PSL v2.
* You may obtain a copy of Mulan PSL v2 at:
* <http://license.coscl.org.cn/MulanPSL2>
* THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
* EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
* MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
* See the Mulan PSL v2 for more details.
*
*/
package server
import (
"fmt"
"os"
"path/filepath"
"strings"
"testing"
"github.com/agiledragon/gomonkey/v2"
"github.com/stretchr/testify/assert"
"gopkg.openfuyao.cn/bkeadm/pkg/executor/exec"
"gopkg.openfuyao.cn/bkeadm/pkg/infrastructure/k3s"
"gopkg.openfuyao.cn/bkeadm/utils"
)
const (
testFileModeReadOnly = 0644
testFileModeExec = 0755
)
func TestFileExists(t *testing.T) {
tempDir := t.TempDir()
testFile := filepath.Join(tempDir, "test-file.txt")
err := os.WriteFile(testFile, []byte("test"), testFileModeReadOnly)
assert.NoError(t, err)
testDir := filepath.Join(tempDir, "test-dir")
err = os.MkdirAll(testDir, testFileModeExec)
assert.NoError(t, err)
tests := []struct {
name string
filename string
expected bool
}{
{
name: "existing file",
filename: testFile,
expected: true,
},
{
name: "existing directory",
filename: testDir,
expected: true,
},
{
name: "non-existing file",
filename: filepath.Join(tempDir, "nonexistent.txt"),
expected: false,
},
{
name: "empty filename",
filename: "",
expected: false,
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
result := utils.FileExists(tt.filename)
assert.Equal(t, tt.expected, result)
})
}
}
func TestWriteCommon(t *testing.T) {
tempDir := t.TempDir()
testFile := filepath.Join(tempDir, "test-write.txt")
certContent := "-----BEGIN CERTIFICATE-----\nMIIC...certificate content...\n-----END CERTIFICATE-----"
err := utils.WriteCommon(testFile, certContent)
assert.NoError(t, err)
content, err := os.ReadFile(testFile)
assert.NoError(t, err)
assert.Equal(t, certContent, string(content))
info, err := os.Stat(testFile)
assert.NoError(t, err)
assert.Equal(t, os.FileMode(utils.DefaultFilePermission), info.Mode())
}
func TestWriteCommonErrorCases(t *testing.T) {
tests := []struct {
name string
setupPath func(t *testing.T) string
mockOpenFile func(string, int, os.FileMode) (*os.File, error)
expectError bool
}{
{
name: "open file fails",
setupPath: func(t *testing.T) string {
return filepath.Join(t.TempDir(), "file.txt")
},
mockOpenFile: func(string, int, os.FileMode) (*os.File, error) {
return nil, fmt.Errorf("open failed")
},
expectError: true,
},
{
name: "write string fails",
setupPath: func(t *testing.T) string {
return t.TempDir()
},
expectError: true,
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
testFile := tt.setupPath(t)
patches := gomonkey.NewPatches()
defer patches.Reset()
if tt.mockOpenFile != nil {
patches.ApplyFunc(os.OpenFile, tt.mockOpenFile)
}
err := utils.WriteCommon(testFile, "test content")
if tt.expectError {
assert.Error(t, err)
} else {
assert.NoError(t, err)
}
})
}
}
func TestWriteCommonWithWriteFailure(t *testing.T) {
testDir := t.TempDir()
err := utils.WriteCommon(testDir, "test certificate content")
assert.Error(t, err)
}
func TestGetCertContent(t *testing.T) {
tempDir := t.TempDir()
certFile := filepath.Join(tempDir, serverCrtFile)
certContent := "certificate content"
err := os.WriteFile(certFile, []byte(certContent), testFileModeReadOnly)
assert.NoError(t, err)
content, err := getCertContent(tempDir)
assert.NoError(t, err)
assert.Equal(t, certContent, content)
}
func TestGetCertContentError(t *testing.T) {
_, err := getCertContent("/nonexistent/directory")
assert.Error(t, err)
assert.Contains(t, err.Error(), "failed to read certificate file")
}
func TestSetCommonCert(t *testing.T) {
tempDir := t.TempDir()
srcDir := filepath.Join(tempDir, "src")
dstDir := filepath.Join(tempDir, "dst")
err := os.MkdirAll(srcDir, testFileModeExec)
assert.NoError(t, err)
srcCertFile := filepath.Join(srcDir, serverCrtFile)
err = os.WriteFile(srcCertFile, []byte("source certificate content"), testFileModeReadOnly)
assert.NoError(t, err)
err = setCommonCert(srcDir, dstDir)
assert.NoError(t, err)
assert.True(t, utils.FileExists(dstDir))
assert.True(t, utils.FileExists(filepath.Join(dstDir, "ca.crt")))
content, err := os.ReadFile(filepath.Join(dstDir, "ca.crt"))
assert.NoError(t, err)
assert.Equal(t, "source certificate content", string(content))
}
func TestSetCommonCertDstDirExists(t *testing.T) {
tempDir := t.TempDir()
srcDir := filepath.Join(tempDir, "src")
dstDir := filepath.Join(tempDir, "dst")
err := os.MkdirAll(srcDir, testFileModeExec)
assert.NoError(t, err)
err = os.MkdirAll(dstDir, testFileModeExec)
assert.NoError(t, err)
srcCertFile := filepath.Join(srcDir, serverCrtFile)
err = os.WriteFile(srcCertFile, []byte("source certificate content"), testFileModeReadOnly)
assert.NoError(t, err)
dstCertFile := filepath.Join(dstDir, "ca.crt")
err = os.WriteFile(dstCertFile, []byte("existing content"), testFileModeReadOnly)
assert.NoError(t, err)
err = setCommonCert(srcDir, dstDir)
assert.NoError(t, err)
content, err := os.ReadFile(dstCertFile)
assert.NoError(t, err)
assert.Equal(t, "existing content", string(content))
}
func TestSetCommonCertErrorCases(t *testing.T) {
tempDir := t.TempDir()
tests := []struct {
name string
srcDir string
dstDir string
expectError bool
}{
{
name: "source directory doesn't exist",
srcDir: "/nonexistent/src",
dstDir: filepath.Join(tempDir, "dst"),
expectError: true,
},
{
name: "source certificate file doesn't exist",
srcDir: filepath.Join(tempDir, "src-no-cert"),
dstDir: filepath.Join(tempDir, "dst"),
expectError: true,
},
{
name: "destination directory creation fails",
srcDir: filepath.Join(tempDir, "src"),
dstDir: filepath.Join(tempDir, "dst-fail"),
expectError: true,
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
if tt.name == "source directory doesn't exist" {
err := setCommonCert(tt.srcDir, tt.dstDir)
if tt.expectError {
assert.Error(t, err)
} else {
assert.NoError(t, err)
}
} else if tt.name == "source certificate file doesn't exist" {
err := os.MkdirAll(tt.srcDir, testFileModeExec)
assert.NoError(t, err)
err = setCommonCert(tt.srcDir, tt.dstDir)
if tt.expectError {
assert.Error(t, err)
} else {
assert.NoError(t, err)
}
} else if tt.name == "destination directory creation fails" {
err := os.MkdirAll(tt.srcDir, testFileModeExec)
assert.NoError(t, err)
srcCertFile := filepath.Join(tt.srcDir, serverCrtFile)
err = os.WriteFile(srcCertFile, []byte("test cert"), testFileModeReadOnly)
assert.NoError(t, err)
patches := gomonkey.NewPatches()
defer patches.Reset()
patches.ApplyFunc(utils.FileExists, func(filename string) bool {
if filename == tt.dstDir || filename == tt.dstDir+"/ca.crt" {
return false
}
_, statErr := os.Stat(filename)
return statErr == nil
})
patches.ApplyFunc(os.MkdirAll, func(path string, perm os.FileMode) error {
if path == tt.dstDir {
return fmt.Errorf("mkdir failed")
}
return nil
})
err = setCommonCert(tt.srcDir, tt.dstDir)
if tt.expectError {
assert.Error(t, err)
} else {
assert.NoError(t, err)
}
}
})
}
}
func TestSetClientLocalCertificate(t *testing.T) {
tempDir := t.TempDir()
srcDir := filepath.Join(tempDir, "src")
err := os.MkdirAll(srcDir, testFileModeExec)
assert.NoError(t, err)
srcCertFile := filepath.Join(srcDir, serverCrtFile)
err = os.WriteFile(srcCertFile, []byte("local certificate content"), testFileModeReadOnly)
assert.NoError(t, err)
clientCertDir := fmt.Sprintf("%s/certs.d/127.0.0.1:%s", k3s.DefaultK3sDataDir, "5000")
patches := gomonkey.NewPatches()
defer patches.Reset()
patches.ApplyFunc(utils.FileExists, func(filename string) bool {
if filename == clientCertDir || filename == clientCertDir+"/ca.crt" {
return false
}
_, err := os.Stat(filename)
return err == nil
})
patches.ApplyFunc(os.MkdirAll, func(path string, perm os.FileMode) error {
if path == clientCertDir {
return fmt.Errorf("mkdir failed")
}
return nil
})
err = SetClientLocalCertificate(srcDir, "5000")
assert.Error(t, err)
}
func TestSetServerCertificate(t *testing.T) {
tempDir := t.TempDir()
patches := gomonkey.NewPatches()
defer patches.Reset()
patches.ApplyFunc(os.WriteFile, func(filename string, data []byte, perm os.FileMode) error {
return nil
})
patches.ApplyFunc((*exec.CommandExecutor).ExecuteCommandWithCombinedOutput, func(c *exec.CommandExecutor, command string, args ...string) (string, error) {
return "script output", nil
})
err := SetServerCertificate(tempDir)
assert.NoError(t, err)
}
func TestSetServerCertificateErrorCases(t *testing.T) {
tests := []struct {
name string
certPath string
mockWriteFile func(string, []byte, os.FileMode) error
mockExecuteCommand func(*exec.CommandExecutor, string, ...string) (string, error)
expectError bool
}{
{
name: "write file fails",
certPath: "/tmp/test",
mockWriteFile: func(filename string, data []byte, perm os.FileMode) error {
return fmt.Errorf("write failed")
},
expectError: true,
},
{
name: "execute command fails",
certPath: "/tmp/test",
mockWriteFile: func(filename string, data []byte, perm os.FileMode) error {
return nil
},
mockExecuteCommand: func(executor *exec.CommandExecutor, command string, args ...string) (string, error) {
return "error output", fmt.Errorf("execution failed")
},
expectError: true,
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
patches := gomonkey.NewPatches()
defer patches.Reset()
patches.ApplyFunc(os.WriteFile, tt.mockWriteFile)
if tt.mockExecuteCommand != nil {
patches.ApplyFunc((*exec.CommandExecutor).ExecuteCommandWithCombinedOutput, tt.mockExecuteCommand)
}
err := SetServerCertificate(tt.certPath)
if tt.expectError {
assert.Error(t, err)
assert.Contains(t, err.Error(), "failed")
} else {
assert.NoError(t, err)
}
})
}
}
func TestSetRegistryConfig(t *testing.T) {
tempDir := t.TempDir()
err := SetRegistryConfig(tempDir)
assert.NoError(t, err)
}
func TestSetRegistryConfigDirectoryCreation(t *testing.T) {
tempDir := t.TempDir()
configDir := filepath.Join(tempDir, "registry-config")
patches := gomonkey.NewPatches()
defer patches.Reset()
patches.ApplyFunc(os.MkdirAll, func(path string, perm os.FileMode) error {
return nil
})
patches.ApplyFunc(utils.FileExists, func(filename string) bool {
if filename == configDir {
return false
}
if strings.Contains(filename, "config.yml") {
return false
}
return false
})
patches.ApplyFunc(utils.WriteCommon, func(file, cert string) error {
return nil
})
err := SetRegistryConfig(configDir)
assert.NoError(t, err)
}
func TestSetRegistryConfigErrorCases(t *testing.T) {
tests := []struct {
name string
certPath string
mockFileExists func(string) bool
mockMkdirAll func(string, os.FileMode) error
mockWriteCommon func(string, string) error
expectError bool
}{
{
name: "mkdir all fails",
certPath: "/invalid/path",
mockFileExists: func(filename string) bool {
return false
},
mockMkdirAll: func(path string, perm os.FileMode) error {
return fmt.Errorf("mkdir failed")
},
expectError: true,
},
{
name: "write common fails",
certPath: "/tmp/test",
mockFileExists: func(filename string) bool {
if strings.Contains(filename, "config.yml") {
return false
}
return true
},
mockWriteCommon: func(file, cert string) error {
return fmt.Errorf("write failed")
},
expectError: true,
},
{
name: "config file already exists",
certPath: "/tmp/test",
mockFileExists: func(filename string) bool {
if strings.Contains(filename, "config.yml") {
return true
}
return true
},
expectError: false,
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
patches := gomonkey.NewPatches()
defer patches.Reset()
patches.ApplyFunc(utils.FileExists, tt.mockFileExists)
if tt.mockMkdirAll != nil {
patches.ApplyFunc(os.MkdirAll, tt.mockMkdirAll)
}
if tt.mockWriteCommon != nil {
patches.ApplyFunc(utils.WriteCommon, tt.mockWriteCommon)
}
err := SetRegistryConfig(tt.certPath)
if tt.expectError {
assert.Error(t, err)
} else {
assert.NoError(t, err)
}
})
}
}
func TestFileExistsWithInvalidPath(t *testing.T) {
result := utils.FileExists("/invalid/path/that/does/not/exist/file.txt")
assert.False(t, result)
}
func TestWriteCommonWithSpecialCharacters(t *testing.T) {
tempDir := t.TempDir()
testFile := filepath.Join(tempDir, "special-chars.txt")
certContent := `-----BEGIN CERTIFICATE-----
MIIC...certificate content with special chars: àáâãäåæçèéêëìíîïñòóôõöøùúûüýþÿ...
-----END CERTIFICATE-----`
err := utils.WriteCommon(testFile, certContent)
assert.NoError(t, err)
}
func TestGetCertContentWithSpecialCharacters(t *testing.T) {
tempDir := t.TempDir()
certFile := filepath.Join(tempDir, serverCrtFile)
certContent := `Certificate with special characters: àáâãäåæçèéêëìíîïñòóôõöøùúûüýþÿ`
err := os.WriteFile(certFile, []byte(certContent), testFileModeReadOnly)
assert.NoError(t, err)
content, err := getCertContent(tempDir)
assert.NoError(t, err)
assert.Equal(t, certContent, content)
}
func TestSetCommonCertWithLongPaths(t *testing.T) {
tempDir := t.TempDir()
longSrcPath := filepath.Join(tempDir, "very", "long", "source", "path", "with", "many", "directories")
longDstPath := filepath.Join(tempDir, "very", "long", "destination", "path", "with", "many", "directories")
err := os.MkdirAll(longSrcPath, testFileModeExec)
assert.NoError(t, err)
srcCertFile := filepath.Join(longSrcPath, serverCrtFile)
err = os.WriteFile(srcCertFile, []byte("long path certificate content"), testFileModeReadOnly)
assert.NoError(t, err)
err = setCommonCert(longSrcPath, longDstPath)
assert.NoError(t, err)
}
func TestSetServerCertificateWithRealScript(t *testing.T) {
tempDir := t.TempDir()
scriptPath := filepath.Join(tempDir, "generate-registry-certs.sh")
err := os.WriteFile(scriptPath, []byte(certGen), testFileModeExec)
assert.NoError(t, err)
patches := gomonkey.NewPatches()
defer patches.Reset()
patches.ApplyFunc((*exec.CommandExecutor).ExecuteCommandWithCombinedOutput, func(c *exec.CommandExecutor, command string, args ...string) (string, error) {
cmdStr := strings.Join(append([]string{command}, args...), " ")
assert.Contains(t, cmdStr, "cd "+tempDir)
assert.Contains(t, cmdStr, "./generate-registry-certs.sh")
return "Script executed successfully", nil
})
err = SetServerCertificate(tempDir)
assert.NoError(t, err)
}
func TestSetRegistryConfigWithExistingConfig(t *testing.T) {
tempDir := t.TempDir()
configFile := filepath.Join(tempDir, "config.yml")
err := os.WriteFile(configFile, []byte("existing config"), testFileModeReadOnly)
assert.NoError(t, err)
patches := gomonkey.NewPatches()
defer patches.Reset()
patches.ApplyFunc(utils.WriteCommon, func(file, cert string) error {
t.Error("writeCommon should not be called when config file already exists")
return nil
})
patches.ApplyFunc(utils.FileExists, func(filename string) bool {
return filename == configFile
})
err = SetRegistryConfig(tempDir)
assert.NoError(t, err)
content, err := os.ReadFile(configFile)
assert.NoError(t, err)
assert.Equal(t, "existing config", string(content))
}
func TestWriteCommonWithLargeContent(t *testing.T) {
tempDir := t.TempDir()
testFile := filepath.Join(tempDir, "large-content.txt")
largeContent := "-----BEGIN CERTIFICATE-----\n"
for i := 0; i < 1000; i++ {
largeContent += fmt.Sprintf("Line %d: This is a line of certificate content\n", i)
}
largeContent += "-----END CERTIFICATE-----\n"
err := utils.WriteCommon(testFile, largeContent)
assert.NoError(t, err)
content, err := os.ReadFile(testFile)
assert.NoError(t, err)
assert.Equal(t, largeContent, string(content))
info, err := os.Stat(testFile)
assert.NoError(t, err)
assert.Equal(t, os.FileMode(utils.DefaultFilePermission), info.Mode())
}
func TestGetCertContentWithLargeFile(t *testing.T) {
tempDir := t.TempDir()
certFile := filepath.Join(tempDir, serverCrtFile)
largeContent := "-----BEGIN CERTIFICATE-----\n"
for i := 0; i < 1000; i++ {
largeContent += fmt.Sprintf("Line %d: This is a line of certificate content\n", i)
}
largeContent += "-----END CERTIFICATE-----\n"
err := os.WriteFile(certFile, []byte(largeContent), testFileModeReadOnly)
assert.NoError(t, err)
content, err := getCertContent(tempDir)
assert.NoError(t, err)
assert.Equal(t, largeContent, content)
}
func TestFileExistsWithSymlinks(t *testing.T) {
tempDir := t.TempDir()
targetFile := filepath.Join(tempDir, "target.txt")
err := os.WriteFile(targetFile, []byte("target content"), testFileModeReadOnly)
assert.NoError(t, err)
symlinkFile := filepath.Join(tempDir, "symlink.txt")
err = os.Symlink(targetFile, symlinkFile)
assert.NoError(t, err)
result := utils.FileExists(symlinkFile)
assert.True(t, result)
result = utils.FileExists(targetFile)
assert.True(t, result)
}
func TestFileExistsWithDirectory(t *testing.T) {
tempDir := t.TempDir()
result := utils.FileExists(tempDir)
assert.True(t, result)
subDir := filepath.Join(tempDir, "subdir")
err := os.MkdirAll(subDir, testFileModeExec)
assert.NoError(t, err)
result = utils.FileExists(subDir)
assert.True(t, result)
}
func TestFileExistsWithPermissionDenied(t *testing.T) {
assert.True(t, true)
}
func TestSetCommonCertWithEmptySrcPath(t *testing.T) {
tempDir := t.TempDir()
err := setCommonCert("", tempDir)
assert.Error(t, err)
assert.Contains(t, err.Error(), "failed to read certificate file")
}
func TestSetCommonCertWithEmptyDstPath(t *testing.T) {
tempDir := t.TempDir()
srcDir := filepath.Join(tempDir, "src")
err := os.MkdirAll(srcDir, testFileModeExec)
assert.NoError(t, err)
srcCertFile := filepath.Join(srcDir, serverCrtFile)
err = os.WriteFile(srcCertFile, []byte("source certificate content"), testFileModeReadOnly)
assert.NoError(t, err)
err = setCommonCert(srcDir, "")
assert.Error(t, err)
}