Skip to content

Commit

Permalink
Plugin controller to manage plugin source from dashboard backend (#4017)
Browse files Browse the repository at this point in the history
* add CRD for Plugin kind

* add api types and test plugin yaml file

* prepare for codegen

* generate code from update-codegen

* add pluginclientset.Interface to clientManager and PluginClient method to ClientManager interface

* map v1alpha1.PluginList to plugin.PluginList

* serve plugin code from configmap data based on spec from Plugin CRD

* move plugin specific routes to handler.go in plugin package

* move plugin-crd.yml to test-resources

* add comments to files

* add content type header and remove file extension properly

* add tests for plugin package

* fix license header errors
  • Loading branch information
ajatprabha authored and k8s-ci-robot committed Jul 16, 2019
1 parent 64f26d7 commit 79e490c
Show file tree
Hide file tree
Showing 43 changed files with 2,167 additions and 3 deletions.
10 changes: 8 additions & 2 deletions aio/gulp/check.js
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,10 @@ gulp.task('check-license-headers', () => {

return gulp
.src(
[path.join(conf.paths.src, getLicenseFileFilter('ts', 'go', 'scss', 'html'))],
[
path.join(conf.paths.src, getLicenseFileFilter('!deepcopy.go', 'ts', 'go', 'scss', 'html')),
path.join("!", conf.paths.src, getLicenseFileFilter('deepcopy.go'))
],
{base: conf.paths.base})
.pipe(commonFilter)
.pipe(licenseCheck(licenseConfig('aio/templates/header.txt')).on('log', handleLogEvent))
Expand Down Expand Up @@ -93,7 +96,10 @@ gulp.task('update-license-headers', (doneFn) => {
const matchRate = 0.9;

gulp.src(
[path.join(conf.paths.src, getLicenseFileFilter('ts', 'go', 'scss', 'html'))],
[
path.join(conf.paths.src, getLicenseFileFilter('ts', 'go', 'scss', 'html')),
path.join("!", conf.paths.src, getLicenseFileFilter('deepcopy.go'))
],
{base: conf.paths.base})
.pipe(commonFilter)
.pipe(license(fs.readFileSync('aio/templates/header.txt', 'utf8'), {}, matchRate))
Expand Down
13 changes: 13 additions & 0 deletions aio/scripts/license-header.go.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
// Copyright 2017 The Kubernetes Authors.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
32 changes: 32 additions & 0 deletions aio/scripts/update-codegen.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
#!/usr/bin/env bash

# Copyright 2017 The Kubernetes Authors.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.

set -o errexit
set -o nounset
set -o pipefail

SCRIPT_ROOT=$(dirname "${BASH_SOURCE[0]}")/../..
CODEGEN_PKG=${GOPATH}/src/k8s.io/code-generator

# generate the code with:
# --output-base because this script should also be able to run inside the vendor dir of
# kl8s.io/kubernetes. The output-base is needed for the generators to output into the vendor dir
# instead of the $GOPATH directly. For normal projects this can be dropped.
"${CODEGEN_PKG}"/generate-groups.sh "deepcopy,client,informer,lister" \
github.com/kubernetes/dashboard/src/app/backend/plugin/client github.com/kubernetes/dashboard/src/app/backend/plugin \
apis:v1alpha1 \
--go-header-file "${SCRIPT_ROOT}"/aio/scripts/license-header.go.txt \
--output-base "$(dirname "${BASH_SOURCE[0]}")/../../../../.."
41 changes: 41 additions & 0 deletions aio/test-resources/plugin-crd.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
apiVersion: apiextensions.k8s.io/v1beta1
kind: CustomResourceDefinition
metadata:
name: plugins.dashboard.k8s.io
spec:
group: dashboard.k8s.io
scope: Namespaced
versions:
- name: v1alpha1
served: true
storage: true
names:
kind: Plugin
plural: plugins
singular: plugin
validation:
openAPIV3Schema:
type: object
properties:
spec:
type: object
properties:
source:
type: object
properties:
configMapRef:
type: object
properties:
name:
type: string
required:
- name
filename:
type: string
required:
- configMapRef
- filename
required:
- source
required:
- spec
25 changes: 25 additions & 0 deletions aio/test-resources/plugin-test.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
# Copyright 2017 Google Inc. All Rights Reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.

# A manifest that creates a plugin resource.

apiVersion: dashboard.k8s.io/v1alpha1
kind: Plugin
metadata:
name: plugin-test
spec:
source:
configMapRef:
name: plugin-test-src
filename: plugin1.js
2 changes: 2 additions & 0 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ github.com/gogo/protobuf v1.2.0 h1:xU6/SpYbvkNYiptHJYEDRseDLvYE7wSqhYYNy0QSUzI=
github.com/gogo/protobuf v1.2.0/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ=
github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b h1:VKtxabqXZkF25pY9ekfRL6a582T4P37/31XEstQ5p58=
github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q=
github.com/golang/groupcache v0.0.0-20160516000752-02826c3e7903 h1:LbsanbbD6LieFkXbj9YNNBupiGHJgFeLpO0j0Fza1h8=
github.com/golang/groupcache v0.0.0-20160516000752-02826c3e7903/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc=
github.com/golang/protobuf v1.2.0 h1:P3YflyNX/ehuJFLhxviNdFxQPkGK5cDcApsge1SqnvM=
github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
Expand All @@ -45,6 +46,7 @@ github.com/gophercloud/gophercloud v0.0.0-20190126172459-c818fa66e4c8/go.mod h1:
github.com/gorilla/websocket v1.4.0 h1:WDFjx/TMzVgy9VdMMQi2K2Emtwi2QcUQsztZ/zLaH/Q=
github.com/gorilla/websocket v1.4.0/go.mod h1:E7qHFY5m1UJ88s3WnNqhKjPHQ0heANvMoAMk2YaljkQ=
github.com/gregjones/httpcache v0.0.0-20170728041850-787624de3eb7/go.mod h1:FecbI9+v66THATjSRHfNgh1IVFe/9kFxbXtjV0ctIMA=
github.com/hashicorp/golang-lru v0.5.0 h1:CL2msUPvZTLb5O648aiLNJw3hnBxN2+1Jq8rCOH9wdo=
github.com/hashicorp/golang-lru v0.5.0/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8=
github.com/hpcloud/tail v1.0.0 h1:nfCOvKYfkgYP8hkirhJocXT2+zOD8yUNjXaWfTlyFKI=
github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU=
Expand Down
5 changes: 5 additions & 0 deletions src/app/backend/auth/manager_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ import (
clientapi "github.com/kubernetes/dashboard/src/app/backend/client/api"
"github.com/kubernetes/dashboard/src/app/backend/errors"

pluginclientset "github.com/kubernetes/dashboard/src/app/backend/plugin/client/clientset/versioned"
v1 "k8s.io/api/authorization/v1"
apiextensionsclientset "k8s.io/apiextensions-apiserver/pkg/client/clientset/clientset"
"k8s.io/client-go/kubernetes"
Expand All @@ -51,6 +52,10 @@ func (self *fakeClientManager) APIExtensionsClient(req *restful.Request) (apiext
return nil, nil
}

func (self *fakeClientManager) PluginClient(req *restful.Request) (pluginclientset.Interface, error) {
return nil, nil
}

func (self *fakeClientManager) InsecureClient() kubernetes.Interface {
return nil
}
Expand Down
2 changes: 2 additions & 0 deletions src/app/backend/client/api/types.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ package api
import (
"github.com/emicklei/go-restful"
authApi "github.com/kubernetes/dashboard/src/app/backend/auth/api"
pluginclientset "github.com/kubernetes/dashboard/src/app/backend/plugin/client/clientset/versioned"
v1 "k8s.io/api/authorization/v1"
apiextensionsclientset "k8s.io/apiextensions-apiserver/pkg/client/clientset/clientset"
"k8s.io/apimachinery/pkg/runtime"
Expand All @@ -40,6 +41,7 @@ type ClientManager interface {
Client(req *restful.Request) (kubernetes.Interface, error)
InsecureClient() kubernetes.Interface
APIExtensionsClient(req *restful.Request) (apiextensionsclientset.Interface, error)
PluginClient(req *restful.Request) (pluginclientset.Interface, error)
InsecureAPIExtensionsClient() apiextensionsclientset.Interface
CanI(req *restful.Request, ssar *v1.SelfSubjectAccessReview) bool
Config(req *restful.Request) (*rest.Config, error)
Expand Down
46 changes: 46 additions & 0 deletions src/app/backend/client/manager.go
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ import (
"strings"

"github.com/emicklei/go-restful"
pluginclientset "github.com/kubernetes/dashboard/src/app/backend/plugin/client/clientset/versioned"
v1 "k8s.io/api/authorization/v1"
apiextensionsclientset "k8s.io/apiextensions-apiserver/pkg/client/clientset/clientset"
"k8s.io/client-go/kubernetes"
Expand Down Expand Up @@ -71,6 +72,9 @@ type clientManager struct {
// API Extensions client created without providing auth info. It uses permissions granted to
// service account used by dashboard or kubeconfig file if it was passed during dashboard init.
insecureAPIExtensionsClient apiextensionsclientset.Interface
// Plugin client created without providing auth info. It uses permissions granted to
// service account used by dashboard or kubeconfig file if it was passed during dashboard init.
insecurePluginClient pluginclientset.Interface
// Kubernetes client created without providing auth info. It uses permissions granted to
// service account used by dashboard or kubeconfig file if it was passed during dashboard init.
insecureClient kubernetes.Interface
Expand Down Expand Up @@ -110,6 +114,21 @@ func (self *clientManager) APIExtensionsClient(req *restful.Request) (apiextensi
return self.InsecureAPIExtensionsClient(), nil
}

// PluginClient returns a plugin client. In case dashboard login is enabled and
// option to skip login page is disabled only secure client will be returned, otherwise insecure
// client will be used.
func (self *clientManager) PluginClient(req *restful.Request) (pluginclientset.Interface, error) {
if req == nil {
return nil, errors.NewBadRequest("request can not be nil!")
}

if self.isSecureModeEnabled(req) {
return self.securePluginClient(req)
}

return self.InsecurePluginClient(), nil
}

// Config returns a rest config. In case dashboard login is enabled and option to skip
// login page is disabled only secure config will be returned, otherwise insecure config will be
// used.
Expand Down Expand Up @@ -139,6 +158,13 @@ func (self *clientManager) InsecureAPIExtensionsClient() apiextensionsclientset.
return self.insecureAPIExtensionsClient
}

// InsecurePluginClient returns plugin client that was created without providing
// auth info. It uses permissions granted to service account used by dashboard or kubeconfig file
// if it was passed during dashboard init.
func (self *clientManager) InsecurePluginClient() pluginclientset.Interface {
return self.insecurePluginClient
}

// InsecureConfig returns kubernetes client config that used privileges of dashboard service account
// or kubeconfig file if it was passed during dashboard init.
func (self *clientManager) InsecureConfig() *rest.Config {
Expand Down Expand Up @@ -358,6 +384,20 @@ func (self *clientManager) secureAPIExtensionsClient(req *restful.Request) (apie
return client, nil
}

func (self *clientManager) securePluginClient(req *restful.Request) (pluginclientset.Interface, error) {
cfg, err := self.secureConfig(req)
if err != nil {
return nil, err
}

client, err := pluginclientset.NewForConfig(cfg)
if err != nil {
return nil, err
}

return client, nil
}

func (self *clientManager) secureConfig(req *restful.Request) (*rest.Config, error) {
cmdConfig, err := self.ClientCmdConfig(req)
if err != nil {
Expand Down Expand Up @@ -425,8 +465,14 @@ func (self *clientManager) initInsecureClients() {
panic(err)
}

pluginclient, err := pluginclientset.NewForConfig(self.insecureConfig)
if err != nil {
panic(err)
}

self.insecureClient = k8sClient
self.insecureAPIExtensionsClient = apiextensionsclient
self.insecurePluginClient = pluginclient
}

func (self *clientManager) initInsecureConfig() {
Expand Down
7 changes: 6 additions & 1 deletion src/app/backend/handler/apihandler.go
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,9 @@ import (
"strconv"
"strings"

restful "github.com/emicklei/go-restful"
"github.com/kubernetes/dashboard/src/app/backend/plugin"

"github.com/emicklei/go-restful"
"github.com/kubernetes/dashboard/src/app/backend/api"
"github.com/kubernetes/dashboard/src/app/backend/auth"
authApi "github.com/kubernetes/dashboard/src/app/backend/auth/api"
Expand Down Expand Up @@ -106,6 +108,9 @@ func CreateHTTPAPIHandler(iManager integration.IntegrationManager, cManager clie
integrationHandler := integration.NewIntegrationHandler(iManager)
integrationHandler.Install(apiV1Ws)

pluginHandler := plugin.NewPluginHandler(cManager)
pluginHandler.Install(apiV1Ws)

authHandler := auth.NewAuthHandler(authManager)
authHandler.Install(apiV1Ws)

Expand Down
20 changes: 20 additions & 0 deletions src/app/backend/plugin/apis/register.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
// Copyright 2017 The Kubernetes Authors.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

package apis

// GroupName is the group name used in this package
const (
GroupName = "dashboard.k8s.io"
)
19 changes: 19 additions & 0 deletions src/app/backend/plugin/apis/v1alpha1/doc.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
// Copyright 2017 The Kubernetes Authors.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

// +k8s:deepcopy-gen=package
// +groupName=dashboard.k8s.io

// Package v1alpha1 is the v1alpha1 version of the API.
package v1alpha1
53 changes: 53 additions & 0 deletions src/app/backend/plugin/apis/v1alpha1/register.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
// Copyright 2017 The Kubernetes Authors.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

package v1alpha1

import (
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/runtime"
"k8s.io/apimachinery/pkg/runtime/schema"

"github.com/kubernetes/dashboard/src/app/backend/plugin/apis"
)

// SchemeGroupVersion is group version used to register these objects
var SchemeGroupVersion = schema.GroupVersion{Group: apis.GroupName, Version: "v1alpha1"}

// Kind takes an unqualified kind and returns back a Group qualified GroupKind
func Kind(kind string) schema.GroupKind {
return SchemeGroupVersion.WithKind(kind).GroupKind()
}

// Resource takes an unqualified resource and returns a Group qualified GroupResource
func Resource(resource string) schema.GroupResource {
return SchemeGroupVersion.WithResource(resource).GroupResource()
}

var (
// SchemeBuilder initializes a scheme builder
SchemeBuilder = runtime.NewSchemeBuilder(addKnownTypes)
// AddToScheme is a global function that registers this API group & version to a scheme
AddToScheme = SchemeBuilder.AddToScheme
)

// Adds the list of known types to Scheme.
func addKnownTypes(scheme *runtime.Scheme) error {
scheme.AddKnownTypes(SchemeGroupVersion,
&Plugin{},
&PluginList{},
)
metav1.AddToGroupVersion(scheme, SchemeGroupVersion)
return nil
}
Loading

0 comments on commit 79e490c

Please sign in to comment.