@@ -7,38 +7,36 @@ import (
7
7
"strings"
8
8
9
9
"github.com/golang/glog"
10
-
11
10
kapierror "k8s.io/apimachinery/pkg/api/errors"
11
+ "k8s.io/apimachinery/pkg/api/meta"
12
12
metainternal "k8s.io/apimachinery/pkg/apis/meta/internalversion"
13
13
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
14
+ "k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
14
15
"k8s.io/apimachinery/pkg/runtime"
15
16
utilerrors "k8s.io/apimachinery/pkg/util/errors"
16
17
utilruntime "k8s.io/apimachinery/pkg/util/runtime"
17
18
"k8s.io/apimachinery/pkg/util/sets"
18
19
"k8s.io/apimachinery/pkg/util/wait"
19
20
apirequest "k8s.io/apiserver/pkg/endpoints/request"
20
21
"k8s.io/apiserver/pkg/registry/rest"
21
- restclient "k8s.io/client-go/rest "
22
+ "k8s.io/client-go/dynamic "
22
23
"k8s.io/client-go/util/retry"
23
24
"k8s.io/kubernetes/pkg/api/legacyscheme"
24
25
authorizationapi "k8s.io/kubernetes/pkg/apis/authorization"
25
26
kapi "k8s.io/kubernetes/pkg/apis/core"
26
27
"k8s.io/kubernetes/pkg/apis/rbac"
27
28
authorizationclient "k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/typed/authorization/internalversion"
28
29
rbaclisters "k8s.io/kubernetes/pkg/client/listers/rbac/internalversion"
29
- "k8s.io/kubernetes/pkg/kubectl/genericclioptions/resource"
30
30
31
31
osauthorizationapi "github.com/openshift/origin/pkg/authorization/apis/authorization"
32
32
authorizationutil "github.com/openshift/origin/pkg/authorization/util"
33
- configcmd "github.com/openshift/origin/pkg/bulk"
34
33
"github.com/openshift/origin/pkg/cmd/server/bootstrappolicy"
35
34
projectapi "github.com/openshift/origin/pkg/project/apis/project"
36
35
projectclientinternal "github.com/openshift/origin/pkg/project/generated/internalclientset/typed/project/internalversion"
37
36
projectrequestregistry "github.com/openshift/origin/pkg/project/registry/projectrequest"
38
37
templateapi "github.com/openshift/origin/pkg/template/apis/template"
39
38
templateinternalclient "github.com/openshift/origin/pkg/template/client/internalversion"
40
39
templateclient "github.com/openshift/origin/pkg/template/generated/internalclientset"
41
- restutil "github.com/openshift/origin/pkg/util/rest"
42
40
)
43
41
44
42
type REST struct {
@@ -49,7 +47,8 @@ type REST struct {
49
47
sarClient authorizationclient.SubjectAccessReviewInterface
50
48
projectGetter projectclientinternal.ProjectsGetter
51
49
templateClient templateclient.Interface
52
- restConfig * restclient.Config
50
+ client dynamic.Interface
51
+ restMapper meta.RESTMapper
53
52
54
53
// policyBindings is an auth cache that is shared with the authorizer for the API server.
55
54
// we use this cache to detect when the authorizer has observed the change for the auth rules
@@ -59,15 +58,22 @@ type REST struct {
59
58
var _ rest.Lister = & REST {}
60
59
var _ rest.Creater = & REST {}
61
60
62
- func NewREST (message , templateNamespace , templateName string , projectClient projectclientinternal.ProjectsGetter , templateClient templateclient.Interface , sarClient authorizationclient.SubjectAccessReviewInterface , restConfig * restclient.Config , roleBindings rbaclisters.RoleBindingLister ) * REST {
61
+ func NewREST (message , templateNamespace , templateName string ,
62
+ projectClient projectclientinternal.ProjectsGetter ,
63
+ templateClient templateclient.Interface ,
64
+ sarClient authorizationclient.SubjectAccessReviewInterface ,
65
+ client dynamic.Interface ,
66
+ restMapper meta.RESTMapper ,
67
+ roleBindings rbaclisters.RoleBindingLister ) * REST {
63
68
return & REST {
64
69
message : message ,
65
70
templateNamespace : templateNamespace ,
66
71
templateName : templateName ,
67
72
projectGetter : projectClient ,
68
73
templateClient : templateClient ,
69
74
sarClient : sarClient ,
70
- restConfig : restConfig ,
75
+ client : client ,
76
+ restMapper : restMapper ,
71
77
roleBindings : roleBindings ,
72
78
}
73
79
}
@@ -190,36 +196,38 @@ func (r *REST) Create(ctx context.Context, obj runtime.Object, createValidation
190
196
return nil , err
191
197
}
192
198
193
- // Stop on the first error, since we have to delete the whole project if any item in the template fails
194
- stopOnErr := configcmd .AfterFunc (func (info * resource.Info , err error ) bool {
195
- // if a default role binding already exists, we're probably racing the controller. Don't die
196
- if gvk := info .Mapping .GroupVersionKind ; kapierror .IsAlreadyExists (err ) &&
197
- gvk .Kind == roleBindingKind && roleBindingGroups .Has (gvk .Group ) && defaultRoleBindingNames .Has (info .Name ) {
198
- return false
199
+ // TODO, stop doing this crazy thing, but for now it's a very simple way to get the unstructured objects we need
200
+ jsonBytes , err := runtime .Encode (legacyscheme .Codecs .LegacyCodec (legacyscheme .Scheme .PrioritizedVersionsAllGroups ()... ), objectsToCreate )
201
+ if err != nil {
202
+ return nil , kapierror .NewInternalError (err )
203
+ }
204
+ uncastList , err := runtime .Decode (unstructured .UnstructuredJSONScheme , jsonBytes )
205
+ if err != nil {
206
+ return nil , kapierror .NewInternalError (err )
207
+ }
208
+ toCreateList := uncastList .(* unstructured.UnstructuredList )
209
+
210
+ for _ , toCreate := range toCreateList .Items {
211
+ restMapping , mappingErr := r .restMapper .RESTMapping (toCreate .GroupVersionKind ().GroupKind (), toCreate .GroupVersionKind ().Version )
212
+ if mappingErr != nil {
213
+ utilruntime .HandleError (fmt .Errorf ("error creating items in requested project %q: %v" , createdProject .Name , mappingErr ))
214
+ return nil , kapierror .NewInternalError (mappingErr )
199
215
}
200
- return err != nil
201
- })
202
216
203
- bulk := configcmd.Bulk {
204
- Mapper : & resource.Mapper {
205
- RESTMapper : restutil .DefaultMultiRESTMapper (),
206
- ObjectTyper : legacyscheme .Scheme ,
207
- ClientMapper : configcmd .ClientMapperFromConfig (r .restConfig ),
208
- },
209
- IgnoreError : func (err error ) bool {
210
- // it is safe to ignore all such errors since stopOnErr will only let these through for the default role bindings
211
- return kapierror .IsAlreadyExists (err )
212
- },
213
- After : stopOnErr ,
214
- Op : configcmd .Create ,
215
- }
216
- if err := utilerrors .NewAggregate (bulk .Run (objectsToCreate , createdProject .Name )); err != nil {
217
- utilruntime .HandleError (fmt .Errorf ("error creating items in requested project %q: %v" , createdProject .Name , err ))
218
- // We have to clean up the project if any part of the project request template fails
219
- if deleteErr := r .projectGetter .Projects ().Delete (createdProject .Name , & metav1.DeleteOptions {}); deleteErr != nil {
220
- utilruntime .HandleError (fmt .Errorf ("error cleaning up requested project %q: %v" , createdProject .Name , deleteErr ))
217
+ _ , createErr := r .client .Resource (restMapping .Resource ).Namespace (createdProject .Name ).Create (& toCreate )
218
+ // if a default role binding already exists, we're probably racing the controller. Don't die
219
+ if gvk := restMapping .GroupVersionKind ; kapierror .IsAlreadyExists (createErr ) &&
220
+ gvk .Kind == roleBindingKind && roleBindingGroups .Has (gvk .Group ) && defaultRoleBindingNames .Has (toCreate .GetName ()) {
221
+ continue
222
+ }
223
+ // it is safe to ignore all such errors since stopOnErr will only let these through for the default role bindings
224
+ if kapierror .IsAlreadyExists (createErr ) {
225
+ continue
226
+ }
227
+ if createErr != nil {
228
+ utilruntime .HandleError (fmt .Errorf ("error creating items in requested project %q: %v" , createdProject .Name , createErr ))
229
+ return nil , kapierror .NewInternalError (createErr )
221
230
}
222
- return nil , kapierror .NewInternalError (err )
223
231
}
224
232
225
233
// wait for a rolebinding if we created one
0 commit comments