func TestStaticPodValidator(t *testing.T) { // test within limits tests := []struct { // given pods <-chan *api.Pod // wants podcount int cputot float64 memtot float64 }{ // test: valid, pod specifies limits for ALL containers { pods: pods(pod( podName("foo", "bar"), containers( container(resourceLimits(10, 20)), // min is 32 container(resourceLimits(30, 40)), container(resourceLimits(50, 60)), ), )), podcount: 1, cputot: 90, memtot: 132, }, // test: valid, multiple pods, specify limits for ALL containers { pods: pods( pod( podName("foo", "bar"), containers( container(resourceLimits(10, 20)), // min is 32 container(resourceLimits(30, 40)), container(resourceLimits(50, 60)), ), ), pod( podName("kjh", "jkk"), containers( container(resourceLimits(15, 25)), // min is 32 container(resourceLimits(35, 45)), container(resourceLimits(55, 65)), ), ), ), podcount: 2, cputot: 195, memtot: 274, }, // test: no limits on CT in first pod so it's rejected { pods: pods( pod( podName("foo", "bar"), containers( container(resourceLimits(10, 20)), // min is 32 container(), // min is 0.01, 32 container(resourceLimits(50, 60)), ), ), pod( podName("wza", "wer"), containers( container(resourceLimits(10, 20)), // min is 32 container(resourceLimits(30, 40)), container(resourceLimits(50, 60)), ), ), ), podcount: 2, cputot: 60.01 + 90, memtot: 124 + 132, }, } for i, tc := range tests { var cpu, mem float64 f := service.StaticPodValidator(0, 0, &cpu, &mem) list := podutil.List(f.Do(tc.pods)) assert.Equal(t, tc.podcount, len(list.Items), "test case #%d: expected %d pods instead of %d", i, tc.podcount, len(list.Items)) assert.EqualValues(t, tc.cputot, cpu, "test case #%d: expected %f total cpu instead of %f", i, tc.cputot, cpu) assert.EqualValues(t, tc.memtot, mem, "test case #%d: expected %f total mem instead of %f", i, tc.memtot, mem) } }
// TestExecutorStaticPods test that the ExecutorInfo.data is parsed // as a zip archive with pod definitions. func TestExecutorInitializeStaticPodsSource(t *testing.T) { // create some zip with static pod definition givenPodsDir, err := ioutil.TempDir("/tmp", "executor-givenpods") assert.NoError(t, err) defer os.RemoveAll(givenPodsDir) var wg sync.WaitGroup reportErrors := func(errCh <-chan error) { wg.Add(1) go func() { defer wg.Done() for err := range errCh { t.Error(err) } }() } createStaticPodFile := func(fileName, name string) { spod := `{ "apiVersion": "v1", "kind": "Pod", "metadata": { "name": "%v", "namespace": "staticpods", "labels": { "name": "foo", "cluster": "bar" } }, "spec": { "containers": [{ "name": "%v", "image": "library/nginx", "ports": [{ "containerPort": 80, "name": "http" }] }] } }` destfile := filepath.Join(givenPodsDir, fileName) err = os.MkdirAll(filepath.Dir(destfile), 0770) assert.NoError(t, err) err = ioutil.WriteFile(destfile, []byte(fmt.Sprintf(spod, name, name)), 0660) assert.NoError(t, err) } createStaticPodFile("spod.json", "spod-01") createStaticPodFile("spod2.json", "spod-02") createStaticPodFile("dir/spod.json", "spod-03") // same file name as first one to check for overwriting staticpods, errs := podutil.ReadFromDir(givenPodsDir) reportErrors(errs) gzipped, err := podutil.Gzip(staticpods) assert.NoError(t, err) expectedStaticPodsNum := 2 // subdirectories are ignored by FileSource, hence only 2 // temporary directory which is normally located in the executor sandbox staticPodsConfigPath, err := ioutil.TempDir("/tmp", "executor-k8sm-archive") assert.NoError(t, err) defer os.RemoveAll(staticPodsConfigPath) executor := &Executor{ staticPodsConfigPath: staticPodsConfigPath, } // extract the pods into staticPodsConfigPath hostname := "h1" err = executor.initializeStaticPodsSource(hostname, gzipped) assert.NoError(t, err) actualpods, errs := podutil.ReadFromDir(staticPodsConfigPath) reportErrors(errs) list := podutil.List(actualpods) assert.NotNil(t, list) assert.Equal(t, expectedStaticPodsNum, len(list.Items)) wg.Wait() }