func newTestController(kubeClient clientset.Interface, volumeSource, claimSource, classSource cache.ListerWatcher, enableDynamicProvisioning bool) *PersistentVolumeController { if volumeSource == nil { volumeSource = fcache.NewFakePVControllerSource() } if claimSource == nil { claimSource = fcache.NewFakePVCControllerSource() } if classSource == nil { classSource = fcache.NewFakeControllerSource() } params := ControllerParameters{ KubeClient: kubeClient, SyncPeriod: 5 * time.Second, VolumePlugins: []vol.VolumePlugin{}, VolumeSource: volumeSource, ClaimSource: claimSource, ClassSource: classSource, EventRecorder: record.NewFakeRecorder(1000), EnableDynamicProvisioning: enableDynamicProvisioning, } ctrl := NewController(params) // Speed up the test ctrl.createProvisionedPVInterval = 5 * time.Millisecond return ctrl }
func newTestController(kubeClient clientset.Interface, volumeSource, claimSource, classSource cache.ListerWatcher, enableDynamicProvisioning bool) *PersistentVolumeController { if volumeSource == nil { volumeSource = framework.NewFakePVControllerSource() } if claimSource == nil { claimSource = framework.NewFakePVCControllerSource() } if classSource == nil { classSource = framework.NewFakeControllerSource() } ctrl := NewPersistentVolumeController( kubeClient, 5*time.Second, // sync period nil, // alpha provisioner []vol.VolumePlugin{}, // recyclers nil, // cloud "", volumeSource, claimSource, classSource, record.NewFakeRecorder(1000), // event recorder enableDynamicProvisioning, ) // Speed up the test ctrl.createProvisionedPVInterval = 5 * time.Millisecond return ctrl }
func TestCreateAppArmorContanier(t *testing.T) { dm, fakeDocker := newTestDockerManagerWithVersion("1.11.1", "1.23") // We want to capture events. recorder := record.NewFakeRecorder(20) dm.recorder = recorder pod := &v1.Pod{ ObjectMeta: metav1.ObjectMeta{ UID: "12345678", Name: "foo", Namespace: "new", Annotations: map[string]string{ apparmor.ContainerAnnotationKeyPrefix + "test": apparmor.ProfileNamePrefix + "test-profile", }, }, Spec: v1.PodSpec{ Containers: []v1.Container{ {Name: "test"}, }, }, } runSyncPod(t, dm, fakeDocker, pod, nil, false) verifyCalls(t, fakeDocker, []string{ // Create pod infra container. "create", "start", "inspect_container", "inspect_container", // Create container. "create", "start", "inspect_container", }) fakeDocker.Lock() if len(fakeDocker.Created) != 2 || !matchString(t, "/k8s_POD\\.[a-f0-9]+_foo_new_", fakeDocker.Created[0]) || !matchString(t, "/k8s_test\\.[a-f0-9]+_foo_new_", fakeDocker.Created[1]) { t.Errorf("unexpected containers created %v", fakeDocker.Created) } fakeDocker.Unlock() // Verify security opts. newContainer, err := fakeDocker.InspectContainer(fakeDocker.Created[1]) if err != nil { t.Fatalf("unexpected error %v", err) } securityOpts := newContainer.HostConfig.SecurityOpt assert.Contains(t, securityOpts, "apparmor=test-profile", "Container should have apparmor security opt") cid := utilstrings.ShortenString(fakeDocker.Created[1], 12) assert.NoError(t, expectEvent(recorder, v1.EventTypeNormal, events.CreatedContainer, fmt.Sprintf("Created container with docker id %s; Security:[seccomp=unconfined apparmor=test-profile]", cid))) }
func TestSeccompIsUnconfinedByDefaultWithDockerV110(t *testing.T) { dm, fakeDocker := newTestDockerManagerWithVersion("1.10.1", "1.22") // We want to capture events. recorder := record.NewFakeRecorder(20) dm.recorder = recorder pod := makePod("foo", &v1.PodSpec{ Containers: []v1.Container{ {Name: "bar"}, }, }) runSyncPod(t, dm, fakeDocker, pod, nil, false) verifyCalls(t, fakeDocker, []string{ // Create pod infra container. "create", "start", "inspect_container", "inspect_container", // Create container. "create", "start", "inspect_container", }) fakeDocker.Lock() if len(fakeDocker.Created) != 2 || !matchString(t, "/k8s_POD\\.[a-f0-9]+_foo_new_", fakeDocker.Created[0]) || !matchString(t, "/k8s_bar\\.[a-f0-9]+_foo_new_", fakeDocker.Created[1]) { t.Errorf("unexpected containers created %v", fakeDocker.Created) } fakeDocker.Unlock() newContainer, err := fakeDocker.InspectContainer(fakeDocker.Created[1]) if err != nil { t.Fatalf("unexpected error %v", err) } assert.Contains(t, newContainer.HostConfig.SecurityOpt, "seccomp:unconfined", "Pods with Docker versions >= 1.10 must not have seccomp disabled by default") cid := utilstrings.ShortenString(fakeDocker.Created[1], 12) assert.NoError(t, expectEvent(recorder, v1.EventTypeNormal, events.CreatedContainer, fmt.Sprintf("Created container with docker id %s; Security:[seccomp=unconfined]", cid))) }
// TestSyncOne_Status tests sj.UpdateStatus in SyncOne func TestSyncOne_Status(t *testing.T) { finishedJob := newJob("1") finishedJob.Status.Conditions = append(finishedJob.Status.Conditions, batch.JobCondition{Type: batch.JobComplete, Status: v1.ConditionTrue}) unexpectedJob := newJob("2") testCases := map[string]struct { // sj spec concurrencyPolicy batch.ConcurrencyPolicy suspend bool schedule string deadline int64 // sj status ranPreviously bool hasFinishedJob bool // environment now time.Time hasUnexpectedJob bool // expectations expectCreate bool expectDelete bool }{ "never ran, not time, A": {A, F, onTheHour, noDead, F, F, justBeforeTheHour(), F, F, F}, "never ran, not time, F": {f, F, onTheHour, noDead, F, F, justBeforeTheHour(), F, F, F}, "never ran, not time, R": {R, F, onTheHour, noDead, F, F, justBeforeTheHour(), F, F, F}, "never ran, is time, A": {A, F, onTheHour, noDead, F, F, justAfterTheHour(), F, T, F}, "never ran, is time, F": {f, F, onTheHour, noDead, F, F, justAfterTheHour(), F, T, F}, "never ran, is time, R": {R, F, onTheHour, noDead, F, F, justAfterTheHour(), F, T, F}, "never ran, is time, suspended": {A, T, onTheHour, noDead, F, F, justAfterTheHour(), F, F, F}, "never ran, is time, past deadline": {A, F, onTheHour, shortDead, F, F, justAfterTheHour(), F, F, F}, "never ran, is time, not past deadline": {A, F, onTheHour, longDead, F, F, justAfterTheHour(), F, T, F}, "prev ran but done, not time, A": {A, F, onTheHour, noDead, T, F, justBeforeTheHour(), F, F, F}, "prev ran but done, not time, finished job, A": {A, F, onTheHour, noDead, T, T, justBeforeTheHour(), F, F, F}, "prev ran but done, not time, unexpected job, A": {A, F, onTheHour, noDead, T, F, justBeforeTheHour(), T, F, F}, "prev ran but done, not time, finished job, unexpected job, A": {A, F, onTheHour, noDead, T, T, justBeforeTheHour(), T, F, F}, "prev ran but done, not time, finished job, F": {f, F, onTheHour, noDead, T, T, justBeforeTheHour(), F, F, F}, "prev ran but done, not time, unexpected job, R": {R, F, onTheHour, noDead, T, F, justBeforeTheHour(), T, F, F}, "prev ran but done, is time, A": {A, F, onTheHour, noDead, T, F, justAfterTheHour(), F, T, F}, "prev ran but done, is time, finished job, A": {A, F, onTheHour, noDead, T, T, justAfterTheHour(), F, T, F}, "prev ran but done, is time, unexpected job, A": {A, F, onTheHour, noDead, T, F, justAfterTheHour(), T, T, F}, "prev ran but done, is time, finished job, unexpected job, A": {A, F, onTheHour, noDead, T, T, justAfterTheHour(), T, T, F}, "prev ran but done, is time, F": {f, F, onTheHour, noDead, T, F, justAfterTheHour(), F, T, F}, "prev ran but done, is time, finished job, F": {f, F, onTheHour, noDead, T, T, justAfterTheHour(), F, T, F}, "prev ran but done, is time, unexpected job, F": {f, F, onTheHour, noDead, T, F, justAfterTheHour(), T, T, F}, "prev ran but done, is time, finished job, unexpected job, F": {f, F, onTheHour, noDead, T, T, justAfterTheHour(), T, T, F}, "prev ran but done, is time, R": {R, F, onTheHour, noDead, T, F, justAfterTheHour(), F, T, F}, "prev ran but done, is time, finished job, R": {R, F, onTheHour, noDead, T, T, justAfterTheHour(), F, T, F}, "prev ran but done, is time, unexpected job, R": {R, F, onTheHour, noDead, T, F, justAfterTheHour(), T, T, F}, "prev ran but done, is time, finished job, unexpected job, R": {R, F, onTheHour, noDead, T, T, justAfterTheHour(), T, T, F}, "prev ran but done, is time, suspended": {A, T, onTheHour, noDead, T, F, justAfterTheHour(), F, F, F}, "prev ran but done, is time, finished job, suspended": {A, T, onTheHour, noDead, T, T, justAfterTheHour(), F, F, F}, "prev ran but done, is time, unexpected job, suspended": {A, T, onTheHour, noDead, T, F, justAfterTheHour(), T, F, F}, "prev ran but done, is time, finished job, unexpected job, suspended": {A, T, onTheHour, noDead, T, T, justAfterTheHour(), T, F, F}, "prev ran but done, is time, past deadline": {A, F, onTheHour, shortDead, T, F, justAfterTheHour(), F, F, F}, "prev ran but done, is time, finished job, past deadline": {A, F, onTheHour, shortDead, T, T, justAfterTheHour(), F, F, F}, "prev ran but done, is time, unexpected job, past deadline": {A, F, onTheHour, shortDead, T, F, justAfterTheHour(), T, F, F}, "prev ran but done, is time, finished job, unexpected job, past deadline": {A, F, onTheHour, shortDead, T, T, justAfterTheHour(), T, F, F}, "prev ran but done, is time, not past deadline": {A, F, onTheHour, longDead, T, F, justAfterTheHour(), F, T, F}, "prev ran but done, is time, finished job, not past deadline": {A, F, onTheHour, longDead, T, T, justAfterTheHour(), F, T, F}, "prev ran but done, is time, unexpected job, not past deadline": {A, F, onTheHour, longDead, T, F, justAfterTheHour(), T, T, F}, "prev ran but done, is time, finished job, unexpected job, not past deadline": {A, F, onTheHour, longDead, T, T, justAfterTheHour(), T, T, F}, } for name, tc := range testCases { // Setup the test sj := cronJob() sj.Spec.ConcurrencyPolicy = tc.concurrencyPolicy sj.Spec.Suspend = &tc.suspend sj.Spec.Schedule = tc.schedule if tc.deadline != noDead { sj.Spec.StartingDeadlineSeconds = &tc.deadline } if tc.ranPreviously { sj.ObjectMeta.CreationTimestamp = metav1.Time{Time: justBeforeThePriorHour()} sj.Status.LastScheduleTime = &metav1.Time{Time: justAfterThePriorHour()} } else { if tc.hasFinishedJob || tc.hasUnexpectedJob { t.Errorf("%s: test setup error: this case makes no sense", name) } sj.ObjectMeta.CreationTimestamp = metav1.Time{Time: justBeforeTheHour()} } jobs := []batch.Job{} if tc.hasFinishedJob { ref, err := getRef(&finishedJob) if err != nil { t.Errorf("%s: test setup error: failed to get job's ref: %v.", name, err) } sj.Status.Active = []v1.ObjectReference{*ref} jobs = append(jobs, finishedJob) } if tc.hasUnexpectedJob { jobs = append(jobs, unexpectedJob) } jc := &fakeJobControl{} sjc := &fakeSJControl{} pc := &fakePodControl{} recorder := record.NewFakeRecorder(10) // Run the code SyncOne(sj, jobs, tc.now, jc, sjc, pc, recorder) // Status update happens once when ranging through job list, and another one if create jobs. expectUpdates := 1 // Events happens when there's unexpected / finished jobs, and upon job creation / deletion. expectedEvents := 0 if tc.expectCreate { expectUpdates++ expectedEvents++ } if tc.expectDelete { expectedEvents++ } if tc.hasFinishedJob { expectedEvents++ } if tc.hasUnexpectedJob { expectedEvents++ } if len(recorder.Events) != expectedEvents { t.Errorf("%s: expected %d event, actually %v: %#v", name, expectedEvents, len(recorder.Events), recorder.Events) } if expectUpdates != len(sjc.Updates) { t.Errorf("%s: expected %d status updates, actually %d", name, expectUpdates, len(sjc.Updates)) } if tc.hasFinishedJob && inActiveList(sjc.Updates[0], finishedJob.UID) { t.Errorf("%s: expected finished job removed from active list, actually active list = %#v", name, sjc.Updates[0].Status.Active) } if tc.hasUnexpectedJob && inActiveList(sjc.Updates[0], unexpectedJob.UID) { t.Errorf("%s: expected unexpected job not added to active list, actually active list = %#v", name, sjc.Updates[0].Status.Active) } if tc.expectCreate && !sjc.Updates[1].Status.LastScheduleTime.Time.Equal(topOfTheHour()) { t.Errorf("%s: expected LastScheduleTime updated to %s, got %s", name, topOfTheHour(), sjc.Updates[1].Status.LastScheduleTime) } } }
func TestSyncOne_RunOrNot(t *testing.T) { testCases := map[string]struct { // sj spec concurrencyPolicy batch.ConcurrencyPolicy suspend bool schedule string deadline int64 // sj status ranPreviously bool stillActive bool // environment now time.Time // expectations expectCreate bool expectDelete bool expectActive int }{ "never ran, not time, A": {A, F, onTheHour, noDead, F, F, justBeforeTheHour(), F, F, 0}, "never ran, not time, F": {f, F, onTheHour, noDead, F, F, justBeforeTheHour(), F, F, 0}, "never ran, not time, R": {R, F, onTheHour, noDead, F, F, justBeforeTheHour(), F, F, 0}, "never ran, is time, A": {A, F, onTheHour, noDead, F, F, justAfterTheHour(), T, F, 1}, "never ran, is time, F": {f, F, onTheHour, noDead, F, F, justAfterTheHour(), T, F, 1}, "never ran, is time, R": {R, F, onTheHour, noDead, F, F, justAfterTheHour(), T, F, 1}, "never ran, is time, suspended": {A, T, onTheHour, noDead, F, F, justAfterTheHour(), F, F, 0}, "never ran, is time, past deadline": {A, F, onTheHour, shortDead, F, F, justAfterTheHour(), F, F, 0}, "never ran, is time, not past deadline": {A, F, onTheHour, longDead, F, F, justAfterTheHour(), T, F, 1}, "prev ran but done, not time, A": {A, F, onTheHour, noDead, T, F, justBeforeTheHour(), F, F, 0}, "prev ran but done, not time, F": {f, F, onTheHour, noDead, T, F, justBeforeTheHour(), F, F, 0}, "prev ran but done, not time, R": {R, F, onTheHour, noDead, T, F, justBeforeTheHour(), F, F, 0}, "prev ran but done, is time, A": {A, F, onTheHour, noDead, T, F, justAfterTheHour(), T, F, 1}, "prev ran but done, is time, F": {f, F, onTheHour, noDead, T, F, justAfterTheHour(), T, F, 1}, "prev ran but done, is time, R": {R, F, onTheHour, noDead, T, F, justAfterTheHour(), T, F, 1}, "prev ran but done, is time, suspended": {A, T, onTheHour, noDead, T, F, justAfterTheHour(), F, F, 0}, "prev ran but done, is time, past deadline": {A, F, onTheHour, shortDead, T, F, justAfterTheHour(), F, F, 0}, "prev ran but done, is time, not past deadline": {A, F, onTheHour, longDead, T, F, justAfterTheHour(), T, F, 1}, "still active, not time, A": {A, F, onTheHour, noDead, T, T, justBeforeTheHour(), F, F, 1}, "still active, not time, F": {f, F, onTheHour, noDead, T, T, justBeforeTheHour(), F, F, 1}, "still active, not time, R": {R, F, onTheHour, noDead, T, T, justBeforeTheHour(), F, F, 1}, "still active, is time, A": {A, F, onTheHour, noDead, T, T, justAfterTheHour(), T, F, 2}, "still active, is time, F": {f, F, onTheHour, noDead, T, T, justAfterTheHour(), F, F, 1}, "still active, is time, R": {R, F, onTheHour, noDead, T, T, justAfterTheHour(), T, T, 1}, "still active, is time, suspended": {A, T, onTheHour, noDead, T, T, justAfterTheHour(), F, F, 1}, "still active, is time, past deadline": {A, F, onTheHour, shortDead, T, T, justAfterTheHour(), F, F, 1}, "still active, is time, not past deadline": {A, F, onTheHour, longDead, T, T, justAfterTheHour(), T, F, 2}, } for name, tc := range testCases { sj := cronJob() sj.Spec.ConcurrencyPolicy = tc.concurrencyPolicy sj.Spec.Suspend = &tc.suspend sj.Spec.Schedule = tc.schedule if tc.deadline != noDead { sj.Spec.StartingDeadlineSeconds = &tc.deadline } var ( job *batch.Job err error ) js := []batch.Job{} if tc.ranPreviously { sj.ObjectMeta.CreationTimestamp = metav1.Time{Time: justBeforeThePriorHour()} sj.Status.LastScheduleTime = &metav1.Time{Time: justAfterThePriorHour()} job, err = getJobFromTemplate(&sj, sj.Status.LastScheduleTime.Time) if err != nil { t.Fatalf("%s: nexpected error creating a job from template: %v", name, err) } job.UID = "1234" job.Namespace = "" if tc.stillActive { sj.Status.Active = []v1.ObjectReference{{UID: job.UID}} js = append(js, *job) } } else { sj.ObjectMeta.CreationTimestamp = metav1.Time{Time: justBeforeTheHour()} if tc.stillActive { t.Errorf("%s: test setup error: this case makes no sense", name) } } jc := &fakeJobControl{Job: job} sjc := &fakeSJControl{} pc := &fakePodControl{} recorder := record.NewFakeRecorder(10) SyncOne(sj, js, tc.now, jc, sjc, pc, recorder) expectedCreates := 0 if tc.expectCreate { expectedCreates = 1 } if len(jc.Jobs) != expectedCreates { t.Errorf("%s: expected %d job started, actually %v", name, expectedCreates, len(jc.Jobs)) } expectedDeletes := 0 if tc.expectDelete { expectedDeletes = 1 } if len(jc.DeleteJobName) != expectedDeletes { t.Errorf("%s: expected %d job deleted, actually %v", name, expectedDeletes, len(jc.DeleteJobName)) } // Status update happens once when ranging through job list, and another one if create jobs. expectUpdates := 1 expectedEvents := 0 if tc.expectCreate { expectedEvents++ expectUpdates++ } if tc.expectDelete { expectedEvents++ } if len(recorder.Events) != expectedEvents { t.Errorf("%s: expected %d event, actually %v", name, expectedEvents, len(recorder.Events)) } if tc.expectActive != len(sjc.Updates[expectUpdates-1].Status.Active) { t.Errorf("%s: expected Active size %d, got %d", name, tc.expectActive, len(sjc.Updates[expectUpdates-1].Status.Active)) } } }
func TestComposeDNSSearch(t *testing.T) { testKubelet := newTestKubelet(t, false /* controllerAttachDetachEnabled */) kubelet := testKubelet.kubelet recorder := record.NewFakeRecorder(20) kubelet.recorder = recorder pod := podWithUidNameNs("", "test_pod", "testNS") kubelet.clusterDomain = "TEST" testCases := []struct { dnsNames []string hostNames []string resultSearch []string events []string }{ { []string{"testNS.svc.TEST", "svc.TEST", "TEST"}, []string{}, []string{"testNS.svc.TEST", "svc.TEST", "TEST"}, []string{}, }, { []string{"testNS.svc.TEST", "svc.TEST", "TEST"}, []string{"AAA", "svc.TEST", "BBB", "TEST"}, []string{"testNS.svc.TEST", "svc.TEST", "TEST", "AAA", "BBB"}, []string{ "Found and omitted duplicated dns domain in host search line: 'svc.TEST' during merging with cluster dns domains", "Found and omitted duplicated dns domain in host search line: 'TEST' during merging with cluster dns domains", }, }, { []string{"testNS.svc.TEST", "svc.TEST", "TEST"}, []string{"AAA", strings.Repeat("B", 256), "BBB"}, []string{"testNS.svc.TEST", "svc.TEST", "TEST", "AAA"}, []string{"Search Line limits were exceeded, some dns names have been omitted, the applied search line is: testNS.svc.TEST svc.TEST TEST AAA"}, }, { []string{"testNS.svc.TEST", "svc.TEST", "TEST"}, []string{"AAA", "TEST", "BBB", "TEST", "CCC", "DDD"}, []string{"testNS.svc.TEST", "svc.TEST", "TEST", "AAA", "BBB", "CCC"}, []string{ "Found and omitted duplicated dns domain in host search line: 'TEST' during merging with cluster dns domains", "Found and omitted duplicated dns domain in host search line: 'TEST' during merging with cluster dns domains", "Search Line limits were exceeded, some dns names have been omitted, the applied search line is: testNS.svc.TEST svc.TEST TEST AAA BBB CCC", }, }, } fetchEvent := func(recorder *record.FakeRecorder) string { select { case event := <-recorder.Events: return event default: return "No more events!" } } for i, tc := range testCases { dnsSearch := kubelet.formDNSSearch(tc.hostNames, pod) if !reflect.DeepEqual(dnsSearch, tc.resultSearch) { t.Errorf("[%d] expected search line %#v, got %#v", i, tc.resultSearch, dnsSearch) } for _, expectedEvent := range tc.events { expected := fmt.Sprintf("%s %s %s", v1.EventTypeWarning, "DNSSearchForming", expectedEvent) event := fetchEvent(recorder) if event != expected { t.Errorf("[%d] expected event '%s', got '%s", i, expected, event) } } } }
func TestSyncOne_RunOrNot(t *testing.T) { testCases := map[string]struct { // sj spec concurrencyPolicy batch.ConcurrencyPolicy suspend bool schedule string deadline int64 // sj status ranPreviously bool stillActive bool // environment now time.Time // expectations expectCreate bool expectDelete bool }{ "never ran, not time, A": {A, F, onTheHour, noDead, F, F, justBeforeTheHour(), F, F}, "never ran, not time, F": {f, F, onTheHour, noDead, F, F, justBeforeTheHour(), F, F}, "never ran, not time, R": {R, F, onTheHour, noDead, F, F, justBeforeTheHour(), F, F}, "never ran, is time, A": {A, F, onTheHour, noDead, F, F, justAfterTheHour(), T, F}, "never ran, is time, F": {f, F, onTheHour, noDead, F, F, justAfterTheHour(), T, F}, "never ran, is time, R": {R, F, onTheHour, noDead, F, F, justAfterTheHour(), T, F}, "never ran, is time, suspended": {A, T, onTheHour, noDead, F, F, justAfterTheHour(), F, F}, "never ran, is time, past deadline": {A, F, onTheHour, shortDead, F, F, justAfterTheHour(), F, F}, "never ran, is time, not past deadline": {A, F, onTheHour, longDead, F, F, justAfterTheHour(), T, F}, "prev ran but done, not time, A": {A, F, onTheHour, noDead, T, F, justBeforeTheHour(), F, F}, "prev ran but done, not time, F": {f, F, onTheHour, noDead, T, F, justBeforeTheHour(), F, F}, "prev ran but done, not time, R": {R, F, onTheHour, noDead, T, F, justBeforeTheHour(), F, F}, "prev ran but done, is time, A": {A, F, onTheHour, noDead, T, F, justAfterTheHour(), T, F}, "prev ran but done, is time, F": {f, F, onTheHour, noDead, T, F, justAfterTheHour(), T, F}, "prev ran but done, is time, R": {R, F, onTheHour, noDead, T, F, justAfterTheHour(), T, F}, "prev ran but done, is time, suspended": {A, T, onTheHour, noDead, T, F, justAfterTheHour(), F, F}, "prev ran but done, is time, past deadline": {A, F, onTheHour, shortDead, T, F, justAfterTheHour(), F, F}, "prev ran but done, is time, not past deadline": {A, F, onTheHour, longDead, T, F, justAfterTheHour(), T, F}, "still active, not time, A": {A, F, onTheHour, noDead, T, T, justBeforeTheHour(), F, F}, "still active, not time, F": {f, F, onTheHour, noDead, T, T, justBeforeTheHour(), F, F}, "still active, not time, R": {R, F, onTheHour, noDead, T, T, justBeforeTheHour(), F, F}, "still active, is time, A": {A, F, onTheHour, noDead, T, T, justAfterTheHour(), T, F}, "still active, is time, F": {f, F, onTheHour, noDead, T, T, justAfterTheHour(), F, F}, "still active, is time, R": {R, F, onTheHour, noDead, T, T, justAfterTheHour(), T, T}, "still active, is time, suspended": {A, T, onTheHour, noDead, T, T, justAfterTheHour(), F, F}, "still active, is time, past deadline": {A, F, onTheHour, shortDead, T, T, justAfterTheHour(), F, F}, "still active, is time, not past deadline": {A, F, onTheHour, longDead, T, T, justAfterTheHour(), T, F}, } for name, tc := range testCases { t.Log("Test case:", name) sj := scheduledJob() sj.Spec.ConcurrencyPolicy = tc.concurrencyPolicy sj.Spec.Suspend = &tc.suspend sj.Spec.Schedule = tc.schedule if tc.deadline != noDead { sj.Spec.StartingDeadlineSeconds = &tc.deadline } if tc.ranPreviously { sj.ObjectMeta.CreationTimestamp = unversioned.Time{Time: justBeforeThePriorHour()} sj.Status.LastScheduleTime = &unversioned.Time{Time: justAfterThePriorHour()} if tc.stillActive { sj.Status.Active = []api.ObjectReference{{}} } } else { sj.ObjectMeta.CreationTimestamp = unversioned.Time{Time: justBeforeTheHour()} if tc.stillActive { t.Errorf("Test setup error: this case makes no sense.") } } jc := &fakeJobControl{} sjc := &fakeSJControl{} recorder := record.NewFakeRecorder(10) SyncOne(sj, []batch.Job{}, tc.now, jc, sjc, recorder) expectedCreates := 0 if tc.expectCreate { expectedCreates = 1 } if len(jc.Jobs) != expectedCreates { t.Errorf("Expected %d job started, actually %v", expectedCreates, len(jc.Jobs)) } expectedDeletes := 0 if tc.expectDelete { expectedDeletes = 1 } if len(jc.DeleteJobName) != expectedDeletes { t.Errorf("Expected %d job deleted, actually %v", expectedDeletes, len(jc.DeleteJobName)) } expectedEvents := 0 if tc.expectCreate { expectedEvents += 1 } if tc.expectDelete { expectedEvents += 1 } if len(recorder.Events) != expectedEvents { t.Errorf("Expected %d event, actually %v", expectedEvents, len(recorder.Events)) } } }
func TestSeccompLocalhostProfileIsLoaded(t *testing.T) { tests := []struct { annotations map[string]string expectedSecOpt string expectedSecMsg string expectedError string }{ { annotations: map[string]string{ v1.SeccompPodAnnotationKey: "localhost/test", }, expectedSecOpt: `seccomp={"foo":"bar"}`, expectedSecMsg: "seccomp=test(md5:21aeae45053385adebd25311f9dd9cb1)", }, { annotations: map[string]string{ v1.SeccompPodAnnotationKey: "localhost/sub/subtest", }, expectedSecOpt: `seccomp={"abc":"def"}`, expectedSecMsg: "seccomp=sub/subtest(md5:07c9bcb4db631f7ca191d6e0bca49f76)", }, { annotations: map[string]string{ v1.SeccompPodAnnotationKey: "localhost/not-existing", }, expectedError: "cannot load seccomp profile", }, } for i, test := range tests { dm, fakeDocker := newTestDockerManagerWithVersion("1.11.0", "1.23") // We want to capture events. recorder := record.NewFakeRecorder(20) dm.recorder = recorder dm.seccompProfileRoot = path.Join("fixtures", "seccomp") pod := makePod("foo2", &v1.PodSpec{ Containers: []v1.Container{ {Name: "bar2"}, }, }) pod.Annotations = test.annotations result := runSyncPod(t, dm, fakeDocker, pod, nil, test.expectedError != "") if test.expectedError != "" { assert.Contains(t, result.Error().Error(), test.expectedError) continue } verifyCalls(t, fakeDocker, []string{ // Create pod infra container. "create", "start", "inspect_container", "inspect_container", // Create container. "create", "start", "inspect_container", }) fakeDocker.Lock() if len(fakeDocker.Created) != 2 || !matchString(t, "/k8s_POD\\.[a-f0-9]+_foo2_new_", fakeDocker.Created[0]) || !matchString(t, "/k8s_bar2\\.[a-f0-9]+_foo2_new_", fakeDocker.Created[1]) { t.Errorf("unexpected containers created %v", fakeDocker.Created) } fakeDocker.Unlock() newContainer, err := fakeDocker.InspectContainer(fakeDocker.Created[1]) if err != nil { t.Fatalf("unexpected error %v", err) } assert.Contains(t, newContainer.HostConfig.SecurityOpt, test.expectedSecOpt, "The compacted seccomp json profile should be loaded.") cid := utilstrings.ShortenString(fakeDocker.Created[1], 12) assert.NoError(t, expectEvent(recorder, v1.EventTypeNormal, events.CreatedContainer, fmt.Sprintf("Created container with docker id %s; Security:[%s]", cid, test.expectedSecMsg)), "testcase %d", i) } }