Set /etc/hostname.
Signed-off-by: Lantao Liu <lantaol@google.com>
This commit is contained in:
parent
7c2498d2e6
commit
089d4fbfb8
@ -28,7 +28,7 @@ import (
|
||||
runtime "k8s.io/kubernetes/pkg/kubelet/apis/cri/runtime/v1alpha2"
|
||||
)
|
||||
|
||||
func TestPodHostnameEnv(t *testing.T) {
|
||||
func TestPodHostname(t *testing.T) {
|
||||
hostname, err := os.Hostname()
|
||||
require.NoError(t, err)
|
||||
for name, test := range map[string]struct {
|
||||
@ -56,13 +56,13 @@ func TestPodHostnameEnv(t *testing.T) {
|
||||
},
|
||||
} {
|
||||
t.Run(name, func(t *testing.T) {
|
||||
testPodLogDir, err := ioutil.TempDir("/tmp", "hostname-env")
|
||||
testPodLogDir, err := ioutil.TempDir("/tmp", "hostname")
|
||||
require.NoError(t, err)
|
||||
defer os.RemoveAll(testPodLogDir)
|
||||
|
||||
opts := append(test.opts, WithPodLogDirectory(testPodLogDir))
|
||||
t.Log("Create a sandbox with hostname")
|
||||
sbConfig := PodSandboxConfig("sandbox", "hostname-env", opts...)
|
||||
sbConfig := PodSandboxConfig("sandbox", "hostname", opts...)
|
||||
sb, err := runtimeService.RunPodSandbox(sbConfig, *runtimeHandler)
|
||||
require.NoError(t, err)
|
||||
defer func() {
|
||||
@ -85,7 +85,8 @@ func TestPodHostnameEnv(t *testing.T) {
|
||||
cnConfig := ContainerConfig(
|
||||
containerName,
|
||||
testImage,
|
||||
WithCommand("env"),
|
||||
WithCommand("sh", "-c",
|
||||
"echo -n /etc/hostname= && cat /etc/hostname && env"),
|
||||
WithLogPath(containerName),
|
||||
)
|
||||
cn, err := runtimeService.CreateContainer(sb, cnConfig, sbConfig)
|
||||
@ -106,10 +107,14 @@ func TestPodHostnameEnv(t *testing.T) {
|
||||
return false, nil
|
||||
}, time.Second, 30*time.Second))
|
||||
|
||||
t.Log("Search hostname env in container log")
|
||||
content, err := ioutil.ReadFile(filepath.Join(testPodLogDir, containerName))
|
||||
assert.NoError(t, err)
|
||||
|
||||
t.Log("Search hostname env in container log")
|
||||
assert.Contains(t, string(content), "HOSTNAME="+test.expectedHostname)
|
||||
|
||||
t.Log("Search /etc/hostname content in container log")
|
||||
assert.Contains(t, string(content), "/etc/hostname="+test.expectedHostname)
|
||||
})
|
||||
}
|
||||
}
|
@ -339,8 +339,7 @@ func (c *criService) generateContainerSpec(id string, sandboxID string, sandboxP
|
||||
|
||||
// Add HOSTNAME env.
|
||||
hostname := sandboxConfig.GetHostname()
|
||||
if sandboxConfig.GetLinux().GetSecurityContext().GetNamespaceOptions().GetNetwork() == runtime.NamespaceMode_NODE &&
|
||||
hostname == "" {
|
||||
if sandboxConfig.GetHostname() == "" {
|
||||
hostname, err = c.os.Hostname()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
@ -483,6 +482,14 @@ func (c *criService) generateVolumeMounts(containerRootDir string, criMounts []*
|
||||
func (c *criService) generateContainerMounts(sandboxID string, config *runtime.ContainerConfig) []*runtime.Mount {
|
||||
var mounts []*runtime.Mount
|
||||
securityContext := config.GetLinux().GetSecurityContext()
|
||||
if !isInCRIMounts(etcHostname, config.GetMounts()) {
|
||||
mounts = append(mounts, &runtime.Mount{
|
||||
ContainerPath: etcHostname,
|
||||
HostPath: c.getSandboxHostname(sandboxID),
|
||||
Readonly: securityContext.GetReadonlyRootfs(),
|
||||
})
|
||||
}
|
||||
|
||||
if !isInCRIMounts(etcHosts, config.GetMounts()) {
|
||||
mounts = append(mounts, &runtime.Mount{
|
||||
ContainerPath: etcHosts,
|
||||
|
@ -534,6 +534,11 @@ func TestGenerateContainerMounts(t *testing.T) {
|
||||
ReadonlyRootfs: true,
|
||||
},
|
||||
expectedMounts: []*runtime.Mount{
|
||||
{
|
||||
ContainerPath: "/etc/hostname",
|
||||
HostPath: filepath.Join(testRootDir, sandboxesDir, testSandboxID, "hostname"),
|
||||
Readonly: true,
|
||||
},
|
||||
{
|
||||
ContainerPath: "/etc/hosts",
|
||||
HostPath: filepath.Join(testRootDir, sandboxesDir, testSandboxID, "hosts"),
|
||||
@ -554,6 +559,11 @@ func TestGenerateContainerMounts(t *testing.T) {
|
||||
"should setup rw mount when rootfs is read-write": {
|
||||
securityContext: &runtime.LinuxContainerSecurityContext{},
|
||||
expectedMounts: []*runtime.Mount{
|
||||
{
|
||||
ContainerPath: "/etc/hostname",
|
||||
HostPath: filepath.Join(testRootDir, sandboxesDir, testSandboxID, "hostname"),
|
||||
Readonly: false,
|
||||
},
|
||||
{
|
||||
ContainerPath: "/etc/hosts",
|
||||
HostPath: filepath.Join(testRootDir, sandboxesDir, testSandboxID, "hosts"),
|
||||
@ -576,6 +586,11 @@ func TestGenerateContainerMounts(t *testing.T) {
|
||||
NamespaceOptions: &runtime.NamespaceOption{Ipc: runtime.NamespaceMode_NODE},
|
||||
},
|
||||
expectedMounts: []*runtime.Mount{
|
||||
{
|
||||
ContainerPath: "/etc/hostname",
|
||||
HostPath: filepath.Join(testRootDir, sandboxesDir, testSandboxID, "hostname"),
|
||||
Readonly: false,
|
||||
},
|
||||
{
|
||||
ContainerPath: "/etc/hosts",
|
||||
HostPath: filepath.Join(testRootDir, sandboxesDir, testSandboxID, "hosts"),
|
||||
@ -595,6 +610,10 @@ func TestGenerateContainerMounts(t *testing.T) {
|
||||
},
|
||||
"should skip container mounts if already mounted by CRI": {
|
||||
criMounts: []*runtime.Mount{
|
||||
{
|
||||
ContainerPath: "/etc/hostname",
|
||||
HostPath: "/test-etc-hostname",
|
||||
},
|
||||
{
|
||||
ContainerPath: "/etc/hosts",
|
||||
HostPath: "/test-etc-host",
|
||||
|
@ -99,6 +99,8 @@ const (
|
||||
devShm = "/dev/shm"
|
||||
// etcHosts is the default path of /etc/hosts file.
|
||||
etcHosts = "/etc/hosts"
|
||||
// etcHostname is the default path of /etc/hostname file.
|
||||
etcHostname = "/etc/hostname"
|
||||
// resolvConfPath is the abs path of resolv.conf on host or container.
|
||||
resolvConfPath = "/etc/resolv.conf"
|
||||
// hostnameEnv is the key for HOSTNAME env.
|
||||
@ -199,6 +201,11 @@ func (c *criService) getVolatileContainerRootDir(id string) string {
|
||||
return filepath.Join(c.config.StateDir, containersDir, id)
|
||||
}
|
||||
|
||||
// getSandboxHostname returns the hostname file path inside the sandbox root directory.
|
||||
func (c *criService) getSandboxHostname(id string) string {
|
||||
return filepath.Join(c.getSandboxRootDir(id), "hostname")
|
||||
}
|
||||
|
||||
// getSandboxHosts returns the hosts file path inside the sandbox root directory.
|
||||
func (c *criService) getSandboxHosts(id string) string {
|
||||
return filepath.Join(c.getSandboxRootDir(id), "hosts")
|
||||
|
@ -233,7 +233,7 @@ func (c *criService) RunPodSandbox(ctx context.Context, r *runtime.RunPodSandbox
|
||||
}
|
||||
}()
|
||||
|
||||
// Setup sandbox /dev/shm, /etc/hosts and /etc/resolv.conf.
|
||||
// Setup sandbox /dev/shm, /etc/hosts, /etc/resolv.conf and /etc/hostname.
|
||||
if err = c.setupSandboxFiles(id, config); err != nil {
|
||||
return nil, errors.Wrapf(err, "failed to setup sandbox files")
|
||||
}
|
||||
@ -456,9 +456,22 @@ func (c *criService) generateSandboxContainerSpec(id string, config *runtime.Pod
|
||||
return g.Config, nil
|
||||
}
|
||||
|
||||
// setupSandboxFiles sets up necessary sandbox files including /dev/shm, /etc/hosts
|
||||
// and /etc/resolv.conf.
|
||||
// setupSandboxFiles sets up necessary sandbox files including /dev/shm, /etc/hosts,
|
||||
// /etc/resolv.conf and /etc/hostname.
|
||||
func (c *criService) setupSandboxFiles(id string, config *runtime.PodSandboxConfig) error {
|
||||
sandboxEtcHostname := c.getSandboxHostname(id)
|
||||
hostname := config.GetHostname()
|
||||
if hostname == "" {
|
||||
var err error
|
||||
hostname, err = c.os.Hostname()
|
||||
if err != nil {
|
||||
return errors.Wrap(err, "failed to get hostname")
|
||||
}
|
||||
}
|
||||
if err := c.os.WriteFile(sandboxEtcHostname, []byte(hostname+"\n"), 0644); err != nil {
|
||||
return errors.Wrapf(err, "failed to write hostname to %q", sandboxEtcHostname)
|
||||
}
|
||||
|
||||
// TODO(random-liu): Consider whether we should maintain /etc/hosts and /etc/resolv.conf in kubelet.
|
||||
sandboxEtcHosts := c.getSandboxHosts(id)
|
||||
if err := c.os.CopyFile(etcHosts, sandboxEtcHosts, 0644); err != nil {
|
||||
|
@ -180,15 +180,30 @@ func TestGenerateSandboxContainerSpec(t *testing.T) {
|
||||
}
|
||||
|
||||
func TestSetupSandboxFiles(t *testing.T) {
|
||||
const testID = "test-id"
|
||||
const (
|
||||
testID = "test-id"
|
||||
realhostname = "test-real-hostname"
|
||||
)
|
||||
for desc, test := range map[string]struct {
|
||||
dnsConfig *runtime.DNSConfig
|
||||
hostname string
|
||||
ipcMode runtime.NamespaceMode
|
||||
expectedCalls []ostesting.CalledDetail
|
||||
}{
|
||||
"should check host /dev/shm existence when ipc mode is NODE": {
|
||||
ipcMode: runtime.NamespaceMode_NODE,
|
||||
expectedCalls: []ostesting.CalledDetail{
|
||||
{
|
||||
Name: "Hostname",
|
||||
},
|
||||
{
|
||||
Name: "WriteFile",
|
||||
Arguments: []interface{}{
|
||||
filepath.Join(testRootDir, sandboxesDir, testID, "hostname"),
|
||||
[]byte(realhostname + "\n"),
|
||||
os.FileMode(0644),
|
||||
},
|
||||
},
|
||||
{
|
||||
Name: "CopyFile",
|
||||
Arguments: []interface{}{
|
||||
@ -219,6 +234,17 @@ func TestSetupSandboxFiles(t *testing.T) {
|
||||
},
|
||||
ipcMode: runtime.NamespaceMode_NODE,
|
||||
expectedCalls: []ostesting.CalledDetail{
|
||||
{
|
||||
Name: "Hostname",
|
||||
},
|
||||
{
|
||||
Name: "WriteFile",
|
||||
Arguments: []interface{}{
|
||||
filepath.Join(testRootDir, sandboxesDir, testID, "hostname"),
|
||||
[]byte(realhostname + "\n"),
|
||||
os.FileMode(0644),
|
||||
},
|
||||
},
|
||||
{
|
||||
Name: "CopyFile",
|
||||
Arguments: []interface{}{
|
||||
@ -246,6 +272,17 @@ options timeout:1
|
||||
"should create sandbox shm when ipc namespace mode is not NODE": {
|
||||
ipcMode: runtime.NamespaceMode_POD,
|
||||
expectedCalls: []ostesting.CalledDetail{
|
||||
{
|
||||
Name: "Hostname",
|
||||
},
|
||||
{
|
||||
Name: "WriteFile",
|
||||
Arguments: []interface{}{
|
||||
filepath.Join(testRootDir, sandboxesDir, testID, "hostname"),
|
||||
[]byte(realhostname + "\n"),
|
||||
os.FileMode(0644),
|
||||
},
|
||||
},
|
||||
{
|
||||
Name: "CopyFile",
|
||||
Arguments: []interface{}{
|
||||
@ -275,10 +312,48 @@ options timeout:1
|
||||
},
|
||||
},
|
||||
},
|
||||
"should create /etc/hostname when hostname is set": {
|
||||
hostname: "test-hostname",
|
||||
ipcMode: runtime.NamespaceMode_NODE,
|
||||
expectedCalls: []ostesting.CalledDetail{
|
||||
{
|
||||
Name: "WriteFile",
|
||||
Arguments: []interface{}{
|
||||
filepath.Join(testRootDir, sandboxesDir, testID, "hostname"),
|
||||
[]byte("test-hostname\n"),
|
||||
os.FileMode(0644),
|
||||
},
|
||||
},
|
||||
{
|
||||
Name: "CopyFile",
|
||||
Arguments: []interface{}{
|
||||
"/etc/hosts",
|
||||
filepath.Join(testRootDir, sandboxesDir, testID, "hosts"),
|
||||
os.FileMode(0644),
|
||||
},
|
||||
},
|
||||
{
|
||||
Name: "CopyFile",
|
||||
Arguments: []interface{}{
|
||||
"/etc/resolv.conf",
|
||||
filepath.Join(testRootDir, sandboxesDir, testID, "resolv.conf"),
|
||||
os.FileMode(0644),
|
||||
},
|
||||
},
|
||||
{
|
||||
Name: "Stat",
|
||||
Arguments: []interface{}{"/dev/shm"},
|
||||
},
|
||||
},
|
||||
},
|
||||
} {
|
||||
t.Logf("TestCase %q", desc)
|
||||
c := newTestCRIService()
|
||||
c.os.(*ostesting.FakeOS).HostnameFn = func() (string, error) {
|
||||
return realhostname, nil
|
||||
}
|
||||
cfg := &runtime.PodSandboxConfig{
|
||||
Hostname: test.hostname,
|
||||
DnsConfig: test.dnsConfig,
|
||||
Linux: &runtime.LinuxPodSandboxConfig{
|
||||
SecurityContext: &runtime.LinuxSandboxSecurityContext{
|
||||
|
Loading…
Reference in New Issue
Block a user