mirror of
https://github.com/ceph/ceph-csi.git
synced 2025-06-14 18:53:35 +00:00
vendor update for CSI 0.3.0
This commit is contained in:
2
vendor/k8s.io/kubernetes/pkg/kubelet/kubeletconfig/util/codec/BUILD
generated
vendored
2
vendor/k8s.io/kubernetes/pkg/kubelet/kubeletconfig/util/codec/BUILD
generated
vendored
@ -13,7 +13,9 @@ go_library(
|
||||
"//pkg/api/legacyscheme:go_default_library",
|
||||
"//pkg/apis/core/install:go_default_library",
|
||||
"//pkg/kubelet/apis/kubeletconfig:go_default_library",
|
||||
"//pkg/kubelet/apis/kubeletconfig/scheme:go_default_library",
|
||||
"//vendor/k8s.io/apimachinery/pkg/runtime:go_default_library",
|
||||
"//vendor/k8s.io/apimachinery/pkg/runtime/schema:go_default_library",
|
||||
"//vendor/k8s.io/apimachinery/pkg/runtime/serializer:go_default_library",
|
||||
],
|
||||
)
|
||||
|
40
vendor/k8s.io/kubernetes/pkg/kubelet/kubeletconfig/util/codec/codec.go
generated
vendored
40
vendor/k8s.io/kubernetes/pkg/kubelet/kubeletconfig/util/codec/codec.go
generated
vendored
@ -23,23 +23,51 @@ import (
|
||||
_ "k8s.io/kubernetes/pkg/apis/core/install"
|
||||
|
||||
"k8s.io/apimachinery/pkg/runtime"
|
||||
"k8s.io/apimachinery/pkg/runtime/schema"
|
||||
"k8s.io/apimachinery/pkg/runtime/serializer"
|
||||
"k8s.io/kubernetes/pkg/api/legacyscheme"
|
||||
"k8s.io/kubernetes/pkg/kubelet/apis/kubeletconfig"
|
||||
"k8s.io/kubernetes/pkg/kubelet/apis/kubeletconfig/scheme"
|
||||
)
|
||||
|
||||
// TODO(mtaufen): allow an encoder to be injected into checkpoint objects at creation time? (then we could ultimately instantiate only one encoder)
|
||||
// EncodeKubeletConfig encodes an internal KubeletConfiguration to an external YAML representation
|
||||
func EncodeKubeletConfig(internal *kubeletconfig.KubeletConfiguration, targetVersion schema.GroupVersion) ([]byte, error) {
|
||||
encoder, err := NewKubeletconfigYAMLEncoder(targetVersion)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
// encoder will convert to external version
|
||||
data, err := runtime.Encode(encoder, internal)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return data, nil
|
||||
}
|
||||
|
||||
// NewJSONEncoder generates a new runtime.Encoder that encodes objects to JSON
|
||||
func NewJSONEncoder(groupName string) (runtime.Encoder, error) {
|
||||
// encode to json
|
||||
mediaType := "application/json"
|
||||
// NewKubeletconfigYAMLEncoder returns an encoder that can write objects in the kubeletconfig API group to YAML
|
||||
func NewKubeletconfigYAMLEncoder(targetVersion schema.GroupVersion) (runtime.Encoder, error) {
|
||||
_, codecs, err := scheme.NewSchemeAndCodecs()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
mediaType := "application/yaml"
|
||||
info, ok := runtime.SerializerInfoForMediaType(codecs.SupportedMediaTypes(), mediaType)
|
||||
if !ok {
|
||||
return nil, fmt.Errorf("unsupported media type %q", mediaType)
|
||||
}
|
||||
return codecs.EncoderForVersion(info.Serializer, targetVersion), nil
|
||||
}
|
||||
|
||||
// NewYAMLEncoder generates a new runtime.Encoder that encodes objects to YAML
|
||||
func NewYAMLEncoder(groupName string) (runtime.Encoder, error) {
|
||||
// encode to YAML
|
||||
mediaType := "application/yaml"
|
||||
info, ok := runtime.SerializerInfoForMediaType(legacyscheme.Codecs.SupportedMediaTypes(), mediaType)
|
||||
if !ok {
|
||||
return nil, fmt.Errorf("unsupported media type %q", mediaType)
|
||||
}
|
||||
|
||||
versions := legacyscheme.Registry.EnabledVersionsForGroup(groupName)
|
||||
versions := legacyscheme.Scheme.PrioritizedVersionsForGroup(groupName)
|
||||
if len(versions) == 0 {
|
||||
return nil, fmt.Errorf("no enabled versions for group %q", groupName)
|
||||
}
|
||||
|
27
vendor/k8s.io/kubernetes/pkg/kubelet/kubeletconfig/util/equal/equal.go
generated
vendored
27
vendor/k8s.io/kubernetes/pkg/kubelet/kubeletconfig/util/equal/equal.go
generated
vendored
@ -18,33 +18,6 @@ package equal
|
||||
|
||||
import apiv1 "k8s.io/api/core/v1"
|
||||
|
||||
// ConfigSourceEq returns true if the two config sources are semantically equivalent in the context of dynamic config
|
||||
func ConfigSourceEq(a, b *apiv1.NodeConfigSource) bool {
|
||||
if a == b {
|
||||
return true
|
||||
} else if a == nil || b == nil {
|
||||
// not equal, and one is nil
|
||||
return false
|
||||
}
|
||||
// check equality of config source subifelds
|
||||
if a.ConfigMapRef != b.ConfigMapRef {
|
||||
return ObjectRefEq(a.ConfigMapRef, b.ConfigMapRef)
|
||||
}
|
||||
// all internal subfields of the config source are equal
|
||||
return true
|
||||
}
|
||||
|
||||
// ObjectRefEq returns true if the two object references are semantically equivalent in the context of dynamic config
|
||||
func ObjectRefEq(a, b *apiv1.ObjectReference) bool {
|
||||
if a == b {
|
||||
return true
|
||||
} else if a == nil || b == nil {
|
||||
// not equal, and one is nil
|
||||
return false
|
||||
}
|
||||
return a.UID == b.UID && a.Namespace == b.Namespace && a.Name == b.Name
|
||||
}
|
||||
|
||||
// KubeletConfigOkEq returns true if the two conditions are semantically equivalent in the context of dynamic config
|
||||
func KubeletConfigOkEq(a, b *apiv1.NodeCondition) bool {
|
||||
return a.Message == b.Message && a.Reason == b.Reason && a.Status == b.Status
|
||||
|
11
vendor/k8s.io/kubernetes/pkg/kubelet/kubeletconfig/util/files/BUILD
generated
vendored
11
vendor/k8s.io/kubernetes/pkg/kubelet/kubeletconfig/util/files/BUILD
generated
vendored
@ -3,6 +3,7 @@ package(default_visibility = ["//visibility:public"])
|
||||
load(
|
||||
"@io_bazel_rules_go//go:def.bzl",
|
||||
"go_library",
|
||||
"go_test",
|
||||
)
|
||||
|
||||
go_library(
|
||||
@ -24,3 +25,13 @@ filegroup(
|
||||
srcs = [":package-srcs"],
|
||||
tags = ["automanaged"],
|
||||
)
|
||||
|
||||
go_test(
|
||||
name = "go_default_test",
|
||||
srcs = ["files_test.go"],
|
||||
embed = [":go_default_library"],
|
||||
deps = [
|
||||
"//pkg/kubelet/kubeletconfig/util/test:go_default_library",
|
||||
"//pkg/util/filesystem:go_default_library",
|
||||
],
|
||||
)
|
||||
|
100
vendor/k8s.io/kubernetes/pkg/kubelet/kubeletconfig/util/files/files.go
generated
vendored
100
vendor/k8s.io/kubernetes/pkg/kubelet/kubeletconfig/util/files/files.go
generated
vendored
@ -24,7 +24,10 @@ import (
|
||||
utilfs "k8s.io/kubernetes/pkg/util/filesystem"
|
||||
)
|
||||
|
||||
const defaultPerm = 0666
|
||||
const (
|
||||
defaultPerm = 0755
|
||||
tmptag = "tmp_" // additional prefix to prevent accidental collisions
|
||||
)
|
||||
|
||||
// FileExists returns true if a regular file exists at `path`, false if `path` does not exist, otherwise an error
|
||||
func FileExists(fs utilfs.Filesystem, path string) (bool, error) {
|
||||
@ -64,9 +67,10 @@ func EnsureFile(fs utilfs.Filesystem, path string) error {
|
||||
}
|
||||
|
||||
// WriteTmpFile creates a temporary file at `path`, writes `data` into it, and fsyncs the file
|
||||
// Expects the parent directory to exist.
|
||||
func WriteTmpFile(fs utilfs.Filesystem, path string, data []byte) (tmpPath string, retErr error) {
|
||||
dir := filepath.Dir(path)
|
||||
prefix := filepath.Base(path)
|
||||
prefix := tmptag + filepath.Base(path)
|
||||
|
||||
// create the tmp file
|
||||
tmpFile, err := fs.TempFile(dir, prefix)
|
||||
@ -81,7 +85,7 @@ func WriteTmpFile(fs utilfs.Filesystem, path string, data []byte) (tmpPath strin
|
||||
// if there was an error writing, syncing, or closing, delete the temporary file and return the error
|
||||
if retErr != nil {
|
||||
if err := fs.Remove(tmpPath); err != nil {
|
||||
retErr = fmt.Errorf("attempted to remove temporary file %q after error %v, but failed due to error: %v", path, retErr, err)
|
||||
retErr = fmt.Errorf("attempted to remove temporary file %q after error %v, but failed due to error: %v", tmpPath, retErr, err)
|
||||
}
|
||||
tmpPath = ""
|
||||
}
|
||||
@ -100,7 +104,8 @@ func WriteTmpFile(fs utilfs.Filesystem, path string, data []byte) (tmpPath strin
|
||||
}
|
||||
|
||||
// ReplaceFile replaces the contents of the file at `path` with `data` by writing to a tmp file in the same
|
||||
// dir as `path` and renaming the tmp file over `path`. The file does not have to exist to use ReplaceFile.
|
||||
// dir as `path` and renaming the tmp file over `path`. The file does not have to exist to use ReplaceFile,
|
||||
// but the parent directory must exist.
|
||||
// Note ReplaceFile calls fsync.
|
||||
func ReplaceFile(fs utilfs.Filesystem, path string, data []byte) error {
|
||||
// write data to a temporary file
|
||||
@ -118,7 +123,7 @@ func DirExists(fs utilfs.Filesystem, path string) (bool, error) {
|
||||
if info.IsDir() {
|
||||
return true, nil
|
||||
}
|
||||
return false, fmt.Errorf("expected dir at %q, but mode is is %q", path, info.Mode().String())
|
||||
return false, fmt.Errorf("expected dir at %q, but mode is %q", path, info.Mode().String())
|
||||
} else if os.IsNotExist(err) {
|
||||
return false, nil
|
||||
} else {
|
||||
@ -137,3 +142,88 @@ func EnsureDir(fs utilfs.Filesystem, path string) error {
|
||||
// create the dir
|
||||
return fs.MkdirAll(path, defaultPerm)
|
||||
}
|
||||
|
||||
// WriteTempDir creates a temporary dir at `path`, writes `files` into it, and fsyncs all the files
|
||||
// The keys of `files` represent file names. These names must not:
|
||||
// - be empty
|
||||
// - be a path that contains more than the base name of a file (e.g. foo/bar is invalid, as is /bar)
|
||||
// - match `.` or `..` exactly
|
||||
// - be longer than 255 characters
|
||||
// The above validation rules are based on atomic_writer.go, though in this case are more restrictive
|
||||
// because we only allow a flat hierarchy.
|
||||
func WriteTempDir(fs utilfs.Filesystem, path string, files map[string]string) (tmpPath string, retErr error) {
|
||||
// validate the filename keys; for now we only allow a flat keyset
|
||||
for name := range files {
|
||||
// invalidate empty names
|
||||
if name == "" {
|
||||
return "", fmt.Errorf("invalid file key: must not be empty: %q", name)
|
||||
}
|
||||
// invalidate: foo/bar and /bar
|
||||
if name != filepath.Base(name) {
|
||||
return "", fmt.Errorf("invalid file key %q, only base names are allowed", name)
|
||||
}
|
||||
// invalidate `.` and `..`
|
||||
if name == "." || name == ".." {
|
||||
return "", fmt.Errorf("invalid file key, may not be '.' or '..'")
|
||||
}
|
||||
// invalidate length > 255 characters
|
||||
if len(name) > 255 {
|
||||
return "", fmt.Errorf("invalid file key %q, must be less than 255 characters", name)
|
||||
}
|
||||
}
|
||||
|
||||
// write the temp directory in parent dir and return path to the tmp directory
|
||||
dir := filepath.Dir(path)
|
||||
prefix := tmptag + filepath.Base(path)
|
||||
|
||||
// create the tmp dir
|
||||
var err error
|
||||
tmpPath, err = fs.TempDir(dir, prefix)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
// be sure to clean up if there was an error
|
||||
defer func() {
|
||||
if retErr != nil {
|
||||
if err := fs.RemoveAll(tmpPath); err != nil {
|
||||
retErr = fmt.Errorf("attempted to remove temporary directory %q after error %v, but failed due to error: %v", tmpPath, retErr, err)
|
||||
}
|
||||
}
|
||||
}()
|
||||
// write data
|
||||
for name, data := range files {
|
||||
// create the file
|
||||
file, err := fs.Create(filepath.Join(tmpPath, name))
|
||||
if err != nil {
|
||||
return tmpPath, err
|
||||
}
|
||||
// be sure to close the file when we're done
|
||||
defer func() {
|
||||
// close the file when we're done, don't overwrite primary retErr if close fails
|
||||
if err := file.Close(); retErr == nil {
|
||||
retErr = err
|
||||
}
|
||||
}()
|
||||
// write the file
|
||||
if _, err := file.Write([]byte(data)); err != nil {
|
||||
return tmpPath, err
|
||||
}
|
||||
// sync the file, to ensure it's written in case a hard reset happens
|
||||
if err := file.Sync(); err != nil {
|
||||
return tmpPath, err
|
||||
}
|
||||
}
|
||||
return tmpPath, nil
|
||||
}
|
||||
|
||||
// ReplaceDir replaces the contents of the dir at `path` with `files` by writing to a tmp dir in the same
|
||||
// dir as `path` and renaming the tmp dir over `path`. The dir does not have to exist to use ReplaceDir.
|
||||
func ReplaceDir(fs utilfs.Filesystem, path string, files map[string]string) error {
|
||||
// write data to a temporary directory
|
||||
tmpPath, err := WriteTempDir(fs, path, files)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
// rename over target directory
|
||||
return fs.Rename(tmpPath, path)
|
||||
}
|
||||
|
476
vendor/k8s.io/kubernetes/pkg/kubelet/kubeletconfig/util/files/files_test.go
generated
vendored
Normal file
476
vendor/k8s.io/kubernetes/pkg/kubelet/kubeletconfig/util/files/files_test.go
generated
vendored
Normal file
@ -0,0 +1,476 @@
|
||||
/*
|
||||
Copyright 2018 The Kubernetes 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 files
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"testing"
|
||||
|
||||
utiltest "k8s.io/kubernetes/pkg/kubelet/kubeletconfig/util/test"
|
||||
utilfs "k8s.io/kubernetes/pkg/util/filesystem"
|
||||
)
|
||||
|
||||
const (
|
||||
prefix = "test-util-files"
|
||||
)
|
||||
|
||||
type file struct {
|
||||
name string
|
||||
// mode distinguishes file type,
|
||||
// we only check for regular vs. directory in these tests,
|
||||
// specify regular as 0, directory as os.ModeDir
|
||||
mode os.FileMode
|
||||
data string // ignored if mode == os.ModeDir
|
||||
}
|
||||
|
||||
func (f *file) write(fs utilfs.Filesystem, dir string) error {
|
||||
path := filepath.Join(dir, f.name)
|
||||
if f.mode.IsDir() {
|
||||
if err := fs.MkdirAll(path, defaultPerm); err != nil {
|
||||
return err
|
||||
}
|
||||
} else if f.mode.IsRegular() {
|
||||
// create parent directories, if necessary
|
||||
parents := filepath.Dir(path)
|
||||
if err := fs.MkdirAll(parents, defaultPerm); err != nil {
|
||||
return err
|
||||
}
|
||||
// create the file
|
||||
handle, err := fs.Create(path)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
_, err = handle.Write([]byte(f.data))
|
||||
if err != nil {
|
||||
if cerr := handle.Close(); cerr != nil {
|
||||
return fmt.Errorf("error %v closing file after error: %v", cerr, err)
|
||||
}
|
||||
return err
|
||||
}
|
||||
} else {
|
||||
return fmt.Errorf("mode not implemented for testing %s", f.mode.String())
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (f *file) expect(fs utilfs.Filesystem, dir string) error {
|
||||
path := filepath.Join(dir, f.name)
|
||||
if f.mode.IsDir() {
|
||||
info, err := fs.Stat(path)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if !info.IsDir() {
|
||||
return fmt.Errorf("expected directory, got mode %s", info.Mode().String())
|
||||
}
|
||||
} else if f.mode.IsRegular() {
|
||||
info, err := fs.Stat(path)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if !info.Mode().IsRegular() {
|
||||
return fmt.Errorf("expected regular file, got mode %s", info.Mode().String())
|
||||
}
|
||||
data, err := fs.ReadFile(path)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if f.data != string(data) {
|
||||
return fmt.Errorf("expected file data %q, got %q", f.data, string(data))
|
||||
}
|
||||
} else {
|
||||
return fmt.Errorf("mode not implemented for testing %s", f.mode.String())
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// write files, perform some function, then attempt to read files back
|
||||
// if err is non-empty, expects an error from the function performed in the test
|
||||
// and skips reading back the expected files
|
||||
type test struct {
|
||||
desc string
|
||||
writes []file
|
||||
expects []file
|
||||
fn func(fs utilfs.Filesystem, dir string, c *test) []error
|
||||
err string
|
||||
}
|
||||
|
||||
func (c *test) write(t *testing.T, fs utilfs.Filesystem, dir string) {
|
||||
for _, f := range c.writes {
|
||||
if err := f.write(fs, dir); err != nil {
|
||||
t.Fatalf("error pre-writing file: %v", err)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// you can optionally skip calling t.Errorf by passing a nil t, and process the
|
||||
// returned errors instead
|
||||
func (c *test) expect(t *testing.T, fs utilfs.Filesystem, dir string) []error {
|
||||
errs := []error{}
|
||||
for _, f := range c.expects {
|
||||
if err := f.expect(fs, dir); err != nil {
|
||||
msg := fmt.Errorf("expect %#v, got error: %v", f, err)
|
||||
errs = append(errs, msg)
|
||||
if t != nil {
|
||||
t.Errorf("%s", msg)
|
||||
}
|
||||
}
|
||||
}
|
||||
return errs
|
||||
}
|
||||
|
||||
// run a test case, with an arbitrary function to execute between write and expect
|
||||
// if c.fn is nil, errors from c.expect are checked against c.err, instead of errors
|
||||
// from fn being checked against c.err
|
||||
func (c *test) run(t *testing.T, fs utilfs.Filesystem) {
|
||||
// isolate each test case in a new temporary directory
|
||||
dir, err := fs.TempDir("", prefix)
|
||||
if err != nil {
|
||||
t.Fatalf("error creating temporary directory for test: %v", err)
|
||||
}
|
||||
c.write(t, fs, dir)
|
||||
// if fn exists, check errors from fn, then check expected files
|
||||
if c.fn != nil {
|
||||
errs := c.fn(fs, dir, c)
|
||||
if len(errs) > 0 {
|
||||
for _, err := range errs {
|
||||
utiltest.ExpectError(t, err, c.err)
|
||||
}
|
||||
// skip checking expected files if we expected errors
|
||||
// (usually means we didn't create file)
|
||||
return
|
||||
}
|
||||
c.expect(t, fs, dir)
|
||||
return
|
||||
}
|
||||
// just check expected files, and compare errors from c.expect to c.err
|
||||
// (this lets us test the helper functions above)
|
||||
errs := c.expect(nil, fs, dir)
|
||||
for _, err := range errs {
|
||||
utiltest.ExpectError(t, err, c.err)
|
||||
}
|
||||
}
|
||||
|
||||
// simple test of the above helper functions
|
||||
func TestHelpers(t *testing.T) {
|
||||
// omitting the test.fn means test.err is compared to errors from test.expect
|
||||
cases := []test{
|
||||
{
|
||||
desc: "regular file",
|
||||
writes: []file{{name: "foo", data: "bar"}},
|
||||
expects: []file{{name: "foo", data: "bar"}},
|
||||
},
|
||||
{
|
||||
desc: "directory",
|
||||
writes: []file{{name: "foo", mode: os.ModeDir}},
|
||||
expects: []file{{name: "foo", mode: os.ModeDir}},
|
||||
},
|
||||
{
|
||||
desc: "deep regular file",
|
||||
writes: []file{{name: "foo/bar", data: "baz"}},
|
||||
expects: []file{{name: "foo/bar", data: "baz"}},
|
||||
},
|
||||
{
|
||||
desc: "deep directory",
|
||||
writes: []file{{name: "foo/bar", mode: os.ModeDir}},
|
||||
expects: []file{{name: "foo/bar", mode: os.ModeDir}},
|
||||
},
|
||||
{
|
||||
desc: "missing file",
|
||||
expects: []file{{name: "foo", data: "bar"}},
|
||||
err: "no such file or directory",
|
||||
},
|
||||
{
|
||||
desc: "missing directory",
|
||||
expects: []file{{name: "foo/bar", mode: os.ModeDir}},
|
||||
err: "no such file or directory",
|
||||
},
|
||||
}
|
||||
for _, c := range cases {
|
||||
t.Run(c.desc, func(t *testing.T) {
|
||||
c.run(t, utilfs.DefaultFs{})
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestFileExists(t *testing.T) {
|
||||
fn := func(fs utilfs.Filesystem, dir string, c *test) []error {
|
||||
ok, err := FileExists(fs, filepath.Join(dir, "foo"))
|
||||
if err != nil {
|
||||
return []error{err}
|
||||
}
|
||||
if !ok {
|
||||
return []error{fmt.Errorf("does not exist (test)")}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
cases := []test{
|
||||
{
|
||||
fn: fn,
|
||||
desc: "file exists",
|
||||
writes: []file{{name: "foo"}},
|
||||
},
|
||||
{
|
||||
fn: fn,
|
||||
desc: "file does not exist",
|
||||
err: "does not exist (test)",
|
||||
},
|
||||
{
|
||||
fn: fn,
|
||||
desc: "object has non-file mode",
|
||||
writes: []file{{name: "foo", mode: os.ModeDir}},
|
||||
err: "expected regular file",
|
||||
},
|
||||
}
|
||||
for _, c := range cases {
|
||||
t.Run(c.desc, func(t *testing.T) {
|
||||
c.run(t, utilfs.DefaultFs{})
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestEnsureFile(t *testing.T) {
|
||||
fn := func(fs utilfs.Filesystem, dir string, c *test) []error {
|
||||
var errs []error
|
||||
for _, f := range c.expects {
|
||||
if err := EnsureFile(fs, filepath.Join(dir, f.name)); err != nil {
|
||||
errs = append(errs, err)
|
||||
}
|
||||
}
|
||||
return errs
|
||||
}
|
||||
cases := []test{
|
||||
{
|
||||
fn: fn,
|
||||
desc: "file exists",
|
||||
writes: []file{{name: "foo"}},
|
||||
expects: []file{{name: "foo"}},
|
||||
},
|
||||
{
|
||||
fn: fn,
|
||||
desc: "file does not exist",
|
||||
expects: []file{{name: "bar"}},
|
||||
},
|
||||
{
|
||||
fn: fn,
|
||||
desc: "neither parent nor file exists",
|
||||
expects: []file{{name: "baz/quux"}},
|
||||
},
|
||||
}
|
||||
for _, c := range cases {
|
||||
t.Run(c.desc, func(t *testing.T) {
|
||||
c.run(t, utilfs.DefaultFs{})
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
// Note: This transitively tests WriteTmpFile
|
||||
func TestReplaceFile(t *testing.T) {
|
||||
fn := func(fs utilfs.Filesystem, dir string, c *test) []error {
|
||||
var errs []error
|
||||
for _, f := range c.expects {
|
||||
if err := ReplaceFile(fs, filepath.Join(dir, f.name), []byte(f.data)); err != nil {
|
||||
errs = append(errs, err)
|
||||
}
|
||||
}
|
||||
return errs
|
||||
}
|
||||
cases := []test{
|
||||
{
|
||||
fn: fn,
|
||||
desc: "file exists",
|
||||
writes: []file{{name: "foo"}},
|
||||
expects: []file{{name: "foo", data: "bar"}},
|
||||
},
|
||||
{
|
||||
fn: fn,
|
||||
desc: "file does not exist",
|
||||
expects: []file{{name: "foo", data: "bar"}},
|
||||
},
|
||||
{
|
||||
fn: func(fs utilfs.Filesystem, dir string, c *test) []error {
|
||||
if err := ReplaceFile(fs, filepath.Join(dir, "foo/bar"), []byte("")); err != nil {
|
||||
return []error{err}
|
||||
}
|
||||
return nil
|
||||
},
|
||||
desc: "neither parent nor file exists",
|
||||
err: "no such file or directory",
|
||||
},
|
||||
}
|
||||
for _, c := range cases {
|
||||
t.Run(c.desc, func(t *testing.T) {
|
||||
c.run(t, utilfs.DefaultFs{})
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestDirExists(t *testing.T) {
|
||||
fn := func(fs utilfs.Filesystem, dir string, c *test) []error {
|
||||
ok, err := DirExists(fs, filepath.Join(dir, "foo"))
|
||||
if err != nil {
|
||||
return []error{err}
|
||||
}
|
||||
if !ok {
|
||||
return []error{fmt.Errorf("does not exist (test)")}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
cases := []test{
|
||||
{
|
||||
fn: fn,
|
||||
desc: "dir exists",
|
||||
writes: []file{{name: "foo", mode: os.ModeDir}},
|
||||
},
|
||||
{
|
||||
fn: fn,
|
||||
desc: "dir does not exist",
|
||||
err: "does not exist (test)",
|
||||
},
|
||||
{
|
||||
fn: fn,
|
||||
desc: "object has non-dir mode",
|
||||
writes: []file{{name: "foo"}},
|
||||
err: "expected dir",
|
||||
},
|
||||
}
|
||||
for _, c := range cases {
|
||||
t.Run(c.desc, func(t *testing.T) {
|
||||
c.run(t, utilfs.DefaultFs{})
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestEnsureDir(t *testing.T) {
|
||||
fn := func(fs utilfs.Filesystem, dir string, c *test) []error {
|
||||
var errs []error
|
||||
for _, f := range c.expects {
|
||||
if err := EnsureDir(fs, filepath.Join(dir, f.name)); err != nil {
|
||||
errs = append(errs, err)
|
||||
}
|
||||
}
|
||||
return errs
|
||||
}
|
||||
cases := []test{
|
||||
{
|
||||
fn: fn,
|
||||
desc: "dir exists",
|
||||
writes: []file{{name: "foo", mode: os.ModeDir}},
|
||||
expects: []file{{name: "foo", mode: os.ModeDir}},
|
||||
},
|
||||
{
|
||||
fn: fn,
|
||||
desc: "dir does not exist",
|
||||
expects: []file{{name: "bar", mode: os.ModeDir}},
|
||||
},
|
||||
{
|
||||
fn: fn,
|
||||
desc: "neither parent nor dir exists",
|
||||
expects: []file{{name: "baz/quux", mode: os.ModeDir}},
|
||||
},
|
||||
}
|
||||
for _, c := range cases {
|
||||
t.Run(c.desc, func(t *testing.T) {
|
||||
c.run(t, utilfs.DefaultFs{})
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestWriteTempDir(t *testing.T) {
|
||||
// writing a tmp dir is covered by TestReplaceDir, but we additionally test filename validation here
|
||||
c := test{
|
||||
desc: "invalid file key",
|
||||
err: "invalid file key",
|
||||
fn: func(fs utilfs.Filesystem, dir string, c *test) []error {
|
||||
if _, err := WriteTempDir(fs, filepath.Join(dir, "tmpdir"), map[string]string{"foo/bar": ""}); err != nil {
|
||||
return []error{err}
|
||||
}
|
||||
return nil
|
||||
},
|
||||
}
|
||||
c.run(t, utilfs.DefaultFs{})
|
||||
}
|
||||
|
||||
func TestReplaceDir(t *testing.T) {
|
||||
fn := func(fs utilfs.Filesystem, dir string, c *test) []error {
|
||||
errs := []error{}
|
||||
|
||||
// compute filesets from expected files and call ReplaceDir for each
|
||||
// we don't nest dirs in test cases, order of ReplaceDir call is not guaranteed
|
||||
dirs := map[string]map[string]string{}
|
||||
|
||||
// allocate dirs
|
||||
for _, f := range c.expects {
|
||||
if f.mode.IsDir() {
|
||||
path := filepath.Join(dir, f.name)
|
||||
if _, ok := dirs[path]; !ok {
|
||||
dirs[path] = map[string]string{}
|
||||
}
|
||||
} else if f.mode.IsRegular() {
|
||||
path := filepath.Join(dir, filepath.Dir(f.name))
|
||||
if _, ok := dirs[path]; !ok {
|
||||
// require an expectation for the parent directory if there is an expectation for the file
|
||||
errs = append(errs, fmt.Errorf("no prior parent directory in c.expects for file %s", f.name))
|
||||
continue
|
||||
}
|
||||
dirs[path][filepath.Base(f.name)] = f.data
|
||||
}
|
||||
}
|
||||
|
||||
// short-circuit test case validation errors
|
||||
if len(errs) > 0 {
|
||||
return errs
|
||||
}
|
||||
|
||||
// call ReplaceDir for each desired dir
|
||||
for path, files := range dirs {
|
||||
if err := ReplaceDir(fs, path, files); err != nil {
|
||||
errs = append(errs, err)
|
||||
}
|
||||
}
|
||||
return errs
|
||||
}
|
||||
cases := []test{
|
||||
{
|
||||
fn: fn,
|
||||
desc: "fn catches invalid test case",
|
||||
expects: []file{{name: "foo/bar"}},
|
||||
err: "no prior parent directory",
|
||||
},
|
||||
{
|
||||
fn: fn,
|
||||
desc: "empty dir",
|
||||
expects: []file{{name: "foo", mode: os.ModeDir}},
|
||||
},
|
||||
{
|
||||
fn: fn,
|
||||
desc: "dir with files",
|
||||
expects: []file{
|
||||
{name: "foo", mode: os.ModeDir},
|
||||
{name: "foo/bar", data: "baz"},
|
||||
{name: "foo/baz", data: "bar"},
|
||||
},
|
||||
},
|
||||
}
|
||||
for _, c := range cases {
|
||||
t.Run(c.desc, func(t *testing.T) {
|
||||
c.run(t, utilfs.DefaultFs{})
|
||||
})
|
||||
}
|
||||
}
|
15
vendor/k8s.io/kubernetes/pkg/kubelet/kubeletconfig/util/test/test.go
generated
vendored
15
vendor/k8s.io/kubernetes/pkg/kubelet/kubeletconfig/util/test/test.go
generated
vendored
@ -21,6 +21,21 @@ import (
|
||||
"testing"
|
||||
)
|
||||
|
||||
// ExpectError calls t.Fatalf if the error does not contain a substr match.
|
||||
// If substr is empty, a nil error is expected.
|
||||
// It is useful to call ExpectError from subtests.
|
||||
func ExpectError(t *testing.T, err error, substr string) {
|
||||
if err != nil {
|
||||
if len(substr) == 0 {
|
||||
t.Fatalf("expect nil error but got %q", err.Error())
|
||||
} else if !strings.Contains(err.Error(), substr) {
|
||||
t.Fatalf("expect error to contain %q but got %q", substr, err.Error())
|
||||
}
|
||||
} else if len(substr) > 0 {
|
||||
t.Fatalf("expect error to contain %q but got nil error", substr)
|
||||
}
|
||||
}
|
||||
|
||||
// SkipRest returns true if there was a non-nil error or if we expected an error that didn't happen,
|
||||
// and logs the appropriate error on the test object.
|
||||
// The return value indicates whether we should skip the rest of the test case due to the error result.
|
||||
|
Reference in New Issue
Block a user