Skip to content

Commit

Permalink
allow templateinstance controller to instantiate non-v1 objects
Browse files Browse the repository at this point in the history
  • Loading branch information
Jim Minter committed Jun 22, 2017
1 parent a192b3e commit c954817
Show file tree
Hide file tree
Showing 9 changed files with 268 additions and 59 deletions.
37 changes: 3 additions & 34 deletions pkg/build/admission/jenkinsbootstrapper/admission.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,6 @@ import (

"github.com/golang/glog"
kapierrors "k8s.io/apimachinery/pkg/api/errors"
"k8s.io/apimachinery/pkg/api/meta"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/runtime"
kutilerrors "k8s.io/apimachinery/pkg/util/errors"
Expand All @@ -15,11 +14,9 @@ import (
kapi "k8s.io/kubernetes/pkg/api"
kclientset "k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset"
coreclient "k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset/typed/core/internalversion"
kclient "k8s.io/kubernetes/pkg/client/unversioned"
kadmission "k8s.io/kubernetes/pkg/kubeapiserver/admission"
"k8s.io/kubernetes/pkg/kubectl/resource"

"github.com/openshift/origin/pkg/api/latest"
authenticationclient "github.com/openshift/origin/pkg/auth/client"
buildapi "github.com/openshift/origin/pkg/build/api"
jenkinscontroller "github.com/openshift/origin/pkg/build/controller/jenkins"
Expand Down Expand Up @@ -101,37 +98,9 @@ func (a *jenkinsBootstrapper) Admit(attributes admission.Attributes) error {

bulk := &cmd.Bulk{
Mapper: &resource.Mapper{
RESTMapper: kapi.Registry.RESTMapper(),
ObjectTyper: kapi.Scheme,
ClientMapper: resource.ClientMapperFunc(func(mapping *meta.RESTMapping) (resource.RESTClient, error) {
// TODO this is a nasty copy&paste from pkg/cmd/util/clientcmd/factory_object_mapping.go#ClientForMapping
if latest.OriginKind(mapping.GroupVersionKind) {
if err := client.SetOpenShiftDefaults(&impersonatingConfig); err != nil {
return nil, err
}
impersonatingConfig.APIPath = "/apis"
if mapping.GroupVersionKind.Group == kapi.GroupName {
impersonatingConfig.APIPath = "/oapi"
}
gv := mapping.GroupVersionKind.GroupVersion()
impersonatingConfig.GroupVersion = &gv
return restclient.RESTClientFor(&impersonatingConfig)
}
// TODO and this from vendor/k8s.io/kubernetes/pkg/kubectl/cmd/util/factory_object_mapping.go#ClientForMapping
if err := kclient.SetKubernetesDefaults(&impersonatingConfig); err != nil {
return nil, err
}
gvk := mapping.GroupVersionKind
switch gvk.Group {
case kapi.GroupName:
impersonatingConfig.APIPath = "/api"
default:
impersonatingConfig.APIPath = "/apis"
}
gv := gvk.GroupVersion()
impersonatingConfig.GroupVersion = &gv
return restclient.RESTClientFor(&impersonatingConfig)
}),
RESTMapper: kapi.Registry.RESTMapper(),
ObjectTyper: kapi.Scheme,
ClientMapper: cmd.ClientMapperFromConfig(&impersonatingConfig),
},
Op: cmd.Create,
After: func(info *resource.Info, err error) bool {
Expand Down
6 changes: 6 additions & 0 deletions pkg/cmd/server/origin/controller/template.go
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,11 @@ type TemplateInstanceControllerConfig struct {
func (c *TemplateInstanceControllerConfig) RunController(ctx ControllerContext) (bool, error) {
saName := bootstrappolicy.InfraTemplateInstanceControllerServiceAccountName

restConfig, err := ctx.ClientBuilder.Config(saName)
if err != nil {
return true, err
}

internalKubeClient, err := ctx.ClientBuilder.KubeInternalClient(saName)
if err != nil {
return true, err
Expand All @@ -27,6 +32,7 @@ func (c *TemplateInstanceControllerConfig) RunController(ctx ControllerContext)
}

go templatecontroller.NewTemplateInstanceController(
restConfig,
deprecatedOcClient,
internalKubeClient,
templateClient.Template(),
Expand Down
2 changes: 1 addition & 1 deletion pkg/cmd/server/origin/storage.go
Original file line number Diff line number Diff line change
Expand Up @@ -350,7 +350,7 @@ func (c OpenshiftAPIConfig) GetRestStorage() (map[schema.GroupVersion]map[string
PolicyBindingLister: c.AuthorizationInformers.Authorization().InternalVersion().PolicyBindings().Lister(),
versioner: c.AuthorizationInformers.Authorization().InternalVersion().PolicyBindings().Informer(),
}
projectRequestStorage := projectrequeststorage.NewREST(c.ProjectRequestMessage, namespace, templateName, c.DeprecatedOpenshiftClient, c.KubeClientInternal, policyBindings)
projectRequestStorage := projectrequeststorage.NewREST(c.ProjectRequestMessage, namespace, templateName, c.DeprecatedOpenshiftClient, c.GenericConfig.LoopbackClientConfig, policyBindings)

buildConfigWebHooks := buildconfigregistry.NewWebHookREST(
buildConfigRegistry,
Expand Down
42 changes: 42 additions & 0 deletions pkg/config/cmd/cmd.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,9 +10,14 @@ import (
"k8s.io/apimachinery/pkg/labels"
"k8s.io/apimachinery/pkg/runtime"
"k8s.io/apimachinery/pkg/runtime/schema"
"k8s.io/client-go/rest"
kapi "k8s.io/kubernetes/pkg/api"
"k8s.io/kubernetes/pkg/client/unversioned"
cmdutil "k8s.io/kubernetes/pkg/kubectl/cmd/util"
"k8s.io/kubernetes/pkg/kubectl/resource"

"github.com/openshift/origin/pkg/api/latest"
"github.com/openshift/origin/pkg/client"
)

type Runner interface {
Expand Down Expand Up @@ -99,6 +104,43 @@ func (b *Bulk) Run(list *kapi.List, namespace string) []error {
return errs
}

// ClientMapperFromConfig returns a ClientMapper suitable for Bulk operations.
// TODO: copied from
// pkg/cmd/util/clientcmd/factory_object_mapping.go#ClientForMapping and
// vendor/k8s.io/kubernetes/pkg/kubectl/cmd/util/factory_object_mapping.go#ClientForMapping
func ClientMapperFromConfig(config *rest.Config) resource.ClientMapperFunc {
return resource.ClientMapperFunc(func(mapping *meta.RESTMapping) (resource.RESTClient, error) {
configCopy := *config

if latest.OriginKind(mapping.GroupVersionKind) {
if err := client.SetOpenShiftDefaults(&configCopy); err != nil {
return nil, err
}
configCopy.APIPath = "/apis"
if mapping.GroupVersionKind.Group == kapi.GroupName {
configCopy.APIPath = "/oapi"
}
gv := mapping.GroupVersionKind.GroupVersion()
configCopy.GroupVersion = &gv
return rest.RESTClientFor(&configCopy)
}

if err := unversioned.SetKubernetesDefaults(&configCopy); err != nil {
return nil, err
}
gvk := mapping.GroupVersionKind
switch gvk.Group {
case kapi.GroupName:
configCopy.APIPath = "/api"
default:
configCopy.APIPath = "/apis"
}
gv := gvk.GroupVersion()
configCopy.GroupVersion = &gv
return rest.RESTClientFor(&configCopy)
})
}

func NewPrintNameOrErrorAfterIndent(mapper meta.RESTMapper, short bool, operation string, out, errs io.Writer, dryRun bool, indent string, prefixForError PrefixForError) AfterFunc {
return func(info *resource.Info, err error) bool {
if err == nil {
Expand Down
21 changes: 7 additions & 14 deletions pkg/project/registry/projectrequest/delegated/delegated.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,6 @@ import (
"github.com/golang/glog"

kapierror "k8s.io/apimachinery/pkg/api/errors"
"k8s.io/apimachinery/pkg/api/meta"
metainternal "k8s.io/apimachinery/pkg/apis/meta/internalversion"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/labels"
Expand All @@ -18,12 +17,11 @@ import (
"k8s.io/apimachinery/pkg/util/wait"
apirequest "k8s.io/apiserver/pkg/endpoints/request"
"k8s.io/apiserver/pkg/registry/rest"
restclient "k8s.io/client-go/rest"
kapi "k8s.io/kubernetes/pkg/api"
kclientset "k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset"
"k8s.io/kubernetes/pkg/client/retry"
"k8s.io/kubernetes/pkg/kubectl/resource"

"github.com/openshift/origin/pkg/api/latest"
authorizationapi "github.com/openshift/origin/pkg/authorization/api"
authorizationlister "github.com/openshift/origin/pkg/authorization/generated/listers/authorization/internalversion"
"github.com/openshift/origin/pkg/client"
Expand All @@ -39,20 +37,20 @@ type REST struct {
templateName string

openshiftClient *client.Client
kubeClient kclientset.Interface
restConfig *restclient.Config

// policyBindings is an auth cache that is shared with the authorizer for the API server.
// we use this cache to detect when the authorizer has observed the change for the auth rules
policyBindings authorizationlister.PolicyBindingLister
}

func NewREST(message, templateNamespace, templateName string, openshiftClient *client.Client, kubeClient kclientset.Interface, policyBindingCache authorizationlister.PolicyBindingLister) *REST {
func NewREST(message, templateNamespace, templateName string, openshiftClient *client.Client, restConfig *restclient.Config, policyBindingCache authorizationlister.PolicyBindingLister) *REST {
return &REST{
message: message,
templateNamespace: templateNamespace,
templateName: templateName,
openshiftClient: openshiftClient,
kubeClient: kubeClient,
restConfig: restConfig,
policyBindings: policyBindingCache,
}
}
Expand Down Expand Up @@ -169,14 +167,9 @@ func (r *REST) Create(ctx apirequest.Context, obj runtime.Object) (runtime.Objec

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.Core().RESTClient(), nil
}),
RESTMapper: client.DefaultMultiRESTMapper(),
ObjectTyper: kapi.Scheme,
ClientMapper: configcmd.ClientMapperFromConfig(r.restConfig),
},
After: stopOnErr,
Op: configcmd.Create,
Expand Down
17 changes: 7 additions & 10 deletions pkg/template/controller/templateinstance_controller.go
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ import (
utilruntime "k8s.io/apimachinery/pkg/util/runtime"
"k8s.io/apimachinery/pkg/util/wait"
"k8s.io/apiserver/pkg/authentication/user"
"k8s.io/client-go/rest"
"k8s.io/client-go/tools/cache"
"k8s.io/client-go/util/workqueue"
kapi "k8s.io/kubernetes/pkg/api"
Expand All @@ -23,7 +24,6 @@ import (

"github.com/golang/glog"

"github.com/openshift/origin/pkg/api/latest"
"github.com/openshift/origin/pkg/authorization/util"
"github.com/openshift/origin/pkg/client"
"github.com/openshift/origin/pkg/config/cmd"
Expand All @@ -40,6 +40,7 @@ import (
// using its own service account, first verifying that the requester also has
// permissions to instantiate.
type TemplateInstanceController struct {
config *rest.Config
oc client.Interface
kc kclientsetinternal.Interface
templateclient internalversiontemplate.TemplateInterface
Expand All @@ -51,8 +52,9 @@ type TemplateInstanceController struct {
}

// NewTemplateInstanceController returns a new TemplateInstanceController.
func NewTemplateInstanceController(oc client.Interface, kc kclientsetinternal.Interface, templateclient internalversiontemplate.TemplateInterface, informer internalversion.TemplateInstanceInformer) *TemplateInstanceController {
func NewTemplateInstanceController(config *rest.Config, oc client.Interface, kc kclientsetinternal.Interface, templateclient internalversiontemplate.TemplateInterface, informer internalversion.TemplateInstanceInformer) *TemplateInstanceController {
c := &TemplateInstanceController{
config: config,
oc: oc,
kc: kc,
templateclient: templateclient,
Expand Down Expand Up @@ -304,14 +306,9 @@ func (c *TemplateInstanceController) instantiate(templateInstance *templateapi.T

bulk := cmd.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 c.oc.(*client.Client), nil
}
return c.kc.Core().RESTClient(), nil
}),
RESTMapper: client.DefaultMultiRESTMapper(),
ObjectTyper: kapi.Scheme,
ClientMapper: cmd.ClientMapperFromConfig(c.config),
},
Op: func(info *resource.Info, namespace string, obj runtime.Object) (runtime.Object, error) {
if len(info.Namespace) > 0 {
Expand Down
64 changes: 64 additions & 0 deletions test/extended/templates/templateinstance_objectkinds.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
package templates

import (
"fmt"
"time"

g "github.com/onsi/ginkgo"
o "github.com/onsi/gomega"

metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/util/wait"
kapi "k8s.io/kubernetes/pkg/api"

exutil "github.com/openshift/origin/test/extended/util"
)

// ensure that we can instantiate Kubernetes and OpenShift objects, legacy and
// non-legacy, from a range of API groups.
var _ = g.Describe("[templates] templateinstance object kinds test", func() {
defer g.GinkgoRecover()

var (
fixture = exutil.FixturePath("testdata", "templates", "templateinstance_objectkinds.yaml")
cli = exutil.NewCLI("templates", exutil.KubeConfigPath())
)

g.It("should create objects from varying API groups", func() {
err := cli.Run("create").Args("-f", fixture).Execute()
o.Expect(err).NotTo(o.HaveOccurred())

// wait for templateinstance controller to do its thing
err = wait.Poll(time.Second, time.Minute, func() (bool, error) {
templateinstance, err := cli.TemplateClient().Template().TemplateInstances(cli.Namespace()).Get("templateinstance", metav1.GetOptions{})
if err != nil {
return false, err
}

for _, c := range templateinstance.Status.Conditions {
if c.Reason == "Failed" && c.Status == kapi.ConditionTrue {
return false, fmt.Errorf("failed condition: %s", c.Message)
}
if c.Reason == "Created" && c.Status == kapi.ConditionTrue {
return true, nil
}
}

return false, nil
})
o.Expect(err).NotTo(o.HaveOccurred())

// check everything was created as expected
_, err = cli.KubeClient().CoreV1().Secrets(cli.Namespace()).Get("secret", metav1.GetOptions{})
o.Expect(err).NotTo(o.HaveOccurred())

_, err = cli.KubeClient().AppsV1beta1().Deployments(cli.Namespace()).Get("deployment", metav1.GetOptions{})
o.Expect(err).NotTo(o.HaveOccurred())

_, err = cli.Client().Routes(cli.Namespace()).Get("route", metav1.GetOptions{})
o.Expect(err).NotTo(o.HaveOccurred())

_, err = cli.Client().Routes(cli.Namespace()).Get("newroute", metav1.GetOptions{})
o.Expect(err).NotTo(o.HaveOccurred())
})
})
Loading

0 comments on commit c954817

Please sign in to comment.