func (r *REST) Create(ctx kapi.Context, obj runtime.Object) (runtime.Object, error) { if err := rest.BeforeCreate(projectrequestregistry.Strategy, ctx, obj); err != nil { return nil, err } projectRequest := obj.(*projectapi.ProjectRequest) if _, err := r.openshiftClient.Projects().Get(projectRequest.Name); err == nil { return nil, kapierror.NewAlreadyExists(projectapi.Resource("project"), projectRequest.Name) } projectName := projectRequest.Name projectAdmin := "" projectRequester := "" if userInfo, exists := kapi.UserFrom(ctx); exists { projectAdmin = userInfo.GetName() projectRequester = userInfo.GetName() } template, err := r.getTemplate() if err != nil { return nil, err } for i := range template.Parameters { switch template.Parameters[i].Name { case ProjectAdminUserParam: template.Parameters[i].Value = projectAdmin case ProjectDescriptionParam: template.Parameters[i].Value = projectRequest.Description case ProjectDisplayNameParam: template.Parameters[i].Value = projectRequest.DisplayName case ProjectNameParam: template.Parameters[i].Value = projectName case ProjectRequesterParam: template.Parameters[i].Value = projectRequester } } list, err := r.openshiftClient.TemplateConfigs(kapi.NamespaceDefault).Create(template) if err != nil { return nil, err } if err := utilerrors.NewAggregate(runtime.DecodeList(list.Objects, kapi.Codecs.UniversalDecoder())); err != nil { return nil, kapierror.NewInternalError(err) } // one of the items in this list should be the project. We are going to locate it, remove it from the list, create it separately var projectFromTemplate *projectapi.Project var lastRoleBinding *authorizationapi.RoleBinding objectsToCreate := &kapi.List{} for i := range list.Objects { if templateProject, ok := list.Objects[i].(*projectapi.Project); ok { projectFromTemplate = templateProject // don't add this to the list to create. We'll create the project separately. continue } if roleBinding, ok := list.Objects[i].(*authorizationapi.RoleBinding); ok { // keep track of the rolebinding, but still add it to the list lastRoleBinding = roleBinding } objectsToCreate.Items = append(objectsToCreate.Items, list.Objects[i]) } if projectFromTemplate == nil { return nil, kapierror.NewInternalError(fmt.Errorf("the project template (%s/%s) is not correctly configured: must contain a project resource", r.templateNamespace, r.templateName)) } // we split out project creation separately so that in a case of racers for the same project, only one will win and create the rest of their template objects createdProject, err := r.openshiftClient.Projects().Create(projectFromTemplate) if err != nil { // log errors other than AlreadyExists and Forbidden if !kapierror.IsAlreadyExists(err) && !kapierror.IsForbidden(err) { utilruntime.HandleError(fmt.Errorf("error creating requested project %#v: %v", projectFromTemplate, err)) } return nil, err } // Stop on the first error, since we have to delete the whole project if any item in the template fails stopOnErr := configcmd.AfterFunc(func(_ *resource.Info, err error) bool { return err != nil }) bulk := configcmd.Bulk{ Mapper: &resource.Mapper{ RESTMapper: client.DefaultMultiRESTMapper(), ObjectTyper: kapi.Scheme, ClientMapper: resource.ClientMapperFunc(func(mapping *meta.RESTMapping) (resource.RESTClient, error) { if latest.OriginKind(mapping.GroupVersionKind) { return r.openshiftClient, nil } return r.kubeClient, nil }), }, After: stopOnErr, Op: configcmd.Create, } if err := utilerrors.NewAggregate(bulk.Run(objectsToCreate, projectName)); err != nil { utilruntime.HandleError(fmt.Errorf("error creating items in requested project %q: %v", createdProject.Name, err)) // We have to clean up the project if any part of the project request template fails if deleteErr := r.openshiftClient.Projects().Delete(createdProject.Name); deleteErr != nil { utilruntime.HandleError(fmt.Errorf("error cleaning up requested project %q: %v", createdProject.Name, deleteErr)) } return nil, kapierror.NewInternalError(err) } // wait for a rolebinding if we created one if lastRoleBinding != nil { r.waitForRoleBinding(projectName, lastRoleBinding.Name) } return r.openshiftClient.Projects().Get(projectName) }