From 0d2279f5e497e59966aaa8c5f2cfb53156cc56ce Mon Sep 17 00:00:00 2001 From: hongming Date: Sun, 29 Mar 2020 00:35:00 +0800 Subject: [PATCH] fix somme error in controller-manager Signed-off-by: hongming --- cmd/controller-manager/app/controllers.go | 7 +++ cmd/controller-manager/app/server.go | 6 ++- config/crds/iam.kubesphere.io_users.yaml | 7 ++- config/samples/iam_v1alpha2_user.yaml | 6 +-- pkg/apis/iam/v1alpha2/user_types.go | 23 +++++---- pkg/apis/iam/v1alpha2/user_types_test.go | 30 ++++++----- .../namespace/namespace_controller.go | 51 ------------------- pkg/controller/user/user_controller.go | 12 +++-- pkg/controller/user/user_controller_test.go | 2 +- pkg/informers/informers.go | 2 +- pkg/kapis/oauth/register.go | 24 ++++++++- pkg/kapis/serverconfig/v1alpha2/register.go | 18 ++++--- pkg/simple/client/k8s/kubernetes.go | 6 +++ 13 files changed, 96 insertions(+), 98 deletions(-) diff --git a/cmd/controller-manager/app/controllers.go b/cmd/controller-manager/app/controllers.go index 3a739c943..5c471ee69 100644 --- a/cmd/controller-manager/app/controllers.go +++ b/cmd/controller-manager/app/controllers.go @@ -25,6 +25,7 @@ import ( "kubesphere.io/kubesphere/pkg/controller/s2ibinary" "kubesphere.io/kubesphere/pkg/controller/s2irun" "kubesphere.io/kubesphere/pkg/controller/storage/expansion" + "kubesphere.io/kubesphere/pkg/controller/user" "kubesphere.io/kubesphere/pkg/controller/virtualservice" "kubesphere.io/kubesphere/pkg/informers" "kubesphere.io/kubesphere/pkg/simple/client/k8s" @@ -87,6 +88,11 @@ func AddControllers( kubernetesInformer.Apps().V1().ReplicaSets(), kubernetesInformer.Apps().V1().StatefulSets()) + userController := user.NewController( + client.Kubernetes(), + client.KubeSphere(), + kubesphereInformer.Iam().V1alpha2().Users()) + controllers := map[string]manager.Runnable{ "virtualservice-controller": vsController, "destinationrule-controller": drController, @@ -95,6 +101,7 @@ func AddControllers( "s2ibinary-controller": s2iBinaryController, "s2irun-controller": s2iRunController, "volumeexpansion-controller": volumeExpansionController, + "user-controller": userController, } for name, ctrl := range controllers { diff --git a/cmd/controller-manager/app/server.go b/cmd/controller-manager/app/server.go index 6aa8e3c85..647fb9c98 100644 --- a/cmd/controller-manager/app/server.go +++ b/cmd/controller-manager/app/server.go @@ -49,11 +49,13 @@ func NewControllerManagerCommand() *cobra.Command { s := options.NewKubeSphereControllerManagerOptions() conf, err := controllerconfig.TryLoadFromDisk() if err == nil { + // make sure LeaderElection is not nil s = &options.KubeSphereControllerManagerOptions{ KubernetesOptions: conf.KubernetesOptions, DevopsOptions: conf.DevopsOptions, S3Options: conf.S3Options, OpenPitrixOptions: conf.OpenPitrixOptions, + LeaderElection: s.LeaderElection, } } @@ -118,7 +120,6 @@ func Run(s *options.KubeSphereControllerManagerOptions, stopCh <-chan struct{}) */ informerFactory := informers.NewInformerFactories(kubernetesClient.Kubernetes(), kubernetesClient.KubeSphere(), kubernetesClient.Istio(), kubernetesClient.Application()) - informerFactory.Start(stopCh) run := func(ctx context.Context) { klog.V(0).Info("setting up manager") @@ -147,6 +148,9 @@ func Run(s *options.KubeSphereControllerManagerOptions, stopCh <-chan struct{}) klog.Fatalf("unable to register controllers to the manager: %v", err) } + // Start cache data after all informer is registered + informerFactory.Start(stopCh) + klog.V(0).Info("Starting the controllers.") if err = mgr.Start(stopCh); err != nil { klog.Fatalf("unable to run the manager: %v", err) diff --git a/config/crds/iam.kubesphere.io_users.yaml b/config/crds/iam.kubesphere.io_users.yaml index 9b1fde0ee..eec35e012 100644 --- a/config/crds/iam.kubesphere.io_users.yaml +++ b/config/crds/iam.kubesphere.io_users.yaml @@ -12,6 +12,9 @@ spec: - JSONPath: .spec.email name: Email type: string + - JSONPath: .status.state + name: Status + type: string group: iam.kubesphere.io names: categories: @@ -94,8 +97,8 @@ spec: - type type: object type: array - phase: - description: Phase is the phase of the user. + state: + description: The user status type: string type: object required: diff --git a/config/samples/iam_v1alpha2_user.yaml b/config/samples/iam_v1alpha2_user.yaml index 6820fd744..8bd165623 100644 --- a/config/samples/iam_v1alpha2_user.yaml +++ b/config/samples/iam_v1alpha2_user.yaml @@ -3,7 +3,7 @@ kind: User metadata: labels: controller-tools.k8s.io: "1.0" - name: user-sample + name: admin spec: - # Add fields here - foo: bar + email: admin@kubesphere.io + password: d41d8cd98f00b204e9800998ecf8427e diff --git a/pkg/apis/iam/v1alpha2/user_types.go b/pkg/apis/iam/v1alpha2/user_types.go index 9158f6ed5..ee9034af7 100644 --- a/pkg/apis/iam/v1alpha2/user_types.go +++ b/pkg/apis/iam/v1alpha2/user_types.go @@ -29,6 +29,7 @@ import ( // +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object // +genclient:nonNamespaced // +kubebuilder:printcolumn:name="Email",type="string",JSONPath=".spec.email" +// +kubebuilder:printcolumn:name="Status",type="string",JSONPath=".status.state" // +kubebuilder:resource:categories="iam",scope="Cluster" type User struct { metav1.TypeMeta `json:",inline"` @@ -62,40 +63,40 @@ type UserSpec struct { Finalizers []FinalizerName `json:"finalizers,omitempty"` } -type UserPhase string +type UserState string // These are the valid phases of a user. const ( // UserActive means the user is available. - UserActive UserPhase = "Active" + UserActive UserState = "Active" // UserDisabled means the user is disabled. - UserDisabled UserPhase = "Disabled" + UserDisabled UserState = "Disabled" ) // UserStatus defines the observed state of User type UserStatus struct { - // Phase is the phase of the user. + // The user status // +optional - Phase UserPhase `json:"phase,omitempty" protobuf:"bytes,1,opt,name=phase,casttype=UserPhase"` + State UserState `json:"state,omitempty"` // Represents the latest available observations of a namespace's current state. // +optional // +patchMergeKey=type // +patchStrategy=merge - Conditions []UserCondition `json:"conditions,omitempty" patchStrategy:"merge" patchMergeKey:"type" protobuf:"bytes,2,rep,name=conditions"` + Conditions []UserCondition `json:"conditions,omitempty"` } type UserCondition struct { // Type of namespace controller condition. - Type UserConditionType `json:"type" protobuf:"bytes,1,opt,name=type,casttype=NamespaceConditionType"` + Type UserConditionType `json:"type"` // Status of the condition, one of True, False, Unknown. - Status ConditionStatus `json:"status" protobuf:"bytes,2,opt,name=status,casttype=ConditionStatus"` + Status ConditionStatus `json:"status"` // +optional - LastTransitionTime metav1.Time `json:"lastTransitionTime,omitempty" protobuf:"bytes,4,opt,name=lastTransitionTime"` + LastTransitionTime metav1.Time `json:"lastTransitionTime,omitempty"` // +optional - Reason string `json:"reason,omitempty" protobuf:"bytes,5,opt,name=reason"` + Reason string `json:"reason,omitempty"` // +optional - Message string `json:"message,omitempty" protobuf:"bytes,6,opt,name=message"` + Message string `json:"message,omitempty"` } type UserConditionType string diff --git a/pkg/apis/iam/v1alpha2/user_types_test.go b/pkg/apis/iam/v1alpha2/user_types_test.go index 2146c1a87..a47667ef7 100644 --- a/pkg/apis/iam/v1alpha2/user_types_test.go +++ b/pkg/apis/iam/v1alpha2/user_types_test.go @@ -1,18 +1,20 @@ /* -Copyright 2019 The KubeSphere 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. -*/ + * + * Copyright 2020 The KubeSphere 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 v1alpha2 diff --git a/pkg/controller/namespace/namespace_controller.go b/pkg/controller/namespace/namespace_controller.go index 9a2f38228..42af07656 100644 --- a/pkg/controller/namespace/namespace_controller.go +++ b/pkg/controller/namespace/namespace_controller.go @@ -24,7 +24,6 @@ import ( "github.com/golang/protobuf/ptypes/wrappers" appsv1 "k8s.io/api/apps/v1" corev1 "k8s.io/api/core/v1" - rbac "k8s.io/api/rbac/v1" "k8s.io/apimachinery/pkg/api/errors" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/runtime" @@ -44,22 +43,6 @@ import ( "sigs.k8s.io/controller-runtime/pkg/source" ) -const ( - adminDescription = "Allows admin access to perform any action on any resource, it gives full control over every resource in the namespace." - operatorDescription = "The maintainer of the namespace who can manage resources other than users and roles in the namespace." - viewerDescription = "Allows viewer access to view all resources in the namespace." -) - -var ( - admin = rbac.Role{ObjectMeta: metav1.ObjectMeta{Name: "admin", Annotations: map[string]string{constants.DescriptionAnnotationKey: adminDescription, constants.CreatorAnnotationKey: constants.System}}, Rules: []rbac.PolicyRule{{Verbs: []string{"*"}, APIGroups: []string{"*"}, Resources: []string{"*"}}}} - operator = rbac.Role{ObjectMeta: metav1.ObjectMeta{Name: "operator", Annotations: map[string]string{constants.DescriptionAnnotationKey: operatorDescription, constants.CreatorAnnotationKey: constants.System}}, Rules: []rbac.PolicyRule{{Verbs: []string{"get", "list", "watch"}, APIGroups: []string{"*"}, Resources: []string{"*"}}, - {Verbs: []string{"*"}, APIGroups: []string{"apps", "extensions", "batch", "logging.kubesphere.io", "monitoring.kubesphere.io", "iam.kubesphere.io", "autoscaling", "alerting.kubesphere.io", "openpitrix.io", "app.k8s.io", "servicemesh.kubesphere.io", "operations.kubesphere.io", "devops.kubesphere.io"}, Resources: []string{"*"}}, - {Verbs: []string{"*"}, APIGroups: []string{"", "resources.kubesphere.io"}, Resources: []string{"jobs", "cronjobs", "daemonsets", "deployments", "horizontalpodautoscalers", "ingresses", "endpoints", "configmaps", "events", "persistentvolumeclaims", "pods", "podtemplates", "pods", "secrets", "services"}}, - }} - viewer = rbac.Role{ObjectMeta: metav1.ObjectMeta{Name: "viewer", Annotations: map[string]string{constants.DescriptionAnnotationKey: viewerDescription, constants.CreatorAnnotationKey: constants.System}}, Rules: []rbac.PolicyRule{{Verbs: []string{"get", "list", "watch"}, APIGroups: []string{"*"}, Resources: []string{"*"}}}} - defaultRoles = []rbac.Role{admin, operator, viewer} -) - /** * USER ACTION REQUIRED: This is a scaffold file intended for the user to modify with their own Controller * business logic. Delete these comments after modifying this file.* @@ -164,19 +147,6 @@ func (r *ReconcileNamespace) Reconcile(request reconcile.Request) (reconcile.Res return reconcile.Result{}, nil } - controlledByWorkspace, err := r.isControlledByWorkspace(instance) - - if err != nil { - return reconcile.Result{}, err - } - - if !controlledByWorkspace { - - err = r.deleteRoleBindings(instance) - - return reconcile.Result{}, err - } - if err = r.checkAndBindWorkspace(instance); err != nil { return reconcile.Result{}, err } @@ -357,24 +327,3 @@ func (r *ReconcileNamespace) deleteRouter(namespace string) error { return nil } - -func (r *ReconcileNamespace) deleteRoleBindings(namespace *corev1.Namespace) error { - klog.V(4).Info("deleting role bindings namespace: ", namespace.Name) - adminBinding := &rbac.RoleBinding{} - adminBinding.Name = admin.Name - adminBinding.Namespace = namespace.Name - err := r.Delete(context.TODO(), adminBinding) - if err != nil && !errors.IsNotFound(err) { - klog.Errorf("deleting role binding namespace: %s, role binding: %s,error: %s", namespace.Name, adminBinding.Name, err) - return err - } - viewerBinding := &rbac.RoleBinding{} - viewerBinding.Name = viewer.Name - viewerBinding.Namespace = namespace.Name - err = r.Delete(context.TODO(), viewerBinding) - if err != nil && !errors.IsNotFound(err) { - klog.Errorf("deleting role binding namespace: %s,role binding: %s,error: %s", namespace.Name, viewerBinding.Name, err) - return err - } - return nil -} diff --git a/pkg/controller/user/user_controller.go b/pkg/controller/user/user_controller.go index c31117bed..7ab3557a6 100644 --- a/pkg/controller/user/user_controller.go +++ b/pkg/controller/user/user_controller.go @@ -66,7 +66,6 @@ type Controller struct { func NewController(kubeclientset kubernetes.Interface, kubesphereklientset kubesphereclient.Interface, userInformer userinformer.UserInformer) *Controller { - // Create event broadcaster // Add sample-controller types to the default Kubernetes Scheme so Events can be // logged for sample-controller types. @@ -180,7 +179,7 @@ func (c *Controller) processNextWorkItem() bool { // Finally, if no error occurs we Forget this item so it does not // get queued again until another change happens. c.workqueue.Forget(obj) - klog.Info("Successfully synced", "key", key) + klog.Infof("Successfully synced %s:%s", "key", key) return nil }(obj) @@ -206,11 +205,11 @@ func (c *Controller) reconcile(key string) error { utilruntime.HandleError(fmt.Errorf("user '%s' in work queue no longer exists", key)) return nil } - return err } err = c.updateUserStatus(user) + if err != nil { return err } @@ -220,9 +219,12 @@ func (c *Controller) reconcile(key string) error { } func (c *Controller) updateUserStatus(user *iamv1alpha2.User) error { - userCopy := user.DeepCopy() - userCopy.Status.Phase = iamv1alpha2.UserActive + userCopy.Status.State = iamv1alpha2.UserActive _, err := c.kubesphereClientset.IamV1alpha2().Users().Update(userCopy) return err } + +func (c *Controller) Start(stopCh <-chan struct{}) error { + return c.Run(4, stopCh) +} diff --git a/pkg/controller/user/user_controller_test.go b/pkg/controller/user/user_controller_test.go index bf364b9e6..60b3afc06 100644 --- a/pkg/controller/user/user_controller_test.go +++ b/pkg/controller/user/user_controller_test.go @@ -219,7 +219,7 @@ func filterInformerActions(actions []core.Action) []core.Action { func (f *fixture) expectUpdateUserStatusAction(user *iamv1alpha2.User) { expect := user.DeepCopy() - expect.Status.Phase = iamv1alpha2.UserActive + expect.Status.State = iamv1alpha2.UserActive action := core.NewUpdateAction(schema.GroupVersionResource{Resource: "users"}, "", expect) f.actions = append(f.actions, action) } diff --git a/pkg/informers/informers.go b/pkg/informers/informers.go index bbc6a83c6..36a3bd6a7 100644 --- a/pkg/informers/informers.go +++ b/pkg/informers/informers.go @@ -98,7 +98,7 @@ func (f *informerFactories) Start(stopCh <-chan struct{}) { f.ksInformerFactory.Start(stopCh) } - if f.informerFactory != nil { + if f.istioInformerFactory != nil { f.istioInformerFactory.Start(stopCh) } diff --git a/pkg/kapis/oauth/register.go b/pkg/kapis/oauth/register.go index e27e9b74e..81d2bb426 100644 --- a/pkg/kapis/oauth/register.go +++ b/pkg/kapis/oauth/register.go @@ -47,7 +47,8 @@ func AddToContainer(c *restful.Container, issuer token.Issuer, options *authopti // Implement webhook authentication interface // https://kubernetes.io/docs/reference/access-authn-authz/authentication/#webhook-token-authentication ws.Route(ws.POST("/authenticate"). - Doc("TokenReview attempts to authenticate a token to a known user. Note: TokenReview requests may be cached by the webhook token authenticator plugin in the kube-apiserver."). + Doc("TokenReview attempts to authenticate a token to a known user. Note: TokenReview requests may be "+ + "cached by the webhook token authenticator plugin in the kube-apiserver."). Reads(auth.TokenReview{}). To(handler.TokenReviewHandler). Returns(http.StatusOK, api.StatusOK, auth.TokenReview{}). @@ -57,6 +58,14 @@ func AddToContainer(c *restful.Container, issuer token.Issuer, options *authopti // https://tools.ietf.org/html/rfc6749#section-4.2 ws.Route(ws.GET("/authorize"). Doc("All requests for OAuth tokens involve a request to /oauth/authorize."). + Param(ws.QueryParameter("response_type", "The value MUST be one of \"code\" for requesting an "+ + "authorization code as described by [RFC6749] Section 4.1.1, \"token\" for requesting an access token (implicit grant)"+ + " as described by [RFC6749] Section 4.2.2.").Required(true)). + Param(ws.QueryParameter("client_id", "The client identifier issued to the client during the "+ + "registration process described by [RFC6749] Section 2.2.").Required(true)). + Param(ws.QueryParameter("redirect_uri", "After completing its interaction with the resource owner, "+ + "the authorization server directs the resource owner's user-agent back to the client.The redirection endpoint "+ + "URI MUST be an absolute URI as defined by [RFC3986] Section 4.3.").Required(false)). To(handler.AuthorizeHandler)) //ws.Route(ws.POST("/token")) @@ -64,6 +73,19 @@ func AddToContainer(c *restful.Container, issuer token.Issuer, options *authopti // The provider name is also used to build the callback URL. ws.Route(ws.GET("/callback/{callback}"). Doc("OAuth callback API, the path param callback is config by identity provider"). + Param(ws.QueryParameter("access_token", "The access token issued by the authorization server."). + Required(true)). + Param(ws.QueryParameter("token_type", "The type of the token issued as described in [RFC6479] Section 7.1. "+ + "Value is case insensitive.").Required(true)). + Param(ws.QueryParameter("expires_in", "The lifetime in seconds of the access token. For "+ + "example, the value \"3600\" denotes that the access token will "+ + "expire in one hour from the time the response was generated."+ + "If omitted, the authorization server SHOULD provide the "+ + "expiration time via other means or document the default value.")). + Param(ws.QueryParameter("scope", "if identical to the scope requested by the client;"+ + "otherwise, REQUIRED. The scope of the access token as described by [RFC6479] Section 3.3.").Required(false)). + Param(ws.QueryParameter("state", "if the \"state\" parameter was present in the client authorization request."+ + "The exact value received from the client.").Required(true)). To(handler.OAuthCallBackHandler). Returns(http.StatusOK, api.StatusOK, oauth.Token{})) diff --git a/pkg/kapis/serverconfig/v1alpha2/register.go b/pkg/kapis/serverconfig/v1alpha2/register.go index 739a31c02..785d9c5a1 100644 --- a/pkg/kapis/serverconfig/v1alpha2/register.go +++ b/pkg/kapis/serverconfig/v1alpha2/register.go @@ -34,15 +34,17 @@ var GroupVersion = schema.GroupVersion{Group: GroupName, Version: "v1alpha2"} func AddToContainer(c *restful.Container, config *apiserverconfig.Config) error { webservice := runtime.NewWebService(GroupVersion) - // information about the authorization server are published. - webservice.Route(webservice.GET("/configs/oauth").To(func(request *restful.Request, response *restful.Response) { - response.WriteEntity(config.AuthenticationOptions.OAuthOptions) - })) + webservice.Route(webservice.GET("/configs/oauth"). + Doc("Information about the authorization server are published."). + To(func(request *restful.Request, response *restful.Response) { + response.WriteEntity(config.AuthenticationOptions.OAuthOptions) + })) - // information about the server configuration - webservice.Route(webservice.GET("/configs/configz").To(func(request *restful.Request, response *restful.Response) { - response.WriteAsJson(config.ToMap()) - })) + webservice.Route(webservice.GET("/configs/configz"). + Doc("Information about the server configuration"). + To(func(request *restful.Request, response *restful.Response) { + response.WriteAsJson(config.ToMap()) + })) c.Add(webservice) return nil diff --git a/pkg/simple/client/k8s/kubernetes.go b/pkg/simple/client/k8s/kubernetes.go index 32bf5796c..c46e51b18 100644 --- a/pkg/simple/client/k8s/kubernetes.go +++ b/pkg/simple/client/k8s/kubernetes.go @@ -98,6 +98,12 @@ func NewKubernetesClient(options *KubernetesOptions) (Client, error) { return nil, err } + k.istio, err = istioclient.NewForConfig(config) + + if err != nil { + return nil, err + } + k.master = options.Master k.config = config