Skip to content
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

Implement Eventing Auth Kyma Controller #16

Merged
merged 5 commits into from
May 9, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
20 changes: 13 additions & 7 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -150,35 +150,41 @@ kubectl create ns kcp-system
kubectl create secret generic eventing-auth-ias-creds -n kcp-system --from-literal=username=$TEST_EVENTING_AUTH_IAS_USER --from-literal=password=$TEST_EVENTING_AUTH_IAS_PASSWORD --from-literal=url=$TEST_EVENTING_AUTH_IAS_URL
```

3. Create the secret containing the kubeconfig of the cluster on which the "eventing-webhook-auth" secret is created by specifying `PATH_TO_TARGET_CLUSTER_KUBECONFIG` and `EVENTING_AUTH_CR_NAME`:
3. Create the secret containing the kubeconfig of the cluster on which the "eventing-webhook-auth" secret is created by specifying `PATH_TO_TARGET_CLUSTER_KUBECONFIG` and `KYMA_CR_NAME`:

```sh
kubectl create secret generic kubeconfig-$EVENTING_AUTH_CR_NAME -n kcp-system --from-file=config=$PATH_TO_TARGET_CLUSTER_KUBECONFIG
kubectl create secret generic kubeconfig-$KYMA_CR_NAME -n kcp-system --from-file=config=$PATH_TO_TARGET_CLUSTER_KUBECONFIG
```

#### Prepare the secret target cluster
#### Prepare the target cluster
Create the namespace in which the "eventing-webhook-auth" secret is created on the target cluster:

```sh
kubectl create ns kyma-system
```

### Running on the cluster
1. Update name of Custom Resource in `config/samples/eventing_v1alpha1_eventingauth.yaml` to contain the name of the kubeconfig secret created in [Preparing the clusters](#preparing-the-clusters).
1. Install the Kyma and EventingAuth CRDs:
```sh
make install
```

2. Update name of Custom Resource in `config/samples/operator_v1beta1_kyma.yaml` to contain the name of the kubeconfig secret created in [Preparing the clusters](#preparing-the-clusters).
The Kyma CR name is equal to target K8s cluster name too.

2. Install Instances of Custom Resources:
3. Install Instances of Custom Resources:

```sh
kubectl apply -f config/samples/
```

3. Build and push your image to the location specified by `IMG`:
4. Build and push your image to the location specified by `IMG`:

```sh
make docker-build docker-push IMG=<some-registry>/eventing-auth-manager:tag
```

4. Deploy the controller to the cluster with the image specified by `IMG`:
5. Deploy the controller to the cluster with the image specified by `IMG`:

```sh
make deploy IMG=<some-registry>/eventing-auth-manager:tag
Expand Down
12 changes: 10 additions & 2 deletions cmd/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ package main
import (
"flag"
"github.com/kyma-project/eventing-auth-manager/controllers"
kymav1beta1 "github.com/kyma-project/lifecycle-manager/api/v1beta1"
"os"
"time"

Expand Down Expand Up @@ -50,6 +51,8 @@ var (
func init() {
utilruntime.Must(clientgoscheme.AddToScheme(scheme))

utilruntime.Must(kymav1beta1.AddToScheme(scheme))

utilruntime.Must(operatorv1alpha1.AddToScheme(scheme))
//+kubebuilder:scaffold:scheme
}
Expand Down Expand Up @@ -95,9 +98,14 @@ func main() {
os.Exit(1)
}

reconciler := controllers.NewEventingAuthReconciler(mgr.GetClient(), mgr.GetScheme(), requeueAfterError, requeueAfter)
kymaReconciler := controllers.NewKymaReconciler(mgr.GetClient(), mgr.GetScheme(), requeueAfterError, requeueAfter)
if err = kymaReconciler.SetupWithManager(mgr); err != nil {
setupLog.Error(err, "unable to create controller", "controller", "Kyma")
os.Exit(1)
}

if err = reconciler.SetupWithManager(mgr); err != nil {
eventingAuthReconciler := controllers.NewEventingAuthReconciler(mgr.GetClient(), mgr.GetScheme(), requeueAfterError, requeueAfter)
if err = eventingAuthReconciler.SetupWithManager(mgr); err != nil {
setupLog.Error(err, "unable to create controller", "controller", "EventingAuth")
os.Exit(1)
}
Expand Down
723 changes: 723 additions & 0 deletions config/crd/external/operator.kyma-project.io_kymas.yaml

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion config/default/kustomization.yaml
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
# Adds namespace to all resources.
namespace: kyma-system
namespace: kcp-system

# Value of this field is prepended to the
# names of all resources, e.g. a deployment named
Expand Down
13 changes: 0 additions & 13 deletions config/manager/manager.yaml
Original file line number Diff line number Diff line change
@@ -1,16 +1,3 @@
apiVersion: v1
kind: Namespace
metadata:
labels:
control-plane: controller-manager
app.kubernetes.io/name: namespace
app.kubernetes.io/instance: system
app.kubernetes.io/component: manager
app.kubernetes.io/created-by: eventing-auth-manager
app.kubernetes.io/part-of: eventing-auth-manager
app.kubernetes.io/managed-by: kustomize
name: system
---
apiVersion: apps/v1
kind: Deployment
metadata:
Expand Down
7 changes: 7 additions & 0 deletions config/rbac/role.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,13 @@ rules:
verbs:
- list
- watch
- apiGroups:
- operator.kyma-project.io
resources:
- kymas
verbs:
- list
- watch
- apiGroups:
- operator.kyma-project.io
resources:
Expand Down
2 changes: 1 addition & 1 deletion config/samples/kustomization.yaml
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
## Append samples of your project ##
resources:
- operator_v1alpha1_eventingauth.yaml
- operator_v1beta1_kyma.yaml
#+kubebuilder:scaffold:manifestskustomizesamples
11 changes: 0 additions & 11 deletions config/samples/operator_v1alpha1_eventingauth.yaml

This file was deleted.

8 changes: 8 additions & 0 deletions config/samples/operator_v1beta1_kyma.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
apiVersion: operator.kyma-project.io/v1beta1
kind: Kyma
metadata:
name: kyma1
spec:
modules:
- name: sample-module
channel: alpha
2 changes: 1 addition & 1 deletion controllers/eventingauth_controller_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ var appSecretObjectKey = ctrlClient.ObjectKey{Name: "eventing-webhook-auth", Nam
// Since all tests use the same target cluster and therefore share the same application secret, they need to be executed serially
var _ = Describe("EventingAuth Controller", Serial, func() {

BeforeEach(func() {
AfterEach(func() {
muralov marked this conversation as resolved.
Show resolved Hide resolved
deleteEventingAuths()
// We also need to clean up the app secret before each test, because a failing test could leave the secret in the cluster and this can lead to cascading failures.
deleteApplicationSecretOnTargetCluster()
Expand Down
96 changes: 96 additions & 0 deletions controllers/kyma_controller.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,96 @@
package controllers

import (
"context"
"fmt"
"github.com/kyma-project/eventing-auth-manager/api/v1alpha1"
kymav1beta1 "github.com/kyma-project/lifecycle-manager/api/v1beta1"
apiErrors "k8s.io/apimachinery/pkg/api/errors"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/runtime"
"k8s.io/apimachinery/pkg/types"
ctrl "sigs.k8s.io/controller-runtime"
"sigs.k8s.io/controller-runtime/pkg/client"
"sigs.k8s.io/controller-runtime/pkg/controller/controllerutil"
"sigs.k8s.io/controller-runtime/pkg/log"
"time"
)

// KymaReconciler reconciles a Kyma resource
type KymaReconciler struct {
client.Client
Scheme *runtime.Scheme
errorRequeuePeriod time.Duration
defaultRequeuePeriod time.Duration
}

func NewKymaReconciler(c client.Client, s *runtime.Scheme, errorRequeuePeriod time.Duration, defaultRequeuePeriod time.Duration) *KymaReconciler {
return &KymaReconciler{
Client: c,
Scheme: s,
errorRequeuePeriod: errorRequeuePeriod,
defaultRequeuePeriod: defaultRequeuePeriod,
}
}

// +kubebuilder:rbac:groups=operator.kyma-project.io,resources=kymas,verbs=get;list;watch
// +kubebuilder:rbac:groups=operator.kyma-project.io,resources=eventingauths,verbs=get;list;watch;create;update;patch;delete
// +kubebuilder:rbac:groups=operator.kyma-project.io,resources=eventingauths/status,verbs=get;list
func (r *KymaReconciler) Reconcile(ctx context.Context, req ctrl.Request) (ctrl.Result, error) {
logger := log.FromContext(ctx)
logger.Info("Reconciling Kyma resource")

kyma := &kymav1beta1.Kyma{}
err := r.Client.Get(ctx, req.NamespacedName, kyma)
if err != nil {
if apiErrors.IsNotFound(err) {
return ctrl.Result{}, nil
}
return ctrl.Result{
RequeueAfter: r.errorRequeuePeriod,
}, err
}

if err = r.createEventingAuth(ctx, kyma); err != nil {
return ctrl.Result{
RequeueAfter: r.errorRequeuePeriod,
}, err
}

return ctrl.Result{
RequeueAfter: r.defaultRequeuePeriod,
}, nil
}

func (r *KymaReconciler) createEventingAuth(ctx context.Context, kyma *kymav1beta1.Kyma) error {
eventingAuth := &v1alpha1.EventingAuth{
ObjectMeta: metav1.ObjectMeta{
Namespace: kyma.Namespace,
Name: kyma.Name,
},
}

err := r.Client.Get(ctx, types.NamespacedName{Namespace: eventingAuth.Namespace, Name: eventingAuth.Name}, eventingAuth)
if err != nil {
if apiErrors.IsNotFound(err) {
if err = controllerutil.SetControllerReference(kyma, eventingAuth, r.Scheme); err != nil {
return err
}
err = r.Client.Create(ctx, eventingAuth)
if err != nil {
return fmt.Errorf("failed to create EventingAuth resource: %v", err)
}
return nil
}
return fmt.Errorf("failed to retrieve EventingAuth resource: %v", err)
}
return nil
}

// SetupWithManager sets up the controller with the Manager.
func (r *KymaReconciler) SetupWithManager(mgr ctrl.Manager) error {
return ctrl.NewControllerManagedBy(mgr).
For(&kymav1beta1.Kyma{}).
Owns(&v1alpha1.EventingAuth{}).
Complete(r)
}
102 changes: 102 additions & 0 deletions controllers/kyma_controller_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,102 @@
package controllers_test

import (
"context"
"fmt"
"github.com/kyma-project/eventing-auth-manager/api/v1alpha1"
kymav1beta1 "github.com/kyma-project/lifecycle-manager/api/v1beta1"
. "github.com/onsi/ginkgo/v2"
. "github.com/onsi/gomega"
"k8s.io/apimachinery/pkg/api/errors"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/types"
ctrlClient "sigs.k8s.io/controller-runtime/pkg/client"
)

// Since all tests use the same target cluster and therefore share the same application secret, they need to be executed serially
var _ = Describe("Kyma Controller", Serial, func() {
AfterEach(func() {
deleteKymaResources()
deleteKubeconfigSecrets()
})

Context("Creating Kyma CR", func() {
It("should create Kyma CR", func() {
crName := generateCrName()
createKubeconfigSecret(crName)
kyma := createKymaResource(crName)
verifyEventingAuth(kyma.Namespace, kyma.Name)
})
})

Context("Creating and Deleting Kyma CR", func() {
It("should delete Kyma CR", func() {
if !useExistingCluster {
Skip("Skipping not for a real cluster as k8s garbage collection works with a real cluster")
}
// create Kyma CR
crName := generateCrName()
createKubeconfigSecret(crName)
kyma := createKymaResource(crName)
verifyEventingAuth(kyma.Namespace, kyma.Name)
// delete Kyma CR
deleteKymaResource(kyma)
By(fmt.Sprintf("Verifying whether EventingAuth CR is deleted %s", kyma.Namespace+"/"+kyma.Name))
Eventually(func(g Gomega) {
eventingAuth := &v1alpha1.EventingAuth{}
err := k8sClient.Get(context.TODO(), types.NamespacedName{Namespace: kyma.Namespace, Name: kyma.Name}, eventingAuth)
g.Expect(err).ShouldNot(BeNil())
g.Expect(errors.IsNotFound(err)).To(BeTrue())
}, defaultTimeout).Should(Succeed())
})
})
})

func verifyEventingAuth(namespace, name string) {
nsName := types.NamespacedName{Namespace: namespace, Name: name}
By(fmt.Sprintf("Verifying Kyma CR %s", nsName.String()))
Eventually(func(g Gomega) {
eventingAuth := &v1alpha1.EventingAuth{}
g.Expect(k8sClient.Get(context.TODO(), nsName, eventingAuth)).Should(Succeed())
g.Expect(eventingAuth.Name).To(Equal(name))
g.Expect(eventingAuth.Namespace).To(Equal(namespace))
}, defaultTimeout).Should(Succeed())
}

func createKymaResource(name string) *kymav1beta1.Kyma {
kyma := kymav1beta1.Kyma{
ObjectMeta: metav1.ObjectMeta{
Name: name,
Namespace: namespace,
},
Spec: kymav1beta1.KymaSpec{
Modules: []kymav1beta1.Module{kymav1beta1.Module{Name: "nats"}},
Channel: "alpha",
},
}

By("Creating Kyma CR")
Expect(k8sClient.Create(context.TODO(), &kyma)).Should(Succeed())

return &kyma
}

func deleteKymaResource(kyma *kymav1beta1.Kyma) {
By(fmt.Sprintf("Deleting Kyma %s", kyma.Name))
Expect(k8sClient.Delete(context.TODO(), kyma)).Should(Succeed())
Eventually(func(g Gomega) {
err := k8sClient.Get(context.TODO(), ctrlClient.ObjectKeyFromObject(kyma), &kymav1beta1.Kyma{})
g.Expect(errors.IsNotFound(err)).To(BeTrue())
}, defaultTimeout).Should(Succeed())
}

func deleteKymaResources() {
kymaList := kymav1beta1.KymaList{}
Expect(k8sClient.List(context.TODO(), &kymaList, ctrlClient.InNamespace(namespace))).Should(Succeed())

for _, kyma := range kymaList.Items {
if err := k8sClient.Delete(context.TODO(), &kyma); err != nil && !errors.IsNotFound(err) {
Expect(err).Should(Succeed())
}
}
}
Loading