Skip to content

Commit 6678a48

Browse files
committed
GABE: stop using kubectl based client for admission plugin
1 parent 2ef846c commit 6678a48

File tree

4 files changed

+56
-58
lines changed

4 files changed

+56
-58
lines changed

pkg/build/admission/jenkinsbootstrapper/admission.go

Lines changed: 30 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -6,20 +6,19 @@ import (
66

77
"github.com/golang/glog"
88
kapierrors "k8s.io/apimachinery/pkg/api/errors"
9+
"k8s.io/apimachinery/pkg/api/meta"
910
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
1011
"k8s.io/apimachinery/pkg/runtime"
1112
kutilerrors "k8s.io/apimachinery/pkg/util/errors"
1213
"k8s.io/apiserver/pkg/admission"
14+
"k8s.io/client-go/dynamic"
1315
restclient "k8s.io/client-go/rest"
14-
"k8s.io/kubernetes/pkg/api/legacyscheme"
1516
kclientset "k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset"
1617
coreclient "k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/typed/core/internalversion"
1718
kadmission "k8s.io/kubernetes/pkg/kubeapiserver/admission"
18-
"k8s.io/kubernetes/pkg/kubectl/genericclioptions/resource"
1919

2020
buildapi "github.com/openshift/origin/pkg/build/apis/build"
21-
jenkinscontroller "github.com/openshift/origin/pkg/build/controller/jenkins"
22-
"github.com/openshift/origin/pkg/bulk"
21+
jenkinscontroller "github.com/openshift/origin/pkg/build/admission/jenkinsbootstrapper/jenkins"
2322
authenticationclient "github.com/openshift/origin/pkg/client/impersonatingclient"
2423
oadmission "github.com/openshift/origin/pkg/cmd/server/admission"
2524
configapi "github.com/openshift/origin/pkg/cmd/server/apis/config"
@@ -39,6 +38,7 @@ type jenkinsBootstrapper struct {
3938
privilegedRESTClientConfig restclient.Config
4039
serviceClient coreclient.ServicesGetter
4140
templateClient templateclient.Interface
41+
restMapper meta.RESTMapper
4242

4343
jenkinsConfig configapi.JenkinsPipelineConfig
4444
}
@@ -47,6 +47,7 @@ var _ = oadmission.WantsJenkinsPipelineConfig(&jenkinsBootstrapper{})
4747
var _ = oadmission.WantsRESTClientConfig(&jenkinsBootstrapper{})
4848
var _ = oadmission.WantsOpenshiftInternalTemplateClient(&jenkinsBootstrapper{})
4949
var _ = kadmission.WantsInternalKubeClientSet(&jenkinsBootstrapper{})
50+
var _ = kadmission.WantsRESTMapper(&jenkinsBootstrapper{})
5051

5152
// NewJenkinsBootstrapper returns an admission plugin that will create required jenkins resources as the user if they are needed.
5253
func NewJenkinsBootstrapper() admission.Interface {
@@ -99,35 +100,28 @@ func (a *jenkinsBootstrapper) Admit(attributes admission.Attributes) error {
99100
}
100101

101102
impersonatingConfig := authenticationclient.NewImpersonatingConfig(attributes.GetUserInfo(), a.privilegedRESTClientConfig)
102-
103-
var bulkErr error
104-
105-
bulk := &bulk.Bulk{
106-
Mapper: &resource.Mapper{
107-
RESTMapper: legacyscheme.Registry.RESTMapper(),
108-
ObjectTyper: legacyscheme.Scheme,
109-
ClientMapper: bulk.ClientMapperFromConfig(&impersonatingConfig),
110-
},
111-
Op: bulk.Create,
112-
After: func(info *resource.Info, err error) bool {
113-
if kapierrors.IsAlreadyExists(err) {
114-
return false
115-
}
116-
if err != nil {
117-
bulkErr = err
118-
return true
119-
}
120-
return false
121-
},
103+
dynamicClient, err := dynamic.NewForConfig(&impersonatingConfig)
104+
if err != nil {
105+
return err
122106
}
123-
// we're intercepting the error we care about using After
124-
bulk.Run(objects, namespace)
125-
if bulkErr != nil {
126-
return bulkErr
107+
108+
for _, toCreate := range objects.Items {
109+
restMapping, mappingErr := a.restMapper.RESTMapping(toCreate.GroupVersionKind().GroupKind(), toCreate.GroupVersionKind().Version)
110+
if mappingErr != nil {
111+
return kapierrors.NewInternalError(mappingErr)
112+
}
113+
114+
_, createErr := dynamicClient.Resource(restMapping.Resource).Namespace(namespace).Create(&toCreate)
115+
// it is safe to ignore all such errors since stopOnErr will only let these through for the default role bindings
116+
if kapierrors.IsAlreadyExists(createErr) {
117+
continue
118+
}
119+
if createErr != nil {
120+
return kapierrors.NewInternalError(createErr)
121+
}
127122
}
128123

129124
glog.V(1).Infof("Jenkins Pipeline service %q created", svcName)
130-
131125
return nil
132126

133127
}
@@ -159,12 +153,19 @@ func (a *jenkinsBootstrapper) SetOpenshiftInternalTemplateClient(c templateclien
159153
a.templateClient = c
160154
}
161155

156+
func (a *jenkinsBootstrapper) SetRESTMapper(restMapper meta.RESTMapper) {
157+
a.restMapper = restMapper
158+
}
159+
162160
func (a *jenkinsBootstrapper) ValidateInitialization() error {
163161
if a.serviceClient == nil {
164162
return fmt.Errorf("missing serviceClient")
165163
}
166164
if a.templateClient == nil {
167165
return fmt.Errorf("missing templateClient")
168166
}
167+
if a.restMapper == nil {
168+
return fmt.Errorf("missing restMapper")
169+
}
169170
return nil
170171
}

pkg/build/controller/jenkins/jenkins.go renamed to pkg/build/admission/jenkinsbootstrapper/jenkins/jenkins.go

Lines changed: 25 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -5,10 +5,10 @@ import (
55

66
"github.com/golang/glog"
77
"github.com/openshift/origin/pkg/template/templateprocessing"
8+
"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
89
"k8s.io/kubernetes/pkg/api/legacyscheme"
910

1011
kerrs "k8s.io/apimachinery/pkg/api/errors"
11-
"k8s.io/apimachinery/pkg/api/meta"
1212
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
1313
"k8s.io/apimachinery/pkg/runtime"
1414
kapi "k8s.io/kubernetes/pkg/apis/core"
@@ -38,7 +38,7 @@ func NewPipelineTemplate(ns string, conf serverapi.JenkinsPipelineConfig, templa
3838
}
3939

4040
// Process processes the Jenkins template. If an error occurs
41-
func (t *PipelineTemplate) Process() (*kapi.List, []error) {
41+
func (t *PipelineTemplate) Process() (*unstructured.UnstructuredList, []error) {
4242
var errors []error
4343
jenkinsTemplate, err := t.templateClient.Template().Templates(t.Config.TemplateNamespace).Get(t.Config.TemplateName, metav1.GetOptions{})
4444
if err != nil {
@@ -56,41 +56,37 @@ func (t *PipelineTemplate) Process() (*kapi.List, []error) {
5656
errors = append(errors, fmt.Errorf("processing Jenkins template %s/%s failed: %v", t.Config.TemplateNamespace, t.Config.TemplateName, err))
5757
return nil, errors
5858
}
59-
var items []runtime.Object
60-
for _, obj := range pTemplate.Objects {
61-
if unknownObj, ok := obj.(*runtime.Unknown); ok {
62-
decodedObj, err := runtime.Decode(legacyscheme.Codecs.UniversalDecoder(), unknownObj.Raw)
63-
if err != nil {
64-
errors = append(errors, err)
65-
}
66-
items = append(items, decodedObj)
67-
}
59+
60+
objectsToCreate := &kapi.List{}
61+
for i := range pTemplate.Objects {
62+
// use .Objects[i] in append to avoid range memory address reuse
63+
objectsToCreate.Items = append(objectsToCreate.Items, pTemplate.Objects[i])
64+
}
65+
66+
// TODO, stop doing this crazy thing, but for now it's a very simple way to get the unstructured objects we need
67+
jsonBytes, err := runtime.Encode(legacyscheme.Codecs.LegacyCodec(legacyscheme.Scheme.PrioritizedVersionsAllGroups()...), objectsToCreate)
68+
if err != nil {
69+
errors = append(errors, err)
70+
return nil, errors
6871
}
72+
uncastList, err := runtime.Decode(unstructured.UnstructuredJSONScheme, jsonBytes)
73+
if err != nil {
74+
errors = append(errors, err)
75+
return nil, errors
76+
}
77+
6978
glog.V(4).Infof("Processed Jenkins pipeline jenkinsTemplate %s/%s", pTemplate.Namespace, pTemplate.Namespace)
70-
return &kapi.List{ListMeta: metav1.ListMeta{}, Items: items}, errors
79+
return uncastList.(*unstructured.UnstructuredList), errors
7180
}
7281

7382
// HasJenkinsService searches the template items and return true if the expected
7483
// Jenkins service is contained in template.
75-
func (t *PipelineTemplate) HasJenkinsService(items *kapi.List) bool {
76-
accessor := meta.NewAccessor()
84+
func (t *PipelineTemplate) HasJenkinsService(items *unstructured.UnstructuredList) bool {
7785
for _, item := range items.Items {
78-
kinds, _, err := legacyscheme.Scheme.ObjectKinds(item)
79-
if err != nil {
80-
glog.Infof("Error checking Jenkins service kind: %v", err)
81-
return false
82-
}
83-
name, err := accessor.Name(item)
84-
if err != nil {
85-
glog.Infof("Error checking Jenkins service name: %v", err)
86-
return false
87-
}
88-
glog.Infof("Jenkins Pipeline template object %q with name %q", name, kinds[0].Kind)
86+
glog.Infof("Jenkins Pipeline template object %q with name %q", item.GetName(), item.GetObjectKind().GroupVersionKind())
8987

90-
for _, kind := range kinds {
91-
if name == t.Config.ServiceName && kind.GroupKind() == kapi.Kind("Service") {
92-
return true
93-
}
88+
if item.GetName() == t.Config.ServiceName && item.GetObjectKind().GroupVersionKind().GroupKind() == kapi.Kind("Service") {
89+
return true
9490
}
9591
}
9692
return false

pkg/project/admission/lifecycle/admission.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -58,6 +58,7 @@ var recommendedCreatableResources = map[schema.GroupResource]bool{
5858
}
5959
var _ = oadmission.WantsProjectCache(&lifecycle{})
6060
var _ = kadmission.WantsInternalKubeClientSet(&lifecycle{})
61+
var _ = kadmission.WantsRESTMapper(&lifecycle{})
6162

6263
// Admit enforces that a namespace must have the openshift finalizer associated with it in order to create origin API objects within it
6364
func (e *lifecycle) Admit(a admission.Attributes) (err error) {

0 commit comments

Comments
 (0)