Skip to content

Commit 265b394

Browse files
Merge pull request #5284 from claudiubelu/test-symlinks
tests: Symlink volume tests
2 parents 6dcd883 + 93e268f commit 265b394

2 files changed

Lines changed: 162 additions & 0 deletions

File tree

Lines changed: 152 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,152 @@
1+
/*
2+
Copyright The containerd Authors.
3+
4+
Licensed under the Apache License, Version 2.0 (the "License");
5+
you may not use this file except in compliance with the License.
6+
You may obtain a copy of the License at
7+
8+
http://www.apache.org/licenses/LICENSE-2.0
9+
10+
Unless required by applicable law or agreed to in writing, software
11+
distributed under the License is distributed on an "AS IS" BASIS,
12+
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
See the License for the specific language governing permissions and
14+
limitations under the License.
15+
*/
16+
17+
package integration
18+
19+
import (
20+
"io/ioutil"
21+
"os"
22+
"path/filepath"
23+
"testing"
24+
"time"
25+
26+
"github.com/stretchr/testify/assert"
27+
"github.com/stretchr/testify/require"
28+
runtime "k8s.io/cri-api/pkg/apis/runtime/v1alpha2"
29+
)
30+
31+
func createRegularFile(basePath, content string) (string, error) {
32+
newFolder := filepath.Join(basePath, "regular")
33+
err := os.Mkdir(newFolder, 0755)
34+
if err != nil {
35+
return "", err
36+
}
37+
38+
newFile := filepath.Join(newFolder, "foo.txt")
39+
err = ioutil.WriteFile(newFile, []byte(content), 0644)
40+
return filepath.Join("regular", "foo.txt"), err
41+
}
42+
43+
func fileInSymlinkedFolder(basePath, targetFile string) (string, error) {
44+
symlinkFolder := filepath.Join(basePath, "symlink_folder")
45+
err := os.Symlink(filepath.Dir(targetFile), symlinkFolder)
46+
47+
return filepath.Join(symlinkFolder, filepath.Base(targetFile)), err
48+
}
49+
50+
func symlinkedFile(basePath, targetFile string) (string, error) {
51+
symlinkFile := filepath.Join(basePath, "symlink_file")
52+
err := os.Symlink(targetFile, symlinkFile)
53+
54+
return symlinkFile, err
55+
}
56+
57+
func symlinkedFileInSymlinkedFolder(basePath, targetFile string) (string, error) {
58+
symlinkFolderFile, err := fileInSymlinkedFolder(basePath, targetFile)
59+
if err != nil {
60+
return "", err
61+
}
62+
63+
return symlinkedFile(basePath, symlinkFolderFile)
64+
}
65+
66+
func TestContainerSymlinkVolumes(t *testing.T) {
67+
for name, testCase := range map[string]struct {
68+
createFileFn func(basePath, targetFile string) (string, error)
69+
}{
70+
// Create difference file / symlink scenarios:
71+
// - symlink_file -> regular_folder/regular_file
72+
// - symlink_folder/regular_file (symlink_folder -> regular_folder)
73+
// - symlink_file -> symlink_folder/regular_file (symlink_folder -> regular_folder)
74+
"file in symlinked folder": {
75+
createFileFn: fileInSymlinkedFolder,
76+
},
77+
"symlinked file": {
78+
createFileFn: symlinkedFile,
79+
},
80+
"symlinkedFileInSymlinkedFolder": {
81+
createFileFn: symlinkedFileInSymlinkedFolder,
82+
},
83+
} {
84+
testCase := testCase // capture range variable
85+
t.Run(name, func(t *testing.T) {
86+
testPodLogDir, err := ioutil.TempDir("", "symlink-test")
87+
require.NoError(t, err)
88+
defer os.RemoveAll(testPodLogDir)
89+
90+
testVolDir, err := ioutil.TempDir("", "symlink-test-vol")
91+
require.NoError(t, err)
92+
defer os.RemoveAll(testVolDir)
93+
94+
content := "hello there\n"
95+
regularFile, err := createRegularFile(testVolDir, content)
96+
require.NoError(t, err)
97+
98+
file, err := testCase.createFileFn(testVolDir, regularFile)
99+
require.NoError(t, err)
100+
101+
t.Log("Create test sandbox with log directory")
102+
sbConfig := PodSandboxConfig("sandbox", "test-symlink",
103+
WithPodLogDirectory(testPodLogDir),
104+
)
105+
sb, err := runtimeService.RunPodSandbox(sbConfig, *runtimeHandler)
106+
require.NoError(t, err)
107+
defer func() {
108+
assert.NoError(t, runtimeService.StopPodSandbox(sb))
109+
assert.NoError(t, runtimeService.RemovePodSandbox(sb))
110+
}()
111+
112+
var (
113+
testImage = GetImage(BusyBox)
114+
containerName = "test-container"
115+
)
116+
117+
EnsureImageExists(t, testImage)
118+
119+
t.Log("Create a container with a symlink volume mount")
120+
cnConfig := ContainerConfig(
121+
containerName,
122+
testImage,
123+
WithCommand("cat", "/mounted_file"),
124+
WithLogPath(containerName),
125+
WithVolumeMount(file, "/mounted_file"),
126+
)
127+
128+
cn, err := runtimeService.CreateContainer(sb, cnConfig, sbConfig)
129+
require.NoError(t, err)
130+
131+
t.Log("Start the container")
132+
require.NoError(t, runtimeService.StartContainer(cn))
133+
134+
t.Log("Wait for container to finish running")
135+
require.NoError(t, Eventually(func() (bool, error) {
136+
s, err := runtimeService.ContainerStatus(cn)
137+
if err != nil {
138+
return false, err
139+
}
140+
if s.GetState() == runtime.ContainerState_CONTAINER_EXITED {
141+
return true, nil
142+
}
143+
return false, nil
144+
}, time.Second, 30*time.Second))
145+
146+
output, err := ioutil.ReadFile(filepath.Join(testPodLogDir, containerName))
147+
assert.NoError(t, err)
148+
149+
assert.Contains(t, string(output), content)
150+
})
151+
}
152+
}

integration/main_test.go

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@ import (
2323
"fmt"
2424
"os"
2525
"os/exec"
26+
"path/filepath"
2627
"strconv"
2728
"strings"
2829
"testing"
@@ -206,6 +207,15 @@ func WithResources(r *runtime.LinuxContainerResources) ContainerOpts { //nolint:
206207
}
207208
}
208209

210+
func WithVolumeMount(hostPath, containerPath string) ContainerOpts {
211+
return func(c *runtime.ContainerConfig) {
212+
hostPath, _ = filepath.Abs(hostPath)
213+
containerPath, _ = filepath.Abs(containerPath)
214+
mount := &runtime.Mount{HostPath: hostPath, ContainerPath: containerPath}
215+
c.Mounts = append(c.Mounts, mount)
216+
}
217+
}
218+
209219
// Add container command.
210220
func WithCommand(cmd string, args ...string) ContainerOpts {
211221
return func(c *runtime.ContainerConfig) {

0 commit comments

Comments
 (0)