package integration import ( "testing" kapi "k8s.io/kubernetes/pkg/api" kapierrors "k8s.io/kubernetes/pkg/api/errors" "k8s.io/kubernetes/pkg/api/unversioned" "k8s.io/kubernetes/pkg/apis/batch" "k8s.io/kubernetes/pkg/apis/extensions" kclientset "k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset" "github.com/openshift/origin/pkg/client" policy "github.com/openshift/origin/pkg/cmd/admin/policy" configapi "github.com/openshift/origin/pkg/cmd/server/api" "github.com/openshift/origin/pkg/cmd/server/bootstrappolicy" deployapi "github.com/openshift/origin/pkg/deploy/api" pluginapi "github.com/openshift/origin/pkg/scheduler/admission/podnodeconstraints/api" testutil "github.com/openshift/origin/test/util" testserver "github.com/openshift/origin/test/util/server" ) func TestPodNodeConstraintsAdmissionPluginSetNodeNameClusterAdmin(t *testing.T) { defer testutil.DumpEtcdOnFailure(t) oclient, kclientset := setupClusterAdminPodNodeConstraintsTest(t, &pluginapi.PodNodeConstraintsConfig{}) testPodNodeConstraintsObjectCreationWithPodTemplate(t, "set node name, cluster admin", kclientset, oclient, "nodename.example.com", nil, false) } func TestPodNodeConstraintsAdmissionPluginSetNodeNameNonAdmin(t *testing.T) { defer testutil.DumpEtcdOnFailure(t) config := &pluginapi.PodNodeConstraintsConfig{} oclient, kclientset := setupUserPodNodeConstraintsTest(t, config, "derples") testPodNodeConstraintsObjectCreationWithPodTemplate(t, "set node name, regular user", kclientset, oclient, "nodename.example.com", nil, true) } func TestPodNodeConstraintsAdmissionPluginSetNodeSelectorClusterAdmin(t *testing.T) { defer testutil.DumpEtcdOnFailure(t) config := &pluginapi.PodNodeConstraintsConfig{ NodeSelectorLabelBlacklist: []string{"hostname"}, } oclient, kclientset := setupClusterAdminPodNodeConstraintsTest(t, config) testPodNodeConstraintsObjectCreationWithPodTemplate(t, "set node selector, cluster admin", kclientset, oclient, "", map[string]string{"hostname": "foo"}, false) } func TestPodNodeConstraintsAdmissionPluginSetNodeSelectorNonAdmin(t *testing.T) { defer testutil.DumpEtcdOnFailure(t) config := &pluginapi.PodNodeConstraintsConfig{ NodeSelectorLabelBlacklist: []string{"hostname"}, } oclient, kclientset := setupUserPodNodeConstraintsTest(t, config, "derples") testPodNodeConstraintsObjectCreationWithPodTemplate(t, "set node selector, regular user", kclientset, oclient, "", map[string]string{"hostname": "foo"}, true) } func setupClusterAdminPodNodeConstraintsTest(t *testing.T, pluginConfig *pluginapi.PodNodeConstraintsConfig) (*client.Client, *kclientset.Clientset) { testutil.RequireEtcd(t) masterConfig, err := testserver.DefaultMasterOptions() if err != nil { t.Fatalf("error creating config: %v", err) } cfg := map[string]configapi.AdmissionPluginConfig{ "PodNodeConstraints": { Configuration: pluginConfig, }, } masterConfig.AdmissionConfig.PluginConfig = cfg masterConfig.KubernetesMasterConfig.AdmissionConfig.PluginConfig = cfg kubeConfigFile, err := testserver.StartConfiguredMaster(masterConfig) if err != nil { t.Fatalf("error starting server: %v", err) } kubeClientset, err := testutil.GetClusterAdminKubeClient(kubeConfigFile) if err != nil { t.Fatalf("error getting client: %v", err) } openShiftClient, err := testutil.GetClusterAdminClient(kubeConfigFile) if err != nil { t.Fatalf("error getting client: %v", err) } ns := &kapi.Namespace{} ns.Name = testutil.Namespace() _, err = kubeClientset.Core().Namespaces().Create(ns) if err != nil { t.Fatalf("error creating namespace: %v", err) } if err := testserver.WaitForPodCreationServiceAccounts(kubeClientset, testutil.Namespace()); err != nil { t.Fatalf("unexpected error: %v", err) } return openShiftClient, kubeClientset } func setupUserPodNodeConstraintsTest(t *testing.T, pluginConfig *pluginapi.PodNodeConstraintsConfig, user string) (*client.Client, *kclientset.Clientset) { testutil.RequireEtcd(t) masterConfig, err := testserver.DefaultMasterOptions() if err != nil { t.Fatalf("error creating config: %v", err) } cfg := map[string]configapi.AdmissionPluginConfig{ "PodNodeConstraints": { Configuration: pluginConfig, }, } masterConfig.AdmissionConfig.PluginConfig = cfg masterConfig.KubernetesMasterConfig.AdmissionConfig.PluginConfig = cfg kubeConfigFile, err := testserver.StartConfiguredMaster(masterConfig) if err != nil { t.Fatalf("error starting server: %v", err) } clusterAdminClient, err := testutil.GetClusterAdminClient(kubeConfigFile) if err != nil { t.Fatalf("unexpected error: %v", err) } clusterAdminClientConfig, err := testutil.GetClusterAdminClientConfig(kubeConfigFile) if err != nil { t.Fatalf("unexpected error: %v", err) } userClient, userkubeClientset, _, err := testutil.GetClientForUser(*clusterAdminClientConfig, user) if err != nil { t.Fatalf("error getting user/kube client: %v", err) } kubeClientset, err := testutil.GetClusterAdminKubeClient(kubeConfigFile) if err != nil { t.Fatalf("error getting kube client: %v", err) } ns := &kapi.Namespace{} ns.Name = testutil.Namespace() _, err = kubeClientset.Core().Namespaces().Create(ns) if err != nil { t.Fatalf("error creating namespace: %v", err) } if err := testserver.WaitForServiceAccounts(kubeClientset, testutil.Namespace(), []string{bootstrappolicy.DefaultServiceAccountName}); err != nil { t.Fatalf("unexpected error: %v", err) } addUser := &policy.RoleModificationOptions{ RoleNamespace: ns.Name, RoleName: bootstrappolicy.AdminRoleName, RoleBindingAccessor: policy.NewClusterRoleBindingAccessor(clusterAdminClient), Users: []string{user}, } if err := addUser.AddRole(); err != nil { t.Fatalf("unexpected error: %v", err) } return userClient, userkubeClientset } func testPodNodeConstraintsPodSpec(nodeName string, nodeSelector map[string]string) kapi.PodSpec { spec := kapi.PodSpec{} spec.RestartPolicy = kapi.RestartPolicyAlways spec.NodeName = nodeName spec.NodeSelector = nodeSelector spec.Containers = []kapi.Container{ { Name: "container", Image: "test/image", }, } return spec } func testPodNodeConstraintsPod(nodeName string, nodeSelector map[string]string) *kapi.Pod { pod := &kapi.Pod{} pod.Name = "testpod" pod.Spec = testPodNodeConstraintsPodSpec(nodeName, nodeSelector) return pod } func testPodNodeConstraintsReplicationController(nodeName string, nodeSelector map[string]string) *kapi.ReplicationController { rc := &kapi.ReplicationController{} rc.Name = "testrc" rc.Spec.Replicas = 1 rc.Spec.Selector = map[string]string{"foo": "bar"} rc.Spec.Template = &kapi.PodTemplateSpec{} rc.Spec.Template.Labels = map[string]string{"foo": "bar"} rc.Spec.Template.Spec = testPodNodeConstraintsPodSpec(nodeName, nodeSelector) return rc } func testPodNodeConstraintsDeployment(nodeName string, nodeSelector map[string]string) *extensions.Deployment { d := &extensions.Deployment{} d.Name = "testdeployment" d.Spec.Replicas = 1 d.Spec.Template.Labels = map[string]string{"foo": "bar"} d.Spec.Template.Spec = testPodNodeConstraintsPodSpec(nodeName, nodeSelector) d.Spec.Selector = &unversioned.LabelSelector{ MatchLabels: map[string]string{"foo": "bar"}, } return d } func testPodNodeConstraintsReplicaSet(nodeName string, nodeSelector map[string]string) *extensions.ReplicaSet { rs := &extensions.ReplicaSet{} rs.Name = "testrs" rs.Spec.Replicas = 1 rs.Spec.Template = kapi.PodTemplateSpec{} rs.Spec.Template.Labels = map[string]string{"foo": "bar"} rs.Spec.Template.Spec = testPodNodeConstraintsPodSpec(nodeName, nodeSelector) rs.Spec.Selector = &unversioned.LabelSelector{ MatchLabels: map[string]string{"foo": "bar"}, } return rs } func testPodNodeConstraintsJob(nodeName string, nodeSelector map[string]string) *batch.Job { job := &batch.Job{} job.Name = "testjob" job.Spec.Template.Labels = map[string]string{"foo": "bar"} job.Spec.Template.Spec = testPodNodeConstraintsPodSpec(nodeName, nodeSelector) job.Spec.Template.Spec.RestartPolicy = kapi.RestartPolicyNever // Matching selector is now generated automatically // job.Spec.Selector = ... return job } func testPodNodeConstraintsDeploymentConfig(nodeName string, nodeSelector map[string]string) *deployapi.DeploymentConfig { dc := &deployapi.DeploymentConfig{} dc.Name = "testdc" dc.Spec.Replicas = 1 dc.Spec.Template = &kapi.PodTemplateSpec{} dc.Spec.Template.Labels = map[string]string{"foo": "bar"} dc.Spec.Template.Spec = testPodNodeConstraintsPodSpec(nodeName, nodeSelector) dc.Spec.Selector = map[string]string{"foo": "bar"} return dc } // testPodNodeConstraintsObjectCreationWithPodTemplate attemps to create different object types that contain pod templates // using the passed in nodeName and nodeSelector. It will use the expectError flag to determine if an error should be returned or not func testPodNodeConstraintsObjectCreationWithPodTemplate(t *testing.T, name string, kclientset kclientset.Interface, client client.Interface, nodeName string, nodeSelector map[string]string, expectError bool) { checkForbiddenErr := func(objType string, err error) { if err == nil && expectError { t.Errorf("%s (%s): expected forbidden error but did not receive one", name, objType) return } if err != nil && !expectError { t.Errorf("%s (%s): got error but did not expect one: %v", name, objType, err) return } if err != nil && expectError && !kapierrors.IsForbidden(err) { t.Errorf("%s (%s): did not get an expected forbidden error: %v", name, objType, err) return } } // Pod pod := testPodNodeConstraintsPod(nodeName, nodeSelector) _, err := kclientset.Core().Pods(testutil.Namespace()).Create(pod) checkForbiddenErr("pod", err) // ReplicationController rc := testPodNodeConstraintsReplicationController(nodeName, nodeSelector) _, err = kclientset.Core().ReplicationControllers(testutil.Namespace()).Create(rc) checkForbiddenErr("rc", err) // TODO: Enable when the deployments endpoint is supported in Origin // Deployment // d := testPodNodeConstraintsDeployment(nodeName, nodeSelector) // _, err = kclientset.Extensions().Deployments(testutil.Namespace()).Create(d) // checkForbiddenErr("deployment", err) // ReplicaSet rs := testPodNodeConstraintsReplicaSet(nodeName, nodeSelector) _, err = kclientset.Extensions().ReplicaSets(testutil.Namespace()).Create(rs) checkForbiddenErr("replicaset", err) // Job job := testPodNodeConstraintsJob(nodeName, nodeSelector) _, err = kclientset.Batch().Jobs(testutil.Namespace()).Create(job) checkForbiddenErr("job", err) // DeploymentConfig dc := testPodNodeConstraintsDeploymentConfig(nodeName, nodeSelector) _, err = client.DeploymentConfigs(testutil.Namespace()).Create(dc) checkForbiddenErr("dc", err) }