-
Notifications
You must be signed in to change notification settings - Fork 4
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #10 from IMGARENA/BAU_ingress_controller
Add Ingress Controller annotations feature
- Loading branch information
Showing
8 changed files
with
461 additions
and
13 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -62,8 +62,6 @@ rules: | |
resources: | ||
- ingresses | ||
verbs: | ||
- create | ||
- delete | ||
- get | ||
- list | ||
- patch | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,6 +1,6 @@ | ||
## Append samples you want in your CSV to this file as resources ## | ||
resources: | ||
# - networking_v1_ingress.yaml | ||
- networking_v1_ingress.yaml | ||
- checkly_v1alpha1_apicheck.yaml | ||
- checkly_v1alpha1_group.yaml | ||
#+kubebuilder:scaffold:manifestskustomizesamples |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,23 @@ | ||
--- | ||
apiVersion: networking.k8s.io/v1 | ||
kind: Ingress | ||
metadata: | ||
name: ingress-sample | ||
annotations: | ||
checkly.imgarena.com/enabled: "true" | ||
checkly.imgarena.com/path: "/baz" | ||
# checkly.imgarena.com/endpoint: "foo.baaz" - Default read from spec.rules[0].host | ||
# checkly.imgarena.com/success: "200" - Default "200" | ||
checkly.imgarena.com/group: "group-sample" | ||
spec: | ||
rules: | ||
- host: "foo.bar" | ||
http: | ||
paths: | ||
- path: / | ||
pathType: ImplementationSpecific | ||
backend: | ||
service: | ||
name: test-service | ||
port: | ||
number: 8080 |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -18,8 +18,12 @@ package networking | |
|
||
import ( | ||
"context" | ||
"fmt" | ||
|
||
checklyv1alpha1 "github.com/imgarena/checkly-operator/apis/checkly/v1alpha1" | ||
networkingv1 "k8s.io/api/networking/v1" | ||
"k8s.io/apimachinery/pkg/api/errors" | ||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" | ||
"k8s.io/apimachinery/pkg/runtime" | ||
ctrl "sigs.k8s.io/controller-runtime" | ||
"sigs.k8s.io/controller-runtime/pkg/client" | ||
|
@@ -32,23 +36,95 @@ type IngressReconciler struct { | |
Scheme *runtime.Scheme | ||
} | ||
|
||
//+kubebuilder:rbac:groups=networking.k8s.io,resources=ingresses,verbs=get;list;watch;create;update;patch;delete | ||
//+kubebuilder:rbac:groups=networking.k8s.io,resources=ingresses,verbs=get;list;watch;update;patch | ||
//+kubebuilder:rbac:groups=networking.k8s.io,resources=ingresses/status,verbs=get;update;patch | ||
//+kubebuilder:rbac:groups=networking.k8s.io,resources=ingresses/finalizers,verbs=update | ||
//+kubebuilder:rbac:groups=checkly.imgarena.com,resources=apichecks,verbs=get;list;watch;create;update;patch;delete | ||
//+kubebuilder:rbac:groups=checkly.imgarena.com,resources=apichecks/status,verbs=get;update;patch | ||
|
||
// Reconcile is part of the main kubernetes reconciliation loop which aims to | ||
// move the current state of the cluster closer to the desired state. | ||
// TODO(user): Modify the Reconcile function to compare the state specified by | ||
// the Ingress object against the actual cluster state, and then | ||
// perform operations to make the cluster state reflect the state specified by | ||
// the user. | ||
// | ||
// For more details, check Reconcile and its Result here: | ||
// - https://pkg.go.dev/sigs.k8s.io/[email protected]/pkg/reconcile | ||
func (r *IngressReconciler) Reconcile(ctx context.Context, req ctrl.Request) (ctrl.Result, error) { | ||
_ = log.FromContext(ctx) | ||
logger := log.FromContext(ctx) | ||
logger.Info("Reconciler started") | ||
|
||
// TODO(user): your logic here | ||
ingress := &networkingv1.Ingress{} | ||
apiCheck := &checklyv1alpha1.ApiCheck{} | ||
|
||
// Check if ingress object is still present | ||
err := r.Get(ctx, req.NamespacedName, ingress) | ||
if err != nil { | ||
if errors.IsNotFound(err) { | ||
logger.Info("Ingress got deleted") | ||
return ctrl.Result{}, nil | ||
} | ||
logger.Error(err, "Can't read the Ingress object") | ||
return ctrl.Result{}, err | ||
} | ||
logger.Info("Ingress Object found") | ||
|
||
// Check if annotation is present on the object | ||
checklyAnnotation := ingress.Annotations["checkly.imgarena.com/enabled"] == "true" | ||
if !checklyAnnotation { | ||
// Annotation may have been removed or updated, we have to determine if we need to delete a previously created ApiCheck resource | ||
logger.Info("annotation is not present, checking if ApiCheck was created") | ||
err = r.Get(ctx, req.NamespacedName, apiCheck) | ||
if err != nil { | ||
logger.Info("Apicheck not present") | ||
return ctrl.Result{}, nil | ||
} | ||
logger.Info("ApiCheck is present, but we need to delete it") | ||
err = r.Delete(ctx, apiCheck) | ||
if err != nil { | ||
logger.Info("Failed to delete ApiCheck") | ||
return ctrl.Result{}, err | ||
// } | ||
} | ||
|
||
return ctrl.Result{}, nil | ||
} | ||
|
||
// Gather data for the checkly check | ||
apiCheckSpec, err := r.gatherApiCheckData(ingress) | ||
if err != nil { | ||
logger.Info("unable to gather data for the apiCheck resource") | ||
return ctrl.Result{}, err | ||
} | ||
|
||
// Check and see if the ApiCheck has been created before | ||
err = r.Get(ctx, req.NamespacedName, apiCheck) | ||
if err == nil { | ||
logger.Info("apiCheck exists, doing an update") | ||
// We can reference the exiting apiCheck object that the server returned | ||
apiCheck.Spec = apiCheckSpec | ||
err = r.Update(ctx, apiCheck) | ||
if err != nil { | ||
return ctrl.Result{}, err | ||
} | ||
return ctrl.Result{}, nil | ||
} | ||
|
||
// Create apiCheck | ||
// We need to write the k8s spec resources as it is a new object | ||
newApiCheck := &checklyv1alpha1.ApiCheck{ | ||
ObjectMeta: metav1.ObjectMeta{ | ||
Name: ingress.Name, | ||
Namespace: ingress.Namespace, | ||
OwnerReferences: []metav1.OwnerReference{ | ||
*metav1.NewControllerRef(ingress, networkingv1.SchemeGroupVersion.WithKind("ingress")), | ||
}, | ||
}, | ||
Spec: apiCheckSpec, | ||
} | ||
|
||
err = r.Create(ctx, newApiCheck) | ||
if err != nil { | ||
logger.Info("Failed to create ApiCheck", "err", err) | ||
return ctrl.Result{}, err | ||
} | ||
|
||
return ctrl.Result{}, nil | ||
} | ||
|
@@ -59,3 +135,53 @@ func (r *IngressReconciler) SetupWithManager(mgr ctrl.Manager) error { | |
For(&networkingv1.Ingress{}). | ||
Complete(r) | ||
} | ||
|
||
func (r *IngressReconciler) gatherApiCheckData(ingress *networkingv1.Ingress) (apiCheckSpec checklyv1alpha1.ApiCheckSpec, err error) { | ||
|
||
annotationHost := "checkly.imgarena.com" | ||
annotationPath := fmt.Sprintf("%s/path", annotationHost) | ||
annotationEndpoint := fmt.Sprintf("%s/endpoint", annotationHost) | ||
annotationSuccess := fmt.Sprintf("%s/success", annotationHost) | ||
annotationGroup := fmt.Sprintf("%s/group", annotationHost) | ||
|
||
// Construct the endpoint | ||
path := "" | ||
if ingress.Annotations[annotationPath] != "" { | ||
path = ingress.Annotations[annotationPath] | ||
} | ||
|
||
var host string | ||
if ingress.Annotations[annotationEndpoint] == "" { | ||
host = ingress.Spec.Rules[0].Host | ||
} else { | ||
host = ingress.Annotations[annotationEndpoint] | ||
} | ||
|
||
endpoint := fmt.Sprintf("https://%s%s", host, path) | ||
|
||
// Expected success code | ||
var success string | ||
if ingress.Annotations[annotationSuccess] != "" { | ||
success = ingress.Annotations[annotationSuccess] | ||
} else { | ||
success = "200" | ||
} | ||
|
||
// Group | ||
var group string | ||
if ingress.Annotations[annotationGroup] != "" { | ||
group = ingress.Annotations[annotationGroup] | ||
} else { | ||
err = fmt.Errorf("could not find a value for the group annotation, can't continue without one") | ||
} | ||
|
||
apiCheckSpec = checklyv1alpha1.ApiCheckSpec{ | ||
Endpoint: endpoint, | ||
Group: group, | ||
Team: "group-test", | ||
Success: success, | ||
} | ||
|
||
// Last return | ||
return | ||
} |
Oops, something went wrong.