diff --git a/pkg/cmd/server/origin/master.go b/pkg/cmd/server/origin/master.go index 36a0a5d9252f..a5c37ea0ead5 100644 --- a/pkg/cmd/server/origin/master.go +++ b/pkg/cmd/server/origin/master.go @@ -528,8 +528,6 @@ func (c *MasterConfig) Run(protected []APIInstaller, unprotected []APIInstaller) go util.Forever(func() { c.ensureOpenShiftSharedResourcesNamespace() }, 10*time.Second) - - c.checkProjectRequestTemplate() } func (c *MasterConfig) defaultAPIGroupVersion() *apiserver.APIGroupVersion { @@ -586,40 +584,6 @@ func (c *MasterConfig) getRequestContextMapper() kapi.RequestContextMapper { return c.RequestContextMapper } -// checkProjectRequestTemplate looks to see if there should be a projectrequest template. If there should be one and it's not present -func (c *MasterConfig) checkProjectRequestTemplate() { - if len(c.Options.ProjectRequestConfig.ProjectRequestTemplate) == 0 { - return - } - - const baseErrorFormat = "Error creating default project request template %v. Unprivileged project requests will fail until a template is available." - - namespace, templateName, err := configapi.ParseNamespaceAndName(c.Options.ProjectRequestConfig.ProjectRequestTemplate) - if err != nil { - glog.Errorf(baseErrorFormat+" Caused by: %v", c.Options.ProjectRequestConfig.ProjectRequestTemplate, err) - return - } - if len(namespace) == 0 { - glog.Errorf(baseErrorFormat+" The namespace for the project request template may not be empty.", c.Options.ProjectRequestConfig.ProjectRequestTemplate) - return - } - if len(templateName) == 0 { - glog.Errorf(baseErrorFormat+" The name for the project request template may not be empty.", c.Options.ProjectRequestConfig.ProjectRequestTemplate) - return - } - - // if the template already exists, no work to do - if _, err := c.PrivilegedLoopbackOpenShiftClient.Templates(namespace).Get(templateName); err == nil { - return - } - - template := projectrequeststorage.NewSampleTemplate(namespace, templateName) - if _, err := c.PrivilegedLoopbackOpenShiftClient.Templates(namespace).Create(template); err != nil { - glog.Errorf(baseErrorFormat+" Caused by: %v", c.Options.ProjectRequestConfig.ProjectRequestTemplate, err) - return - } -} - // ensureOpenShiftSharedResourcesNamespace is called as part of global policy initialization to ensure shared namespace exists func (c *MasterConfig) ensureOpenShiftSharedResourcesNamespace() { namespace, err := c.KubeClient().Namespaces().Get(c.Options.PolicyConfig.OpenShiftSharedResourcesNamespace) diff --git a/pkg/cmd/server/start/master_args.go b/pkg/cmd/server/start/master_args.go index d8fb2c7c443a..cb8b82eaa367 100644 --- a/pkg/cmd/server/start/master_args.go +++ b/pkg/cmd/server/start/master_args.go @@ -198,9 +198,7 @@ func (args MasterArgs) BuildSerializeableMasterConfig() (*configapi.MasterConfig Latest: args.ImageFormatArgs.ImageTemplate.Latest, }, - ProjectRequestConfig: configapi.ProjectRequestConfig{ - ProjectRequestTemplate: bootstrappolicy.DefaultOpenShiftSharedResourcesNamespace + "/project-request", - }, + ProjectRequestConfig: configapi.ProjectRequestConfig{}, NetworkConfig: configapi.NetworkConfig{ NetworkPluginName: args.NetworkArgs.NetworkPluginName, diff --git a/pkg/project/registry/projectrequest/delegated/delegated.go b/pkg/project/registry/projectrequest/delegated/delegated.go index eba0188ec6e4..57123e231ce6 100644 --- a/pkg/project/registry/projectrequest/delegated/delegated.go +++ b/pkg/project/registry/projectrequest/delegated/delegated.go @@ -20,6 +20,7 @@ import ( configcmd "github.com/openshift/origin/pkg/config/cmd" projectapi "github.com/openshift/origin/pkg/project/api" projectrequestregistry "github.com/openshift/origin/pkg/project/registry/projectrequest" + templateapi "github.com/openshift/origin/pkg/template/api" ) type REST struct { @@ -48,9 +49,6 @@ func (r *REST) NewList() runtime.Object { } func (r *REST) Create(ctx kapi.Context, obj runtime.Object) (runtime.Object, error) { - if len(r.openshiftNamespace) == 0 || len(r.templateName) == 0 { - return nil, errors.New("this endpoint is disabled") - } if err := rest.BeforeCreate(projectrequestregistry.Strategy, ctx, obj); err != nil { return nil, err @@ -78,7 +76,7 @@ func (r *REST) Create(ctx kapi.Context, obj runtime.Object) (runtime.Object, err projectAdmin = userInfo.GetName() } - template, err := r.openshiftClient.Templates(r.openshiftNamespace).Get(r.templateName) + template, err := r.getTemplate() if err != nil { return nil, err } @@ -96,7 +94,7 @@ func (r *REST) Create(ctx kapi.Context, obj runtime.Object) (runtime.Object, err } } - list, err := r.openshiftClient.TemplateConfigs(r.openshiftNamespace).Create(template) + list, err := r.openshiftClient.TemplateConfigs(kapi.NamespaceDefault).Create(template) if err != nil { return nil, err } @@ -118,6 +116,14 @@ func (r *REST) Create(ctx kapi.Context, obj runtime.Object) (runtime.Object, err return r.openshiftClient.Projects().Get(projectName) } +func (r *REST) getTemplate() (*templateapi.Template, error) { + if len(r.openshiftNamespace) == 0 || len(r.templateName) == 0 { + return DefaultTemplate(), nil + } + + return r.openshiftClient.Templates(r.openshiftNamespace).Get(r.templateName) +} + func (r *REST) List(ctx kapi.Context, label labels.Selector, field fields.Selector) (runtime.Object, error) { userInfo, exists := kapi.UserFrom(ctx) if !exists { diff --git a/pkg/project/registry/projectrequest/delegated/sample_template.go b/pkg/project/registry/projectrequest/delegated/sample_template.go index 1044938840f6..d8dbc6b351ee 100644 --- a/pkg/project/registry/projectrequest/delegated/sample_template.go +++ b/pkg/project/registry/projectrequest/delegated/sample_template.go @@ -1,10 +1,10 @@ package delegated import ( + kapi "github.com/GoogleCloudPlatform/kubernetes/pkg/api" "github.com/GoogleCloudPlatform/kubernetes/pkg/util" authorizationapi "github.com/openshift/origin/pkg/authorization/api" - "github.com/openshift/origin/pkg/cmd/server/bootstrappolicy" projectapi "github.com/openshift/origin/pkg/project/api" templateapi "github.com/openshift/origin/pkg/template/api" @@ -21,10 +21,10 @@ var ( parameters = []string{ProjectNameParam, ProjectDisplayNameParam, ProjectDescriptionParam, ProjectAdminUserParam} ) -func NewSampleTemplate(openshiftNamespace, templateName string) *templateapi.Template { +func DefaultTemplate() *templateapi.Template { ret := &templateapi.Template{} - ret.Name = templateName - ret.Namespace = openshiftNamespace + ret.Name = "project-request" + ret.Namespace = kapi.NamespaceDefault project := &projectapi.Project{} project.Name = "${" + ProjectNameParam + "}" diff --git a/test/integration/unprivileged_newproject_test.go b/test/integration/unprivileged_newproject_test.go index 95b6067d276c..087b7155c272 100644 --- a/test/integration/unprivileged_newproject_test.go +++ b/test/integration/unprivileged_newproject_test.go @@ -4,7 +4,6 @@ package integration import ( "io/ioutil" - "strings" "testing" "time" @@ -18,11 +17,13 @@ import ( osc "github.com/openshift/origin/pkg/cmd/cli/cmd" "github.com/openshift/origin/pkg/cmd/server/bootstrappolicy" "github.com/openshift/origin/pkg/cmd/util/tokencmd" + projectapi "github.com/openshift/origin/pkg/project/api" + projectrequeststorage "github.com/openshift/origin/pkg/project/registry/projectrequest/delegated" testutil "github.com/openshift/origin/test/util" ) func TestUnprivilegedNewProject(t *testing.T) { - masterConfig, clusterAdminKubeConfig, err := testutil.StartTestMaster() + _, clusterAdminKubeConfig, err := testutil.StartTestMaster() if err != nil { t.Fatalf("unexpected error: %v", err) } @@ -31,10 +32,6 @@ func TestUnprivilegedNewProject(t *testing.T) { if err != nil { t.Fatalf("unexpected error: %v", err) } - clusterAdminClient, err := testutil.GetClusterAdminClient(clusterAdminKubeConfig) - if err != nil { - t.Fatalf("unexpected error: %v", err) - } valerieClientConfig := *clusterAdminClientConfig valerieClientConfig.Username = "" @@ -80,13 +77,92 @@ func TestUnprivilegedNewProject(t *testing.T) { waitForProject(t, valerieOpenshiftClient, "new-project", 5*time.Second, 10) - // request the same one again. This should fail during the bulk creation step - if err := requestProject.Run(); err == nil || !strings.Contains(err.Error(), "already exists") { + if err := requestProject.Run(); !kapierrors.IsAlreadyExists(err) { t.Fatalf("expected an already exists error, but got %v", err) } - tokens := strings.Split(masterConfig.ProjectRequestConfig.ProjectRequestTemplate, "/") - if err := clusterAdminClient.Templates(tokens[0]).Delete(tokens[1]); err != nil { +} +func TestUnprivilegedNewProjectFromTemplate(t *testing.T) { + namespace := "foo" + templateName := "bar" + + masterOptions, err := testutil.DefaultMasterOptions() + if err != nil { + t.Fatalf("unexpected error: %v", err) + } + masterOptions.ProjectRequestConfig.ProjectRequestTemplate = namespace + "/" + templateName + + clusterAdminKubeConfig, err := testutil.StartConfiguredMaster(masterOptions) + if err != nil { + t.Fatalf("unexpected error: %v", err) + } + + clusterAdminClientConfig, err := testutil.GetClusterAdminClientConfig(clusterAdminKubeConfig) + if err != nil { + t.Fatalf("unexpected error: %v", err) + } + clusterAdminClient, err := testutil.GetClusterAdminClient(clusterAdminKubeConfig) + if err != nil { + t.Fatalf("unexpected error: %v", err) + } + + valerieClientConfig := *clusterAdminClientConfig + valerieClientConfig.Username = "" + valerieClientConfig.Password = "" + valerieClientConfig.BearerToken = "" + valerieClientConfig.CertFile = "" + valerieClientConfig.KeyFile = "" + valerieClientConfig.CertData = nil + valerieClientConfig.KeyData = nil + + accessToken, err := tokencmd.RequestToken(&valerieClientConfig, nil, "valerie", "security!") + if err != nil { + t.Fatalf("unexpected error: %v", err) + } + + valerieClientConfig.BearerToken = accessToken + valerieOpenshiftClient, err := client.New(&valerieClientConfig) + if err != nil { + t.Fatalf("unexpected error: %v", err) + } + + if _, err := clusterAdminClient.Projects().Create(&projectapi.Project{ObjectMeta: kapi.ObjectMeta{Name: namespace}}); err != nil { + t.Fatalf("unexpected error: %v", err) + } + + template := projectrequeststorage.DefaultTemplate() + template.Name = templateName + template.Namespace = namespace + + template.Objects[0].(*projectapi.Project).Annotations["extra"] = "here" + _, err = clusterAdminClient.Templates(namespace).Create(template) + if err != nil { + t.Fatalf("unexpected error: %v", err) + } + + requestProject := osc.NewProjectOptions{ + ProjectName: "new-project", + DisplayName: "display name here", + Description: "the special description", + + Client: valerieOpenshiftClient, + Out: ioutil.Discard, + } + + if err := requestProject.Run(); err != nil { + t.Fatalf("unexpected error: %v", err) + } + + waitForProject(t, valerieOpenshiftClient, "new-project", 5*time.Second, 10) + project, err := valerieOpenshiftClient.Projects().Get("new-project") + if err != nil { + t.Fatalf("unexpected error: %v", err) + } + if project.Annotations["extra"] != "here" { + t.Errorf("unexpected project %#v", project) + } + + if err := clusterAdminClient.Templates(namespace).Delete(templateName); err != nil { t.Fatalf("unexpected error: %v", err) }