rkt: Do not run rkt pod inside a pre-created netns when network plugin is no-op.

This fixed a panic where the returned pod network status is nil.
Also this makes lkvm stage1 able to run inside a user defined
network, where the network name needs to be 'rkt.kubernetes.io'.

Also fixed minor issues such as passing the wrong pod UID, ignoring
logging errors.
This commit is contained in:
Yifan Gu 2016-06-07 13:22:55 -07:00
parent 6a388d4a0d
commit 5a9ea30814
2 changed files with 235 additions and 69 deletions

View File

@ -82,7 +82,7 @@ const (
unitPodUID = "PodUID"
unitPodName = "PodName"
unitPodNamespace = "PodNamespace"
unitRestartCount = "RestartCount"
unitPodHostNetwork = "PodHostNetwork"
k8sRktKubeletAnno = "rkt.kubernetes.io/managed-by-kubelet"
k8sRktKubeletAnnoValue = "true"
@ -120,6 +120,13 @@ const (
// TODO(yifan): Reuse this const with Docker runtime.
minimumGracePeriodInSeconds = 2
// The network name of the network when no-op plugin is being used.
// TODO(yifan): This is not ideal since today we cannot make the rkt's 'net.d' dir point to the
// CNI directory specified by kubelet. Once that is fixed, we can just use the network config
// under the CNI directory directly.
// See https://github.com/coreos/rkt/pull/2312#issuecomment-200068370.
defaultNetworkName = "rkt.kubernetes.io"
)
// Runtime implements the Containerruntime for rkt. The implementation
@ -902,6 +909,20 @@ func serviceFilePath(serviceName string) string {
return path.Join(systemdServiceDir, serviceName)
}
// shouldCreateNetns returns true if:
// The pod does not run in host network. And
// The pod runs inside a netns created outside of rkt.
func (r *Runtime) shouldCreateNetns(pod *api.Pod) bool {
return !kubecontainer.IsHostNetworkPod(pod) && r.networkPlugin.Name() != network.DefaultPluginName
}
// usesRktHostNetwork returns true if:
// The pod runs in the host network. Or
// The pod runs inside a netns created outside of rkt.
func (r *Runtime) usesRktHostNetwork(pod *api.Pod) bool {
return kubecontainer.IsHostNetworkPod(pod) || r.shouldCreateNetns(pod)
}
// generateRunCommand crafts a 'rkt run-prepared' command with necessary parameters.
func (r *Runtime) generateRunCommand(pod *api.Pod, uuid, netnsName string) (string, error) {
runPrepared := buildCommand(r.config, "run-prepared").Args
@ -921,10 +942,14 @@ func (r *Runtime) generateRunCommand(pod *api.Pod, uuid, netnsName string) (stri
runPrepared = append(runPrepared, "--no-overlay=true")
}
// Network namespace set up in kubelet; rkt networking not used
runPrepared = append(runPrepared, "--net=host")
// Apply '--net=host' to pod that is running on host network or inside a network namespace.
if r.usesRktHostNetwork(pod) {
runPrepared = append(runPrepared, "--net=host")
} else {
runPrepared = append(runPrepared, fmt.Sprintf("--net=%s", defaultNetworkName))
}
if len(netnsName) == 0 {
if kubecontainer.IsHostNetworkPod(pod) {
// TODO(yifan): Let runtimeHelper.GeneratePodHostNameAndDomain() to handle this.
hostname, err = r.os.Hostname()
if err != nil {
@ -951,7 +976,12 @@ func (r *Runtime) generateRunCommand(pod *api.Pod, uuid, netnsName string) (stri
if err != nil {
return "", err
}
}
runPrepared = append(runPrepared, fmt.Sprintf("--hostname=%s", hostname))
runPrepared = append(runPrepared, uuid)
if r.shouldCreateNetns(pod) {
// Drop the `rkt run-prepared` into the network namespace we
// created.
// TODO: switch to 'ip netns exec' once we can depend on a new
@ -961,18 +991,22 @@ func (r *Runtime) generateRunCommand(pod *api.Pod, uuid, netnsName string) (stri
runPrepared = append(nsenterExec, runPrepared...)
}
runPrepared = append(runPrepared, fmt.Sprintf("--hostname=%s", hostname))
runPrepared = append(runPrepared, uuid)
return strings.Join(runPrepared, " "), nil
}
func (r *Runtime) cleanupPodNetwork(pod *api.Pod) error {
glog.V(3).Infof("Calling network plugin %s to tear down pod for %s", r.networkPlugin.Name(), format.Pod(pod))
// No-op if the pod is not running in a created netns.
if !r.shouldCreateNetns(pod) {
return nil
}
var teardownErr error
containerID := kubecontainer.ContainerID{ID: string(pod.UID)}
if err := r.networkPlugin.TearDownPod(pod.Namespace, pod.Name, containerID); err != nil {
teardownErr = fmt.Errorf("rkt: failed to tear down network for pod %s: %v", format.Pod(pod), err)
glog.Errorf("%v", teardownErr)
}
if _, err := r.execer.Command("ip", "netns", "del", makePodNetnsName(pod.UID)).Output(); err != nil {
@ -1089,6 +1123,8 @@ func (r *Runtime) preparePod(pod *api.Pod, podIP string, pullSecrets []api.Secre
// TODO per container finishedAt, not just per pod
markPodFinished := podFinishedMarkCommand(r.touchPath, r.runtimeHelper.GetPodDir(pod.UID), uuid)
hostNetwork := kubecontainer.IsHostNetworkPod(pod)
units := []*unit.UnitOption{
newUnitOption("Service", "ExecStart", runPrepared),
newUnitOption("Service", "ExecStopPost", markPodFinished),
@ -1098,6 +1134,7 @@ func (r *Runtime) preparePod(pod *api.Pod, podIP string, pullSecrets []api.Secre
newUnitOption(unitKubernetesSection, unitPodUID, string(pod.UID)),
newUnitOption(unitKubernetesSection, unitPodName, pod.Name),
newUnitOption(unitKubernetesSection, unitPodNamespace, pod.Namespace),
newUnitOption(unitKubernetesSection, unitPodHostNetwork, fmt.Sprintf("%v", hostNetwork)),
}
if pod.Spec.SecurityContext != nil && pod.Spec.SecurityContext.SELinuxOptions != nil {
@ -1161,7 +1198,7 @@ func (r *Runtime) generateEvents(runtimePod *kubecontainer.Pod, reason string, f
}
func makePodNetnsName(podID kubetypes.UID) string {
return fmt.Sprintf("%s_%s", kubernetesUnitPrefix, string(podID))
return fmt.Sprintf("%s%s", kubernetesUnitPrefix, string(podID))
}
func netnsPathFromName(netnsName string) string {
@ -1172,7 +1209,16 @@ func netnsPathFromName(netnsName string) string {
// configured NetworkPlugin's setup function on it.
// It returns the namespace name, configured IP (if available), and an error if
// one occured.
//
// If the pod is running in host network or is running using the no-op plugin, then nothing will be done.
func (r *Runtime) setupPodNetwork(pod *api.Pod) (string, string, error) {
glog.V(3).Infof("Calling network plugin %s to set up pod for %s", r.networkPlugin.Name(), format.Pod(pod))
// No-op if the pod is not running in a created netns.
if !r.shouldCreateNetns(pod) {
return "", "", nil
}
netnsName := makePodNetnsName(pod.UID)
// Create a new network namespace for the pod
@ -1211,12 +1257,10 @@ func (r *Runtime) RunPod(pod *api.Pod, pullSecrets []api.Secret) error {
var err error
var netnsName string
var podIP string
if !kubecontainer.IsHostNetworkPod(pod) {
netnsName, podIP, err = r.setupPodNetwork(pod)
if err != nil {
r.cleanupPodNetwork(pod)
return err
}
netnsName, podIP, err = r.setupPodNetwork(pod)
if err != nil {
r.cleanupPodNetwork(pod)
return err
}
name, runtimePod, prepareErr := r.preparePod(pod, podIP, pullSecrets, netnsName)
@ -1549,6 +1593,8 @@ func (r *Runtime) KillPod(pod *api.Pod, runningPod kubecontainer.Pod, gracePerio
return err
}
serviceName := makePodServiceFileName(containerID.uuid)
serviceFile := serviceFilePath(serviceName)
r.generateEvents(&runningPod, "Killing", nil)
for _, c := range runningPod.Containers {
r.containerRefManager.ClearRef(c.ID)
@ -1556,7 +1602,7 @@ func (r *Runtime) KillPod(pod *api.Pod, runningPod kubecontainer.Pod, gracePerio
// Touch the systemd service file to update the mod time so it will
// not be garbage collected too soon.
if err := r.os.Chtimes(serviceFilePath(serviceName), time.Now(), time.Now()); err != nil {
if err := r.os.Chtimes(serviceFile, time.Now(), time.Now()); err != nil {
glog.Errorf("rkt: Failed to change the modification time of the service file %q: %v", serviceName, err)
return err
}
@ -1576,19 +1622,10 @@ func (r *Runtime) KillPod(pod *api.Pod, runningPod kubecontainer.Pod, gracePerio
return err
}
// Clean up networking; use running pod details since 'pod' can be nil
if pod == nil || !kubecontainer.IsHostNetworkPod(pod) {
err := r.cleanupPodNetwork(&api.Pod{
ObjectMeta: api.ObjectMeta{
UID: runningPod.ID,
Name: runningPod.Name,
Namespace: runningPod.Namespace,
},
})
if err != nil {
glog.Errorf("rkt: failed to tear down network for unit %q: %v", serviceName, err)
return err
}
// Clean up networking. Use the service file to get pod details since 'pod' can be nil.
if err := r.cleanupPodNetworkFromServiceFile(serviceFile); err != nil {
glog.Errorf("rkt: failed to tear down network for unit %q: %v", serviceName, err)
return err
}
return nil
@ -1725,19 +1762,19 @@ func (r *Runtime) GetNetNS(containerID kubecontainer.ContainerID) (string, error
return netnsPathFromName(makePodNetnsName(kubetypes.UID(containerID.ID))), nil
}
func podDetailsFromServiceFile(serviceFilePath string) (string, string, string, error) {
func podDetailsFromServiceFile(serviceFilePath string) (string, string, string, bool, error) {
f, err := os.Open(serviceFilePath)
if err != nil {
return "", "", "", err
return "", "", "", false, err
}
defer f.Close()
opts, err := unit.Deserialize(f)
if err != nil {
return "", "", "", err
return "", "", "", false, err
}
var id, name, namespace string
var id, name, namespace, hostnetwork string
for _, o := range opts {
if o.Section != unitKubernetesSection {
continue
@ -1749,14 +1786,20 @@ func podDetailsFromServiceFile(serviceFilePath string) (string, string, string,
name = o.Value
case unitPodNamespace:
namespace = o.Value
case unitPodHostNetwork:
hostnetwork = o.Value
}
if id != "" && name != "" && namespace != "" {
return id, name, namespace, nil
if id != "" && name != "" && namespace != "" && hostnetwork != "" {
podHostNetwork, err := strconv.ParseBool(hostnetwork)
if err != nil {
return "", "", "", false, err
}
return id, name, namespace, podHostNetwork, nil
}
}
return "", "", "", fmt.Errorf("failed to parse pod from file %s", serviceFilePath)
return "", "", "", false, fmt.Errorf("failed to parse pod from file %s", serviceFilePath)
}
// GarbageCollect collects the pods/containers.
@ -1822,8 +1865,9 @@ func (r *Runtime) GarbageCollect(gcPolicy kubecontainer.ContainerGCPolicy) error
serviceFile := serviceFilePath(serviceName)
// Network may not be around anymore so errors are ignored
r.cleanupPodNetworkFromServiceFile(serviceFile)
if err := r.cleanupPodNetworkFromServiceFile(serviceFile); err != nil {
glog.Warningf("rkt: Failed to clean up pod network from service %q: %v, the network may not be around already", serviceName, err)
}
if err := r.os.Remove(serviceFile); err != nil {
errlist = append(errlist, fmt.Errorf("rkt: Failed to remove service file %q: %v", serviceFile, err))
}
@ -1859,17 +1903,23 @@ func (r *Runtime) GarbageCollect(gcPolicy kubecontainer.ContainerGCPolicy) error
// Read kubernetes pod UUID, namespace, and name from systemd service file and
// use that to clean up any pod network that may still exist.
func (r *Runtime) cleanupPodNetworkFromServiceFile(serviceFilePath string) {
id, name, namespace, err := podDetailsFromServiceFile(serviceFilePath)
if err == nil {
r.cleanupPodNetwork(&api.Pod{
ObjectMeta: api.ObjectMeta{
UID: kubetypes.UID(id),
Name: name,
Namespace: namespace,
},
})
func (r *Runtime) cleanupPodNetworkFromServiceFile(serviceFilePath string) error {
id, name, namespace, hostnetwork, err := podDetailsFromServiceFile(serviceFilePath)
if err != nil {
return err
}
return r.cleanupPodNetwork(&api.Pod{
ObjectMeta: api.ObjectMeta{
UID: kubetypes.UID(id),
Name: name,
Namespace: namespace,
},
Spec: api.PodSpec{
SecurityContext: &api.PodSecurityContext{
HostNetwork: hostnetwork,
},
},
})
}
// removePod calls 'rkt rm $UUID' to delete a rkt pod, it also remove the systemd service file
@ -1882,7 +1932,9 @@ func (r *Runtime) removePod(uuid string) error {
serviceFile := serviceFilePath(serviceName)
// Network may not be around anymore so errors are ignored
r.cleanupPodNetworkFromServiceFile(serviceFile)
if err := r.cleanupPodNetworkFromServiceFile(serviceFile); err != nil {
glog.Warningf("rkt: Failed to clean up pod network from service %q: %v, the network may not be around already", serviceName, err)
}
if _, err := r.cli.RunCommand(nil, "rm", uuid); err != nil {
errlist = append(errlist, fmt.Errorf("rkt: Failed to remove pod %q: %v", uuid, err))
@ -2148,6 +2200,7 @@ func (r *Runtime) GetPodStatus(uid kubetypes.UID, name, namespace string) (*kube
return nil, fmt.Errorf("couldn't list pods: %v", err)
}
var latestPod *rktapi.Pod
var latestRestartCount int = -1
// In this loop, we group all containers from all pods together,
@ -2160,6 +2213,7 @@ func (r *Runtime) GetPodStatus(uid kubetypes.UID, name, namespace string) (*kube
}
if restartCount > latestRestartCount {
latestPod = pod
latestRestartCount = restartCount
}
@ -2175,10 +2229,26 @@ func (r *Runtime) GetPodStatus(uid kubetypes.UID, name, namespace string) (*kube
}
}
// TODO(euank): this will not work in host networking mode
containerID := kubecontainer.ContainerID{ID: string(uid)}
if status, err := r.networkPlugin.GetPodNetworkStatus(namespace, name, containerID); err == nil {
podStatus.IP = status.IP.String()
// If we are running no-op network plugin, then get the pod IP from the rkt pod status.
if r.networkPlugin.Name() == network.DefaultPluginName {
if latestPod != nil {
for _, n := range latestPod.Networks {
if n.Name == defaultNetworkName {
podStatus.IP = n.Ipv4
break
}
}
}
} else {
containerID := kubecontainer.ContainerID{ID: string(uid)}
status, err := r.networkPlugin.GetPodNetworkStatus(namespace, name, containerID)
if err != nil {
glog.Warningf("rkt: Failed to get pod network status for pod (UID %q, name %q, namespace %q): %v", uid, name, namespace, err)
} else if status != nil {
// status can be nil when the pod is running on the host network, in which case the pod IP
// will be populated by the upper layer.
podStatus.IP = status.IP.String()
}
}
return podStatus, nil

View File

@ -38,6 +38,7 @@ import (
kubetesting "k8s.io/kubernetes/pkg/kubelet/container/testing"
"k8s.io/kubernetes/pkg/kubelet/lifecycle"
"k8s.io/kubernetes/pkg/kubelet/network"
"k8s.io/kubernetes/pkg/kubelet/network/kubenet"
"k8s.io/kubernetes/pkg/kubelet/network/mock_network"
"k8s.io/kubernetes/pkg/kubelet/rkt/mock_os"
"k8s.io/kubernetes/pkg/kubelet/types"
@ -75,7 +76,7 @@ func makeRktPod(rktPodState rktapi.PodState,
rktPodID, podUID, podName, podNamespace string, podCreatedAt, podStartedAt int64,
podRestartCount string, appNames, imgIDs, imgNames,
containerHashes []string, appStates []rktapi.AppState,
exitcodes []int32) *rktapi.Pod {
exitcodes []int32, ips map[string]string) *rktapi.Pod {
podManifest := &appcschema.PodManifest{
ACKind: appcschema.PodManifestKind,
@ -149,6 +150,11 @@ func makeRktPod(rktPodState rktapi.PodState,
})
}
var networks []*rktapi.Network
for name, ip := range ips {
networks = append(networks, &rktapi.Network{Name: name, Ipv4: ip})
}
return &rktapi.Pod{
Id: rktPodID,
State: rktPodState,
@ -156,6 +162,7 @@ func makeRktPod(rktPodState rktapi.PodState,
Manifest: mustMarshalPodManifest(podManifest),
StartedAt: podStartedAt,
CreatedAt: podCreatedAt,
Networks: networks,
}
}
@ -357,6 +364,7 @@ func TestGetPods(t *testing.T) {
[]string{"1001", "1002"},
[]rktapi.AppState{rktapi.AppState_APP_STATE_RUNNING, rktapi.AppState_APP_STATE_EXITED},
[]int32{0, 0},
nil,
),
},
[]*kubecontainer.Pod{
@ -395,6 +403,7 @@ func TestGetPods(t *testing.T) {
[]string{"1001", "1002"},
[]rktapi.AppState{rktapi.AppState_APP_STATE_RUNNING, rktapi.AppState_APP_STATE_EXITED},
[]int32{0, 0},
nil,
),
makeRktPod(rktapi.PodState_POD_STATE_EXITED,
"uuid-4003", "43", "guestbook", "default",
@ -405,6 +414,7 @@ func TestGetPods(t *testing.T) {
[]string{"10011", "10022"},
[]rktapi.AppState{rktapi.AppState_APP_STATE_EXITED, rktapi.AppState_APP_STATE_EXITED},
[]int32{0, 0},
nil,
),
makeRktPod(rktapi.PodState_POD_STATE_EXITED,
"uuid-4004", "43", "guestbook", "default",
@ -415,6 +425,7 @@ func TestGetPods(t *testing.T) {
[]string{"10011", "10022"},
[]rktapi.AppState{rktapi.AppState_APP_STATE_RUNNING, rktapi.AppState_APP_STATE_RUNNING},
[]int32{0, 0},
nil,
),
},
[]*kubecontainer.Pod{
@ -560,16 +571,19 @@ func TestGetPodStatus(t *testing.T) {
}
tests := []struct {
pods []*rktapi.Pod
result *kubecontainer.PodStatus
networkPluginName string
pods []*rktapi.Pod
result *kubecontainer.PodStatus
}{
// No pods.
// # case 0, No pods.
{
kubenet.KubenetPluginName,
nil,
&kubecontainer.PodStatus{ID: "42", Name: "guestbook", Namespace: "default"},
},
// One pod.
// # case 1, One pod.
{
kubenet.KubenetPluginName,
[]*rktapi.Pod{
makeRktPod(rktapi.PodState_POD_STATE_RUNNING,
"uuid-4002", "42", "guestbook", "default",
@ -580,6 +594,7 @@ func TestGetPodStatus(t *testing.T) {
[]string{"1001", "1002"},
[]rktapi.AppState{rktapi.AppState_APP_STATE_RUNNING, rktapi.AppState_APP_STATE_EXITED},
[]int32{0, 0},
nil,
),
},
&kubecontainer.PodStatus{
@ -616,8 +631,59 @@ func TestGetPodStatus(t *testing.T) {
},
},
},
// Multiple pods.
// # case 2, One pod with no-op network plugin name.
{
network.DefaultPluginName,
[]*rktapi.Pod{
makeRktPod(rktapi.PodState_POD_STATE_RUNNING,
"uuid-4002", "42", "guestbook", "default",
ns(10), ns(20), "7",
[]string{"app-1", "app-2"},
[]string{"img-id-1", "img-id-2"},
[]string{"img-name-1", "img-name-2"},
[]string{"1001", "1002"},
[]rktapi.AppState{rktapi.AppState_APP_STATE_RUNNING, rktapi.AppState_APP_STATE_EXITED},
[]int32{0, 0},
map[string]string{defaultNetworkName: "10.10.10.22"},
),
},
&kubecontainer.PodStatus{
ID: "42",
Name: "guestbook",
Namespace: "default",
IP: "10.10.10.22",
ContainerStatuses: []*kubecontainer.ContainerStatus{
{
ID: kubecontainer.BuildContainerID("rkt", "uuid-4002:app-1"),
Name: "app-1",
State: kubecontainer.ContainerStateRunning,
CreatedAt: time.Unix(10, 0),
StartedAt: time.Unix(20, 0),
FinishedAt: time.Unix(0, 30),
Image: "img-name-1:latest",
ImageID: "rkt://img-id-1",
Hash: 1001,
RestartCount: 7,
},
{
ID: kubecontainer.BuildContainerID("rkt", "uuid-4002:app-2"),
Name: "app-2",
State: kubecontainer.ContainerStateExited,
CreatedAt: time.Unix(10, 0),
StartedAt: time.Unix(20, 0),
FinishedAt: time.Unix(0, 30),
Image: "img-name-2:latest",
ImageID: "rkt://img-id-2",
Hash: 1002,
RestartCount: 7,
Reason: "Completed",
},
},
},
},
// # case 3, Multiple pods.
{
kubenet.KubenetPluginName,
[]*rktapi.Pod{
makeRktPod(rktapi.PodState_POD_STATE_EXITED,
"uuid-4002", "42", "guestbook", "default",
@ -628,6 +694,7 @@ func TestGetPodStatus(t *testing.T) {
[]string{"1001", "1002"},
[]rktapi.AppState{rktapi.AppState_APP_STATE_RUNNING, rktapi.AppState_APP_STATE_EXITED},
[]int32{0, 0},
nil,
),
makeRktPod(rktapi.PodState_POD_STATE_RUNNING, // The latest pod is running.
"uuid-4003", "42", "guestbook", "default",
@ -638,6 +705,7 @@ func TestGetPodStatus(t *testing.T) {
[]string{"1001", "1002"},
[]rktapi.AppState{rktapi.AppState_APP_STATE_RUNNING, rktapi.AppState_APP_STATE_EXITED},
[]int32{0, 1},
nil,
),
},
&kubecontainer.PodStatus{
@ -721,13 +789,16 @@ func TestGetPodStatus(t *testing.T) {
mockFI.EXPECT().ModTime().Return(podTime)
return mockFI, nil
}
fnp.EXPECT().Name().Return(tt.networkPluginName)
if tt.result.IP != "" {
fnp.EXPECT().GetPodNetworkStatus("default", "guestbook", kubecontainer.ContainerID{ID: "42"}).
Return(&network.PodNetworkStatus{IP: net.ParseIP(tt.result.IP)}, nil)
} else {
fnp.EXPECT().GetPodNetworkStatus("default", "guestbook", kubecontainer.ContainerID{ID: "42"}).
Return(nil, fmt.Errorf("no such network"))
if tt.networkPluginName == kubenet.KubenetPluginName {
if tt.result.IP != "" {
fnp.EXPECT().GetPodNetworkStatus("default", "guestbook", kubecontainer.ContainerID{ID: "42"}).
Return(&network.PodNetworkStatus{IP: net.ParseIP(tt.result.IP)}, nil)
} else {
fnp.EXPECT().GetPodNetworkStatus("default", "guestbook", kubecontainer.ContainerID{ID: "42"}).
Return(nil, fmt.Errorf("no such network"))
}
}
status, err := r.GetPodStatus("42", "guestbook", "default")
@ -1070,9 +1141,10 @@ func TestSetApp(t *testing.T) {
func TestGenerateRunCommand(t *testing.T) {
hostName := "test-hostname"
tests := []struct {
pod *api.Pod
uuid string
netnsName string
networkPlugin network.NetworkPlugin
pod *api.Pod
uuid string
netnsName string
dnsServers []string
dnsSearches []string
@ -1083,6 +1155,7 @@ func TestGenerateRunCommand(t *testing.T) {
}{
// Case #0, returns error.
{
kubenet.NewPlugin("/tmp"),
&api.Pod{
ObjectMeta: api.ObjectMeta{
Name: "pod-name-foo",
@ -1099,6 +1172,7 @@ func TestGenerateRunCommand(t *testing.T) {
},
// Case #1, returns no dns, with private-net.
{
kubenet.NewPlugin("/tmp"),
&api.Pod{
ObjectMeta: api.ObjectMeta{
Name: "pod-name-foo",
@ -1110,10 +1184,11 @@ func TestGenerateRunCommand(t *testing.T) {
[]string{},
"pod-hostname-foo",
nil,
" --net=/var/run/netns/default -- /bin/rkt/rkt --insecure-options=image,ondisk --local-config=/var/rkt/local/data --dir=/var/data run-prepared --net=host --hostname=pod-hostname-foo rkt-uuid-foo",
"/usr/bin/nsenter --net=/var/run/netns/default -- /bin/rkt/rkt --insecure-options=image,ondisk --local-config=/var/rkt/local/data --dir=/var/data run-prepared --net=host --hostname=pod-hostname-foo rkt-uuid-foo",
},
// Case #2, returns no dns, with host-net.
{
kubenet.NewPlugin("/tmp"),
&api.Pod{
ObjectMeta: api.ObjectMeta{
Name: "pod-name-foo",
@ -1134,6 +1209,7 @@ func TestGenerateRunCommand(t *testing.T) {
},
// Case #3, returns dns, dns searches, with private-net.
{
kubenet.NewPlugin("/tmp"),
&api.Pod{
ObjectMeta: api.ObjectMeta{
Name: "pod-name-foo",
@ -1150,10 +1226,11 @@ func TestGenerateRunCommand(t *testing.T) {
[]string{"."},
"pod-hostname-foo",
nil,
" --net=/var/run/netns/default -- /bin/rkt/rkt --insecure-options=image,ondisk --local-config=/var/rkt/local/data --dir=/var/data run-prepared --net=host --dns=127.0.0.1 --dns-search=. --dns-opt=ndots:5 --hostname=pod-hostname-foo rkt-uuid-foo",
"/usr/bin/nsenter --net=/var/run/netns/default -- /bin/rkt/rkt --insecure-options=image,ondisk --local-config=/var/rkt/local/data --dir=/var/data run-prepared --net=host --dns=127.0.0.1 --dns-search=. --dns-opt=ndots:5 --hostname=pod-hostname-foo rkt-uuid-foo",
},
// Case #4, returns no dns, dns searches, with host-network.
{
kubenet.NewPlugin("/tmp"),
&api.Pod{
ObjectMeta: api.ObjectMeta{
Name: "pod-name-foo",
@ -1172,10 +1249,28 @@ func TestGenerateRunCommand(t *testing.T) {
nil,
fmt.Sprintf("/bin/rkt/rkt --insecure-options=image,ondisk --local-config=/var/rkt/local/data --dir=/var/data run-prepared --net=host --hostname=%s rkt-uuid-foo", hostName),
},
// Case #5, with no-op plugin, returns --net=rkt.kubernetes.io, with dns and dns search.
{
&network.NoopNetworkPlugin{},
&api.Pod{
ObjectMeta: api.ObjectMeta{
Name: "pod-name-foo",
},
Spec: api.PodSpec{},
},
"rkt-uuid-foo",
"default",
[]string{"127.0.0.1"},
[]string{"."},
"pod-hostname-foo",
nil,
"/bin/rkt/rkt --insecure-options=image,ondisk --local-config=/var/rkt/local/data --dir=/var/data run-prepared --net=rkt.kubernetes.io --dns=127.0.0.1 --dns-search=. --dns-opt=ndots:5 --hostname=pod-hostname-foo rkt-uuid-foo",
},
}
rkt := &Runtime{
os: &kubetesting.FakeOS{HostName: hostName},
nsenterPath: "/usr/bin/nsenter",
os: &kubetesting.FakeOS{HostName: hostName},
config: &Config{
Path: "/bin/rkt/rkt",
Stage1Image: "/bin/rkt/stage1-coreos.aci",
@ -1187,6 +1282,7 @@ func TestGenerateRunCommand(t *testing.T) {
for i, tt := range tests {
testCaseHint := fmt.Sprintf("test case #%d", i)
rkt.networkPlugin = tt.networkPlugin
rkt.runtimeHelper = &fakeRuntimeHelper{tt.dnsServers, tt.dnsSearches, tt.hostName, "", tt.err}
rkt.execer = &utilexec.FakeExec{CommandScript: []utilexec.FakeCommandAction{func(cmd string, args ...string) utilexec.Cmd {
return utilexec.InitFakeCmd(&utilexec.FakeCmd{}, cmd, args...)