Change the way how the fdb kubernetes monitor is copying files (#11109)

* Change the way how the fdb kubernetes monitor is copying files

* Add additional tests for the copy setup
This commit is contained in:
Johannes Scheuermann 2024-03-15 14:57:43 +01:00 committed by GitHub
parent de5cc85c28
commit 3643906535
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
8 changed files with 604 additions and 55 deletions

View File

@ -1,2 +1,2 @@
fdbkubernetesmonitor
cover.out

View File

@ -23,10 +23,19 @@ import (
"fmt"
"os"
"path"
"regexp"
"github.com/go-logr/logr"
)
const (
libraryTestDirectoryEnv = "TEST_LIBRARY_DIRECTORY"
binaryTestDirectoryEnv = "TEST_BINARY_DIRECTORY"
)
// versionRegex represents the regex to parse the compact version string.
var versionRegex = regexp.MustCompile(`^(\d+)\.(\d+)`)
// copyFile copies a file into the output directory.
func copyFile(logger logr.Logger, inputPath string, outputPath string, required bool) error {
logger.Info("Copying file", "inputPath", inputPath, "outputPath", outputPath)
@ -83,8 +92,7 @@ func CopyFiles(logger logr.Logger, outputDir string, copyDetails map[string]stri
return err
}
required := requiredCopies[inputPath]
err = copyFile(logger, inputPath, outputPath, required)
err = copyFile(logger, inputPath, outputPath, requiredCopies[inputPath])
if err != nil {
return err
}
@ -92,3 +100,83 @@ func CopyFiles(logger logr.Logger, outputDir string, copyDetails map[string]stri
return nil
}
// getCompactVersion will return the compact version representation for the input version. The compact version consists
// of the major and minor version.
func getCompactVersion(version string) (string, error) {
matches := versionRegex.FindStringSubmatch(version)
if matches == nil {
return "", fmt.Errorf("could not parse FDB compact version from %s", version)
}
return matches[0], nil
}
// getBinaryDirectory returns the directory where the binaries are located. This will return `/usr/bin` if the env
// variable TEST_BINARY_DIRECTORY is unset.
func getBinaryDirectory() string {
binaryDirectory, ok := os.LookupEnv(binaryTestDirectoryEnv)
if ok {
return binaryDirectory
}
return "/usr/bin"
}
// getLibraryPath returns the library where the binaries are located. This will return `/usr/lib/fdb/multiversion` if the env
// variable TEST_LIBRARY_DIRECTORY is unset.
func getLibraryPath() string {
libraryDirectory, ok := os.LookupEnv(libraryTestDirectoryEnv)
if ok {
return libraryDirectory
}
return "/usr/lib/fdb/multiversion"
}
// getCopyDetails will generate the details for all the files that should be copied.
func getCopyDetails(inputDir string, copyPrimaryLibrary string, binaryOutputDirectory string, copyFiles []string, copyBinaries []string, copyLibraries []string, requiredCopyFiles []string, currentContainerVersion string) (map[string]string, map[string]bool, error) {
copyDetails := make(map[string]string, len(copyFiles)+len(copyBinaries))
for _, filePath := range copyFiles {
copyDetails[path.Join(inputDir, filePath)] = ""
}
if len(copyBinaries) > 0 {
if binaryOutputDirectory == "" {
compactVersion, err := getCompactVersion(currentContainerVersion)
if err != nil {
return nil, nil, err
}
binaryOutputDirectory = compactVersion
}
binaryDirectory := getBinaryDirectory()
for _, copyBinary := range copyBinaries {
copyDetails[path.Join(binaryDirectory, copyBinary)] = path.Join(binaryOutputDirectory, copyBinary)
}
}
libraryPath := getLibraryPath()
for _, library := range copyLibraries {
libraryName := fmt.Sprintf("libfdb_c_%s.so", library)
copyDetails[path.Join(libraryPath, libraryName)] = libraryName
}
if copyPrimaryLibrary != "" {
copyDetails[path.Join(libraryPath, fmt.Sprintf("libfdb_c_%s.so", copyPrimaryLibrary))] = "libfdb_c.so"
}
requiredCopyMap := make(map[string]bool, len(requiredCopyFiles))
for _, filePath := range requiredCopyFiles {
fullFilePath := path.Join(inputDir, filePath)
_, present := copyDetails[fullFilePath]
if !present {
return nil, nil, fmt.Errorf("file %s is required, but is not in the --copy-file list", filePath)
}
requiredCopyMap[fullFilePath] = true
}
return copyDetails, requiredCopyMap, nil
}

View File

@ -0,0 +1,427 @@
// copy_test.go
//
// This source file is part of the FoundationDB open source project
//
// Copyright 2023 Apple Inc. and the FoundationDB project authors
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//
package main
import (
"fmt"
"os"
"path"
. "github.com/onsi/ginkgo/v2"
. "github.com/onsi/gomega"
)
var _ = Describe("Testing the copy methods", func() {
When("getting the copy details", func() {
var copyFiles, copyBinaries, copyLibraries, requiredCopyFiles []string
var currentContainerVersion, inputDir, copyPrimaryLibrary, binaryOutputDirectory string
AfterEach(func() {
copyFiles = []string{}
copyBinaries = []string{}
copyLibraries = []string{}
requiredCopyFiles = []string{}
})
BeforeEach(func() {
currentContainerVersion = "7.1.43"
})
When("no files should be copied", func() {
It("no error should be thrown", func() {
copyDetails, requiredCopyMap, err := getCopyDetails(inputDir, copyPrimaryLibrary, binaryOutputDirectory, copyFiles, copyBinaries, copyLibraries, requiredCopyFiles, currentContainerVersion)
Expect(err).NotTo(HaveOccurred())
Expect(copyDetails).To(BeEmpty())
Expect(requiredCopyMap).To(BeEmpty())
})
})
When("the fdbserver binary should be copied", func() {
When("the binary output directory is not set", func() {
BeforeEach(func() {
copyBinaries = []string{"fdbserver"}
})
It("no error should be thrown", func() {
copyDetails, requiredCopyMap, err := getCopyDetails(inputDir, copyPrimaryLibrary, binaryOutputDirectory, copyFiles, copyBinaries, copyLibraries, requiredCopyFiles, currentContainerVersion)
Expect(err).NotTo(HaveOccurred())
Expect(copyDetails).To(HaveKeyWithValue("/usr/bin/fdbserver", "7.1/fdbserver"))
Expect(copyDetails).To(HaveLen(1))
Expect(requiredCopyMap).To(BeEmpty())
})
})
When("the binary output directory is set", func() {
BeforeEach(func() {
copyBinaries = []string{"fdbserver"}
binaryOutputDirectory = "testing"
})
AfterEach(func() {
binaryOutputDirectory = ""
})
It("no error should be thrown", func() {
copyDetails, requiredCopyMap, err := getCopyDetails(inputDir, copyPrimaryLibrary, binaryOutputDirectory, copyFiles, copyBinaries, copyLibraries, requiredCopyFiles, currentContainerVersion)
Expect(err).NotTo(HaveOccurred())
Expect(copyDetails).To(HaveKeyWithValue("/usr/bin/fdbserver", "testing/fdbserver"))
Expect(copyDetails).To(HaveLen(1))
Expect(requiredCopyMap).To(BeEmpty())
})
})
})
When("the fdbserver and fdbbackup binary should be copied", func() {
BeforeEach(func() {
copyBinaries = []string{"fdbserver", "fdbbackup"}
})
It("no error should be thrown", func() {
copyDetails, requiredCopyMap, err := getCopyDetails(inputDir, copyPrimaryLibrary, binaryOutputDirectory, copyFiles, copyBinaries, copyLibraries, requiredCopyFiles, currentContainerVersion)
Expect(err).NotTo(HaveOccurred())
Expect(copyDetails).To(
And(
HaveKeyWithValue("/usr/bin/fdbserver", "7.1/fdbserver"),
HaveKeyWithValue("/usr/bin/fdbbackup", "7.1/fdbbackup"),
),
)
Expect(copyDetails).To(HaveLen(2))
Expect(requiredCopyMap).To(BeEmpty())
})
})
When("libraries should be copied", func() {
BeforeEach(func() {
copyLibraries = []string{"7.1.43", "7.3.27"}
})
It("no error should be thrown", func() {
copyDetails, requiredCopyMap, err := getCopyDetails(inputDir, copyPrimaryLibrary, binaryOutputDirectory, copyFiles, copyBinaries, copyLibraries, requiredCopyFiles, currentContainerVersion)
Expect(err).NotTo(HaveOccurred())
Expect(copyDetails).To(
And(
HaveKeyWithValue("/usr/lib/fdb/multiversion/libfdb_c_7.1.43.so", "libfdb_c_7.1.43.so"),
HaveKeyWithValue("/usr/lib/fdb/multiversion/libfdb_c_7.3.27.so", "libfdb_c_7.3.27.so"),
),
)
Expect(copyDetails).To(HaveLen(2))
Expect(requiredCopyMap).To(BeEmpty())
})
})
When("the fdbserver and fdbbackup binary should be copied", func() {
BeforeEach(func() {
copyBinaries = []string{"fdbserver", "fdbbackup"}
})
It("no error should be thrown", func() {
copyDetails, requiredCopyMap, err := getCopyDetails(inputDir, copyPrimaryLibrary, binaryOutputDirectory, copyFiles, copyBinaries, copyLibraries, requiredCopyFiles, currentContainerVersion)
Expect(err).NotTo(HaveOccurred())
Expect(copyDetails).To(
And(
HaveKeyWithValue("/usr/bin/fdbserver", "7.1/fdbserver"),
HaveKeyWithValue("/usr/bin/fdbbackup", "7.1/fdbbackup"),
),
)
Expect(copyDetails).To(HaveLen(2))
Expect(requiredCopyMap).To(BeEmpty())
})
})
When("libraries and binaries should be copied", func() {
BeforeEach(func() {
copyLibraries = []string{"7.1.43", "7.3.27"}
copyBinaries = []string{"fdbserver", "fdbbackup"}
})
It("no error should be thrown", func() {
copyDetails, requiredCopyMap, err := getCopyDetails(inputDir, copyPrimaryLibrary, binaryOutputDirectory, copyFiles, copyBinaries, copyLibraries, requiredCopyFiles, currentContainerVersion)
Expect(err).NotTo(HaveOccurred())
Expect(copyDetails).To(
And(
HaveKeyWithValue("/usr/bin/fdbserver", "7.1/fdbserver"),
HaveKeyWithValue("/usr/bin/fdbbackup", "7.1/fdbbackup"),
HaveKeyWithValue("/usr/lib/fdb/multiversion/libfdb_c_7.1.43.so", "libfdb_c_7.1.43.so"),
HaveKeyWithValue("/usr/lib/fdb/multiversion/libfdb_c_7.3.27.so", "libfdb_c_7.3.27.so"),
),
)
Expect(copyDetails).To(HaveLen(4))
Expect(requiredCopyMap).To(BeEmpty())
})
})
When("files should be copied", func() {
BeforeEach(func() {
copyFiles = []string{"testFile"}
})
When("no input directory is set", func() {
It("no error should be thrown", func() {
copyDetails, requiredCopyMap, err := getCopyDetails(inputDir, copyPrimaryLibrary, binaryOutputDirectory, copyFiles, copyBinaries, copyLibraries, requiredCopyFiles, currentContainerVersion)
Expect(err).NotTo(HaveOccurred())
Expect(copyDetails).To(
And(
HaveKeyWithValue("testFile", ""),
),
)
Expect(copyDetails).To(HaveLen(1))
Expect(requiredCopyMap).To(BeEmpty())
})
})
When("the input directory is set", func() {
BeforeEach(func() {
inputDir = "/testing"
})
AfterEach(func() {
inputDir = ""
})
It("no error should be thrown", func() {
copyDetails, requiredCopyMap, err := getCopyDetails(inputDir, copyPrimaryLibrary, binaryOutputDirectory, copyFiles, copyBinaries, copyLibraries, requiredCopyFiles, currentContainerVersion)
Expect(err).NotTo(HaveOccurred())
Expect(copyDetails).To(
And(
HaveKeyWithValue("/testing/testFile", ""),
),
)
Expect(copyDetails).To(HaveLen(1))
Expect(requiredCopyMap).To(BeEmpty())
})
})
})
When("the primary fdb library should be copied", func() {
BeforeEach(func() {
copyPrimaryLibrary = "7.1.43"
})
AfterEach(func() {
copyPrimaryLibrary = ""
})
It("no error should be thrown", func() {
copyDetails, requiredCopyMap, err := getCopyDetails(inputDir, copyPrimaryLibrary, binaryOutputDirectory, copyFiles, copyBinaries, copyLibraries, requiredCopyFiles, currentContainerVersion)
Expect(err).NotTo(HaveOccurred())
Expect(copyDetails).To(
And(
HaveKeyWithValue("/usr/lib/fdb/multiversion/libfdb_c_7.1.43.so", "libfdb_c.so"),
),
)
Expect(copyDetails).To(HaveLen(1))
Expect(requiredCopyMap).To(BeEmpty())
})
})
When("some files are required not to be empty", func() {
BeforeEach(func() {
requiredCopyFiles = []string{"testFile"}
copyBinaries = []string{"fdbserver"}
inputDir = "/testing"
})
AfterEach(func() {
inputDir = ""
})
When("a file is present in the require not empty list but should not be copied", func() {
BeforeEach(func() {
copyFiles = nil
})
It("should throw an error", func() {
copyDetails, requiredCopyMap, err := getCopyDetails(inputDir, copyPrimaryLibrary, binaryOutputDirectory, copyFiles, copyBinaries, copyLibraries, requiredCopyFiles, currentContainerVersion)
Expect(err).To(HaveOccurred())
Expect(copyDetails).To(BeEmpty())
Expect(requiredCopyMap).To(BeEmpty())
})
})
When("all files are present", func() {
BeforeEach(func() {
copyFiles = requiredCopyFiles
})
It("should not throw an error and include all files", func() {
copyDetails, requiredCopyMap, err := getCopyDetails(inputDir, copyPrimaryLibrary, binaryOutputDirectory, copyFiles, copyBinaries, copyLibraries, requiredCopyFiles, currentContainerVersion)
Expect(err).NotTo(HaveOccurred())
Expect(copyDetails).To(
And(
HaveKeyWithValue("/usr/bin/fdbserver", "7.1/fdbserver"),
HaveKeyWithValue("/testing/testFile", ""),
),
)
Expect(copyDetails).To(HaveLen(2))
Expect(requiredCopyMap).To(HaveLen(1))
Expect(requiredCopyMap).To(HaveKeyWithValue("/testing/testFile", true))
})
})
})
})
When("copying the binaries from the input directory to the output directory", func() {
var inputBinaryDir, outputBinaryDir string
binaries := []string{"fdbserver", "fdbbackup", "fdbrestore"}
BeforeEach(func() {
inputBinaryDir = GinkgoT().TempDir()
outputBinaryDir = GinkgoT().TempDir()
for _, binary := range binaries {
_, err := os.Create(path.Join(inputBinaryDir, binary))
Expect(err).NotTo(HaveOccurred())
}
})
When("copying the binaries", func() {
var copyDetails map[string]string
BeforeEach(func() {
// Simulate the binary directory
GinkgoT().Setenv(binaryTestDirectoryEnv, inputBinaryDir)
var err error
copyDetails, _, err = getCopyDetails("", "", "", nil, binaries, nil, nil, "7.1.43")
Expect(err).NotTo(HaveOccurred())
Expect(copyDetails).To(HaveLen(3))
Expect(CopyFiles(GinkgoLogr, outputBinaryDir, copyDetails, map[string]bool{})).NotTo(HaveOccurred())
})
It("should copy all the files", func() {
Expect(path.Join(outputBinaryDir, "7.1", "fdbserver")).Should(BeAnExistingFile())
Expect(path.Join(outputBinaryDir, "7.1", "fdbrestore")).Should(BeAnExistingFile())
Expect(path.Join(outputBinaryDir, "7.1", "fdbbackup")).Should(BeAnExistingFile())
})
})
})
When("copying the libraries from the input directory to the output directory", func() {
var inputLibraryDir, outputLibraryDir string
libraries := []string{"7.1", "7.3", "6.3"}
BeforeEach(func() {
inputLibraryDir = GinkgoT().TempDir()
outputLibraryDir = GinkgoT().TempDir()
for _, library := range libraries {
_, err := os.Create(path.Join(inputLibraryDir, fmt.Sprintf("libfdb_c_%s.so", library)))
Expect(err).NotTo(HaveOccurred())
}
// Simulate the binary directory
GinkgoT().Setenv(libraryTestDirectoryEnv, inputLibraryDir)
})
When("copying the libraries without a primary library", func() {
var copyDetails map[string]string
BeforeEach(func() {
var err error
copyDetails, _, err = getCopyDetails("", "", "", nil, nil, libraries, nil, "7.1.43")
Expect(err).NotTo(HaveOccurred())
Expect(copyDetails).To(HaveLen(3))
Expect(CopyFiles(GinkgoLogr, outputLibraryDir, copyDetails, map[string]bool{})).NotTo(HaveOccurred())
})
It("should copy all the files", func() {
Expect(path.Join(outputLibraryDir, "libfdb_c_7.1.so")).Should(BeAnExistingFile())
Expect(path.Join(outputLibraryDir, "libfdb_c_6.3.so")).Should(BeAnExistingFile())
Expect(path.Join(outputLibraryDir, "libfdb_c_7.3.so")).Should(BeAnExistingFile())
})
})
When("copying the libraries with a primary library", func() {
var copyDetails map[string]string
BeforeEach(func() {
var err error
copyDetails, _, err = getCopyDetails("", "7.1", "", nil, nil, libraries, nil, "7.1.43")
Expect(err).NotTo(HaveOccurred())
Expect(copyDetails).To(HaveLen(3))
Expect(CopyFiles(GinkgoLogr, outputLibraryDir, copyDetails, map[string]bool{})).NotTo(HaveOccurred())
})
It("should copy all the files", func() {
Expect(path.Join(outputLibraryDir, "libfdb_c.so")).Should(BeAnExistingFile())
Expect(path.Join(outputLibraryDir, "libfdb_c_6.3.so")).Should(BeAnExistingFile())
Expect(path.Join(outputLibraryDir, "libfdb_c_7.3.so")).Should(BeAnExistingFile())
})
})
When("copying the binaries from the input directory to the output directory", func() {
var testInputDir, testOutputDir string
BeforeEach(func() {
testInputDir = GinkgoT().TempDir()
testOutputDir = GinkgoT().TempDir()
_, err := os.Create(path.Join(testInputDir, "testfile"))
Expect(err).NotTo(HaveOccurred())
})
When("copying the file", func() {
var copyDetails map[string]string
BeforeEach(func() {
var err error
copyDetails, _, err = getCopyDetails(testInputDir, "", "", []string{"testfile"}, nil, nil, nil, "7.1.43")
Expect(err).NotTo(HaveOccurred())
Expect(copyDetails).To(HaveLen(1))
Expect(CopyFiles(GinkgoLogr, testOutputDir, copyDetails, map[string]bool{})).NotTo(HaveOccurred())
})
It("should copy the file", func() {
Expect(path.Join(testOutputDir, "testfile")).Should(BeAnExistingFile())
})
})
When("the file is required to not be empty", func() {
var copyDetails map[string]string
var requiredFiles map[string]bool
BeforeEach(func() {
var err error
copyDetails, requiredFiles, err = getCopyDetails(testInputDir, "", "", []string{"testfile"}, nil, nil, []string{"testfile"}, "7.1.43")
Expect(err).NotTo(HaveOccurred())
Expect(copyDetails).To(HaveLen(1))
})
When("the file is empty", func() {
It("should not copy the file", func() {
Expect(CopyFiles(GinkgoLogr, testOutputDir, copyDetails, requiredFiles)).To(HaveOccurred())
Expect(path.Join(testOutputDir, "testfile")).NotTo(BeAnExistingFile())
})
})
When("the file is not empty", func() {
BeforeEach(func() {
Expect(os.WriteFile(path.Join(testInputDir, "testfile"), []byte("Hello World"), 0644)).NotTo(HaveOccurred())
})
It("should copy the file", func() {
Expect(CopyFiles(GinkgoLogr, testOutputDir, copyDetails, requiredFiles)).NotTo(HaveOccurred())
Expect(path.Join(testOutputDir, "testfile")).To(BeAnExistingFile())
})
})
})
})
})
})

View File

@ -25,6 +25,8 @@ require (
github.com/fsnotify/fsnotify v1.6.0
github.com/go-logr/logr v1.2.4
github.com/go-logr/zapr v1.2.4
github.com/onsi/ginkgo/v2 v2.9.7
github.com/onsi/gomega v1.27.8
github.com/prometheus/client_golang v1.16.0
github.com/spf13/pflag v1.0.5
go.uber.org/zap v1.25.0
@ -45,11 +47,13 @@ require (
github.com/go-openapi/jsonpointer v0.19.5 // indirect
github.com/go-openapi/jsonreference v0.20.0 // indirect
github.com/go-openapi/swag v0.19.14 // indirect
github.com/go-task/slim-sprig v0.0.0-20230315185526-52ccab3ef572 // indirect
github.com/gogo/protobuf v1.3.2 // indirect
github.com/golang/protobuf v1.5.3 // indirect
github.com/google/gnostic v0.5.7-v3refs // indirect
github.com/google/go-cmp v0.5.9 // indirect
github.com/google/gofuzz v1.1.0 // indirect
github.com/google/pprof v0.0.0-20210407192527-94a9f03dee38 // indirect
github.com/josharian/intern v1.0.0 // indirect
github.com/json-iterator/go v1.1.12 // indirect
github.com/mailru/easyjson v0.7.6 // indirect
@ -69,6 +73,7 @@ require (
golang.org/x/term v0.13.0 // indirect
golang.org/x/text v0.13.0 // indirect
golang.org/x/time v0.3.0 // indirect
golang.org/x/tools v0.9.1 // indirect
google.golang.org/appengine v1.6.7 // indirect
google.golang.org/protobuf v1.33.0 // indirect
gopkg.in/inf.v0 v0.9.1 // indirect

View File

@ -7,6 +7,9 @@ github.com/beorn7/perks v1.0.1/go.mod h1:G2ZrVWU2WbWT9wwq4/hrbKbnv/1ERSJQ0ibhJ6r
github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU=
github.com/cespare/xxhash/v2 v2.2.0 h1:DC2CZ1Ep5Y4k3ZQ899DldepgrayRUGE6BBZ/cd9Cj44=
github.com/cespare/xxhash/v2 v2.2.0/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs=
github.com/chzyer/logex v1.1.10/go.mod h1:+Ywpsq7O8HXn0nuIou7OrIPyXbp3wmkHB+jjWRnGsAI=
github.com/chzyer/readline v0.0.0-20180603132655-2972be24d48e/go.mod h1:nSuG5e5PlCu98SY8svDHJxuZscDgtXS6KTTbou5AhLI=
github.com/chzyer/test v0.0.0-20180213035817-a1ea475d72b1/go.mod h1:Q3SI9o4m/ZMnBNeIyt5eFwwo7qiLfzFZmjNmxjkiQlU=
github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw=
github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E=
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
@ -34,6 +37,8 @@ github.com/go-openapi/jsonreference v0.20.0/go.mod h1:Ag74Ico3lPc+zR+qjn4XBUmXym
github.com/go-openapi/swag v0.19.5/go.mod h1:POnQmlKehdgb5mhVOsnJFsivZCEZ/vjK9gh66Z9tfKk=
github.com/go-openapi/swag v0.19.14 h1:gm3vOOXfiuw5i9p5N9xJvfjvuofpyvLA9Wr6QfK5Fng=
github.com/go-openapi/swag v0.19.14/go.mod h1:QYRuS/SOXUCsnplDa677K7+DxSOj6IPNl/eQntq43wQ=
github.com/go-task/slim-sprig v0.0.0-20230315185526-52ccab3ef572 h1:tfuBGBXKqDEevZMzYi5KSi8KkcZtzBcTgAUUtapy0OI=
github.com/go-task/slim-sprig v0.0.0-20230315185526-52ccab3ef572/go.mod h1:9Pwr4B2jHnOSGXyyzV8ROjYa2ojvAY6HCGYYfMoC3Ls=
github.com/gogo/protobuf v1.3.2 h1:Ov1cvc58UF3b5XjBnZv7+opcTcQFZebYjWzi34vdm4Q=
github.com/gogo/protobuf v1.3.2/go.mod h1:P1XiOD3dCwIKUDQYPy72D8LYyHL2YPYrpS2s69NZV8Q=
github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q=
@ -65,7 +70,10 @@ github.com/google/go-cmp v0.5.9/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeN
github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg=
github.com/google/gofuzz v1.1.0 h1:Hsa8mG0dQ46ij8Sl2AYJDUv1oA9/d6Vk+3LG99Oe02g=
github.com/google/gofuzz v1.1.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg=
github.com/google/pprof v0.0.0-20210407192527-94a9f03dee38 h1:yAJXTCF9TqKcTiHJAE8dj7HMvPfh66eeA2JYW7eFpSE=
github.com/google/pprof v0.0.0-20210407192527-94a9f03dee38/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE=
github.com/google/uuid v1.1.2 h1:EVhdT+1Kseyi1/pUmXKaFxYsDNy9RQYkMWRH68J/W7Y=
github.com/ianlancetaylor/demangle v0.0.0-20200824232613-28f6c0f3b639/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc=
github.com/imdario/mergo v0.3.6 h1:xTNEAn+kxVO7dTZGu0CegyqKZmoWFI0rF8UxjlB2d28=
github.com/jessevdk/go-flags v1.4.0/go.mod h1:4FA24M0QyGHXBuZZK/XkWh8h0e1EYbRYJSGM75WSRxI=
github.com/josharian/intern v1.0.0 h1:vlS4z54oSdjm0bgjRigI+G1HpF+tI+9rE5LLzOg8HmY=
@ -95,8 +103,10 @@ github.com/modern-go/reflect2 v1.0.2/go.mod h1:yWuevngMOJpCy52FWWMvUC8ws7m/LJsjY
github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 h1:C3w9PqII01/Oq1c1nUAm88MOHcQC9l5mIlSMApZMrHA=
github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822/go.mod h1:+n7T8mK8HuQTcFwEeznm/DIxMOiR9yIdICNftLE1DvQ=
github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e/go.mod h1:zD1mROLANZcx1PVRCS0qkT7pwLkGfwJo4zjcN/Tysno=
github.com/onsi/ginkgo/v2 v2.6.0 h1:9t9b9vRUbFq3C4qKFCGkVuq/fIHji802N1nrtkh1mNc=
github.com/onsi/gomega v1.24.1 h1:KORJXNNTzJXzu4ScJWssJfJMnJ+2QJqhoQSRwNlze9E=
github.com/onsi/ginkgo/v2 v2.9.7 h1:06xGQy5www2oN160RtEZoTvnP2sPhEfePYmCDc2szss=
github.com/onsi/ginkgo/v2 v2.9.7/go.mod h1:cxrmXWykAwTwhQsJOPfdIDiJ+l2RYq7U8hFU+M/1uw0=
github.com/onsi/gomega v1.27.8 h1:gegWiwZjBsf2DgiSbf5hpokZ98JVDMcWkUiigk6/KXc=
github.com/onsi/gomega v1.27.8/go.mod h1:2J8vzI/s+2shY9XHRApDkdgPo1TKT7P2u6fXeJKFnNQ=
github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4=
github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
@ -148,6 +158,7 @@ golang.org/x/lint v0.0.0-20190930215403-16217165b5de/go.mod h1:6SW0HCj/g11FgYtHl
golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
golang.org/x/mod v0.4.2/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
golang.org/x/mod v0.10.0 h1:lFO9qtOdlre5W1jxS3r/4szv2/6iXxScdzjoBMXNhYk=
golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20190213061140-3a22650c66bd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
@ -173,6 +184,7 @@ golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJ
golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20191204072324-ce4227a45e2e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210330210617-4fbd30eecc44/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
@ -199,6 +211,8 @@ golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtn
golang.org/x/tools v0.0.0-20200619180055-7c47624df98f/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE=
golang.org/x/tools v0.0.0-20210106214847-113979e3529a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA=
golang.org/x/tools v0.1.5/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk=
golang.org/x/tools v0.9.1 h1:8WMNJAz3zrtPmnYC7ISf5dEn3MT0gY7jBJfw27yrrLo=
golang.org/x/tools v0.9.1/go.mod h1:owI94Op576fPu3cIGQeHs3joujW/2Oc6MtlxbF5dfNc=
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=

View File

@ -25,7 +25,6 @@ import (
"fmt"
"io"
"os"
"path"
"regexp"
"strings"
@ -88,6 +87,9 @@ func initLogger(logPath string) *zap.Logger {
}
func main() {
var copyFiles, copyBinaries, copyLibraries, requiredCopyFiles []string
var inputDir, copyPrimaryLibrary, binaryOutputDirectory string
pflag.StringVar(&executionModeString, "mode", "launcher", "Execution mode. Valid options are launcher, sidecar, and init")
pflag.StringVar(&fdbserverPath, "fdbserver-path", "/usr/bin/fdbserver", "Path to the fdbserver binary")
pflag.StringVar(&inputDir, "input-dir", ".", "Directory containing input files")
@ -111,17 +113,17 @@ func main() {
logger := zapr.NewLogger(initLogger(logPath))
copyDetails, requiredCopies, err := getCopyDetails()
if err != nil {
logger.Error(err, "Error getting list of files to copy")
os.Exit(1)
}
versionBytes, err := os.ReadFile(versionFilePath)
if err != nil {
panic(err)
}
currentContainerVersion = strings.TrimSpace(string(versionBytes))
currentContainerVersion := strings.TrimSpace(string(versionBytes))
copyDetails, requiredCopies, err := getCopyDetails(inputDir, copyPrimaryLibrary, binaryOutputDirectory, copyFiles, copyBinaries, copyLibraries, requiredCopyFiles, currentContainerVersion)
if err != nil {
logger.Error(err, "Error getting list of files to copy")
os.Exit(1)
}
mode := executionMode(executionModeString)
switch mode {
@ -131,7 +133,7 @@ func main() {
logger.Error(err, "Error loading additional environment")
os.Exit(1)
}
StartMonitor(context.Background(), logger, fmt.Sprintf("%s/%s", inputDir, monitorConfFile), customEnvironment, processCount, listenAddress, enablePprof)
StartMonitor(context.Background(), logger, fmt.Sprintf("%s/%s", inputDir, monitorConfFile), customEnvironment, processCount, listenAddress, enablePprof, currentContainerVersion)
case executionModeInit:
err = CopyFiles(logger, outputDir, copyDetails, requiredCopies)
if err != nil {
@ -155,39 +157,6 @@ func main() {
}
}
func getCopyDetails() (map[string]string, map[string]bool, error) {
copyDetails := make(map[string]string, len(copyFiles)+len(copyBinaries))
for _, filePath := range copyFiles {
copyDetails[path.Join(inputDir, filePath)] = ""
}
if copyBinaries != nil {
if binaryOutputDirectory == "" {
binaryOutputDirectory = currentContainerVersion
}
for _, copyBinary := range copyBinaries {
copyDetails[fmt.Sprintf("/usr/bin/%s", copyBinary)] = path.Join("bin", binaryOutputDirectory, copyBinary)
}
}
for _, library := range copyLibraries {
copyDetails[fmt.Sprintf("/usr/lib/fdb/multiversion/libfdb_c_%s.so", library)] = path.Join("lib", "multiversion", fmt.Sprintf("libfdb_c_%s.so", library))
}
if copyPrimaryLibrary != "" {
copyDetails[fmt.Sprintf("/usr/lib/fdb/multiversion/libfdb_c_%s.so", copyPrimaryLibrary)] = path.Join("lib", "libfdb_c.so")
}
requiredCopyMap := make(map[string]bool, len(requiredCopyFiles))
for _, filePath := range requiredCopyFiles {
fullFilePath := path.Join(inputDir, filePath)
_, present := copyDetails[fullFilePath]
if !present {
return nil, nil, fmt.Errorf("file %s is required, but is not in the --copy-file list", filePath)
}
requiredCopyMap[fullFilePath] = true
}
return copyDetails, requiredCopyMap, nil
}
func loadAdditionalEnvironment(logger logr.Logger) (map[string]string, error) {
var customEnvironment = make(map[string]string)
if additionalEnvFile != "" {
@ -197,7 +166,12 @@ func loadAdditionalEnvironment(logger logr.Logger) (map[string]string, error) {
if err != nil {
return nil, err
}
defer file.Close()
defer func() {
err := file.Close()
if err != nil {
logger.Error(err, "error when closing file")
}
}()
envScanner := bufio.NewScanner(file)
for envScanner.Scan() {

View File

@ -54,6 +54,9 @@ type Monitor struct {
// ConfigFile defines the path to the config file to load.
ConfigFile string
// CurrentContainerVersion defines the version of the container. This will be the same as the fdbserver version.
CurrentContainerVersion string
// CustomEnvironment defines the custom environment variables to use when
// interpreting the monitor configuration.
CustomEnvironment map[string]string
@ -92,7 +95,7 @@ type Monitor struct {
}
// StartMonitor starts the monitor loop.
func StartMonitor(ctx context.Context, logger logr.Logger, configFile string, customEnvironment map[string]string, processCount int, listenAddr string, enableDebug bool) {
func StartMonitor(ctx context.Context, logger logr.Logger, configFile string, customEnvironment map[string]string, processCount int, listenAddr string, enableDebug bool, currentContainerVersion string) {
podClient, err := CreatePodClient(ctx, logger)
if err != nil {
logger.Error(err, "could not create Pod client")
@ -100,11 +103,12 @@ func StartMonitor(ctx context.Context, logger logr.Logger, configFile string, cu
}
monitor := &Monitor{
ConfigFile: configFile,
PodClient: podClient,
Logger: logger,
CustomEnvironment: customEnvironment,
ProcessCount: processCount,
ConfigFile: configFile,
PodClient: podClient,
Logger: logger,
CustomEnvironment: customEnvironment,
ProcessCount: processCount,
CurrentContainerVersion: currentContainerVersion,
}
go func() { monitor.WatchPodTimestamps() }()
@ -157,7 +161,7 @@ func (monitor *Monitor) LoadConfiguration() {
return
}
if currentContainerVersion == configuration.Version {
if monitor.CurrentContainerVersion == configuration.Version {
configuration.BinaryPath = fdbserverPath
} else {
configuration.BinaryPath = path.Join(sharedBinaryDir, configuration.Version, "fdbserver")

View File

@ -0,0 +1,37 @@
/*
* suite_test.go
*
* This source file is part of the FoundationDB open source project
*
* Copyright 2023 Apple Inc. and the FoundationDB project authors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package main
import (
"testing"
"time"
. "github.com/onsi/ginkgo/v2"
. "github.com/onsi/gomega"
)
// These tests use Ginkgo (BDD-style Go testing framework). Refer to
// http://onsi.github.io/ginkgo/ to learn more about Ginkgo.
func TestAPIs(t *testing.T) {
RegisterFailHandler(Fail)
SetDefaultEventuallyTimeout(10 * time.Second)
RunSpecs(t, "FDB Kubernetes Monitor")
}