-
Notifications
You must be signed in to change notification settings - Fork 8
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Watching for Kyma Custom Resource #7
Changes from all commits
a96042e
513f358
a8fcabb
bc05c0b
28c5a68
2d328d5
5422866
3cdb836
1eefe3a
d886495
c8669ad
b2b479e
bf79026
bb97a69
8196d8c
ace9b9a
f0f3c0a
0ecc24c
072ab87
9e5b6bf
eab88b4
7fa9906
ffdc016
84f7ab2
2d56740
f23343f
947a45a
e901238
e7919c3
d244c4d
b436cad
623034c
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,2 +1,8 @@ | ||
resources: | ||
- manager.yaml | ||
apiVersion: kustomize.config.k8s.io/v1beta1 | ||
kind: Kustomization | ||
images: | ||
- name: controller | ||
newName: mvshao/compass-manager | ||
newTag: latest |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,31 @@ | ||
# permissions for end users to edit compassmanagers. | ||
apiVersion: rbac.authorization.k8s.io/v1 | ||
kind: ClusterRole | ||
metadata: | ||
labels: | ||
app.kubernetes.io/name: clusterrole | ||
app.kubernetes.io/instance: compassmanager-editor-role | ||
app.kubernetes.io/component: rbac | ||
app.kubernetes.io/created-by: compass-manager | ||
app.kubernetes.io/part-of: compass-manager | ||
app.kubernetes.io/managed-by: kustomize | ||
name: compassmanager-editor-role | ||
rules: | ||
- apiGroups: | ||
- operator.kyma-project.io | ||
resources: | ||
- compassmanagers | ||
verbs: | ||
- create | ||
- delete | ||
- get | ||
- list | ||
- patch | ||
- update | ||
- watch | ||
- apiGroups: | ||
- operator.kyma-project.io | ||
resources: | ||
- compassmanagers/status | ||
verbs: | ||
- get |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,27 @@ | ||
# permissions for end users to view compassmanagers. | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Is it needed? |
||
apiVersion: rbac.authorization.k8s.io/v1 | ||
kind: ClusterRole | ||
metadata: | ||
labels: | ||
app.kubernetes.io/name: clusterrole | ||
app.kubernetes.io/instance: compassmanager-viewer-role | ||
app.kubernetes.io/component: rbac | ||
app.kubernetes.io/created-by: compass-manager | ||
app.kubernetes.io/part-of: compass-manager | ||
app.kubernetes.io/managed-by: kustomize | ||
name: compassmanager-viewer-role | ||
rules: | ||
- apiGroups: | ||
- operator.kyma-project.io | ||
resources: | ||
- compassmanagers | ||
verbs: | ||
- get | ||
- list | ||
- watch | ||
- apiGroups: | ||
- operator.kyma-project.io | ||
resources: | ||
- compassmanagers/status | ||
verbs: | ||
- get |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,38 @@ | ||
--- | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Is it needed? |
||
apiVersion: rbac.authorization.k8s.io/v1 | ||
kind: ClusterRole | ||
metadata: | ||
creationTimestamp: null | ||
name: manager-role | ||
rules: | ||
- apiGroups: | ||
- apiextensions.k8s.io | ||
resources: | ||
- customresourcedefinitions | ||
verbs: | ||
- get | ||
- list | ||
- watch | ||
- apiGroups: | ||
- "" | ||
resources: | ||
- secrets | ||
verbs: | ||
- get | ||
- list | ||
- watch | ||
- apiGroups: | ||
- operator.kyma-project.io | ||
resources: | ||
- kymas | ||
verbs: | ||
- get | ||
- list | ||
- update | ||
- watch | ||
- apiGroups: | ||
- operator.kyma-project.io | ||
resources: | ||
- kymas/status | ||
verbs: | ||
- get |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,12 @@ | ||
apiVersion: operator.kyma-project.io/v1beta1 | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Not needed, as Compass Manager doesn't need have its own CRD. |
||
kind: CompassManager | ||
metadata: | ||
labels: | ||
app.kubernetes.io/name: compassmanager | ||
app.kubernetes.io/instance: compassmanager-sample | ||
app.kubernetes.io/part-of: compass-manager | ||
app.kubernetes.io/managed-by: kustomize | ||
app.kubernetes.io/created-by: compass-manager | ||
name: compassmanager-sample | ||
spec: | ||
# TODO(user): Add fields here |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,182 @@ | ||
package controllers | ||
|
||
import ( | ||
"context" | ||
"time" | ||
|
||
corev1 "k8s.io/api/core/v1" | ||
"k8s.io/apimachinery/pkg/labels" | ||
|
||
kyma "github.com/kyma-project/lifecycle-manager/api/v1beta1" | ||
log "github.com/sirupsen/logrus" | ||
"k8s.io/apimachinery/pkg/runtime" | ||
"k8s.io/apimachinery/pkg/types" | ||
ctrl "sigs.k8s.io/controller-runtime" | ||
"sigs.k8s.io/controller-runtime/pkg/builder" | ||
"sigs.k8s.io/controller-runtime/pkg/client" | ||
"sigs.k8s.io/controller-runtime/pkg/event" | ||
"sigs.k8s.io/controller-runtime/pkg/manager" | ||
"sigs.k8s.io/controller-runtime/pkg/predicate" | ||
) | ||
|
||
const ( | ||
KymaNameLabel = "operator.kyma-project.io/kyma-name" | ||
CompassIDLabel = "operator.kyma-project.io/compass-id" | ||
// KubeconfigKey is the name of the key in the secret storing cluster credentials. | ||
// The secret is created by KEB: https://github.com/kyma-project/control-plane/blob/main/components/kyma-environment-broker/internal/process/steps/lifecycle_manager_kubeconfig.go | ||
KubeconfigKey = "config" | ||
) | ||
|
||
//+kubebuilder:rbac:groups=apiextensions.k8s.io,resources=customresourcedefinitions,verbs=get;list;watch | ||
//+kubebuilder:rbac:groups=operator.kyma-project.io,resources=kymas,verbs=get;list;watch;update | ||
//+kubebuilder:rbac:groups=operator.kyma-project.io,resources=kymas/status,verbs=get | ||
//+kubebuilder:rbac:groups=core,resources=secrets,verbs=get;list;watch | ||
|
||
//go:generate mockery --name=Registrator | ||
type Registrator interface { | ||
akgalwas marked this conversation as resolved.
Show resolved
Hide resolved
|
||
// Register creates Runtime in the Compass system. It must be idempotent. | ||
Register(name string) (string, error) | ||
// ConfigureRuntimeAgent creates a config map in the Runtime that is used by the Compass Runtime Agent. It must be idempotent. | ||
ConfigureRuntimeAgent(kubeconfig string, runtimeID string) error | ||
} | ||
|
||
type Client interface { | ||
Get(ctx context.Context, key client.ObjectKey, obj client.Object, opts ...client.GetOption) error | ||
Update(ctx context.Context, obj client.Object, opts ...client.UpdateOption) error | ||
List(ctx context.Context, obj client.ObjectList, opts ...client.ListOption) error | ||
} | ||
|
||
// CompassManagerReconciler reconciles a CompassManager object | ||
type CompassManagerReconciler struct { | ||
Client Client | ||
Scheme *runtime.Scheme | ||
Log *log.Logger | ||
Registrator Registrator | ||
} | ||
|
||
func NewCompassManagerReconciler(mgr manager.Manager, log *log.Logger, r Registrator) *CompassManagerReconciler { | ||
return &CompassManagerReconciler{ | ||
Client: mgr.GetClient(), | ||
Scheme: mgr.GetScheme(), | ||
Log: log, | ||
Registrator: r, | ||
} | ||
} | ||
|
||
var requeueTime = time.Minute * 5 | ||
|
||
func (cm *CompassManagerReconciler) Reconcile(ctx context.Context, req ctrl.Request) (ctrl.Result, error) { | ||
|
||
cm.Log.Infof("Reconciliation triggered for Kyma Resource %s", req.Name) | ||
kubeconfig, err := cm.getKubeconfig(req.Name) | ||
if err != nil { | ||
return ctrl.Result{}, err | ||
} | ||
|
||
if kubeconfig == "" { | ||
cm.Log.Infof("Kubeconfig for Kyma resource %s not available.", req.Name) | ||
return ctrl.Result{RequeueAfter: requeueTime}, nil | ||
akgalwas marked this conversation as resolved.
Show resolved
Hide resolved
|
||
} | ||
|
||
compassRuntimeID, err := cm.Registrator.Register(req.Name) | ||
if err != nil { | ||
cm.Log.Warnf("Failed to register Runtime for Kyma resource %s: %v.", req.Name, err) | ||
return ctrl.Result{RequeueAfter: requeueTime}, err | ||
} | ||
cm.Log.Infof("Runtime %s registered for Kyma resource %s.", compassRuntimeID, req.Name) | ||
|
||
err = cm.Registrator.ConfigureRuntimeAgent(kubeconfig, compassRuntimeID) | ||
if err != nil { | ||
cm.Log.Warnf("Failed to configure Compass Runtime Agent for Kyma resource %s: %v.", req.Name, err) | ||
return ctrl.Result{RequeueAfter: requeueTime}, err | ||
} | ||
cm.Log.Infof("Compass Runtime Agent for Runtime %s configured.", compassRuntimeID) | ||
|
||
return ctrl.Result{}, cm.markRuntimeRegistered(req.NamespacedName, compassRuntimeID) | ||
} | ||
|
||
func (cm *CompassManagerReconciler) getKubeconfig(kymaName string) (string, error) { | ||
secretList := &corev1.SecretList{} | ||
labelSelector := labels.SelectorFromSet(map[string]string{ | ||
KymaNameLabel: kymaName, | ||
}) | ||
|
||
err := cm.Client.List(context.Background(), secretList, &client.ListOptions{ | ||
LabelSelector: labelSelector, | ||
}) | ||
|
||
if err != nil { | ||
return "", err | ||
} | ||
|
||
if len(secretList.Items) == 0 { | ||
return "", nil | ||
} | ||
secret := &secretList.Items[0] | ||
|
||
return string(secret.Data[KubeconfigKey]), nil | ||
} | ||
|
||
func (cm *CompassManagerReconciler) markRuntimeRegistered(objKey types.NamespacedName, compassID string) error { | ||
|
||
instance := &kyma.Kyma{} | ||
err := cm.Client.Get(context.Background(), objKey, instance) | ||
if err != nil { | ||
return err | ||
} | ||
|
||
l := instance.GetLabels() | ||
if l == nil { | ||
l = make(map[string]string) | ||
} | ||
|
||
l[CompassIDLabel] = compassID | ||
|
||
instance.SetLabels(l) | ||
|
||
return cm.Client.Update(context.Background(), instance) | ||
} | ||
|
||
// SetupWithManager sets up the controller with the Manager. | ||
func (cm *CompassManagerReconciler) SetupWithManager(mgr ctrl.Manager) error { | ||
fieldSelectorPredicate := predicate.Funcs{ | ||
akgalwas marked this conversation as resolved.
Show resolved
Hide resolved
|
||
CreateFunc: func(e event.CreateEvent) bool { | ||
return cm.needsToBeReconciled(e.Object) | ||
}, | ||
UpdateFunc: func(e event.UpdateEvent) bool { | ||
return cm.needsToBeReconciled(e.ObjectNew) | ||
}, | ||
} | ||
|
||
omitStatusChanged := predicate.Or( | ||
predicate.GenerationChangedPredicate{}, | ||
predicate.LabelChangedPredicate{}, | ||
predicate.AnnotationChangedPredicate{}, | ||
) | ||
|
||
// We can simplify passing the predicate filters to controller | ||
// The predicates passed in For(builder.WithPredicates()) function is merged with runner.WithEventFilter() predicates to single slice with predicates. | ||
// Proposal: delete the predicates from For() functions, and return runner.WithEventFilter(fieldSelectorPredicate).WithEventFilter(predicates).Complete(cm) | ||
|
||
runner := ctrl.NewControllerManagedBy(mgr). | ||
For(&kyma.Kyma{}, builder.WithPredicates( | ||
predicate.And( | ||
predicate.ResourceVersionChangedPredicate{}, | ||
omitStatusChanged, | ||
))) | ||
|
||
return runner.WithEventFilter(fieldSelectorPredicate).Complete(cm) | ||
} | ||
|
||
func (cm *CompassManagerReconciler) needsToBeReconciled(obj runtime.Object) bool { | ||
|
||
kymaObj, ok := obj.(*kyma.Kyma) | ||
|
||
if !ok { | ||
cm.Log.Error("Unexpected type detected. Object type is supposed to be of Kyma type.") | ||
return false | ||
} | ||
_, labelFound := kymaObj.GetLabels()[CompassIDLabel] | ||
|
||
return !labelFound | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think it is not needed