fix somme error in controller-manager
Signed-off-by: hongming <talonwan@yunify.com>
This commit is contained in:
@@ -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 {
|
||||
|
||||
@@ -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)
|
||||
|
||||
7
config/crds/iam.kubesphere.io_users.yaml
generated
7
config/crds/iam.kubesphere.io_users.yaml
generated
@@ -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:
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
@@ -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
|
||||
}
|
||||
|
||||
@@ -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)
|
||||
}
|
||||
|
||||
@@ -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)
|
||||
}
|
||||
|
||||
@@ -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)
|
||||
}
|
||||
|
||||
|
||||
@@ -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 <ks-apiserver>/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{}))
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
Reference in New Issue
Block a user